Source code for pestifer.objs.transfer_coords
# Author: Cameron F. Abrams, <cfa22@drexel.edu>
"""
A coordinate-transfer coormod: copies atomic coordinates from a selected
subset of a donor system directly onto the corresponding atoms of the
pipeline system.
Unlike :class:`~pestifer.objs.align.Align`, which computes a rigid-body
transformation, ``transfer_coords`` overwrites positions atom-by-atom and
therefore handles non-rigid changes (re-modeled loops, isolated
energy-minimization, ligand repositioning, etc.).
An optional pre-alignment step can be requested by supplying both
``align_donor_sel`` and ``align_mobile_sel``. When present, the entire
donor molecule is rigidly fitted to the pipeline system using those
selections before the coordinate transfer is performed. Supplying only
one of the two raises a ``ValueError``.
All selection strings must be supplied explicitly; no defaults are inferred
from each other in order to avoid hidden decision-making. Congruent
selections (same atom count, same order) are required for both the
alignment pair and the transfer pair.
"""
import logging
logger = logging.getLogger(__name__)
from typing import ClassVar
from pydantic import Field, model_validator
from ..core.baseobj import BaseObj, BaseObjList
[docs]
class TransferCoords(BaseObj):
"""
Copy coordinates from a donor PDB onto a selection in the pipeline system,
with an optional prior rigid-body alignment of the donor to the pipeline.
Parameters (from YAML ``specs``)
---------------------------------
donor_pdb : str
Path to the donor PDB file.
donor_psf : str, optional
Path to a donor PSF file. When provided both files are loaded so
that VMD selection syntax can reference topology attributes.
donor_sel : str
VMD atomselect string for the atoms to copy **from** in the donor.
mobile_sel : str
VMD atomselect string for the atoms to overwrite **in** the pipeline
system. Must select the same number of atoms as ``donor_sel``,
in the same order.
align_donor_sel : str, optional
VMD atomselect string for donor atoms used in the pre-alignment fit.
Must be supplied together with ``align_mobile_sel``; omitting both
skips the alignment step entirely.
align_mobile_sel : str, optional
VMD atomselect string for pipeline atoms used in the pre-alignment
fit. Must be supplied together with ``align_donor_sel``.
"""
_required_fields = {'donor_pdb', 'donor_sel', 'mobile_sel'}
_optional_fields = {'donor_psf', 'align_donor_sel', 'align_mobile_sel'}
donor_pdb: str = Field(..., description="Path to the donor PDB file.")
donor_psf: str | None = Field(None, description="Path to the donor PSF file (optional).")
donor_sel: str = Field(..., description="VMD atomselect string for atoms to copy from in the donor.")
mobile_sel: str = Field(..., description="VMD atomselect string for atoms to overwrite in the pipeline system.")
align_donor_sel: str | None = Field(None, description="Donor selection for pre-alignment fit (requires align_mobile_sel).")
align_mobile_sel: str | None = Field(None, description="Pipeline selection for pre-alignment fit (requires align_donor_sel).")
_yaml_header: ClassVar[str] = 'transfer_coords'
_objcat: ClassVar[str] = 'coord'
@model_validator(mode='after')
def _check_align_pair(self):
has_donor = self.align_donor_sel is not None
has_mobile = self.align_mobile_sel is not None
if has_donor != has_mobile:
missing = 'align_mobile_sel' if has_donor else 'align_donor_sel'
present = 'align_donor_sel' if has_donor else 'align_mobile_sel'
raise ValueError(
f"transfer_coords: '{present}' was supplied but '{missing}' is missing. "
f"Both alignment selections must be provided together, or neither."
)
return self
@property
def pre_align(self) -> bool:
return self.align_donor_sel is not None
[docs]
class TransferCoordsList(BaseObjList[TransferCoords]):
[docs]
def describe(self):
return f'<TransferCoordsList with {len(self)} transfers>'