3.1.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 rms_fit_trj()
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.
3.1.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
>>> from MDAnalysis import *
>>> from MDAnalysis.analysis.align import *
>>> 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 = Universe(PDB_small)
>>> mobile = Universe(PSF,DCD)
>>> rmsd(mobile.atoms.CA.positions, ref.atoms.CA.positions)
18.858259026820352
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:
>>> ref0 = ref.atoms.CA.positions - ref.atoms.CA.center_of_mass()
>>> mobile0 = mobile.atoms.CA.positions - mobile.atoms.CA.center_of_mass()
>>> rmsd(mobile0, ref0)
6.8093965864717951
The rotation matrix that superimposes mobile on ref while
minimizing the CA-RMSD is obtained with the rotation_matrix()
function
>>> R, rmsd = 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.atoms.CA.center_of_mass())
>>> mobile.atoms.rotate(R)
>>> mobile.atoms.translate(ref.atoms.CA.center_of_mass())
>>> mobile.atoms.write("mobile_on_ref.pdb")
3.1.1.2. Common usage¶
To fit a single structure with alignto()
:
>>> ref = Universe(PSF, PDB_small)
>>> mobile = Universe(PSF, DCD) # we use the first frame
>>> alignto(mobile, ref, select="protein and name CA", mass_weighted=True)
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
rms_fit_trj()
function:
>>> ref = Universe(PSF, PDB_small) # reference structure 1AKE
>>> trj = Universe(PSF, DCD) # trajectory of change 1AKE->4AKE
>>> rms_fit_trj(trj, ref, filename='rmsfit.dcd')
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 rms_fit_trj()
:
>>> seldict = fasta2select('sequences.aln')
>>> rms_fit_trj(trj, ref, filename='rmsfit.dcd', select=seldict)
(See the documentation of the functions for this advanced usage.)
3.1.1.3. Functions¶
-
MDAnalysis.analysis.align.
alignto
(mobile, reference, select='all', mass_weighted=False, subselection=None, tol_mass=0.1, strict=False)[source]¶ Spatially align 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 contains 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* – structure to be aligned, a
AtomGroup
or a wholeUniverse
- *reference* – reference structure, a
AtomGroup
or a wholeUniverse
- *select* –
- any valid selection string for
select_atoms()
that produces identical selections in mobile and reference; or - dictionary
{'mobile':sel1, 'reference':sel2}
. (thefasta2select()
function returns such a dictionary based on a ClustalW or STAMP sequence alignment); or - tuple
(sel1, sel2)
When using 2. or 3. with sel1 and sel2 then these selections can also each be a list of selection strings (to generate a AtomGroup with defined atom order as described under Ordered selections).
- any valid selection string for
- *mass_weighted* – boolean
True
uses the massesreference.masses()
as weights for the RMSD fit. - *tol_mass* – Reject match if the atomic masses for matched atoms differ by more than tol_mass [0.1]
- *strict* –
True
- Will raise
SelectioError
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* –
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: RMSD before and after spatial alignment.
See also
For RMSD-fitting trajectories it is more efficient to use
rms_fit_trj()
.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 of strict =True
.
-
MDAnalysis.analysis.align.
rms_fit_trj
(traj, reference, select='all', filename=None, rmsdfile=None, prefix='rmsfit_', mass_weighted=False, tol_mass=0.1, strict=False, force=True, quiet=False, **kwargs)[source]¶ RMS-fit trajectory to a reference structure using a selection.
Both reference ref and trajectory traj 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.Parameters: - *traj* – trajectory,
MDAnalysis.Universe
object - *reference* – reference coordinates;
MDAnalysis.Universe
object (uses the current time step of the object) - *select* –
- any valid selection string for
select_atoms()
that produces identical selections in mobile and reference; or - a dictionary
{'mobile':sel1, 'reference':sel2}
(thefasta2select()
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 selections can also each be a list of selection strings (to generate a AtomGroup with defined atom order as described under Ordered selections).
- any valid selection string for
- *filename* – file name for the RMS-fitted trajectory or pdb; defaults to the original trajectory filename (from traj) with prefix prepended
- *rmsdfile* – file name for writing the RMSD timeseries [
None
] - *prefix* – prefix for autogenerating the new output filename
- *mass_weighted* – do a mass-weighted RMSD fit
- *tol_mass* – Reject match if the atomic masses for matched atoms differ by more than tol_mass [0.1]
- *strict* –
Default:
False
-True
: Will raiseSelectioError
if a single atom does notmatch between the two selections.False
: Will try to prepare a matching selection by dropping residues with non-matching atoms. Seeget_matching_atoms()
for details.
- *force* –
True
: Overwrite an existing output trajectory (default)False
: simply return if the file already exists
- *quiet* –
True
: suppress progress and logging for levels INFO and below.False
: show all status messages and do not change the the logging level (default)
Note
If
- *kwargs* – All other keyword arguments are passed on the trajectory
Writer
; this allows manipulating/fixing trajectories on the fly (e.g. change the output format by changing the extension of filename and setting different parameters as described for the corresponding writer).
Returns: filename (either provided or auto-generated)
Changed in version 0.8: Added kwargs to be passed to the trajectory
Writer
and filename is returned.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 of strict =True
.- *traj* – trajectory,
-
MDAnalysis.analysis.align.
rotation_matrix
(a, b, weights=None)[source]¶ Returns the 3x3 rotation matrix for RMSD fitting coordinate sets a and b.
The rotation matrix R transforms a to overlap with b (i.e. b is the reference structure):
b = R . aParameters: - *a* – coordinates that are to be rotated (“mobile set”); array of N atoms
of shape N*3 as generated by, e.g.,
MDAnalysis.core.AtomGroup.AtomGroup.coordinates()
. - *b* – reference coordinates; array of N atoms of shape N*3 as generated by,
e.g.,
MDAnalysis.core.AtomGroup.AtomGroup.coordinates()
. - *weights* – array of floats of size N for doing weighted RMSD fitting (e.g. the masses of the atoms)
Returns: (R, rmsd)
rmsd and rotation matrix RR can be used as an argument for
MDAnalysis.core.AtomGroup.AtomGroup.rotate()
to generate a rotated selection, e.g.>>> R = rotation_matrix(A.select_atoms('backbone').coordinates(), B.select_atoms('backbone').coordinates()) >>> A.atoms.rotate(R) >>> A.atoms.write("rotated.pdb")
Note that the function does not shift the centers of mass or geometry; this needs to be done by the user.
See also
rmsd()
calculates the RMSD between a and b; for fitting a whole trajectory it is more efficient to userms_fit_trj()
. A complete fit of two structures can be done withalignto()
.- *a* – coordinates that are to be rotated (“mobile set”); array of N atoms
of shape N*3 as generated by, e.g.,
3.1.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.
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 structure/psf has gaps due to missing parts), simply provide the sequence of resids as they appear in the psf 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 xxx_offset!)
Parameters: - *fastafilename* – FASTA file with first sequence as reference and second the one to be aligned (ORDER IS IMPORTANT!)
- *is_aligned* – False: run clustalw for sequence alignment; True: use
the alignment in the file (e.g. from STAMP) [
False
] - *ref_offset* – add this number to the column number in the FASTA file to get the original residue number
- *target_offset* – same for the target
- *ref_resids* – sequence of resids as they appear in the reference structure
- *target_resids* – sequence of resids as they appear in the target
- *alnfilename* – filename of ClustalW alignment (clustal format) that is
produced by clustalw when is_aligned =
False
.None
uses the name and path of fastafilename and subsititutes the suffix with ‘.aln’.[None
] - *treefilename* – filename of ClustalW guide tree (Newick format);
if
None
the the filename is generated from alnfilename with the suffix ‘.dnd’ instead of ‘.aln’ [None
] - *clustalw* – path to the ClustalW (or ClustalW2) binary; only
needed for is_aligned =
False
[“clustalw2”]
Returns: select_dict dictionary with ‘reference’ and ‘mobile’ selection string that can be used immediately in
rms_fit_trj()
asselect=select_dict
.
-
MDAnalysis.analysis.align.
get_matching_atoms
(ag1, ag2, tol_mass=0.1, strict=False)[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: ag2 (*ag1*,) –
AtomGroup
instances that are comparedKeywords: - tol_mass
Reject if the atomic masses for matched atoms differ by more than tol_mass [0.1]
- strict
True
Will raise
SelectioError
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.
Returns: Tuple
(g1, g2)
withAtomGroup
instances that match, atom by atom. The groups are either the original groups if all matches or slices of the original groups.Raises: SelectionError
if the number of residues does not match or if in the final matching masses differ by more than tol.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)