LCOV - code coverage report
Current view: top level - tools - PDB.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 221 259 85.3 %
Date: 2019-08-13 10:15:31 Functions: 36 43 83.7 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-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             : #include "PDB.h"
      23             : #include "Tools.h"
      24             : #include "Log.h"
      25             : #include "h36.h"
      26             : #include <cstdio>
      27             : #include <iostream>
      28             : #include "core/SetupMolInfo.h"
      29             : #include "Tensor.h"
      30             : 
      31             : using namespace std;
      32             : 
      33             : //+PLUMEDOC INTERNAL pdbreader
      34             : /*
      35             : PLUMED can use the PDB format in several places
      36             : 
      37             : - To read molecular structure (\ref MOLINFO).
      38             : - To read reference conformations (\ref RMSD, but also many other methods in \ref dists, \ref FIT_TO_TEMPLATE, etc).
      39             : 
      40             : The implemented PDB reader expects a file formatted correctly according to the
      41             : [PDB standard](http://www.wwpdb.org/documentation/file-format-content/format33/v3.3.html).
      42             : In particular, the following columns are read from ATOM records
      43             : \verbatim
      44             : columns | content
      45             : 1-6     | record name (ATOM or HETATM)
      46             : 7-11    | serial number of the atom (starting from 1)
      47             : 13-16   | atom name
      48             : 18-20   | residue name
      49             : 22      | chain id
      50             : 23-26   | residue number
      51             : 31-38   | x coordinate
      52             : 39-46   | y coordinate
      53             : 47-54   | z coordinate
      54             : 55-60   | occupancy
      55             : 61-66   | beta factor
      56             : \endverbatim
      57             : PLUMED parser is slightly more permissive than the official PDB format
      58             : in the fact that the format of real numbers is not fixed. In other words,
      59             : any real number that can be parsed is OK and the dot can be placed anywhere. However,
      60             : __columns are interpret strictly__. A sample PDB should look like the following
      61             : \verbatim
      62             : ATOM      2  CH3 ACE     1      12.932 -14.718  -6.016  1.00  1.00
      63             : ATOM      5  C   ACE     1      21.312  -9.928  -5.946  1.00  1.00
      64             : ATOM      9  CA  ALA     2      19.462 -11.088  -8.986  1.00  1.00
      65             : \endverbatim
      66             : 
      67             : Notice that serial numbers need not to be consecutive. In the three-line example above,
      68             : only the coordinates of three atoms are provided. This is perfectly legal and indicates PLUMED
      69             : that information about these atoms only is available. This could be both for structural
      70             : information in \ref MOLINFO, where the other atoms would have no name assigned, and for
      71             : reference structures used in \ref RMSD, where only the provided atoms would be used to compute RMSD.
      72             : 
      73             : \par Occupancy and beta factors
      74             : 
      75             : PLUMED reads also occupancy and beta factors that however are given a very special meaning.
      76             : In cases where the PDB structure is used as a reference for an alignment (that's the case
      77             : for instance in \ref RMSD and in \ref FIT_TO_TEMPLATE), the occupancy column is used
      78             : to provide the weight of each atom in the alignment. In cases where, perhaps after alignment,
      79             : the displacement between running coordinates and the provided PDB is computed, the beta factors
      80             : are used as weight for the displacement.
      81             : Since setting the weights to zero is the same as __not__ including an atom in the alignment or
      82             : displacement calculation, the two following reference files would be equivalent when used in an \ref RMSD
      83             : calculation. First file:
      84             : \verbatim
      85             : ATOM      2  CH3 ACE     1      12.932 -14.718  -6.016  1.00  1.00
      86             : ATOM      5  C   ACE     1      21.312  -9.928  -5.946  1.00  1.00
      87             : ATOM      9  CA  ALA     2      19.462 -11.088  -8.986  0.00  0.00
      88             : \endverbatim
      89             : Second file:
      90             : \verbatim
      91             : ATOM      2  CH3 ACE     1      12.932 -14.718  -6.016  1.00  1.00
      92             : ATOM      5  C   ACE     1      21.312  -9.928  -5.946  1.00  1.00
      93             : \endverbatim
      94             : However notice that many extra atoms with zero weight might slow down the calculation, so
      95             : removing lines is better than setting their weights to zero.
      96             : In addition, weights for alignment need not to be equivalent to weights for displacement.
      97             : 
      98             : \par Systems with more than 100k atoms
      99             : 
     100             : Notice that it very likely does not make any sense to compute the \ref RMSD or any other structural
     101             : deviation __using__ so many atoms. However, if the protein for which you want to compute \ref RMSD
     102             : has atoms with large serial numbers (e.g. because it is located __after__ solvent in the sorted list of atoms)
     103             : you might end up with troubles with the limitations of the PDB format. Indeed, since there are 5
     104             : columns available for atom serial number, this number cannot be larger than 99999.
     105             : In addition, providing \ref MOLINFO with names associated to atoms with a serial larger than 99999 would be impossible.
     106             : 
     107             : Since PLUMED 2.4 we allow [hybrid 36](http://cci.lbl.gov/hybrid_36/) format to be used to specify atom numbers.
     108             : This format is not particularly widespread, but has the nice feature that it provides a one-to-one mapping
     109             : between numbers up to approximately 80 millions and strings with 5 characters, plus it is backward compatible
     110             : for numbers smaller than 100000. This is not true for notations like the hex notation exported by VMD.
     111             : Using the hybrid 36 format, the ATOM records for atom ranging from 99997 to 100002 would read like these:
     112             : \verbatim
     113             : ATOM  99997  Ar      X   1      45.349  38.631  15.116  1.00  1.00
     114             : ATOM  99998  Ar      X   1      46.189  38.631  15.956  1.00  1.00
     115             : ATOM  99999  Ar      X   1      46.189  39.471  15.116  1.00  1.00
     116             : ATOM  A0000  Ar      X   1      45.349  39.471  15.956  1.00  1.00
     117             : ATOM  A0000  Ar      X   1      45.349  38.631  16.796  1.00  1.00
     118             : ATOM  A0001  Ar      X   1      46.189  38.631  17.636  1.00  1.00
     119             : \endverbatim
     120             : There are tools that can be found to translate from integers to strings and back using hybrid 36 format
     121             : (a simple python script can be found [here](https://sourceforge.net/p/cctbx/code/HEAD/tree/trunk/iotbx/pdb/hybrid_36.py)).
     122             : In addition, as of PLUMED 2.5, we provide a \ref pdbrenumber "command line tool" that can be used to renumber atoms in a PDB file.
     123             : 
     124             : */
     125             : //+ENDPLUMEDOC
     126             : 
     127             : 
     128             : namespace PLMD {
     129             : 
     130          27 : void PDB::setAtomNumbers( const std::vector<AtomNumber>& atoms ) {
     131          54 :   positions.resize( atoms.size() ); occupancy.resize( atoms.size() );
     132          54 :   beta.resize( atoms.size() ); numbers.resize( atoms.size() );
     133         786 :   for(unsigned i=0; i<atoms.size(); ++i) { numbers[i]=atoms[i]; beta[i]=1.0; occupancy[i]=1.0; }
     134          27 : }
     135             : 
     136          34 : void PDB::setArgumentNames( const std::vector<std::string>& argument_names ) {
     137          34 :   argnames.resize( argument_names.size() );
     138         196 :   for(unsigned i=0; i<argument_names.size(); ++i) {
     139             :     argnames[i]=argument_names[i];
     140          64 :     arg_data.insert( std::pair<std::string,double>( argnames[i], 0.0 ) );
     141             :   }
     142          34 : }
     143             : 
     144     1504260 : bool PDB::getArgumentValue( const std::string& name, double& value ) const {
     145             :   std::map<std::string,double>::const_iterator it = arg_data.find(name);
     146     1504260 :   if( it!=arg_data.end() ) { value = it->second; return true; }
     147             :   return false;
     148             : }
     149             : 
     150      493287 : void PDB::setAtomPositions( const std::vector<Vector>& pos ) {
     151      493287 :   plumed_assert( pos.size()==positions.size() );
     152      545641 :   for(unsigned i=0; i<positions.size(); ++i) positions[i]=pos[i];
     153      493287 : }
     154             : 
     155     1502798 : void PDB::setArgumentValue( const std::string& argname, const double& val ) {
     156             :   // First set the value of the value of the argument in the map
     157     1502798 :   arg_data.find(argname)->second = val;
     158     1502798 : }
     159             : 
     160             : // bool PDB::hasRequiredProperties( const std::vector<std::string>& inproperties ){
     161             : //   bool hasprop=false;
     162             : //   for(unsigned i=0;i<remark.size();++i){
     163             : //       if( remark[i].find("PROPERTIES=")!=std::string::npos){ hasprop=true; break; }
     164             : //   }
     165             : //   if( !hasprop ){
     166             : //       std::string mypropstr="PROPERTIES=" + inproperties[0];
     167             : //       for(unsigned i=1;i<inproperties.size();++i) mypropstr += "," + inproperties[i];
     168             : //       remark.push_back( mypropstr );
     169             : //   }
     170             : //   // Now check that all required properties are there
     171             : //   for(unsigned i=0;i<inproperties.size();++i){
     172             : //       hasprop=false;
     173             : //       for(unsigned j=0;j<remark.size();++j){
     174             : //           if( remark[j].find(inproperties[i]+"=")!=std::string::npos){ hasprop=true; break; }
     175             : //       }
     176             : //       if( !hasprop ) return false;
     177             : //   }
     178             : //   return true;
     179             : // }
     180             : 
     181          17 : void PDB::addBlockEnd( const unsigned& end ) {
     182          17 :   block_ends.push_back( end );
     183          17 : }
     184             : 
     185         472 : unsigned PDB::getNumberOfAtomBlocks()const {
     186         472 :   return block_ends.size();
     187             : }
     188             : 
     189          14 : const std::vector<unsigned> & PDB::getAtomBlockEnds()const {
     190          14 :   return block_ends;
     191             : }
     192             : 
     193    23048038 : const std::vector<Vector> & PDB::getPositions()const {
     194    23048038 :   return positions;
     195             : }
     196             : 
     197           0 : void PDB::setPositions(const std::vector<Vector> &v ) {
     198           0 :   plumed_assert( v.size()==positions.size() );
     199           0 :   positions=v;
     200           0 : }
     201             : 
     202       16508 : const std::vector<double> & PDB::getOccupancy()const {
     203       16508 :   return occupancy;
     204             : }
     205             : 
     206       16508 : const std::vector<double> & PDB::getBeta()const {
     207       16508 :   return beta;
     208             : }
     209             : 
     210        1330 : void PDB::addRemark( std::vector<std::string>& v1 ) {
     211        2660 :   Tools::parse(v1,"TYPE",mtype);
     212        2660 :   Tools::parseVector(v1,"ARG",argnames);
     213        7438 :   for(unsigned i=0; i<v1.size(); ++i) {
     214        2389 :     if( v1[i].find("=")!=std::string::npos ) {
     215             :       std::size_t eq=v1[i].find_first_of('=');
     216        1864 :       std::string name=v1[i].substr(0,eq);
     217        3728 :       std::string sval=v1[i].substr(eq+1);
     218        1864 :       double val; Tools::convert( sval, val );
     219        1864 :       arg_data.insert( std::pair<std::string,double>( name, val ) );
     220             :     } else {
     221         525 :       flags.push_back(v1[i]);
     222             :     }
     223             :   }
     224        1330 : }
     225             : 
     226           8 : bool PDB::hasFlag( const std::string& fname ) const {
     227          16 :   for(unsigned i=0; i<flags.size(); ++i) {
     228           0 :     if( flags[i]==fname ) return true;
     229             :   }
     230             :   return false;
     231             : }
     232             : 
     233             : 
     234      701331 : const std::vector<AtomNumber> & PDB::getAtomNumbers()const {
     235      701331 :   return numbers;
     236             : }
     237             : 
     238           0 : const Vector & PDB::getBoxAxs()const {
     239           0 :   return BoxXYZ;
     240             : }
     241             : 
     242           0 : const Vector & PDB::getBoxAng()const {
     243           0 :   return BoxABG;
     244             : }
     245             : 
     246          12 : const Tensor & PDB::getBoxVec()const {
     247          12 :   return Box;
     248             : }
     249             : 
     250     6764682 : std::string PDB::getAtomName(AtomNumber a)const {
     251             :   const auto p=number2index.find(a);
     252     6764682 :   if(p==number2index.end()) return "";
     253    13529360 :   else return atomsymb[p->second];
     254             : }
     255             : 
     256      110010 : unsigned PDB::getResidueNumber(AtomNumber a)const {
     257             :   const auto p=number2index.find(a);
     258      110010 :   if(p==number2index.end()) return 0;
     259      220016 :   else return residue[p->second];
     260             : }
     261             : 
     262       96425 : std::string PDB::getResidueName(AtomNumber a) const {
     263             :   const auto p=number2index.find(a);
     264       96425 :   if(p==number2index.end()) return "";
     265      192846 :   else return residuenames[p->second];
     266             : }
     267             : 
     268   204174678 : unsigned PDB::size()const {
     269   204174678 :   return positions.size();
     270             : }
     271             : 
     272        2015 : bool PDB::readFromFilepointer(FILE *fp,bool naturalUnits,double scale) {
     273             :   //cerr<<file<<endl;
     274             :   bool file_is_alive=false;
     275        2015 :   if(naturalUnits) scale=1.0;
     276             :   string line;
     277             :   fpos_t pos; bool between_ters=true;
     278      151031 :   while(Tools::getline(fp,line)) {
     279             :     //cerr<<line<<"\n";
     280      148830 :     fgetpos (fp,&pos);
     281     1828058 :     while(line.length()<80) line.push_back(' ');
     282      148830 :     string record=line.substr(0,6);
     283      148830 :     string serial=line.substr(6,5);
     284      148830 :     string atomname=line.substr(12,4);
     285      148830 :     string residuename=line.substr(17,3);
     286      148830 :     string chainID=line.substr(21,1);
     287      148830 :     string resnum=line.substr(22,4);
     288      148830 :     string x=line.substr(30,8);
     289      148830 :     string y=line.substr(38,8);
     290      148830 :     string z=line.substr(46,8);
     291      148830 :     string occ=line.substr(54,6);
     292      148830 :     string bet=line.substr(60,6);
     293      148830 :     string BoxX=line.substr(6,9);
     294      148830 :     string BoxY=line.substr(15,9);
     295      148830 :     string BoxZ=line.substr(24,9);
     296      148830 :     string BoxA=line.substr(33,7);
     297      148830 :     string BoxB=line.substr(40,7);
     298      148830 :     string BoxG=line.substr(47,7);
     299      148830 :     Tools::trim(record);
     300      149202 :     if(record=="TER") { between_ters=false; block_ends.push_back( positions.size() ); }
     301      148830 :     if(record=="END") { file_is_alive=true;  break;}
     302      147134 :     if(record=="ENDMDL") { file_is_alive=true;  break;}
     303      147001 :     if(record=="REMARK") {
     304        3990 :       vector<string> v1;  v1=Tools::getWords(line.substr(6));
     305        1330 :       addRemark( v1 );
     306             :     }
     307      147001 :     if(record=="CRYST1") {
     308          56 :       Tools::convert(BoxX,BoxXYZ[0]);
     309          56 :       Tools::convert(BoxY,BoxXYZ[1]);
     310          56 :       Tools::convert(BoxZ,BoxXYZ[2]);
     311          56 :       Tools::convert(BoxA,BoxABG[0]);
     312          56 :       Tools::convert(BoxB,BoxABG[1]);
     313          56 :       Tools::convert(BoxG,BoxABG[2]);
     314          56 :       BoxXYZ*=scale;
     315          56 :       double cosA=cos(BoxABG[0]*pi/180.);
     316          56 :       double cosB=cos(BoxABG[1]*pi/180.);
     317          56 :       double cosG=cos(BoxABG[2]*pi/180.);
     318          56 :       double sinG=sin(BoxABG[2]*pi/180.);
     319          56 :       for (unsigned i=0; i<3; i++) {Box[i][0]=0.; Box[i][1]=0.; Box[i][2]=0.;}
     320          56 :       Box[0][0]=BoxXYZ[0];
     321          56 :       Box[1][0]=BoxXYZ[1]*cosG;
     322          56 :       Box[1][1]=BoxXYZ[1]*sinG;
     323          56 :       Box[2][0]=BoxXYZ[2]*cosB;
     324          56 :       Box[2][1]=(BoxXYZ[2]*BoxXYZ[1]*cosA-Box[2][0]*Box[1][0])/Box[1][1];
     325          56 :       Box[2][2]=sqrt(BoxXYZ[2]*BoxXYZ[2]-Box[2][0]*Box[2][0]-Box[2][1]*Box[2][1]);
     326             :     }
     327      148970 :     if(record=="ATOM" || record=="HETATM") {
     328             :       between_ters=true;
     329             :       AtomNumber a; unsigned resno;
     330             :       double o,b;
     331      145032 :       Vector p;
     332             :       {
     333             :         int result;
     334      145032 :         auto trimmed=serial;
     335      145032 :         Tools::trim(trimmed);
     336      145032 :         const char* errmsg = h36::hy36decode(5, trimmed.c_str(),trimmed.length(), &result);
     337      145032 :         if(errmsg) {
     338           0 :           std::string msg(errmsg);
     339           0 :           plumed_merror(msg);
     340             :         }
     341      145032 :         a.setSerial(result);
     342             :       }
     343             : 
     344      145032 :       Tools::convert(resnum,resno);
     345      145032 :       Tools::convert(occ,o);
     346      145032 :       Tools::convert(bet,b);
     347      145032 :       Tools::convert(x,p[0]);
     348      145032 :       Tools::convert(y,p[1]);
     349      145032 :       Tools::convert(z,p[2]);
     350             :       // scale into nm
     351      145032 :       p*=scale;
     352      145032 :       numbers.push_back(a);
     353      290064 :       number2index[a]=positions.size();
     354      145032 :       std::size_t startpos=atomname.find_first_not_of(" \t");
     355      145032 :       std::size_t endpos=atomname.find_last_not_of(" \t");
     356      290064 :       atomsymb.push_back( atomname.substr(startpos, endpos-startpos+1) );
     357      145032 :       residue.push_back(resno);
     358      145032 :       chain.push_back(chainID);
     359      145032 :       occupancy.push_back(o);
     360      145032 :       beta.push_back(b);
     361      145032 :       positions.push_back(p);
     362      145032 :       residuenames.push_back(residuename);
     363             :     }
     364             :   }
     365        5727 :   if( between_ters ) block_ends.push_back( positions.size() );
     366        2015 :   return file_is_alive;
     367             : }
     368             : 
     369         269 : bool PDB::read(const std::string&file,bool naturalUnits,double scale) {
     370         269 :   FILE* fp=fopen(file.c_str(),"r");
     371         269 :   if(!fp) return false;
     372         267 :   readFromFilepointer(fp,naturalUnits,scale);
     373         267 :   fclose(fp);
     374         267 :   return true;
     375             : }
     376             : 
     377         221 : void PDB::getChainNames( std::vector<std::string>& chains ) const {
     378         221 :   chains.resize(0);
     379         221 :   chains.push_back( chain[0] );
     380      413527 :   for(unsigned i=1; i<size(); ++i) {
     381     1239918 :     if( chains[chains.size()-1]!=chain[i] ) chains.push_back( chain[i] );
     382             :   }
     383         221 : }
     384             : 
     385       11565 : void PDB::getResidueRange( const std::string& chainname, unsigned& res_start, unsigned& res_end, std::string& errmsg ) const {
     386             :   bool inres=false, foundchain=false;
     387    30013040 :   for(unsigned i=0; i<size(); ++i) {
     388    60002950 :     if( chain[i]==chainname ) {
     389    26553091 :       if(!inres) {
     390       11565 :         if(foundchain) errmsg="found second start of chain named " + chainname;
     391       11565 :         res_start=residue[i];
     392             :       }
     393             :       inres=true; foundchain=true;
     394     3448384 :     } else if( inres && chain[i]!=chainname ) {
     395             :       inres=false;
     396       22148 :       res_end=residue[i-1];
     397             :     }
     398             :   }
     399       12056 :   if(inres) res_end=residue[size()-1];
     400       11565 : }
     401             : 
     402         132 : void PDB::getAtomRange( const std::string& chainname, AtomNumber& a_start, AtomNumber& a_end, std::string& errmsg ) const {
     403             :   bool inres=false, foundchain=false;
     404      175859 :   for(unsigned i=0; i<size(); ++i) {
     405      351454 :     if( chain[i]==chainname ) {
     406       38659 :       if(!inres) {
     407         132 :         if(foundchain) errmsg="found second start of chain named " + chainname;
     408         132 :         a_start=numbers[i];
     409             :       }
     410             :       inres=true; foundchain=true;
     411      137068 :     } else if( inres && chain[i]!=chainname ) {
     412             :       inres=false;
     413         116 :       a_end=numbers[i-1];
     414             :     }
     415             :   }
     416         206 :   if(inres) a_end=numbers[size()-1];
     417         132 : }
     418             : 
     419        5958 : std::string PDB::getResidueName( const unsigned& resnum ) const {
     420     7317600 :   for(unsigned i=0; i<size(); ++i) {
     421    14641158 :     if( residue[i]==resnum ) return residuenames[i];
     422             :   }
     423           0 :   return "";
     424             : }
     425             : 
     426       46556 : std::string PDB::getResidueName(const unsigned& resnum,const std::string& chainid ) const {
     427    59108755 :   for(unsigned i=0; i<size(); ++i) {
     428   118357006 :     if( residue[i]==resnum && ( chainid=="*" || chain[i]==chainid) ) return residuenames[i];
     429             :   }
     430           0 :   return "";
     431             : }
     432             : 
     433             : 
     434       13260 : AtomNumber PDB::getNamedAtomFromResidue( const std::string& aname, const unsigned& resnum ) const {
     435    16347180 :   for(unsigned i=0; i<size(); ++i) {
     436    32812980 :     if( residue[i]==resnum && atomsymb[i]==aname ) return numbers[i];
     437             :   }
     438           0 :   std::string num; Tools::convert( resnum, num );
     439           0 :   plumed_merror("residue " + num + " does not contain an atom named " + aname );
     440             :   return numbers[0]; // This is to stop compiler errors
     441             : }
     442             : 
     443        2072 : AtomNumber PDB::getNamedAtomFromResidueAndChain( const std::string& aname, const unsigned& resnum, const std::string& chainid ) const {
     444     1053924 :   for(unsigned i=0; i<size(); ++i) {
     445     2143205 :     if( residue[i]==resnum && atomsymb[i]==aname && ( chainid=="*" || chain[i]==chainid) ) return numbers[i];
     446             :   }
     447           0 :   std::string num; Tools::convert( resnum, num );
     448           0 :   plumed_merror("residue " + num + " from chain " + chainid + " does not contain an atom named " + aname );
     449             :   return numbers[0]; // This is to stop compiler errors
     450             : }
     451             : 
     452       32148 : std::vector<AtomNumber> PDB::getAtomsInResidue(const unsigned& resnum,const std::string& chainid)const {
     453             :   std::vector<AtomNumber> tmp;
     454    84002724 :   for(unsigned i=0; i<size(); ++i) {
     455   169398720 :     if( residue[i]==resnum && ( chainid=="*" || chain[i]==chainid) ) tmp.push_back(numbers[i]);
     456             :   }
     457       32148 :   if(tmp.size()==0) {
     458           0 :     std::string num; Tools::convert( resnum, num );
     459           0 :     plumed_merror("Cannot find residue " + num + " from chain " + chainid  );
     460             :   }
     461       32148 :   return tmp;
     462             : }
     463             : 
     464           0 : std::vector<AtomNumber> PDB::getAtomsInChain(const std::string& chainid)const {
     465             :   std::vector<AtomNumber> tmp;
     466           0 :   for(unsigned i=0; i<size(); ++i) {
     467           0 :     if( chainid=="*" || chain[i]==chainid ) tmp.push_back(numbers[i]);
     468             :   }
     469           0 :   if(tmp.size()==0) {
     470           0 :     plumed_merror("Cannot find atoms from chain " + chainid  );
     471             :   }
     472           0 :   return tmp;
     473             : }
     474             : 
     475        4638 : std::string PDB::getChainID(const unsigned& resnumber) const {
     476     5689172 :   for(unsigned i=0; i<size(); ++i) {
     477    11382982 :     if(resnumber==residue[i]) return chain[i];
     478             :   }
     479           0 :   plumed_merror("Not enough residues in pdb input file");
     480             : }
     481             : 
     482           0 : bool PDB::checkForResidue( const std::string& name ) const {
     483           0 :   for(unsigned i=0; i<size(); ++i) {
     484           0 :     if( residuenames[i]==name ) return true;
     485             :   }
     486             :   return false;
     487             : }
     488             : 
     489           0 : bool PDB::checkForAtom( const std::string& name ) const {
     490           0 :   for(unsigned i=0; i<size(); ++i) {
     491           0 :     if( atomsymb[i]==name ) return true;
     492             :   }
     493             :   return false;
     494             : }
     495             : 
     496           0 : Log& operator<<(Log& ostr, const PDB&  pdb) {
     497             :   char buffer[1000];
     498           0 :   for(unsigned i=0; i<pdb.positions.size(); i++) {
     499           0 :     sprintf(buffer,"ATOM %3d %8.3f %8.3f %8.3f\n",pdb.numbers[i].serial(),pdb.positions[i][0],pdb.positions[i][1],pdb.positions[i][2]);
     500           0 :     ostr<<buffer;
     501             :   }
     502           0 :   return ostr;
     503             : }
     504             : 
     505         852 : Vector PDB::getPosition(AtomNumber a)const {
     506             :   const auto p=number2index.find(a);
     507         852 :   if(p==number2index.end()) plumed_merror("atom not available");
     508        1704 :   else return positions[p->second];
     509             : }
     510             : 
     511     2539432 : std::vector<std::string> PDB::getArgumentNames()const {
     512     2539432 :   return argnames;
     513             : }
     514             : 
     515          10 : std::string PDB::getMtype() const {
     516          10 :   return mtype;
     517             : }
     518             : 
     519         497 : void PDB::print( const double& lunits, SetupMolInfo* mymoldat, OFile& ofile, const std::string& fmt ) {
     520         497 :   if( argnames.size()>0 ) {
     521         476 :     ofile.printf("REMARK ARG=%s", argnames[0].c_str() );
     522        3012 :     for(unsigned i=1; i<argnames.size(); ++i) ofile.printf(",%s",argnames[i].c_str() );
     523         476 :     ofile.printf("\n"); ofile.printf("REMARK ");
     524             :   }
     525             :   std::string descr2;
     526         497 :   if(fmt.find("-")!=std::string::npos) {
     527           0 :     descr2="%s=" + fmt + " ";
     528             :   } else {
     529             :     // This ensures numbers are left justified (i.e. next to the equals sign
     530         497 :     std::size_t psign=fmt.find("%");
     531         497 :     plumed_assert( psign!=std::string::npos );
     532        1988 :     descr2="%s=%-" + fmt.substr(psign+1) + " ";
     533             :   }
     534        4482 :   for(std::map<std::string,double>::iterator it=arg_data.begin(); it!=arg_data.end(); ++it) ofile.printf( descr2.c_str(),it->first.c_str(), it->second );
     535         497 :   if( argnames.size()>0 ) ofile.printf("\n");
     536         497 :   if( !mymoldat ) {
     537        4032 :     for(unsigned i=0; i<positions.size(); ++i) {
     538             :       std::array<char,6> at;
     539        1769 :       const char* msg = h36::hy36encode(5,numbers[i].serial(),&at[0]);
     540        1769 :       plumed_assert(msg==nullptr) << msg;
     541        1769 :       at[5]=0;
     542             :       ofile.printf("ATOM  %s  X   RES  %4u    %8.3f%8.3f%8.3f%6.2f%6.2f\n",
     543             :                    &at[0], i,
     544        5307 :                    lunits*positions[i][0], lunits*positions[i][1], lunits*positions[i][2],
     545        8845 :                    occupancy[i], beta[i] );
     546             :     }
     547             :   } else {
     548         135 :     for(unsigned i=0; i<positions.size(); ++i) {
     549             :       std::array<char,6> at;
     550          66 :       const char* msg = h36::hy36encode(5,numbers[i].serial(),&at[0]);
     551          66 :       plumed_assert(msg==nullptr) << msg;
     552          66 :       at[5]=0;
     553             :       ofile.printf("ATOM  %s %-4s %3s  %4u    %8.3f%8.3f%8.3f%6.2f%6.2f\n",
     554             :                    &at[0], mymoldat->getAtomName(numbers[i]).c_str(),
     555             :                    mymoldat->getResidueName(numbers[i]).c_str(), mymoldat->getResidueNumber(numbers[i]),
     556         198 :                    lunits*positions[i][0], lunits*positions[i][1], lunits*positions[i][2],
     557         726 :                    occupancy[i], beta[i] );
     558             :     }
     559             :   }
     560         497 :   ofile.printf("END\n");
     561         497 : }
     562             : 
     563             : 
     564        5874 : }
     565             : 

Generated by: LCOV version 1.14