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.addInputKeyword("optional","ARG","scalar/vector","the labels of the values whose time series you would like to collect for later analysis"); 53 62 : keys.add("compulsory","STRIDE","1","the frequency with which data should be stored for analysis. By default data is collected on every step"); 54 62 : keys.add("compulsory","CLEAR","0","the frequency with which data should all be deleted and restarted"); 55 62 : keys.add("compulsory","ALIGN","OPTIMAL","if storing atoms how would you like the alignment to be done can be SIMPLE/OPTIMAL"); 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","matrix","the data that is being collected by this action"); 59 62 : keys.addOutputComponent("logweights","default","vector","the logarithms of the weights of the data points"); 60 124 : keys.needsAction("POSITION"); keys.needsAction("CONCATENATE"); keys.needsAction("MEAN"); keys.needsAction("CUSTOM"); 61 124 : keys.needsAction("CONCATENATE"); keys.needsAction("COLLECT"); keys.needsAction("TRANSPOSE"); keys.needsAction("RMSD_VECTOR"); 62 93 : keys.needsAction("COMBINE"); keys.needsAction("VSTACK"); keys.needsAction("CONSTANT"); 63 31 : } 64 : 65 48 : std::string CollectFrames::fixArgumentName( const std::string& argin ) { 66 48 : std::string argout = argin; std::size_t dot=argin.find("."); 67 52 : if( dot!=std::string::npos ) argout = argin.substr(0,dot) + "_" + argin.substr(dot+1); 68 48 : return argout; 69 : } 70 : 71 19 : CollectFrames::CollectFrames( const ActionOptions& ao ): 72 : Action(ao), 73 19 : ActionShortcut(ao) 74 : { 75 57 : std::string stride, clearstride; parse("STRIDE",stride); parse("CLEAR",clearstride); 76 38 : std::vector<std::string> argn; parseVector("ARG",argn); std::vector<Value*> theargs; 77 19 : ActionWithArguments::interpretArgumentList( argn, plumed.getActionSet(), this, theargs ); 78 38 : std::string indices; parse("ATOMS",indices); 79 19 : if( theargs.size()==0 && indices.length()==0 ) error("no arguments or atoms were specified for collection"); 80 : 81 : // Create the values to collect the atomic positions 82 19 : if( indices.length()>0 ) { 83 : // Collect reference position 84 12 : readInputLine( getShortcutLabel() + "_getposx: POSITION ATOMS=" + indices ); std::string align; parse("ALIGN",align); 85 12 : readInputLine( getShortcutLabel() + "_getpos: CONCATENATE ARG=" + getShortcutLabel() + "_getposx.x," + getShortcutLabel() + "_getposx.y," + getShortcutLabel() + "_getposx.z"); 86 : // Find atomic center 87 12 : readInputLine( getShortcutLabel() + "_cposx: MEAN ARG=" + getShortcutLabel() + "_getposx.x PERIODIC=NO"); 88 12 : readInputLine( getShortcutLabel() + "_cposy: MEAN ARG=" + getShortcutLabel() + "_getposx.y PERIODIC=NO"); 89 12 : readInputLine( getShortcutLabel() + "_cposz: MEAN ARG=" + getShortcutLabel() + "_getposx.z PERIODIC=NO"); 90 : // Subtract atomimc center 91 12 : readInputLine( getShortcutLabel() + "_refx: CUSTOM ARG=" + getShortcutLabel() + "_getposx.x," + getShortcutLabel() + "_cposx FUNC=x-y PERIODIC=NO"); 92 12 : readInputLine( getShortcutLabel() + "_refy: CUSTOM ARG=" + getShortcutLabel() + "_getposx.y," + getShortcutLabel() + "_cposy FUNC=x-y PERIODIC=NO"); 93 12 : readInputLine( getShortcutLabel() + "_refz: CUSTOM ARG=" + getShortcutLabel() + "_getposx.z," + getShortcutLabel() + "_cposz FUNC=x-y PERIODIC=NO"); 94 12 : readInputLine( getShortcutLabel() + "_ref: CONCATENATE ARG=" + getShortcutLabel() + "_refx," + getShortcutLabel() + "_refy," + getShortcutLabel() + "_refz"); 95 : // Store the reference position in a collect action 96 12 : readInputLine( getShortcutLabel() + "_refpos: COLLECT TYPE=matrix ARG=" + getShortcutLabel() + "_ref STRIDE=" + clearstride + " CLEAR=" + clearstride ); 97 12 : readInputLine( getShortcutLabel() + "_refposT: TRANSPOSE ARG=" + getShortcutLabel() + "_refpos"); 98 : // Calculate the RMSD between the instaneous position and the reference position 99 12 : readInputLine( getShortcutLabel() + "_rmsd: RMSD_VECTOR ARG=" + getShortcutLabel() + "_getpos," + getShortcutLabel() + "_refpos DISPLACEMENT SQUARED TYPE=" + align ); 100 : // Add the reference position to the RMSD displacement 101 12 : readInputLine( getShortcutLabel() + "_fpos: COMBINE ARG=" + getShortcutLabel() + "_refposT," + getShortcutLabel() + "_rmsd.disp PERIODIC=NO"); 102 : // Store the reference data 103 6 : std::string suffix = "_atomdata"; if( theargs.size()==0 ) suffix = "_data"; 104 12 : readInputLine( getShortcutLabel() + suffix + ": COLLECT TYPE=matrix ARG=" + getShortcutLabel() + "_fpos STRIDE=" + stride + " CLEAR=" + clearstride ); 105 : } 106 : 107 : // Create all the collect actions for arguments 108 43 : for(unsigned i=0; i<theargs.size(); ++i) { 109 24 : if( theargs[i]->getNumberOfValues()!=theargs[0]->getNumberOfValues() ) error("mismatch between number of arguments calculated by each collected argument"); 110 48 : readInputLine( getShortcutLabel() + "_" + fixArgumentName( theargs[i]->getName() ) + ": COLLECT ARG=" + theargs[i]->getName() + " STRIDE=" + stride + " CLEAR=" + clearstride ); 111 : } 112 : // Make a list of collect actions 113 19 : if( theargs.size()>0 ) { 114 26 : std::string allcol = getShortcutLabel() + "_" + fixArgumentName( theargs[0]->getName() ); 115 24 : for(unsigned i=1; i<theargs.size(); ++i) allcol += "," + getShortcutLabel() + "_" + fixArgumentName( theargs[i]->getName() ); 116 : // And transfer everything to a matrix 117 13 : std::string suffix = "_argdata"; if( indices.length()==0 ) suffix = "_data"; 118 26 : readInputLine( getShortcutLabel() + suffix + ": VSTACK ARG=" + allcol ); 119 : } 120 : // Merge all the collected data together into a single matrix 121 19 : if( theargs.size()>0 && indices.length()>0 ) readInputLine( getShortcutLabel() + "_data: CONCATENATE MATRIX11=" + getShortcutLabel() + "_atomdata MATRIX12=" + getShortcutLabel() + "_argdata"); 122 : 123 : // Now get the logweights 124 38 : std::vector<std::string> logw; parseVector("LOGWEIGHTS",logw); std::vector<Value*> thew; 125 19 : if( logw.size()>0 ) ActionWithArguments::interpretArgumentList( logw, plumed.getActionSet(), this, thew ); 126 19 : if( logw.size()>1 ) error("maximum of one argument should be specified for logweights"); 127 : 128 19 : if( logw.size()==0 ) { 129 19 : std::string zeros="0"; if( theargs.size()>0 ) { for(unsigned i=1; i<theargs[0]->getNumberOfValues(); ++i) zeros += ",0"; } 130 38 : readInputLine( getShortcutLabel() + "_cweight: CONSTANT VALUE=" + zeros ); 131 38 : readInputLine( getShortcutLabel() + "_logweights: COLLECT ARG=" + getShortcutLabel() + "_cweight STRIDE=" + stride + " CLEAR=" + clearstride ); 132 : } else { 133 0 : if( theargs[0]->getNumberOfValues()!=thew[0]->getNumberOfValues() ) error("mismatch between number of weights and number of collected arguments"); 134 0 : readInputLine( getShortcutLabel() + "_logweights: COLLECT ARG=" + thew[0]->getName() + " STRIDE=" + stride + " CLEAR=" + clearstride ); 135 : } 136 : // 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 137 19 : readInputLine( getShortcutLabel() + "_one: CONSTANT VALUE=1"); 138 38 : readInputLine( getShortcutLabel() + "_ones: COLLECT ARG=" + getShortcutLabel() + "_one STRIDE=" + stride + " CLEAR=" + clearstride ); 139 57 : } 140 : 141 : } 142 : }