Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2015-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 "core/ActionSet.h" 27 : 28 : //+PLUMEDOC ANALYSIS COLLECT_FRAMES 29 : /* 30 : This allows you to convert a trajectory and a dissimilarity matrix into a dissimilarity object 31 : 32 : \par Examples 33 : 34 : */ 35 : //+ENDPLUMEDOC 36 : 37 : namespace PLMD { 38 : namespace landmarks { 39 : 40 : class CollectFrames : public ActionShortcut { 41 : private: 42 : std::string fixArgumentName( const std::string& argin ); 43 : public: 44 : static void registerKeywords( Keywords& keys ); 45 : explicit CollectFrames( const ActionOptions& ao ); 46 : }; 47 : 48 : PLUMED_REGISTER_ACTION(CollectFrames,"COLLECT_FRAMES") 49 : 50 31 : void CollectFrames::registerKeywords( Keywords& keys ) { 51 31 : ActionShortcut::registerKeywords( keys ); 52 62 : keys.add("compulsory","STRIDE","1","the frequency with which data should be stored for analysis. By default data is collected on every step"); 53 62 : keys.add("compulsory","CLEAR","0","the frequency with which data should all be deleted and restarted"); 54 62 : keys.add("compulsory","ALIGN","OPTIMAL","if storing atoms how would you like the alignment to be done can be SIMPLE/OPTIMAL"); 55 62 : keys.add("optional","ARG","the arguments you would like to collect"); 56 62 : keys.add("optional","ATOMS","list of atomic positions that you would like to collect and store for later analysis"); 57 62 : keys.add("optional","LOGWEIGHTS","list of actions that calculates log weights that should be used to weight configurations when calculating averages"); 58 62 : keys.addOutputComponent("data","default","the data that is being collected by this action"); 59 62 : keys.addOutputComponent("logweights","default","the logarithms of the weights of the data points"); 60 31 : keys.needsAction("POSITION"); 61 31 : keys.needsAction("CONCATENATE"); 62 31 : keys.needsAction("MEAN"); 63 31 : keys.needsAction("CUSTOM"); 64 31 : keys.needsAction("CONCATENATE"); 65 31 : keys.needsAction("COLLECT"); 66 31 : keys.needsAction("TRANSPOSE"); 67 31 : keys.needsAction("RMSD_VECTOR"); 68 31 : keys.needsAction("COMBINE"); 69 31 : keys.needsAction("VSTACK"); 70 31 : keys.needsAction("CONSTANT"); 71 31 : } 72 : 73 48 : std::string CollectFrames::fixArgumentName( const std::string& argin ) { 74 48 : std::string argout = argin; 75 48 : std::size_t dot=argin.find("."); 76 48 : if( dot!=std::string::npos ) { 77 8 : argout = argin.substr(0,dot) + "_" + argin.substr(dot+1); 78 : } 79 48 : return argout; 80 : } 81 : 82 19 : CollectFrames::CollectFrames( const ActionOptions& ao ): 83 : Action(ao), 84 19 : ActionShortcut(ao) { 85 : std::string stride, clearstride; 86 19 : parse("STRIDE",stride); 87 38 : parse("CLEAR",clearstride); 88 : std::vector<std::string> argn; 89 38 : parseVector("ARG",argn); 90 : std::vector<Value*> theargs; 91 19 : ActionWithArguments::interpretArgumentList( argn, plumed.getActionSet(), this, theargs ); 92 : std::string indices; 93 38 : parse("ATOMS",indices); 94 19 : if( theargs.size()==0 && indices.length()==0 ) { 95 0 : error("no arguments or atoms were specified for collection"); 96 : } 97 : 98 : // Create the values to collect the atomic positions 99 19 : if( indices.length()>0 ) { 100 : // Collect reference position 101 12 : readInputLine( getShortcutLabel() + "_getposx: POSITION ATOMS=" + indices ); 102 : std::string align; 103 6 : parse("ALIGN",align); 104 12 : readInputLine( getShortcutLabel() + "_getpos: CONCATENATE ARG=" + getShortcutLabel() + "_getposx.x," + getShortcutLabel() + "_getposx.y," + getShortcutLabel() + "_getposx.z"); 105 : // Find atomic center 106 12 : readInputLine( getShortcutLabel() + "_cposx: MEAN ARG=" + getShortcutLabel() + "_getposx.x PERIODIC=NO"); 107 12 : readInputLine( getShortcutLabel() + "_cposy: MEAN ARG=" + getShortcutLabel() + "_getposx.y PERIODIC=NO"); 108 12 : readInputLine( getShortcutLabel() + "_cposz: MEAN ARG=" + getShortcutLabel() + "_getposx.z PERIODIC=NO"); 109 : // Subtract atomimc center 110 12 : readInputLine( getShortcutLabel() + "_refx: CUSTOM ARG=" + getShortcutLabel() + "_getposx.x," + getShortcutLabel() + "_cposx FUNC=x-y PERIODIC=NO"); 111 12 : readInputLine( getShortcutLabel() + "_refy: CUSTOM ARG=" + getShortcutLabel() + "_getposx.y," + getShortcutLabel() + "_cposy FUNC=x-y PERIODIC=NO"); 112 12 : readInputLine( getShortcutLabel() + "_refz: CUSTOM ARG=" + getShortcutLabel() + "_getposx.z," + getShortcutLabel() + "_cposz FUNC=x-y PERIODIC=NO"); 113 12 : readInputLine( getShortcutLabel() + "_ref: CONCATENATE ARG=" + getShortcutLabel() + "_refx," + getShortcutLabel() + "_refy," + getShortcutLabel() + "_refz"); 114 : // Store the reference position in a collect action 115 12 : readInputLine( getShortcutLabel() + "_refpos: COLLECT TYPE=matrix ARG=" + getShortcutLabel() + "_ref STRIDE=" + clearstride + " CLEAR=" + clearstride ); 116 12 : readInputLine( getShortcutLabel() + "_refposT: TRANSPOSE ARG=" + getShortcutLabel() + "_refpos"); 117 : // Calculate the RMSD between the instaneous position and the reference position 118 12 : readInputLine( getShortcutLabel() + "_rmsd: RMSD_VECTOR ARG=" + getShortcutLabel() + "_getpos," + getShortcutLabel() + "_refpos DISPLACEMENT SQUARED TYPE=" + align ); 119 : // Add the reference position to the RMSD displacement 120 12 : readInputLine( getShortcutLabel() + "_fpos: COMBINE ARG=" + getShortcutLabel() + "_refposT," + getShortcutLabel() + "_rmsd.disp PERIODIC=NO"); 121 : // Store the reference data 122 6 : std::string suffix = "_atomdata"; 123 6 : if( theargs.size()==0 ) { 124 : suffix = "_data"; 125 : } 126 12 : readInputLine( getShortcutLabel() + suffix + ": COLLECT TYPE=matrix ARG=" + getShortcutLabel() + "_fpos STRIDE=" + stride + " CLEAR=" + clearstride ); 127 : } 128 : 129 : // Create all the collect actions for arguments 130 43 : for(unsigned i=0; i<theargs.size(); ++i) { 131 24 : if( theargs[i]->getNumberOfValues()!=theargs[0]->getNumberOfValues() ) { 132 0 : error("mismatch between number of arguments calculated by each collected argument"); 133 : } 134 48 : readInputLine( getShortcutLabel() + "_" + fixArgumentName( theargs[i]->getName() ) + ": COLLECT ARG=" + theargs[i]->getName() + " STRIDE=" + stride + " CLEAR=" + clearstride ); 135 : } 136 : // Make a list of collect actions 137 19 : if( theargs.size()>0 ) { 138 26 : std::string allcol = getShortcutLabel() + "_" + fixArgumentName( theargs[0]->getName() ); 139 24 : for(unsigned i=1; i<theargs.size(); ++i) { 140 22 : allcol += "," + getShortcutLabel() + "_" + fixArgumentName( theargs[i]->getName() ); 141 : } 142 : // And transfer everything to a matrix 143 13 : std::string suffix = "_argdata"; 144 13 : if( indices.length()==0 ) { 145 : suffix = "_data"; 146 : } 147 26 : readInputLine( getShortcutLabel() + suffix + ": VSTACK ARG=" + allcol ); 148 : } 149 : // Merge all the collected data together into a single matrix 150 19 : if( theargs.size()>0 && indices.length()>0 ) { 151 0 : readInputLine( getShortcutLabel() + "_data: CONCATENATE MATRIX11=" + getShortcutLabel() + "_atomdata MATRIX12=" + getShortcutLabel() + "_argdata"); 152 : } 153 : 154 : // Now get the logweights 155 : std::vector<std::string> logw; 156 38 : parseVector("LOGWEIGHTS",logw); 157 : std::vector<Value*> thew; 158 19 : if( logw.size()>0 ) { 159 0 : ActionWithArguments::interpretArgumentList( logw, plumed.getActionSet(), this, thew ); 160 : } 161 19 : if( logw.size()>1 ) { 162 0 : error("maximum of one argument should be specified for logweights"); 163 : } 164 : 165 19 : if( logw.size()==0 ) { 166 19 : std::string zeros="0"; 167 19 : if( theargs.size()>0 ) { 168 13 : for(unsigned i=1; i<theargs[0]->getNumberOfValues(); ++i) { 169 : zeros += ",0"; 170 : } 171 : } 172 38 : readInputLine( getShortcutLabel() + "_cweight: CONSTANT VALUE=" + zeros ); 173 38 : readInputLine( getShortcutLabel() + "_logweights: COLLECT ARG=" + getShortcutLabel() + "_cweight STRIDE=" + stride + " CLEAR=" + clearstride ); 174 : } else { 175 0 : if( theargs[0]->getNumberOfValues()!=thew[0]->getNumberOfValues() ) { 176 0 : error("mismatch between number of weights and number of collected arguments"); 177 : } 178 0 : readInputLine( getShortcutLabel() + "_logweights: COLLECT ARG=" + thew[0]->getName() + " STRIDE=" + stride + " CLEAR=" + clearstride ); 179 : } 180 : // And finally create a value that contains as many ones as there are data points (this is used if we want to do Classical MDS 181 19 : readInputLine( getShortcutLabel() + "_one: CONSTANT VALUE=1"); 182 38 : readInputLine( getShortcutLabel() + "_ones: COLLECT ARG=" + getShortcutLabel() + "_one STRIDE=" + stride + " CLEAR=" + clearstride ); 183 57 : } 184 : 185 : } 186 : }