Skip to content

Commit

Permalink
Merge pull request #2247 from SCIInstitute/2218-scalar-eval
Browse files Browse the repository at this point in the history
2218 scalar eval
  • Loading branch information
akenmorris committed May 6, 2024
2 parents 4e2dab7 + 6344e80 commit 0f03661
Show file tree
Hide file tree
Showing 18 changed files with 151 additions and 134 deletions.
6 changes: 3 additions & 3 deletions Applications/shapeworks/MeshCommands.cpp
Expand Up @@ -1439,14 +1439,14 @@ bool WarpMesh::execute(const optparse::Values &options, SharedCommandData &share
if (warp_along_with_landmarks) {
std::vector<std::string> landmarks_ar = {landmarkFilename};
ParticleSystemEvaluation landmarksystem(landmarks_ar);
Eigen::MatrixXd landmarksPoints = landmarksystem.Particles().col(0);
Eigen::MatrixXd landmarksPoints = landmarksystem.get_matrix().col(0);
numLandmarks = landmarksPoints.rows() / 3;
landmarksPoints.resize(3, numLandmarks);
landmarksPoints.transposeInPlace();
landmarks = landmarksPoints;
}

Eigen::MatrixXd allPts = particlesystem.Particles();
Eigen::MatrixXd allPts = particlesystem.get_matrix();
Eigen::MatrixXd staticPoints = allPts.col(targetPointsFilenames.size() - 1);
int numParticles = staticPoints.rows() / 3;
staticPoints.resize(3, numParticles);
Expand Down Expand Up @@ -1614,7 +1614,7 @@ bool LandmarkGeodesics::execute(const optparse::Values &options, SharedCommandDa
}

Eigen::VectorXd points;
if (!ParticleSystemEvaluation::ReadParticleFile(filename, points)) {
if (!ParticleSystemEvaluation::read_particle_file(filename, points)) {
SW_ERROR("Unable to read landmark file: {}", filename);
return false;
}
Expand Down
7 changes: 4 additions & 3 deletions Applications/shapeworks/ParticleSystemCommands.cpp
Expand Up @@ -54,7 +54,7 @@ bool Compactness::execute(const optparse::Values &options, SharedCommandData &sh

const int nModes = static_cast<int>(options.get("nmodes"));
const std::string saveTo = static_cast<std::string>(options.get("saveto"));
const double r = ShapeEvaluation::ComputeCompactness(sharedData.particleSystem, nModes, saveTo);
const double r = ShapeEvaluation::compute_compactness(sharedData.particleSystem, nModes, saveTo);
std::cout << "Particle system compactness: " << r << std::endl;

return true;
Expand Down Expand Up @@ -85,7 +85,8 @@ bool Generalization::execute(const optparse::Values &options, SharedCommandData

const int nModes = static_cast<int>(options.get("nmodes"));
const std::string saveTo = static_cast<std::string>(options.get("saveto"));
const double r = ShapeEvaluation::ComputeGeneralization(sharedData.particleSystem, nModes, saveTo);
const double r =
ShapeEvaluation::compute_generalization(sharedData.particleSystem, nModes, saveTo);
std::cout << "Particle system generalization: " << r << std::endl;

return true;
Expand Down Expand Up @@ -116,7 +117,7 @@ bool Specificity::execute(const optparse::Values &options, SharedCommandData &sh

const int nModes = static_cast<int>(options.get("nmodes"));
const std::string saveTo = static_cast<std::string>(options.get("saveto"));
const double r = ShapeEvaluation::ComputeSpecificity(sharedData.particleSystem, nModes, saveTo);
const double r = ShapeEvaluation::compute_specificity(sharedData.particleSystem, nModes, saveTo);
std::cout << "Particle system specificity: " << r << std::endl;

return true;
Expand Down
2 changes: 1 addition & 1 deletion Applications/shapeworks/SharedCommandData.h
Expand Up @@ -19,7 +19,7 @@ struct SharedCommandData

bool validImage() const { return image.itk_image_ != nullptr; }
bool validMesh() const { return mesh != nullptr; }
bool validParticleSystem() const {return particleSystem.N() >= 1 && particleSystem.D() >= 1; }
bool validParticleSystem() const {return particleSystem.num_samples() >= 1 && particleSystem.num_dims() >= 1; }
};


Expand Down
4 changes: 2 additions & 2 deletions Libs/Analyze/Analyze.cpp
Expand Up @@ -81,8 +81,8 @@ static void write_good_bad_angles(json& json_object, ProjectHandle project, Anal
}

auto base = analyze.get_local_particle_system(d);
auto normals = ParticleNormalEvaluation::compute_particle_normals(base.Particles(), meshes);
auto angles = ParticleNormalEvaluation::evaluate_particle_normals(base.Particles(), normals);
auto normals = ParticleNormalEvaluation::compute_particle_normals(base.get_matrix(), meshes);
auto angles = ParticleNormalEvaluation::evaluate_particle_normals(base.get_matrix(), normals);

// round angles to 2 decimal places
for (auto& angle : angles) {
Expand Down
2 changes: 1 addition & 1 deletion Libs/Analyze/Shape.cpp
Expand Up @@ -495,7 +495,7 @@ void Shape::generate_meshes(std::vector<std::string> filenames, MeshGroup& mesh_

//---------------------------------------------------------------------------
bool Shape::import_point_file(std::string filename, Eigen::VectorXd& points) {
return ParticleSystemEvaluation::ReadParticleFile(filename, points);
return ParticleSystemEvaluation::read_particle_file(filename, points);
}

//---------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion Libs/Optimize/OptimizeParameters.cpp
Expand Up @@ -670,7 +670,7 @@ bool OptimizeParameters::set_up_optimize(Optimize* optimize) {
if (get_use_geodesics_to_landmarks()) {
auto filenames = s->get_landmarks_filenames();
Eigen::VectorXd points;
if (!ParticleSystemEvaluation::ReadParticleFile(filenames[0], points)) {
if (!ParticleSystemEvaluation::read_particle_file(filenames[0], points)) {
SW_ERROR("Unable to read landmark file: {}", filenames[0]);
}

Expand Down
24 changes: 12 additions & 12 deletions Libs/Particles/ParticleShapeStatistics.cpp
Expand Up @@ -483,7 +483,7 @@ ParticleShapeStatistics::ParticleShapeStatistics(std::shared_ptr<Project> projec
Eigen::VectorXd particles;
for (auto& file : world_files) {
Eigen::VectorXd domain_particles;
ParticleSystemEvaluation::ReadParticleFile(file, domain_particles);
ParticleSystemEvaluation::read_particle_file(file, domain_particles);
Eigen::VectorXd combined(particles.size() + domain_particles.size());
combined << particles, domain_particles;
particles = combined;
Expand Down Expand Up @@ -551,7 +551,7 @@ int ParticleShapeStatistics::do_pca(std::vector<std::vector<Point>> global_pts,

//---------------------------------------------------------------------------
int ParticleShapeStatistics::do_pca(ParticleSystemEvaluation ParticleSystemEvaluation, int domainsPerShape) {
Eigen::MatrixXd p = ParticleSystemEvaluation.Particles();
Eigen::MatrixXd p = ParticleSystemEvaluation.get_matrix();

std::vector<std::vector<Point>> particlePoints;

Expand Down Expand Up @@ -650,14 +650,14 @@ int ParticleShapeStatistics::write_csv_file(const std::string& s) {
for (unsigned int i = 0; i < num_samples_; i++) {
outfile << ",P" << i;
}
outfile << std::endl;
outfile << "\n";

for (unsigned int r = 0; r < num_samples_; r++) {
outfile << group_ids_[r];
for (unsigned int c = 0; c < num_samples_; c++) {
outfile << "," << principals_(r, c);
}
outfile << std::endl;
outfile << "\n";
}

outfile.close();
Expand All @@ -666,26 +666,26 @@ int ParticleShapeStatistics::write_csv_file(const std::string& s) {

//---------------------------------------------------------------------------
Eigen::VectorXd ParticleShapeStatistics::get_compactness(const std::function<void(float)>& progress_callback) const {
auto ps = shapeworks::ParticleSystemEvaluation(this->matrix_);
return shapeworks::ShapeEvaluation::ComputeFullCompactness(ps, progress_callback);
auto ps = ParticleSystemEvaluation(matrix_);
return shapeworks::ShapeEvaluation::compute_full_compactness(ps, progress_callback);
}

//---------------------------------------------------------------------------
Eigen::VectorXd ParticleShapeStatistics::get_specificity(const std::function<void(float)>& progress_callback) const {
auto ps = shapeworks::ParticleSystemEvaluation(this->matrix_);
return shapeworks::ShapeEvaluation::ComputeFullSpecificity(ps, progress_callback);
auto ps = ParticleSystemEvaluation(matrix_);
return shapeworks::ShapeEvaluation::compute_full_specificity(ps, progress_callback);
}

//---------------------------------------------------------------------------
Eigen::VectorXd ParticleShapeStatistics::get_generalization(const std::function<void(float)>& progress_callback) const {
auto ps = shapeworks::ParticleSystemEvaluation(this->matrix_);
return shapeworks::ShapeEvaluation::ComputeFullGeneralization(ps, progress_callback);
auto ps = ParticleSystemEvaluation(matrix_);
return shapeworks::ShapeEvaluation::compute_full_generalization(ps, progress_callback);
}

//---------------------------------------------------------------------------
Eigen::MatrixXd ParticleShapeStatistics::get_group1_matrix() const { return this->group1_matrix_; }
Eigen::MatrixXd ParticleShapeStatistics::get_group1_matrix() const { return group1_matrix_; }

//---------------------------------------------------------------------------
Eigen::MatrixXd ParticleShapeStatistics::get_group2_matrix() const { return this->group2_matrix_; }
Eigen::MatrixXd ParticleShapeStatistics::get_group2_matrix() const { return group2_matrix_; }

} // namespace shapeworks
26 changes: 13 additions & 13 deletions Libs/Particles/ParticleSystemEvaluation.cpp
Expand Up @@ -15,19 +15,18 @@ ParticleSystemEvaluation::ParticleSystemEvaluation(const std::vector<std::string

paths_ = paths;
const int N = paths_.size();
const int VDimension = 3;
assert(N > 0);

// Read the first file to find dimensions
auto points0 = particles::read_particles_as_vector(paths_[0]);
const int D = points0.size() * VDimension;
const int D = points0.size() * num_values_per_particle_;

matrix_.resize(D, N);
matrix_.col(0) = Eigen::Map<const Eigen::VectorXd>((double*)points0.data(), D);

for (int i = 1; i < N; i++) {
auto points = particles::read_particles_as_vector(paths_[i]);
int count = points.size() * VDimension;
int count = points.size() * num_values_per_particle_;
if (count != D) {
throw std::runtime_error("ParticleSystemEvaluation files must have the same number of particles");
}
Expand All @@ -36,10 +35,11 @@ ParticleSystemEvaluation::ParticleSystemEvaluation(const std::vector<std::string
}

//---------------------------------------------------------------------------
ParticleSystemEvaluation::ParticleSystemEvaluation(const Eigen::MatrixXd& matrix) { matrix_ = matrix; }
ParticleSystemEvaluation::ParticleSystemEvaluation(const Eigen::MatrixXd& matrix, int num_values_per_particle)
: matrix_(matrix), num_values_per_particle_(num_values_per_particle) {}

//---------------------------------------------------------------------------
bool ParticleSystemEvaluation::ExactCompare(const ParticleSystemEvaluation& other) const {
bool ParticleSystemEvaluation::exact_compare(const ParticleSystemEvaluation& other) const {
if (matrix_.rows() != other.matrix_.rows() || matrix_.cols() != other.matrix_.cols()) {
std::cerr << "Rows/Columns mismatch\n";
return false;
Expand All @@ -57,9 +57,9 @@ bool ParticleSystemEvaluation::ExactCompare(const ParticleSystemEvaluation& othe
}

//---------------------------------------------------------------------------
bool ParticleSystemEvaluation::EvaluationCompare(const ParticleSystemEvaluation& other) const {
auto compactness1 = ShapeEvaluation::ComputeFullCompactness(*this);
auto compactness2 = ShapeEvaluation::ComputeFullCompactness(other);
bool ParticleSystemEvaluation::evaluation_compare(const ParticleSystemEvaluation& other) const {
auto compactness1 = ShapeEvaluation::compute_full_compactness(*this);
auto compactness2 = ShapeEvaluation::compute_full_compactness(other);
if (compactness1.size() != compactness2.size()) {
std::cout << "Shape models have a different number of modes: " << compactness1.size() << " and "
<< compactness2.size() << "\n";
Expand All @@ -77,8 +77,8 @@ bool ParticleSystemEvaluation::EvaluationCompare(const ParticleSystemEvaluation&
}
}

auto gen1 = ShapeEvaluation::ComputeFullGeneralization(*this);
auto gen2 = ShapeEvaluation::ComputeFullGeneralization(other);
auto gen1 = ShapeEvaluation::compute_full_generalization(*this);
auto gen2 = ShapeEvaluation::compute_full_generalization(other);
if (gen1.size() != gen2.size()) {
return false;
}
Expand All @@ -93,8 +93,8 @@ bool ParticleSystemEvaluation::EvaluationCompare(const ParticleSystemEvaluation&
}
}

auto spec1 = ShapeEvaluation::ComputeFullSpecificity(*this);
auto spec2 = ShapeEvaluation::ComputeFullSpecificity(other);
auto spec1 = ShapeEvaluation::compute_full_specificity(*this);
auto spec2 = ShapeEvaluation::compute_full_specificity(other);
if (spec1.size() != spec2.size()) {
return false;
}
Expand All @@ -113,7 +113,7 @@ bool ParticleSystemEvaluation::EvaluationCompare(const ParticleSystemEvaluation&
}

//---------------------------------------------------------------------------
bool ParticleSystemEvaluation::ReadParticleFile(std::string filename, Eigen::VectorXd& points) {
bool ParticleSystemEvaluation::read_particle_file(std::string filename, Eigen::VectorXd& points) {
points = particles::read_particles(filename);
return true;
}
Expand Down
34 changes: 22 additions & 12 deletions Libs/Particles/ParticleSystemEvaluation.h
Expand Up @@ -7,34 +7,44 @@ namespace shapeworks {

class ParticleSystemEvaluation {
public:
ParticleSystemEvaluation(const std::vector<std::string>& paths);
//! Initialize particle system from a list of paths to particle files
explicit ParticleSystemEvaluation(const std::vector<std::string>& paths);

// Initialize particle system from eigen matrix (rows=dimensions, cols=num_samples)
ParticleSystemEvaluation(const Eigen::MatrixXd& matrix);
//! Initialize particle system from eigen matrix (rows=dimensions, cols=num_samples)
explicit ParticleSystemEvaluation(const Eigen::MatrixXd& matrix, int num_values_per_particle = 3);

const Eigen::MatrixXd& Particles() const { return matrix_; };
//! Get the matrix representation of the particle system
const Eigen::MatrixXd& get_matrix() const { return matrix_; };

const std::vector<std::string>& Paths() const { return paths_; }
//! Get the number of values for each particle (e.g. 3 for x/y/z, 4 for x/y/z/scalar)
int get_num_values_per_particle() const { return num_values_per_particle_; }

//! Get the paths to the particle files
const std::vector<std::string>& get_paths() const { return paths_; }

//! Number of samples
int N() const { return matrix_.cols(); }
long num_samples() const { return matrix_.cols(); }

//! Dimensions (e.g. x/y/z * number of particles)
int D() const { return matrix_.rows(); }
long num_dims() const { return matrix_.rows(); }

bool ExactCompare(const ParticleSystemEvaluation& other) const;
//! Perform an exact comparison of two particle systems
bool exact_compare(const ParticleSystemEvaluation& other) const;

bool EvaluationCompare(const ParticleSystemEvaluation& other) const;
//! Perform an evaluation comparison of two particle systems
bool evaluation_compare(const ParticleSystemEvaluation& other) const;

static bool ReadParticleFile(std::string filename, Eigen::VectorXd& points);
//! Read a particle file into an Eigen vector
static bool read_particle_file(std::string filename, Eigen::VectorXd& points);

private:
friend struct SharedCommandData;

ParticleSystemEvaluation() {
} // only for use by SharedCommandData since a ParticleSystem should always be valid, never "empty"
//! only for use by SharedCommandData since a ParticleSystem should always be valid, never "empty"
ParticleSystemEvaluation() {}

Eigen::MatrixXd matrix_;
std::vector<std::string> paths_;
int num_values_per_particle_ = 3; // e.g. 3 for x/y/z, 4 for x/y/z/scalar, 1 for scalar-only
};
} // namespace shapeworks

0 comments on commit 0f03661

Please sign in to comment.