Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2012-2023 The plumed team 3 : (see the PEOPLE file at the root of the distribution for a list of names) 4 : 5 : See http://www.plumed.org for more information. 6 : 7 : This file is part of plumed, version 2. 8 : 9 : plumed is free software: you can redistribute it and/or modify 10 : it under the terms of the GNU Lesser General Public License as published by 11 : the Free Software Foundation, either version 3 of the License, or 12 : (at your option) any later version. 13 : 14 : plumed is distributed in the hope that it will be useful, 15 : but WITHOUT ANY WARRANTY; without even the implied warranty of 16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 : GNU Lesser General Public License for more details. 18 : 19 : You should have received a copy of the GNU Lesser General Public License 20 : along with plumed. If not, see <http://www.gnu.org/licenses/>. 21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 22 : #include "core/ActionShortcut.h" 23 : #include "core/ActionRegister.h" 24 : #include "core/ActionWithArguments.h" 25 : #include "core/PlumedMain.h" 26 : #include "tools/PDB.h" 27 : 28 : namespace PLMD { 29 : namespace generic { 30 : 31 : //+PLUMEDOC COLVAR PDB2CONSTANT 32 : /* 33 : Create a constant value from a PDB input file 34 : 35 : \par Examples 36 : 37 : */ 38 : //+ENDPLUMEDOC 39 : 40 : class PDB2Constant : public ActionShortcut { 41 : public: 42 : static void registerKeywords(Keywords& keys); 43 : explicit PDB2Constant(const ActionOptions&); 44 : }; 45 : 46 : PLUMED_REGISTER_ACTION(PDB2Constant,"PDB2CONSTANT") 47 : 48 168 : void PDB2Constant::registerKeywords(Keywords& keys) { 49 168 : ActionShortcut::registerKeywords( keys ); 50 336 : keys.add("compulsory","REFERENCE","a file in pdb format containing the reference structure"); 51 336 : keys.add("compulsory","NUMBER","0","if there are multiple structures in the pdb file you can specify that you want the RMSD from a specific structure by specifying its place in the file here. If NUMBER=0 then the RMSD from all structures are computed"); 52 336 : keys.addFlag("NOARGS",false,"the arguments that are being read from the PDB file are not in the plumed input"); 53 336 : keys.addInputKeyword("optional","ARG","scalar/vector","read this single argument from the input rather than the atomic structure"); 54 336 : keys.setValueDescription("scalar/vector/matrix","a value that is constructed from the information in the PDB file"); 55 168 : keys.needsAction("CONSTANT"); 56 168 : } 57 : 58 115 : PDB2Constant::PDB2Constant(const ActionOptions& ao): 59 : Action(ao), 60 115 : ActionShortcut(ao) 61 : { 62 115 : std::string input; parse("REFERENCE",input); 63 230 : unsigned frame; parse("NUMBER",frame); bool noargs=false; 64 230 : std::vector<std::string> argn; parseVector("ARG",argn); std::vector<Value*> theargs; 65 115 : if( argn.size()>0 ) { 66 75 : parseFlag("NOARGS",noargs); 67 75 : if( !noargs ) ActionWithArguments::interpretArgumentList( argn, plumed.getActionSet(), this, theargs ); 68 2 : else if( argn.size()>1 ) error("can only read one argument at a time from input pdb file"); 69 2 : else log.printf(" reading argument %s from file \n", argn[0].c_str() ); 70 : } 71 115 : if( theargs.size()>1 ) error("can only read one argument at a time from input pdb file"); 72 : 73 115 : FILE* fp=std::fopen(input.c_str(),"r"); bool do_read=true; std::vector<double> vals; 74 115 : if(!fp) plumed_merror("could not open reference file " + input); unsigned natoms=0, nframes=0; 75 : 76 2235 : while ( do_read ) { 77 2235 : PDB mypdb; do_read=mypdb.readFromFilepointer(fp,plumed.usingNaturalUnits(),0.1/plumed.getUnits().getLength()); 78 2235 : if( !do_read && nframes>0 ) break ; 79 : 80 2120 : if( natoms==0 ) natoms = mypdb.getPositions().size(); 81 742 : else if( mypdb.getPositions().size()!=natoms ) plumed_merror("mismatch between sizes of reference configurations"); 82 : 83 2120 : if( nframes+1==frame || frame==0 ) { 84 1642 : std::vector<double> align( mypdb.getOccupancy() ); 85 10326 : double asum=0; for(unsigned i=0; i<align.size(); ++i) asum += align[i]; 86 1642 : if( asum>epsilon ) { 87 9358 : double iasum = 1 / asum; for(unsigned i=0; i<align.size(); ++i) align[i] *= iasum; 88 968 : } else if( mypdb.size()>0 ) { 89 0 : double iasum = 1 / mypdb.size(); for(unsigned i=0; i<align.size(); ++i) align[i] = iasum; 90 : } 91 10326 : Vector center; center.zero(); for(unsigned i=0; i<mypdb.getPositions().size(); ++i) center += align[i]*mypdb.getPositions()[i]; 92 : 93 1642 : if( theargs.size()==0 && argn.size()==0 ) { 94 1688 : for(unsigned j=0; j<3; ++j) { 95 17490 : for(unsigned i=0; i<mypdb.getPositions().size(); ++i) vals.push_back( mypdb.getPositions()[i][j] - center[j] ); 96 : } 97 1220 : } else if( noargs ) { 98 20 : std::vector<double> argvals( 1 ); 99 20 : if( !mypdb.getArgumentValue(argn[0], argvals ) ) error("argument " + argn[0] + " was not set in pdb input"); 100 20 : vals.push_back( argvals[0] ); 101 : } else { 102 1200 : std::vector<double> argvals( theargs[0]->getNumberOfValues() ); 103 1200 : if( !mypdb.getArgumentValue(theargs[0]->getName(), argvals ) ) error("argument " + theargs[0]->getName() + " was not set in pdb input"); 104 2402 : for(unsigned i=0; i<argvals.size(); ++i) vals.push_back( argvals[i] ); 105 : } 106 : } 107 2120 : nframes++; 108 2235 : } 109 115 : if( frame>0 ) nframes=1; 110 115 : std::fclose(fp); std::string rnum; plumed_assert( vals.size()>0 ); 111 115 : Tools::convert( vals[0], rnum ); std::string valstr = " VALUES=" + rnum; 112 17446 : for(unsigned i=1; i<vals.size(); ++i) { Tools::convert( vals[i], rnum ); valstr += "," + rnum; } 113 115 : if( vals.size()>nframes ) { 114 41 : std::string nc, nr; Tools::convert( nframes, nr ); Tools::convert( vals.size()/nframes, nc ); 115 82 : readInputLine( getShortcutLabel() + ": CONSTANT NROWS=" + nr + " NCOLS=" + nc + valstr ); 116 148 : } else readInputLine( getShortcutLabel() + ": CONSTANT" + valstr ); 117 230 : } 118 : 119 : } 120 : }