LCOV - code coverage report
Current view: top level - secondarystructure - AntibetaRMSD.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 118 125 94.4 %
Date: 2025-04-14 15:25:36 Functions: 2 3 66.7 %

          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/ActionShortcut.h"
      24             : #include "core/ActionRegister.h"
      25             : 
      26             : namespace PLMD {
      27             : namespace secondarystructure {
      28             : 
      29             : //+PLUMEDOC COLVAR ANTIBETARMSD
      30             : /*
      31             : Probe the antiparallel beta sheet content of your protein structure.
      32             : 
      33             : Two protein segments containing three contiguous residues can form an antiparallel beta sheet.
      34             : Although if the two segments are part of the same protein chain they must be separated by
      35             : a minimum of 2 residues to make room for the turn. This colvar thus generates the set of
      36             : all possible six residue sections that could conceivably form an antiparallel beta sheet
      37             : and calculates the [DRMSD](DRMSD.md) or [RMSD](RMSD.md) distance between the configuration in which the residues find themselves
      38             : and an idealized antiparallel 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 ideas from the paper cited below.  The authors of
      44             : this paper use the set of distances from the anti parallel beta sheet configurations to measure
      45             : the number of segments that have an configuration that resembles an anti parallel beta sheet. This is done by calculating
      46             : the following sum of functions of the rmsd distances:
      47             : 
      48             : $$
      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             : $$
      51             : 
      52             : where the sum runs over all possible segments of antiparallel beta sheet.  By default the
      53             : NN, MM and D_0 parameters are set equal to those used in the paper cited below.  The R_0
      54             : parameter must be set by the user - the value used in the paper below 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 purely configuration composed of pure anti-parallel beta sheets or the distance between the set of
      58             : residues that is closest to an anti-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             : The following input calculates the number of six residue segments of
      64             : protein that are in an antiparallel beta sheet configuration.
      65             : 
      66             : ```plumed
      67             : #SETTINGS MOLFILE=regtest/basic/rt32/helix.pdb
      68             : MOLINFO STRUCTURE=regtest/basic/rt32/helix.pdb
      69             : ab: ANTIBETARMSD RESIDUES=all STRANDS_CUTOFF=1 R_0=0.1
      70             : PRINT ARG=ab FILE=colvar
      71             : ```
      72             : 
      73             : Here the same is done use [RMSD](RMSD.md) instead of [DRMSD](DRMSD.md)
      74             : 
      75             : ```plumed
      76             : #SETTINGS MOLFILE=regtest/basic/rt32/helix.pdb
      77             : MOLINFO STRUCTURE=regtest/basic/rt32/helix.pdb
      78             : WHOLEMOLECULES ENTITY0=1-100
      79             : hh: ANTIBETARMSD RESIDUES=all TYPE=OPTIMAL LESS_THAN={RATIONAL R_0=0.1 NN=8 MM=12}  STRANDS_CUTOFF=1
      80             : PRINT ARG=hh.lessthan FILE=colvar
      81             : ```
      82             : 
      83             : __YOUR CALCULATION WILL BE MUCH FASTER IF YOU USE THE `STRANDS_CUTOFF` KEYWORD.__  As you can see from the
      84             : expanded version of the inputs above this keyword reduces the computational cost of the calculation by
      85             : avoiding calculations of the RMSD values for segments that have the two strands of the beta sheet further apart
      86             : than a cutoff.
      87             : 
      88             : */
      89             : //+ENDPLUMEDOC
      90             : 
      91             : class AntibetaRMSD : public ActionShortcut {
      92             : public:
      93             :   static void registerKeywords( Keywords& keys );
      94             :   explicit AntibetaRMSD(const ActionOptions&);
      95             : };
      96             : 
      97             : PLUMED_REGISTER_ACTION(AntibetaRMSD,"ANTIBETARMSD")
      98             : 
      99         101 : void AntibetaRMSD::registerKeywords( Keywords& keys ) {
     100         101 :   SecondaryStructureRMSD::registerKeywords( keys );
     101         202 :   keys.setValueDescription("scalar/vector","if LESS_THAN is present the RMSD distance between each residue and the ideal antiparallel beta sheet.  If LESS_THAN is not present the number of residue segments where the structure is similar to an anti parallel beta sheet");
     102         101 :   keys.remove("ATOMS");
     103         101 :   keys.remove("SEGMENT");
     104         101 :   keys.remove("BONDLENGTH");
     105         101 :   keys.remove("NO_ACTION_LOG");
     106         101 :   keys.remove("CUTOFF_ATOMS");
     107         202 :   keys.remove("STRUCTURE");
     108         101 :   keys.add("compulsory","STYLE","all","Antiparallel beta sheets can either form in a single chain or from a pair of chains. If STYLE=all all "
     109             :            "chain configuration with the appropriate geometry are counted.  If STYLE=inter "
     110             :            "only sheet-like configurations involving two chains are counted, while if STYLE=intra "
     111             :            "only sheet-like configurations involving a single chain are counted");
     112         101 : }
     113             : 
     114          17 : AntibetaRMSD::AntibetaRMSD(const ActionOptions&ao):
     115             :   Action(ao),
     116          17 :   ActionShortcut(ao) {
     117             :   // Read in the input and create a string that describes how to compute the less than
     118             :   std::string ltmap;
     119          17 :   bool uselessthan=SecondaryStructureRMSD::readShortcutWords( ltmap, this );
     120             :   // read in the backbone atoms
     121             :   std::vector<unsigned> chains;
     122             :   std::string atoms;
     123          34 :   SecondaryStructureRMSD::readBackboneAtoms( this, plumed, "protein", chains, atoms );
     124             : 
     125             :   bool intra_chain(false), inter_chain(false);
     126             :   std::string style;
     127          17 :   parse("STYLE",style);
     128          34 :   if( Tools::caseInSensStringCompare(style, "all") ) {
     129             :     intra_chain=true;
     130             :     inter_chain=true;
     131           4 :   } else if( Tools::caseInSensStringCompare(style, "inter") ) {
     132             :     intra_chain=false;
     133             :     inter_chain=true;
     134           2 :   } else if( Tools::caseInSensStringCompare(style, "intra") ) {
     135             :     intra_chain=true;
     136             :     inter_chain=false;
     137             :   } else {
     138           0 :     error( style + " is not a valid directive for the STYLE keyword");
     139             :   }
     140             : 
     141             :   // This constructs all conceivable sections of antibeta sheet in the backbone of the chains
     142             :   std::string seglist;
     143          17 :   unsigned k=1;
     144          17 :   if( intra_chain ) {
     145             :     unsigned nprevious=0;
     146          16 :     std::vector<unsigned> nlist(30);
     147         287 :     for(unsigned i=0; i<chains.size(); ++i) {
     148         271 :       if( chains[i]<40 ) {
     149           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");
     150             :       }
     151             :       // Loop over all possible triples in each 8 residue segment of protein
     152         271 :       unsigned nres=chains[i]/5;
     153         271 :       if( chains[i]%5!=0 ) {
     154           0 :         error("backbone segment received does not contain a multiple of five residues");
     155             :       }
     156         546 :       for(unsigned ires=0; ires<nres-7; ires++) {
     157         560 :         for(unsigned jres=ires+7; jres<nres; jres++) {
     158        4560 :           for(unsigned k=0; k<15; ++k) {
     159        4275 :             nlist[k]=nprevious + ires*5+k;
     160        4275 :             nlist[k+15]=nprevious + (jres-2)*5+k;
     161             :           }
     162             :           std::string nlstr, num;
     163         285 :           Tools::convert( nlist[0], nlstr );
     164         285 :           Tools::convert(k, num);
     165         285 :           k++;
     166         570 :           seglist += " SEGMENT" + num + "=" + nlstr;
     167        8550 :           for(unsigned kk=1; kk<nlist.size(); ++kk ) {
     168        8265 :             Tools::convert( nlist[kk], nlstr );
     169       16530 :             seglist += "," + nlstr;
     170             :           }
     171             :         }
     172             :       }
     173         271 :       nprevious+=chains[i];
     174             :     }
     175             :   }
     176          17 :   if( inter_chain ) {
     177          17 :     if( chains.size()==1 && style!="all" ) {
     178           0 :       error("there is only one chain defined so cannot use inter_chain option");
     179             :     }
     180          16 :     std::vector<unsigned> nlist(30);
     181         255 :     for(unsigned ichain=1; ichain<chains.size(); ++ichain) {
     182             :       unsigned iprev=0;
     183        2382 :       for(unsigned i=0; i<ichain; ++i) {
     184        2143 :         iprev+=chains[i];
     185             :       }
     186         239 :       unsigned inres=chains[ichain]/5;
     187         239 :       if( chains[ichain]%5!=0 ) {
     188           0 :         error("backbone segment received does not contain a multiple of five residues");
     189             :       }
     190        1668 :       for(unsigned ires=0; ires<inres-2; ++ires) {
     191       14282 :         for(unsigned jchain=0; jchain<ichain; ++jchain) {
     192             :           unsigned jprev=0;
     193       81397 :           for(unsigned i=0; i<jchain; ++i) {
     194       68544 :             jprev+=chains[i];
     195             :           }
     196       12853 :           unsigned jnres=chains[jchain]/5;
     197       12853 :           if( chains[jchain]%5!=0 ) {
     198           0 :             error("backbone segment received does not contain a multiple of five residues");
     199             :           }
     200       89966 :           for(unsigned jres=0; jres<jnres-2; ++jres) {
     201     1233808 :             for(unsigned k=0; k<15; ++k) {
     202     1156695 :               nlist[k]=iprev+ ires*5+k;
     203     1156695 :               nlist[k+15]=jprev+ jres*5+k;
     204             :             }
     205             :             std::string nlstr, num;
     206       77113 :             Tools::convert( nlist[0], nlstr );
     207       77113 :             Tools::convert(k, num);
     208       77113 :             k++;
     209      154226 :             seglist += " SEGMENT" + num + "=" + nlstr;
     210     2313390 :             for(unsigned kk=1; kk<nlist.size(); ++kk ) {
     211     2236277 :               Tools::convert( nlist[kk], nlstr );
     212     4472554 :               seglist += "," + nlstr;
     213             :             }
     214             :           }
     215             :         }
     216             :       }
     217             :     }
     218             :   }
     219             : 
     220             :   // Build the reference structure ( in angstroms )
     221          17 :   std::vector<Vector> reference(30);
     222          17 :   reference[0]=Vector( 2.263, -3.795,  1.722); // N    i
     223          17 :   reference[1]=Vector( 2.493, -2.426,  2.263); // CA
     224          17 :   reference[2]=Vector( 3.847, -1.838,  1.761); // CB
     225          17 :   reference[3]=Vector( 1.301, -1.517,  1.921); // C
     226          17 :   reference[4]=Vector( 0.852, -1.504,  0.739); // O
     227          17 :   reference[5]=Vector( 0.818, -0.738,  2.917); // N    i+1
     228          17 :   reference[6]=Vector(-0.299,  0.243,  2.748); // CA
     229          17 :   reference[7]=Vector(-1.421, -0.076,  3.757); // CB
     230          17 :   reference[8]=Vector( 0.273,  1.680,  2.854); // C
     231          17 :   reference[9]=Vector( 0.902,  1.993,  3.888); // O
     232          17 :   reference[10]=Vector( 0.119,  2.532,  1.813); // N    i+2
     233          17 :   reference[11]=Vector( 0.683,  3.916,  1.680); // CA
     234          17 :   reference[12]=Vector( 1.580,  3.940,  0.395); // CB
     235          17 :   reference[13]=Vector(-0.394,  5.011,  1.630); // C
     236          17 :   reference[14]=Vector(-1.459,  4.814,  0.982); // O
     237          17 :   reference[15]=Vector(-2.962,  3.559, -1.359); // N    j-2
     238          17 :   reference[16]=Vector(-2.439,  2.526, -2.287); // CA
     239          17 :   reference[17]=Vector(-1.189,  3.006, -3.087); // CB
     240          17 :   reference[18]=Vector(-2.081,  1.231, -1.520); // C
     241          17 :   reference[19]=Vector(-1.524,  1.324, -0.409); // O
     242          17 :   reference[20]=Vector(-2.326,  0.037, -2.095); // N    j-1
     243          17 :   reference[21]=Vector(-1.858, -1.269, -1.554); // CA
     244          17 :   reference[22]=Vector(-3.053, -2.199, -1.291); // CB
     245          17 :   reference[23]=Vector(-0.869, -1.949, -2.512); // C
     246          17 :   reference[24]=Vector(-1.255, -2.070, -3.710); // O
     247          17 :   reference[25]=Vector( 0.326, -2.363, -2.072); // N    j
     248          17 :   reference[26]=Vector( 1.405, -2.992, -2.872); // CA
     249          17 :   reference[27]=Vector( 2.699, -2.129, -2.917); // CB
     250          17 :   reference[28]=Vector( 1.745, -4.399, -2.330); // C
     251          17 :   reference[29]=Vector( 1.899, -4.545, -1.102); // O
     252             :   std::string ref0, ref1, ref2;
     253          17 :   Tools::convert(  reference[0][0], ref0 );
     254          17 :   Tools::convert(  reference[0][1], ref1 );
     255          17 :   Tools::convert(  reference[0][2], ref2 );
     256          34 :   std::string structure=" STRUCTURE1=" + ref0 + "," + ref1 + "," + ref2;
     257         510 :   for(unsigned i=1; i<30; ++i) {
     258        1972 :     for(unsigned k=0; k<3; ++k) {
     259        1479 :       Tools::convert( reference[i][k], ref0 );
     260        2958 :       structure += "," + ref0;
     261             :     }
     262             :   }
     263             : 
     264             :   std::string strands_cutoff;
     265          34 :   parse("STRANDS_CUTOFF",strands_cutoff);
     266          17 :   if( strands_cutoff.length()>0 ) {
     267          32 :     strands_cutoff=" CUTOFF_ATOMS=6,21 STRANDS_CUTOFF="+strands_cutoff;
     268             :   }
     269             :   std::string type;
     270          17 :   parse("TYPE",type);
     271          17 :   std::string lab = getShortcutLabel() + "_rmsd";
     272          17 :   if( uselessthan ) {
     273          17 :     lab = getShortcutLabel();
     274             :   }
     275          17 :   std::string nopbcstr="";
     276             :   bool nopbc;
     277          17 :   parseFlag("NOPBC",nopbc);
     278          17 :   if( nopbc ) {
     279             :     nopbcstr = " NOPBC";
     280             :   }
     281          17 :   if( seglist.length()==0 ) {
     282           0 :     error("no segments to investigate");
     283             :   }
     284          34 :   readInputLine( lab + ": SECONDARY_STRUCTURE_RMSD BONDLENGTH=0.17" + seglist + structure + " " + atoms + " TYPE=" + type + strands_cutoff + nopbcstr );
     285             :   // Create the less than object
     286          17 :   if( ltmap.length()>0 ) {
     287          17 :     SecondaryStructureRMSD::expandShortcut( uselessthan, getShortcutLabel(), lab, ltmap, this );
     288             :   }
     289          17 : }
     290             : 
     291             : }
     292             : }

Generated by: LCOV version 1.16