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 { return true; } 62 : /// Get the dissimilarity between two data points 63 : double getDissimilarity( const unsigned&, const unsigned& ) override; 64 : /// Get the weight from the input file 65 : double getWeight( const unsigned& idata ) override; 66 : /// Just tell plumed to stop 67 : void update() override; 68 : /// Read in the dissimilarity matrix 69 : void runFinalJobs() override; 70 : /// This does nothing 71 0 : void performAnalysis() override {}; 72 : /// Overwrite virtual function in base class 73 0 : void performTask( const unsigned&, const unsigned&, MultiValue& ) const override { plumed_error(); } 74 : }; 75 : 76 10423 : PLUMED_REGISTER_ACTION(ReadDissimilarityMatrix,"READ_DISSIMILARITY_MATRIX") 77 : 78 3 : void ReadDissimilarityMatrix::registerKeywords( Keywords& keys ) { 79 3 : AnalysisBase::registerKeywords( keys ); 80 6 : keys.add("compulsory","FILE","an input file containing the matrix of dissimilarities"); 81 6 : keys.add("optional","WFILE","input file containing weights of points"); 82 6 : keys.reset_style("USE_OUTPUT_DATA_FROM","optional"); 83 3 : } 84 : 85 2 : ReadDissimilarityMatrix::ReadDissimilarityMatrix( const ActionOptions& ao ): 86 : Action(ao), 87 : AnalysisBase(ao), 88 2 : nnodes(1) 89 : { 90 2 : setStride(1); // Set the stride equal to one to ensure we don't get stuck in an infinite loop 91 2 : std::vector<ActionSetup*> setupActions=plumed.getActionSet().select<ActionSetup*>(); 92 2 : if( my_input_data && (plumed.getActionSet().size()-setupActions.size())!=1 ) error("should only be this action and the READ_ANALYSIS_FRAMES command in the input file"); 93 2 : if( !my_input_data && plumed.getActionSet().size()!=0 ) error("read dissimilarity matrix command must be at top of input file"); 94 : 95 2 : parse("FILE",fname); 96 2 : log.printf(" reading dissimilarity matrix from file %s \n",fname.c_str() ); 97 4 : parse("WFILE",wfile); 98 : 99 2 : if( wfile.length()>0 ) log.printf(" reading weights of nodes from file named %s \n",wfile.c_str() ); 100 2 : else log.printf(" setting weights of all nodes equal to one\n"); 101 2 : } 102 : 103 7 : void ReadDissimilarityMatrix::update() { if(!my_input_data) plumed.stop(); } 104 : 105 2 : void ReadDissimilarityMatrix::runFinalJobs() { 106 2 : IFile mfile; mfile.open(fname); 107 : // Read in first line 108 2 : std::vector<std::string> words; nnodes=0; 109 4 : while( nnodes==0 ) { 110 2 : Tools::getParsedLine( mfile, words ); 111 2 : nnodes=words.size(); 112 : } 113 : 114 2 : std::vector<double> tmpdis( nnodes ); 115 20 : for(unsigned j=0; j<nnodes; ++j) Tools::convert( words[j], tmpdis[j] ); 116 2 : dissimilarities.push_back( tmpdis ); 117 : 118 18 : while( Tools::getParsedLine( mfile, words ) ) { 119 16 : if( words.size()!=nnodes ) error("bad formatting in matrix file"); 120 192 : for(unsigned j=0; j<nnodes; ++j) Tools::convert( words[j], tmpdis[j] ); 121 16 : dissimilarities.push_back( tmpdis ); 122 : } 123 2 : mfile.close(); 124 2 : if( my_input_data && dissimilarities.size()!=getNumberOfDataPoints() ) { 125 0 : error("mismatch between number of data points in trajectory and the dimensions of the dissimilarity matrix"); 126 : } 127 2 : if( !my_input_data ) fake_data.resize( dissimilarities.size() ); 128 : 129 2 : weights.resize( dissimilarities.size() ); 130 2 : if( wfile.length()>0 ) { 131 0 : IFile wfilef; wfilef.open(wfile); 132 0 : for(unsigned i=0; i<weights.size(); ++i) { 133 0 : Tools::getParsedLine( wfilef, words ); Tools::convert( words[0], weights[i] ); 134 : } 135 0 : wfilef.close(); 136 0 : } else { 137 2 : weights.assign(weights.size(),1.0); 138 : } 139 2 : } 140 : 141 257 : unsigned ReadDissimilarityMatrix::getNumberOfDataPoints() const { 142 302 : if( my_input_data ) return AnalysisBase::getNumberOfDataPoints(); 143 212 : return dissimilarities.size(); 144 : } 145 : 146 0 : unsigned ReadDissimilarityMatrix::getDataPointIndexInBase( const unsigned& idata ) const { 147 0 : return idata; 148 : } 149 : 150 334 : double ReadDissimilarityMatrix::getDissimilarity( const unsigned& iframe, const unsigned& jframe ) { 151 334 : return dissimilarities[iframe][jframe]*dissimilarities[iframe][jframe]; 152 : } 153 : 154 5 : DataCollectionObject& ReadDissimilarityMatrix::getStoredData( const unsigned& idata, const bool& calcdist ) { 155 5 : plumed_massert( !calcdist, "cannot calc dist as this data was read in from input"); 156 10 : if( my_input_data ) return AnalysisBase::getStoredData( idata, calcdist ); 157 0 : return fake_data[idata]; 158 : } 159 : 160 18 : double ReadDissimilarityMatrix::getWeight( const unsigned& idata ) { 161 18 : plumed_assert( idata<dissimilarities.size() ); return weights[idata]; 162 : } 163 : 164 : } 165 : }