IMP  2.1.0
The Integrative Modeling Platform
eigen_analysis.h
Go to the documentation of this file.
1 /**
2  * \file IMP/algebra/eigen_analysis.h
3  * \brief Principal component analysis of a set of points
4  *
5  * Copyright 2007-2013 IMP Inventors. All rights reserved.
6  */
7 
8 #ifndef IMPALGEBRA_EIGEN_ANALYSIS_H
9 #define IMPALGEBRA_EIGEN_ANALYSIS_H
10 
11 #include "VectorD.h"
12 #include "Transformation3D.h"
13 #include "GeometricPrimitiveD.h"
14 #include "IMP/algebra/internal/utility.h"
16 #include <IMP/algebra/internal/jama_svd.h>
17 #include <IMP/base/log.h>
18 
19 IMPALGEBRA_BEGIN_NAMESPACE
20 /** Represent a eigen analysis of some data.
21  */
22 template <int D>
24  public:
27  VectorD<D> values, VectorD<D> centroid)
28  : eigen_vecs_(pcs), eigen_values_(values), centroid_(centroid) {}
30  IMP_USAGE_CHECK(!eigen_vecs_.empty(), "The PCA was not initialized");
31  return eigen_vecs_;
32  }
33  VectorD<D> get_principal_component(unsigned int i) const {
34  IMP_USAGE_CHECK(!eigen_vecs_.empty(), "The PCA was not initialized");
35  return eigen_vecs_[i];
36  }
37  VectorD<D> get_principal_values() const {
38  IMP_USAGE_CHECK(!eigen_vecs_.empty(), "The PCA was not initialized");
39  return eigen_values_;
40  }
41  double get_principal_value(unsigned int i) const {
42  IMP_USAGE_CHECK(!eigen_vecs_.empty(), "The PCA was not initialized");
43  return eigen_values_[i];
44  }
45  inline VectorD<D> get_centroid() const { return centroid_; }
46  void set_centroid(VectorD<D> cntr) {
47  IMP_USAGE_CHECK(!eigen_vecs_.empty(), "The PCA was not initialized");
48  centroid_ = cntr;
49  }
52 
53  private:
54  int compare(const PrincipalComponentAnalysisD &o) const {
55  IMP_USAGE_CHECK(eigen_vecs_.empty() || o.eigen_vecs_.empty(),
56  "Cannot compare against anything other than the default"
57  " PrincipalComponentAnalysis");
58  if (eigen_vecs_.empty() && o.eigen_vecs_.empty()) {
59  return 0;
60  } else {
61  return -1;
62  }
63  }
64  base::Vector<VectorD<D> > eigen_vecs_;
65  VectorD<D> eigen_values_;
66  VectorD<D> centroid_;
67 };
68 
69 #ifndef IMP_DOXYGEN
70 typedef PrincipalComponentAnalysisD<1> PrincipalComponentAnalysis1D;
71 typedef PrincipalComponentAnalysisD<2> PrincipalComponentAnalysis2D;
72 typedef PrincipalComponentAnalysisD<3> PrincipalComponentAnalysis3D;
73 typedef PrincipalComponentAnalysisD<4> PrincipalComponentAnalysis4D;
74 typedef PrincipalComponentAnalysisD<5> PrincipalComponentAnalysis5D;
75 typedef PrincipalComponentAnalysisD<6> PrincipalComponentAnalysis6D;
76 typedef PrincipalComponentAnalysisD<-1> PrincipalComponentAnalysisKD;
78  PrincipalComponentAnalysis1Ds;
80  PrincipalComponentAnalysis2Ds;
82  PrincipalComponentAnalysis3Ds;
84  PrincipalComponentAnalysis4Ds;
86  PrincipalComponentAnalysis5Ds;
88  PrincipalComponentAnalysis6Ds;
90  PrincipalComponentAnalysisKDs;
91 
92 template <int D>
93 inline void PrincipalComponentAnalysisD<D>::show(std::ostream &out) const {
94  if (eigen_vecs_.empty()) {
95  out << "invalid";
96  return;
97  }
98  out << "vectors: " << eigen_vecs_ << " weights: " << eigen_values_
99  << " centroid: " << centroid_ << std::endl;
100 }
101 
102 #endif
103 
104 //! Perform principal components analysis on a set of vectors
105 /** See PrincipalComponentAnalysis
106  */
107 template <int D>
109  const base::Vector<VectorD<D> > &ps) {
110  IMP_USAGE_CHECK(!ps.empty(), "Need some vectors to get components.");
111  unsigned int dim = ps[0].get_dimension();
112  VectorD<D> m =
113  std::accumulate(ps.begin(), ps.end(), get_zero_vector_kd(dim)) /
114  ps.size();
115  internal::TNT::Array2D<double> cov = internal::get_covariance_matrix(ps, m);
116  IMP_LOG_VERBOSE("The covariance matrix is " << cov << std::endl);
117  internal::JAMA::SVD<double> svd(cov);
118  internal::TNT::Array2D<double> V(dim, dim);
119  internal::TNT::Array1D<double> SV;
120 
121  svd.getV(V);
122  IMP_LOG_VERBOSE("V is " << V << std::endl);
123  svd.getSingularValues(SV);
124  VectorD<D> values = ps[0];
125  base::Vector<VectorD<D> > vectors(dim, values);
126  for (unsigned int i = 0; i < dim; ++i) {
127  values[i] = SV[i];
128  for (unsigned int j = 0; j < dim; ++j) {
129  vectors[i][j] = V[j][i];
130  }
131  }
132  // the principal components are the columns of V
133  // pc1(pc3) is the vector of the largest(smallest) eigenvalue
134  return PrincipalComponentAnalysisD<D>(vectors, values, m);
135 }
136 
137 //! Get all possible alignments of the first principal
138 //! component system to the second one
140  const PrincipalComponentAnalysisD<3> &pca1,
141  const PrincipalComponentAnalysisD<3> &pca2);
142 
143 #ifndef IMP_DOXYGEN
144 typedef PrincipalComponentAnalysisD<3> PrincipalComponentAnalysis;
145 #endif
146 
147 IMPALGEBRA_END_NAMESPACE
148 #endif /* IMPALGEBRA_EIGEN_ANALYSIS_H */
Basic types used by IMP.
VectorD< D > get_zero_vector_kd(int Di)
Return a dynamically sized vector of zeros.
Definition: VectorD.h:454
PrincipalComponentAnalysisD< D > get_principal_components(const base::Vector< VectorD< D > > &ps)
Perform principal components analysis on a set of vectors.
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
#define IMP_COMPARISONS(Name)
Implement comparison in a class using a compare function.
#define IMP_SHOWABLE(Name)
A Cartesian vector in D-dimensions.
Definition: VectorD.h:48
int compare(const VectorD< D > &a, const VectorD< D > &b)
lexicographic comparison of two vectors
Definition: VectorD.h:371
IMP::base::Vector< Transformation3D > Transformation3Ds
Simple D vector class.
Transformation3Ds get_alignments_from_first_to_second(const PrincipalComponentAnalysisD< 3 > &pca1, const PrincipalComponentAnalysisD< 3 > &pca2)
Simple 3D transformation class.
Vector3D get_centroid(const Vector3Ds &ps)
Returns the centroid of a set of vectors.
Definition: Vector3D.h:56
void show(Hierarchy h, std::ostream &out=std::cout)
Print out a molecular hierarchy.
Logging and error reporting support.
Simple 3D rotation class.
#define IMP_LOG_VERBOSE(expr)