LCOV - code coverage report
Current view: top level - isdb - CS2Backbone.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 1323 1389 95.2 %
Date: 2020-11-18 11:20:57 Functions: 42 44 95.5 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2013-2019 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             : 
      23             : #define cutOffNB      0.70      // buffer distance for neighbour-lists 
      24             : #define cutOffDist    0.50      // cut off distance for non-bonded pairwise forces
      25             : #define cutOnDist     0.32      // cut off distance for non-bonded pairwise forces
      26             : #define cutOffNB2     cutOffNB*cutOffNB // squared buffer distance for neighbour-lists 
      27             : #define cutOffDist2   cutOffDist*cutOffDist
      28             : #define cutOnDist2    cutOnDist*cutOnDist
      29             : #define invswitch     1.0/((cutOffDist2-cutOnDist2)*(cutOffDist2-cutOnDist2)*(cutOffDist2-cutOnDist2))
      30             : #define cutOffDist4   cutOffDist2*cutOffDist2
      31             : #define cutMixed      cutOffDist2*cutOffDist2*cutOffDist2 -3.*cutOffDist2*cutOffDist2*cutOnDist2
      32             : 
      33             : #include <string>
      34             : #include <fstream>
      35             : #include <iterator>
      36             : #include <sstream>
      37             : 
      38             : #include "MetainferenceBase.h"
      39             : #include "core/ActionRegister.h"
      40             : #include "tools/Pbc.h"
      41             : #include "tools/PDB.h"
      42             : #include "tools/Torsion.h"
      43             : 
      44             : using namespace std;
      45             : 
      46             : namespace PLMD {
      47             : namespace isdb {
      48             : 
      49             : //+PLUMEDOC ISDB_COLVAR CS2BACKBONE
      50             : /*
      51             : Calculates the backbone chemical shifts for a protein.
      52             : 
      53             : The functional form is that of CamShift \cite Kohlhoff:2009us. The chemical shifts
      54             : of the selected nuclei/residues are saved as components. Reference experimental values
      55             : can also be stored as components. The two sets of components can then be used to calculate
      56             : either a scoring function as in \cite Robustelli:2010dn \cite Granata:2013dk, using
      57             : the keyword CAMSHIFT or to calculate ensemble averaged chemical shift as in \cite Camilloni:2012je
      58             : \cite Camilloni:2013hs (see \ref ENSEMBLE, \ref STATS and \ref RESTRAINT). Finally they can
      59             : also be used as input for \ref METAINFERENCE, \cite Bonomi:2016ip . In the current implementation there is
      60             : no need to pass the data to \ref METAINFERENCE because \ref CS2BACKBONE can internally enable Metainference
      61             : using the keywork DOSCORE.
      62             : 
      63             : CamShift calculation is relatively heavy because it often uses a large number of atoms, in order
      64             : to make it faster it is currently parallelised with \ref Openmp.
      65             : 
      66             : As a general rule, when using \ref CS2BACKBONE or other experimental restraints it is better to
      67             : increase the accuracy of the constraint algorithm due to the increased strain on the bonded structure.
      68             : In the case of GROMACS it is safer to use lincs-iter=2 and lincs-order=6.
      69             : 
      70             : In general the system for which chemical shifts are calculated must be completly included in
      71             : ATOMS and a TEMPLATE pdb file for the same atoms should be provided as well in the folder DATADIR.
      72             : The atoms are made automatically whole unless NOPBC is used, in particular if the system is made of
      73             : by multiple chains it is usually better to use NOPBC and make the molecule whole \ref WHOLEMOLECULES
      74             : selecting an appropriate order.
      75             : 
      76             : In addition to a pdb file one needs to provide a list of chemical shifts to be calculated using one
      77             : file per nucleus type (CAshifts.dat, CBshifts.dat, Cshifts.dat, Hshifts.dat, HAshifts.dat, Nshifts.dat),
      78             : all the six files should always be present. A chemical shift for a nucleus is calculated if a value
      79             : greater than 0 is provided. For practical purposes the value can correspond to the experimental value.
      80             : Residues numbers should go from 1 to N irrespectively of the numbers used in the pdb file. The first and
      81             : last residue of each chain should be preceeded by a # character. Termini groups like ACE or NME should
      82             : be removed from the PDB.
      83             : 
      84             : \verbatim
      85             : CAshifts.dat:
      86             : #1 0.0
      87             : 2 55.5
      88             : 3 58.4
      89             : .
      90             : .
      91             : #last 0.0
      92             : #last+1 (first) of second chain
      93             : .
      94             : #last of second chain
      95             : \endverbatim
      96             : 
      97             : The default behaviour is to store the values for the active nuclei in components (ca_#, cb_#,
      98             : co_#, ha_#, hn_#, nh_# and expca_#, expcb_#, expco_#, expha_#, exphn_#, exp_nh#) with NOEXP it is possible
      99             : to only store the backcalculated values.
     100             : 
     101             : A pdb file is needed to the generate a simple topology of the protein. For histidines in protonation
     102             : states different from D the HIE/HSE HIP/HSP name should be used. GLH and ASH can be used for the alternative
     103             : protonation of GLU and ASP. Non-standard amino acids and other molecules are not yet supported, but in principle
     104             : they can be named UNK. If multiple chains are present the chain identifier must be in the standard PDB format,
     105             : together with the TER keyword at the end of each chain.
     106             : 
     107             : One more standard file is also needed in the folder DATADIR: camshift.db. This file includes all the CamShift parameters
     108             : and can be found in regtest/isdb/rt-cs2backbone/data/ .
     109             : 
     110             : All the above files must be in a single folder that must be specified with the keyword DATADIR.
     111             : 
     112             : Additional material and examples can be also found in the tutorial \ref belfast-9
     113             : 
     114             : \par Examples
     115             : 
     116             : In this first example the chemical shifts are used to calculate a scoring function to be used
     117             : in NMR driven Metadynamics \cite Granata:2013dk :
     118             : 
     119             : \plumedfile
     120             : whole: GROUP ATOMS=2612-2514:-1,961-1:-1,2466-962:-1,2513-2467:-1
     121             : WHOLEMOLECULES ENTITY0=whole
     122             : cs: CS2BACKBONE ATOMS=1-2612 NRES=176 DATADIR=../data/ TEMPLATE=template.pdb CAMSHIFT NOPBC
     123             : metad: METAD ARG=cs HEIGHT=0.5 SIGMA=0.1 PACE=200 BIASFACTOR=10
     124             : PRINT ARG=cs,metad.bias FILE=COLVAR STRIDE=100
     125             : \endplumedfile
     126             : 
     127             : In this second example the chemical shifts are used as replica-averaged restrained as in \cite Camilloni:2012je \cite Camilloni:2013hs.
     128             : 
     129             : \plumedfile
     130             : cs: CS2BACKBONE ATOMS=1-174 DATADIR=data/ NRES=13
     131             : encs: ENSEMBLE ARG=(cs\.hn_.*),(cs\.nh_.*)
     132             : stcs: STATS ARG=encs.* SQDEVSUM PARARG=(cs\.exphn_.*),(cs\.expnh_.*)
     133             : RESTRAINT ARG=stcs.sqdevsum AT=0 KAPPA=0 SLOPE=24
     134             : 
     135             : PRINT ARG=(cs\.hn_.*),(cs\.nh_.*) FILE=RESTRAINT STRIDE=100
     136             : 
     137             : \endplumedfile
     138             : 
     139             : This third example show how to use chemical shifts to calculate a \ref METAINFERENCE score .
     140             : 
     141             : \plumedfile
     142             : cs: CS2BACKBONE ATOMS=1-174 DATADIR=data/ NRES=13 DOSCORE NDATA=24
     143             : csbias: BIASVALUE ARG=cs.score
     144             : 
     145             : PRINT ARG=(cs\.hn_.*),(cs\.nh_.*) FILE=CS.dat STRIDE=1000
     146             : PRINT ARG=cs.score FILE=BIAS STRIDE=100
     147             : \endplumedfile
     148             : 
     149             : */
     150             : //+ENDPLUMEDOC
     151             : 
     152             : class CS2BackboneDB {
     153             :   enum { STD, GLY, PRO};
     154             :   enum { HA_ATOM, H_ATOM, N_ATOM, CA_ATOM, CB_ATOM, C_ATOM };
     155             :   static const unsigned aa_kind = 3;
     156             :   static const unsigned atm_kind = 6;
     157             :   static const unsigned numXtraDists = 27;
     158             : 
     159             :   // ALA, ARG, ASN, ASP, CYS, GLU, GLN, GLY, HIS, ILE, LEU, LYS, MET, PHE, PRO, SER, THR, TRP, TYR, VAL
     160             :   double c_aa[aa_kind][atm_kind][20];
     161             :   double c_aa_prev[aa_kind][atm_kind][20];
     162             :   double c_aa_succ[aa_kind][atm_kind][20];
     163             :   double co_bb[aa_kind][atm_kind][16];
     164             :   double co_sc_[aa_kind][atm_kind][20][20];
     165             :   double co_xd[aa_kind][atm_kind][numXtraDists];
     166             :   double co_sphere[aa_kind][atm_kind][2][8];
     167             :   // for ring current effects
     168             :   // Phe, Tyr, Trp_1, Trp_2, His
     169             :   double co_ring[aa_kind][atm_kind][5];
     170             :   // for dihedral angles
     171             :   // co * (a * cos(3 * omega + c) + b * cos(omega + d))
     172             :   double co_da[aa_kind][atm_kind][3];
     173             :   double pars_da[aa_kind][atm_kind][3][5];
     174             : 
     175             : public:
     176             : 
     177        2716 :   inline unsigned kind(const string &s) {
     178        2716 :     if(s=="GLY") return GLY;
     179        2212 :     else if(s=="PRO") return PRO;
     180        2030 :     return STD;
     181             :   }
     182             : 
     183         252 :   inline unsigned atom_kind(const string &s) {
     184         252 :     if(s=="HA")return HA_ATOM;
     185         210 :     else if(s=="H") return H_ATOM;
     186         168 :     else if(s=="N") return N_ATOM;
     187         126 :     else if(s=="CA")return CA_ATOM;
     188          84 :     else if(s=="CB")return CB_ATOM;
     189          42 :     else if(s=="C") return C_ATOM;
     190           0 :     return -1;
     191             :   }
     192             : 
     193             :   unsigned get_numXtraDists() {return numXtraDists;}
     194             : 
     195             :   //PARAMETERS
     196        8246 :   inline double * CONSTAACURR(const unsigned a_kind, const unsigned at_kind) {return c_aa[a_kind][at_kind];}
     197        8246 :   inline double * CONSTAANEXT(const unsigned a_kind, const unsigned at_kind) {return c_aa_succ[a_kind][at_kind];}
     198        8246 :   inline double * CONSTAAPREV(const unsigned a_kind, const unsigned at_kind) {return c_aa_prev[a_kind][at_kind];}
     199        8246 :   inline double * CONST_BB2_PREV(const unsigned a_kind, const unsigned at_kind) {return co_bb[a_kind][at_kind];}
     200             :   inline double * CONST_BB2_CURR(const unsigned a_kind, const unsigned at_kind) {return co_bb[a_kind][at_kind]+5;}
     201             :   inline double * CONST_BB2_NEXT(const unsigned a_kind, const unsigned at_kind) {return co_bb[a_kind][at_kind]+11;}
     202        8246 :   inline double * CONST_SC2(const unsigned a_kind, const unsigned at_kind, unsigned res_type) { return co_sc_[a_kind][at_kind][res_type];}
     203        8246 :   inline double * CONST_XD(const unsigned a_kind, const unsigned at_kind) { return co_xd[a_kind][at_kind];}
     204        8246 :   inline double * CO_SPHERE(const unsigned a_kind, const unsigned at_kind, unsigned exp_type) { return co_sphere[a_kind][at_kind][exp_type];}
     205        8246 :   inline double * CO_RING(const unsigned a_kind, const unsigned at_kind) { return co_ring[a_kind][at_kind];}
     206        8246 :   inline double * CO_DA(const unsigned a_kind, const unsigned at_kind) { return co_da[a_kind][at_kind];}
     207       23072 :   inline double * PARS_DA(const unsigned a_kind, const unsigned at_kind, const unsigned ang_kind) { return pars_da[a_kind][at_kind][ang_kind];}
     208             : 
     209          14 :   void parse(const string &file, const double dscale) {
     210          28 :     ifstream in;
     211          14 :     in.open(file.c_str());
     212          14 :     if(!in) plumed_merror("Unable to open CS2Backbone DB file " +file);
     213             : 
     214             :     unsigned c_kind = 0;
     215             :     unsigned c_atom = 0;
     216             :     unsigned nline = 0;
     217             : 
     218         308 :     for(unsigned i=0; i<3; i++) for(unsigned j=0; j<6; j++) {
     219       10332 :         for(unsigned k=0; k<20; k++) {
     220        5040 :           c_aa[i][j][k]=0.;
     221        5040 :           c_aa_prev[i][j][k]=0.;
     222        5040 :           c_aa_succ[i][j][k]=0.;
     223      105840 :           for(unsigned m=0; m<20; m++) co_sc_[i][j][k][m]=0.;
     224             :         }
     225        4284 :         for(unsigned k=0; k<16; k++) {co_bb[i][j][k]=0.; }
     226        2268 :         for(unsigned k=0; k<8; k++) { co_sphere[i][j][0][k]=0.; co_sphere[i][j][1][k]=0.; }
     227        1764 :         for(unsigned k=0; k<3; k++) {
     228         756 :           co_da[i][j][k]=0.;
     229        4536 :           for(unsigned l=0; l<5; l++) pars_da[i][j][k][l]=0.;
     230             :         }
     231        1512 :         for(unsigned k=0; k<5; k++) co_ring[i][j][k]=0.;
     232        7056 :         for(unsigned k=0; k<numXtraDists; k++) co_xd[i][j][k]=0.;
     233             :       }
     234             : 
     235       29330 :     while(!in.eof()) {
     236             :       string line;
     237       29316 :       getline(in,line);
     238             :       ++nline;
     239       29316 :       if(line.compare(0,1,"#")==0) continue;
     240           0 :       vector<string> tok;
     241           0 :       vector<string> tmp;
     242       31780 :       tok = split(line,' ');
     243      595042 :       for(unsigned q=0; q<tok.size(); q++)
     244      187754 :         if(tok[q].size()) tmp.push_back(tok[q]);
     245       15890 :       tok = tmp;
     246       31780 :       if(tok.size()==0) continue;
     247       16128 :       if(tok[0]=="PAR") {
     248         252 :         c_kind = kind(tok[2]);
     249         252 :         c_atom = atom_kind(tok[1]);
     250         252 :         continue;
     251             :       }
     252       15624 :       else if(tok[0]=="WEIGHT") {
     253         252 :         continue;
     254             :       }
     255       15372 :       else if(tok[0]=="FLATBTM") {
     256         252 :         continue;
     257             :       }
     258       15120 :       else if (tok[0] == "SCALEHARM") {
     259         252 :         continue;
     260             :       }
     261       14868 :       else if (tok[0] == "TANHAMPLI") {
     262         252 :         continue;
     263             :       }
     264       14616 :       else if (tok[0] == "ENDHARMON") {
     265         252 :         continue;
     266             :       }
     267       14364 :       else if (tok[0] == "MAXRCDEVI") {
     268         252 :         continue;
     269             :       }
     270       14112 :       else if (tok[0] == "RANDCOIL") {
     271         252 :         continue;
     272             :       }
     273       13860 :       else if (tok[0] == "CONST") {
     274         252 :         continue;
     275             :       }
     276       13860 :       else if (tok[0] == "CONSTAA") {
     277         252 :         assign(c_aa[c_kind][c_atom],tok,1);
     278         252 :         continue;
     279             :       }
     280       13608 :       else if (tok[0] == "CONSTAA-1") {
     281         252 :         assign(c_aa_prev[c_kind][c_atom],tok,1);
     282         252 :         continue;
     283             :       }
     284       13356 :       else if (tok[0] == "CONSTAA+1") {
     285         252 :         assign(c_aa_succ[c_kind][c_atom],tok,1);
     286         252 :         continue;
     287             :       }
     288       12852 :       else if (tok[0] == "COBB1") {
     289         252 :         continue;
     290             :       }
     291       12852 :       else if (tok[0] == "COBB2") {
     292             :         //angstrom to nm
     293         252 :         assign(co_bb[c_kind][c_atom],tok,dscale);
     294         252 :         continue;
     295             :       }
     296       12600 :       else if (tok[0] == "SPHERE1") {
     297             :         // angstrom^-3 to nm^-3
     298         252 :         assign(co_sphere[c_kind][c_atom][0],tok,1./(dscale*dscale*dscale));
     299         252 :         continue;
     300             :       }
     301       12348 :       else if (tok[0] == "SPHERE2") {
     302             :         //angstrom to nm
     303         252 :         assign(co_sphere[c_kind][c_atom][1],tok,dscale);
     304         252 :         continue;
     305             :       }
     306       12096 :       else if (tok[0] == "DIHEDRALS") {
     307         252 :         assign(co_da[c_kind][c_atom],tok,1);
     308         252 :         continue;
     309             :       }
     310       11592 :       else if (tok[0] == "RINGS") {
     311             :         // angstrom^-3 to nm^-3
     312         252 :         assign(co_ring[c_kind][c_atom],tok,1./(dscale*dscale*dscale));
     313        4284 :         for(unsigned i=1; i<tok.size(); i++)
     314        1260 :           co_ring[c_kind][c_atom][i-1] *= 1000;
     315         252 :         continue;
     316             :       }
     317       11340 :       else if (tok[0] == "HBONDS") {
     318         252 :         continue;
     319             :       }
     320       11340 :       else if (tok[0] == "XTRADISTS") {
     321             :         //angstrom to nm
     322         252 :         assign(co_xd[c_kind][c_atom],tok,dscale);
     323         252 :         continue;
     324             :       }
     325       11088 :       else if(tok[0]=="DIHEDPHI") {
     326         252 :         assign(pars_da[c_kind][c_atom][0],tok,1);
     327         252 :         continue;
     328             :       }
     329       10836 :       else if(tok[0]=="DIHEDPSI") {
     330         252 :         assign(pars_da[c_kind][c_atom][1],tok,1);
     331         252 :         continue;
     332             :       }
     333       10584 :       else if(tok[0]=="DIHEDCHI1") {
     334         252 :         assign(pars_da[c_kind][c_atom][2],tok,1);
     335         252 :         continue;
     336             :       }
     337             : 
     338             :       bool ok = false;
     339             :       string scIdent1 [] = {"COSCALA1", "COSCARG1", "COSCASN1", "COSCASP1", "COSCCYS1", "COSCGLN1", "COSCGLU1",
     340             :                             "COSCGLY1", "COSCHIS1", "COSCILE1", "COSCLEU1", "COSCLYS1", "COSCMET1", "COSCPHE1",
     341             :                             "COSCPRO1", "COSCSER1", "COSCTHR1", "COSCTRP1", "COSCTYR1", "COSCVAL1"
     342       10080 :                            };
     343             : 
     344      307440 :       for(unsigned scC = 0; scC < 20; scC++) {
     345      307440 :         if(tok[0]==scIdent1[scC]) {
     346             :           ok = true;
     347             :           break;
     348             :         }
     349             :       }
     350      221760 :       if(ok) continue;
     351             : 
     352             :       string scIdent2 [] = {"COSCALA2", "COSCARG2", "COSCASN2", "COSCASP2", "COSCCYS2", "COSCGLN2", "COSCGLU2",
     353             :                             "COSCGLY2", "COSCHIS2", "COSCILE2", "COSCLEU2", "COSCLYS2", "COSCMET2", "COSCPHE2",
     354             :                             "COSCPRO2", "COSCSER2", "COSCTHR2", "COSCTRP2", "COSCTYR2", "COSCVAL2"
     355        5040 :                            };
     356             : 
     357      100800 :       for(unsigned scC = 0; scC < 20; scC++) {
     358      105840 :         if(tok[0]==scIdent2[scC]) {
     359             :           //angstrom to nm
     360        5040 :           assign(co_sc_[c_kind][c_atom][scC],tok,dscale);
     361             :           ok = true; break;
     362             :         }
     363             :       }
     364      110880 :       if(ok) continue;
     365             : 
     366           0 :       if(tok.size()) {
     367           0 :         string str_err = "CS2Backbone DB WARNING: unrecognized token: " + tok[0];
     368           0 :         plumed_merror(str_err);
     369             :       }
     370             :     }
     371          14 :     in.close();
     372          14 :   }
     373             : 
     374             : private:
     375             : 
     376       15890 :   vector<string> &split(const string &s, char delim, vector<string> &elems) {
     377       31780 :     stringstream ss(s);
     378             :     string item;
     379      407288 :     while (getline(ss, item, delim)) {
     380      187754 :       elems.push_back(item);
     381             :     }
     382       15890 :     return elems;
     383             :   }
     384             : 
     385       15890 :   vector<string> split(const string &s, char delim) {
     386             :     vector<string> elems;
     387       15890 :     split(s, delim, elems);
     388       15890 :     return elems;
     389             :   }
     390             : 
     391        8064 :   void assign(double * f, const vector<string> & v, const double scale) {
     392      278460 :     for(unsigned i=1; i<v.size(); i++) {
     393       87444 :       f[i-1] = scale*(atof(v[i].c_str()));
     394       87444 :       if(fabs(f[i-1])<0.000001) f[i-1]=0.;
     395             :     }
     396        8064 :   }
     397             : };
     398             : 
     399          42 : class CS2Backbone : public MetainferenceBase {
     400       47320 :   struct Fragment {
     401             :     vector<Value*> comp;
     402             :     vector<double> exp_cs;
     403             :     unsigned res_type_prev;
     404             :     unsigned res_type_curr;
     405             :     unsigned res_type_next;
     406             :     unsigned res_kind;
     407             :     unsigned fd;
     408             :     string res_name;
     409             :     vector<int> pos;
     410             :     vector<int> prev;
     411             :     vector<int> curr;
     412             :     vector<int> next;
     413             :     vector<int> side_chain;
     414             :     vector<int> xd1;
     415             :     vector<int> xd2;
     416             :     vector<unsigned> box_nb;
     417             :     vector<int> phi;
     418             :     vector<int> psi;
     419             :     vector<int> chi1;
     420             :     double t_phi;
     421             :     double t_psi;
     422             :     double t_chi1;
     423             :     vector<Vector> dd0, dd10, dd21, dd2;
     424             : 
     425       44352 :     Fragment() {
     426        2464 :       comp.resize(6);
     427        2464 :       exp_cs.resize(6,0);
     428        2464 :       res_type_prev = res_type_curr = res_type_next = 0;
     429        2464 :       res_kind = 0;
     430        2464 :       fd = 0;
     431             :       res_name = "";
     432        2464 :       pos.resize(6,-1);
     433        2464 :       prev.reserve(5);
     434        2464 :       curr.reserve(6);
     435        2464 :       next.reserve(5);
     436        2464 :       side_chain.reserve(20);
     437        2464 :       xd1.reserve(27);
     438        2464 :       xd2.reserve(27);
     439        2464 :       box_nb.reserve(250);
     440        2464 :       phi.reserve(4);
     441        2464 :       psi.reserve(4);
     442        2464 :       chi1.reserve(4);
     443        2464 :       t_phi = t_psi = t_chi1 = 0;
     444        2464 :       dd0.resize(3);
     445        2464 :       dd10.resize(3);
     446        2464 :       dd21.resize(3);
     447        2464 :       dd2.resize(3);
     448        2464 :     }
     449             : 
     450             :   };
     451             : 
     452             :   struct RingInfo {
     453             :     enum {R_PHE, R_TYR, R_TRP1, R_TRP2, R_HIS};
     454             :     unsigned rtype;    // one out of five different types
     455             :     unsigned atom[6];  // up to six member per ring
     456             :     unsigned numAtoms; // number of ring members (5 or 6)
     457             :     Vector position;   // center of ring coordinates
     458             :     Vector normVect;   // ring plane normal vector
     459             :     Vector n1, n2;     // two atom plane normal vectors used to compute ring plane normal
     460             :     Vector g[6];       // vector of the vectors used to calculate n1,n2
     461             :     double lengthN2;   // square of length of normVect
     462             :     double lengthNV;   // length of normVect
     463         280 :     RingInfo():
     464             :       rtype(0),numAtoms(0),
     465         280 :       lengthN2(NAN),lengthNV(NAN)
     466        1960 :     {for(unsigned i=0; i<6; i++) atom[i]=0;}
     467             :   };
     468             : 
     469             :   enum aa_t {ALA, ARG, ASN, ASP, CYS, GLN, GLU, GLY, HIS, ILE, LEU, LYS, MET, PHE, PRO, SER, THR, TRP, TYR, VAL, UNK};
     470             :   enum atom_t {D_C, D_H, D_N, D_O, D_S, D_C2, D_N2, D_O2};
     471             : 
     472             :   CS2BackboneDB    db;
     473             :   vector<vector<Fragment> > atom;
     474             :   vector<vector<vector<unsigned> > > index_cs;
     475             :   vector<RingInfo> ringInfo;
     476             :   vector<unsigned> seg_last;
     477             :   vector<unsigned> type;
     478             :   vector<unsigned> res_num;
     479             :   unsigned         box_nupdate;
     480             :   unsigned         box_count;
     481             :   bool             camshift;
     482             :   bool             pbc;
     483             : 
     484             :   void remove_problematic(const string &res, const string &nucl);
     485             :   void read_cs(const string &file, const string &k);
     486             :   void update_neighb();
     487             :   void compute_ring_parameters();
     488             :   void compute_dihedrals();
     489             :   void init_backbone(const PDB &pdb);
     490             :   void init_sidechain(const PDB &pdb);
     491             :   void init_xdist(const PDB &pdb);
     492             :   void init_types(const PDB &pdb);
     493             :   void init_rings(const PDB &pdb);
     494             :   aa_t frag2enum(const string &aa);
     495             :   vector<string> side_chain_atoms(const string &s);
     496             :   bool isSP2(const string & resType, const string & atomName);
     497             :   bool is_chi1_cx(const string & frg, const string & atm);
     498             :   unsigned frag_segment(const unsigned p);
     499             :   unsigned frag_relitive_index(const unsigned p, const unsigned s);
     500             :   void debug_report();
     501             :   void xdist_name_map(string & name);
     502             : 
     503             : public:
     504             : 
     505             :   explicit CS2Backbone(const ActionOptions&);
     506             :   static void registerKeywords( Keywords& keys );
     507             :   void calculate();
     508             :   void update();
     509             : };
     510             : 
     511        6466 : PLUMED_REGISTER_ACTION(CS2Backbone,"CS2BACKBONE")
     512             : 
     513          15 : void CS2Backbone::registerKeywords( Keywords& keys ) {
     514          15 :   componentsAreNotOptional(keys);
     515          15 :   useCustomisableComponents(keys);
     516          15 :   MetainferenceBase::registerKeywords( keys );
     517          45 :   keys.addFlag("NOPBC",false,"ignore the periodic boundary conditions when calculating distances");
     518          60 :   keys.add("atoms","ATOMS","The atoms to be included in the calculation, e.g. the whole protein.");
     519          75 :   keys.add("compulsory","DATADIR","data/","The folder with the experimental chemical shifts.");
     520          75 :   keys.add("compulsory","TEMPLATE","template.pdb","A PDB file of the protein system to initialise ALMOST.");
     521          75 :   keys.add("compulsory","NEIGH_FREQ","20","Period in step for neighbour list update.");
     522          60 :   keys.add("compulsory","NRES","Number of residues, corresponding to the number of chemical shifts.");
     523          45 :   keys.addFlag("CAMSHIFT",false,"Set to TRUE if you to calculate a single CamShift score.");
     524          45 :   keys.addFlag("NOEXP",false,"Set to TRUE if you don't want to have fixed components with the experimetnal values.");
     525          60 :   keys.addOutputComponent("ha","default","the calculated Ha hydrogen chemical shifts");
     526          60 :   keys.addOutputComponent("hn","default","the calculated H hydrogen chemical shifts");
     527          60 :   keys.addOutputComponent("nh","default","the calculated N nitrogen chemical shifts");
     528          60 :   keys.addOutputComponent("ca","default","the calculated Ca carbon chemical shifts");
     529          60 :   keys.addOutputComponent("cb","default","the calculated Cb carbon chemical shifts");
     530          60 :   keys.addOutputComponent("co","default","the calculated C' carbon chemical shifts");
     531          60 :   keys.addOutputComponent("expha","default","the experimental Ha hydrogen chemical shifts");
     532          60 :   keys.addOutputComponent("exphn","default","the experimental H hydrogen chemical shifts");
     533          60 :   keys.addOutputComponent("expnh","default","the experimental N nitrogen chemical shifts");
     534          60 :   keys.addOutputComponent("expca","default","the experimental Ca carbon chemical shifts");
     535          60 :   keys.addOutputComponent("expcb","default","the experimental Cb carbon chemical shifts");
     536          60 :   keys.addOutputComponent("expco","default","the experimental C' carbon chemical shifts");
     537          15 : }
     538             : 
     539          14 : CS2Backbone::CS2Backbone(const ActionOptions&ao):
     540             :   PLUMED_METAINF_INIT(ao),
     541             :   camshift(false),
     542          42 :   pbc(true)
     543             : {
     544             :   string stringadb;
     545             :   string stringapdb;
     546             : 
     547          28 :   parseFlag("CAMSHIFT",camshift);
     548          15 :   if(camshift&&getDoScore()) error("It is not possible to use CAMSHIFT together with DOSCORE");
     549             : 
     550          14 :   bool nopbc=!pbc;
     551          28 :   parseFlag("NOPBC",nopbc);
     552          14 :   pbc=!nopbc;
     553             : 
     554          14 :   bool noexp=false;
     555          28 :   parseFlag("NOEXP",noexp);
     556             : 
     557             :   string stringa_data;
     558          28 :   parse("DATADIR",stringa_data);
     559             : 
     560             :   string stringa_template;
     561          28 :   parse("TEMPLATE",stringa_template);
     562             : 
     563          14 :   box_count=0;
     564          14 :   box_nupdate=20;
     565          28 :   parse("NEIGH_FREQ", box_nupdate);
     566             : 
     567             :   unsigned numResidues;
     568          28 :   parse("NRES", numResidues);
     569             : 
     570          42 :   stringadb  = stringa_data + string("/camshift.db");
     571          56 :   stringapdb = stringa_data + string("/") + stringa_template;
     572             : 
     573             :   /* Lenght conversion (parameters are tuned for angstrom) */
     574             :   double scale=1.;
     575          14 :   if(!plumed.getAtoms().usingNaturalUnits()) {
     576          14 :     scale = 10.*atoms.getUnits().getLength();
     577             :   }
     578             : 
     579          14 :   log.printf("  Initialization of the predictor ...\n"); log.flush();
     580          14 :   db.parse(stringadb,scale);
     581          28 :   PDB pdb;
     582          28 :   if( !pdb.read(stringapdb,plumed.getAtoms().usingNaturalUnits(),1./scale) ) error("missing input file " + stringapdb);
     583          14 :   init_backbone(pdb);
     584          14 :   init_sidechain(pdb);
     585          14 :   init_xdist(pdb);
     586          14 :   init_types(pdb);
     587          14 :   init_rings(pdb);
     588             : #ifndef NDEBUG
     589             :   debug_report();
     590             : #endif
     591          14 :   log.printf("  Reading experimental data ...\n"); log.flush();
     592          42 :   stringadb = stringa_data + string("/CAshifts.dat");
     593          28 :   log.printf("  Initializing CA shifts %s\n", stringadb.c_str()); log.flush();
     594          28 :   read_cs(stringadb, "CA");
     595          42 :   stringadb = stringa_data + string("/CBshifts.dat");
     596          28 :   log.printf("  Initializing CB shifts %s\n", stringadb.c_str()); log.flush();
     597          28 :   read_cs(stringadb, "CB");
     598          42 :   stringadb = stringa_data + string("/Cshifts.dat");
     599          28 :   log.printf("  Initializing C' shifts %s\n", stringadb.c_str()); log.flush();
     600          28 :   read_cs(stringadb, "C");
     601          42 :   stringadb = stringa_data + string("/HAshifts.dat");
     602          28 :   log.printf("  Initializing HA shifts %s\n", stringadb.c_str()); log.flush();
     603          28 :   read_cs(stringadb, "HA");
     604          42 :   stringadb = stringa_data + string("/Hshifts.dat");
     605          28 :   log.printf("  Initializing H shifts %s\n", stringadb.c_str()); log.flush();
     606          28 :   read_cs(stringadb, "H");
     607          42 :   stringadb = stringa_data + string("/Nshifts.dat");
     608          28 :   log.printf("  Initializing N shifts %s\n", stringadb.c_str()); log.flush();
     609          28 :   read_cs(stringadb, "N");
     610             : 
     611             :   /* this is a workaround for those chemical shifts that can result in too large forces */
     612          42 :   remove_problematic("GLN", "CB");
     613          42 :   remove_problematic("ILE", "CB");
     614          42 :   remove_problematic("PRO", "N");
     615          42 :   remove_problematic("PRO", "H");
     616          42 :   remove_problematic("PRO", "CB");
     617          42 :   remove_problematic("GLY", "HA");
     618          42 :   remove_problematic("GLY", "CB");
     619             :   /* this is a workaround for those chemical shifts that are not parameterized */
     620          98 :   remove_problematic("HIE", "HA"); remove_problematic("HIP", "HA"); remove_problematic("HSP", "HA");
     621          98 :   remove_problematic("HIE", "H");  remove_problematic("HIP", "H");  remove_problematic("HSP", "H");
     622          98 :   remove_problematic("HIE", "N");  remove_problematic("HIP", "N");  remove_problematic("HSP", "N");
     623          98 :   remove_problematic("HIE", "CA"); remove_problematic("HIP", "CA"); remove_problematic("HSP", "CA");
     624          98 :   remove_problematic("HIE", "CB"); remove_problematic("HIP", "CB"); remove_problematic("HSP", "CB");
     625          98 :   remove_problematic("HIE", "C");  remove_problematic("HIP", "C");  remove_problematic("HSP", "C");
     626          98 :   remove_problematic("GLH", "HA"); remove_problematic("ASH", "HA"); remove_problematic("HSE", "HA");
     627          98 :   remove_problematic("GLH", "H");  remove_problematic("ASH", "H");  remove_problematic("HSE", "H");
     628          98 :   remove_problematic("GLH", "N");  remove_problematic("ASH", "N");  remove_problematic("HSE", "N");
     629          98 :   remove_problematic("GLH", "CA"); remove_problematic("ASH", "CA"); remove_problematic("HSE", "CA");
     630          98 :   remove_problematic("GLH", "CB"); remove_problematic("ASH", "CB"); remove_problematic("HSE", "CB");
     631          98 :   remove_problematic("GLH", "C");  remove_problematic("ASH", "C");  remove_problematic("HSE", "C");
     632          42 :   remove_problematic("UNK", "HA");
     633          42 :   remove_problematic("UNK", "H");
     634          42 :   remove_problematic("UNK", "N");
     635          42 :   remove_problematic("UNK", "CA");
     636          42 :   remove_problematic("UNK", "CB");
     637          42 :   remove_problematic("UNK", "C");
     638          42 :   remove_problematic("CYS", "HA");
     639          42 :   remove_problematic("CYS", "H");
     640          42 :   remove_problematic("CYS", "N");
     641          42 :   remove_problematic("CYS", "CA");
     642          42 :   remove_problematic("CYS", "CB");
     643          42 :   remove_problematic("CYS", "C");
     644          42 :   remove_problematic("HIS", "HA");
     645          42 :   remove_problematic("HIS", "H");
     646          42 :   remove_problematic("HIS", "N");
     647          42 :   remove_problematic("HIS", "CA");
     648          42 :   remove_problematic("HIS", "CB");
     649          42 :   remove_problematic("HIS", "C");
     650             :   /* done */
     651             : 
     652             :   vector<AtomNumber> atoms;
     653          28 :   parseAtomList("ATOMS",atoms);
     654             : 
     655          14 :   log<<"  Bibliography "
     656          42 :      <<plumed.cite("Kohlhoff K, Robustelli P, Cavalli A, Salvatella A, Vendruscolo M, J. Am. Chem. Soc. 131, 13894 (2009)");
     657          16 :   if(camshift) log<<plumed.cite("Granata D, Camilloni C, Vendruscolo M, Laio A, Proc. Natl. Acad. Sci. USA 110, 6817 (2013)");
     658          39 :   else log<<plumed.cite("Camilloni C, Robustelli P, De Simone A, Cavalli A, Vendruscolo M, J. Am. Chem. Soc. 134, 3968 (2012)");
     659          42 :   log<<plumed.cite("Bonomi M, Camilloni C, Bioinformatics, 33, 3999 (2017)");
     660          14 :   log<<"\n";
     661             : 
     662         112 :   const string str_cs[] = {"ha_","hn_","nh_","ca_","cb_","co_"};
     663             :   unsigned index=0;
     664          14 :   if(camshift) {
     665           1 :     noexp = true;
     666           1 :     addValueWithDerivatives();
     667           1 :     setNotPeriodic();
     668             :   } else {
     669          13 :     if(getDoScore()) {
     670           4 :       index_cs.resize(atom.size(), vector<vector<unsigned> >());
     671          20 :       for(unsigned i=0; i<atom.size(); i++) {
     672          24 :         index_cs[i].resize(atom[i].size(), vector<unsigned>(6));
     673             :       }
     674             :     }
     675             :     unsigned l=0;
     676         104 :     for(unsigned i=0; i<atom.size(); i++) {
     677        6916 :       for(unsigned a=0; a<atom[i].size(); a++) {
     678        2288 :         unsigned res=index+a;
     679        2288 :         std::string num; Tools::convert(res,num);
     680       29744 :         for(unsigned at_kind=0; at_kind<6; at_kind++) {
     681       27456 :           if(atom[i][a].exp_cs[at_kind]!=0) {
     682        7657 :             if(getDoScore()) {
     683        4712 :               addComponent(str_cs[at_kind]+num);
     684        4712 :               componentIsNotPeriodic(str_cs[at_kind]+num);
     685        7068 :               atom[i][a].comp[at_kind] = getPntrToComponent(str_cs[at_kind]+num);
     686        2356 :               index_cs[i][a][at_kind]=l;
     687        2356 :               setParameter(atom[i][a].exp_cs[at_kind]);
     688        2356 :               l++;
     689             :             } else {
     690       10602 :               addComponentWithDerivatives(str_cs[at_kind]+num);
     691       10602 :               componentIsNotPeriodic(str_cs[at_kind]+num);
     692       15903 :               atom[i][a].comp[at_kind] = getPntrToComponent(str_cs[at_kind]+num);
     693             :             }
     694             :           }
     695             :         }
     696             :       }
     697          26 :       index += atom[i].size();
     698             :     }
     699          13 :     if(getDoScore()) Initialise(l);
     700             :   }
     701             : 
     702          14 :   if(!noexp) {
     703             :     index = 0;
     704         104 :     for(unsigned i=0; i<atom.size(); i++) {
     705        6916 :       for(unsigned a=0; a<atom[i].size(); a++) {
     706        2288 :         unsigned res=index+a;
     707        2288 :         std::string num; Tools::convert(res,num);
     708       29744 :         for(unsigned at_kind=0; at_kind<6; at_kind++) {
     709       27456 :           if(atom[i][a].exp_cs[at_kind]!=0) {
     710       22971 :             addComponent("exp"+str_cs[at_kind]+num);
     711       22971 :             componentIsNotPeriodic("exp"+str_cs[at_kind]+num);
     712       22971 :             Value* comp=getPntrToComponent("exp"+str_cs[at_kind]+num);
     713        7657 :             comp->set(atom[i][a].exp_cs[at_kind]);
     714             :           }
     715             :         }
     716             :       }
     717          26 :       index += atom[i].size();
     718             :     }
     719             :   }
     720             : 
     721             :   /* temporary check, the idea is that I can remove NRES completely */
     722             :   index=0;
     723         112 :   for(unsigned i=0; i<atom.size(); i++) {
     724          28 :     index += atom[i].size();
     725             :   }
     726          14 :   if(index!=numResidues) error("NRES and the number of residues in the PDB do not match!");
     727             : 
     728          14 :   requestAtoms(atoms);
     729          14 :   setDerivatives();
     730          14 :   checkRead();
     731          14 : }
     732             : 
     733         854 : void CS2Backbone::remove_problematic(const string &res, const string &nucl) {
     734             :   unsigned n;
     735         854 :   if(nucl=="HA")     n=0;
     736         714 :   else if(nucl=="H") n=1;
     737         574 :   else if(nucl=="N") n=2;
     738         434 :   else if(nucl=="CA")n=3;
     739         308 :   else if(nucl=="CB")n=4;
     740         126 :   else if(nucl=="C") n=5;
     741             :   else return;
     742             : 
     743        6832 :   for(unsigned i=0; i<atom.size(); i++) {
     744      454328 :     for(unsigned a=0; a<atom[i].size(); a++) {
     745      150304 :       if(atom[i][a].res_name.c_str()==res) {
     746        3304 :         atom[i][a].exp_cs[n] = 0;
     747             :       }
     748             :     }
     749             :   }
     750             : }
     751             : 
     752          84 : void CS2Backbone::read_cs(const string &file, const string &nucl) {
     753         168 :   ifstream in;
     754          84 :   in.open(file.c_str());
     755          84 :   if(!in) error("CS2Backbone: Unable to open " + file);
     756          84 :   istream_iterator<string> iter(in), end;
     757             : 
     758             :   unsigned n;
     759          84 :   if(nucl=="HA")     n=0;
     760          70 :   else if(nucl=="H") n=1;
     761          56 :   else if(nucl=="N") n=2;
     762          42 :   else if(nucl=="CA")n=3;
     763          28 :   else if(nucl=="CB")n=4;
     764          14 :   else if(nucl=="C") n=5;
     765             :   else return;
     766             : 
     767             :   int oldseg = -1;
     768             :   int oldp = -1;
     769             :   while(iter!=end) {
     770             :     string tok;
     771             :     tok = *iter; ++iter;
     772       15120 :     if(tok[0]=='#') { ++iter; continue;}
     773             :     int p = atoi(tok.c_str());
     774       14448 :     p = p - 1;
     775       14448 :     const int seg = frag_segment(p);
     776       14448 :     p = frag_relitive_index(p,seg);
     777       14448 :     if(oldp==-1) oldp=p;
     778       14448 :     if(oldseg==-1) oldseg=seg;
     779       14448 :     if(p<oldp&&seg==oldseg) {
     780           0 :       string errmsg = "Error while reading " + file + "! The same residue number has been used twice!";
     781           0 :       error(errmsg);
     782             :     }
     783             :     tok = *iter; ++iter;
     784             :     double cs = atof(tok.c_str());
     785       28896 :     if(atom[seg][p].pos[n]<=0) cs=0;
     786       14042 :     else atom[seg][p].exp_cs[n] = cs;
     787             :     oldseg = seg;
     788             :     oldp = p;
     789             :   }
     790          84 :   in.close();
     791             : }
     792             : 
     793          14 : void CS2Backbone::calculate()
     794             : {
     795          14 :   if(pbc) makeWhole();
     796          14 :   if(getExchangeStep()) box_count=0;
     797          14 :   if(box_count==0) update_neighb();
     798             : 
     799          14 :   compute_ring_parameters();
     800          14 :   compute_dihedrals();
     801             : 
     802          14 :   double score = 0.;
     803             : 
     804          14 :   vector<double> camshift_sigma2(6);
     805          14 :   camshift_sigma2[0] = 0.08; // HA
     806          14 :   camshift_sigma2[1] = 0.30; // HN
     807          14 :   camshift_sigma2[2] = 9.00; // NH
     808          14 :   camshift_sigma2[3] = 1.30; // CA
     809          14 :   camshift_sigma2[4] = 1.56; // CB
     810          14 :   camshift_sigma2[5] = 1.70; // CO
     811             : 
     812          14 :   const unsigned chainsize = atom.size();
     813          14 :   const unsigned atleastned = 72+ringInfo.size()*6;
     814             : 
     815          14 :   vector<vector<unsigned> > all_list;
     816          14 :   vector<vector<Vector> > all_ff;
     817          14 :   if(getDoScore()) {
     818           8 :     all_list.resize(getNarg(), vector<unsigned>());
     819           8 :     all_ff.resize(getNarg(), vector<Vector>());
     820             :   }
     821             : 
     822             :   // CYCLE OVER MULTIPLE CHAINS
     823          42 :   #pragma omp parallel num_threads(OpenMP::getNumThreads())
     824         140 :   for(unsigned s=0; s<chainsize; s++) {
     825         112 :     const unsigned psize = atom[s].size();
     826             :     vector<Vector> omp_deriv;
     827          60 :     if(camshift) omp_deriv.resize(getNumberOfAtoms(), Vector(0,0,0));
     828          56 :     #pragma omp for reduction(+:score)
     829             :     // SKIP FIRST AND LAST RESIDUE OF EACH CHAIN
     830          56 :     for(unsigned a=1; a<psize-1; a++) {
     831             : 
     832        2408 :       const Fragment *myfrag = &atom[s][a];
     833        2408 :       const unsigned aa_kind = myfrag->res_kind;
     834        2408 :       const unsigned needed_atoms = atleastned+myfrag->box_nb.size();
     835             : 
     836             :       /* Extra Distances are the same for each residue */
     837        2408 :       const unsigned xdsize=myfrag->xd1.size();
     838        2408 :       vector<Vector> ext_distances(xdsize);
     839        2408 :       vector<double> ext_d(xdsize);
     840      127624 :       for(unsigned q=0; q<xdsize; q++) {
     841      190260 :         if(myfrag->xd1[q]==-1||myfrag->xd2[q]==-1) continue;
     842       56056 :         const Vector distance = delta(getPosition(myfrag->xd1[q]),getPosition(myfrag->xd2[q]));
     843       56056 :         ext_d[q] = distance.modulo();
     844      112112 :         ext_distances[q] = distance/ext_d[q];
     845             :       }
     846             : 
     847             :       // CYCLE OVER THE SIX BACKBONE CHEMICAL SHIFTS
     848       31304 :       for(unsigned at_kind=0; at_kind<6; at_kind++) {
     849       28896 :         if(atom[s][a].exp_cs[at_kind]!=0) {
     850             :           // Common constant and AATYPE
     851             :           const double * CONSTAACURR = db.CONSTAACURR(aa_kind,at_kind);
     852             :           const double * CONSTAANEXT = db.CONSTAANEXT(aa_kind,at_kind);
     853             :           const double * CONSTAAPREV = db.CONSTAAPREV(aa_kind,at_kind);
     854             : 
     855       24738 :           double cs = CONSTAACURR[myfrag->res_type_curr] +
     856        8246 :                       CONSTAANEXT[myfrag->res_type_next] +
     857        8246 :                       CONSTAAPREV[myfrag->res_type_prev];
     858             :           // this is the atom for which we are calculating the chemical shift
     859        8246 :           const unsigned ipos = myfrag->pos[at_kind];
     860             : 
     861             :           vector<unsigned> list;
     862        8246 :           list.reserve(needed_atoms);
     863        8246 :           list.push_back(ipos);
     864             :           vector<Vector> ff;
     865        8246 :           ff.reserve(needed_atoms);
     866        8246 :           ff.push_back(Vector(0,0,0));
     867             : 
     868             : 
     869             :           //PREV
     870             :           const double * CONST_BB2_PREV = db.CONST_BB2_PREV(aa_kind,at_kind);
     871        8246 :           const unsigned presize = myfrag->prev.size();
     872       90706 :           for(unsigned q=0; q<presize; q++) {
     873       41230 :             const double cb2pq = CONST_BB2_PREV[q];
     874       47782 :             if(cb2pq==0.) continue;
     875       34678 :             const unsigned jpos = myfrag->prev[q];
     876       34678 :             list.push_back(jpos);
     877      104034 :             const Vector distance = delta(getPosition(jpos),getPosition(ipos));
     878       34678 :             const double d = distance.modulo();
     879       34678 :             const double fact = cb2pq/d;
     880             : 
     881       34678 :             cs += cb2pq*d;
     882       34678 :             const Vector der = fact*distance;
     883       34678 :             ff[0] += der;
     884       69356 :             ff.push_back(-der);
     885             :           }
     886             : 
     887             :           //CURR
     888             :           const double * CONST_BB2_CURR = db.CONST_BB2_CURR(aa_kind,at_kind);
     889        8246 :           const unsigned cursize = myfrag->curr.size();
     890      107198 :           for(unsigned q=0; q<cursize; q++) {
     891       49476 :             const double cb2cq = CONST_BB2_CURR[q];
     892       79436 :             if(cb2cq==0.) continue;
     893       34496 :             const unsigned jpos = myfrag->curr[q];
     894       34496 :             if(ipos==jpos) continue;
     895       34496 :             list.push_back(jpos);
     896      103488 :             const Vector distance = delta(getPosition(jpos),getPosition(ipos));
     897       34496 :             const double d = distance.modulo();
     898       34496 :             const double fact = cb2cq/d;
     899             : 
     900       34496 :             cs += cb2cq*d;
     901       34496 :             const Vector der = fact*distance;
     902       34496 :             ff[0] += der;
     903       68992 :             ff.push_back(-der);
     904             :           }
     905             : 
     906             :           //NEXT
     907             :           const double * CONST_BB2_NEXT = db.CONST_BB2_NEXT(aa_kind,at_kind);
     908        8246 :           const unsigned nexsize = myfrag->next.size();
     909       90706 :           for(unsigned q=0; q<nexsize; q++) {
     910       41230 :             const double cb2nq = CONST_BB2_NEXT[q];
     911       43414 :             if(cb2nq==0.) continue;
     912       39046 :             const unsigned jpos = myfrag->next[q];
     913       39046 :             list.push_back(jpos);
     914      117138 :             const Vector distance = delta(getPosition(jpos),getPosition(ipos));
     915       39046 :             const double d = distance.modulo();
     916       39046 :             const double fact = cb2nq/d;
     917             : 
     918       39046 :             cs += cb2nq*d;
     919       39046 :             const Vector der = fact*distance;
     920       39046 :             ff[0] += der;
     921       78092 :             ff.push_back(-der);
     922             :           }
     923             : 
     924             :           //SIDE CHAIN
     925        8246 :           const double * CONST_SC2 = db.CONST_SC2(aa_kind,at_kind,myfrag->res_type_curr);
     926        8246 :           const unsigned sidsize = myfrag->side_chain.size();
     927      162498 :           for(unsigned q=0; q<sidsize; q++) {
     928       77126 :             const double cs2q = CONST_SC2[q];
     929      165242 :             if(cs2q==0.) continue;
     930       33068 :             const unsigned jpos = myfrag->side_chain[q];
     931       33068 :             if(ipos==jpos) continue;
     932       33068 :             list.push_back(jpos);
     933       99204 :             const Vector distance = delta(getPosition(jpos),getPosition(ipos));
     934       33068 :             const double d = distance.modulo();
     935       33068 :             const double fact = cs2q/d;
     936             : 
     937       33068 :             cs += cs2q*d;
     938       33068 :             const Vector der = fact*distance;
     939       33068 :             ff[0] += der;
     940       66136 :             ff.push_back(-der);
     941             :           }
     942             : 
     943             :           //EXTRA DIST
     944             :           const double * CONST_XD  = db.CONST_XD(aa_kind,at_kind);
     945      437038 :           for(unsigned q=0; q<xdsize; q++) {
     946      214396 :             const double cxdq = CONST_XD[q];
     947      239106 :             if(cxdq==0.) continue;
     948      421820 :             if(myfrag->xd1[q]==-1||myfrag->xd2[q]==-1) continue;
     949      389172 :             list.push_back(myfrag->xd2[q]);
     950      389172 :             list.push_back(myfrag->xd1[q]);
     951      194586 :             cs += cxdq*ext_d[q];
     952      194586 :             const Vector der = cxdq*ext_distances[q];
     953      194586 :             ff.push_back( der);
     954      389172 :             ff.push_back(-der);
     955             :           }
     956             : 
     957             :           //NON BOND
     958             :           {
     959             :             const double * CONST_CO_SPHERE3 = db.CO_SPHERE(aa_kind,at_kind,0);
     960             :             const double * CONST_CO_SPHERE  = db.CO_SPHERE(aa_kind,at_kind,1);
     961        8246 :             const unsigned boxsize = myfrag->box_nb.size();
     962     1755970 :             for(unsigned bat=0; bat<boxsize; bat++) {
     963     1747724 :               const unsigned jpos = myfrag->box_nb[bat];
     964     2621586 :               const Vector distance = delta(getPosition(jpos),getPosition(ipos));
     965      873862 :               const double d2 = distance.modulo2();
     966             : 
     967      873862 :               if(d2<cutOffDist2) {
     968      151762 :                 double factor1  = sqrt(d2);
     969      151762 :                 double dfactor1 = 1./factor1;
     970      151762 :                 double factor3  = dfactor1*dfactor1*dfactor1;
     971      151762 :                 double dfactor3 = -3.*factor3*dfactor1*dfactor1;
     972             : 
     973      151762 :                 if(d2>cutOnDist2) {
     974      142214 :                   const double af = cutOffDist2 - d2;
     975      142214 :                   const double bf = cutOffDist2 - 3.*cutOnDist2 + 2.*d2;
     976      142214 :                   const double cf = invswitch*af;
     977      142214 :                   const double df = cf*af*bf;
     978      142214 :                   factor1 *= df;
     979      142214 :                   factor3 *= df;
     980             : 
     981      142214 :                   const double d4  = d2*d2;
     982      142214 :                   const double af1 = 15.*cutOnDist2*d2;
     983      142214 :                   const double bf1 = -14.*d4;
     984      142214 :                   const double cf1 = -3.*cutOffDist2*cutOnDist2 + cutOffDist2*d2;
     985      142214 :                   const double df1 = af1+bf1+cf1;
     986      142214 :                   dfactor1 *= cf*(cutOffDist4+df1);
     987             : 
     988             :                   const double af3 = +2.*cutOffDist2*cutOnDist2;
     989      142214 :                   const double bf3 = d2*(cutOffDist2+cutOnDist2);
     990      142214 :                   const double cf3 = -2.*d4;
     991      142214 :                   const double df3 = (af3+bf3+cf3)*d2;
     992      142214 :                   dfactor3 *= invswitch*(cutMixed+df3);
     993             :                 }
     994             : 
     995      303524 :                 const unsigned t = type[jpos];
     996      151762 :                 cs += factor1*CONST_CO_SPHERE[t] + factor3*CONST_CO_SPHERE3[t] ;
     997      151762 :                 const double fact = dfactor1*CONST_CO_SPHERE[t]+dfactor3*CONST_CO_SPHERE3[t];
     998      151762 :                 const Vector der  = fact*distance;
     999             : 
    1000      151762 :                 list.push_back(jpos);
    1001      151762 :                 ff[0] += der;
    1002      303524 :                 ff.push_back(-der);
    1003             :               }
    1004             :             }
    1005             :           }
    1006             :           //END NON BOND
    1007             : 
    1008             :           //RINGS
    1009             :           {
    1010             :             const double *rc = db.CO_RING(aa_kind,at_kind);
    1011        8246 :             const unsigned rsize = ringInfo.size();
    1012      338086 :             for(unsigned i=0; i<rsize; i++) {
    1013             :               // compute angle from ring middle point to current atom position
    1014             :               // get distance vector from query atom to ring center and normal vector to ring plane
    1015      329840 :               const Vector n   = ringInfo[i].normVect;
    1016      164920 :               const double nL  = ringInfo[i].lengthNV;
    1017      164920 :               const double inL2 = ringInfo[i].lengthN2;
    1018             : 
    1019      329840 :               const Vector d = delta(ringInfo[i].position, getPosition(ipos));
    1020      164920 :               const double dL2 = d.modulo2();
    1021      164920 :               double dL  = sqrt(dL2);
    1022      164920 :               const double idL3 = 1./(dL2*dL);
    1023             : 
    1024      164920 :               const double dn    = dotProduct(d,n);
    1025      164920 :               const double dn2   = dn*dn;
    1026      164920 :               const double dLnL  = dL*nL;
    1027      164920 :               const double dL_nL = dL/nL;
    1028             : 
    1029      164920 :               const double ang2 = dn2*inL2/dL2;
    1030      164920 :               const double u    = 1.-3.*ang2;
    1031      164920 :               const double cc   = rc[ringInfo[i].rtype];
    1032             : 
    1033      164920 :               cs += cc*u*idL3;
    1034             : 
    1035      164920 :               const double fUU    = -6*dn*inL2;
    1036      164920 :               const double fUQ    = fUU/dL;
    1037      164920 :               const Vector gradUQ = fUQ*(dL2*n - dn*d);
    1038      164920 :               const Vector gradVQ = (3*dL*u)*d;
    1039             : 
    1040      164920 :               const double fact   = cc*idL3*idL3;
    1041      329840 :               ff[0] += fact*(gradUQ - gradVQ);
    1042             : 
    1043      164920 :               const double fU       = fUU/nL;
    1044             :               double OneOverN = 1./6.;
    1045      164920 :               if(ringInfo[i].numAtoms==5) OneOverN=1./3.;
    1046      164920 :               const Vector factor2  = OneOverN*n;
    1047      164920 :               const Vector factor4  = (OneOverN/dL_nL)*d;
    1048             : 
    1049      164920 :               const Vector gradV    = -OneOverN*gradVQ;
    1050             : 
    1051      164920 :               if(ringInfo[i].numAtoms==6) {
    1052             :                 // update forces on ring atoms
    1053     2036762 :                 for(unsigned at=0; at<6; at++) {
    1054      940044 :                   const Vector ab = crossProduct(d,ringInfo[i].g[at]);
    1055      940044 :                   const Vector c  = crossProduct(n,ringInfo[i].g[at]);
    1056      940044 :                   const Vector factor3 = 0.5*dL_nL*c;
    1057      940044 :                   const Vector factor1 = 0.5*ab;
    1058      940044 :                   const Vector gradU   = fU*( dLnL*(factor1 - factor2) -dn*(factor3 - factor4) );
    1059     1880088 :                   ff.push_back(fact*(gradU - gradV));
    1060      940044 :                   list.push_back(ringInfo[i].atom[at]);
    1061             :                 }
    1062             :               }  else {
    1063       57722 :                 for(unsigned at=0; at<3; at++) {
    1064       24738 :                   const Vector ab = crossProduct(d,ringInfo[i].g[at]);
    1065       24738 :                   const Vector c  = crossProduct(n,ringInfo[i].g[at]);
    1066       24738 :                   const Vector factor3 = dL_nL*c;
    1067       24738 :                   const Vector factor1 = ab;
    1068       24738 :                   const Vector gradU   = fU*( dLnL*(factor1 - factor2) -dn*(factor3 - factor4) );
    1069       49476 :                   ff.push_back(fact*(gradU - gradV));
    1070             :                 }
    1071        8246 :                 list.push_back(ringInfo[i].atom[0]);
    1072        8246 :                 list.push_back(ringInfo[i].atom[2]);
    1073        8246 :                 list.push_back(ringInfo[i].atom[3]);
    1074             :               }
    1075             :             }
    1076             :           }
    1077             :           //END OF RINGS
    1078             : 
    1079             :           //DIHEDRAL ANGLES
    1080             :           {
    1081             :             const double *CO_DA = db.CO_DA(aa_kind,at_kind);
    1082        8246 :             if(myfrag->phi.size()==4) {
    1083             :               const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,0);
    1084        8246 :               const double val1 = 3.*myfrag->t_phi+PARS_DA[3];
    1085        8246 :               const double val2 = myfrag->t_phi+PARS_DA[4];
    1086        8246 :               cs += CO_DA[0]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]);
    1087        8246 :               const double fact = -CO_DA[0]*(+3.*PARS_DA[0]*sin(val1)+PARS_DA[1]*sin(val2));
    1088             : 
    1089       16492 :               ff.push_back(fact*myfrag->dd0[0]);
    1090       16492 :               ff.push_back(fact*myfrag->dd10[0]);
    1091       16492 :               ff.push_back(fact*myfrag->dd21[0]);
    1092       16492 :               ff.push_back(-fact*myfrag->dd2[0]);
    1093       16492 :               list.push_back(myfrag->phi[0]);
    1094       16492 :               list.push_back(myfrag->phi[1]);
    1095       16492 :               list.push_back(myfrag->phi[2]);
    1096       16492 :               list.push_back(myfrag->phi[3]);
    1097             :             }
    1098             : 
    1099        8246 :             if(myfrag->psi.size()==4) {
    1100             :               const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,1);
    1101        8246 :               const double val1 = 3.*myfrag->t_psi+PARS_DA[3];
    1102        8246 :               const double val2 = myfrag->t_psi+PARS_DA[4];
    1103        8246 :               cs += CO_DA[1]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]);
    1104        8246 :               const double fact = -CO_DA[1]*(+3.*PARS_DA[0]*sin(val1)+PARS_DA[1]*sin(val2));
    1105             : 
    1106       16492 :               ff.push_back(fact*myfrag->dd0[1]);
    1107       16492 :               ff.push_back(fact*myfrag->dd10[1]);
    1108       16492 :               ff.push_back(fact*myfrag->dd21[1]);
    1109       16492 :               ff.push_back(-fact*myfrag->dd2[1]);
    1110       16492 :               list.push_back(myfrag->psi[0]);
    1111       16492 :               list.push_back(myfrag->psi[1]);
    1112       16492 :               list.push_back(myfrag->psi[2]);
    1113       16492 :               list.push_back(myfrag->psi[3]);
    1114             :             }
    1115             : 
    1116             :             //Chi
    1117        8246 :             if(myfrag->chi1.size()==4) {
    1118             :               const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,2);
    1119        6580 :               const double val1 = 3.*myfrag->t_chi1+PARS_DA[3];
    1120        6580 :               const double val2 = myfrag->t_chi1+PARS_DA[4];
    1121        6580 :               cs += CO_DA[2]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]);
    1122        6580 :               const double fact = -CO_DA[2]*(+3.*PARS_DA[0]*sin(val1)+PARS_DA[1]*sin(val2));
    1123             : 
    1124       13160 :               ff.push_back(fact*myfrag->dd0[2]);
    1125       13160 :               ff.push_back(fact*myfrag->dd10[2]);
    1126       13160 :               ff.push_back(fact*myfrag->dd21[2]);
    1127       13160 :               ff.push_back(-fact*myfrag->dd2[2]);
    1128       13160 :               list.push_back(myfrag->chi1[0]);
    1129       13160 :               list.push_back(myfrag->chi1[1]);
    1130       13160 :               list.push_back(myfrag->chi1[2]);
    1131       13160 :               list.push_back(myfrag->chi1[3]);
    1132             :             }
    1133             :           }
    1134             :           //END OF DIHE
    1135             : 
    1136        8246 :           if(getDoScore()) {
    1137        2356 :             setCalcData(index_cs[s][a][at_kind], cs);
    1138        4712 :             all_list[index_cs[s][a][at_kind]] = list;
    1139        4712 :             all_ff[index_cs[s][a][at_kind]] = ff;
    1140        2356 :             Value *comp = atom[s][a].comp[at_kind];
    1141             :             comp->set(cs);
    1142             :           } else {
    1143        5890 :             if(camshift) {
    1144        1178 :               score += (cs - atom[s][a].exp_cs[at_kind])*(cs - atom[s][a].exp_cs[at_kind])/camshift_sigma2[at_kind];
    1145         589 :               double fact = 2.0*(cs - atom[s][a].exp_cs[at_kind])/camshift_sigma2[at_kind];
    1146      625603 :               for(unsigned i=0; i<list.size(); i++) omp_deriv[list[i]] += fact*ff[i];
    1147             :             } else {
    1148        5301 :               Value *comp = atom[s][a].comp[at_kind];
    1149             :               comp->set(cs);
    1150        5301 :               Tensor virial;
    1151     3380793 :               for(unsigned i=0; i<list.size(); i++) {
    1152     2246794 :                 setAtomsDerivatives(comp,list[i],ff[i]);
    1153     2246794 :                 virial-=Tensor(getPosition(list[i]),ff[i]);
    1154             :               }
    1155        5301 :               setBoxDerivatives(comp,virial);
    1156             :             }
    1157             :           }
    1158             :         }
    1159             :       }
    1160             :     }
    1161         112 :     #pragma omp critical
    1162       31408 :     if(camshift) for(unsigned i=0; i<getPositions().size(); i++) setAtomsDerivatives(getPntrToValue(),i,omp_deriv[i]);
    1163             :   }
    1164             : 
    1165          14 :   if(getDoScore()) {
    1166             :     /* Metainference */
    1167           4 :     double score = getScore();
    1168             :     setScore(score);
    1169             : 
    1170             :     /* calculate final derivatives */
    1171           8 :     Value* val=getPntrToComponent("score");
    1172             : 
    1173           4 :     Tensor virial;
    1174             : 
    1175        7076 :     for(unsigned i=0; i<all_list.size(); i++) {
    1176             :       const double fact = getMetaDer(i);
    1177     1502480 :       for(unsigned j=0; j<all_list[i].size(); j++) {
    1178      998512 :         setAtomsDerivatives(val, all_list[i][j],  all_ff[i][j]*fact);
    1179     1497768 :         virial-=Tensor(getPosition(all_list[i][j]), all_ff[i][j]*fact);
    1180             :       }
    1181             :     }
    1182           4 :     setBoxDerivatives(val,virial);
    1183             :   }
    1184             : 
    1185             :   // in the case of camshift we calculate the virial at the end
    1186          14 :   if(camshift) {
    1187           1 :     Tensor virial;
    1188             :     unsigned nat=getNumberOfAtoms();
    1189           1 :     Value* val=getPntrToValue();
    1190       10449 :     for(unsigned i=0; i<nat; i++) virial-=Tensor(getPosition(i),
    1191        7836 :                                             Vector(val->getDerivative(3*i+0),
    1192             :                                                 val->getDerivative(3*i+1),
    1193        2612 :                                                 val->getDerivative(3*i+2)));
    1194           1 :     setBoxDerivatives(val,virial);
    1195           1 :     setValue(score);
    1196             :   }
    1197             : 
    1198          14 :   ++box_count;
    1199          14 :   if(box_count == box_nupdate) box_count = 0;
    1200          14 : }
    1201             : 
    1202          14 : void CS2Backbone::update_neighb() {
    1203          14 :   const unsigned chainsize = atom.size();
    1204          70 :   for(unsigned s=0; s<chainsize; s++) {
    1205          56 :     const unsigned psize = atom[s].size();
    1206          84 :     #pragma omp parallel for num_threads(OpenMP::getNumThreads())
    1207          56 :     for(unsigned a=1; a<psize-1; a++) {
    1208             :       const unsigned boxsize = getNumberOfAtoms();
    1209        2408 :       atom[s][a].box_nb.clear();
    1210        2408 :       atom[s][a].box_nb.reserve(300);
    1211        4816 :       const unsigned res_curr = res_num[atom[s][a].pos[0]];
    1212     6292104 :       for(unsigned bat=0; bat<boxsize; bat++) {
    1213    12579392 :         const unsigned res_dist = abs(static_cast<int>(res_curr-res_num[bat]));
    1214     6397062 :         if(res_dist<2) continue;
    1215    78235586 :         for(unsigned at_kind=0; at_kind<6; at_kind++) {
    1216    88150694 :           if(atom[s][a].exp_cs[at_kind]==0.) continue;
    1217    20652670 :           const unsigned ipos = atom[s][a].pos[at_kind];
    1218    41305340 :           const Vector distance = delta(getPosition(bat),getPosition(ipos));
    1219    20652670 :           const double d2=distance.modulo2();
    1220    20652670 :           if(d2<cutOffNB2) {
    1221      241160 :             atom[s][a].box_nb.push_back(bat);
    1222      241160 :             break;
    1223             :           }
    1224             :         }
    1225             :       }
    1226             :     }
    1227             :   }
    1228          14 : }
    1229             : 
    1230          14 : void CS2Backbone::compute_ring_parameters() {
    1231         868 :   for(unsigned i=0; i<ringInfo.size(); i++) {
    1232         280 :     const unsigned size = ringInfo[i].numAtoms;
    1233         280 :     if(size==6) {
    1234         798 :       ringInfo[i].g[0] = delta(getPosition(ringInfo[i].atom[4]),getPosition(ringInfo[i].atom[2]));
    1235         798 :       ringInfo[i].g[1] = delta(getPosition(ringInfo[i].atom[5]),getPosition(ringInfo[i].atom[3]));
    1236         798 :       ringInfo[i].g[2] = delta(getPosition(ringInfo[i].atom[0]),getPosition(ringInfo[i].atom[4]));
    1237         798 :       ringInfo[i].g[3] = delta(getPosition(ringInfo[i].atom[1]),getPosition(ringInfo[i].atom[5]));
    1238         798 :       ringInfo[i].g[4] = delta(getPosition(ringInfo[i].atom[2]),getPosition(ringInfo[i].atom[0]));
    1239         798 :       ringInfo[i].g[5] = delta(getPosition(ringInfo[i].atom[3]),getPosition(ringInfo[i].atom[1]));
    1240         266 :       vector<Vector> a(size);
    1241         532 :       a[0] = getPosition(ringInfo[i].atom[0]);
    1242             :       // ring center
    1243         266 :       Vector midP = a[0];
    1244        2926 :       for(unsigned j=1; j<size; j++) {
    1245        3990 :         a[j] = getPosition(ringInfo[i].atom[j]);
    1246        1330 :         midP += a[j];
    1247             :       }
    1248         266 :       midP /= (double) size;
    1249         266 :       ringInfo[i].position = midP;
    1250             :       // compute normal vector to plane containing first three atoms in array
    1251         798 :       ringInfo[i].n1 = crossProduct(delta(a[0],a[4]), delta(a[0],a[2]));
    1252             :       // compute normal vector to plane containing last three atoms in array
    1253             :       // NB: third atom of five-membered ring used for both computations above
    1254         798 :       ringInfo[i].n2 = crossProduct(delta(a[3],a[1]), delta(a[3],a[5]));
    1255             :       // ring plane normal vector is average of n1 and n2
    1256         532 :       ringInfo[i].normVect = 0.5*(ringInfo[i].n1 + ringInfo[i].n2);
    1257             :     }  else {
    1258          42 :       ringInfo[i].g[0] = delta(getPosition(ringInfo[i].atom[3]),getPosition(ringInfo[i].atom[2]));
    1259          42 :       ringInfo[i].g[1] = delta(getPosition(ringInfo[i].atom[0]),getPosition(ringInfo[i].atom[3]));
    1260          42 :       ringInfo[i].g[2] = delta(getPosition(ringInfo[i].atom[2]),getPosition(ringInfo[i].atom[0]));
    1261          14 :       vector<Vector> a(size);
    1262         154 :       for(unsigned j=0; j<size; j++) {
    1263         210 :         a[j] = getPosition(ringInfo[i].atom[j]);
    1264             :       }
    1265             :       // ring center
    1266          14 :       Vector midP = (a[0]+a[2]+a[3])/3.;
    1267          14 :       ringInfo[i].position = midP;
    1268             :       // compute normal vector to plane containing first three atoms in array
    1269          42 :       ringInfo[i].n1 = crossProduct(delta(a[0],a[3]), delta(a[0],a[2]));
    1270             :       // ring plane normal vector is average of n1 and n2
    1271          14 :       ringInfo[i].normVect = ringInfo[i].n1;
    1272             : 
    1273             :     }
    1274             :     // calculate squared length and length of normal vector
    1275         280 :     ringInfo[i].lengthN2 = 1./ringInfo[i].normVect.modulo2();
    1276         560 :     ringInfo[i].lengthNV = 1./sqrt(ringInfo[i].lengthN2);
    1277             :   }
    1278          14 : }
    1279             : 
    1280          14 : void CS2Backbone::compute_dihedrals() {
    1281          14 :   const unsigned chainsize = atom.size();
    1282          70 :   for(unsigned s=0; s<chainsize; s++) {
    1283          56 :     const unsigned psize = atom[s].size();
    1284          84 :     #pragma omp parallel for num_threads(OpenMP::getNumThreads())
    1285          56 :     for(unsigned a=1; a<psize-1; a++) {
    1286        2408 :       const Fragment *myfrag = &atom[s][a];
    1287        2408 :       if(myfrag->phi.size()==4) {
    1288        7224 :         const Vector d0 = delta(getPosition(myfrag->phi[1]), getPosition(myfrag->phi[0]));
    1289        7224 :         const Vector d1 = delta(getPosition(myfrag->phi[2]), getPosition(myfrag->phi[1]));
    1290        7224 :         const Vector d2 = delta(getPosition(myfrag->phi[3]), getPosition(myfrag->phi[2]));
    1291             :         Torsion t;
    1292        2408 :         Vector dd0, dd1, dd2;
    1293        2408 :         atom[s][a].t_phi = t.compute(d0,d1,d2,dd0,dd1,dd2);
    1294        2408 :         atom[s][a].dd0[0]  = dd0;
    1295        2408 :         atom[s][a].dd10[0] = dd1-dd0;
    1296        2408 :         atom[s][a].dd21[0] = dd2-dd1;
    1297        2408 :         atom[s][a].dd2[0]  = dd2;
    1298             :       }
    1299        2408 :       if(myfrag->psi.size()==4) {
    1300        7224 :         const Vector d0 = delta(getPosition(myfrag->psi[1]), getPosition(myfrag->psi[0]));
    1301        7224 :         const Vector d1 = delta(getPosition(myfrag->psi[2]), getPosition(myfrag->psi[1]));
    1302        7224 :         const Vector d2 = delta(getPosition(myfrag->psi[3]), getPosition(myfrag->psi[2]));
    1303             :         Torsion t;
    1304        2408 :         Vector dd0, dd1, dd2;
    1305        2408 :         atom[s][a].t_psi = t.compute(d0,d1,d2,dd0,dd1,dd2);
    1306        2408 :         atom[s][a].dd0[1]  = dd0;
    1307        2408 :         atom[s][a].dd10[1] = dd1-dd0;
    1308        2408 :         atom[s][a].dd21[1] = dd2-dd1;
    1309        2408 :         atom[s][a].dd2[1]  = dd2;
    1310             :       }
    1311        2408 :       if(myfrag->chi1.size()==4) {
    1312        5586 :         const Vector d0 = delta(getPosition(myfrag->chi1[1]), getPosition(myfrag->chi1[0]));
    1313        5586 :         const Vector d1 = delta(getPosition(myfrag->chi1[2]), getPosition(myfrag->chi1[1]));
    1314        5586 :         const Vector d2 = delta(getPosition(myfrag->chi1[3]), getPosition(myfrag->chi1[2]));
    1315             :         Torsion t;
    1316        1862 :         Vector dd0, dd1, dd2;
    1317        1862 :         atom[s][a].t_chi1 = t.compute(d0,d1,d2,dd0,dd1,dd2);
    1318        1862 :         atom[s][a].dd0[2]  = dd0;
    1319        1862 :         atom[s][a].dd10[2] = dd1-dd0;
    1320        1862 :         atom[s][a].dd21[2] = dd2-dd1;
    1321        1862 :         atom[s][a].dd2[2]  = dd2;
    1322             :       }
    1323             :     }
    1324             :   }
    1325          14 : }
    1326             : 
    1327          14 : void CS2Backbone::init_backbone(const PDB &pdb) {
    1328             :   // number of chains
    1329          14 :   vector<string> chains;
    1330          14 :   pdb.getChainNames( chains );
    1331          28 :   seg_last.resize(chains.size());
    1332             :   unsigned old_size=0;
    1333             : 
    1334         112 :   for(unsigned i=0; i<chains.size(); i++) {
    1335             :     unsigned start, end;
    1336             :     string errmsg;
    1337          28 :     pdb.getResidueRange( chains[i], start, end, errmsg );
    1338             : 
    1339          28 :     unsigned res_offset = start;
    1340          28 :     unsigned resrange = end-start+1;
    1341             : 
    1342          42 :     if(i==0) seg_last[i] = resrange;
    1343          42 :     else seg_last[i] = seg_last[i-1]+resrange;
    1344             : 
    1345             :     vector<int> N_;
    1346             :     vector<int> H_;
    1347             :     vector<int> CA_;
    1348             :     vector<int> CB_;
    1349             :     vector<int> HA_;
    1350             :     vector<int> C_;
    1351             :     vector<int> O_;
    1352             :     vector<int> CX_;
    1353          28 :     N_.resize (resrange,-1);
    1354          28 :     H_.resize (resrange,-1);
    1355          28 :     CA_.resize(resrange,-1);
    1356          28 :     CB_.resize(resrange,-1);
    1357          28 :     HA_.resize(resrange,-1);
    1358          28 :     C_.resize (resrange,-1);
    1359          28 :     O_.resize (resrange,-1);
    1360          28 :     CX_.resize(resrange,-1);
    1361             : 
    1362          28 :     vector<AtomNumber> allatoms = pdb.getAtomsInChain(chains[i]);
    1363             :     // cycle over all the atoms in the chain
    1364      109760 :     for(unsigned a=0; a<allatoms.size(); a++) {
    1365       36568 :       unsigned atm_index=a+old_size;
    1366       36568 :       unsigned f = pdb.getResidueNumber(allatoms[a]);
    1367       36568 :       unsigned f_idx = f-res_offset;
    1368       36568 :       string AN = pdb.getAtomName(allatoms[a]);
    1369       36568 :       string RES = pdb.getResidueName(allatoms[a]);
    1370       39032 :       if(AN=="N") N_[f_idx] = atm_index;
    1371       68208 :       else if(AN=="H" ||AN=="HN" ) H_[f_idx] = atm_index;
    1372       95718 :       else if(AN=="HA"||AN=="HA1"||AN=="HA3") HA_[f_idx] = atm_index;
    1373       34230 :       else if(AN=="CA") CA_[f_idx] = atm_index;
    1374       28882 :       else if(AN=="CB") CB_[f_idx] = atm_index;
    1375       27258 :       else if(AN=="C" ) C_ [f_idx] = atm_index;
    1376       24766 :       else if(AN=="O" ) O_ [f_idx] = atm_index;
    1377       20734 :       else if(AN=="CD"&&RES=="PRO") H_[f_idx] = atm_index;
    1378       38472 :       if(is_chi1_cx(RES,AN)) CX_[f_idx] = atm_index;
    1379             :     }
    1380          28 :     old_size+=allatoms.size();
    1381             : 
    1382             :     // vector of residues for a given chain
    1383          28 :     vector<Fragment> atm_;
    1384             :     // cycle over all residues in the chain
    1385        2492 :     for(unsigned a=start; a<=end; a++) {
    1386        2464 :       unsigned f_idx = a - res_offset;
    1387        4928 :       Fragment at;
    1388        4928 :       at.pos[0] = HA_[f_idx];
    1389        2464 :       at.pos[1] =  H_[f_idx];
    1390        2464 :       at.pos[2] =  N_[f_idx];
    1391        2464 :       at.pos[3] = CA_[f_idx];
    1392        2464 :       at.pos[4] = CB_[f_idx];
    1393        2464 :       at.pos[5] =  C_[f_idx];
    1394        2464 :       at.res_type_prev = at.res_type_curr = at.res_type_next = 0;
    1395        4928 :       at.res_name = pdb.getResidueName(a, chains[i]);
    1396        2464 :       at.res_kind = db.kind(at.res_name);
    1397        2464 :       at.fd = a;
    1398             :       //REGISTER PREV CURR NEXT
    1399             :       {
    1400        2464 :         if(a>start) {
    1401        4872 :           at.prev.push_back( N_[f_idx-1]);
    1402        2436 :           at.prev.push_back(CA_[f_idx-1]);
    1403        2436 :           at.prev.push_back(HA_[f_idx-1]);
    1404        2436 :           at.prev.push_back( C_[f_idx-1]);
    1405        2436 :           at.prev.push_back( O_[f_idx-1]);
    1406        4872 :           at.res_type_prev = frag2enum(pdb.getResidueName(a-1, chains[i]));
    1407             :         }
    1408             : 
    1409        2464 :         at.curr.push_back( N_[f_idx]);
    1410        2464 :         at.curr.push_back( H_[f_idx]);
    1411        2464 :         at.curr.push_back(CA_[f_idx]);
    1412        2464 :         at.curr.push_back(HA_[f_idx]);
    1413        2464 :         at.curr.push_back( C_[f_idx]);
    1414        2464 :         at.curr.push_back( O_[f_idx]);
    1415        4928 :         at.res_type_curr = frag2enum(pdb.getResidueName(a, chains[i]));
    1416             : 
    1417        2464 :         if(a<end) {
    1418        4872 :           at.next.push_back (N_[f_idx+1]);
    1419        2436 :           at.next.push_back (H_[f_idx+1]);
    1420        2436 :           at.next.push_back(CA_[f_idx+1]);
    1421        2436 :           at.next.push_back(HA_[f_idx+1]);
    1422        2436 :           at.next.push_back( C_[f_idx+1]);
    1423        4872 :           at.res_type_next = frag2enum(pdb.getResidueName(a+1, chains[i]));
    1424             :         }
    1425             : 
    1426             :         //PHI | PSI | CH1
    1427        2464 :         if(a>start) {
    1428        4872 :           at.phi.push_back( C_[f_idx-1]);
    1429        2436 :           at.phi.push_back( N_[f_idx]);
    1430        2436 :           at.phi.push_back(CA_[f_idx]);
    1431        2436 :           at.phi.push_back( C_[f_idx]);
    1432             :         }
    1433             : 
    1434        2464 :         if(a<end) {
    1435        2436 :           at.psi.push_back( N_[f_idx]);
    1436        2436 :           at.psi.push_back(CA_[f_idx]);
    1437        2436 :           at.psi.push_back( C_[f_idx]);
    1438        4872 :           at.psi.push_back( N_[f_idx+1]);
    1439             :         }
    1440             : 
    1441        4368 :         if(CX_[f_idx]!=-1&&CB_[f_idx]!=-1) {
    1442        1904 :           at.chi1.push_back( N_[f_idx]);
    1443        1904 :           at.chi1.push_back(CA_[f_idx]);
    1444        1904 :           at.chi1.push_back(CB_[f_idx]);
    1445        1904 :           at.chi1.push_back(CX_[f_idx]);
    1446             :         }
    1447             :       }
    1448        2464 :       atm_.push_back(at);
    1449             :     }
    1450          28 :     atom.push_back(atm_);
    1451             :   }
    1452          14 : }
    1453             : 
    1454          14 : void CS2Backbone::init_sidechain(const PDB &pdb) {
    1455          14 :   vector<string> chains;
    1456          14 :   pdb.getChainNames( chains );
    1457             :   unsigned old_size=0;
    1458             :   // cycle over chains
    1459         112 :   for(unsigned s=0; s<atom.size(); s++) {
    1460             :     AtomNumber astart, aend;
    1461             :     string errmsg;
    1462          28 :     pdb.getAtomRange( chains[s], astart, aend, errmsg );
    1463             :     unsigned atom_offset = astart.index();
    1464             :     // cycle over residues
    1465        7448 :     for(unsigned a=0; a<atom[s].size(); a++) {
    1466        4928 :       if(atom[s][a].res_name=="UNK") continue;
    1467        2464 :       vector<AtomNumber> atm = pdb.getAtomsInResidue(atom[s][a].fd, chains[s]);
    1468        4928 :       vector<string> sc_atm = side_chain_atoms(atom[s][a].res_name);
    1469             : 
    1470       90902 :       for(unsigned sc=0; sc<sc_atm.size(); sc++) {
    1471     1593970 :         for(unsigned aa=0; aa<atm.size(); aa++) {
    1472     1024436 :           if(pdb.getAtomName(atm[aa])==sc_atm[sc]) {
    1473       65394 :             atom[s][a].side_chain.push_back(atm[aa].index()-atom_offset+old_size);
    1474             :           }
    1475             :         }
    1476             :       }
    1477             : 
    1478             :     }
    1479          28 :     old_size = aend.index()+1;
    1480             :   }
    1481          14 : }
    1482             : 
    1483          14 : void CS2Backbone::init_xdist(const PDB &pdb) {
    1484             :   const string atomsP1[] = {"H", "H", "H", "C", "C", "C",
    1485             :                             "O", "O", "O", "N", "N", "N",
    1486             :                             "O", "O", "O", "N", "N", "N",
    1487             :                             "CG", "CG", "CG", "CG", "CG",
    1488             :                             "CG", "CG", "CA"
    1489         392 :                            };
    1490             : 
    1491          14 :   const int resOffsetP1 [] = {0, 0, 0, -1, -1, -1,
    1492             :                               0, 0, 0, 1, 1, 1,
    1493             :                               -1, -1, -1, 0, 0, 0,
    1494             :                               0, 0, 0, 0, 0, -1, 1, -1
    1495             :                              };
    1496             : 
    1497             :   const string atomsP2[] = {"HA", "C", "CB", "HA", "C", "CB",
    1498             :                             "HA", "N", "CB", "HA", "N", "CB",
    1499             :                             "HA", "N", "CB", "HA", "N", "CB",
    1500             :                             "HA", "N", "C", "C", "N", "CA", "CA", "CA"
    1501         392 :                            };
    1502             : 
    1503          14 :   const int resOffsetP2 [] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, 0, 0, 0, -1, 1, 0, 0, 1};
    1504             : 
    1505          14 :   vector<string> chains;
    1506          14 :   pdb.getChainNames( chains );
    1507             :   unsigned old_size=0;
    1508         112 :   for(unsigned s=0; s<atom.size(); s++) {
    1509             :     AtomNumber astart, aend;
    1510             :     string errmsg;
    1511          28 :     pdb.getAtomRange( chains[s], astart, aend, errmsg );
    1512             :     unsigned atom_offset = astart.index();
    1513             : 
    1514        7280 :     for(unsigned a=1; a<atom[s].size()-1; a++) {
    1515        2408 :       vector<AtomNumber> atm_curr = pdb.getAtomsInResidue(atom[s][a].fd,chains[s]);
    1516        2408 :       vector<AtomNumber> atm_prev = pdb.getAtomsInResidue(atom[s][a].fd-1,chains[s]);
    1517        2408 :       vector<AtomNumber> atm_next = pdb.getAtomsInResidue(atom[s][a].fd+1,chains[s]);
    1518             : 
    1519      127624 :       for(unsigned q=0; q<db.get_numXtraDists()-1; q++) {
    1520             :         vector<AtomNumber>::iterator at1, at1_end;
    1521             :         vector<AtomNumber>::iterator at2, at2_end;
    1522             : 
    1523             :         bool init_p1=false;
    1524             :         AtomNumber p1;
    1525             :         bool init_p2=false;
    1526             :         AtomNumber p2;
    1527             : 
    1528       62608 :         if(resOffsetP1[q]== 0) { at1 = atm_curr.begin(); at1_end = atm_curr.end();}
    1529       62608 :         if(resOffsetP1[q]==-1) { at1 = atm_prev.begin(); at1_end = atm_prev.end();}
    1530       62608 :         if(resOffsetP1[q]==+1) { at1 = atm_next.begin(); at1_end = atm_next.end();}
    1531      496846 :         while(at1!=at1_end) {
    1532      492730 :           AtomNumber aa = *at1;
    1533             :           ++at1;
    1534      492730 :           string name = pdb.getAtomName(aa);
    1535             : 
    1536      492730 :           xdist_name_map(name);
    1537             : 
    1538      492730 :           if(name==atomsP1[q]) {
    1539       58492 :             p1 = aa;
    1540             :             init_p1=true;
    1541             :             break;
    1542             :           }
    1543             :         }
    1544             : 
    1545       62608 :         if(resOffsetP2[q]== 0) { at2 = atm_curr.begin(); at2_end = atm_curr.end();}
    1546       62608 :         if(resOffsetP2[q]==-1) { at2 = atm_prev.begin(); at2_end = atm_prev.end();}
    1547       62608 :         if(resOffsetP2[q]==+1) { at2 = atm_next.begin(); at2_end = atm_next.end();}
    1548      326396 :         while(at2!=at2_end) {
    1549      323960 :           AtomNumber aa = *at2;
    1550             :           ++at2;
    1551      323960 :           string name = pdb.getAtomName(aa);
    1552             : 
    1553      323960 :           xdist_name_map(name);
    1554             : 
    1555      323960 :           if(name==atomsP2[q]) {
    1556       60172 :             p2 = aa;
    1557             :             init_p2=true;
    1558             :             break;
    1559             :           }
    1560             :         }
    1561       62608 :         int add1 = -1;
    1562       62608 :         int add2 = -1;
    1563       62608 :         if(init_p1) add1=p1.index()-atom_offset+old_size;
    1564       62608 :         if(init_p2) add2=p2.index()-atom_offset+old_size;
    1565       62608 :         atom[s][a].xd1.push_back(add1);
    1566       62608 :         atom[s][a].xd2.push_back(add2);
    1567             :       }
    1568             :     }
    1569          28 :     old_size = aend.index()+1;
    1570             :   }
    1571          14 : }
    1572             : 
    1573          14 : void CS2Backbone::init_types(const PDB &pdb) {
    1574          14 :   vector<AtomNumber> aa = pdb.getAtomNumbers();
    1575      109732 :   for(unsigned i=0; i<aa.size(); i++) {
    1576       36568 :     unsigned frag = pdb.getResidueNumber(aa[i]);
    1577       36568 :     string fragName = pdb.getResidueName(aa[i]);
    1578       36568 :     string atom_name = pdb.getAtomName(aa[i]);
    1579       36568 :     char atom_type = atom_name[0];
    1580       36568 :     if(isdigit(atom_name[0])) atom_type = atom_name[1];
    1581       36568 :     res_num.push_back(frag);
    1582       36568 :     unsigned t = 0;
    1583       36568 :     if (!isSP2(fragName, atom_name)) {
    1584       28728 :       if (atom_type == 'C') t = D_C;
    1585       21714 :       else if (atom_type == 'O') t = D_O;
    1586       21350 :       else if (atom_type == 'H') t = D_H;
    1587        3262 :       else if (atom_type == 'N') t = D_N;
    1588         126 :       else if (atom_type == 'S') t = D_S;
    1589           0 :       else plumed_merror("CS2Backbone:init_type: unknown atom type!\n");
    1590             :     } else {
    1591        7840 :       if (atom_type == 'C') t = D_C2;
    1592        3192 :       else if (atom_type == 'O') t = D_O2;
    1593           0 :       else if (atom_type == 'N') t = D_N2;
    1594           0 :       else plumed_merror("CS2Backbone:init_type: unknown atom type!\n");
    1595             :     }
    1596       36568 :     type.push_back(t);
    1597             :   }
    1598          14 : }
    1599             : 
    1600          14 : void CS2Backbone::init_rings(const PDB &pdb) {
    1601             : 
    1602         112 :   const string pheTyr_n[] = {"CG","CD1","CE1","CZ","CE2","CD2"};
    1603         112 :   const string trp1_n[]   = {"CD2","CE2","CZ2","CH2","CZ3","CE3"};
    1604          98 :   const string trp2_n[]   = {"CG","CD1","NE1","CE2","CD2"};
    1605          98 :   const string his_n[]    = {"CG","ND1","CD2","CE1","NE2"};
    1606             : 
    1607          14 :   vector<string> chains;
    1608          14 :   pdb.getChainNames( chains );
    1609          14 :   vector<AtomNumber> allatoms = pdb.getAtomNumbers();
    1610             :   unsigned old_size=0;
    1611             : 
    1612         112 :   for(unsigned s=0; s<atom.size(); s++) {
    1613             :     AtomNumber astart, aend;
    1614             :     string errmsg;
    1615          28 :     pdb.getAtomRange( chains[s], astart, aend, errmsg );
    1616             :     unsigned atom_offset = astart.index();
    1617        7448 :     for(unsigned r=0; r<atom[s].size(); r++) {
    1618        2464 :       string frg = pdb.getResidueName(atom[s][r].fd);
    1619       11312 :       if(!((frg=="PHE")||(frg=="TYR")||(frg=="TRP")||
    1620        6594 :            (frg=="HIS")||(frg=="HIP")||(frg=="HID")||
    1621        4396 :            (frg=="HIE")||(frg=="HSD")||(frg=="HSE")||
    1622             :            (frg=="HSP"))) continue;
    1623             : 
    1624         266 :       vector<AtomNumber> frg_atoms = pdb.getAtomsInResidue(atom[s][r].fd,chains[s]);
    1625             : 
    1626         308 :       if(frg=="PHE"||frg=="TYR") {
    1627         252 :         RingInfo ri;
    1628       15708 :         for(unsigned a=0; a<frg_atoms.size(); a++) {
    1629        5068 :           unsigned atm = frg_atoms[a].index()-atom_offset+old_size;
    1630       55300 :           for(unsigned aa=0; aa<6; aa++) {
    1631       79884 :             if(pdb.getAtomName(frg_atoms[a])==pheTyr_n[aa]) {
    1632        1512 :               ri.atom[aa] = atm;
    1633        1512 :               break;
    1634             :             }
    1635             :           }
    1636             :         }
    1637         252 :         ri.numAtoms = 6;
    1638         252 :         if(frg=="PHE") ri.rtype = RingInfo::R_PHE;
    1639         252 :         if(frg=="TYR") ri.rtype = RingInfo::R_TYR;
    1640         252 :         ringInfo.push_back(ri);
    1641             : 
    1642          14 :       } else if(frg=="TRP") {
    1643             :         //First ring
    1644          14 :         RingInfo ri;
    1645        1036 :         for(unsigned a=0; a<frg_atoms.size(); a++) {
    1646         336 :           unsigned atm = frg_atoms[a].index()-atom_offset+old_size;
    1647        3780 :           for(unsigned aa=0; aa<6; aa++) {
    1648        5418 :             if(pdb.getAtomName(frg_atoms[a])==trp1_n[aa]) {
    1649          84 :               ri.atom[aa] = atm;
    1650          84 :               break;
    1651             :             }
    1652             :           }
    1653             :         }
    1654          14 :         ri.numAtoms = 6;
    1655          14 :         ri.rtype = RingInfo::R_TRP1;
    1656          14 :         ringInfo.push_back(ri);
    1657             :         //Second Ring
    1658          14 :         RingInfo ri2;
    1659        1036 :         for(unsigned a=0; a<frg_atoms.size(); a++) {
    1660         336 :           unsigned atm = frg_atoms[a].index()-atom_offset+old_size;
    1661        3276 :           for(unsigned aa=0; aa<5; aa++) {
    1662        4620 :             if(pdb.getAtomName(frg_atoms[a])==trp2_n[aa]) {
    1663          70 :               ri2.atom[aa] = atm;
    1664          70 :               break;
    1665             :             }
    1666             :           }
    1667             :         }
    1668          14 :         ri2.numAtoms = 5;
    1669          14 :         ri2.rtype = RingInfo::R_TRP2;
    1670          14 :         ringInfo.push_back(ri2);
    1671             : 
    1672           0 :       } else if((frg=="HIS")||(frg=="HIP")||(frg=="HID")||
    1673           0 :                 (frg=="HIE")||(frg=="HSD")||(frg=="HSE")||
    1674             :                 (frg=="HSP")) {//HIS case
    1675           0 :         RingInfo ri;
    1676           0 :         for(unsigned a=0; a<frg_atoms.size(); a++) {
    1677           0 :           unsigned atm = frg_atoms[a].index()-atom_offset+old_size;
    1678           0 :           for(unsigned aa=0; aa<5; aa++) {
    1679           0 :             if(pdb.getAtomName(frg_atoms[a])==his_n[aa]) {
    1680           0 :               ri.atom[aa] = atm;
    1681           0 :               break;
    1682             :             }
    1683             :           }
    1684             :         }
    1685           0 :         ri.numAtoms = 5;
    1686           0 :         ri.rtype = RingInfo::R_HIS;
    1687           0 :         ringInfo.push_back(ri);
    1688             :       } else {
    1689           0 :         plumed_merror("Unkwown Ring Fragment");
    1690             :       }
    1691             :     }
    1692          28 :     old_size = aend.index()+1;
    1693             :   }
    1694          14 : }
    1695             : 
    1696        7336 : CS2Backbone::aa_t CS2Backbone::frag2enum(const string &aa) {
    1697             : 
    1698             :   aa_t type = ALA;
    1699        7336 :   if (aa == "ALA") type = ALA;
    1700        6916 :   else if (aa == "ARG") type = ARG;
    1701        6622 :   else if (aa == "ASN") type = ASN;
    1702        6244 :   else if (aa == "ASP") type = ASP;
    1703        5880 :   else if (aa == "ASH") type = ASP;
    1704        5880 :   else if (aa == "CYS") type = CYS;
    1705        5712 :   else if (aa == "CYM") type = CYS;
    1706        5712 :   else if (aa == "GLN") type = GLN;
    1707        5586 :   else if (aa == "GLU") type = GLU;
    1708        5096 :   else if (aa == "GLH") type = GLU;
    1709        5096 :   else if (aa == "GLY") type = GLY;
    1710        3850 :   else if (aa == "HIS") type = HIS;
    1711        3850 :   else if (aa == "HSE") type = HIS;
    1712        3850 :   else if (aa == "HIE") type = HIS;
    1713        3850 :   else if (aa == "HSP") type = HIS;
    1714        3850 :   else if (aa == "HIP") type = HIS;
    1715        3850 :   else if (aa == "HSD") type = HIS;
    1716        3850 :   else if (aa == "HID") type = HIS;
    1717        3850 :   else if (aa == "ILE") type = ILE;
    1718        3430 :   else if (aa == "LEU") type = LEU;
    1719        3052 :   else if (aa == "LYS") type = LYS;
    1720        2464 :   else if (aa == "MET") type = MET;
    1721        2268 :   else if (aa == "PHE") type = PHE;
    1722        1596 :   else if (aa == "PRO") type = PRO;
    1723        1302 :   else if (aa == "SER") type = SER;
    1724         924 :   else if (aa == "THR") type = THR;
    1725         462 :   else if (aa == "TRP") type = TRP;
    1726         420 :   else if (aa == "TYR") type = TYR;
    1727         336 :   else if (aa == "VAL") type = VAL;
    1728           0 :   else if (aa == "UNK") type = UNK;
    1729           0 :   else plumed_merror("CS2Backbone: Error converting string " + aa + " into amino acid index: not a valid 3-letter code");
    1730        7336 :   return type;
    1731             : }
    1732             : 
    1733        2464 : vector<string> CS2Backbone::side_chain_atoms(const string &s) {
    1734             :   vector<string> sc;
    1735             : 
    1736        2464 :   if(s=="ALA") {
    1737         280 :     sc.push_back( "CB" );
    1738         280 :     sc.push_back( "HB1" );
    1739         280 :     sc.push_back( "HB2" );
    1740         280 :     sc.push_back( "HB3" );
    1741         140 :     return sc;
    1742        2324 :   } else if(s=="ARG") {
    1743         196 :     sc.push_back( "CB" );
    1744         196 :     sc.push_back( "CG" );
    1745         196 :     sc.push_back( "CD" );
    1746         196 :     sc.push_back( "NE" );
    1747         196 :     sc.push_back( "CZ" );
    1748         196 :     sc.push_back( "NH1" );
    1749         196 :     sc.push_back( "NH2" );
    1750         196 :     sc.push_back( "NH3" );
    1751         196 :     sc.push_back( "HB1" );
    1752         196 :     sc.push_back( "HB2" );
    1753         196 :     sc.push_back( "HB3" );
    1754         196 :     sc.push_back( "HG1" );
    1755         196 :     sc.push_back( "HG2" );
    1756         196 :     sc.push_back( "HG3" );
    1757         196 :     sc.push_back( "HD1" );
    1758         196 :     sc.push_back( "HD2" );
    1759         196 :     sc.push_back( "HD3" );
    1760         196 :     sc.push_back( "HE" );
    1761         196 :     sc.push_back( "HH11" );
    1762         196 :     sc.push_back( "HH12" );
    1763         196 :     sc.push_back( "HH21" );
    1764         196 :     sc.push_back( "HH22" );
    1765         196 :     sc.push_back( "1HH1" );
    1766         196 :     sc.push_back( "2HH1" );
    1767         196 :     sc.push_back( "1HH2" );
    1768         196 :     sc.push_back( "2HH2" );
    1769          98 :     return sc;
    1770        2226 :   } else if(s=="ASN") {
    1771         252 :     sc.push_back( "CB" );
    1772         252 :     sc.push_back( "CG" );
    1773         252 :     sc.push_back( "OD1" );
    1774         252 :     sc.push_back( "ND2" );
    1775         252 :     sc.push_back( "HB1" );
    1776         252 :     sc.push_back( "HB2" );
    1777         252 :     sc.push_back( "HB3" );
    1778         252 :     sc.push_back( "HD21" );
    1779         252 :     sc.push_back( "HD22" );
    1780         252 :     sc.push_back( "1HD2" );
    1781         252 :     sc.push_back( "2HD2" );
    1782         126 :     return sc;
    1783        4074 :   } else if(s=="ASP"||s=="ASH") {
    1784         252 :     sc.push_back( "CB" );
    1785         252 :     sc.push_back( "CG" );
    1786         252 :     sc.push_back( "OD1" );
    1787         252 :     sc.push_back( "OD2" );
    1788         252 :     sc.push_back( "HB1" );
    1789         252 :     sc.push_back( "HB2" );
    1790         252 :     sc.push_back( "HB3" );
    1791         126 :     return sc;
    1792        3892 :   } else if(s=="CYS"||s=="CYM") {
    1793         112 :     sc.push_back( "CB" );
    1794         112 :     sc.push_back( "SG" );
    1795         112 :     sc.push_back( "HB1" );
    1796         112 :     sc.push_back( "HB2" );
    1797         112 :     sc.push_back( "HB3" );
    1798         112 :     sc.push_back( "HG1" );
    1799         112 :     sc.push_back( "HG" );
    1800          56 :     return sc;
    1801        1918 :   } else if(s=="GLN") {
    1802          84 :     sc.push_back( "CB" );
    1803          84 :     sc.push_back( "CG" );
    1804          84 :     sc.push_back( "CD" );
    1805          84 :     sc.push_back( "OE1" );
    1806          84 :     sc.push_back( "NE2" );
    1807          84 :     sc.push_back( "HB1" );
    1808          84 :     sc.push_back( "HB2" );
    1809          84 :     sc.push_back( "HB3" );
    1810          84 :     sc.push_back( "HG1" );
    1811          84 :     sc.push_back( "HG2" );
    1812          84 :     sc.push_back( "HG3" );
    1813          84 :     sc.push_back( "HE21" );
    1814          84 :     sc.push_back( "HE22" );
    1815          84 :     sc.push_back( "1HE2" );
    1816          84 :     sc.push_back( "2HE2" );
    1817          42 :     return sc;
    1818        3584 :   } else if(s=="GLU"||s=="GLH") {
    1819         336 :     sc.push_back( "CB" );
    1820         336 :     sc.push_back( "CG" );
    1821         336 :     sc.push_back( "CD" );
    1822         336 :     sc.push_back( "OE1" );
    1823         336 :     sc.push_back( "OE2" );
    1824         336 :     sc.push_back( "HB1" );
    1825         336 :     sc.push_back( "HB2" );
    1826         336 :     sc.push_back( "HB3" );
    1827         336 :     sc.push_back( "HG1" );
    1828         336 :     sc.push_back( "HG2" );
    1829         336 :     sc.push_back( "HG3" );
    1830         168 :     return sc;
    1831        1708 :   } else if(s=="GLY") {
    1832         840 :     sc.push_back( "HA2" );
    1833         420 :     return sc;
    1834        9016 :   } else if(s=="HIS"||s=="HSE"||s=="HIE"||s=="HSD"||s=="HID"||s=="HIP"||s=="HSP") {
    1835           0 :     sc.push_back( "CB" );
    1836           0 :     sc.push_back( "CG" );
    1837           0 :     sc.push_back( "ND1" );
    1838           0 :     sc.push_back( "CD2" );
    1839           0 :     sc.push_back( "CE1" );
    1840           0 :     sc.push_back( "NE2" );
    1841           0 :     sc.push_back( "HB1" );
    1842           0 :     sc.push_back( "HB2" );
    1843           0 :     sc.push_back( "HB3" );
    1844           0 :     sc.push_back( "HD1" );
    1845           0 :     sc.push_back( "HD2" );
    1846           0 :     sc.push_back( "HE1" );
    1847           0 :     sc.push_back( "HE2" );
    1848           0 :     return sc;
    1849        1288 :   } else if(s=="ILE") {
    1850         280 :     sc.push_back( "CB" );
    1851         280 :     sc.push_back( "CG1" );
    1852         280 :     sc.push_back( "CG2" );
    1853         280 :     sc.push_back( "CD" );
    1854         280 :     sc.push_back( "HB" );
    1855         280 :     sc.push_back( "HG11" );
    1856         280 :     sc.push_back( "HG12" );
    1857         280 :     sc.push_back( "HG21" );
    1858         280 :     sc.push_back( "HG22" );
    1859         280 :     sc.push_back( "HG23" );
    1860         280 :     sc.push_back( "1HG1" );
    1861         280 :     sc.push_back( "2HG1" );
    1862         280 :     sc.push_back( "1HG2" );
    1863         280 :     sc.push_back( "2HG2" );
    1864         280 :     sc.push_back( "3HG2" );
    1865         280 :     sc.push_back( "HD1" );
    1866         280 :     sc.push_back( "HD2" );
    1867         280 :     sc.push_back( "HD3" );
    1868         140 :     return sc;
    1869        1148 :   } else if(s=="LEU") {
    1870         252 :     sc.push_back( "CB" );
    1871         252 :     sc.push_back( "CG" );
    1872         252 :     sc.push_back( "CD1" );
    1873         252 :     sc.push_back( "CD2" );
    1874         252 :     sc.push_back( "HB1" );
    1875         252 :     sc.push_back( "HB2" );
    1876         252 :     sc.push_back( "HB3" );
    1877         252 :     sc.push_back( "HG" );
    1878         252 :     sc.push_back( "HD11" );
    1879         252 :     sc.push_back( "HD12" );
    1880         252 :     sc.push_back( "HD13" );
    1881         252 :     sc.push_back( "HD21" );
    1882         252 :     sc.push_back( "HD22" );
    1883         252 :     sc.push_back( "HD23" );
    1884         252 :     sc.push_back( "1HD1" );
    1885         252 :     sc.push_back( "2HD1" );
    1886         252 :     sc.push_back( "3HD1" );
    1887         252 :     sc.push_back( "1HD2" );
    1888         252 :     sc.push_back( "2HD2" );
    1889         252 :     sc.push_back( "3HD2" );
    1890         126 :     return sc;
    1891        1022 :   } else if(s=="LYS") {
    1892         392 :     sc.push_back( "CB" );
    1893         392 :     sc.push_back( "CG" );
    1894         392 :     sc.push_back( "CD" );
    1895         392 :     sc.push_back( "CE" );
    1896         392 :     sc.push_back( "NZ" );
    1897         392 :     sc.push_back( "HB1" );
    1898         392 :     sc.push_back( "HB2" );
    1899         392 :     sc.push_back( "HB3" );
    1900         392 :     sc.push_back( "HG1" );
    1901         392 :     sc.push_back( "HG2" );
    1902         392 :     sc.push_back( "HG3" );
    1903         392 :     sc.push_back( "HD1" );
    1904         392 :     sc.push_back( "HD2" );
    1905         392 :     sc.push_back( "HD3" );
    1906         392 :     sc.push_back( "HE1" );
    1907         392 :     sc.push_back( "HE2" );
    1908         392 :     sc.push_back( "HE3" );
    1909         392 :     sc.push_back( "HZ1" );
    1910         392 :     sc.push_back( "HZ2" );
    1911         392 :     sc.push_back( "HZ3" );
    1912         196 :     return sc;
    1913         826 :   } else if(s=="MET") {
    1914         140 :     sc.push_back( "CB" );
    1915         140 :     sc.push_back( "CG" );
    1916         140 :     sc.push_back( "SD" );
    1917         140 :     sc.push_back( "CE" );
    1918         140 :     sc.push_back( "HB1" );
    1919         140 :     sc.push_back( "HB2" );
    1920         140 :     sc.push_back( "HB3" );
    1921         140 :     sc.push_back( "HG1" );
    1922         140 :     sc.push_back( "HG2" );
    1923         140 :     sc.push_back( "HG3" );
    1924         140 :     sc.push_back( "HE1" );
    1925         140 :     sc.push_back( "HE2" );
    1926         140 :     sc.push_back( "HE3" );
    1927          70 :     return sc;
    1928         756 :   } else if(s=="PHE") {
    1929         448 :     sc.push_back( "CB" );
    1930         448 :     sc.push_back( "CG" );
    1931         448 :     sc.push_back( "CD1" );
    1932         448 :     sc.push_back( "CD2" );
    1933         448 :     sc.push_back( "CE1" );
    1934         448 :     sc.push_back( "CE2" );
    1935         448 :     sc.push_back( "CZ" );
    1936         448 :     sc.push_back( "HB1" );
    1937         448 :     sc.push_back( "HB2" );
    1938         448 :     sc.push_back( "HB3" );
    1939         448 :     sc.push_back( "HD1" );
    1940         448 :     sc.push_back( "HD2" );
    1941         448 :     sc.push_back( "HD3" );
    1942         448 :     sc.push_back( "HE1" );
    1943         448 :     sc.push_back( "HE2" );
    1944         448 :     sc.push_back( "HE3" );
    1945         448 :     sc.push_back( "HZ" );
    1946         224 :     return sc;
    1947         532 :   } else if(s=="PRO") {
    1948         196 :     sc.push_back( "CB" );
    1949         196 :     sc.push_back( "CG" );
    1950         196 :     sc.push_back( "CD" );
    1951         196 :     sc.push_back( "HB1" );
    1952         196 :     sc.push_back( "HB2" );
    1953         196 :     sc.push_back( "HB3" );
    1954         196 :     sc.push_back( "HG1" );
    1955         196 :     sc.push_back( "HG2" );
    1956         196 :     sc.push_back( "HG3" );
    1957         196 :     sc.push_back( "HD1" );
    1958         196 :     sc.push_back( "HD2" );
    1959         196 :     sc.push_back( "HD3" );
    1960          98 :     return sc;
    1961         434 :   } else if(s=="SER") {
    1962         252 :     sc.push_back( "CB" );
    1963         252 :     sc.push_back( "OG" );
    1964         252 :     sc.push_back( "HB1" );
    1965         252 :     sc.push_back( "HB2" );
    1966         252 :     sc.push_back( "HB3" );
    1967         252 :     sc.push_back( "HG1" );
    1968         252 :     sc.push_back( "HG" );
    1969         126 :     return sc;
    1970         308 :   } else if(s=="THR") {
    1971         308 :     sc.push_back( "CB" );
    1972         308 :     sc.push_back( "OG1" );
    1973         308 :     sc.push_back( "CG2" );
    1974         308 :     sc.push_back( "HB" );
    1975         308 :     sc.push_back( "HG1" );
    1976         308 :     sc.push_back( "HG21" );
    1977         308 :     sc.push_back( "HG22" );
    1978         308 :     sc.push_back( "HG23" );
    1979         308 :     sc.push_back( "1HG2" );
    1980         308 :     sc.push_back( "2HG2" );
    1981         308 :     sc.push_back( "3HG2" );
    1982         154 :     return sc;
    1983         154 :   } else if(s=="TRP") {
    1984          28 :     sc.push_back( "CB" );
    1985          28 :     sc.push_back( "CG" );
    1986          28 :     sc.push_back( "CD1" );
    1987          28 :     sc.push_back( "CD2" );
    1988          28 :     sc.push_back( "NE1" );
    1989          28 :     sc.push_back( "CE2" );
    1990          28 :     sc.push_back( "CE3" );
    1991          28 :     sc.push_back( "CZ2" );
    1992          28 :     sc.push_back( "CZ3" );
    1993          28 :     sc.push_back( "CH2" );
    1994          28 :     sc.push_back( "HB1" );
    1995          28 :     sc.push_back( "HB2" );
    1996          28 :     sc.push_back( "HB3" );
    1997          28 :     sc.push_back( "HD1" );
    1998          28 :     sc.push_back( "HE1" );
    1999          28 :     sc.push_back( "HE3" );
    2000          28 :     sc.push_back( "HZ2" );
    2001          28 :     sc.push_back( "HZ3" );
    2002          28 :     sc.push_back( "HH2" );
    2003          14 :     return sc;
    2004         140 :   } else if(s=="TYR") {
    2005          56 :     sc.push_back( "CB" );
    2006          56 :     sc.push_back( "CG" );
    2007          56 :     sc.push_back( "CD1" );
    2008          56 :     sc.push_back( "CD2" );
    2009          56 :     sc.push_back( "CE1" );
    2010          56 :     sc.push_back( "CE2" );
    2011          56 :     sc.push_back( "CZ" );
    2012          56 :     sc.push_back( "OH" );
    2013          56 :     sc.push_back( "HB1" );
    2014          56 :     sc.push_back( "HB2" );
    2015          56 :     sc.push_back( "HB3" );
    2016          56 :     sc.push_back( "HD1" );
    2017          56 :     sc.push_back( "HD2" );
    2018          56 :     sc.push_back( "HD3" );
    2019          56 :     sc.push_back( "HE1" );
    2020          56 :     sc.push_back( "HE2" );
    2021          56 :     sc.push_back( "HE3" );
    2022          56 :     sc.push_back( "HH" );
    2023          28 :     return sc;
    2024         112 :   } else if(s=="VAL") {
    2025         224 :     sc.push_back( "CB" );
    2026         224 :     sc.push_back( "CG1" );
    2027         224 :     sc.push_back( "CG2" );
    2028         224 :     sc.push_back( "HB" );
    2029         224 :     sc.push_back( "HG11" );
    2030         224 :     sc.push_back( "HG12" );
    2031         224 :     sc.push_back( "HG13" );
    2032         224 :     sc.push_back( "HG21" );
    2033         224 :     sc.push_back( "HG22" );
    2034         224 :     sc.push_back( "HG23" );
    2035         224 :     sc.push_back( "1HG1" );
    2036         224 :     sc.push_back( "2HG1" );
    2037         224 :     sc.push_back( "3HG1" );
    2038         224 :     sc.push_back( "1HG2" );
    2039         224 :     sc.push_back( "2HG2" );
    2040         224 :     sc.push_back( "3HG2" );
    2041         112 :     return sc;
    2042           0 :   } else plumed_merror("CS2Backbone: side_chain_atoms unknown");
    2043             : }
    2044             : 
    2045       36568 : bool CS2Backbone::isSP2(const string & resType, const string & atomName) {
    2046             :   bool sp2 = false;
    2047       36568 :   if (atomName == "C") return true;
    2048       34104 :   if (atomName == "O") return true;
    2049             : 
    2050       31668 :   if(resType == "TRP") {
    2051             : 
    2052         308 :     if      (atomName == "CG")  sp2 = true;
    2053         294 :     else if (atomName == "CD1") sp2 = true;
    2054         280 :     else if (atomName == "CD2") sp2 = true;
    2055         266 :     else if (atomName == "CE2") sp2 = true;
    2056         252 :     else if (atomName == "CE3") sp2 = true;
    2057         238 :     else if (atomName == "CZ2") sp2 = true;
    2058         224 :     else if (atomName == "CZ3") sp2 = true;
    2059         210 :     else if (atomName == "CH2") sp2 = true;
    2060             : 
    2061       31360 :   } else if (resType == "ASP") {
    2062             : 
    2063        1288 :     if      (atomName == "CG")  sp2 = true;
    2064        1162 :     else if (atomName == "OD1") sp2 = true;
    2065        1036 :     else if (atomName == "OD2") sp2 = true;
    2066             : 
    2067       30072 :   } else if (resType == "GLU") {
    2068             : 
    2069        2212 :     if      (atomName == "CD")  sp2 = true;
    2070        2044 :     else if (atomName == "OE1") sp2 = true;
    2071        1876 :     else if (atomName == "OE2") sp2 = true;
    2072             : 
    2073       27860 :   } else if (resType == "ARG") {
    2074             : 
    2075        2156 :     if (atomName == "CZ") sp2 = true;
    2076             : 
    2077       25704 :   } else if (resType == "HIS") {
    2078             : 
    2079           0 :     if      (atomName == "CG")  sp2 = true;
    2080           0 :     else if (atomName == "ND1") sp2 = true;
    2081           0 :     else if (atomName == "CD2") sp2 = true;
    2082           0 :     else if (atomName == "CE1") sp2 = true;
    2083           0 :     else if (atomName == "NE2") sp2 = true;
    2084             : 
    2085       25704 :   } else if (resType == "PHE") {
    2086             : 
    2087        4032 :     if      (atomName == "CG")  sp2 = true;
    2088        3808 :     else if (atomName == "CD1") sp2 = true;
    2089        3584 :     else if (atomName == "CD2") sp2 = true;
    2090        3360 :     else if (atomName == "CE1") sp2 = true;
    2091        3136 :     else if (atomName == "CE2") sp2 = true;
    2092        2912 :     else if (atomName == "CZ")  sp2 = true;
    2093             : 
    2094       21672 :   } else if (resType == "TYR") {
    2095             : 
    2096         532 :     if      (atomName == "CG")  sp2 = true;
    2097         504 :     else if (atomName == "CD1") sp2 = true;
    2098         476 :     else if (atomName == "CD2") sp2 = true;
    2099         448 :     else if (atomName == "CE1") sp2 = true;
    2100         420 :     else if (atomName == "CE2") sp2 = true;
    2101         392 :     else if (atomName == "CZ")  sp2 = true;
    2102             : 
    2103       21140 :   } else if (resType == "ASN") {
    2104             : 
    2105        1512 :     if      (atomName == "CG")  sp2 = true;
    2106        1386 :     else if (atomName == "OD1") sp2 = true;
    2107             : 
    2108       19628 :   } else if (resType == "GLN") {
    2109             : 
    2110         630 :     if      (atomName == "CD")  sp2 = true;
    2111         588 :     else if (atomName == "OE1") sp2 = true;
    2112             : 
    2113             :   }
    2114             : 
    2115             :   return sp2;
    2116             : }
    2117             : 
    2118       36568 : bool CS2Backbone::is_chi1_cx(const string & frg, const string & atm) {
    2119       36568 :   if(atm=="CG")                                        return true;
    2120       35868 :   if((frg == "CYS")&&(atm =="SG"))                     return true;
    2121       72184 :   if(((frg == "ILE")||(frg == "VAL"))&&(atm == "CG1")) return true;
    2122       36330 :   if((frg == "SER")&&(atm == "OG"))                    return true;
    2123       36974 :   if((frg == "THR")&&(atm == "OG1"))                   return true;
    2124             : 
    2125             :   return false;
    2126             : }
    2127             : 
    2128       14448 : unsigned CS2Backbone::frag_segment(const unsigned p) {
    2129             :   unsigned s = 0;
    2130       31164 :   for(unsigned i=0; i<seg_last.size()-1; i++) {
    2131       14448 :     if(p>seg_last[i]) s  = i+1;
    2132             :     else break;
    2133             :   }
    2134       14448 :   return s;
    2135             : }
    2136             : 
    2137       14448 : unsigned CS2Backbone::frag_relitive_index(const unsigned p, const unsigned s) {
    2138       14448 :   if(s==0) return p;
    2139        1512 :   return p-seg_last[s-1];
    2140             : }
    2141             : 
    2142           0 : void CS2Backbone::debug_report() {
    2143             :   printf("\t CS2Backbone Initialization report: \n");
    2144             :   printf("\t -------------------------------\n");
    2145           0 :   printf("\t Number of segments: %u\n", static_cast<unsigned>(atom.size()));
    2146             :   printf("\t Segments size:      ");
    2147           0 :   for(unsigned i=0; i<atom.size(); i++) {printf("%u ", static_cast<unsigned>(atom[i].size()));} printf("\n");
    2148             :   printf("\t%8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s \n",
    2149             :          "Seg","N","AA","Prev","Curr","Next","SC","XD1","XD2","Phi","Psi","Chi1");
    2150           0 :   for(unsigned i=0; i<atom.size(); i++) {
    2151           0 :     for(unsigned j=0; j<atom[i].size(); j++) {
    2152           0 :       printf("\t%8u %8u %8s %8u %8u %8u %8u %8u %8u %8u %8u %8u \n",
    2153             :              i+1, j+1,
    2154             :              atom[i][j].res_name.c_str(),
    2155             :              (unsigned)atom[i][j].prev.size(),
    2156             :              (unsigned)atom[i][j].curr.size(),
    2157             :              (unsigned)atom[i][j].next.size(),
    2158             :              (unsigned)atom[i][j].side_chain.size(),
    2159             :              (unsigned)atom[i][j].xd1.size(),
    2160             :              (unsigned)atom[i][j].xd2.size(),
    2161             :              (unsigned)atom[i][j].phi.size(),
    2162             :              (unsigned)atom[i][j].psi.size(),
    2163             :              (unsigned)atom[i][j].chi1.size());
    2164             : 
    2165           0 :       for(unsigned k=0; k<atom[i][j].prev.size(); k++) { printf("%8i ", atom[i][j].prev[k]);} printf("\n");
    2166           0 :       for(unsigned k=0; k<atom[i][j].curr.size(); k++) { printf("%8i ", atom[i][j].curr[k]);} printf("\n");
    2167           0 :       for(unsigned k=0; k<atom[i][j].next.size(); k++) { printf("%8i ", atom[i][j].next[k]);} printf("\n");
    2168           0 :       for(unsigned k=0; k<atom[i][j].side_chain.size(); k++) { printf("%8i ", atom[i][j].side_chain[k]);} printf("\n");
    2169           0 :       for(unsigned k=0; k<atom[i][j].xd1.size(); k++) { printf("%8i ", atom[i][j].xd1[k]);} printf("\n");
    2170           0 :       for(unsigned k=0; k<atom[i][j].xd2.size(); k++) { printf("%8i ", atom[i][j].xd2[k]);} printf("\n");
    2171           0 :       for(unsigned k=0; k<atom[i][j].phi.size(); k++) { printf("%8i ", atom[i][j].phi[k]);} printf("\n");
    2172           0 :       for(unsigned k=0; k<atom[i][j].psi.size(); k++) { printf("%8i ", atom[i][j].psi[k]);} printf("\n");
    2173           0 :       for(unsigned k=0; k<atom[i][j].chi1.size(); k++) { printf("%8i ", atom[i][j].chi1[k]);} printf("\n");
    2174             : 
    2175             :     }
    2176             :   }
    2177             : 
    2178             :   printf("\t Rings: \n");
    2179             :   printf("\t ------ \n");
    2180           0 :   printf("\t Number of rings: %u\n", static_cast<unsigned>(ringInfo.size()));
    2181             :   printf("\t%8s %8s %8s %8s\n", "Num","Type","RType","N.atoms");
    2182           0 :   for(unsigned i=0; i<ringInfo.size(); i++) {
    2183           0 :     printf("\t%8u %8u %8u \n",i+1,ringInfo[i].rtype,ringInfo[i].numAtoms);
    2184           0 :     for(unsigned j=0; j<ringInfo[i].numAtoms; j++) {printf("%8u ", ringInfo[i].atom[j]);} printf("\n");
    2185             :   }
    2186           0 : }
    2187             : 
    2188      816690 : void CS2Backbone::xdist_name_map(string & name) {
    2189     1633380 :   if((name == "OT1")||(name == "OC1")) name = "O";
    2190     2450070 :   else if ((name == "HN") || (name == "HT1") || (name == "H1")) name = "H";
    2191     1620094 :   else if ((name == "CG1")|| (name == "OG")||
    2192     1624000 :            (name == "SG") || (name == "OG1")) name = "CG";
    2193     1595790 :   else if ((name == "HA1")|| (name == "HA3")) name = "HA";
    2194      816690 : }
    2195             : 
    2196          14 : void CS2Backbone::update() {
    2197             :   // write status file
    2198          28 :   if(getWstride()>0&& (getStep()%getWstride()==0 || getCPT()) ) writeStatus();
    2199          14 : }
    2200             : 
    2201             : }
    2202        4839 : }

Generated by: LCOV version 1.13