LCOV - code coverage report
Current view: top level - analysis - EuclideanDissimilarityMatrix.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 56 68 82.4 %
Date: 2026-03-30 13:16:06 Functions: 9 11 81.8 %

          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 "tools/PDB.h"
      24             : #include "core/ActionRegister.h"
      25             : #include "reference/MetricRegister.h"
      26             : #include "reference/ReferenceConfiguration.h"
      27             : 
      28             : //+PLUMEDOC ANALYSIS EUCLIDEAN_DISSIMILARITIES
      29             : /*
      30             : Calculate the matrix of dissimilarities between a trajectory of atomic configurations.
      31             : 
      32             : \par Examples
      33             : 
      34             : */
      35             : //+ENDPLUMEDOC
      36             : 
      37             : namespace PLMD {
      38             : namespace analysis {
      39             : 
      40             : class EuclideanDissimilarityMatrix : public AnalysisBase {
      41             : private:
      42             :   PDB mypdb;
      43             :   std::string mtype;
      44             :   Matrix<double> dissimilarities;
      45             : public:
      46             :   static void registerKeywords( Keywords& keys );
      47             :   explicit EuclideanDissimilarityMatrix( const ActionOptions& ao );
      48             : /// Do the analysis
      49             :   void performAnalysis() override;
      50             : /// This ensures that classes that use this data know that dissimilarities were set
      51         436 :   bool dissimilaritiesWereSet() const override {
      52         436 :     return true;
      53             :   }
      54             : /// Get information on how to calculate dissimilarities
      55             :   std::string getDissimilarityInstruction() const override;
      56             : /// Get the squared dissimilarity between two reference configurations
      57             :   double getDissimilarity( const unsigned& i, const unsigned& j ) override;
      58             : /// This is just to deal with ActionWithVessel
      59           0 :   void performTask( const unsigned&, const unsigned&, MultiValue& ) const override {
      60           0 :     plumed_error();
      61             :   }
      62             : };
      63             : 
      64       13811 : PLUMED_REGISTER_ACTION(EuclideanDissimilarityMatrix,"EUCLIDEAN_DISSIMILARITIES")
      65             : 
      66          17 : void EuclideanDissimilarityMatrix::registerKeywords( Keywords& keys ) {
      67          17 :   AnalysisBase::registerKeywords( keys );
      68          17 :   keys.use("ARG");
      69          34 :   keys.reset_style("ARG","optional");
      70          34 :   keys.add("compulsory","METRIC","EUCLIDEAN","the method that you are going to use to measure the distances between points");
      71          34 :   keys.add("atoms","ATOMS","the list of atoms that you are going to use in the measure of distance that you are using");
      72          17 : }
      73             : 
      74          13 : EuclideanDissimilarityMatrix::EuclideanDissimilarityMatrix( const ActionOptions& ao ):
      75             :   Action(ao),
      76          13 :   AnalysisBase(ao) {
      77          26 :   parse("METRIC",mtype);
      78             :   std::vector<AtomNumber> atoms;
      79          13 :   if( my_input_data->getNumberOfAtoms()>0 ) {
      80           6 :     parseAtomList("ATOMS",atoms);
      81           3 :     if( atoms.size()!=0 ) {
      82           0 :       mypdb.setAtomNumbers( atoms );
      83           0 :       for(unsigned i=0; i<atoms.size(); ++i) {
      84             :         bool found=false;
      85           0 :         for(unsigned j=0; j<my_input_data->getAtomIndexes().size(); ++j) {
      86           0 :           if( my_input_data->getAtomIndexes()[j]==atoms[i] ) {
      87             :             found=true;
      88             :             break;
      89             :           }
      90             :         }
      91           0 :         if( !found ) {
      92             :           std::string num;
      93           0 :           Tools::convert( atoms[i].serial(), num );
      94           0 :           error("atom number " + num + " is not stored in any action that has been input");
      95             :         }
      96             :       }
      97           0 :       mypdb.addBlockEnd( atoms.size() );
      98           3 :     } else if( getNumberOfArguments()==0 ) {
      99           1 :       mypdb.setAtomNumbers( my_input_data->getAtomIndexes() );
     100           1 :       mypdb.addBlockEnd( my_input_data->getAtomIndexes().size() );
     101           1 :       if( mtype=="EUCLIDEAN" ) {
     102             :         mtype="OPTIMAL";
     103             :       }
     104             :     }
     105             :   }
     106          13 :   log.printf("  measuring distances using %s metric \n",mtype.c_str() );
     107          13 :   if( my_input_data->getArgumentNames().size()>0 ) {
     108          12 :     if( getNumberOfArguments()==0 && atoms.size()==0 ) {
     109          10 :       std::vector<std::string> argnames( my_input_data->getArgumentNames() );
     110          10 :       mypdb.setArgumentNames( argnames );
     111          10 :       requestArguments( my_input_data->getArgumentList() );
     112          10 :     } else {
     113           2 :       std::vector<Value*> myargs( getArguments() );
     114           2 :       std::vector<std::string> inargnames( my_input_data->getArgumentNames() );
     115           2 :       std::vector<std::string> argnames( myargs.size() );
     116           6 :       for(unsigned i=0; i<myargs.size(); ++i) {
     117           4 :         argnames[i]=myargs[i]->getName();
     118             :         bool found=false;
     119           6 :         for(unsigned j=0; j<inargnames.size(); ++j) {
     120           6 :           if( argnames[i]==inargnames[j] ) {
     121             :             found=true;
     122             :             break;
     123             :           }
     124             :         }
     125           4 :         if( !found ) {
     126           0 :           error("input named " + my_input_data->getLabel() + " does not store/calculate quantity named " + argnames[i] );
     127             :         }
     128             :       }
     129           2 :       mypdb.setArgumentNames( argnames );
     130           2 :       requestArguments( myargs );
     131           2 :     }
     132             :   }
     133          13 : }
     134             : 
     135          20 : void EuclideanDissimilarityMatrix::performAnalysis() {
     136             :   // Resize dissimilarities matrix and set all elements to zero
     137          20 :   if( !usingLowMem() ) {
     138          20 :     dissimilarities.resize( getNumberOfDataPoints(), getNumberOfDataPoints() );
     139             :     dissimilarities=0;
     140             :   }
     141          20 : }
     142             : 
     143         413 : std::string EuclideanDissimilarityMatrix::getDissimilarityInstruction() const {
     144         413 :   return "TYPE=" + mtype;
     145             : }
     146             : 
     147      611659 : double EuclideanDissimilarityMatrix::getDissimilarity( const unsigned& iframe, const unsigned& jframe ) {
     148             :   plumed_dbg_assert( iframe<getNumberOfDataPoints() && jframe<getNumberOfDataPoints() );
     149      611659 :   if( !usingLowMem() ) {
     150      611659 :     if( dissimilarities(iframe,jframe)>0. ) {
     151             :       return dissimilarities(iframe,jframe);
     152             :     }
     153             :   }
     154      256165 :   if( iframe!=jframe ) {
     155             :     double dd;
     156      255613 :     getStoredData( iframe, true ).transferDataToPDB( mypdb );
     157      255613 :     auto myref1=metricRegister().create<ReferenceConfiguration>(mtype, mypdb);
     158      255613 :     getStoredData( jframe, true ).transferDataToPDB( mypdb );
     159      255613 :     auto myref2=metricRegister().create<ReferenceConfiguration>(mtype, mypdb);
     160      255613 :     if( !usingLowMem() ) {
     161      255613 :       dd=dissimilarities(iframe,jframe) = dissimilarities(jframe,iframe) = distance( getPbc(), getArguments(), myref1.get(), myref2.get(), true );
     162             :     } else {
     163           0 :       dd=distance( getPbc(), getArguments(), myref1.get(), myref2.get(), true );
     164             :     }
     165             :     return dd;
     166      255613 :   }
     167             :   return 0.0;
     168             : }
     169             : 
     170             : }
     171             : }

Generated by: LCOV version 1.16