LCOV - code coverage report
Current view: top level - tools - RMSD.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 29 34 85.3 %
Date: 2018-12-19 07:49:13 Functions: 12 15 80.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2018 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             : #ifndef __PLUMED_tools_RMSD_h
      23             : #define __PLUMED_tools_RMSD_h
      24             : 
      25             : #include "Vector.h"
      26             : #include "Matrix.h"
      27             : #include "Tensor.h"
      28             : #include <vector>
      29             : #include <string>
      30             : 
      31             : namespace PLMD {
      32             : 
      33             : class Log;
      34             : class PDB;
      35             : 
      36             : /** \ingroup TOOLBOX
      37             : A class that implements RMSD calculations
      38             : This is a class that implements the various infrastructure to calculate the
      39             : RMSD or MSD respect a given frame. It can be done through an optimal alignment scheme
      40             : as Kearsley or, more simply, by resetting the center of mass.
      41             : This is the class that decides this. A very simple use is
      42             : \verbatim
      43             : #include "tools/PDB.h"
      44             : #include "tools/RMSD.h"
      45             : #include "tools/Vector.h"
      46             : using namespace PLMD;
      47             : RMSD rmsd;
      48             : PDB pdb;
      49             : // get the pdb (see PDB documentation)
      50             : pdb.read("file.pdb",true,1.0);
      51             : string type;
      52             : type.assign("OPTIMAL");
      53             : // set the reference and the type
      54             : rmsd.set(pdb,type);
      55             : // this calculates the rmsd and the derivatives
      56             : vector<Vector> derivs;
      57             : double val;
      58             : val=rmsd.calculate(getPositions(),derivs,true);
      59             : \endverbatim
      60             : 
      61             : **/
      62             : 
      63        6590 : class RMSD
      64             : {
      65             :   enum AlignmentMethod {SIMPLE, OPTIMAL, OPTIMAL_FAST};
      66             :   AlignmentMethod alignmentMethod;
      67             : // Reference coordinates
      68             :   std::vector<Vector> reference;
      69             : // Weights for alignment
      70             :   std::vector<double> align;
      71             : // Weights for deviation
      72             :   std::vector<double> displace;
      73             : // Center for reference and flag for its calculation
      74             :   Vector reference_center;
      75             :   bool reference_center_is_calculated;
      76             :   bool reference_center_is_removed;
      77             : // Center for running position (not used in principle but here to reflect reference/positio symmetry
      78             :   Vector positions_center;
      79             :   bool positions_center_is_calculated;
      80             :   bool positions_center_is_removed;
      81             : // calculates the center from the position provided
      82        1877 :   Vector calculateCenter(std::vector<Vector> &p,std::vector<double> &w) {
      83        1877 :     plumed_massert(p.size()==w.size(),"mismatch in dimension of position/align arrays while calculating the center");
      84        1877 :     unsigned n; n=p.size();
      85        1877 :     Vector c; c.zero();
      86        1877 :     for(unsigned i=0; i<n; i++)c+=p[i]*w[i];
      87        1877 :     return c;
      88             :   };
      89             : // removes the center for the position provided
      90        3750 :   void removeCenter(std::vector<Vector> &p, Vector &c) {
      91        3750 :     unsigned n; n=p.size();
      92        3750 :     for(unsigned i=0; i<n; i++)p[i]-=c;
      93        3750 :   };
      94             : // add center
      95        1877 :   void addCenter(std::vector<Vector> &p, Vector &c) {Vector cc=c*-1.; removeCenter(p,cc);};
      96             : 
      97             : public:
      98             : /// Constructor
      99             :   RMSD();
     100             : /// clear the structure
     101             :   void clear();
     102             : /// set reference, align and displace from input pdb structure: evtl remove com from the initial structure and normalize the input weights from the pdb
     103             :   void set(const PDB&,const std::string & mytype, bool remove_center=true, bool normalize_weights=true);
     104             : /// set align displace reference and type from input vectors
     105             :   void set(const std::vector<double> & align, const std::vector<double> & displace, const std::vector<Vector> & reference,const std::string & mytype, bool remove_center=true, bool normalize_weights=true );
     106             : /// set the type of alignment we are doing
     107             :   void setType(const std::string & mytype);
     108             : /// set reference coordinates, remove the com by using uniform weights
     109             :   void setReference(const std::vector<Vector> & reference);
     110             : /// set weights and remove the center from reference with normalized weights. If the com has been removed, it resets to the new value
     111             :   void setAlign(const std::vector<double> & align, bool normalize_weights=true, bool remove_center=true);
     112             : /// set align
     113             :   void setDisplace(const std::vector<double> & displace, bool normalize_weights=true);
     114             : ///
     115             :   std::string getMethod();
     116             : /// workhorses
     117             :   double simpleAlignment(const  std::vector<double>  & align,
     118             :                          const  std::vector<double>  & displace,
     119             :                          const std::vector<Vector> & positions,
     120             :                          const std::vector<Vector> & reference,
     121             :                          std::vector<Vector>  & derivatives,
     122             :                          std::vector<Vector>  & displacement,
     123             :                          bool squared=false)const;
     124             :   template <bool safe,bool alEqDis>
     125             :   double optimalAlignment(const  std::vector<double>  & align,
     126             :                           const  std::vector<double>  & displace,
     127             :                           const std::vector<Vector> & positions,
     128             :                           const std::vector<Vector> & reference,
     129             :                           std::vector<Vector>  & DDistDPos, bool squared=false)const;
     130             : 
     131             :   template <bool safe,bool alEqDis>
     132             :   double optimalAlignment_DDistDRef(const  std::vector<double>  & align,
     133             :                                     const  std::vector<double>  & displace,
     134             :                                     const std::vector<Vector> & positions,
     135             :                                     const std::vector<Vector> & reference,
     136             :                                     std::vector<Vector>  & DDistDPos,
     137             :                                     std::vector<Vector> &  DDistDRef,
     138             :                                     bool squared=false) const;
     139             : 
     140             :   template <bool safe,bool alEqDis>
     141             :   double optimalAlignment_SOMA(const  std::vector<double>  & align,
     142             :                                const  std::vector<double>  & displace,
     143             :                                const std::vector<Vector> & positions,
     144             :                                const std::vector<Vector> & reference,
     145             :                                std::vector<Vector>  & DDistDPos,
     146             :                                std::vector<Vector> &  DDistDRef,
     147             :                                bool squared=false) const;
     148             : 
     149             :   template <bool safe,bool alEqDis>
     150             :   double optimalAlignment_DDistDRef_Rot_DRotDPos(const  std::vector<double>  & align,
     151             :       const  std::vector<double>  & displace,
     152             :       const std::vector<Vector> & positions,
     153             :       const std::vector<Vector> & reference,
     154             :       std::vector<Vector>  & DDistDPos,
     155             :       std::vector<Vector> &  DDistDRef,
     156             :       Tensor & Rotation,
     157             :       Matrix<std::vector<Vector> > &DRotDPos,
     158             :       bool squared=false) const;
     159             : 
     160             :   template <bool safe,bool alEqDis>
     161             :   double optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(const  std::vector<double>  & align,
     162             :       const  std::vector<double>  & displace,
     163             :       const std::vector<Vector> & positions,
     164             :       const std::vector<Vector> & reference,
     165             :       std::vector<Vector>  & DDistDPos,
     166             :       std::vector<Vector> &  DDistDRef,
     167             :       Tensor & Rotation,
     168             :       Matrix<std::vector<Vector> > &DRotDPos,
     169             :       Matrix<std::vector<Vector> > &DRotDRef,
     170             :       bool squared=false) const;
     171             : 
     172             :   template <bool safe,bool alEqDis>
     173             :   double optimalAlignment_PCA(const  std::vector<double>  & align,
     174             :                               const  std::vector<double>  & displace,
     175             :                               const std::vector<Vector> & positions,
     176             :                               const std::vector<Vector> & reference,
     177             :                               std::vector<Vector> & alignedpositions,
     178             :                               std::vector<Vector> & centeredpositions,
     179             :                               std::vector<Vector> & centeredreference,
     180             :                               Tensor & Rotation,
     181             :                               std::vector<Vector> & DDistDPos,
     182             :                               Matrix<std::vector<Vector> > & DRotDPos,
     183             :                               bool squared=false) const ;
     184             : 
     185             :   template <bool safe,bool alEqDis>
     186             :   double optimalAlignment_Fit(const  std::vector<double>  & align,
     187             :                               const  std::vector<double>  & displace,
     188             :                               const std::vector<Vector> & positions,
     189             :                               const std::vector<Vector> & reference,
     190             :                               Tensor & Rotation,
     191             :                               Matrix<std::vector<Vector> > & DRotDPos,
     192             :                               std::vector<Vector> & centeredpositions,
     193             :                               Vector & center_positions,
     194             :                               bool squared=false);
     195             : 
     196             : 
     197             : /// Compute rmsd: note that this is an intermediate layer which is kept in order to evtl expand with more alignment types/user options to be called while keeping the workhorses separated
     198             :   double calculate(const std::vector<Vector> & positions,std::vector<Vector> &derivatives, bool squared=false)const;
     199             : /// Other convenience methods:
     200             : /// calculate the derivative of distance respect to position(DDistDPos) and reference (DDistDPos)
     201             :   double calc_DDistDRef( const std::vector<Vector>& positions, std::vector<Vector> &DDistDPos, std::vector<Vector>& DDistDRef, const bool squared=false   );
     202             : /// calculate the derivative for SOMA (i.e. derivative respect to reference frame without the matrix derivative)
     203             :   double calc_SOMA( const std::vector<Vector>& positions, std::vector<Vector> &DDistDPos, std::vector<Vector>& DDistDRef, const bool squared=false   );
     204             : ///
     205             :   double calc_DDistDRef_Rot_DRotDPos( const std::vector<Vector>& positions, std::vector<Vector> &DDistDPos, std::vector<Vector>& DDistDRef, Tensor & Rotation,Matrix<std::vector<Vector> > &DRotDPos, const bool squared=false   );
     206             :   double calc_DDistDRef_Rot_DRotDPos_DRotDRef( const std::vector<Vector>& positions, std::vector<Vector> &DDistDPos, std::vector<Vector>& DDistDRef, Tensor & Rotation,Matrix<std::vector<Vector> > &DRotDPos,Matrix<std::vector<Vector> > &DRotDRef, const bool squared=false   );
     207             : /// convenience method to retrieve all the bits and pieces for PCA
     208             :   double calc_PCAelements( const std::vector<Vector>& pos, std::vector<Vector> &DDistDPos, Tensor & Rotation, Matrix<std::vector<Vector> > & DRotDPos,std::vector<Vector>  & alignedpositions, std::vector<Vector> & centeredpositions, std::vector<Vector> &centeredreference, const bool& squared=false) const ;
     209             : /// convenience method to retrieve all the bits and pieces needed by FitToTemplate
     210             :   double calc_FitElements( const std::vector<Vector>& pos, Tensor & Rotation, Matrix<std::vector<Vector> > & DRotDPos,std::vector<Vector> & centeredpositions,Vector & center_positions, const bool& squared=false );
     211             : /// static convenience method to get the matrix i,a from drotdpos (which is a bit tricky)
     212         720 :   static  Tensor getMatrixFromDRot(Matrix< std::vector<Vector> > &drotdpos, const unsigned &i, const unsigned &a) {
     213         720 :     Tensor t;
     214         720 :     t[0][0]=drotdpos[0][0][i][a]; t[0][1]=drotdpos[0][1][i][a]; t[0][2]=drotdpos[0][2][i][a];
     215         720 :     t[1][0]=drotdpos[1][0][i][a]; t[1][1]=drotdpos[1][1][i][a]; t[1][2]=drotdpos[1][2][i][a];
     216         720 :     t[2][0]=drotdpos[2][0][i][a]; t[2][1]=drotdpos[2][1][i][a]; t[2][2]=drotdpos[2][2][i][a];
     217         720 :     return t;
     218             :   };
     219             : };
     220             : 
     221             : /// this is a class which is needed to share information across the various non-threadsafe routines
     222             : /// so that the public function of rmsd are threadsafe while the inner core can safely share information
     223        1719 : class RMSDCoreData
     224             : {
     225             : private:
     226             :   bool alEqDis;
     227             :   bool distanceIsMSD; // default is RMSD but can deliver the MSD
     228             :   bool hasDistance;  // distance is already calculated
     229             :   bool isInitialized;
     230             :   bool safe;
     231             : 
     232             :   // this need to be copied and they are small, should not affect the performance
     233             :   Vector creference;
     234             :   bool creference_is_calculated;
     235             :   bool creference_is_removed;
     236             :   Vector cpositions;
     237             :   bool cpositions_is_calculated;
     238             :   bool cpositions_is_removed;
     239             :   bool retrieve_only_rotation;
     240             : 
     241             :   // use reference assignment to speed up instead of copying
     242             :   const std::vector<Vector> &positions;
     243             :   const std::vector<Vector> &reference;
     244             :   const std::vector<double> &align;
     245             :   const std::vector<double> &displace;
     246             : 
     247             :   // the needed stuff for distance and more (one could use eigenvecs components and eigenvals for some reason)
     248             :   double dist;
     249             :   std::vector<double> eigenvals;
     250             :   Matrix<double> eigenvecs;
     251             :   double rr00; //  sum of positions squared (needed for dist calc)
     252             :   double rr11; //  sum of reference squared (needed for dist calc)
     253             :   Tensor rotation; // rotation derived from the eigenvector having the smallest eigenvalue
     254             :   Tensor drotation_drr01[3][3]; // derivative of the rotation only available when align!=displace
     255             :   Tensor ddist_drr01;
     256             :   Tensor ddist_drotation;
     257             :   std::vector<Vector> d; // difference of components
     258             : public:
     259             :   /// the constructor (note: only references are passed, therefore is rather fast)
     260             :   /// note: this aligns the reference onto the positions
     261             :   ///
     262             :   /// this method assumes that the centers are already calculated and subtracted
     263             :   RMSDCoreData(const std::vector<double> &a,const std::vector<double> &d,const std::vector<Vector> &p, const std::vector<Vector> &r, Vector &cp, Vector &cr ):
     264             :     alEqDis(false),distanceIsMSD(false),hasDistance(false),isInitialized(false),safe(false),
     265             :     creference(cr),creference_is_calculated(true),creference_is_removed(true),
     266             :     cpositions(cp),cpositions_is_calculated(true),cpositions_is_removed(true),retrieve_only_rotation(false),positions(p),reference(r),align(a),displace(d),dist(0.0),rr00(0.0),rr11(0.0) {};
     267             : 
     268             :   // this constructor does not assume that the positions and reference have the center subtracted
     269        1719 :   RMSDCoreData(const std::vector<double> &a,const std::vector<double> &d,const std::vector<Vector> &p, const std::vector<Vector> &r):
     270             :     alEqDis(false),distanceIsMSD(false),hasDistance(false),isInitialized(false),safe(false),
     271             :     creference_is_calculated(false),creference_is_removed(false),
     272        1719 :     cpositions_is_calculated(false),cpositions_is_removed(false),retrieve_only_rotation(false),positions(p),reference(r),align(a),displace(d),dist(0.0),rr00(0.0),rr11(0.0)
     273        1719 :   {cpositions.zero(); creference.zero();};
     274             : 
     275             :   // set the center on the fly without subtracting
     276        1719 :   void calcPositionsCenter() {
     277        1719 :     plumed_massert(!cpositions_is_calculated,"the center was already calculated");
     278        1719 :     cpositions.zero(); for(unsigned i=0; i<positions.size(); i++) {cpositions+=positions[i]*align[i];} cpositions_is_calculated=true;
     279        1719 :   }
     280           0 :   void calcReferenceCenter() {
     281           0 :     plumed_massert(!creference_is_calculated,"the center was already calculated");
     282           0 :     creference.zero(); for(unsigned i=0; i<reference.size(); i++) {creference+=reference[i]*align[i];} creference_is_calculated=true;
     283           0 :   };
     284             :   // assume the center is given externally
     285           0 :   void setPositionsCenter(Vector v) {plumed_massert(!cpositions_is_calculated,"You are setting the center two times!"); cpositions=v; cpositions_is_calculated=true;};
     286        1719 :   void setReferenceCenter(Vector v) {plumed_massert(!creference_is_calculated,"You are setting the center two times!"); creference=v; creference_is_calculated=true;};
     287             :   // the center is already removed
     288        1719 :   void setPositionsCenterIsRemoved(bool t) {cpositions_is_removed=t;};
     289        1719 :   void setReferenceCenterIsRemoved(bool t) {creference_is_removed=t;};
     290             :   bool getPositionsCenterIsRemoved() {return cpositions_is_removed;};
     291             :   bool getReferenceCenterIsRemoved() {return creference_is_removed;};
     292             :   //  does the core calc : first thing to call after the constructor:
     293             :   // only_rotation=true does not retrieve the derivatives, just retrieve the optimal rotation (the same calc cannot be exploit further)
     294             :   void doCoreCalc(bool safe,bool alEqDis, bool only_rotation=false);
     295             :   // retrieve the distance if required after doCoreCalc
     296             :   double getDistance(bool squared);
     297             :   // retrieve the derivative of the distance respect to the position
     298             :   std::vector<Vector> getDDistanceDPositions();
     299             :   // retrieve the derivative of the distance respect to the reference
     300             :   std::vector<Vector> getDDistanceDReference();
     301             :   // specific version for SOMA calculation (i.e. does not need derivative respect to rotation matrix)
     302             :   std::vector<Vector> getDDistanceDReferenceSOMA();
     303             :   // get aligned reference onto position
     304             :   std::vector<Vector> getAlignedReferenceToPositions();
     305             :   // get aligned position onto reference
     306             :   std::vector<Vector> getAlignedPositionsToReference();
     307             :   // get centered positions
     308             :   std::vector<Vector> getCenteredPositions();
     309             :   // get centered reference
     310             :   std::vector<Vector> getCenteredReference();
     311             :   // get center of positions
     312             :   Vector getPositionsCenter();
     313             :   // get center of reference
     314             :   Vector getReferenceCenter();
     315             :   // get rotation matrix (reference ->positions)
     316             :   Tensor getRotationMatrixReferenceToPositions();
     317             :   // get rotation matrix (positions -> reference)
     318             :   Tensor getRotationMatrixPositionsToReference();
     319             :   // get the derivative of the rotation matrix respect to positions
     320             :   // note that the this transformation overlap the  reference onto position
     321             :   // if inverseTransform=true then aligns the positions onto reference
     322             :   Matrix<std::vector<Vector> > getDRotationDPositions( bool inverseTransform=false );
     323             :   // get the derivative of the rotation matrix respect to reference
     324             :   // note that the this transformation overlap the  reference onto position
     325             :   // if inverseTransform=true then aligns the positions onto reference
     326             :   Matrix<std::vector<Vector> >  getDRotationDReference(bool inverseTransform=false );
     327             : };
     328             : 
     329             : }
     330             : 
     331             : #endif
     332             : 

Generated by: LCOV version 1.13