LCOV - code coverage report
Current view: top level - colvar - RMSD.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 41 42 97.6 %
Date: 2024-10-18 14:00:25 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #include "Colvar.h"
      23             : #include "core/PlumedMain.h"
      24             : #include "core/ActionRegister.h"
      25             : #include "tools/RMSD.h"
      26             : #include "tools/PDB.h"
      27             : 
      28             : namespace PLMD {
      29             : namespace colvar {
      30             : 
      31             : class RMSD : public Colvar {
      32             : 
      33             :   bool squared;
      34             :   bool nopbc;
      35             :   PLMD::RMSD myrmsd;
      36             :   std::vector<Vector> der;
      37             : public:
      38             :   explicit RMSD(const ActionOptions&);
      39             :   void calculate() override;
      40             :   static void registerKeywords(Keywords& keys);
      41             : };
      42             : 
      43             : //+PLUMEDOC DCOLVAR RMSD_SCALAR
      44             : /*
      45             : Calculate the RMSD with respect to a reference structure.
      46             : 
      47             : \par Examples
      48             : 
      49             : */
      50             : //+ENDPLUMEDOC
      51             : 
      52             : //+PLUMEDOC DCOLVAR RMSD
      53             : /*
      54             : Calculate the RMSD with respect to a reference structure.
      55             : 
      56             : The aim with this colvar it to calculate something like:
      57             : 
      58             : \f[
      59             : d(X,X') = \vert X-X' \vert
      60             : \f]
      61             : 
      62             : where \f$ X \f$ is the instantaneous position of all the atoms in the system and
      63             : \f$ X' \f$ is the positions of the atoms in some reference structure provided as input.
      64             : \f$ d(X,X') \f$ thus measures the distance all the atoms have moved away from this reference configuration.
      65             : Oftentimes, it is only the internal motions of the structure - i.e. not the translations of the center of
      66             : mass or the rotations of the reference frame - that are interesting.  Hence, when calculating the
      67             : the root-mean-square deviation between the atoms in two configurations
      68             : you must first superimpose the two structures in some way. At present PLUMED provides two distinct ways
      69             : of performing this superposition.  The first method is applied when you use TYPE=SIMPLE in the input
      70             : line.  This instruction tells PLUMED that the root mean square deviation is to be calculated after the
      71             : positions of the geometric centers in the reference and instantaneous configurations are aligned.  In
      72             : other words \f$d(X,x')\f$ is to be calculated using:
      73             : 
      74             : \f[
      75             :  d(X,X') = \sqrt{ \sum_i \sum_\alpha^{x,y,z}  \frac{w_i}{\sum_j w_j}( X_{i,\alpha}-com_\alpha(X)-{X'}_{i,\alpha}+com_\alpha(X') )^2 }
      76             : \f]
      77             : with
      78             : \f[
      79             : com_\alpha(X)= \sum_i  \frac{w'_{i}}{\sum_j w'_j}X_{i,\alpha}
      80             : \f]
      81             : and
      82             : \f[
      83             : com_\alpha(X')= \sum_i  \frac{w'_{i}}{\sum_j w'_j}X'_{i,\alpha}
      84             : \f]
      85             : Obviously, \f$ com_\alpha(X) \f$ and  \f$ com_\alpha(X') \f$  represent the positions of the center of mass in the reference
      86             : and instantaneous configurations if the weights $w'$ are set equal to the atomic masses.  If the weights are all set equal to
      87             : one, however, \f$com_\alpha(X) \f$ and  \f$ com_\alpha(X') \f$ are the positions of the geometric centers.
      88             : Notice that there are sets of weights:  \f$ w' \f$ and  \f$ w \f$. The first is used to calculate the position of the center of mass
      89             : (so it determines how the atoms are \e aligned).  Meanwhile, the second is used when calculating how far the atoms have actually been
      90             : \e displaced.  These weights are assigned in the reference configuration that you provide as input (i.e. the appear in the input file
      91             : to this action that you set using REFERENCE=whatever.pdb).  This input reference configuration consists of a simple pdb file
      92             : containing the set of atoms for which you want to calculate the RMSD displacement and their positions in the reference configuration.
      93             : It is important to note that the indices in this pdb need to be set correctly.  The indices in this file determine the indices of the
      94             : instantaneous atomic positions that are used by PLUMED when calculating this colvar.  As such if you want to calculate the RMSD distance
      95             : moved by the first, fourth, sixth and twenty eighth atoms in the MD codes input file then the indices of the corresponding reference positions in this pdb
      96             : file should be set equal to 1, 4, 6 and 28.
      97             : 
      98             : The pdb input file should also contain the values of \f$w\f$ and \f$w'\f$. In particular, the OCCUPANCY column (the first column after the coordinates)
      99             : is used provides the values of \f$ w'\f$ that are used to calculate the position of the center of mass.  The BETA column (the second column
     100             : after the Cartesian coordinates) is used to provide the \f$ w \f$ values which are used in the the calculation of the displacement.
     101             : Please note that it is possible to use fractional values for beta and for the occupancy. However, we recommend you only do this when
     102             : you really know what you are doing however as the results can be rather strange.
     103             : 
     104             : In PDB files the atomic coordinates and box lengths should be in Angstroms unless
     105             : you are working with natural units.  If you are working with natural units then the coordinates
     106             : should be in your natural length unit.  For more details on the PDB file format visit http://www.wwpdb.org/docs.html.
     107             : Make sure your PDB file is correctly formatted as explained \ref pdbreader "in this page".
     108             : 
     109             : A different method is used to calculate the RMSD distance when you use TYPE=OPTIMAL on the input line.  In this case  the root mean square
     110             : deviation is calculated after the positions of geometric centers in the reference and instantaneous configurations are aligned AND after
     111             : an optimal alignment of the two frames is performed so that motion due to rotation of the reference frame between the two structures is
     112             : removed.  The equation for \f$d(X,X')\f$ in this case reads:
     113             : 
     114             : \f[
     115             : d(X,X') = \sqrt{ \sum_i \sum_\alpha^{x,y,z}  \frac{w_i}{\sum_j w_j}[ X_{i,\alpha}-com_\alpha(X)- \sum_\beta M(X,X',w')_{\alpha,\beta}({X'}_{i,\beta}-com_\beta(X')) ]^2 }
     116             : \f]
     117             : 
     118             : where \f$ M(X,X',w') \f$ is the optimal alignment matrix which is calculated using the Kearsley \cite kearsley algorithm.  Again different sets of
     119             : weights are used for the alignment (\f$w'\f$) and for the displacement calculations (\f$w\f$).
     120             : This gives a great deal of flexibility as it allows you to use a different sets of atoms (which may or may not overlap) for the alignment and displacement
     121             : parts of the calculation. This may be very useful when you want to calculate how a ligand moves about in a protein cavity as you can use the protein as a reference
     122             : system and do no alignment of the ligand.
     123             : 
     124             : (Note: when this form of RMSD is used to calculate the secondary structure variables (\ref ALPHARMSD, \ref ANTIBETARMSD and \ref PARABETARMSD
     125             : all the atoms in the segment are assumed to be part of both the alignment and displacement sets and all weights are set equal to one)
     126             : 
     127             : Please note that there are a number of other methods for calculating the distance between the instantaneous configuration and a reference configuration
     128             : that are available in plumed.  More information on these various methods can be found in the section of the manual on \ref dists.
     129             : 
     130             : When running with periodic boundary conditions, the atoms should be
     131             : in the proper periodic image. This is done automatically since PLUMED 2.5,
     132             : by considering the ordered list of atoms and rebuilding molecules using a procedure
     133             : that is equivalent to that done in \ref WHOLEMOLECULES . Notice that
     134             : rebuilding is local to this action. This is different from \ref WHOLEMOLECULES
     135             : which actually modifies the coordinates stored in PLUMED.
     136             : 
     137             : In case you want to recover the old behavior you should use the NOPBC flag.
     138             : In that case you need to take care that atoms are in the correct
     139             : periodic image.
     140             : 
     141             : \par Examples
     142             : 
     143             : The following tells plumed to calculate the RMSD distance between
     144             : the positions of the atoms in the reference file and their instantaneous
     145             : position.  The Kearsley algorithm is used so this is done optimally.
     146             : 
     147             : \plumedfile
     148             : RMSD REFERENCE=file.pdb TYPE=OPTIMAL
     149             : \endplumedfile
     150             : 
     151             : The reference configuration is specified in a pdb file that will have a format similar to the one shown below:
     152             : 
     153             : \auxfile{file.pdb}
     154             : ATOM      1  CL  ALA     1      -3.171   0.295   2.045  1.00  1.00
     155             : ATOM      5  CLP ALA     1      -1.819  -0.143   1.679  1.00  1.00
     156             : ATOM      6  OL  ALA     1      -1.177  -0.889   2.401  1.00  1.00
     157             : ATOM      7  NL  ALA     1      -1.313   0.341   0.529  1.00  1.00
     158             : ATOM      8  HL  ALA     1      -1.845   0.961  -0.011  1.00  1.00
     159             : END
     160             : \endauxfile
     161             : 
     162             : ...
     163             : 
     164             : */
     165             : //+ENDPLUMEDOC
     166             : 
     167             : PLUMED_REGISTER_ACTION(RMSD,"RMSD_SCALAR")
     168             : 
     169         163 : void RMSD::registerKeywords(Keywords& keys) {
     170         163 :   Colvar::registerKeywords(keys); keys.setDisplayName("RMSD");
     171         326 :   keys.add("compulsory","REFERENCE","a file in pdb format containing the reference structure and the atoms involved in the CV.");
     172         326 :   keys.add("compulsory","TYPE","SIMPLE","the manner in which RMSD alignment is performed.  Should be OPTIMAL or SIMPLE.");
     173         326 :   keys.addFlag("SQUARED",false," This should be set if you want mean squared displacement instead of RMSD ");
     174         163 :   keys.setValueDescription("the RMSD between the instantaneous structure and the reference structure that was input");
     175         163 : }
     176             : 
     177          81 : RMSD::RMSD(const ActionOptions&ao):
     178             :   PLUMED_COLVAR_INIT(ao),
     179          81 :   squared(false),
     180          81 :   nopbc(false)
     181             : {
     182             :   std::string reference;
     183         163 :   parse("REFERENCE",reference);
     184             :   std::string type;
     185          81 :   type.assign("SIMPLE");
     186          81 :   parse("TYPE",type);
     187          81 :   parseFlag("SQUARED",squared);
     188          81 :   parseFlag("NOPBC",nopbc);
     189          81 :   checkRead();
     190             : 
     191         163 :   addValueWithDerivatives(); setNotPeriodic();
     192          81 :   PDB pdb;
     193             : 
     194             :   // read everything in ang and transform to nm if we are not in natural units
     195          81 :   if( !pdb.read(reference,usingNaturalUnits(),0.1/getUnits().getLength()) )
     196           0 :     error("missing input file " + reference );
     197          81 :   myrmsd.set( pdb, type, true, true );
     198             : 
     199          81 :   std::vector<AtomNumber> atoms( pdb.getAtomNumbers() );
     200          81 :   requestAtoms( atoms ); der.resize( atoms.size() );
     201             : 
     202          80 :   log.printf("  reference from file %s\n",reference.c_str());
     203          80 :   log.printf("  which contains %d atoms\n",getNumberOfAtoms());
     204          80 :   log.printf("  with indices : ");
     205        3867 :   for(unsigned i=0; i<atoms.size(); ++i) {
     206        3787 :     if(i%25==0) log<<"\n";
     207        3787 :     log.printf("%d ",atoms[i].serial());
     208             :   }
     209          80 :   log.printf("\n");
     210          80 :   log.printf("  method for alignment : %s \n",type.c_str() );
     211          80 :   if(squared)log.printf("  chosen to use SQUARED option for MSD instead of RMSD\n");
     212          80 :   if(nopbc) log.printf("  without periodic boundary conditions\n");
     213          19 :   else      log.printf("  using periodic boundary conditions\n");
     214         164 : }
     215             : 
     216             : 
     217             : // calculator
     218       40516 : void RMSD::calculate() {
     219       40516 :   if(!nopbc) makeWhole();
     220       40516 :   double r=myrmsd.calculate( getPositions(), der, squared );
     221             : 
     222       40516 :   setValue(r);
     223    14617897 :   for(unsigned i=0; i<getNumberOfAtoms(); i++) setAtomsDerivatives( i, der[i] );
     224       40516 :   setBoxDerivativesNoPbc();
     225       40516 : }
     226             : 
     227             : }
     228             : }
     229             : 
     230             : 
     231             : 

Generated by: LCOV version 1.16