LCOV - code coverage report
Current view: top level - dimred - ProjectNonLandmarkPoints.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 39 43 90.7 %
Date: 2024-10-11 08:09:47 Functions: 9 12 75.0 %

          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/ActionRegister.h"
      23             : #include "core/PlumedMain.h"
      24             : #include "core/ActionSet.h"
      25             : #include "tools/Random.h"
      26             : #include "tools/ConjugateGradient.h"
      27             : #include "analysis/AnalysisBase.h"
      28             : #include "reference/ReferenceConfiguration.h"
      29             : #include "DimensionalityReductionBase.h"
      30             : #include "PCA.h"
      31             : 
      32             : //+PLUMEDOC DIMRED PROJECT_ALL_ANALYSIS_DATA
      33             : /*
      34             : Find projections of all non-landmark points using the embedding calculated by a dimensionality reduction optimization calculation.
      35             : 
      36             : \par Examples
      37             : 
      38             : */
      39             : //+ENDPLUMEDOC
      40             : 
      41             : namespace PLMD {
      42             : namespace dimred {
      43             : 
      44             : class ProjectNonLandmarkPoints : public analysis::AnalysisBase {
      45             : private:
      46             : /// Tolerance for conjugate gradient algorithm
      47             :   double cgtol;
      48             : /// Number of diemsions in low dimensional space
      49             :   unsigned nlow;
      50             : /// The class that calculates the projection of the data that is required
      51             :   DimensionalityReductionBase* mybase;
      52             : /// Generate a projection of the ith data point - this is called in two routine
      53             :   void generateProjection( const unsigned& idat, std::vector<double>& point );
      54             : public:
      55             :   static void registerKeywords( Keywords& keys );
      56             :   explicit ProjectNonLandmarkPoints( const ActionOptions& ao );
      57             : /// Get a reference configuration (this returns the projection)
      58             :   analysis::DataCollectionObject& getStoredData( const unsigned& idat, const bool& calcdist );
      59             : /// Overwrite getArguments so we get arguments from underlying class
      60             :   std::vector<Value*> getArgumentList();
      61             : /// This does nothing -- projections are calculated when getDataPoint and getReferenceConfiguration are called
      62           2 :   void performAnalysis() {}
      63             : /// This just calls calculate stress in the underlying projection object
      64             :   double calculateStress( const std::vector<double>& pp, std::vector<double>& der );
      65             : /// Overwrite virtual function in ActionWithVessel
      66           0 :   void performTask( const unsigned&, const unsigned&, MultiValue& ) const { plumed_error(); }
      67             : };
      68             : 
      69       10423 : PLUMED_REGISTER_ACTION(ProjectNonLandmarkPoints,"PROJECT_ALL_ANALYSIS_DATA")
      70             : 
      71           3 : void ProjectNonLandmarkPoints::registerKeywords( Keywords& keys ) {
      72           3 :   analysis::AnalysisBase::registerKeywords( keys );
      73           6 :   keys.add("compulsory","PROJECTION","the projection that you wish to generate out-of-sample projections with");
      74           6 :   keys.add("compulsory","CGTOL","1E-6","the tolerance for the conjugate gradient optimization");
      75           6 :   keys.addOutputComponent("coord","default","the low-dimensional projections of the various input configurations");
      76           3 : }
      77             : 
      78           2 : ProjectNonLandmarkPoints::ProjectNonLandmarkPoints( const ActionOptions& ao ):
      79             :   Action(ao),
      80             :   analysis::AnalysisBase(ao),
      81           2 :   mybase(NULL)
      82             : {
      83           2 :   std::string myproj; parse("PROJECTION",myproj);
      84           2 :   mybase = plumed.getActionSet().selectWithLabel<DimensionalityReductionBase*>( myproj );
      85           2 :   if( !mybase ) error("could not find projection of data named " + myproj );
      86             :   // Add the dependency and set the dimensionality
      87           2 :   addDependency( mybase ); nlow = mybase->nlow;
      88             :   // Add fake components to the underlying ActionWithValue for the arguments
      89             :   std::string num;
      90           6 :   for(unsigned i=0; i<nlow; ++i) {
      91          12 :     Tools::convert(i+1,num); addComponent( "coord-" + num ); componentIsNotPeriodic( "coord-" + num );
      92             :   }
      93             : 
      94           2 :   log.printf("  generating out-of-sample projections using projection with label %s \n",myproj.c_str() );
      95           4 :   parse("CGTOL",cgtol);
      96           2 : }
      97             : 
      98           0 : std::vector<Value*> ProjectNonLandmarkPoints::getArgumentList() {
      99             :   std::vector<Value*> arglist( analysis::AnalysisBase::getArgumentList() );
     100           0 :   for(unsigned i=0; i<nlow; ++i) arglist.push_back( getPntrToComponent(i) );
     101           0 :   return arglist;
     102             : }
     103             : 
     104        1046 : void ProjectNonLandmarkPoints::generateProjection( const unsigned& idat, std::vector<double>& point ) {
     105        1046 :   PCA* ispca = dynamic_cast<PCA*>( mybase );
     106        1046 :   if( ispca ) {
     107         546 :     ispca->getProjection( my_input_data->getStoredData(idat,false), point );
     108             :   } else {
     109             :     ConjugateGradient<ProjectNonLandmarkPoints> myminimiser( this );
     110         500 :     unsigned closest=0; double mindist = std::sqrt( getDissimilarity( mybase->getDataPointIndexInBase(0), idat ) );
     111         500 :     mybase->setTargetDistance( 0, mindist );
     112      125000 :     for(unsigned i=1; i<mybase->getNumberOfDataPoints(); ++i) {
     113      124500 :       double dist = std::sqrt( getDissimilarity( mybase->getDataPointIndexInBase(i), idat ) );
     114      124500 :       mybase->setTargetDistance( i, dist );
     115      124500 :       if( dist<mindist ) { mindist=dist; closest=i; }
     116             :     }
     117             :     // Put the initial guess near to the closest landmark  -- may wish to use grid here again Sandip??
     118         500 :     Random random; random.setSeed(-1234);
     119        1500 :     for(unsigned j=0; j<nlow; ++j) point[j]=mybase->projections(closest,j) + (random.RandU01() - 0.5)*0.01;
     120         500 :     myminimiser.minimise( cgtol, point, &ProjectNonLandmarkPoints::calculateStress );
     121             :   }
     122        1046 : }
     123             : 
     124        1046 : analysis::DataCollectionObject& ProjectNonLandmarkPoints::getStoredData( const unsigned& idat, const bool& calcdist ) {
     125        1046 :   std::vector<double> pp(nlow); generateProjection( idat, pp ); std::string num;
     126             :   analysis::DataCollectionObject& myref=AnalysisBase::getStoredData(idat,calcdist);
     127        3138 :   for(unsigned i=0; i<nlow; ++i) { Tools::convert(i+1,num); myref.setArgument( getLabel() + ".coord-" + num, pp[i] ); }
     128        1046 :   return myref;
     129             : }
     130             : 
     131       16744 : double ProjectNonLandmarkPoints::calculateStress( const std::vector<double>& pp, std::vector<double>& der ) {
     132       16744 :   return mybase->calculateStress( pp, der );
     133             : }
     134             : 
     135             : }
     136             : }
     137             : 

Generated by: LCOV version 1.15