Skip to content

Commit 38be981

Browse files
authored
Merge pull request #2118 from SCIInstitute/fix_matrix_2117
Switch to eigen matrix for inverse covariance matrix to fix #2117
2 parents 9629116 + 4e0cd8e commit 38be981

6 files changed

Lines changed: 44 additions & 20 deletions

File tree

Libs/Optimize/Function/CorrespondenceFunction.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ void CorrespondenceFunction::ComputeUpdates(const ParticleSystem* c) {
4141

4242
if (this->m_UseMeanEnergy) {
4343
pinvMat.set_identity();
44-
m_InverseCovMatrix->clear();
44+
45+
m_InverseCovMatrix->setZero();
46+
4547
} else {
4648
gramMat = points_minus_mean.transpose() * points_minus_mean;
4749

@@ -60,7 +62,11 @@ void CorrespondenceFunction::ComputeUpdates(const ParticleSystem* c) {
6062
const auto lhs = projMat * invLambda;
6163
const auto rhs =
6264
invLambda * projMat.transpose(); // invLambda doesn't need to be transposed since its a diagonal matrix
63-
m_InverseCovMatrix->set_size(num_dims, num_dims);
65+
66+
// resize the inverse covariance matrix if necessary
67+
if (m_InverseCovMatrix->rows() != num_dims || m_InverseCovMatrix->cols() != num_dims) {
68+
m_InverseCovMatrix->resize(num_dims, num_dims);
69+
}
6470
Utils::multiply_into(*m_InverseCovMatrix, lhs, rhs);
6571
}
6672

@@ -166,7 +172,14 @@ CorrespondenceFunction::VectorType CorrespondenceFunction::Evaluate(unsigned int
166172
if (this->m_UseMeanEnergy) {
167173
tmp1.set_identity();
168174
} else {
169-
tmp1 = m_InverseCovMatrix->extract(sz_Yidx, sz_Yidx, num, num);
175+
// extract 3x3 submatrix at k,k
176+
Eigen::MatrixXd region = m_InverseCovMatrix->block(sz_Yidx, sz_Yidx, 3, 3);
177+
// convert to vnl
178+
for (unsigned int i = 0; i < 3; i++) {
179+
for (unsigned int j = 0; j < 3; j++) {
180+
tmp1(i, j) = region(i, j);
181+
}
182+
}
170183
}
171184

172185
vnl_matrix_type Y_dom_idx(sz_Yidx, 1, 0.0);

Libs/Optimize/Function/CorrespondenceFunction.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ class CorrespondenceFunction : public VectorFunction {
175175
num_dims = 0;
176176
num_samples = 0;
177177
m_PointsUpdate = std::make_shared<vnl_matrix_type>(10, 10);
178-
m_InverseCovMatrix = std::make_shared<vnl_matrix_type>(10, 10);
178+
m_InverseCovMatrix = std::make_shared<Eigen::MatrixXd>(10, 10);
179179
m_points_mean = std::make_shared<vnl_matrix_type>(10, 10);
180180
}
181181
virtual ~CorrespondenceFunction() {}
@@ -203,7 +203,7 @@ class CorrespondenceFunction : public VectorFunction {
203203
std::vector<bool> m_UseXYZ;
204204
std::vector<bool> m_UseNormals;
205205
std::shared_ptr<vnl_matrix_type> m_points_mean;
206-
std::shared_ptr<vnl_matrix_type> m_InverseCovMatrix;
206+
std::shared_ptr<Eigen::MatrixXd> m_InverseCovMatrix;
207207
int num_dims, num_samples;
208208
};
209209
} // namespace shapeworks

Libs/Optimize/Function/LegacyCorrespondenceFunction.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ void LegacyCorrespondenceFunction ::ComputeCovarianceMatrix() {
6363

6464
if (this->m_UseMeanEnergy) {
6565
pinvMat.set_identity();
66-
m_InverseCovMatrix->clear();
66+
m_InverseCovMatrix->setZero();
6767
} else {
6868
gramMat = points_minus_mean.transpose() * points_minus_mean;
6969

@@ -83,7 +83,9 @@ void LegacyCorrespondenceFunction ::ComputeCovarianceMatrix() {
8383
const auto lhs = projMat * invLambda;
8484
const auto rhs =
8585
invLambda * projMat.transpose(); // invLambda doesn't need to be transposed since its a diagonal matrix
86-
m_InverseCovMatrix->set_size(num_dims, num_dims);
86+
if (m_InverseCovMatrix->rows() != num_dims || m_InverseCovMatrix->cols() != num_dims) {
87+
m_InverseCovMatrix->resize(num_dims, num_dims);
88+
}
8789
Utils::multiply_into(*m_InverseCovMatrix, lhs, rhs);
8890
}
8991
m_PointsUpdate->update(points_minus_mean * pinvMat);
@@ -108,9 +110,8 @@ void LegacyCorrespondenceFunction ::ComputeCovarianceMatrix() {
108110
}
109111

110112
LegacyCorrespondenceFunction::VectorType LegacyCorrespondenceFunction ::Evaluate(unsigned int idx, unsigned int d,
111-
const ParticleSystem* system,
112-
double& maxdt,
113-
double& energy) const {
113+
const ParticleSystem* system,
114+
double& maxdt, double& energy) const {
114115
// NOTE: This code requires that indices be contiguous, i.e. it won't work if
115116
// you start deleting particles.
116117
const unsigned int DomainsPerShape = m_ShapeMatrix->GetDomainsPerShape();
@@ -130,10 +131,18 @@ LegacyCorrespondenceFunction::VectorType LegacyCorrespondenceFunction ::Evaluate
130131

131132
vnl_matrix_type tmp1(3, 3, 0.0);
132133

133-
if (this->m_UseMeanEnergy)
134+
if (this->m_UseMeanEnergy) {
134135
tmp1.set_identity();
135-
else
136-
tmp1 = m_InverseCovMatrix->extract(3, 3, k, k);
136+
} else {
137+
// extract 3x3 submatrix at k,k
138+
Eigen::MatrixXd region = m_InverseCovMatrix->block(k, k, 3, 3);
139+
// convert to vnl
140+
for (unsigned int i = 0; i < 3; i++) {
141+
for (unsigned int j = 0; j < 3; j++) {
142+
tmp1(i, j) = region(i, j);
143+
}
144+
}
145+
}
137146

138147
vnl_matrix_type tmp = Xi.transpose() * tmp1;
139148

Libs/Optimize/Function/LegacyCorrespondenceFunction.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ class LegacyCorrespondenceFunction : public VectorFunction {
144144
m_Counter = 0;
145145
m_UseMeanEnergy = true;
146146
m_PointsUpdate = std::make_shared<vnl_matrix_type>(10, 10);
147-
m_InverseCovMatrix = std::make_shared<vnl_matrix_type>(10, 10);
147+
m_InverseCovMatrix = std::make_shared<Eigen::MatrixXd>(10, 10);
148148
m_points_mean = std::make_shared<vnl_matrix_type>(10, 10);
149149
}
150150
virtual ~LegacyCorrespondenceFunction() {}
@@ -164,7 +164,7 @@ class LegacyCorrespondenceFunction : public VectorFunction {
164164
bool m_UseMeanEnergy;
165165

166166
std::shared_ptr<vnl_matrix_type> m_points_mean; // 3Nx3N - used for energy computation
167-
std::shared_ptr<vnl_matrix_type> m_InverseCovMatrix; // 3NxM - used for energy computation
167+
std::shared_ptr<Eigen::MatrixXd> m_InverseCovMatrix; // 3NxM - used for energy computation
168168
};
169169

170170
} // namespace shapeworks

Libs/Utils/Utils.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -412,17 +412,17 @@ std::string Utils::int2str(int n, int number_of_zeros)
412412
// A, VXL does an extra allocation and copy. This could be many GB large. Additionally Eigen
413413
// is slightly faster.
414414
template<typename T>
415-
void Utils::multiply_into(vnl_matrix<T> &out, const vnl_matrix<T> &lhs, const vnl_matrix<T> &rhs) {
415+
void Utils::multiply_into(Eigen::MatrixXd &out, const vnl_matrix<T> &lhs, const vnl_matrix<T> &rhs) {
416416
typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> RowMajorMatrix;
417-
Eigen::Map<RowMajorMatrix> eig_out(out.data_block(), out.rows(), out.cols());
417+
//Eigen::Map<RowMajorMatrix> eig_out(out.data_block(), out.rows(), out.cols());
418418
Eigen::Map<const RowMajorMatrix> eig_lhs(lhs.data_block(), lhs.rows(), lhs.cols());
419419
Eigen::Map<const RowMajorMatrix> eig_rhs(rhs.data_block(), rhs.rows(), rhs.cols());
420-
eig_out.noalias() = eig_lhs * eig_rhs;
420+
out.noalias() = eig_lhs * eig_rhs;
421421
}
422422

423423
// Explicitly instantiate this function templatized over double
424424
template void
425-
Utils::multiply_into(vnl_matrix<double> &, const vnl_matrix<double> &, const vnl_matrix<double> &);
425+
Utils::multiply_into(Eigen::MatrixXd &, const vnl_matrix<double> &, const vnl_matrix<double> &);
426426

427427

428428
//--------------- average normal directions --------------------------------

Libs/Utils/Utils.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#endif
2222
#endif
2323

24+
#include <Eigen/Core>
25+
2426
#include <math.h>
2527
#include <iostream>
2628
#include <map>
@@ -101,7 +103,7 @@ class Utils{
101103

102104
// matrix multiplication without an allocation for the output
103105
template<typename T>
104-
static void multiply_into(vnl_matrix<T> &out, const vnl_matrix<T> &lhs, const vnl_matrix<T> &rhs);
106+
static void multiply_into(Eigen::MatrixXd &out, const vnl_matrix<T> &lhs, const vnl_matrix<T> &rhs);
105107

106108
//--------------- average normal directions --------------------------------
107109
/**

0 commit comments

Comments
 (0)