From 731aee8794daaddea54e47dd2b4379afdc26eba2 Mon Sep 17 00:00:00 2001 From: Alan Morris Date: Wed, 27 Mar 2024 14:33:39 -0600 Subject: [PATCH 1/5] Address part of #2218. This commit adds the ability to see both the predicted scalar on all samples as well as the diff to predicted. --- Libs/Analyze/StudioMesh.cpp | 2 +- Studio/Analysis/AnalysisTool.cpp | 63 +++++++++++++++++++ Studio/Analysis/AnalysisTool.h | 2 + Studio/Analysis/AnalysisTool.ui | 80 +++++++++++++++++++----- Studio/Data/Session.cpp | 22 ++++++- Studio/Data/Session.h | 1 + Studio/Interface/ShapeWorksStudioApp.cpp | 31 ++------- Studio/Interface/ShapeWorksStudioApp.h | 3 - 8 files changed, 155 insertions(+), 49 deletions(-) diff --git a/Libs/Analyze/StudioMesh.cpp b/Libs/Analyze/StudioMesh.cpp index d5e6eb3eb0..d15ac9e5ec 100644 --- a/Libs/Analyze/StudioMesh.cpp +++ b/Libs/Analyze/StudioMesh.cpp @@ -98,7 +98,7 @@ void StudioMesh::interpolate_scalars_to_mesh(std::string name, Eigen::VectorXd p if (num_points != scalar_values.size()) { std::cerr << "Warning, mismatch of points and scalar values (num_points = " << num_points - << ", scalar_values.size() = " << scalar_values.size() << std::endl; + << ", scalar_values.size() = " << scalar_values.size() << ")\n"; return; } diff --git a/Studio/Analysis/AnalysisTool.cpp b/Studio/Analysis/AnalysisTool.cpp index ab001092e1..7c12e1bd93 100644 --- a/Studio/Analysis/AnalysisTool.cpp +++ b/Studio/Analysis/AnalysisTool.cpp @@ -161,6 +161,23 @@ AnalysisTool::AnalysisTool(Preferences& prefs) : preferences_(prefs) { connect(ui_->group_analysis_combo, qOverload(&QComboBox::currentIndexChanged), this, &AnalysisTool::group_analysis_combo_changed); + + // when one is checked, turn the other off, connect these first + connect(ui_->show_difference_to_predicted_scalar, &QPushButton::clicked, this, [this]() { + if (ui_->show_difference_to_predicted_scalar->isChecked()) { + ui_->show_predicted_scalar->setChecked(false); + } + }); + connect(ui_->show_predicted_scalar, &QPushButton::clicked, this, [this]() { + if (ui_->show_predicted_scalar->isChecked()) { + ui_->show_difference_to_predicted_scalar->setChecked(false); + } + }); + + connect(ui_->show_difference_to_predicted_scalar, &QPushButton::clicked, this, + &AnalysisTool::handle_samples_predicted_scalar_options); + connect(ui_->show_predicted_scalar, &QPushButton::clicked, this, + &AnalysisTool::handle_samples_predicted_scalar_options); } //--------------------------------------------------------------------------- @@ -280,6 +297,9 @@ void AnalysisTool::set_session(QSharedPointer session) { ui_->group2_button->setChecked(false); update_difference_particles(); + ui_->show_predicted_scalar->setChecked(false); + ui_->show_difference_to_predicted_scalar->setChecked(false); + connect(ui_->show_good_bad, &QCheckBox::toggled, session_.data(), &Session::set_show_good_bad_particles); } @@ -1091,6 +1111,11 @@ void AnalysisTool::reset_stats() { ui_->pca_scalar_combo->addItem(QString::fromStdString(feature)); } } + bool has_scalars = ui_->pca_scalar_combo->count() > 0; + if (!has_scalars) { + ui_->show_difference_to_predicted_scalar->setChecked(false); + } + ui_->show_difference_to_predicted_scalar->setEnabled(has_scalars); ui_->shape_scalar_groupbox->setVisible(ui_->pca_scalar_combo->count() > 0); } @@ -1303,6 +1328,15 @@ std::string AnalysisTool::get_display_feature_map() { } } + if (get_analysis_mode() == AnalysisTool::MODE_ALL_SAMPLES_C && + ui_->show_difference_to_predicted_scalar->isChecked()) { + return "predicted_scalar_diff"; + } + + if (get_analysis_mode() == AnalysisTool::MODE_ALL_SAMPLES_C && ui_->show_predicted_scalar->isChecked()) { + return "predicted_scalar"; + } + return feature_map_; } @@ -1763,6 +1797,11 @@ void AnalysisTool::change_pca_analysis_type() { ui_->pca_predict_scalar->setEnabled(ui_->pca_scalar_shape_only->isChecked()); ui_->pca_predict_shape->setEnabled(ui_->pca_scalar_only->isChecked()); + if (ui_->pca_predict_scalar->isChecked()) { + // set the feature map to the target feature + session_->set_feature_map(ui_->pca_scalar_combo->currentText().toStdString()); + } + compute_stats(); Q_EMIT pca_update(); } @@ -1785,6 +1824,30 @@ Eigen::VectorXd AnalysisTool::construct_mean_shape() { return mean_shape; } +//--------------------------------------------------------------------------- +void AnalysisTool::handle_samples_predicted_scalar_options() { + if (ui_->show_difference_to_predicted_scalar->isChecked() || ui_->show_predicted_scalar->isChecked()) { + // iterate over all samples, predict scalars, compute the difference and store as a new scalar field + auto shapes = session_->get_non_excluded_shapes(); + for (auto& shape : shapes) { + auto particles = shape->get_particles(); + auto target_feature = ui_->pca_scalar_combo->currentText(); + auto predicted = + ShapeScalarJob::predict_scalars(session_, target_feature, particles.get_combined_global_particles()); + + // load the mesh and feature + shape->get_meshes(session_->get_display_mode(), true); + shape->load_feature(session_->get_display_mode(), target_feature.toStdString()); + auto scalars = shape->get_point_features(target_feature.toStdString()); + // compute difference + auto diff = predicted - scalars; + shape->set_point_features("predicted_scalar_diff", diff); + shape->set_point_features("predicted_scalar", predicted); + } + } + Q_EMIT update_view(); +} + //--------------------------------------------------------------------------- void AnalysisTool::reconstruction_method_changed() { ui_->reconstruction_options->setVisible(ui_->distance_transform_radio_button->isChecked()); diff --git a/Studio/Analysis/AnalysisTool.h b/Studio/Analysis/AnalysisTool.h index 5678850dc2..19921d7735 100644 --- a/Studio/Analysis/AnalysisTool.h +++ b/Studio/Analysis/AnalysisTool.h @@ -197,6 +197,8 @@ class AnalysisTool : public QWidget { //! Compute the mean shape outside of the PCA in case we are using scalars only Eigen::VectorXd construct_mean_shape(); + void handle_samples_predicted_scalar_options(); + Q_SIGNALS: void update_view(); diff --git a/Studio/Analysis/AnalysisTool.ui b/Studio/Analysis/AnalysisTool.ui index 6067da6599..24370ec049 100644 --- a/Studio/Analysis/AnalysisTool.ui +++ b/Studio/Analysis/AnalysisTool.ui @@ -535,7 +535,7 @@ QWidget#particles_panel { - 2 + 1 @@ -1089,16 +1089,6 @@ QWidget#particles_panel { Samples - - - - false - - - Sample selection - - - @@ -1109,6 +1099,19 @@ QWidget#particles_panel { + + + + false + + + Show median sample + + + Median + + + @@ -1122,19 +1125,62 @@ QWidget#particles_panel { - - + + + + + + + Show difference to predicted scalar + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Show predicted scalar + + + + + + + + false - Show median sample - - - Median + Sample selection + + + + Qt::Vertical + + + + 20 + 40 + + + + diff --git a/Studio/Data/Session.cpp b/Studio/Data/Session.cpp index b7576ce6ba..26b335d644 100644 --- a/Studio/Data/Session.cpp +++ b/Studio/Data/Session.cpp @@ -1138,11 +1138,23 @@ bool Session::get_image_thickness_feature() { return params_.get("image_thicknes void Session::set_feature_map(std::string feature_map) { if (feature_map != get_feature_map() || is_loading()) { params_.set("feature_map", feature_map); + Q_EMIT feature_map_changed(); } } //--------------------------------------------------------------------------- -std::string Session::get_feature_map() { return params_.get("feature_map", ""); } +std::string Session::get_feature_map() { + std::string feature_map = params_.get("feature_map", ""); + + // confirm that this is a valid feature map + auto feature_maps = get_project()->get_feature_names(); + for (const std::string& feature : feature_maps) { + if (feature_map == feature) { + return feature_map; + } + } + return ""; +} //--------------------------------------------------------------------------- bool Session::has_constraints() { @@ -1281,6 +1293,14 @@ Eigen::MatrixXd Session::get_all_scalars(std::string target_feature) { Eigen::VectorXd scalars = shapes[i]->get_point_features(target_feature); + // check that the scalars are the right size + if (scalars.size() != num_particles) { + SW_ERROR("scalars.size() : {}", scalars.size()); + SW_ERROR("num_particles : {}", num_particles); + SW_ERROR("Error: scalars size does not match number of particles"); + return Eigen::MatrixXd(); + } + // write into all_scalars all_scalars.row(i) = scalars.transpose(); } diff --git a/Studio/Data/Session.h b/Studio/Data/Session.h index 69f38e22b4..c1d217bb1c 100644 --- a/Studio/Data/Session.h +++ b/Studio/Data/Session.h @@ -285,6 +285,7 @@ class Session : public QObject, public QEnableSharedFromThis { void planes_changed(); void ffc_changed(); void update_display(); + void feature_map_changed(); void reset_stats(); void new_mesh(); void feature_range_changed(); diff --git a/Studio/Interface/ShapeWorksStudioApp.cpp b/Studio/Interface/ShapeWorksStudioApp.cpp index 375696365a..9156421d40 100644 --- a/Studio/Interface/ShapeWorksStudioApp.cpp +++ b/Studio/Interface/ShapeWorksStudioApp.cpp @@ -423,7 +423,7 @@ void ShapeWorksStudioApp::import_files(QStringList file_names) { if (first_load) { // On first load, we can check if there was an active scalar on loaded meshes - set_feature_map(session_->get_default_feature_map()); + session_->set_feature_map(session_->get_default_feature_map()); } } catch (std::runtime_error& e) { handle_error(e.what()); @@ -970,6 +970,7 @@ void ShapeWorksStudioApp::new_session() { connect(session_.data(), &Session::reset_stats, this, &ShapeWorksStudioApp::handle_reset_stats); connect(session_.data(), &Session::update_display, this, &ShapeWorksStudioApp::handle_display_setting_changed); connect(session_.data(), &Session::update_view_mode, this, &ShapeWorksStudioApp::update_view_mode); + connect(session_.data(), &Session::feature_map_changed, this, &ShapeWorksStudioApp::update_view_mode); connect(session_.data(), &Session::new_mesh, this, &ShapeWorksStudioApp::handle_new_mesh); connect(session_.data(), &Session::reinsert_shapes, this, [&]() { update_display(true); }); connect(session_.data(), &Session::save, this, &ShapeWorksStudioApp::on_action_save_project_triggered); @@ -1087,7 +1088,7 @@ void ShapeWorksStudioApp::update_view_mode() { ui_->view_mode_combobox->setCurrentText(QString::fromStdString(display_mode_to_string(view_mode))); update_view_combo(); - auto feature_map = get_feature_map(); + auto feature_map = session_->get_feature_map(); ui_->features->setCurrentText(QString::fromStdString(feature_map)); if (visualizer_) { @@ -2041,7 +2042,7 @@ QString ShapeWorksStudioApp::get_mesh_file_filter() { //--------------------------------------------------------------------------- void ShapeWorksStudioApp::update_feature_map_selection(int index) { QString feature_map = ui_->features->itemText(index); - set_feature_map(feature_map.toStdString()); + session_->set_feature_map(feature_map.toStdString()); } //--------------------------------------------------------------------------- @@ -2065,30 +2066,6 @@ void ShapeWorksStudioApp::image_combo_changed(int index) { session_->set_image_name(ui_->image_combo_->itemText(index).toStdString()); } -//--------------------------------------------------------------------------- -bool ShapeWorksStudioApp::set_feature_map(std::string feature_map) { - if (feature_map != get_feature_map()) { - session_->set_feature_map(feature_map); - update_view_mode(); - return true; - } - return false; -} - -//--------------------------------------------------------------------------- -std::string ShapeWorksStudioApp::get_feature_map() { - std::string feature_map = session_->get_feature_map(); - - // confirm that this is a valid feature map - auto feature_maps = session_->get_project()->get_feature_names(); - for (const std::string& feature : feature_maps) { - if (feature_map == feature) { - return feature_map; - } - } - return ""; -} - //--------------------------------------------------------------------------- bool ShapeWorksStudioApp::get_feature_uniform_scale() { return session_->parameters().get("feature_uniform_scale", true); diff --git a/Studio/Interface/ShapeWorksStudioApp.h b/Studio/Interface/ShapeWorksStudioApp.h index 6938ece1b0..3c8e8404c8 100644 --- a/Studio/Interface/ShapeWorksStudioApp.h +++ b/Studio/Interface/ShapeWorksStudioApp.h @@ -195,9 +195,6 @@ class ShapeWorksStudioApp : public QMainWindow { void display_mode_shape(); - bool set_feature_map(std::string feature_map); - std::string get_feature_map(); - bool get_feature_uniform_scale(); void set_feature_uniform_scale(bool value); From 343f58500c9b2a05580bb3a781c6e36e959d6c1f Mon Sep 17 00:00:00 2001 From: Alan Morris Date: Wed, 27 Mar 2024 14:52:56 -0600 Subject: [PATCH 2/5] Restyle/reformat ShapeEvaluationJob --- Studio/Analysis/ShapeEvaluationJob.cpp | 48 +++++++++++--------------- Studio/Analysis/ShapeEvaluationJob.h | 24 ++++++------- 2 files changed, 32 insertions(+), 40 deletions(-) diff --git a/Studio/Analysis/ShapeEvaluationJob.cpp b/Studio/Analysis/ShapeEvaluationJob.cpp index 69d8234812..cb8a509a47 100644 --- a/Studio/Analysis/ShapeEvaluationJob.cpp +++ b/Studio/Analysis/ShapeEvaluationJob.cpp @@ -1,44 +1,38 @@ - +#include "ShapeEvaluationJob.h" #include -#include "ShapeEvaluationJob.h" + namespace shapeworks { //----------------------------------------------------------------------------- ShapeEvaluationJob::ShapeEvaluationJob(JobType job_type, ParticleShapeStatistics stats) - : job_type_(job_type), stats_(stats) -{ - qRegisterMetaType( - "shapeworks::ShapeEvaluationWorker::JobType"); + : job_type_(job_type), stats_(stats) { + qRegisterMetaType("shapeworks::ShapeEvaluationWorker::JobType"); qRegisterMetaType("Eigen::VectorXd"); } //----------------------------------------------------------------------------- -void ShapeEvaluationJob::run() -{ +void ShapeEvaluationJob::run() { auto callback = std::bind(&ShapeEvaluationJob::receive_progress, this, std::placeholders::_1); - switch (this->job_type_) { - case JobType::CompactnessType: - Q_EMIT result_ready(this->job_type_, this->stats_.get_compactness(callback)); - break; - case JobType::GeneralizationType: - Q_EMIT result_ready(this->job_type_, this->stats_.get_generalization(callback)); - break; - case JobType::SpecificityType: - Q_EMIT result_ready(this->job_type_, this->stats_.get_specificity(callback)); - break; + switch (job_type_) { + case JobType::CompactnessType: + Q_EMIT result_ready(job_type_, stats_.get_compactness(callback)); + break; + case JobType::GeneralizationType: + Q_EMIT result_ready(job_type_, stats_.get_generalization(callback)); + break; + case JobType::SpecificityType: + Q_EMIT result_ready(job_type_, stats_.get_specificity(callback)); + break; } } //----------------------------------------------------------------------------- -QString ShapeEvaluationJob::name() -{ - return "Shape Evaluation"; -} +QString ShapeEvaluationJob::name() { return "Shape Evaluation"; } //----------------------------------------------------------------------------- -void ShapeEvaluationJob::receive_progress(float progress) -{ - Q_EMIT report_progress(this->job_type_, progress); -} -} +void ShapeEvaluationJob::receive_progress(float progress) { Q_EMIT report_progress(job_type_, progress); } + +//----------------------------------------------------------------------------- + +} // namespace shapeworks diff --git a/Studio/Analysis/ShapeEvaluationJob.h b/Studio/Analysis/ShapeEvaluationJob.h index b1c1407d72..ca70da7251 100644 --- a/Studio/Analysis/ShapeEvaluationJob.h +++ b/Studio/Analysis/ShapeEvaluationJob.h @@ -1,20 +1,19 @@ #pragma once -#include - #include #include +#include namespace shapeworks { -class ShapeEvaluationJob : public Job -{ +/** + * @brief The ShapeEvaluationJob class is a worker class that computes shape evaluation metrics of compactness, + * specificity, and generalization. It runs asynchronously using the Job and Worker interfaces. + */ +class ShapeEvaluationJob : public Job { Q_OBJECT -public: - - enum class JobType { - CompactnessType, SpecificityType, GeneralizationType - }; + public: + enum class JobType { CompactnessType, SpecificityType, GeneralizationType }; ShapeEvaluationJob(JobType job_type, ParticleShapeStatistics stats); @@ -22,19 +21,18 @@ class ShapeEvaluationJob : public Job QString name() override; -Q_SIGNALS: + Q_SIGNALS: void report_progress(shapeworks::ShapeEvaluationJob::JobType job_type, float progress); void result_ready(shapeworks::ShapeEvaluationJob::JobType job_type, Eigen::VectorXd data); -private: - + private: void receive_progress(float progress); JobType job_type_; ParticleShapeStatistics stats_; }; -} +} // namespace shapeworks Q_DECLARE_METATYPE(Eigen::VectorXd); Q_DECLARE_METATYPE(shapeworks::ShapeEvaluationJob::JobType); From 7573599f94e12b8a3435013b2fd54e90ae1be4c3 Mon Sep 17 00:00:00 2001 From: Alan Morris Date: Wed, 27 Mar 2024 15:00:11 -0600 Subject: [PATCH 3/5] Restyle ParticleSystemEvaluation. --- Libs/Particles/ParticleSystemEvaluation.cpp | 37 ++++++++++++--------- Libs/Particles/ParticleSystemEvaluation.h | 12 +++---- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/Libs/Particles/ParticleSystemEvaluation.cpp b/Libs/Particles/ParticleSystemEvaluation.cpp index fef1d496fb..7199d89684 100644 --- a/Libs/Particles/ParticleSystemEvaluation.cpp +++ b/Libs/Particles/ParticleSystemEvaluation.cpp @@ -7,13 +7,14 @@ namespace shapeworks { -ParticleSystemEvaluation::ParticleSystemEvaluation(const std::vector& _paths) { - if (_paths.empty()) { +//--------------------------------------------------------------------------- +ParticleSystemEvaluation::ParticleSystemEvaluation(const std::vector& paths) { + if (paths.empty()) { throw std::runtime_error("No filenames passed to readParticleSystemEvaluation"); } - this->paths = _paths; - const int N = paths.size(); + paths_ = paths; + const int N = paths_.size(); const int VDimension = 3; assert(N > 0); @@ -23,34 +24,36 @@ ParticleSystemEvaluation::ParticleSystemEvaluation(const std::vector((double*)points0.data(), D); + matrix_.resize(D, N); + matrix_.col(0) = Eigen::Map((double*)points0.data(), D); for (int i = 1; i < N; i++) { - auto points = particles::read_particles_as_vector(paths[i]); + auto points = particles::read_particles_as_vector(paths_[i]); int count = points.size() * VDimension; if (count != D) { throw std::runtime_error("ParticleSystemEvaluation files must have the same number of particles"); } - P.col(i) = Eigen::Map((double*)points.data(), D); + matrix_.col(i) = Eigen::Map((double*)points.data(), D); } } -ParticleSystemEvaluation::ParticleSystemEvaluation(const Eigen::MatrixXd& matrix) { this->P = matrix; } +//--------------------------------------------------------------------------- +ParticleSystemEvaluation::ParticleSystemEvaluation(const Eigen::MatrixXd& matrix) { matrix_ = matrix; } +//--------------------------------------------------------------------------- bool ParticleSystemEvaluation::ExactCompare(const ParticleSystemEvaluation& other) const { - if (P.rows() != other.P.rows() || P.cols() != other.P.cols()) { + if (matrix_.rows() != other.matrix_.rows() || matrix_.cols() != other.matrix_.cols()) { std::cerr << "Rows/Columns mismatch\n"; return false; } bool same = true; - for (int r = 0; r < P.rows(); r++) { - for (int c = 0; c < P.cols(); c++) { - if (!epsEqual(P(r, c), other.P(r, c), 0.001)) { - std::cerr << "(" << r << "," << c << "): " << P(r, c) << " vs " << other.P(r, c) << "\n"; + for (int r = 0; r < matrix_.rows(); r++) { + for (int c = 0; c < matrix_.cols(); c++) { + if (!epsEqual(matrix_(r, c), other.matrix_(r, c), 0.001)) { + std::cerr << "(" << r << "," << c << "): " << matrix_(r, c) << " vs " << other.matrix_(r, c) << "\n"; same = false; } } @@ -58,6 +61,7 @@ bool ParticleSystemEvaluation::ExactCompare(const ParticleSystemEvaluation& othe return same; } +//--------------------------------------------------------------------------- bool ParticleSystemEvaluation::EvaluationCompare(const ParticleSystemEvaluation& other) const { auto compactness1 = ShapeEvaluation::ComputeFullCompactness(*this); auto compactness2 = ShapeEvaluation::ComputeFullCompactness(other); @@ -113,9 +117,12 @@ bool ParticleSystemEvaluation::EvaluationCompare(const ParticleSystemEvaluation& return good; } +//--------------------------------------------------------------------------- bool ParticleSystemEvaluation::ReadParticleFile(std::string filename, Eigen::VectorXd& points) { points = particles::read_particles(filename); return true; } +//--------------------------------------------------------------------------- + } // namespace shapeworks diff --git a/Libs/Particles/ParticleSystemEvaluation.h b/Libs/Particles/ParticleSystemEvaluation.h index 1392ddb60a..463fe39035 100644 --- a/Libs/Particles/ParticleSystemEvaluation.h +++ b/Libs/Particles/ParticleSystemEvaluation.h @@ -12,15 +12,15 @@ class ParticleSystemEvaluation { // Initialize particle system from eigen matrix (rows=dimensions, cols=num_samples) ParticleSystemEvaluation(const Eigen::MatrixXd& matrix); - const Eigen::MatrixXd& Particles() const { return P; }; + const Eigen::MatrixXd& Particles() const { return matrix_; }; - const std::vector& Paths() const { return paths; } + const std::vector& Paths() const { return paths_; } //! Number of samples - int N() const { return P.cols(); } + int N() const { return matrix_.cols(); } //! Dimensions (e.g. x/y/z * number of particles) - int D() const { return P.rows(); } + int D() const { return matrix_.rows(); } bool ExactCompare(const ParticleSystemEvaluation& other) const; @@ -34,7 +34,7 @@ class ParticleSystemEvaluation { ParticleSystemEvaluation() { } // only for use by SharedCommandData since a ParticleSystem should always be valid, never "empty" - Eigen::MatrixXd P; - std::vector paths; + Eigen::MatrixXd matrix_; + std::vector paths_; }; } // namespace shapeworks From 5c94554177aeb2609e6464c5ce9bc1d6d73bac24 Mon Sep 17 00:00:00 2001 From: Alan Morris Date: Wed, 27 Mar 2024 15:00:52 -0600 Subject: [PATCH 4/5] Remove unnecessary TODO --- Libs/Particles/ParticleSystemEvaluation.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Libs/Particles/ParticleSystemEvaluation.cpp b/Libs/Particles/ParticleSystemEvaluation.cpp index 7199d89684..a058bae029 100644 --- a/Libs/Particles/ParticleSystemEvaluation.cpp +++ b/Libs/Particles/ParticleSystemEvaluation.cpp @@ -18,11 +18,6 @@ ParticleSystemEvaluation::ParticleSystemEvaluation(const std::vector 0); - // TODO: We're using the existing particle file reader here. This is not ideal - // since this particle reader loads into a std::vector, which subsequently - // is copied to Eigen. Refactor it to load directly to Eigen. (This is not a - // huge problem for now because the particle files are quite small) - // Read the first file to find dimensions auto points0 = particles::read_particles_as_vector(paths_[0]); const int D = points0.size() * VDimension; From 852496d6abc84617d0f4fabdda5d2530052fbfe6 Mon Sep 17 00:00:00 2001 From: Alan Morris Date: Wed, 27 Mar 2024 16:59:29 -0600 Subject: [PATCH 5/5] Clean headers --- Libs/Particles/ShapeEvaluation.cpp | 3 +-- Libs/Particles/ShapeEvaluation.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Libs/Particles/ShapeEvaluation.cpp b/Libs/Particles/ShapeEvaluation.cpp index 9a9baf3ad0..498819416f 100644 --- a/Libs/Particles/ShapeEvaluation.cpp +++ b/Libs/Particles/ShapeEvaluation.cpp @@ -2,8 +2,7 @@ #include #include -#include - +#include #include "EvaluationUtil.h" typedef Eigen::Matrix RowMajorMatrix; diff --git a/Libs/Particles/ShapeEvaluation.h b/Libs/Particles/ShapeEvaluation.h index 00e8fbeae2..0f6f077513 100644 --- a/Libs/Particles/ShapeEvaluation.h +++ b/Libs/Particles/ShapeEvaluation.h @@ -3,7 +3,6 @@ #include #include -#include "ParticleShapeStatistics.h" #include "ParticleSystemEvaluation.h" namespace shapeworks {