LCOV - code coverage report
Current view: top level - secondarystructure - ParabetaRMSD.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 110 116 94.8 %
Date: 2026-03-30 13:16:06 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-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 "SecondaryStructureRMSD.h"
      23             : #include "core/ActionRegister.h"
      24             : #include "core/PlumedMain.h"
      25             : 
      26             : namespace PLMD {
      27             : namespace secondarystructure {
      28             : 
      29             : //+PLUMEDOC COLVAR PARABETARMSD
      30             : /*
      31             : Probe the parallel beta sheet content of your protein structure.
      32             : 
      33             : Two protein segments containing three contiguous residues can form a parallel beta sheet.
      34             : Although if the two segments are part of the same protein chain they must be separated by
      35             : a minimum of 3 residues to make room for the turn. This colvar thus generates the set of
      36             : all possible six residue sections that could conceivably form a parallel beta sheet
      37             : and calculates the RMSD distance between the configuration in which the residues find themselves
      38             : and an idealized parallel beta sheet structure. These distances can be calculated by either
      39             : aligning the instantaneous structure with the reference structure and measuring each
      40             : atomic displacement or by calculating differences between the set of inter-atomic
      41             : distances in the reference and instantaneous structures.
      42             : 
      43             : This colvar is based on the following reference \cite pietrucci09jctc.  The authors of
      44             : this paper use the set of distances from the parallel beta sheet configurations to measure
      45             : the number of segments whose configuration resembles a parallel beta sheet. This is done by calculating
      46             : the following sum of functions of the rmsd distances:
      47             : 
      48             : \f[
      49             : s = \sum_i \frac{ 1 - \left(\frac{r_i-d_0}{r_0}\right)^n } { 1 - \left(\frac{r_i-d_0}{r_0}\right)^m }
      50             : \f]
      51             : 
      52             : where the sum runs over all possible segments of parallel beta sheet.  By default the
      53             : NN, MM and D_0 parameters are set equal to those used in \cite pietrucci09jctc.  The R_0
      54             : parameter must be set by the user - the value used in \cite pietrucci09jctc was 0.08 nm.
      55             : 
      56             : If you change the function in the above sum you can calculate quantities such as the average
      57             : distance from a structure composed of only parallel beta sheets or the distance between the set of
      58             : residues that is closest to a parallel beta sheet and the reference configuration. To do these sorts of
      59             : calculations you can use the AVERAGE and MIN keywords. In addition you can use the LESS_THAN
      60             : keyword if you would like to change the form of the switching function. If you use any of these
      61             : options you no longer need to specify NN, R_0, MM and D_0.
      62             : 
      63             : Please be aware that for codes like gromacs you must ensure that plumed
      64             : reconstructs the chains involved in your CV when you calculate this CV using
      65             : anything other than TYPE=DRMSD.  For more details as to how to do this see \ref WHOLEMOLECULES.
      66             : 
      67             : \par Examples
      68             : 
      69             : The following input calculates the number of six residue segments of
      70             : protein that are in an parallel beta sheet configuration.
      71             : 
      72             : \plumedfile
      73             : #SETTINGS MOLFILE=regtest/basic/rt32/helix.pdb
      74             : MOLINFO STRUCTURE=beta.pdb
      75             : pb: PARABETARMSD RESIDUES=all STRANDS_CUTOFF=1
      76             : \endplumedfile
      77             : 
      78             : Here the same is done use RMSD instead of DRMSD
      79             : 
      80             : \plumedfile
      81             : #SETTINGS MOLFILE=regtest/basic/rt32/helix.pdb
      82             : MOLINFO STRUCTURE=helix.pdb
      83             : WHOLEMOLECULES ENTITY0=1-100
      84             : hh: PARABETARMSD RESIDUES=all TYPE=OPTIMAL R_0=0.1  STRANDS_CUTOFF=1
      85             : \endplumedfile
      86             : 
      87             : */
      88             : //+ENDPLUMEDOC
      89             : 
      90             : class ParabetaRMSD : public SecondaryStructureRMSD {
      91             : public:
      92             :   static void registerKeywords( Keywords& keys );
      93             :   explicit ParabetaRMSD(const ActionOptions&);
      94             : };
      95             : 
      96       13823 : PLUMED_REGISTER_ACTION(ParabetaRMSD,"PARABETARMSD")
      97             : 
      98          23 : void ParabetaRMSD::registerKeywords( Keywords& keys ) {
      99          23 :   SecondaryStructureRMSD::registerKeywords( keys );
     100          46 :   keys.add("compulsory","STYLE","all","Parallel beta sheets can either form in a single chain or from a pair of chains. If STYLE=all all "
     101             :            "chain configuration with the appropriate geometry are counted.  If STYLE=inter "
     102             :            "only sheet-like configurations involving two chains are counted, while if STYLE=intra "
     103             :            "only sheet-like configurations involving a single chain are counted");
     104          23 :   keys.use("STRANDS_CUTOFF");
     105          23 : }
     106             : 
     107          19 : ParabetaRMSD::ParabetaRMSD(const ActionOptions&ao):
     108             :   Action(ao),
     109          19 :   SecondaryStructureRMSD(ao) {
     110             :   // read in the backbone atoms
     111             :   std::vector<unsigned> chains;
     112          38 :   readBackboneAtoms( "protein", chains );
     113             : 
     114             :   bool intra_chain(false), inter_chain(false);
     115             :   std::string style;
     116          38 :   parse("STYLE",style);
     117          19 :   if( style=="all" ) {
     118             :     intra_chain=true;
     119             :     inter_chain=true;
     120           2 :   } else if( style=="inter") {
     121             :     intra_chain=false;
     122             :     inter_chain=true;
     123           1 :   } else if( style=="intra") {
     124             :     intra_chain=true;
     125             :     inter_chain=false;
     126             :   } else {
     127           0 :     error( style + " is not a valid directive for the STYLE keyword");
     128             :   }
     129             : 
     130             :   // Align the atoms based on the positions of these two atoms
     131          19 :   setAtomsFromStrands( 6, 21 );
     132             : 
     133             :   // This constructs all conceivable sections of antibeta sheet in the backbone of the chains
     134          19 :   if( intra_chain ) {
     135             :     unsigned nprevious=0;
     136          18 :     std::vector<unsigned> nlist(30);
     137         325 :     for(unsigned i=0; i<chains.size(); ++i) {
     138         307 :       if( chains[i]<40 ) {
     139           0 :         error("segment of backbone is not long enough to form an antiparallel beta hairpin. Each backbone fragment must contain a minimum of 8 residues");
     140             :       }
     141             :       // Loop over all possible triples in each 8 residue segment of protein
     142         307 :       unsigned nres=chains[i]/5;
     143         307 :       if( chains[i]%5!=0 ) {
     144           0 :         error("backbone segment received does not contain a multiple of five residues");
     145             :       }
     146         311 :       for(unsigned ires=0; ires<nres-8; ires++) {
     147          14 :         for(unsigned jres=ires+6; jres<nres-2; jres++) {
     148         160 :           for(unsigned k=0; k<15; ++k) {
     149         150 :             nlist[k]=nprevious + ires*5+k;
     150         150 :             nlist[k+15]=nprevious + jres*5+k;
     151             :           }
     152          10 :           addColvar( nlist );
     153             :         }
     154             :       }
     155         307 :       nprevious+=chains[i];
     156             :     }
     157             :   }
     158             :   // This constructs all conceivable sections of antibeta sheet that form between chains
     159          19 :   if( inter_chain ) {
     160          19 :     if( chains.size()==1 && style!="all" ) {
     161           0 :       error("there is only one chain defined so cannot use inter_chain option");
     162             :     }
     163          18 :     std::vector<unsigned> nlist(30);
     164         307 :     for(unsigned ichain=1; ichain<chains.size(); ++ichain) {
     165             :       unsigned iprev=0;
     166        2890 :       for(unsigned i=0; i<ichain; ++i) {
     167        2601 :         iprev+=chains[i];
     168             :       }
     169         289 :       unsigned inres=chains[ichain]/5;
     170         289 :       if( chains[ichain]%5!=0 ) {
     171           0 :         error("backbone segment received does not contain a multiple of five residues");
     172             :       }
     173        2023 :       for(unsigned ires=0; ires<inres-2; ++ires) {
     174       17340 :         for(unsigned jchain=0; jchain<ichain; ++jchain) {
     175             :           unsigned jprev=0;
     176       98838 :           for(unsigned i=0; i<jchain; ++i) {
     177       83232 :             jprev+=chains[i];
     178             :           }
     179       15606 :           unsigned jnres=chains[jchain]/5;
     180       15606 :           if( chains[jchain]%5!=0 ) {
     181           0 :             error("backbone segment received does not contain a multiple of five residues");
     182             :           }
     183      109242 :           for(unsigned jres=0; jres<jnres-2; ++jres) {
     184     1498176 :             for(unsigned k=0; k<15; ++k) {
     185     1404540 :               nlist[k]=iprev + ires*5+k;
     186     1404540 :               nlist[k+15]=jprev + jres*5+k;
     187             :             }
     188       93636 :             addColvar( nlist );
     189             :           }
     190             :         }
     191             :       }
     192             :     }
     193             :   }
     194             : 
     195             :   // Build the reference structure ( in angstroms )
     196          19 :   std::vector<Vector> reference(30);
     197          19 :   reference[0]=Vector( 1.244, -4.620, -2.127); // N    i
     198          19 :   reference[1]=Vector(-0.016, -4.500, -1.395); // CA
     199          19 :   reference[2]=Vector( 0.105, -5.089,  0.024); // CB
     200          19 :   reference[3]=Vector(-0.287, -3.000, -1.301); // C
     201          19 :   reference[4]=Vector( 0.550, -2.245, -0.822); // O
     202          19 :   reference[5]=Vector(-1.445, -2.551, -1.779); // N    i+1
     203          19 :   reference[6]=Vector(-1.752, -1.130, -1.677); // CA
     204          19 :   reference[7]=Vector(-2.113, -0.550, -3.059); // CB
     205          19 :   reference[8]=Vector(-2.906, -0.961, -0.689); // C
     206          19 :   reference[9]=Vector(-3.867, -1.738, -0.695); // O
     207          19 :   reference[10]=Vector(-2.774,  0.034,  0.190); // N    i+2
     208          19 :   reference[11]=Vector(-3.788,  0.331,  1.201); // CA
     209          19 :   reference[12]=Vector(-3.188,  0.300,  2.624); // CB
     210          19 :   reference[13]=Vector(-4.294,  1.743,  0.937); // C
     211          19 :   reference[14]=Vector(-3.503,  2.671,  0.821); // O
     212          19 :   reference[15]=Vector( 4.746, -2.363,  0.188); // N    j
     213          19 :   reference[16]=Vector( 3.427, -1.839,  0.545); // CA
     214          19 :   reference[17]=Vector( 3.135, -1.958,  2.074); // CB
     215          19 :   reference[18]=Vector( 3.346, -0.365,  0.181); // C
     216          19 :   reference[19]=Vector( 4.237,  0.412,  0.521); // O
     217          19 :   reference[20]=Vector( 2.261,  0.013, -0.487); // N    j+1
     218          19 :   reference[21]=Vector( 2.024,  1.401, -0.875); // CA
     219          19 :   reference[22]=Vector( 1.489,  1.514, -2.313); // CB
     220          19 :   reference[23]=Vector( 0.914,  1.902,  0.044); // C
     221          19 :   reference[24]=Vector(-0.173,  1.330,  0.052); // O
     222          19 :   reference[25]=Vector( 1.202,  2.940,  0.828); // N    j+2
     223          19 :   reference[26]=Vector( 0.190,  3.507,  1.718); // CA
     224          19 :   reference[27]=Vector( 0.772,  3.801,  3.104); // CB
     225          19 :   reference[28]=Vector(-0.229,  4.791,  1.038); // C
     226          19 :   reference[29]=Vector( 0.523,  5.771,  0.996); // O
     227             :   // Store the secondary structure ( last number makes sure we convert to internal units nm )
     228          19 :   setSecondaryStructure( reference, 0.17/atoms.getUnits().getLength(), 0.1/atoms.getUnits().getLength() );
     229             : 
     230          19 :   reference[0]=Vector(-1.439, -5.122, -1.144); // N    i
     231          19 :   reference[1]=Vector(-0.816, -3.803, -1.013); // CA
     232          19 :   reference[2]=Vector( 0.099, -3.509, -2.206); // CB
     233          19 :   reference[3]=Vector(-1.928, -2.770, -0.952); // C
     234          19 :   reference[4]=Vector(-2.991, -2.970, -1.551); // O
     235          19 :   reference[5]=Vector(-1.698, -1.687, -0.215); // N    i+1
     236          19 :   reference[6]=Vector(-2.681, -0.613, -0.143); // CA
     237          19 :   reference[7]=Vector(-3.323, -0.477,  1.267); // CB
     238          19 :   reference[8]=Vector(-1.984,  0.681, -0.574); // C
     239          19 :   reference[9]=Vector(-0.807,  0.921, -0.273); // O
     240          19 :   reference[10]=Vector(-2.716,  1.492, -1.329); // N    i+2
     241          19 :   reference[11]=Vector(-2.196,  2.731, -1.883); // CA
     242          19 :   reference[12]=Vector(-2.263,  2.692, -3.418); // CB
     243          19 :   reference[13]=Vector(-2.989,  3.949, -1.433); // C
     244          19 :   reference[14]=Vector(-4.214,  3.989, -1.583); // O
     245          19 :   reference[15]=Vector( 2.464, -4.352,  2.149); // N    j
     246          19 :   reference[16]=Vector( 3.078, -3.170,  1.541); // CA
     247          19 :   reference[17]=Vector( 3.398, -3.415,  0.060); // CB
     248          19 :   reference[18]=Vector( 2.080, -2.021,  1.639); // C
     249          19 :   reference[19]=Vector( 0.938, -2.178,  1.225); // O
     250          19 :   reference[20]=Vector( 2.525, -0.886,  2.183); // N    j+1
     251          19 :   reference[21]=Vector( 1.692,  0.303,  2.346); // CA
     252          19 :   reference[22]=Vector( 1.541,  0.665,  3.842); // CB
     253          19 :   reference[23]=Vector( 2.420,  1.410,  1.608); // C
     254          19 :   reference[24]=Vector( 3.567,  1.733,  1.937); // O
     255          19 :   reference[25]=Vector( 1.758,  1.976,  0.600); // N    j+2
     256          19 :   reference[26]=Vector( 2.373,  2.987, -0.238); // CA
     257          19 :   reference[27]=Vector( 2.367,  2.527, -1.720); // CB
     258          19 :   reference[28]=Vector( 1.684,  4.331, -0.148); // C
     259          19 :   reference[29]=Vector( 0.486,  4.430, -0.415); // O
     260             :   // Store the secondary structure ( last number makes sure we convert to internal units nm )
     261          19 :   setSecondaryStructure( reference, 0.17/atoms.getUnits().getLength(), 0.1/atoms.getUnits().getLength() );
     262          19 : }
     263             : 
     264             : }
     265             : }

Generated by: LCOV version 1.16