9 #include "PrincipalComponentAnalysis.h"
10 #include "jama/jama_eig.h"
11 #include "jama/jama_lu.h"
17 PrincipalComponentAnalysis::PrincipalComponentAnalysis(
const int n) {
20 p_statistics.resize(n * n);
21 for(
int i = 0; i < n; i++) {
22 for(
int j = 0; j <= i; j++) {
24 p_statistics[n*j+i] = p_statistics[n*i+j];
28 p_hasTransform =
false;
32 PrincipalComponentAnalysis::PrincipalComponentAnalysis(TNT::Array2D<double> transform) {
33 if(transform.dim1() != transform.dim2()) {
34 std::string m =
"Illegal transform matrix";
35 throw IException(IException::Programmer, m, _FILEINFO_);
38 p_dimensions = transform.dim1();
39 p_transform = transform;
42 p_hasTransform =
true;
48 void PrincipalComponentAnalysis::AddData(
const double *data,
const unsigned int count) {
52 std::string m =
"Cannot add data to a PCA that has a defined transform matrix";
53 throw IException(IException::Programmer, m, _FILEINFO_);
57 for(
int i = 0; i < p_dimensions; i++) {
58 for(
int j = 0; j <= i; j++) {
59 p_statistics[p_dimensions*i+j]->AddData(&data[count*i], &data[count*j], count);
65 void PrincipalComponentAnalysis::ComputeTransform() {
67 std::string m =
"This PCA already has a computed transform";
68 throw IException(IException::Programmer, m, _FILEINFO_);
71 TNT::Array2D<double> C(p_dimensions, p_dimensions);
72 for(
int i = 0; i < p_dimensions; i++) {
73 for(
int j = 0; j < p_dimensions; j++) {
74 C[i][j] = (p_statistics[p_dimensions*i+j])->Correlation();
78 JAMA::Eigenvalue<double>
E(C);
79 TNT::Array2D<double> D, V;
83 p_transform = TNT::Array2D<double>(V.dim1(), V.dim2());
89 for(
int i = 0; i < V.dim1(); i++) {
90 for(
int j = 0; j < V.dim2(); j++) {
91 p_transform[i][j] = V[i][V.dim2()-j-1];
97 p_hasTransform =
true;
101 void PrincipalComponentAnalysis::ComputeInverse() {
102 TNT::Array2D<double> id(p_transform.dim1(), p_transform.dim2(), 0.0);
103 for(
int i = 0; i < p_transform.dim1(); i++)
id[i][i] = 1;
105 JAMA::LU<double> lu(p_transform);
106 if(lu.det() == 0.0) {
107 std::string m =
"Cannot take the inverse of the transform matrix";
108 throw IException(IException::Programmer, m, _FILEINFO_);
111 p_inverse = lu.solve(
id);
115 TNT::Array2D<double> PrincipalComponentAnalysis::Transform(TNT::Array2D<double> data) {
116 if(data.dim1() != 1 || data.dim2() != p_dimensions) {
117 QString m =
"Transform input must be of dimension 1 x " + QString::number(p_dimensions);
118 throw IException(IException::Programmer, m, _FILEINFO_);
122 return TNT::matmult(data, p_transform);
126 TNT::Array2D<double> PrincipalComponentAnalysis::Inverse(TNT::Array2D<double> data) {
127 if(data.dim1() != 1 || data.dim2() != p_dimensions) {
128 QString m =
"Transform input must be of dimension 1 x " + QString::number(p_dimensions);
129 throw IException(IException::Programmer, m, _FILEINFO_);
133 return TNT::matmult(data, p_inverse);