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 170 : void PDB2Constant::registerKeywords(Keywords& keys) { 49 170 : ActionShortcut::registerKeywords( keys ); 50 340 : keys.add("compulsory","REFERENCE","a file in pdb format containing the reference structure"); 51 340 : 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 340 : keys.addFlag("NOARGS",false,"the arguments that are being read from the PDB file are not in the plumed input"); 53 340 : keys.add("optional","ARG","read this single argument from the input rather than the atomic structure"); 54 170 : keys.setValueDescription("a value that is constructed from the information in the PDB file"); 55 170 : keys.needsAction("CONSTANT"); 56 170 : } 57 : 58 115 : PDB2Constant::PDB2Constant(const ActionOptions& ao): 59 : Action(ao), 60 115 : ActionShortcut(ao) { 61 : std::string input; 62 115 : parse("REFERENCE",input); 63 : unsigned frame; 64 115 : parse("NUMBER",frame); 65 115 : bool noargs=false; 66 : std::vector<std::string> argn; 67 230 : parseVector("ARG",argn); 68 : std::vector<Value*> theargs; 69 115 : if( argn.size()>0 ) { 70 75 : parseFlag("NOARGS",noargs); 71 75 : if( !noargs ) { 72 73 : ActionWithArguments::interpretArgumentList( argn, plumed.getActionSet(), this, theargs ); 73 2 : } else if( argn.size()>1 ) { 74 0 : error("can only read one argument at a time from input pdb file"); 75 : } else { 76 2 : log.printf(" reading argument %s from file \n", argn[0].c_str() ); 77 : } 78 : } 79 115 : if( theargs.size()>1 ) { 80 0 : error("can only read one argument at a time from input pdb file"); 81 : } 82 : 83 115 : FILE* fp=std::fopen(input.c_str(),"r"); 84 : bool do_read=true; 85 : std::vector<double> vals; 86 115 : if(!fp) { 87 0 : plumed_merror("could not open reference file " + input); 88 : } 89 115 : unsigned natoms=0, nframes=0; 90 : 91 2235 : while ( do_read ) { 92 2235 : PDB mypdb; 93 2235 : do_read=mypdb.readFromFilepointer(fp,plumed.usingNaturalUnits(),0.1/plumed.getUnits().getLength()); 94 2235 : if( !do_read && nframes>0 ) { 95 : break ; 96 : } 97 : 98 2120 : if( natoms==0 ) { 99 1378 : natoms = mypdb.getPositions().size(); 100 742 : } else if( mypdb.getPositions().size()!=natoms ) { 101 0 : plumed_merror("mismatch between sizes of reference configurations"); 102 : } 103 : 104 2120 : if( nframes+1==frame || frame==0 ) { 105 1642 : std::vector<double> align( mypdb.getOccupancy() ); 106 : double asum=0; 107 10326 : for(unsigned i=0; i<align.size(); ++i) { 108 8684 : asum += align[i]; 109 : } 110 1642 : if( asum>epsilon ) { 111 674 : double iasum = 1 / asum; 112 9358 : for(unsigned i=0; i<align.size(); ++i) { 113 8684 : align[i] *= iasum; 114 : } 115 968 : } else if( mypdb.size()>0 ) { 116 0 : double iasum = 1 / mypdb.size(); 117 0 : for(unsigned i=0; i<align.size(); ++i) { 118 0 : align[i] = iasum; 119 : } 120 : } 121 1642 : Vector center; 122 1642 : center.zero(); 123 10326 : for(unsigned i=0; i<mypdb.getPositions().size(); ++i) { 124 8684 : center += align[i]*mypdb.getPositions()[i]; 125 : } 126 : 127 1642 : if( theargs.size()==0 && argn.size()==0 ) { 128 1688 : for(unsigned j=0; j<3; ++j) { 129 17490 : for(unsigned i=0; i<mypdb.getPositions().size(); ++i) { 130 16224 : vals.push_back( mypdb.getPositions()[i][j] - center[j] ); 131 : } 132 : } 133 1220 : } else if( noargs ) { 134 20 : std::vector<double> argvals( 1 ); 135 20 : if( !mypdb.getArgumentValue(argn[0], argvals ) ) { 136 0 : error("argument " + argn[0] + " was not set in pdb input"); 137 : } 138 20 : vals.push_back( argvals[0] ); 139 : } else { 140 1200 : std::vector<double> argvals( theargs[0]->getNumberOfValues() ); 141 1200 : if( !mypdb.getArgumentValue(theargs[0]->getName(), argvals ) ) { 142 0 : error("argument " + theargs[0]->getName() + " was not set in pdb input"); 143 : } 144 2402 : for(unsigned i=0; i<argvals.size(); ++i) { 145 1202 : vals.push_back( argvals[i] ); 146 : } 147 : } 148 : } 149 2120 : nframes++; 150 2235 : } 151 115 : if( frame>0 ) { 152 68 : nframes=1; 153 : } 154 115 : std::fclose(fp); 155 : std::string rnum; 156 115 : plumed_assert( vals.size()>0 ); 157 115 : Tools::convert( vals[0], rnum ); 158 115 : std::string valstr = " VALUES=" + rnum; 159 17446 : for(unsigned i=1; i<vals.size(); ++i) { 160 17331 : Tools::convert( vals[i], rnum ); 161 34662 : valstr += "," + rnum; 162 : } 163 115 : if( vals.size()>nframes ) { 164 : std::string nc, nr; 165 41 : Tools::convert( nframes, nr ); 166 41 : Tools::convert( vals.size()/nframes, nc ); 167 82 : readInputLine( getShortcutLabel() + ": CONSTANT NROWS=" + nr + " NCOLS=" + nc + valstr ); 168 : } else { 169 148 : readInputLine( getShortcutLabel() + ": CONSTANT" + valstr ); 170 : } 171 230 : } 172 : 173 : } 174 : }