4.2.1. Coordinate fitting and alignment — MDAnalysis.analysis.align
¶
Author: | Oliver Beckstein, Joshua Adelman |
---|---|
Year: | 2010–2013 |
Copyright: | GNU Public License v3 |
The module contains functions to fit a target structure to a reference structure. They use the fast QCP algorithm to calculate the root mean square distance (RMSD) between two coordinate sets [Theobald2005] and the rotation matrix R that minimizes the RMSD [Liu2010]. (Please cite these references when using this module.).
Typically, one selects a group of atoms (such as the C-alphas),
calculates the RMSD and transformation matrix, and applys the
transformation to the current frame of a trajectory to obtain the
rotated structure. The alignto()
and AlignTraj
functions can be used to do this for individual frames and
trajectories respectively.
The RMS-fitting tutorial shows how to do the individual steps manually and explains the intermediate steps.
See also
MDAnalysis.analysis.rms
- contains functions to compute RMSD (when structural alignment is not required)
MDAnalysis.lib.qcprot
- implements the fast RMSD algorithm.
4.2.1.1. RMS-fitting tutorial¶
The example uses files provided as part of the MDAnalysis test suite
(in the variables PSF
,
DCD
, and
PDB_small
). For all further
examples execute first
>>> import MDAnalysis as mda
>>> from MDAnalysis.analysis import align
>>> from MDAnalysis.analysis.rms import rmsd
>>> from MDAnalysis.tests.datafiles import PSF, DCD, PDB_small
In the simplest case, we can simply calculate the C-alpha RMSD between
two structures, using rmsd()
:
>>> ref = mda.Universe(PDB_small)
>>> mobile = mda.Universe(PSF,DCD)
>>> rmsd(mobile.select_atoms('name CA').positions, ref.select_atoms('name CA').positions)
16.282308620224068
Note that in this example translations have not been removed. In order to look at the pure rotation one needs to superimpose the centres of mass (or geometry) first:
>>> rmsd(mobile.select_atoms('name CA').positions, ref.select_atoms('name CA').positions, center=True)
12.639693690256898
This has only done a translational superposition. If you want to also do a rotational superposition use the superposition keyword. This will calculate a minimized RMSD between the reference and mobile structure.
>>> rmsd(mobile.select_atoms('name CA').positions, ref.select_atoms('name CA').positions,
>>> superposition=True)
6.8093965864717951
The rotation matrix that superimposes mobile on ref while
minimizing the CA-RMSD is obtained with the rotation_matrix()
function
>>> mobile0 = mobile.select_atoms('name CA').positions - mobile.atoms.center_of_mass()
>>> ref0 = ref.select_atoms('name CA').positions - ref.atoms.center_of_mass()
>>> R, rmsd = align.rotation_matrix(mobile0, ref0)
>>> print rmsd
6.8093965864717951
>>> print R
[[ 0.14514539 -0.27259113 0.95111876]
[ 0.88652593 0.46267112 -0.00268642]
[-0.43932289 0.84358136 0.30881368]]
Putting all this together one can superimpose all of mobile onto ref:
>>> mobile.atoms.translate(-mobile.select_atoms('name CA').center_of_mass())
>>> mobile.atoms.rotate(R)
>>> mobile.atoms.translate(ref.select_atoms('name CA').center_of_mass())
>>> mobile.atoms.write("mobile_on_ref.pdb")
4.2.1.2. Common usage¶
To fit a single structure with alignto()
:
>>> ref = mda.Universe(PSF, PDB_small)
>>> mobile = mda.Universe(PSF, DCD) # we use the first frame
>>> align.alignto(mobile, ref, select="protein and name CA", weights="mass")
This will change all coordinates in mobile so that the protein C-alpha atoms are optimally superimposed (translation and rotation).
To fit a whole trajectory to a reference structure with the
AlignTraj
class:
>>> ref = mda.Universe(PSF, PDB_small) # reference structure 1AKE
>>> trj = mda.Universe(PSF, DCD) # trajectory of change 1AKE->4AKE
>>> alignment = align.AlignTraj(trj, ref, filename='rmsfit.dcd')
>>> alignment.run()
It is also possible to align two arbitrary structures by providing a mapping between atoms based on a sequence alignment. This allows fitting of structural homologs or wild type and mutant.
If a alignment was provided as “sequences.aln” one would first produce
the appropriate MDAnalysis selections with the fasta2select()
function and then feed the resulting dictionary to AlignTraj
:
>>> seldict = align.fasta2select('sequences.aln')
>>> alignment = align.AlignTraj(trj, ref, filename='rmsfit.dcd', select=seldict)
>>> alignment.run()
(See the documentation of the functions for this advanced usage.)
4.2.1.3. Functions and Classes¶
Changed in version 0.10.0: Function rmsd()
was removed from
this module and is now exclusively accessible as
rmsd()
.
Changed in version 0.16.0: Function rms_fit_trj()
deprecated
in favor of AlignTraj
class.
Changed in version 0.17.0: removed deprecated rms_fit_trj()
-
MDAnalysis.analysis.align.
alignto
(mobile, reference, select=None, weights=None, subselection=None, tol_mass=0.1, strict=False, match_atoms=True)[source]¶ Perform a spatial superposition by minimizing the RMSD.
Spatially align the group of atoms mobile to reference by doing a RMSD fit on select atoms.
The superposition is done in the following way:
- A rotation matrix is computed that minimizes the RMSD between the coordinates of mobile.select_atoms(sel1) and reference.select_atoms(sel2); before the rotation, mobile is translated so that its center of geometry (or center of mass) coincides with the one of reference. (See below for explanation of how sel1 and sel2 are derived from select.)
- All atoms in
Universe
that contain mobile are shifted and rotated. (See below for how to change this behavior through the subselection keyword.)
The mobile and reference atom groups can be constructed so that they already match atom by atom. In this case, select should be set to “all” (or
None
) so that no further selections are applied to mobile and reference, therefore preserving the exact atom ordering (see Ordered selections).Warning
The atom order for mobile and reference is only preserved when select is either “all” or
None
. In any other case, a new selection will be made that will sort the resulting AtomGroup by index and therefore destroy the correspondence between the two groups. It is safest not to mix ordered AtomGroups with selection strings.Parameters: - mobile (Universe or AtomGroup) – structure to be aligned, a
AtomGroup
or a wholeUniverse
- reference (Universe or AtomGroup) – reference structure, a
AtomGroup
or a wholeUniverse
- select (str or dict or tuple (optional)) –
The selection to operate on; can be one of:
- any valid selection string for
select_atoms()
that produces identical selections in mobile and reference; or - a dictionary
{'mobile': sel1, 'reference': sel2}
where sel1 and sel2 are valid selection strings that are applied to mobile and reference respectively (theMDAnalysis.analysis.align.fasta2select()
function returns such a dictionary based on a ClustalW or STAMP sequence alignment); or - a tuple
(sel1, sel2)
When using 2. or 3. with sel1 and sel2 then these selection strings are applied to atomgroup and reference respectively and should generate groups of equivalent atoms. sel1 and sel2 can each also be a list of selection strings to generate a
AtomGroup
with defined atom order as described under Ordered selections). - any valid selection string for
- match_atoms (bool (optional)) – Whether to match the mobile and reference atom-by-atom. Default
True
. - weights ({“mass”,
None
} or array_like (optional)) – choose weights. With"mass"
uses masses as weights; withNone
weigh each atom equally. If a float array of the same length as mobile is provided, use each element of the array_like as a weight for the corresponding atom in mobile. - tol_mass (float (optional)) – Reject match if the atomic masses for matched atoms differ by more than tol_mass, default [0.1]
- strict (bool (optional)) –
True
- Will raise
SelectionError
if a single atom does not match between the two selections. False
[default]- Will try to prepare a matching selection by dropping
residues with non-matching atoms. See
get_matching_atoms()
for details.
- subselection (str or AtomGroup or None (optional)) –
Apply the transformation only to this selection.
None
[default]- Apply to
mobile.universe.atoms
(i.e., all atoms in the context of the selection from mobile such as the rest of a protein, ligands and the surrounding water) - selection-string
- Apply to
mobile.select_atoms(selection-string)
AtomGroup
- Apply to the arbitrary group of atoms
Returns: - old_rmsd (float) – RMSD before spatial alignment
- new_rmsd (float) – RMSD after spatial alignment
See also
AlignTraj()
- More efficient method for RMSD-fitting trajectories.
Changed in version 1.0.0: Added match_atoms keyword to toggle atom matching.
Changed in version 0.8: Added check that the two groups describe the same atoms including the new tol_mass keyword.
Changed in version 0.10.0: Uses
get_matching_atoms()
to work with incomplete selections and new strict keyword. The new default is to be lenient whereas the old behavior was the equivalent ofstrict = True
.Changed in version 0.16.0: new general ‘weights’ kwarg replace mass_weighted, deprecated mass_weighted
Deprecated since version 0.16.0: Instead of
mass_weighted=True
use newweights='mass'
Changed in version 0.17.0: Deprecated keyword mass_weighted was removed.
-
class
MDAnalysis.analysis.align.
AlignTraj
(mobile, reference, select='all', filename=None, prefix='rmsfit_', weights=None, tol_mass=0.1, match_atoms=True, strict=False, force=True, in_memory=False, **kwargs)[source]¶ RMS-align trajectory to a reference structure using a selection.
Both the reference reference and the trajectory mobile must be
MDAnalysis.Universe
instances. If they contain a trajectory then it is used. The output file format is determined by the file extension of filename. One can also use the same universe if one wants to fit to the current frame.Changed in version 1.0.0:
save()
has now been removed, as an alternative usenp.savetxt()
onrmsd
.Parameters: - mobile (Universe) – Universe containing trajectory to be fitted to reference
- reference (Universe) – Universe containing trajectory frame to be used as reference
- select (str (optional)) – Set as default to all, is used for Universe.select_atoms to choose subdomain to be fitted against
- filename (str (optional)) – Provide a filename for results to be written to
- prefix (str (optional)) – Provide a string to prepend to filename for results to be written to
- weights ({“mass”,
None
} or array_like (optional)) – choose weights. With"mass"
uses masses of reference as weights; withNone
weigh each atom equally. If a float array of the same length as the selection is provided, use each element of the array_like as a weight for the corresponding atom in the selection. - tol_mass (float (optional)) – Tolerance given to get_matching_atoms to find appropriate atoms
- match_atoms (bool (optional)) – Whether to match the mobile and reference atom-by-atom. Default
True
. - strict (bool (optional)) – Force get_matching_atoms to fail if atoms can’t be found using exact methods
- force (bool (optional)) – Force overwrite of filename for rmsd-fitting
- in_memory (bool (optional)) – Permanently switch mobile to an in-memory trajectory so that alignment can be done in-place, which can improve performance substantially in some cases. In this case, no file is written out (filename and prefix are ignored) and only the coordinates of mobile are changed in memory.
- verbose (bool (optional)) – Set logger to show more information and show detailed progress of
the calculation if set to
True
; the default isFalse
.
-
rmsd
¶ Array of the rmsd values of the least rmsd between the mobile_atoms and reference_atoms after superposition and minimimization of rmsd
Type: Array
-
filename
¶ String reflecting the filename of the file where the aligned positions will be written to upon running RMSD alignment
Type: str
Notes
- If set to
verbose=False
, it is recommended to wrap the statement in atry ... finally
to guarantee restoring of the log level in the case of an exception. - The
in_memory
option changes the mobile universe to an in-memory representation (seeMDAnalysis.coordinates.memory
) for the remainder of the Python session. Ifmobile.trajectory
is already aMemoryReader
then it is always treated as ifin_memory
had been set toTrue
.
Changed in version 1.0.0: Default
filename
has now been changed to the current directory.Deprecated since version 0.19.1: Default
filename
directory will change in 1.0 to the current directory.Changed in version 0.16.0: new general
weights
kwarg replacemass_weights
Deprecated since version 0.16.0: Instead of
mass_weighted=True
use newweights='mass'
Changed in version 0.17.0: removed deprecated mass_weighted keyword
Changed in version 1.0.0: Support for the
start
,stop
, andstep
keywords has been removed. These should instead be passed toAlignTraj.run()
.
-
MDAnalysis.analysis.align.
rotation_matrix
(a, b, weights=None)[source]¶ Returns the 3x3 rotation matrix R for RMSD fitting coordinate sets a and b.
The rotation matrix R transforms vector a to overlap with vector b (i.e., b is the reference structure):
\[\mathbf{b} = \mathsf{R} \cdot \mathbf{a}\]Parameters: - a (array_like) – coordinates that are to be rotated (“mobile set”); array of N atoms
of shape N*3 as generated by, e.g.,
MDAnalysis.core.groups.AtomGroup.positions
. - b (array_like) – reference coordinates; array of N atoms of shape N*3 as generated by,
e.g.,
MDAnalysis.core.groups.AtomGroup.positions
. - weights (array_like (optional)) – array of floats of size N for doing weighted RMSD fitting (e.g. the masses of the atoms)
Returns: - R (ndarray) – rotation matrix
- rmsd (float) – RMSD between a and b before rotation
(R, rmsd)
rmsd and rotation matrix R
Example
R can be used as an argument for
MDAnalysis.core.groups.AtomGroup.rotate()
to generate a rotated selection, e.g.>>> R = rotation_matrix(A.select_atoms('backbone').positions, >>> B.select_atoms('backbone').positions)[0] >>> A.atoms.rotate(R) >>> A.atoms.write("rotated.pdb")
Notes
The function does not shift the centers of mass or geometry; this needs to be done by the user.
See also
MDAnalysis.analysis.rms.rmsd()
- Calculates the RMSD between a and b.
alignto()
- A complete fit of two structures.
AlignTraj()
- Fit a whole trajectory.
- a (array_like) – coordinates that are to be rotated (“mobile set”); array of N atoms
of shape N*3 as generated by, e.g.,
4.2.1.4. Helper functions¶
The following functions are used by the other functions in this module. They are probably of more interest to developers than to normal users.
-
MDAnalysis.analysis.align.
_fit_to
(mobile_coordinates, ref_coordinates, mobile_atoms, mobile_com, ref_com, weights=None)[source]¶ Perform an rmsd-fitting to determine rotation matrix and align atoms
Parameters: - mobile_coordinates (ndarray) – Coordinates of atoms to be aligned
- ref_coordinates (ndarray) – Coordinates of atoms to be fit against
- mobile_atoms (AtomGroup) – Atoms to be translated
- mobile_com (ndarray) – array of xyz coordinate of mobile center of mass
- ref_com (ndarray) – array of xyz coordinate of reference center of mass
- weights (array_like (optional)) – choose weights. With
None
weigh each atom equally. If a float array of the same length as mobile_coordinates is provided, use each element of the array_like as a weight for the corresponding atom in mobile_coordinates.
Returns: - mobile_atoms (AtomGroup) – AtomGroup of translated and rotated atoms
- min_rmsd (float) – Minimum rmsd of coordinates
Notes
This function assumes that mobile_coordinates and ref_coordinates have already been shifted so that their centers of geometry (or centers of mass, depending on weights) coincide at the origin. mobile_com and ref_com are the centers before this shift.
The rotation matrix \(\mathsf{R}\) is determined with
rotation_matrix()
directly from mobile_coordinates and ref_coordinates.mobile_atoms \(X\) is rotated according to the rotation matrix and the centers according to
\[X' = \mathsf{R}(X - \bar{X}) + \bar{X}_{\text{ref}}\]where \(\bar{X}\) is the center.
-
MDAnalysis.analysis.align.
fasta2select
(fastafilename, is_aligned=False, ref_resids=None, target_resids=None, ref_offset=0, target_offset=0, verbosity=3, alnfilename=None, treefilename=None, clustalw='clustalw2')[source]¶ Return selection strings that will select equivalent residues.
The function aligns two sequences provided in a FASTA file and constructs MDAnalysis selection strings of the common atoms. When these two strings are applied to the two different proteins they will generate AtomGroups of the aligned residues.
fastafilename contains the two un-aligned sequences in FASTA format. The reference is assumed to be the first sequence, the target the second. ClustalW produces a pairwise alignment (which is written to a file with suffix
.aln
). The output contains atom selection strings that select the same atoms in the two structures.Unless ref_offset and/or target_offset are specified, the resids in the structure are assumed to correspond to the positions in the un-aligned sequence, namely the first residue has resid == 1.
In more complicated cases (e.g., when the resid numbering in the input structure has gaps due to missing parts), simply provide the sequence of resids as they appear in the topology in ref_resids or target_resids, e.g.
target_resids = [a.resid for a in trj.select_atoms('name CA')]
(This translation table is combined with any value for ref_offset or target_offset!)
Parameters: - fastafilename (str, path to filename) – FASTA file with first sequence as reference and second the one to be aligned (ORDER IS IMPORTANT!)
- is_aligned (bool (optional)) –
False
(default)- run clustalw for sequence alignment;
True
- use the alignment in the file (e.g. from STAMP) [
False
]
- ref_offset (int (optional)) – add this number to the column number in the FASTA file to get the original residue number, default: 0
- target_offset (int (optional)) – add this number to the column number in the FASTA file to get the original residue number, default: 0
- ref_resids (str (optional)) – sequence of resids as they appear in the reference structure
- target_resids (str (optional)) – sequence of resids as they appear in the target
- alnfilename (str (optional)) – filename of ClustalW alignment (clustal format) that is
produced by clustalw when is_aligned =
False
. defaultNone
uses the name and path of fastafilename and subsititutes the suffix with ‘.aln’. - treefilename (str (optional)) – filename of ClustalW guide tree (Newick format);
if default
None
the the filename is generated from alnfilename with the suffix ‘.dnd’ instead of ‘.aln’ - clustalw (str (optional)) – path to the ClustalW (or ClustalW2) binary; only
needed for is_aligned =
False
, default: “ClustalW2”
Returns: select_dict – dictionary with ‘reference’ and ‘mobile’ selection string that can be used immediately in
AlignTraj
asselect=select_dict
.Return type: See also
sequence_alignment()
,which()
,programs.()
Changed in version 1.0.0: Passing alnfilename or treefilename as None will create a file in the current working directory.
-
MDAnalysis.analysis.align.
sequence_alignment
(mobile, reference, match_score=2, mismatch_penalty=-1, gap_penalty=-2, gapextension_penalty=-0.1)[source]¶ Generate a global sequence alignment between two residue groups.
The residues in reference and mobile will be globally aligned. The global alignment uses the Needleman-Wunsch algorithm as implemented in
Bio.pairwise2
. The parameters of the dynamic programming algorithm can be tuned with the keywords. The defaults should be suitable for two similar sequences. For sequences with low sequence identity, more specialized tools such as clustalw, muscle, tcoffee, or similar should be used.Parameters: - mobile (AtomGroup) – Atom group to be aligned
- reference (AtomGroup) – Atom group to be aligned against
- match_score (float (optional), default 2) – score for matching residues, default 2
- mismatch_penalty (float (optional), default -1) – penalty for residues that do not match , default : -1
- gap_penalty (float (optional), default -2) – penalty for opening a gap; the high default value creates compact alignments for highly identical sequences but might not be suitable for sequences with low identity, default : -2
- gapextension_penalty (float (optional), default -0.1) – penalty for extending a gap, default: -0.1
Returns: alignment – Tuple of top sequence matching output (‘Sequence A’, ‘Sequence B’, score, begin, end)
Return type: See also
BioPython documentation for pairwise2. Alternatively, use
fasta2select()
with clustalw2 and the optionis_aligned=False
.New in version 0.10.0.
-
MDAnalysis.analysis.align.
get_matching_atoms
(ag1, ag2, tol_mass=0.1, strict=False, match_atoms=True)[source]¶ Return two atom groups with one-to-one matched atoms.
The function takes two
AtomGroup
instances ag1 and ag2 and returns two atom groups g1 and g2 that consist of atoms so that the mass of atomg1[0]
is the same as the mass of atomg2[0]
,g1[1]
andg2[1]
etc.The current implementation is very simplistic and works on a per-residue basis:
- The two groups must contain the same number of residues.
- Any residues in each group that have differing number of atoms are discarded.
- The masses of corresponding atoms are compared. and if any masses differ
by more than tol_mass the test is considered failed and a
SelectionError
is raised.
The log file (see
MDAnalysis.start_logging()
) will contain detailed information about mismatches.Parameters: - ag1 (AtomGroup) – First
AtomGroup
instance that is compared - ag2 (AtomGroup) – Second
AtomGroup
instance that is compared - tol_mass (float (optional)) – Reject if the atomic masses for matched atoms differ by more than tol_mass [0.1]
- strict (bool (optional)) –
True
- Will raise
SelectionError
if a single atom does not match between the two selections. False
[default]- Will try to prepare a matching selection by dropping
residues with non-matching atoms. See
get_matching_atoms()
for details.
- match_atoms (bool (optional)) –
True
- Will attempt to match atoms based on mass
False
- Will not attempt to match atoms based on mass
Returns: (g1, g2) – Tuple with
AtomGroup
instances that match, atom by atom. The groups are either the original groups if all matched or slices of the original groups.Return type: Raises: SelectionError
– Error raised if the number of residues does not match or if in the final matching masses differ by more than tol.Notes
The algorithm could be improved by using e.g. the Needleman-Wunsch algorithm in
Bio.profile2
to align atoms in each residue (doing a global alignment is too expensive).New in version 0.8.
Changed in version 0.10.0: Renamed from
check_same_atoms()
toget_matching_atoms()
and now returns matching atomgroups (possibly with residues removed)