Newer
Older
Gareth Tribello
committed
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Gareth Tribello
committed
(see the PEOPLE file at the root of the distribution for a list of names)
Gareth Tribello
committed
This file is part of plumed, version 2.
plumed is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
plumed is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with plumed. If not, see <http://www.gnu.org/licenses/>.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
#include "AnalysisBase.h"
#include "tools/PDB.h"
Gareth Tribello
committed
#include "core/ActionRegister.h"
#include "reference/MetricRegister.h"
Gareth Tribello
committed
#include "reference/ReferenceConfiguration.h"
//+PLUMEDOC ANALYSIS EUCLIDEAN_DISSIMILARITIES
Calculate the matrix of dissimilarities between a trajectory of atomic configurations.
\par Examples
*/
//+ENDPLUMEDOC
Gareth Tribello
committed
namespace PLMD {
namespace analysis {
class EuclideanDissimilarityMatrix : public AnalysisBase {
Gareth Tribello
committed
private:
PDB mypdb;
std::string mtype;
Gareth Tribello
committed
Matrix<double> dissimilarities;
public:
static void registerKeywords( Keywords& keys );
explicit EuclideanDissimilarityMatrix( const ActionOptions& ao );
Gareth Tribello
committed
/// Do the analysis
void performAnalysis();
/// This ensures that classes that use this data know that dissimilarities were set
bool dissimilaritiesWereSet() const { return true; }
/// Get information on how to calculate dissimilarities
std::string getDissimilarityInstruction() const ;
Gareth Tribello
committed
/// Get the squared dissimilarity between two reference configurations
double getDissimilarity( const unsigned& i, const unsigned& j );
/// This is just to deal with ActionWithVessel
void performTask( const unsigned&, const unsigned&, MultiValue& ) const { plumed_error(); }
Gareth Tribello
committed
};
PLUMED_REGISTER_ACTION(EuclideanDissimilarityMatrix,"EUCLIDEAN_DISSIMILARITIES")
void EuclideanDissimilarityMatrix::registerKeywords( Keywords& keys ) {
AnalysisBase::registerKeywords( keys ); keys.use("ARG"); keys.reset_style("ARG","optional");
keys.add("compulsory","METRIC","EUCLIDEAN","the method that you are going to use to measure the distances between points");
keys.add("atoms","ATOMS","the list of atoms that you are going to use in the measure of distance that you are using");
Gareth Tribello
committed
}
EuclideanDissimilarityMatrix::EuclideanDissimilarityMatrix( const ActionOptions& ao ):
Gareth Tribello
committed
{
parse("METRIC",mtype); std::vector<AtomNumber> atoms;
if( my_input_data->getNumberOfAtoms()>0 ) {
parseAtomList("ATOMS",atoms);
if( atoms.size()!=0 ) {
mypdb.setAtomNumbers( atoms );
for(unsigned i=0; i<atoms.size(); ++i) {
bool found=false;
for(unsigned j=0; j<my_input_data->getAtomIndexes().size(); ++j) {
if( my_input_data->getAtomIndexes()[j]==atoms[i] ) { found=true; break; }
}
if( !found ) {
std::string num; Tools::convert( atoms[i].serial(), num );
error("atom number " + num + " is not stored in any action that has been input");
}
mypdb.addBlockEnd( atoms.size() );
} else if( getNumberOfArguments()==0 ) {
mypdb.setAtomNumbers( my_input_data->getAtomIndexes() );
mypdb.addBlockEnd( my_input_data->getAtomIndexes().size() );
if( mtype=="EUCLIDEAN" ) mtype="OPTIMAL";
}
}
log.printf(" measuring distances using %s metric \n",mtype.c_str() );
if( my_input_data->getArgumentNames().size()>0 ) {
if( getNumberOfArguments()==0 && atoms.size()==0 ) {
std::vector<std::string> argnames( my_input_data->getArgumentNames() );
mypdb.setArgumentNames( argnames ); requestArguments( my_input_data->getArgumentList() );
} else {
std::vector<Value*> myargs( getArguments() );
std::vector<std::string> inargnames( my_input_data->getArgumentNames() );
std::vector<std::string> argnames( myargs.size() );
for(unsigned i=0; i<myargs.size(); ++i) {
argnames[i]=myargs[i]->getName();
bool found=false;
for(unsigned j=0; j<inargnames.size(); ++j) {
if( argnames[i]==inargnames[j] ) { found=true; break; }
}
if( !found ) error("input named " + my_input_data->getLabel() + " does not store/calculate quantity named " + argnames[i] );
mypdb.setArgumentNames( argnames ); requestArguments( myargs );
}
Gareth Tribello
committed
}
void EuclideanDissimilarityMatrix::performAnalysis() {
Gareth Tribello
committed
// Resize dissimilarities matrix and set all elements to zero
if( !usingLowMem() ) {
dissimilarities.resize( getNumberOfDataPoints(), getNumberOfDataPoints() ); dissimilarities=0;
sandipde
committed
}
Gareth Tribello
committed
}
std::string EuclideanDissimilarityMatrix::getDissimilarityInstruction() const {
return "TYPE=" + mtype;
}
double EuclideanDissimilarityMatrix::getDissimilarity( const unsigned& iframe, const unsigned& jframe ) {
sandipde
committed
plumed_dbg_assert( iframe<getNumberOfDataPoints() && jframe<getNumberOfDataPoints() );
if( !usingLowMem() ) {
if( dissimilarities(iframe,jframe)>0. ) { return dissimilarities(iframe,jframe); }
sandipde
committed
}
getStoredData( iframe, true ).transferDataToPDB( mypdb );
auto myref1=metricRegister().create<ReferenceConfiguration>(mtype, mypdb);
getStoredData( jframe, true ).transferDataToPDB( mypdb );
auto myref2=metricRegister().create<ReferenceConfiguration>(mtype, mypdb);
if( !usingLowMem() ) dd=dissimilarities(iframe,jframe) = dissimilarities(jframe,iframe) = distance( getPbc(), getArguments(), myref1.get(), myref2.get(), true );
else dd=distance( getPbc(), getArguments(), myref1.get(), myref2.get(), true );
return dd;
Gareth Tribello
committed
}
return 0.0;
}
}
}