From 16a573e1c402fab34442b5aad78434d601c24b26 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Thu, 16 May 2024 16:51:57 -0600 Subject: [PATCH 01/22] expose regression params in opt --- Libs/Optimize/OptimizeParameters.cpp | 16 ++++++++++++++++ Libs/Optimize/OptimizeParameters.h | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/Libs/Optimize/OptimizeParameters.cpp b/Libs/Optimize/OptimizeParameters.cpp index d7f8786002..b45a97f4c6 100644 --- a/Libs/Optimize/OptimizeParameters.cpp +++ b/Libs/Optimize/OptimizeParameters.cpp @@ -45,6 +45,8 @@ const std::string checkpointing_interval = "checkpointing_interval"; const std::string save_init_splits = "save_init_splits"; const std::string keep_checkpoints = "keep_checkpoints"; const std::string use_disentangled_ssm = "use_disentangled_ssm"; +const std::string use_linear_regression = "use_linear_regression"; +const std::string use_mixed_effects_model = "use_mixed_effects_model"; const std::string field_attributes = "field_attributes"; const std::string field_attribute_weights = "field_attribute_weights"; const std::string use_geodesics_to_landmarks = "use_geodesics_to_landmarks"; @@ -93,6 +95,8 @@ OptimizeParameters::OptimizeParameters(ProjectHandle project) { Keys::geodesics_to_landmarks_weight, Keys::keep_checkpoints, Keys::use_disentangled_ssm, + Keys::use_linear_regression, + Keys::use_mixed_effects_model, Keys::particle_format, Keys::geodesic_remesh_percent, Keys::shared_boundary, @@ -201,6 +205,18 @@ bool OptimizeParameters::get_use_disentangled_ssm() { return params_.get(Keys::u //--------------------------------------------------------------------------- void OptimizeParameters::set_use_disentangled_ssm(bool value) { params_.set(Keys::use_disentangled_ssm, value); } +//--------------------------------------------------------------------------- +bool OptimizeParameters::get_use_linear_regression() { return params_.get(Keys::use_linear_regression, false); } + +//--------------------------------------------------------------------------- +void OptimizeParameters::set_use_linear_regression(bool value) { params_.set(Keys::use_linear_regression, value); } + +//--------------------------------------------------------------------------- +bool OptimizeParameters::get_use_mixed_effects_model() { return params_.get(Keys::use_mixed_effects_model, false); } + +//--------------------------------------------------------------------------- +void OptimizeParameters::set_use_mixed_effects_model(bool value) { params_.set(Keys::use_mixed_effects_model, value); } + //--------------------------------------------------------------------------- bool OptimizeParameters::get_use_procrustes_scaling() { return params_.get(Keys::procrustes_scaling, false); } diff --git a/Libs/Optimize/OptimizeParameters.h b/Libs/Optimize/OptimizeParameters.h index 6e37f063b7..fb28b3abd0 100644 --- a/Libs/Optimize/OptimizeParameters.h +++ b/Libs/Optimize/OptimizeParameters.h @@ -60,6 +60,12 @@ class OptimizeParameters { bool get_use_disentangled_ssm(); void set_use_disentangled_ssm(bool value); + bool get_use_linear_regression(); + void set_use_linear_regression(bool value); + + bool get_use_mixed_effects_model(); + void set_use_mixed_effects_model(bool value); + bool get_use_procrustes(); void set_use_procrustes(bool value); From d452bfcb340fb6f3cc751674b9c8dd1988a77079 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Thu, 16 May 2024 18:41:53 -0600 Subject: [PATCH 02/22] support explanatory variable in SW project --- Libs/Project/ProjectReader.cpp | 5 +++++ Libs/Project/Subject.cpp | 6 ++++++ Libs/Project/Subject.h | 6 ++++++ 3 files changed, 17 insertions(+) diff --git a/Libs/Project/ProjectReader.cpp b/Libs/Project/ProjectReader.cpp index d7b4142cd8..936bf3fb1c 100644 --- a/Libs/Project/ProjectReader.cpp +++ b/Libs/Project/ProjectReader.cpp @@ -68,6 +68,11 @@ void ProjectReader::load_subjects(StringMapList list) { if (contains(item, "excluded")) { subject->set_excluded(Variant(item["excluded"])); } + + if (contains(item, "explanatory_variable")) { + subject->set_explanatory_variable(Variant(item["explanatory_variable"])); + } + if (name.empty()) { if (!subject->get_original_filenames().empty()) { name = StringUtils::getBaseFilenameWithoutExtension(subject->get_original_filenames()[0]); diff --git a/Libs/Project/Subject.cpp b/Libs/Project/Subject.cpp index 43b1bda204..57c1eb5d50 100644 --- a/Libs/Project/Subject.cpp +++ b/Libs/Project/Subject.cpp @@ -100,6 +100,12 @@ void Subject::set_fixed(bool fixed) { fixed_ = fixed; } //--------------------------------------------------------------------------- bool Subject::is_excluded() { return excluded_; } +//--------------------------------------------------------------------------- +void Subject::set_explanatory_variable(double val) { explanatory_variable_ = val; } + +//--------------------------------------------------------------------------- +double Subject::get_explanatory_variable() { return explanatory_variable_; } + //--------------------------------------------------------------------------- void Subject::set_excluded(bool excluded) { excluded_ = excluded; } diff --git a/Libs/Project/Subject.h b/Libs/Project/Subject.h index 3b3f176634..16c3297365 100644 --- a/Libs/Project/Subject.h +++ b/Libs/Project/Subject.h @@ -107,6 +107,11 @@ class Subject { //! Set if this subject is excluded or not void set_excluded(bool excluded); + //! Get the explanatory variable defined for the subject, used for Linear Regression and Mixed Effects Model for optimization + double get_explanatory_variable(); + //! Set the explanatory variable defined for the subject, used for Linear Regression and Mixed Effects Model for optimization + void set_explanatory_variable(double val); + //! Get the notes std::string get_notes(); //! Set the notes @@ -118,6 +123,7 @@ class Subject { std::string display_name_; bool fixed_ = false; bool excluded_ = false; + double explanatory_variable_ = 0.0; StringList original_filenames_; StringList groomed_filenames_; StringList local_particle_filenames_; From d67e7076ca5e6ace39ffd2a0b8bc466a10183057 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Mon, 20 May 2024 11:33:27 -0600 Subject: [PATCH 03/22] expose and link linear regression opt params --- Libs/Optimize/Optimize.cpp | 6 ++++++ Libs/Optimize/Optimize.h | 9 +++++++-- Libs/Optimize/OptimizeParameters.cpp | 26 ++++++++++++++++++++++---- Libs/Optimize/OptimizeParameters.h | 4 ++-- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/Libs/Optimize/Optimize.cpp b/Libs/Optimize/Optimize.cpp index fcadbb32fa..dbcec64210 100644 --- a/Libs/Optimize/Optimize.cpp +++ b/Libs/Optimize/Optimize.cpp @@ -1667,6 +1667,12 @@ void Optimize::SetTimePtsPerSubject(int time_pts_per_subject) { this->m_timepts_ //--------------------------------------------------------------------------- int Optimize::GetTimePtsPerSubject() { return this->m_timepts_per_subject; } +//--------------------------------------------------------------------------- +void Optimize::SetExplanatoryVariables(std::vector val) { this->m_explanatory_variables = val; } + +//--------------------------------------------------------------------------- +std::vector Optimize::GetExplanatoryVariables() { return this->m_explanatory_variables; } + //--------------------------------------------------------------------------- void Optimize::SetOptimizationIterations(int optimization_iterations) { this->m_optimization_iterations = optimization_iterations; diff --git a/Libs/Optimize/Optimize.h b/Libs/Optimize/Optimize.h index 3f86a2f059..2744bd5842 100644 --- a/Libs/Optimize/Optimize.h +++ b/Libs/Optimize/Optimize.h @@ -158,10 +158,14 @@ class Optimize { m_mesh_ffc_mode = mesh_ffc_mode; m_sampler->SetMeshFFCMode(mesh_ffc_mode); } - //! Set the number of time points per subject (TODO: details) + //! Set the number of time points per subject used for Linear Regression or Mixed Effects Model optimization void SetTimePtsPerSubject(int time_pts_per_subject); - //! Get the number of time points per subject (TODO: details) + //! Get the number of time points per subject used for Linear Regression or Mixed Effects Model optimization int GetTimePtsPerSubject(); + //! Set Explanatory Variable for | used for Linear Regression or Mixed Effects Model optimization + void SetExplanatoryVariables(std::vector vals); + //! Get the number of time points per subject used for Linear Regression or Mixed Effects Model optimization + std::vector GetExplanatoryVariables(); //! Set the number of optimization iterations void SetOptimizationIterations(int optimization_iterations); //! Set the number of optimization iterations already completed (TODO: details) @@ -388,6 +392,7 @@ class Optimize { bool m_mesh_ffc_mode = 0; unsigned int m_timepts_per_subject = 1; + std::vector m_explanatory_variables; int m_optimization_iterations = 2000; int m_optimization_iterations_completed = 0; int m_iterations_per_split = 1000; diff --git a/Libs/Optimize/OptimizeParameters.cpp b/Libs/Optimize/OptimizeParameters.cpp index b45a97f4c6..efc4653646 100644 --- a/Libs/Optimize/OptimizeParameters.cpp +++ b/Libs/Optimize/OptimizeParameters.cpp @@ -46,7 +46,7 @@ const std::string save_init_splits = "save_init_splits"; const std::string keep_checkpoints = "keep_checkpoints"; const std::string use_disentangled_ssm = "use_disentangled_ssm"; const std::string use_linear_regression = "use_linear_regression"; -const std::string use_mixed_effects_model = "use_mixed_effects_model"; +const std::string time_points_per_subject = "time_points_per_subject"; const std::string field_attributes = "field_attributes"; const std::string field_attribute_weights = "field_attribute_weights"; const std::string use_geodesics_to_landmarks = "use_geodesics_to_landmarks"; @@ -96,7 +96,7 @@ OptimizeParameters::OptimizeParameters(ProjectHandle project) { Keys::keep_checkpoints, Keys::use_disentangled_ssm, Keys::use_linear_regression, - Keys::use_mixed_effects_model, + Keys::time_points_per_subject, Keys::particle_format, Keys::geodesic_remesh_percent, Keys::shared_boundary, @@ -212,10 +212,10 @@ bool OptimizeParameters::get_use_linear_regression() { return params_.get(Keys:: void OptimizeParameters::set_use_linear_regression(bool value) { params_.set(Keys::use_linear_regression, value); } //--------------------------------------------------------------------------- -bool OptimizeParameters::get_use_mixed_effects_model() { return params_.get(Keys::use_mixed_effects_model, false); } +int OptimizeParameters::get_time_points_per_subject() { return params_.get(Keys::time_points_per_subject, 1); } //--------------------------------------------------------------------------- -void OptimizeParameters::set_use_mixed_effects_model(bool value) { params_.set(Keys::use_mixed_effects_model, value); } +void OptimizeParameters::set_time_points_per_subject(int value) { params_.set(Keys::time_points_per_subject, value); } //--------------------------------------------------------------------------- bool OptimizeParameters::get_use_procrustes_scaling() { return params_.get(Keys::procrustes_scaling, false); } @@ -449,6 +449,9 @@ bool OptimizeParameters::set_up_optimize(Optimize* optimize) { optimize->SetMeshFFCMode(get_mesh_ffc_mode()); optimize->SetUseDisentangledSpatiotemporalSSM(get_use_disentangled_ssm()); optimize->set_particle_format(get_particle_format()); + optimize->SetTimePtsPerSubject(get_time_points_per_subject()); + optimize->SetUseRegression(get_use_linear_regression()); + optimize->SetUseMixedEffects(get_time_points_per_subject() > 1 ? true : false); optimize->SetSharedBoundaryEnabled(get_shared_boundary()); optimize->SetSharedBoundaryWeight(get_shared_boundary_weight()); @@ -644,6 +647,21 @@ bool OptimizeParameters::set_up_optimize(Optimize* optimize) { } } + // get explanatory variables for subjects if used for regression + if (get_use_linear_regression()) + { + std::vector exp_vars; + for (const auto& s : subjects) { + exp_vars.push_back(s->get_explanatory_variable()); + } + dynamic_cast( + optimize->GetSampler()->GetEnsembleRegressionEntropyFunction()->GetShapeMatrix()) + ->SetExplanatory(exp_vars); + dynamic_cast( + optimize->GetSampler()->GetEnsembleMixedEffectsEntropyFunction()->GetShapeMatrix()) + ->SetExplanatory(exp_vars); + } + std::vector filenames; int count = 0; domain_count = 0; diff --git a/Libs/Optimize/OptimizeParameters.h b/Libs/Optimize/OptimizeParameters.h index fb28b3abd0..58d014f4fd 100644 --- a/Libs/Optimize/OptimizeParameters.h +++ b/Libs/Optimize/OptimizeParameters.h @@ -63,8 +63,8 @@ class OptimizeParameters { bool get_use_linear_regression(); void set_use_linear_regression(bool value); - bool get_use_mixed_effects_model(); - void set_use_mixed_effects_model(bool value); + int get_time_points_per_subject(); + void set_time_points_per_subject(int value); bool get_use_procrustes(); void set_use_procrustes(bool value); From 17602e7e8e3d8232971be3750a34a2c949ca7491 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Thu, 16 May 2024 18:41:53 -0600 Subject: [PATCH 04/22] support explanatory variable in SW project --- Libs/Project/ProjectReader.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Libs/Project/ProjectReader.cpp b/Libs/Project/ProjectReader.cpp index 936bf3fb1c..9029174296 100644 --- a/Libs/Project/ProjectReader.cpp +++ b/Libs/Project/ProjectReader.cpp @@ -68,7 +68,6 @@ void ProjectReader::load_subjects(StringMapList list) { if (contains(item, "excluded")) { subject->set_excluded(Variant(item["excluded"])); } - if (contains(item, "explanatory_variable")) { subject->set_explanatory_variable(Variant(item["explanatory_variable"])); } From 91d6c4b37f46a280c202da680db50c13c34a7996 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Sat, 1 Jun 2024 15:35:02 -0600 Subject: [PATCH 05/22] add ui elements for use regression feature --- Studio/Optimize/OptimizeTool.ui | 64 +++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/Studio/Optimize/OptimizeTool.ui b/Studio/Optimize/OptimizeTool.ui index 2f1bc5d173..81866106d9 100644 --- a/Studio/Optimize/OptimizeTool.ui +++ b/Studio/Optimize/OptimizeTool.ui @@ -302,6 +302,13 @@ QWidget#optimize_panel { + + + + Use Linear Regression + + + @@ -857,8 +864,59 @@ QWidget#optimize_panel { - - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 100 @@ -1223,6 +1281,8 @@ QWidget#optimize_panel { use_landmarks narrow_band use_disentangled_ssm + use_linear_regression + From 40ff752238adeee698e4275a85e8e22759db0c8c Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Sat, 1 Jun 2024 15:40:54 -0600 Subject: [PATCH 06/22] link linear regression ui to optimizetool --- Studio/Optimize/OptimizeTool.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Studio/Optimize/OptimizeTool.cpp b/Studio/Optimize/OptimizeTool.cpp index c5225f3639..b0c20eb315 100644 --- a/Studio/Optimize/OptimizeTool.cpp +++ b/Studio/Optimize/OptimizeTool.cpp @@ -63,7 +63,10 @@ OptimizeTool::OptimizeTool(Preferences& prefs, Telemetry& telemetry) : preferenc "It has no effect on the optimization"); ui_->shared_boundary->setToolTip("Use shared boundary optimization"); ui_->shared_boundary_weight->setToolTip("Weight of shared boundary optimization"); - ui_->use_disentangled_ssm->setToolTip("Use disentangled Optimization technique to build spatiotemporal SSM."); + ui_->use_disentangled_ssm->setToolTip("Use the disentangled optimization technique to build spatiotemporal SSM."); + ui_->use_linear_regression->setToolTip("Use the linear regression optimization technique, where correspondence particle optimization is performed by regressing shape against an explanatory variable. Ensure that the explanatory variable is specified in the data tab of the project file."); + + // hidden for 6.5 release ui_->disentangled_label->hide(); @@ -286,6 +289,8 @@ void OptimizeTool::load_params() { ui_->use_geodesics_from_landmarks->setChecked(params.get_use_geodesics_to_landmarks()); ui_->geodesics_to_landmarks_weight->setText(QString::number(params.get_geodesic_to_landmarks_weight())); ui_->use_disentangled_ssm->setChecked(params.get_use_disentangled_ssm()); + ui_->use_linear_regression->setChecked(params.get_use_linear_regression()); + ui_->procrustes->setChecked(params.get_use_procrustes()); ui_->procrustes_scaling->setChecked(params.get_use_procrustes_scaling()); @@ -334,6 +339,7 @@ void OptimizeTool::store_params() { params.set_use_geodesics_to_landmarks(ui_->use_geodesics_from_landmarks->isChecked()); params.set_geodesic_to_landmarks_weight(ui_->geodesics_to_landmarks_weight->text().toDouble()); params.set_use_disentangled_ssm(ui_->use_disentangled_ssm->isChecked()); + params.set_use_linear_regression(ui_->use_linear_regression->isChecked()); params.set_use_procrustes(ui_->procrustes->isChecked()); params.set_use_procrustes_scaling(ui_->procrustes_scaling->isChecked()); From 2ef29a2eb458634f8a7d34613b8d6503c0d6ae72 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Tue, 4 Jun 2024 14:06:56 -0600 Subject: [PATCH 07/22] more studio support --- Studio/Optimize/OptimizeTool.cpp | 13 ++++++++++--- Studio/Optimize/OptimizeTool.ui | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Studio/Optimize/OptimizeTool.cpp b/Studio/Optimize/OptimizeTool.cpp index b0c20eb315..705c0771c3 100644 --- a/Studio/Optimize/OptimizeTool.cpp +++ b/Studio/Optimize/OptimizeTool.cpp @@ -33,6 +33,7 @@ OptimizeTool::OptimizeTool(Preferences& prefs, Telemetry& telemetry) : preferenc connect(ui_->use_normals, &QCheckBox::toggled, this, &OptimizeTool::update_ui_elements); connect(ui_->procrustes, &QCheckBox::toggled, this, &OptimizeTool::update_ui_elements); connect(ui_->multiscale, &QCheckBox::toggled, this, &OptimizeTool::update_ui_elements); + connect(ui_->use_linear_regression, &QCheckBox::toggled, this, &OptimizeTool::update_ui_elements); connect(ui_->use_geodesics_from_landmarks, &QCheckBox::toggled, this, &OptimizeTool::update_ui_elements); connect(ui_->use_geodesic_distance, &QCheckBox::toggled, this, &OptimizeTool::update_ui_elements); @@ -65,7 +66,7 @@ OptimizeTool::OptimizeTool(Preferences& prefs, Telemetry& telemetry) : preferenc ui_->shared_boundary_weight->setToolTip("Weight of shared boundary optimization"); ui_->use_disentangled_ssm->setToolTip("Use the disentangled optimization technique to build spatiotemporal SSM."); ui_->use_linear_regression->setToolTip("Use the linear regression optimization technique, where correspondence particle optimization is performed by regressing shape against an explanatory variable. Ensure that the explanatory variable is specified in the data tab of the project file."); - + ui_->time_points_per_subject->setToolTip("Number of timepoints/explanatory variables defined for each subject in the data tab. Note: More than 1 timepoint uses a mixed effects model; 1 timepoint uses linear regression. "); // hidden for 6.5 release @@ -74,6 +75,8 @@ OptimizeTool::OptimizeTool(Preferences& prefs, Telemetry& telemetry) : preferenc QIntValidator* above_zero = new QIntValidator(1, std::numeric_limits::max(), this); QIntValidator* zero_and_up = new QIntValidator(0, std::numeric_limits::max(), this); + QIntValidator* one_and_up = new QIntValidator(1, std::numeric_limits::max(), this); + QDoubleValidator* double_validator = new QDoubleValidator(0, std::numeric_limits::max(), 1000, this); @@ -89,6 +92,7 @@ OptimizeTool::OptimizeTool(Preferences& prefs, Telemetry& telemetry) : preferenc ui_->multiscale_particles->setValidator(above_zero); ui_->narrow_band->setValidator(double_validator); ui_->geodesics_to_landmarks_weight->setValidator(double_validator); + ui_->time_points_per_subject->setValidator(one_and_up); ui_->shared_boundary_weight->setValidator(double_validator); line_edits_.push_back(ui_->number_of_particles); @@ -103,7 +107,7 @@ OptimizeTool::OptimizeTool(Preferences& prefs, Telemetry& telemetry) : preferenc line_edits_.push_back(ui_->multiscale_particles); line_edits_.push_back(ui_->geodesics_to_landmarks_weight); line_edits_.push_back(ui_->narrow_band); - line_edits_.push_back(ui_->shared_boundary_weight); + for (QLineEdit* line_edit : line_edits_) { connect(line_edit, &QLineEdit::textChanged, this, &OptimizeTool::update_run_button); @@ -289,8 +293,9 @@ void OptimizeTool::load_params() { ui_->use_geodesics_from_landmarks->setChecked(params.get_use_geodesics_to_landmarks()); ui_->geodesics_to_landmarks_weight->setText(QString::number(params.get_geodesic_to_landmarks_weight())); ui_->use_disentangled_ssm->setChecked(params.get_use_disentangled_ssm()); - ui_->use_linear_regression->setChecked(params.get_use_linear_regression()); + ui_->use_linear_regression->setChecked(params.get_use_linear_regression()); + ui_->time_points_per_subject->setText(QString::number(params.get_time_points_per_subject())); ui_->procrustes->setChecked(params.get_use_procrustes()); ui_->procrustes_scaling->setChecked(params.get_use_procrustes_scaling()); @@ -340,6 +345,7 @@ void OptimizeTool::store_params() { params.set_geodesic_to_landmarks_weight(ui_->geodesics_to_landmarks_weight->text().toDouble()); params.set_use_disentangled_ssm(ui_->use_disentangled_ssm->isChecked()); params.set_use_linear_regression(ui_->use_linear_regression->isChecked()); + params.set_time_points_per_subject(ui_->time_points_per_subject->text().toDouble()); params.set_use_procrustes(ui_->procrustes->isChecked()); params.set_use_procrustes_scaling(ui_->procrustes_scaling->isChecked()); @@ -388,6 +394,7 @@ void OptimizeTool::update_ui_elements() { ui_->procrustes_rotation_translation->setEnabled(ui_->procrustes->isChecked()); ui_->procrustes_interval->setEnabled(ui_->procrustes->isChecked()); ui_->multiscale_particles->setEnabled(ui_->multiscale->isChecked()); + ui_->time_points_per_subject->setEnabled(ui_->use_linear_regression->isChecked()); ui_->geodesics_to_landmarks_weight->setEnabled(ui_->use_geodesics_from_landmarks->isChecked()); ui_->geodesic_remesh_percent->setEnabled(ui_->use_geodesic_distance->isChecked()); diff --git a/Studio/Optimize/OptimizeTool.ui b/Studio/Optimize/OptimizeTool.ui index 81866106d9..92fcf61bd6 100644 --- a/Studio/Optimize/OptimizeTool.ui +++ b/Studio/Optimize/OptimizeTool.ui @@ -435,6 +435,13 @@ QWidget#optimize_panel { + + + + Timepoints defined per subject + + + @@ -558,6 +565,16 @@ QWidget#optimize_panel { + + + + 1 + + + Qt::AlignCenter + + + @@ -1282,6 +1299,7 @@ QWidget#optimize_panel { narrow_band use_disentangled_ssm use_linear_regression + time_points_per_subject From 69fcb3c6d44759ecf67ea7a321f373e865d930ce Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Thu, 16 May 2024 18:41:53 -0600 Subject: [PATCH 08/22] support explanatory variable in SW project --- Studio/Resources/.nfs000000041c1dd02f0000039f | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Studio/Resources/.nfs000000041c1dd02f0000039f diff --git a/Studio/Resources/.nfs000000041c1dd02f0000039f b/Studio/Resources/.nfs000000041c1dd02f0000039f new file mode 100644 index 0000000000..528a903a88 --- /dev/null +++ b/Studio/Resources/.nfs000000041c1dd02f0000039f @@ -0,0 +1,60 @@ + + + Images/shapes-icon.png + Images/acorn.png + Images/circle.png + Images/hammer.png + Images/bug.png + Images/pencil.png + Images/palette.png + Images/red_dots.png + Images/wand.png + Images/injection.png + Images/hammer2.png + Images/wand2.png + Images/star.png + Images/star2.png + Images/snowflake.png + Images/grey_ball.png + Images/run.png + Images/blocks.png + Images/blocks2.png + Images/blue_ball.png + Images/purple_ball.png + Images/dots.png + Images/wrench.png + Images/wrench2.png + Images/gear2.png + Images/add.png + Images/remove.png + Images/select.png + Images/unselect.png + Images/data.png + Images/chart.png + Images/deep_ssm.png + Images/gear.png + Images/tools.png + Images/shapeworks-logo.png + Images/DownArrow.png + Images/DownArrowWhite.png + Images/RightArrow.png + Images/RightArrowWhite.png + Images/AutoView.png + Images/AutoViewOff.png + Images/IsosurfaceVisible.png + Images/IsosurfaceVisibleOff.png + Images/Visible.png + Images/VisibleGray.png + Images/VisibleOff.png + Images/spinner.png + Images/log_normal.png + Images/log_warning.png + Images/log_error.png + Images/Brush.png + Images/flag_on.png + Images/flag_off.png + Images/planes_on.png + Images/planes_off.png + Images/down_arrow.png + + From 5de96b6e27bd61eeec74165b2dca9d4ea14079c1 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Thu, 13 Jun 2024 10:49:24 -0600 Subject: [PATCH 09/22] more studio changes --- Libs/Optimize/OptimizeParameters.cpp | 5 +++++ Libs/Optimize/OptimizeParameters.h | 1 + Studio/Analysis/AnalysisTool.cpp | 14 ++++++++++++-- Studio/Data/Session.cpp | 2 ++ Studio/Interface/ShapeWorksStudioApp.cpp | 8 ++++++++ Studio/Optimize/OptimizeTool.h | 6 ++++++ 6 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Libs/Optimize/OptimizeParameters.cpp b/Libs/Optimize/OptimizeParameters.cpp index efc4653646..ae6e97a883 100644 --- a/Libs/Optimize/OptimizeParameters.cpp +++ b/Libs/Optimize/OptimizeParameters.cpp @@ -55,6 +55,7 @@ const std::string particle_format = "particle_format"; const std::string geodesic_remesh_percent = "geodesic_remesh_percent"; const std::string shared_boundary = "shared_boundary"; const std::string shared_boundary_weight = "shared_boundary_weight"; +const std::string output_prefix = "output_prefix"; } // namespace Keys //--------------------------------------------------------------------------- @@ -99,6 +100,7 @@ OptimizeParameters::OptimizeParameters(ProjectHandle project) { Keys::time_points_per_subject, Keys::particle_format, Keys::geodesic_remesh_percent, + Keys::output_prefix, Keys::shared_boundary, Keys::shared_boundary_weight}; @@ -887,6 +889,9 @@ void OptimizeParameters::set_geodesic_remesh_percent(double value) { params_.set(Keys::geodesic_remesh_percent, value); } +//--------------------------------------------------------------------------- +void OptimizeParameters::set_output_prefix(std::string value) { params_.set(Keys::output_prefix, value); } + //--------------------------------------------------------------------------- bool OptimizeParameters::get_shared_boundary() { return params_.get(Keys::shared_boundary, false); } diff --git a/Libs/Optimize/OptimizeParameters.h b/Libs/Optimize/OptimizeParameters.h index 58d014f4fd..99727771e6 100644 --- a/Libs/Optimize/OptimizeParameters.h +++ b/Libs/Optimize/OptimizeParameters.h @@ -143,6 +143,7 @@ class OptimizeParameters { double get_shared_boundary_weight(); void set_shared_boundary_weight(double value); + void set_output_prefix(std::string value); private: std::string get_output_prefix(); diff --git a/Studio/Analysis/AnalysisTool.cpp b/Studio/Analysis/AnalysisTool.cpp index 0a4d9b668d..6119d9cccb 100644 --- a/Studio/Analysis/AnalysisTool.cpp +++ b/Studio/Analysis/AnalysisTool.cpp @@ -138,7 +138,7 @@ AnalysisTool::AnalysisTool(Preferences& prefs) : preferences_(prefs) { ui_->metrics_open_button->setChecked(false); /// TODO nothing there yet (regression tab) - ui_->tabWidget->removeTab(3); + // ui_->tabWidget->removeTab(3); for (auto button : {ui_->distance_transform_radio_button, ui_->mesh_warping_radio_button, ui_->legacy_radio_button}) { connect(button, &QRadioButton::clicked, this, &AnalysisTool::reconstruction_method_changed); @@ -378,7 +378,7 @@ void AnalysisTool::handle_analysis_options() { ui_->mcaLevelBetweenButton->setEnabled(true); ui_->vanillaPCAButton->setChecked(true); } - } else { + } else if (ui_->tabWidget->currentWidget() == ui_->regression_tab){ // regression mode ui_->sampleSpinBox->setEnabled(false); ui_->medianButton->setEnabled(false); @@ -386,6 +386,14 @@ void AnalysisTool::handle_analysis_options() { ui_->pcaAnimateCheckBox->setEnabled(false); ui_->pcaModeSpinBox->setEnabled(false); pca_animate_timer_.stop(); + + } else { + ui_->sampleSpinBox->setEnabled(false); + ui_->medianButton->setEnabled(false); + ui_->pcaSlider->setEnabled(false); + ui_->pcaAnimateCheckBox->setEnabled(false); + ui_->pcaModeSpinBox->setEnabled(false); + pca_animate_timer_.stop(); } update_difference_particles(); @@ -861,6 +869,8 @@ void AnalysisTool::store_settings() { params.set("network_pvalue_of_interest", ui_->network_pvalue_of_interest->text().toStdString()); params.set("network_pvalue_threshold", ui_->network_pvalue_threshold->text().toStdString()); + params.set("regression_slope", session->) + session_->get_project()->set_parameters(Parameters::ANALYSIS_PARAMS, params); } diff --git a/Studio/Data/Session.cpp b/Studio/Data/Session.cpp index 8513b99a1d..c79528a74b 100644 --- a/Studio/Data/Session.cpp +++ b/Studio/Data/Session.cpp @@ -837,6 +837,8 @@ void Session::new_plane_point(PickResult result) { //--------------------------------------------------------------------------- QString Session::get_filename() { return filename_; } +QString Session::get_parent_dir() + //--------------------------------------------------------------------------- int Session::get_num_shapes() { return shapes_.size(); } diff --git a/Studio/Interface/ShapeWorksStudioApp.cpp b/Studio/Interface/ShapeWorksStudioApp.cpp index bb0128c0a3..7f58d3f812 100644 --- a/Studio/Interface/ShapeWorksStudioApp.cpp +++ b/Studio/Interface/ShapeWorksStudioApp.cpp @@ -1528,6 +1528,14 @@ void ShapeWorksStudioApp::open_project(QString filename) { groom_tool_->load_params(); optimize_tool_->load_params(); + + if (optimize_tool_->get_regression_analysis_status()) + { + // Verify if slope and intercept files exist + auto particles_dir = session_->get_filename().dir().absolutePath().toStdString(); + auto slope_filename = session_->get_filename().toStdString() + } + analysis_tool_->store_settings(); update_from_preferences(); update_tool_mode(); diff --git a/Studio/Optimize/OptimizeTool.h b/Studio/Optimize/OptimizeTool.h index e62b58a896..f88e322626 100644 --- a/Studio/Optimize/OptimizeTool.h +++ b/Studio/Optimize/OptimizeTool.h @@ -37,6 +37,10 @@ Q_OBJECT; //! Load params from project void load_params(); //! Store params to project + + //! Get flag if regression needs to enabled for analysis in Studio + inline bool get_regression_analysis_status() { return regression_analysis_status; } + void store_params(); //! Enable action buttons @@ -94,5 +98,7 @@ public Q_SLOTS: QElapsedTimer elapsed_timer_; Ui_OptimizeTool* ui_; + + bool regression_analysis_status_; }; } From fd0e1bafef06e1d00d157639fbd1d82c12ea94cc Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Wed, 9 Oct 2024 12:28:42 -0600 Subject: [PATCH 10/22] rebase changes --- Libs/Particles/ParticleShapeStatistics.cpp | 2 ++ Studio/Analysis/AnalysisTool.cpp | 2 +- Studio/Data/Session.cpp | 2 +- Studio/Interface/ShapeWorksStudioApp.cpp | 4 ++-- Studio/Optimize/OptimizeTool.h | 2 +- Studio/Optimize/OptimizeTool.ui | 10 ++++++++++ 6 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Libs/Particles/ParticleShapeStatistics.cpp b/Libs/Particles/ParticleShapeStatistics.cpp index 288eae4a44..aa6d8c008b 100644 --- a/Libs/Particles/ParticleShapeStatistics.cpp +++ b/Libs/Particles/ParticleShapeStatistics.cpp @@ -694,4 +694,6 @@ Eigen::MatrixXd ParticleShapeStatistics::get_group1_matrix() const { return grou //--------------------------------------------------------------------------- Eigen::MatrixXd ParticleShapeStatistics::get_group2_matrix() const { return group2_matrix_; } + + } // namespace shapeworks diff --git a/Studio/Analysis/AnalysisTool.cpp b/Studio/Analysis/AnalysisTool.cpp index 6119d9cccb..5896cf7187 100644 --- a/Studio/Analysis/AnalysisTool.cpp +++ b/Studio/Analysis/AnalysisTool.cpp @@ -869,7 +869,7 @@ void AnalysisTool::store_settings() { params.set("network_pvalue_of_interest", ui_->network_pvalue_of_interest->text().toStdString()); params.set("network_pvalue_threshold", ui_->network_pvalue_threshold->text().toStdString()); - params.set("regression_slope", session->) + // params.set("regression_slope", session->) session_->get_project()->set_parameters(Parameters::ANALYSIS_PARAMS, params); } diff --git a/Studio/Data/Session.cpp b/Studio/Data/Session.cpp index c79528a74b..36b3d6ba2b 100644 --- a/Studio/Data/Session.cpp +++ b/Studio/Data/Session.cpp @@ -837,7 +837,7 @@ void Session::new_plane_point(PickResult result) { //--------------------------------------------------------------------------- QString Session::get_filename() { return filename_; } -QString Session::get_parent_dir() +// QString Session::get_parent_dir() //--------------------------------------------------------------------------- int Session::get_num_shapes() { return shapes_.size(); } diff --git a/Studio/Interface/ShapeWorksStudioApp.cpp b/Studio/Interface/ShapeWorksStudioApp.cpp index 7f58d3f812..b312dea14e 100644 --- a/Studio/Interface/ShapeWorksStudioApp.cpp +++ b/Studio/Interface/ShapeWorksStudioApp.cpp @@ -1532,8 +1532,8 @@ void ShapeWorksStudioApp::open_project(QString filename) { if (optimize_tool_->get_regression_analysis_status()) { // Verify if slope and intercept files exist - auto particles_dir = session_->get_filename().dir().absolutePath().toStdString(); - auto slope_filename = session_->get_filename().toStdString() + // auto particles_dir = session_->get_filename().dir().absolutePath().toStdString(); + // auto slope_filename = session_->get_filename().toStdString(); } analysis_tool_->store_settings(); update_from_preferences(); diff --git a/Studio/Optimize/OptimizeTool.h b/Studio/Optimize/OptimizeTool.h index f88e322626..cab850aa3f 100644 --- a/Studio/Optimize/OptimizeTool.h +++ b/Studio/Optimize/OptimizeTool.h @@ -39,7 +39,7 @@ Q_OBJECT; //! Store params to project //! Get flag if regression needs to enabled for analysis in Studio - inline bool get_regression_analysis_status() { return regression_analysis_status; } + inline bool get_regression_analysis_status() { return regression_analysis_status_; } void store_params(); diff --git a/Studio/Optimize/OptimizeTool.ui b/Studio/Optimize/OptimizeTool.ui index 92fcf61bd6..f741c6c05e 100644 --- a/Studio/Optimize/OptimizeTool.ui +++ b/Studio/Optimize/OptimizeTool.ui @@ -881,6 +881,16 @@ QWidget#optimize_panel { + + + + 100 + + + Qt::AlignCenter + + + From e2be77d7e263dc7c3e5b554113f05cac2d9ab02f Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Tue, 31 Dec 2024 12:22:59 -0700 Subject: [PATCH 11/22] new changes --- Libs/Particles/ParticleShapeStatistics.h | 10 ++- Libs/Project/Subject.h | 2 +- Studio/Analysis/AnalysisTool.cpp | 84 ++++++++++++++++++++++-- Studio/Analysis/AnalysisTool.h | 9 +++ Studio/Analysis/AnalysisTool.ui | 63 ++++++++++++++++++ Studio/Data/Session.cpp | 15 +++++ Studio/Data/Session.h | 2 + 7 files changed, 178 insertions(+), 7 deletions(-) diff --git a/Libs/Particles/ParticleShapeStatistics.h b/Libs/Particles/ParticleShapeStatistics.h index 28b0972676..e8b5746759 100644 --- a/Libs/Particles/ParticleShapeStatistics.h +++ b/Libs/Particles/ParticleShapeStatistics.h @@ -135,6 +135,9 @@ class ParticleShapeStatistics { //! Set the meshes for each sample (used for some evaluation metrics) void set_meshes(const std::vector& meshes) { meshes_ = meshes; } + // import estimated parameters for regression + inline bool import_regression_parameters(Eigen::VectorXd slope, Eigen::VectorXd intercept) { slope_ = slope; intercept_ = intercept; }; + private: unsigned int num_samples_group1_; unsigned int num_samples_group2_; @@ -147,9 +150,14 @@ class ParticleShapeStatistics { std::vector eigenvalues_; Eigen::VectorXd mean_; Eigen::VectorXd mean1_; - Eigen::VectorXd mean2_; + Eigen::VectorXd mean2_;x Eigen::MatrixXd points_minus_mean_; Eigen::MatrixXd shapes_; + + // for regression tasks + Eigen::VectorXd slope_; + Eigen::VectorXd intercept_; + bool regression_enabled_; std::vector percent_variance_by_mode_; Eigen::MatrixXd principals_; diff --git a/Libs/Project/Subject.h b/Libs/Project/Subject.h index 16c3297365..585cd07590 100644 --- a/Libs/Project/Subject.h +++ b/Libs/Project/Subject.h @@ -123,7 +123,7 @@ class Subject { std::string display_name_; bool fixed_ = false; bool excluded_ = false; - double explanatory_variable_ = 0.0; + double explanatory_variable_ = std::numeric_limits::lowest(); StringList original_filenames_; StringList groomed_filenames_; StringList local_particle_filenames_; diff --git a/Studio/Analysis/AnalysisTool.cpp b/Studio/Analysis/AnalysisTool.cpp index 5896cf7187..156bc30928 100644 --- a/Studio/Analysis/AnalysisTool.cpp +++ b/Studio/Analysis/AnalysisTool.cpp @@ -269,6 +269,11 @@ void AnalysisTool::on_reconstructionButton_clicked() { //--------------------------------------------------------------------------- int AnalysisTool::get_pca_mode() { return ui_->pcaModeSpinBox->value() - 1; } +//--------------------------------------------------------------------------- +bool AnalysisTool::get_regression_analysis_status() { + return ui_->enableRegressionCheckBox->isChecked(); +} + //--------------------------------------------------------------------------- double AnalysisTool::get_group_ratio() { double group_slider_value = ui_->group_slider->value(); @@ -505,6 +510,35 @@ void AnalysisTool::network_analysis_clicked() { app_->get_py_worker()->run_job(network_analysis_job_); } +Eigen::VectorXd load_regression_parameters(std::string filepath) { + std::ifstream infile(slope_file_path); + if (!infile.good()) { + throw std::runtime_error("Unable to open regression parameter file: \"" + + filepath + "\" for reading"); + } + try { + std::vector temp_values; + double value; + while (infile >> value) { + temp_values.push_back(value); + } + if (temp_values.empty()) { + std::cerr << "Error: No data found in file " << slope_file_path + << std::endl; + return Eigen::VectorXd(); + } + Eigen::VectorXd param_vector(temp_values.size()); + for (std::size_t i = 0; i < temp_values.size(); ++i) { + param_vector[i] = temp_values[i]; + } + return param_vector; + + } catch (json::exception& e) { + throw std::runtime_error("Unabled to parse regression parameter file " + + filepath + " : " + e.what()); + } +} + //----------------------------------------------------------------------------- bool AnalysisTool::compute_stats() { if (stats_ready_) { @@ -627,6 +661,20 @@ bool AnalysisTool::compute_stats() { compute_shape_evaluations(); } + can_run_regression_ = check_explanatory_variable_limits(); + if (can_run_regression_) { + auto slope = load_regression_parameters( + session_->get_regression_param_file("slope")); + auto intercept = load_regression_parameters( + session_->get_regression_param_file("intercept")); + stats_.import_regression_parameters(slope, intercept); + } + else { + ui_->regression_groupbox->setVisible(false); + ui_->explanatoryVariableSlider->setVisible(false); + ui_->enableRegressionCheckBox->setVisible(false); + } + stats_ready_ = true; /// Set this to true to export long format sample data (e.g. for import into R) @@ -667,6 +715,19 @@ bool AnalysisTool::compute_stats() { return true; } +bool check_explanatory_variable_limits() { + auto subjects = session_->get_project()->get_subjects(); + explanatory_variable_limits_.resize(2); + explanatory_variable_limits_[0] = std::numeric_limits::max(); + explanatory_variable_limits_[1] = std::numeric_limits::lowest(); + for (auto sub : subjects) { + double exp_val = sub->get_explanatory_variable(); + if (exp_val == std::numeric_limits::lowest()) return false; + explanatory_variable_limits_[0] = std::min(explanatory_variable_limits_[0], exp_val); + explanatory_variable_limits_[1] = std::max(explanatory_variable_limits_[1], exp_val); + } + return true; +} //----------------------------------------------------------------------------- Particles AnalysisTool::get_mean_shape_points() { if (!compute_stats()) { @@ -729,8 +790,8 @@ Particles AnalysisTool::get_shape_points(int mode, double value) { ui_->explained_variance->setText(""); ui_->cumulative_explained_variance->setText(""); } - - temp_shape_ = stats_.get_mean() + (e * (value * lambda)); + auto mean = !regression_enabled_ ? stats_.get_mean() : stats_.get_regression_mean(ui_->get_explanatory_variable_value()); + temp_shape_ = mean + (e * (value * lambda)); auto positions = temp_shape_; @@ -829,11 +890,17 @@ ShapeHandle AnalysisTool::get_current_shape() { int pca_mode = get_pca_mode(); double pca_value = get_pca_value(); auto mca_level = get_mca_level(); - if (mca_level == AnalysisTool::McaMode::Vanilla) { - return get_mode_shape(pca_mode, pca_value); + bool regression_analysis_enabled = get_regression_analysis_status(); + if (!regression_analysis_enabled) { + if (mca_level == AnalysisTool::McaMode::Vanilla) { + return get_mode_shape(pca_mode, pca_value); + } else { + return get_mca_mode_shape(pca_mode, pca_value, mca_level); + } } else { - return get_mca_mode_shape(pca_mode, pca_value, mca_level); + } + } //--------------------------------------------------------------------------- @@ -1095,6 +1162,13 @@ double AnalysisTool::get_pca_value() { return value; } + +double AnalysisTool::get_explanatory_variable_value() { + int slider_value = ui_->explanatoryVariableSlider->value(); + return t_min + (static_cast(slider_value) / 100.0) * (t_max - t_min); + +} + //--------------------------------------------------------------------------- void AnalysisTool::pca_labels_changed(QString value, QString eigen, QString lambda) { set_labels(QString("pca"), value); diff --git a/Studio/Analysis/AnalysisTool.h b/Studio/Analysis/AnalysisTool.h index d6198e972a..81e22509bb 100644 --- a/Studio/Analysis/AnalysisTool.h +++ b/Studio/Analysis/AnalysisTool.h @@ -80,6 +80,10 @@ class AnalysisTool : public QWidget { bool pca_animate(); McaMode get_mca_level() const; + bool get_regression_analysis_status(); + + bool check_explanatory_variable_limits(); + int get_sample_number(); bool compute_stats(); @@ -236,6 +240,8 @@ class AnalysisTool : public QWidget { void update_difference_particles(); Eigen::VectorXd get_mean_shape_particles(); + + Eigen::VectorXd load_regression_parameters(std::string filepath); ShapeHandle create_shape_from_points(Particles points); @@ -275,6 +281,9 @@ class AnalysisTool : public QWidget { std::string feature_map_; + std::vector explanatory_variable_limits_; + bool can_run_regression_; + std::vector current_group_names_; std::vector current_group_values_; diff --git a/Studio/Analysis/AnalysisTool.ui b/Studio/Analysis/AnalysisTool.ui index da73800f75..a2316e5b90 100644 --- a/Studio/Analysis/AnalysisTool.ui +++ b/Studio/Analysis/AnalysisTool.ui @@ -1546,6 +1546,69 @@ QWidget#particles_panel { + + + + Regression Analysis + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Enable regression analysis if explanatory variables are provided + + + Enable Regression Analysis + + + + + + + Exp.Var. + + + + + + + false + + + Explanatory variable slider + + + -20 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 1 + + + + + + diff --git a/Studio/Data/Session.cpp b/Studio/Data/Session.cpp index 36b3d6ba2b..2feedec085 100644 --- a/Studio/Data/Session.cpp +++ b/Studio/Data/Session.cpp @@ -1418,4 +1418,19 @@ void Session::recompute_surfaces() { } Q_EMIT update_display(); } + +std::string get_regression_param_file(std::string param_name) { + QFileInfo fileInfo(filename_); + QString baseName = fileInfo.completeBaseName(); + + QDir projectDir = fileInfo.absoluteDir(); + QString particlesDir = baseName + "_particles"; + QString paramFilePath = projectDir.filePath(particlesDir); + paramFilePath = QDir(paramFilePath).filePath(param_name); + + if (!QFile::exists(paramFilePath)) { + return ""; + } + return paramFilePath.toStdString(); +} } // namespace shapeworks diff --git a/Studio/Data/Session.h b/Studio/Data/Session.h index a7d9f7a3f7..a445ec8b55 100644 --- a/Studio/Data/Session.h +++ b/Studio/Data/Session.h @@ -339,6 +339,8 @@ class Session : public QObject, public QEnableSharedFromThis { void new_plane_point(PickResult result); + std::string get_regression_param_file(std::string param_name = "slope"); + QWidget* parent_{nullptr}; Preferences& preferences_; From 92a8570d3948a5cbb656d33888477f6d23da85b3 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Tue, 31 Dec 2024 12:28:00 -0700 Subject: [PATCH 12/22] typos fix --- Libs/Particles/ParticleShapeStatistics.h | 2 +- Studio/Analysis/AnalysisTool.cpp | 2 +- Studio/Resources/.nfs000000041c1dd02f0000039f | 60 ------------------- 3 files changed, 2 insertions(+), 62 deletions(-) delete mode 100644 Studio/Resources/.nfs000000041c1dd02f0000039f diff --git a/Libs/Particles/ParticleShapeStatistics.h b/Libs/Particles/ParticleShapeStatistics.h index e8b5746759..0606b77859 100644 --- a/Libs/Particles/ParticleShapeStatistics.h +++ b/Libs/Particles/ParticleShapeStatistics.h @@ -150,7 +150,7 @@ class ParticleShapeStatistics { std::vector eigenvalues_; Eigen::VectorXd mean_; Eigen::VectorXd mean1_; - Eigen::VectorXd mean2_;x + Eigen::VectorXd mean2_; Eigen::MatrixXd points_minus_mean_; Eigen::MatrixXd shapes_; diff --git a/Studio/Analysis/AnalysisTool.cpp b/Studio/Analysis/AnalysisTool.cpp index 156bc30928..202e6a2cc6 100644 --- a/Studio/Analysis/AnalysisTool.cpp +++ b/Studio/Analysis/AnalysisTool.cpp @@ -138,7 +138,7 @@ AnalysisTool::AnalysisTool(Preferences& prefs) : preferences_(prefs) { ui_->metrics_open_button->setChecked(false); /// TODO nothing there yet (regression tab) - // ui_->tabWidget->removeTab(3); + ui_->tabWidget->removeTab(3); for (auto button : {ui_->distance_transform_radio_button, ui_->mesh_warping_radio_button, ui_->legacy_radio_button}) { connect(button, &QRadioButton::clicked, this, &AnalysisTool::reconstruction_method_changed); diff --git a/Studio/Resources/.nfs000000041c1dd02f0000039f b/Studio/Resources/.nfs000000041c1dd02f0000039f deleted file mode 100644 index 528a903a88..0000000000 --- a/Studio/Resources/.nfs000000041c1dd02f0000039f +++ /dev/null @@ -1,60 +0,0 @@ - - - Images/shapes-icon.png - Images/acorn.png - Images/circle.png - Images/hammer.png - Images/bug.png - Images/pencil.png - Images/palette.png - Images/red_dots.png - Images/wand.png - Images/injection.png - Images/hammer2.png - Images/wand2.png - Images/star.png - Images/star2.png - Images/snowflake.png - Images/grey_ball.png - Images/run.png - Images/blocks.png - Images/blocks2.png - Images/blue_ball.png - Images/purple_ball.png - Images/dots.png - Images/wrench.png - Images/wrench2.png - Images/gear2.png - Images/add.png - Images/remove.png - Images/select.png - Images/unselect.png - Images/data.png - Images/chart.png - Images/deep_ssm.png - Images/gear.png - Images/tools.png - Images/shapeworks-logo.png - Images/DownArrow.png - Images/DownArrowWhite.png - Images/RightArrow.png - Images/RightArrowWhite.png - Images/AutoView.png - Images/AutoViewOff.png - Images/IsosurfaceVisible.png - Images/IsosurfaceVisibleOff.png - Images/Visible.png - Images/VisibleGray.png - Images/VisibleOff.png - Images/spinner.png - Images/log_normal.png - Images/log_warning.png - Images/log_error.png - Images/Brush.png - Images/flag_on.png - Images/flag_off.png - Images/planes_on.png - Images/planes_off.png - Images/down_arrow.png - - From 04c25ea6ac93822a62505e95f6bf0240ce4e2937 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Tue, 31 Dec 2024 12:48:13 -0700 Subject: [PATCH 13/22] edit logic --- Studio/Analysis/AnalysisTool.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Studio/Analysis/AnalysisTool.cpp b/Studio/Analysis/AnalysisTool.cpp index 202e6a2cc6..83fb73b1c9 100644 --- a/Studio/Analysis/AnalysisTool.cpp +++ b/Studio/Analysis/AnalysisTool.cpp @@ -890,17 +890,11 @@ ShapeHandle AnalysisTool::get_current_shape() { int pca_mode = get_pca_mode(); double pca_value = get_pca_value(); auto mca_level = get_mca_level(); - bool regression_analysis_enabled = get_regression_analysis_status(); - if (!regression_analysis_enabled) { - if (mca_level == AnalysisTool::McaMode::Vanilla) { + if (mca_level == AnalysisTool::McaMode::Vanilla) { return get_mode_shape(pca_mode, pca_value); } else { return get_mca_mode_shape(pca_mode, pca_value, mca_level); } - } else { - - } - } //--------------------------------------------------------------------------- From 6eb9637565ee51ddafeb2cebe96193037190602f Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Fri, 3 Jan 2025 16:05:12 -0700 Subject: [PATCH 14/22] add comupte regression mean logic --- Libs/Particles/ParticleShapeStatistics.cpp | 21 +++++++++++++++++++++ Libs/Particles/ParticleShapeStatistics.h | 6 ++++-- Studio/Analysis/AnalysisTool.cpp | 15 +++++++++------ Studio/Analysis/AnalysisTool.h | 4 +++- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/Libs/Particles/ParticleShapeStatistics.cpp b/Libs/Particles/ParticleShapeStatistics.cpp index aa6d8c008b..60effe45a8 100644 --- a/Libs/Particles/ParticleShapeStatistics.cpp +++ b/Libs/Particles/ParticleShapeStatistics.cpp @@ -492,6 +492,27 @@ ParticleShapeStatistics::ParticleShapeStatistics(std::shared_ptr projec groups.push_back(1); } import_points(points, groups); + // TODO: importing regression params doesn't make sense here. take a look again later. +} + + Eigen::VectorXd ParticleShapeStatistics::compute_regression_mean(const std::vector& explanatory_variables) const +{ + // Map explanatory variables to an Eigen vector + Eigen::VectorXd t = Eigen::Map(explanatory_variables.data(), explanatory_variables.size()); + + // Ensure slope and intercept are initialized + if (slope_.size() == 0 || intercept_.size() == 0) { + throw std::runtime_error("Slope and Intercept not initialized yet!"); + } + + // Handle scalar and vector cases for t + if (t.size() == 1) { + return slope_ + intercept_ * t[0]; // Scalar broadcasting + } else if (t.size() == slope_.size()) { + return slope_ + intercept_.cwiseProduct(t); // Element-wise multiplication + } else { + throw std::invalid_argument("Size mismatch: t must be either scalar or match dimensions of slope and intercept."); + } } //--------------------------------------------------------------------------- diff --git a/Libs/Particles/ParticleShapeStatistics.h b/Libs/Particles/ParticleShapeStatistics.h index 0606b77859..1960b85121 100644 --- a/Libs/Particles/ParticleShapeStatistics.h +++ b/Libs/Particles/ParticleShapeStatistics.h @@ -87,7 +87,9 @@ class ParticleShapeStatistics { const Eigen::VectorXd& get_mean_rel_pos() { return mean_rel_pose_; } //! Returns the mean shape. - const Eigen::VectorXd& get_mean() const { return mean_; } + const Eigen::VectorXd get_mean() const { return mean_; } + + Eigen::VectorXd compute_regression_mean(const std::vector& explanatory_variables) const; const Eigen::VectorXd& get_group1_mean() const { return mean1_; } const Eigen::VectorXd& get_group2_mean() const { return mean2_; } @@ -136,7 +138,7 @@ class ParticleShapeStatistics { void set_meshes(const std::vector& meshes) { meshes_ = meshes; } // import estimated parameters for regression - inline bool import_regression_parameters(Eigen::VectorXd slope, Eigen::VectorXd intercept) { slope_ = slope; intercept_ = intercept; }; + inline bool import_regression_parameters(Eigen::VectorXd& slope, Eigen::VectorXd& intercept) { slope_ = slope; intercept_ = intercept; return true;}; private: unsigned int num_samples_group1_; diff --git a/Studio/Analysis/AnalysisTool.cpp b/Studio/Analysis/AnalysisTool.cpp index 83fb73b1c9..a15cd7f581 100644 --- a/Studio/Analysis/AnalysisTool.cpp +++ b/Studio/Analysis/AnalysisTool.cpp @@ -664,10 +664,13 @@ bool AnalysisTool::compute_stats() { can_run_regression_ = check_explanatory_variable_limits(); if (can_run_regression_) { auto slope = load_regression_parameters( - session_->get_regression_param_file("slope")); + session_->get_regression_param_file("slope")); // dM vector auto intercept = load_regression_parameters( - session_->get_regression_param_file("intercept")); - stats_.import_regression_parameters(slope, intercept); + session_->get_regression_param_file("intercept")); // dM vector + stats_.import_regression_parameters(slope, intercept); // set slope and intercept in stats object + ui_->regression_groupbox->setVisible(true); + ui_->explanatoryVariableSlider->setVisible(true); + ui_->enableRegressionCheckBox->setVisible(true); } else { ui_->regression_groupbox->setVisible(false); @@ -790,7 +793,7 @@ Particles AnalysisTool::get_shape_points(int mode, double value) { ui_->explained_variance->setText(""); ui_->cumulative_explained_variance->setText(""); } - auto mean = !regression_enabled_ ? stats_.get_mean() : stats_.get_regression_mean(ui_->get_explanatory_variable_value()); + auto mean = !regression_enabled_ ? stats_.get_mean() : stats_.compute_regression_mean(ui_->get_explanatory_variable_value()); temp_shape_ = mean + (e * (value * lambda)); auto positions = temp_shape_; @@ -1157,9 +1160,9 @@ double AnalysisTool::get_pca_value() { } -double AnalysisTool::get_explanatory_variable_value() { +std::vector AnalysisTool::get_explanatory_variable_value() { int slider_value = ui_->explanatoryVariableSlider->value(); - return t_min + (static_cast(slider_value) / 100.0) * (t_max - t_min); + return {t_min + (static_cast(slider_value) / 100.0) * (t_max - t_min)}; } diff --git a/Studio/Analysis/AnalysisTool.h b/Studio/Analysis/AnalysisTool.h index 81e22509bb..a2d853d7fa 100644 --- a/Studio/Analysis/AnalysisTool.h +++ b/Studio/Analysis/AnalysisTool.h @@ -77,6 +77,8 @@ class AnalysisTool : public QWidget { double get_pca_value(); + std::vector get_explanatory_variable_value(); + bool pca_animate(); McaMode get_mca_level() const; @@ -282,7 +284,7 @@ class AnalysisTool : public QWidget { std::string feature_map_; std::vector explanatory_variable_limits_; - bool can_run_regression_; + bool can_run_regression_; // decide if necessary variables are present to run regression in analysis std::vector current_group_names_; std::vector current_group_values_; From d364a4425ddf99fcd68231fc597e433b0d52fd2e Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Fri, 3 Jan 2025 16:07:46 -0700 Subject: [PATCH 15/22] typo fixes --- Libs/Particles/ParticleShapeStatistics.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Libs/Particles/ParticleShapeStatistics.h b/Libs/Particles/ParticleShapeStatistics.h index 1960b85121..ee3e9e6f8b 100644 --- a/Libs/Particles/ParticleShapeStatistics.h +++ b/Libs/Particles/ParticleShapeStatistics.h @@ -87,9 +87,9 @@ class ParticleShapeStatistics { const Eigen::VectorXd& get_mean_rel_pos() { return mean_rel_pose_; } //! Returns the mean shape. - const Eigen::VectorXd get_mean() const { return mean_; } + const Eigen::VectorXd& get_mean() const { return mean_; } - Eigen::VectorXd compute_regression_mean(const std::vector& explanatory_variables) const; + Eigen::VectorXd compute_regression_mean(const std::vector& explanatory_variables) const; const Eigen::VectorXd& get_group1_mean() const { return mean1_; } const Eigen::VectorXd& get_group2_mean() const { return mean2_; } @@ -138,7 +138,7 @@ class ParticleShapeStatistics { void set_meshes(const std::vector& meshes) { meshes_ = meshes; } // import estimated parameters for regression - inline bool import_regression_parameters(Eigen::VectorXd& slope, Eigen::VectorXd& intercept) { slope_ = slope; intercept_ = intercept; return true;}; + inline bool import_regression_parameters(Eigen::VectorXd slope, Eigen::VectorXd intercept) { slope_ = slope; intercept_ = intercept; return true;}; private: unsigned int num_samples_group1_; From 1783f7710d6d55b7593cefeb02e5e3748a728417 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Fri, 3 Jan 2025 16:10:41 -0700 Subject: [PATCH 16/22] typo fixes --- Libs/Particles/ParticleShapeStatistics.cpp | 32 ++++++++++------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/Libs/Particles/ParticleShapeStatistics.cpp b/Libs/Particles/ParticleShapeStatistics.cpp index 60effe45a8..979c70a394 100644 --- a/Libs/Particles/ParticleShapeStatistics.cpp +++ b/Libs/Particles/ParticleShapeStatistics.cpp @@ -495,24 +495,20 @@ ParticleShapeStatistics::ParticleShapeStatistics(std::shared_ptr projec // TODO: importing regression params doesn't make sense here. take a look again later. } - Eigen::VectorXd ParticleShapeStatistics::compute_regression_mean(const std::vector& explanatory_variables) const -{ - // Map explanatory variables to an Eigen vector - Eigen::VectorXd t = Eigen::Map(explanatory_variables.data(), explanatory_variables.size()); - - // Ensure slope and intercept are initialized - if (slope_.size() == 0 || intercept_.size() == 0) { - throw std::runtime_error("Slope and Intercept not initialized yet!"); - } - - // Handle scalar and vector cases for t - if (t.size() == 1) { - return slope_ + intercept_ * t[0]; // Scalar broadcasting - } else if (t.size() == slope_.size()) { - return slope_ + intercept_.cwiseProduct(t); // Element-wise multiplication - } else { - throw std::invalid_argument("Size mismatch: t must be either scalar or match dimensions of slope and intercept."); - } +Eigen::VectorXd ParticleShapeStatistics::compute_regression_mean( + const std::vector& explanatory_variables) const { + Eigen::VectorXd t = Eigen::Map( + explanatory_variables.data(), explanatory_variables.size()); + + // Ensure slope and intercept are initialized + if (slope_.size() == 0 || intercept_.size() == 0) { + throw std::runtime_error("Slope and Intercept not initialized yet!"); + } + + if (t.size() == 1) + return slope_ + intercept_ * t[0]; + else + return slope_ + intercept_.cwiseProduct(t); } //--------------------------------------------------------------------------- From 332ad71129660165d4bf5929d05eddf3daeaf2c9 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Mon, 6 Jan 2025 18:13:11 -0700 Subject: [PATCH 17/22] previous regression tab logic --- Studio/Analysis/AnalysisTool.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Studio/Analysis/AnalysisTool.cpp b/Studio/Analysis/AnalysisTool.cpp index a15cd7f581..befb551089 100644 --- a/Studio/Analysis/AnalysisTool.cpp +++ b/Studio/Analysis/AnalysisTool.cpp @@ -383,7 +383,7 @@ void AnalysisTool::handle_analysis_options() { ui_->mcaLevelBetweenButton->setEnabled(true); ui_->vanillaPCAButton->setChecked(true); } - } else if (ui_->tabWidget->currentWidget() == ui_->regression_tab){ + } else { // regression mode ui_->sampleSpinBox->setEnabled(false); ui_->medianButton->setEnabled(false); @@ -392,13 +392,6 @@ void AnalysisTool::handle_analysis_options() { ui_->pcaModeSpinBox->setEnabled(false); pca_animate_timer_.stop(); - } else { - ui_->sampleSpinBox->setEnabled(false); - ui_->medianButton->setEnabled(false); - ui_->pcaSlider->setEnabled(false); - ui_->pcaAnimateCheckBox->setEnabled(false); - ui_->pcaModeSpinBox->setEnabled(false); - pca_animate_timer_.stop(); } update_difference_particles(); From abd8fcf96713e0619aa9f09221d1188084632cc3 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Mon, 6 Jan 2025 18:16:06 -0700 Subject: [PATCH 18/22] previous regression tab logic --- Studio/Optimize/OptimizeTool.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Studio/Optimize/OptimizeTool.h b/Studio/Optimize/OptimizeTool.h index cab850aa3f..30da28d10c 100644 --- a/Studio/Optimize/OptimizeTool.h +++ b/Studio/Optimize/OptimizeTool.h @@ -38,8 +38,6 @@ Q_OBJECT; void load_params(); //! Store params to project - //! Get flag if regression needs to enabled for analysis in Studio - inline bool get_regression_analysis_status() { return regression_analysis_status_; } void store_params(); @@ -99,6 +97,5 @@ public Q_SLOTS: Ui_OptimizeTool* ui_; - bool regression_analysis_status_; }; } From ede45bd5fdd921e38a71918f7a070c1150466e1a Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Wed, 8 Jan 2025 11:58:17 -0700 Subject: [PATCH 19/22] more changes --- Libs/Particles/ParticleShapeStatistics.cpp | 1 + Libs/Particles/ParticleShapeStatistics.h | 1 - Studio/Analysis/AnalysisTool.cpp | 7 ++++--- Studio/Interface/ShapeWorksStudioApp.cpp | 8 -------- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Libs/Particles/ParticleShapeStatistics.cpp b/Libs/Particles/ParticleShapeStatistics.cpp index 979c70a394..d35312248f 100644 --- a/Libs/Particles/ParticleShapeStatistics.cpp +++ b/Libs/Particles/ParticleShapeStatistics.cpp @@ -497,6 +497,7 @@ ParticleShapeStatistics::ParticleShapeStatistics(std::shared_ptr projec Eigen::VectorXd ParticleShapeStatistics::compute_regression_mean( const std::vector& explanatory_variables) const { + std::cout << "Computing mean for regression" << std::endl; Eigen::VectorXd t = Eigen::Map( explanatory_variables.data(), explanatory_variables.size()); diff --git a/Libs/Particles/ParticleShapeStatistics.h b/Libs/Particles/ParticleShapeStatistics.h index ee3e9e6f8b..2a1602b806 100644 --- a/Libs/Particles/ParticleShapeStatistics.h +++ b/Libs/Particles/ParticleShapeStatistics.h @@ -159,7 +159,6 @@ class ParticleShapeStatistics { // for regression tasks Eigen::VectorXd slope_; Eigen::VectorXd intercept_; - bool regression_enabled_; std::vector percent_variance_by_mode_; Eigen::MatrixXd principals_; diff --git a/Studio/Analysis/AnalysisTool.cpp b/Studio/Analysis/AnalysisTool.cpp index befb551089..e3bc097e2d 100644 --- a/Studio/Analysis/AnalysisTool.cpp +++ b/Studio/Analysis/AnalysisTool.cpp @@ -713,7 +713,7 @@ bool AnalysisTool::compute_stats() { bool check_explanatory_variable_limits() { auto subjects = session_->get_project()->get_subjects(); - explanatory_variable_limits_.resize(2); + explanatory_variable_limits_.resize(2, 0.0); explanatory_variable_limits_[0] = std::numeric_limits::max(); explanatory_variable_limits_[1] = std::numeric_limits::lowest(); for (auto sub : subjects) { @@ -786,7 +786,7 @@ Particles AnalysisTool::get_shape_points(int mode, double value) { ui_->explained_variance->setText(""); ui_->cumulative_explained_variance->setText(""); } - auto mean = !regression_enabled_ ? stats_.get_mean() : stats_.compute_regression_mean(ui_->get_explanatory_variable_value()); + auto mean = !get_regression_analysis_status() ? stats_.get_mean() : stats_.compute_regression_mean(ui_->get_explanatory_variable_value()); temp_shape_ = mean + (e * (value * lambda)); auto positions = temp_shape_; @@ -1155,7 +1155,8 @@ double AnalysisTool::get_pca_value() { std::vector AnalysisTool::get_explanatory_variable_value() { int slider_value = ui_->explanatoryVariableSlider->value(); - return {t_min + (static_cast(slider_value) / 100.0) * (t_max - t_min)}; + // return {t_min + (static_cast(slider_value) / 100.0) * (t_max - t_min)}; + return {explanatory_variable_limits_[0] + (static_cast(slider_value) / 100.0) * (explanatory_variable_limits_[1] - explanatory_variable_limits_[0])}; } diff --git a/Studio/Interface/ShapeWorksStudioApp.cpp b/Studio/Interface/ShapeWorksStudioApp.cpp index b312dea14e..bb0128c0a3 100644 --- a/Studio/Interface/ShapeWorksStudioApp.cpp +++ b/Studio/Interface/ShapeWorksStudioApp.cpp @@ -1528,14 +1528,6 @@ void ShapeWorksStudioApp::open_project(QString filename) { groom_tool_->load_params(); optimize_tool_->load_params(); - - if (optimize_tool_->get_regression_analysis_status()) - { - // Verify if slope and intercept files exist - // auto particles_dir = session_->get_filename().dir().absolutePath().toStdString(); - // auto slope_filename = session_->get_filename().toStdString(); - } - analysis_tool_->store_settings(); update_from_preferences(); update_tool_mode(); From d13ae70bc61561c55cf1fad10e2be184024e3c64 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Wed, 8 Jan 2025 12:01:48 -0700 Subject: [PATCH 20/22] code clean --- Libs/Particles/ParticleShapeStatistics.cpp | 1 + Studio/Analysis/AnalysisTool.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Libs/Particles/ParticleShapeStatistics.cpp b/Libs/Particles/ParticleShapeStatistics.cpp index d35312248f..f415567e3c 100644 --- a/Libs/Particles/ParticleShapeStatistics.cpp +++ b/Libs/Particles/ParticleShapeStatistics.cpp @@ -495,6 +495,7 @@ ParticleShapeStatistics::ParticleShapeStatistics(std::shared_ptr projec // TODO: importing regression params doesn't make sense here. take a look again later. } +//--------------------------------------------------------------------------- Eigen::VectorXd ParticleShapeStatistics::compute_regression_mean( const std::vector& explanatory_variables) const { std::cout << "Computing mean for regression" << std::endl; diff --git a/Studio/Analysis/AnalysisTool.cpp b/Studio/Analysis/AnalysisTool.cpp index e3bc097e2d..8db6755fa8 100644 --- a/Studio/Analysis/AnalysisTool.cpp +++ b/Studio/Analysis/AnalysisTool.cpp @@ -391,7 +391,6 @@ void AnalysisTool::handle_analysis_options() { ui_->pcaAnimateCheckBox->setEnabled(false); ui_->pcaModeSpinBox->setEnabled(false); pca_animate_timer_.stop(); - } update_difference_particles(); @@ -503,6 +502,7 @@ void AnalysisTool::network_analysis_clicked() { app_->get_py_worker()->run_job(network_analysis_job_); } +//--------------------------------------------------------------------------- Eigen::VectorXd load_regression_parameters(std::string filepath) { std::ifstream infile(slope_file_path); if (!infile.good()) { @@ -711,6 +711,7 @@ bool AnalysisTool::compute_stats() { return true; } +//--------------------------------------------------------------------------- bool check_explanatory_variable_limits() { auto subjects = session_->get_project()->get_subjects(); explanatory_variable_limits_.resize(2, 0.0); From 9e211ca08460d3a19175a147a9abfb7538c6eb85 Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Wed, 8 Jan 2025 12:05:50 -0700 Subject: [PATCH 21/22] code clean --- Studio/Analysis/AnalysisTool.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Studio/Analysis/AnalysisTool.cpp b/Studio/Analysis/AnalysisTool.cpp index 8db6755fa8..66406fe729 100644 --- a/Studio/Analysis/AnalysisTool.cpp +++ b/Studio/Analysis/AnalysisTool.cpp @@ -655,6 +655,7 @@ bool AnalysisTool::compute_stats() { } can_run_regression_ = check_explanatory_variable_limits(); + std::cout << "can run regression set to " << can_run_regression_ << std::endl; if (can_run_regression_) { auto slope = load_regression_parameters( session_->get_regression_param_file("slope")); // dM vector @@ -888,10 +889,10 @@ ShapeHandle AnalysisTool::get_current_shape() { double pca_value = get_pca_value(); auto mca_level = get_mca_level(); if (mca_level == AnalysisTool::McaMode::Vanilla) { - return get_mode_shape(pca_mode, pca_value); - } else { - return get_mca_mode_shape(pca_mode, pca_value, mca_level); - } + return get_mode_shape(pca_mode, pca_value); + } else { + return get_mca_mode_shape(pca_mode, pca_value, mca_level); + } } //--------------------------------------------------------------------------- From fb5698bb2be9fdc2afc476c878ad73f44fad3d4f Mon Sep 17 00:00:00 2001 From: nawazishkhan1-nk Date: Wed, 8 Jan 2025 12:42:30 -0700 Subject: [PATCH 22/22] edits --- Studio/Analysis/AnalysisTool.cpp | 10 +++++++++- Studio/Analysis/AnalysisTool.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Studio/Analysis/AnalysisTool.cpp b/Studio/Analysis/AnalysisTool.cpp index 66406fe729..e3a3127bfd 100644 --- a/Studio/Analysis/AnalysisTool.cpp +++ b/Studio/Analysis/AnalysisTool.cpp @@ -788,7 +788,7 @@ Particles AnalysisTool::get_shape_points(int mode, double value) { ui_->explained_variance->setText(""); ui_->cumulative_explained_variance->setText(""); } - auto mean = !get_regression_analysis_status() ? stats_.get_mean() : stats_.compute_regression_mean(ui_->get_explanatory_variable_value()); + auto mean = !get_regression_analysis_status() ? stats_.get_mean() : stats_.compute_regression_mean(get_explanatory_variable_value()); temp_shape_ = mean + (e * (value * lambda)); auto positions = temp_shape_; @@ -1054,6 +1054,13 @@ void AnalysisTool::on_pcaSlider_valueChanged() { Q_EMIT pca_update(); } +//--------------------------------------------------------------------------- +void AnalysisTool::on_explanatoryVariableSlider_valueChanged() { + // this will make the slider handle redraw making the UI appear more responsive + QCoreApplication::processEvents(); + Q_EMIT pca_update(); +} + //--------------------------------------------------------------------------- void AnalysisTool::on_group_slider_valueChanged() { // this will make the slider handle redraw making the UI appear more responsive @@ -1180,6 +1187,7 @@ void AnalysisTool::update_slider() { void AnalysisTool::reset_stats() { stats_ready_ = false; evals_ready_ = false; + can_run_regression_ = false; ui_->tabWidget->setCurrentWidget(ui_->mean_tab); ui_->allSamplesRadio->setChecked(true); diff --git a/Studio/Analysis/AnalysisTool.h b/Studio/Analysis/AnalysisTool.h index a2d853d7fa..ae35bb5347 100644 --- a/Studio/Analysis/AnalysisTool.h +++ b/Studio/Analysis/AnalysisTool.h @@ -141,6 +141,7 @@ class AnalysisTool : public QWidget { // PCA void on_pcaSlider_valueChanged(); + void on_explanatoryVariableSlider_valueChanged(); void on_group_slider_valueChanged(); void on_pcaModeSpinBox_valueChanged(int i);