Skip to content

Commit

Permalink
Address part of #2218. This commit adds the ability to see both the p…
Browse files Browse the repository at this point in the history
…redicted scalar on all samples as well as the diff to predicted.
  • Loading branch information
akenmorris committed Mar 27, 2024
1 parent 15e5f4c commit 731aee8
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 49 deletions.
2 changes: 1 addition & 1 deletion Libs/Analyze/StudioMesh.cpp
Expand Up @@ -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;
}

Expand Down
63 changes: 63 additions & 0 deletions Studio/Analysis/AnalysisTool.cpp
Expand Up @@ -161,6 +161,23 @@ AnalysisTool::AnalysisTool(Preferences& prefs) : preferences_(prefs) {

connect(ui_->group_analysis_combo, qOverload<int>(&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);
}

//---------------------------------------------------------------------------
Expand Down Expand Up @@ -280,6 +297,9 @@ void AnalysisTool::set_session(QSharedPointer<Session> 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);
}

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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_;
}

Expand Down Expand Up @@ -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();
}
Expand All @@ -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());
Expand Down
2 changes: 2 additions & 0 deletions Studio/Analysis/AnalysisTool.h
Expand Up @@ -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();
Expand Down
80 changes: 63 additions & 17 deletions Studio/Analysis/AnalysisTool.ui
Expand Up @@ -535,7 +535,7 @@ QWidget#particles_panel {
<item row="3" column="0" colspan="2">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>2</number>
<number>1</number>
</property>
<widget class="QWidget" name="mean_tab">
<attribute name="title">
Expand Down Expand Up @@ -1089,16 +1089,6 @@ QWidget#particles_panel {
<string>Samples</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="1" column="1">
<widget class="QSpinBox" name="sampleSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Sample selection</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="singleSamplesRadio">
<property name="toolTip">
Expand All @@ -1109,6 +1099,19 @@ QWidget#particles_panel {
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QPushButton" name="medianButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Show median sample</string>
</property>
<property name="text">
<string>Median</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="allSamplesRadio">
<property name="toolTip">
Expand All @@ -1122,19 +1125,62 @@ QWidget#particles_panel {
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QPushButton" name="medianButton">
<item row="3" column="0" colspan="2">
<widget class="QWidget" name="predict_diff_widget" native="true">
<layout class="QGridLayout" name="gridLayout_28">
<item row="0" column="0">
<widget class="QCheckBox" name="show_difference_to_predicted_scalar">
<property name="text">
<string>Show difference to predicted scalar</string>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="show_predicted_scalar">
<property name="text">
<string>Show predicted scalar</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="sampleSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Show median sample</string>
</property>
<property name="text">
<string>Median</string>
<string>Sample selection</string>
</property>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="pca_tab">
Expand Down
22 changes: 21 additions & 1 deletion Studio/Data/Session.cpp
Expand Up @@ -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() {
Expand Down Expand Up @@ -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();
}
Expand Down
1 change: 1 addition & 0 deletions Studio/Data/Session.h
Expand Up @@ -285,6 +285,7 @@ class Session : public QObject, public QEnableSharedFromThis<Session> {
void planes_changed();
void ffc_changed();
void update_display();
void feature_map_changed();
void reset_stats();
void new_mesh();
void feature_range_changed();
Expand Down
31 changes: 4 additions & 27 deletions Studio/Interface/ShapeWorksStudioApp.cpp
Expand Up @@ -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());
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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_) {
Expand Down Expand Up @@ -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());
}

//---------------------------------------------------------------------------
Expand All @@ -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);
Expand Down
3 changes: 0 additions & 3 deletions Studio/Interface/ShapeWorksStudioApp.h
Expand Up @@ -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);

Expand Down

0 comments on commit 731aee8

Please sign in to comment.