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 "AnalysisBase.h" 23 : #include "ReadAnalysisFrames.h" 24 : #include "reference/ReferenceConfiguration.h" 25 : #include "reference/MetricRegister.h" 26 : #include "core/PlumedMain.h" 27 : #include "core/ActionSet.h" 28 : #include "core/ActionRegister.h" 29 : #include "core/ActionSetup.h" 30 : #include "tools/IFile.h" 31 : 32 : //+PLUMEDOC ANALYSIS READ_DISSIMILARITY_MATRIX 33 : /* 34 : Read a matrix of dissimilarities between a trajectory of atomic configurations from a file. 35 : 36 : \par Examples 37 : 38 : */ 39 : //+ENDPLUMEDOC 40 : 41 : namespace PLMD { 42 : namespace analysis { 43 : 44 : class ReadDissimilarityMatrix : public AnalysisBase { 45 : private: 46 : unsigned nnodes; 47 : std::vector<DataCollectionObject> fake_data; 48 : std::string fname, wfile; 49 : // Matrix<double> dissimilarities; 50 : std::vector<std::vector<double> > dissimilarities; 51 : std::vector<double> weights; 52 : public: 53 : static void registerKeywords( Keywords& keys ); 54 : explicit ReadDissimilarityMatrix( const ActionOptions& ao ); 55 : unsigned getNumberOfDataPoints() const override; 56 : // Return the index of the data point in the base class 57 : unsigned getDataPointIndexInBase( const unsigned& idata ) const override; 58 : /// This gives an error as if we read in the matrix we dont have the coordinates 59 : DataCollectionObject& getStoredData( const unsigned& idata, const bool& calcdist ) override; 60 : /// Tell everyone we have dissimilarities 61 11 : bool dissimilaritiesWereSet() const override { 62 11 : return true; 63 : } 64 : /// Get the dissimilarity between two data points 65 : double getDissimilarity( const unsigned&, const unsigned& ) override; 66 : /// Get the weight from the input file 67 : double getWeight( const unsigned& idata ) override; 68 : /// Just tell plumed to stop 69 : void update() override; 70 : /// Read in the dissimilarity matrix 71 : void runFinalJobs() override; 72 : /// This does nothing 73 0 : void performAnalysis() override {}; 74 : /// Overwrite virtual function in base class 75 0 : void performTask( const unsigned&, const unsigned&, MultiValue& ) const override { 76 0 : plumed_error(); 77 : } 78 : }; 79 : 80 13789 : PLUMED_REGISTER_ACTION(ReadDissimilarityMatrix,"READ_DISSIMILARITY_MATRIX") 81 : 82 6 : void ReadDissimilarityMatrix::registerKeywords( Keywords& keys ) { 83 6 : AnalysisBase::registerKeywords( keys ); 84 12 : keys.add("compulsory","FILE","an input file containing the matrix of dissimilarities"); 85 12 : keys.add("optional","WFILE","input file containing weights of points"); 86 12 : keys.reset_style("USE_OUTPUT_DATA_FROM","optional"); 87 6 : } 88 : 89 2 : ReadDissimilarityMatrix::ReadDissimilarityMatrix( const ActionOptions& ao ): 90 : Action(ao), 91 : AnalysisBase(ao), 92 2 : nnodes(1) { 93 2 : setStride(1); // Set the stride equal to one to ensure we don't get stuck in an infinite loop 94 2 : std::vector<ActionSetup*> setupActions=plumed.getActionSet().select<ActionSetup*>(); 95 2 : if( my_input_data && (plumed.getActionSet().size()-setupActions.size())!=1 ) { 96 0 : error("should only be this action and the READ_ANALYSIS_FRAMES command in the input file"); 97 : } 98 2 : if( !my_input_data && plumed.getActionSet().size()!=0 ) { 99 0 : error("read dissimilarity matrix command must be at top of input file"); 100 : } 101 : 102 2 : parse("FILE",fname); 103 2 : log.printf(" reading dissimilarity matrix from file %s \n",fname.c_str() ); 104 4 : parse("WFILE",wfile); 105 : 106 2 : if( wfile.length()>0 ) { 107 0 : log.printf(" reading weights of nodes from file named %s \n",wfile.c_str() ); 108 : } else { 109 2 : log.printf(" setting weights of all nodes equal to one\n"); 110 : } 111 2 : } 112 : 113 7 : void ReadDissimilarityMatrix::update() { 114 7 : if(!my_input_data) { 115 1 : plumed.stop(); 116 : } 117 7 : } 118 : 119 2 : void ReadDissimilarityMatrix::runFinalJobs() { 120 2 : IFile mfile; 121 2 : mfile.open(fname); 122 : // Read in first line 123 : std::vector<std::string> words; 124 2 : nnodes=0; 125 4 : while( nnodes==0 ) { 126 2 : Tools::getParsedLine( mfile, words ); 127 2 : nnodes=words.size(); 128 : } 129 : 130 2 : std::vector<double> tmpdis( nnodes ); 131 20 : for(unsigned j=0; j<nnodes; ++j) { 132 18 : Tools::convert( words[j], tmpdis[j] ); 133 : } 134 2 : dissimilarities.push_back( tmpdis ); 135 : 136 18 : while( Tools::getParsedLine( mfile, words ) ) { 137 16 : if( words.size()!=nnodes ) { 138 0 : error("bad formatting in matrix file"); 139 : } 140 192 : for(unsigned j=0; j<nnodes; ++j) { 141 176 : Tools::convert( words[j], tmpdis[j] ); 142 : } 143 16 : dissimilarities.push_back( tmpdis ); 144 : } 145 2 : mfile.close(); 146 2 : if( my_input_data && dissimilarities.size()!=getNumberOfDataPoints() ) { 147 0 : error("mismatch between number of data points in trajectory and the dimensions of the dissimilarity matrix"); 148 : } 149 2 : if( !my_input_data ) { 150 1 : fake_data.resize( dissimilarities.size() ); 151 : } 152 : 153 2 : weights.resize( dissimilarities.size() ); 154 2 : if( wfile.length()>0 ) { 155 0 : IFile wfilef; 156 0 : wfilef.open(wfile); 157 0 : for(unsigned i=0; i<weights.size(); ++i) { 158 0 : Tools::getParsedLine( wfilef, words ); 159 0 : Tools::convert( words[0], weights[i] ); 160 : } 161 0 : wfilef.close(); 162 0 : } else { 163 2 : weights.assign(weights.size(),1.0); 164 : } 165 2 : } 166 : 167 257 : unsigned ReadDissimilarityMatrix::getNumberOfDataPoints() const { 168 257 : if( my_input_data ) { 169 45 : return AnalysisBase::getNumberOfDataPoints(); 170 : } 171 212 : return dissimilarities.size(); 172 : } 173 : 174 0 : unsigned ReadDissimilarityMatrix::getDataPointIndexInBase( const unsigned& idata ) const { 175 0 : return idata; 176 : } 177 : 178 334 : double ReadDissimilarityMatrix::getDissimilarity( const unsigned& iframe, const unsigned& jframe ) { 179 334 : return dissimilarities[iframe][jframe]*dissimilarities[iframe][jframe]; 180 : } 181 : 182 5 : DataCollectionObject& ReadDissimilarityMatrix::getStoredData( const unsigned& idata, const bool& calcdist ) { 183 5 : plumed_massert( !calcdist, "cannot calc dist as this data was read in from input"); 184 5 : if( my_input_data ) { 185 5 : return AnalysisBase::getStoredData( idata, calcdist ); 186 : } 187 0 : return fake_data[idata]; 188 : } 189 : 190 18 : double ReadDissimilarityMatrix::getWeight( const unsigned& idata ) { 191 18 : plumed_assert( idata<dissimilarities.size() ); 192 18 : return weights[idata]; 193 : } 194 : 195 : } 196 : }