LCOV - code coverage report
Current view: top level - generic - DumpPDB.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 105 105 100.0 %
Date: 2024-10-18 13:59:31 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #include "core/ActionWithArguments.h"
      23             : #include "core/ActionWithValue.h"
      24             : #include "core/ActionAtomistic.h"
      25             : #include "core/ActionPilot.h"
      26             : #include "core/ActionRegister.h"
      27             : #include "core/PlumedMain.h"
      28             : #include "tools/OFile.h"
      29             : #include "tools/h36.h"
      30             : 
      31             : namespace PLMD {
      32             : namespace generic {
      33             : 
      34             : //+PLUMEDOC PRINTANALYSIS DUMPPDB
      35             : /*
      36             : Output PDB file.
      37             : 
      38             : 
      39             : \par Examples
      40             : 
      41             : */
      42             : //+ENDPLUMEDOC
      43             : 
      44             : class DumpPDB :
      45             :   public ActionWithArguments,
      46             :   public ActionPilot
      47             : {
      48             :   std::string fmt;
      49             :   std::string file;
      50             :   std::string description;
      51             :   std::vector<unsigned> pdb_resid_indices;
      52             :   std::vector<double> beta, occupancy;
      53             :   std::vector<std::string> argnames;
      54             :   std::vector<AtomNumber> pdb_atom_indices;
      55             :   void buildArgnames();
      56             :   void printAtom( OFile& opdbf, const unsigned& anum, const unsigned& rnum, const Vector& pos, const double& m, const double& q ) const ;
      57             : public:
      58             :   static void registerKeywords( Keywords& keys );
      59             :   explicit DumpPDB(const ActionOptions&);
      60           7 :   void calculate() override {}
      61           7 :   void apply() override {}
      62             :   void update() override ;
      63             : };
      64             : 
      65             : PLUMED_REGISTER_ACTION(DumpPDB,"DUMPPDB")
      66             : 
      67          21 : void DumpPDB::registerKeywords( Keywords& keys ) {
      68          21 :   Action::registerKeywords( keys );
      69          21 :   ActionPilot::registerKeywords( keys );
      70          21 :   ActionWithArguments::registerKeywords( keys );
      71          42 :   keys.addInputKeyword("optional","ARG","vector/matrix","the values that are being output in the PDB file");
      72          42 :   keys.add("optional","ATOMS","value containing positions of atoms that should be output");
      73          42 :   keys.add("compulsory","STRIDE","0","the frequency with which the atoms should be output");
      74          42 :   keys.add("compulsory","FILE","the name of the file on which to output these quantities");
      75          42 :   keys.add("compulsory","FMT","%f","the format that should be used to output real numbers");
      76          42 :   keys.add("compulsory","OCCUPANCY","1.0","vector of values to output in the occupancy column of the pdb file");
      77          42 :   keys.add("compulsory","BETA","1.0","vector of values to output in the beta column of the pdb file");
      78          42 :   keys.add("optional","DESCRIPTION","the title to use for your PDB output");
      79          42 :   keys.add("optional","ATOM_INDICES","the indices of the atoms in your PDB output");
      80          42 :   keys.add("optional","RESIDUE_INDICES","the indices of the residues in your PDB output");
      81          42 :   keys.add("optional","ARG_NAMES","the names of the arguments that are being output");
      82          21 : }
      83             : 
      84          15 : DumpPDB::DumpPDB(const ActionOptions&ao):
      85             :   Action(ao),
      86             :   ActionWithArguments(ao),
      87          15 :   ActionPilot(ao)
      88             : {
      89          30 :   parse("FILE",file);
      90          15 :   if(file.length()==0) error("name out output file was not specified");
      91          30 :   std::vector<std::string> atoms; parseVector("ATOMS",atoms);
      92          15 :   if( atoms.size()>0 ) {
      93           8 :     std::vector<Value*> atom_args; interpretArgumentList( atoms, plumed.getActionSet(), this, atom_args );
      94           8 :     if( atom_args.size()!=1 ) error("only one action should appear in input to atom args");
      95           8 :     std::vector<Value*> args( getArguments() ); args.push_back( atom_args[0] ); requestArguments( args );
      96          16 :     std::vector<std::string> indices; parseVector("ATOM_INDICES",indices); std::vector<Value*> xvals,yvals,zvals,masv,chargev;
      97           8 :     ActionAtomistic::getAtomValuesFromPlumedObject(plumed,xvals,yvals,zvals,masv,chargev);
      98           8 :     ActionAtomistic::interpretAtomList( indices, xvals, this, pdb_atom_indices );
      99           8 :     log.printf("  printing atoms : ");
     100         153 :     for(unsigned i=0; i<indices.size(); ++i) log.printf("%d ", pdb_atom_indices[i].serial() );
     101           8 :     log.printf("\n");
     102           8 :     if( pdb_atom_indices.size()!=atom_args[0]->getShape()[1]/3 ) error("mismatch between size of matrix containing positions and vector of atom indices");
     103           8 :     beta.resize( atom_args[0]->getShape()[1]/3 ); occupancy.resize( atom_args[0]->getShape()[1]/3 );
     104          16 :     parseVector("OCCUPANCY", occupancy ); parseVector("BETA", beta );
     105          16 :     parseVector("RESIDUE_INDICES",pdb_resid_indices);
     106           8 :     if( pdb_resid_indices.size()==0 ) {
     107           6 :       pdb_resid_indices.resize( pdb_atom_indices.size() );
     108         125 :       for(unsigned i=0; i<pdb_resid_indices.size(); ++i) pdb_resid_indices[i] = pdb_atom_indices[i].serial();
     109           2 :     } else if( pdb_resid_indices.size()!=pdb_atom_indices.size() ) error("mismatch between number of atom indices provided and number of residue indices provided");
     110           8 :   }
     111          15 :   log.printf("  printing configurations to PDB file to file named %s \n", file.c_str() );
     112          30 :   parseVector("ARG_NAMES",argnames); if( argnames.size()==0 ) buildArgnames();
     113          30 :   parse("FMT",fmt); fmt=" "+fmt;
     114          15 :   if( getStride()==0 ) { setStride(0); log.printf("  printing pdb at end of calculation \n"); }
     115             : 
     116          30 :   parse("DESCRIPTION",description);
     117          15 :   if( getPntrToArgument(0)->getRank()==0 || getPntrToArgument(0)->hasDerivatives() ) error("argument for printing of PDB should be vector or matrix");
     118          15 :   unsigned nv=getPntrToArgument(0)->getShape()[0];
     119          44 :   for(unsigned i=0; i<getNumberOfArguments(); ++i) {
     120          29 :     if( getPntrToArgument(i)->getRank()==0 || getPntrToArgument(i)->hasDerivatives() ) error("argument for printing of PDB should be vector or matrix");
     121          29 :     if( getPntrToArgument(i)->getShape()[0]!=nv ) error("for printing to pdb files all arguments must have same number of values");
     122             :   }
     123          15 : }
     124             : 
     125        2143 : void DumpPDB::printAtom( OFile& opdbf, const unsigned& anum, const unsigned& rnum, const Vector& pos, const double& m, const double& q ) const {
     126        2143 :   if( rnum>999 ) plumed_merror("atom number too large to be used as residue number");
     127        2143 :   std::array<char,6> at; const char* msg = h36::hy36encode(5,anum,&at[0]);
     128        2143 :   plumed_assert(msg==nullptr) << msg; at[5]=0; double lunits = plumed.getUnits().getLength()/0.1;
     129        2143 :   opdbf.printf("ATOM  %s  X   RES  %4u    %8.3f%8.3f%8.3f%6.2f%6.2f\n",
     130        2143 :                &at[0], rnum, lunits*pos[0], lunits*pos[1], lunits*pos[2], m, q );
     131        2143 : }
     132             : 
     133          23 : void DumpPDB::buildArgnames() {
     134          23 :   unsigned nargs = getNumberOfArguments(); if( pdb_atom_indices.size()>0 ) nargs = nargs - 1;
     135             :   if( nargs<0 ) return;
     136             : 
     137          23 :   argnames.resize(0); unsigned nvals = getPntrToArgument(0)->getShape()[0];
     138             :   if( getPntrToArgument(0)->getRank()==2 ) nvals = getPntrToArgument(0)->getShape()[0];
     139          48 :   for(unsigned i=0; i<nargs; ++i) {
     140          25 :     if( getPntrToArgument(i)->getShape()[0]!=nvals ) error("all arguments should have same number of values");
     141          25 :     if( getPntrToArgument(i)->getRank()==1 ) {
     142          17 :       argnames.push_back( getPntrToArgument(i)->getName() );
     143           8 :     } else if( getPntrToArgument(i)->getRank()==2 ) {
     144           8 :       (getPntrToArgument(i)->getPntrToAction())->getMatrixColumnTitles( argnames );
     145             :     }
     146          25 :     getPntrToArgument(i)->buildDataStore();
     147             :   }
     148             : }
     149             : 
     150          19 : void DumpPDB::update() {
     151          19 :   OFile opdbf; opdbf.link(*this);
     152          19 :   opdbf.setBackupString("analysis");
     153          19 :   opdbf.open( file );
     154          19 :   std::size_t psign=fmt.find("%"); plumed_assert( psign!=std::string::npos );
     155          38 :   std::string descr2="%s=%-" + fmt.substr(psign+1) + " ";
     156             : 
     157          19 :   unsigned totargs = 0; unsigned nvals = getPntrToArgument(0)->getShape()[0];
     158          56 :   for(unsigned i=0; i<getNumberOfArguments(); ++i) {
     159          37 :     if( getPntrToArgument(i)->getShape()[0]!=nvals ) error("all arguments should have same number of values");
     160          37 :     if( getPntrToArgument(i)->getRank()==1 ) totargs += 1;
     161          18 :     else if( getPntrToArgument(i)->getRank()==2 ) totargs += getPntrToArgument(i)->getShape()[1];
     162             :   }
     163          19 :   if( totargs!=argnames.size() ) buildArgnames();
     164             : 
     165          19 :   if( description.length()>0 ) opdbf.printf("# %s AT STEP %lld TIME %f \n", description.c_str(), getStep(), getTime() );
     166          19 :   unsigned nargs = getNumberOfArguments(), atomarg=0;
     167          19 :   if( pdb_atom_indices.size()>0 ) {
     168           9 :     if( nargs>1 ) { atomarg = nargs - 1; nargs = nargs-1; }
     169             :     else nargs = 0;
     170             :   }
     171         448 :   for(unsigned i=0; i<nvals; ++i) {
     172             :     unsigned n=0;
     173        1269 :     for(unsigned j=0; j<nargs; j++) {
     174         840 :       Value* thisarg=getPntrToArgument(j); opdbf.printf("REMARK ");
     175         840 :       if( thisarg->getRank()==1 ) {
     176         405 :         opdbf.printf( descr2.c_str(), argnames[n].c_str(), thisarg->get(i) ); n++;
     177         435 :       } else if( thisarg->getRank()==2 ) {
     178         435 :         unsigned ncols = thisarg->getShape()[1];
     179        1297 :         for(unsigned k=0; k<ncols; ++k) { opdbf.printf( descr2.c_str(), argnames[n].c_str(), thisarg->get(i*ncols+k) ); n++; }
     180             :       }
     181         840 :       opdbf.printf("\n");
     182             :     }
     183         429 :     if( pdb_atom_indices.size()>0 ) {
     184         138 :       unsigned npos = pdb_atom_indices.size(); Vector pos;
     185        2281 :       for(unsigned k=0; k<npos; ++k) {
     186        2143 :         pos[0]=getPntrToArgument(atomarg)->get(npos*(3*i+0) + k);
     187        2143 :         pos[1]=getPntrToArgument(atomarg)->get(npos*(3*i+1) + k);
     188        2143 :         pos[2]=getPntrToArgument(atomarg)->get(npos*(3*i+2) + k);
     189        2143 :         printAtom( opdbf, pdb_atom_indices[k].serial(), pdb_resid_indices[k], pos, occupancy[k], beta[k] );
     190             :       }
     191             :     }
     192         429 :     opdbf.printf("END\n");
     193             :   }
     194          19 :   opdbf.close();
     195          19 : }
     196             : 
     197             : }
     198             : }

Generated by: LCOV version 1.16