Skip to content

Commit 731aee8

Browse files
committed
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.
1 parent 15e5f4c commit 731aee8

File tree

8 files changed

+155
-49
lines changed

8 files changed

+155
-49
lines changed

Libs/Analyze/StudioMesh.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ void StudioMesh::interpolate_scalars_to_mesh(std::string name, Eigen::VectorXd p
9898

9999
if (num_points != scalar_values.size()) {
100100
std::cerr << "Warning, mismatch of points and scalar values (num_points = " << num_points
101-
<< ", scalar_values.size() = " << scalar_values.size() << std::endl;
101+
<< ", scalar_values.size() = " << scalar_values.size() << ")\n";
102102
return;
103103
}
104104

Studio/Analysis/AnalysisTool.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,23 @@ AnalysisTool::AnalysisTool(Preferences& prefs) : preferences_(prefs) {
161161

162162
connect(ui_->group_analysis_combo, qOverload<int>(&QComboBox::currentIndexChanged), this,
163163
&AnalysisTool::group_analysis_combo_changed);
164+
165+
// when one is checked, turn the other off, connect these first
166+
connect(ui_->show_difference_to_predicted_scalar, &QPushButton::clicked, this, [this]() {
167+
if (ui_->show_difference_to_predicted_scalar->isChecked()) {
168+
ui_->show_predicted_scalar->setChecked(false);
169+
}
170+
});
171+
connect(ui_->show_predicted_scalar, &QPushButton::clicked, this, [this]() {
172+
if (ui_->show_predicted_scalar->isChecked()) {
173+
ui_->show_difference_to_predicted_scalar->setChecked(false);
174+
}
175+
});
176+
177+
connect(ui_->show_difference_to_predicted_scalar, &QPushButton::clicked, this,
178+
&AnalysisTool::handle_samples_predicted_scalar_options);
179+
connect(ui_->show_predicted_scalar, &QPushButton::clicked, this,
180+
&AnalysisTool::handle_samples_predicted_scalar_options);
164181
}
165182

166183
//---------------------------------------------------------------------------
@@ -280,6 +297,9 @@ void AnalysisTool::set_session(QSharedPointer<Session> session) {
280297
ui_->group2_button->setChecked(false);
281298
update_difference_particles();
282299

300+
ui_->show_predicted_scalar->setChecked(false);
301+
ui_->show_difference_to_predicted_scalar->setChecked(false);
302+
283303
connect(ui_->show_good_bad, &QCheckBox::toggled, session_.data(), &Session::set_show_good_bad_particles);
284304
}
285305

@@ -1091,6 +1111,11 @@ void AnalysisTool::reset_stats() {
10911111
ui_->pca_scalar_combo->addItem(QString::fromStdString(feature));
10921112
}
10931113
}
1114+
bool has_scalars = ui_->pca_scalar_combo->count() > 0;
1115+
if (!has_scalars) {
1116+
ui_->show_difference_to_predicted_scalar->setChecked(false);
1117+
}
1118+
ui_->show_difference_to_predicted_scalar->setEnabled(has_scalars);
10941119

10951120
ui_->shape_scalar_groupbox->setVisible(ui_->pca_scalar_combo->count() > 0);
10961121
}
@@ -1303,6 +1328,15 @@ std::string AnalysisTool::get_display_feature_map() {
13031328
}
13041329
}
13051330

1331+
if (get_analysis_mode() == AnalysisTool::MODE_ALL_SAMPLES_C &&
1332+
ui_->show_difference_to_predicted_scalar->isChecked()) {
1333+
return "predicted_scalar_diff";
1334+
}
1335+
1336+
if (get_analysis_mode() == AnalysisTool::MODE_ALL_SAMPLES_C && ui_->show_predicted_scalar->isChecked()) {
1337+
return "predicted_scalar";
1338+
}
1339+
13061340
return feature_map_;
13071341
}
13081342

@@ -1763,6 +1797,11 @@ void AnalysisTool::change_pca_analysis_type() {
17631797
ui_->pca_predict_scalar->setEnabled(ui_->pca_scalar_shape_only->isChecked());
17641798
ui_->pca_predict_shape->setEnabled(ui_->pca_scalar_only->isChecked());
17651799

1800+
if (ui_->pca_predict_scalar->isChecked()) {
1801+
// set the feature map to the target feature
1802+
session_->set_feature_map(ui_->pca_scalar_combo->currentText().toStdString());
1803+
}
1804+
17661805
compute_stats();
17671806
Q_EMIT pca_update();
17681807
}
@@ -1785,6 +1824,30 @@ Eigen::VectorXd AnalysisTool::construct_mean_shape() {
17851824
return mean_shape;
17861825
}
17871826

1827+
//---------------------------------------------------------------------------
1828+
void AnalysisTool::handle_samples_predicted_scalar_options() {
1829+
if (ui_->show_difference_to_predicted_scalar->isChecked() || ui_->show_predicted_scalar->isChecked()) {
1830+
// iterate over all samples, predict scalars, compute the difference and store as a new scalar field
1831+
auto shapes = session_->get_non_excluded_shapes();
1832+
for (auto& shape : shapes) {
1833+
auto particles = shape->get_particles();
1834+
auto target_feature = ui_->pca_scalar_combo->currentText();
1835+
auto predicted =
1836+
ShapeScalarJob::predict_scalars(session_, target_feature, particles.get_combined_global_particles());
1837+
1838+
// load the mesh and feature
1839+
shape->get_meshes(session_->get_display_mode(), true);
1840+
shape->load_feature(session_->get_display_mode(), target_feature.toStdString());
1841+
auto scalars = shape->get_point_features(target_feature.toStdString());
1842+
// compute difference
1843+
auto diff = predicted - scalars;
1844+
shape->set_point_features("predicted_scalar_diff", diff);
1845+
shape->set_point_features("predicted_scalar", predicted);
1846+
}
1847+
}
1848+
Q_EMIT update_view();
1849+
}
1850+
17881851
//---------------------------------------------------------------------------
17891852
void AnalysisTool::reconstruction_method_changed() {
17901853
ui_->reconstruction_options->setVisible(ui_->distance_transform_radio_button->isChecked());

Studio/Analysis/AnalysisTool.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ class AnalysisTool : public QWidget {
197197
//! Compute the mean shape outside of the PCA in case we are using scalars only
198198
Eigen::VectorXd construct_mean_shape();
199199

200+
void handle_samples_predicted_scalar_options();
201+
200202
Q_SIGNALS:
201203

202204
void update_view();

Studio/Analysis/AnalysisTool.ui

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ QWidget#particles_panel {
535535
<item row="3" column="0" colspan="2">
536536
<widget class="QTabWidget" name="tabWidget">
537537
<property name="currentIndex">
538-
<number>2</number>
538+
<number>1</number>
539539
</property>
540540
<widget class="QWidget" name="mean_tab">
541541
<attribute name="title">
@@ -1089,16 +1089,6 @@ QWidget#particles_panel {
10891089
<string>Samples</string>
10901090
</attribute>
10911091
<layout class="QGridLayout" name="gridLayout_4">
1092-
<item row="1" column="1">
1093-
<widget class="QSpinBox" name="sampleSpinBox">
1094-
<property name="enabled">
1095-
<bool>false</bool>
1096-
</property>
1097-
<property name="toolTip">
1098-
<string>Sample selection</string>
1099-
</property>
1100-
</widget>
1101-
</item>
11021092
<item row="1" column="0">
11031093
<widget class="QRadioButton" name="singleSamplesRadio">
11041094
<property name="toolTip">
@@ -1109,6 +1099,19 @@ QWidget#particles_panel {
11091099
</property>
11101100
</widget>
11111101
</item>
1102+
<item row="2" column="0" colspan="2">
1103+
<widget class="QPushButton" name="medianButton">
1104+
<property name="enabled">
1105+
<bool>false</bool>
1106+
</property>
1107+
<property name="toolTip">
1108+
<string>Show median sample</string>
1109+
</property>
1110+
<property name="text">
1111+
<string>Median</string>
1112+
</property>
1113+
</widget>
1114+
</item>
11121115
<item row="0" column="0">
11131116
<widget class="QRadioButton" name="allSamplesRadio">
11141117
<property name="toolTip">
@@ -1122,19 +1125,62 @@ QWidget#particles_panel {
11221125
</property>
11231126
</widget>
11241127
</item>
1125-
<item row="2" column="0" colspan="2">
1126-
<widget class="QPushButton" name="medianButton">
1128+
<item row="3" column="0" colspan="2">
1129+
<widget class="QWidget" name="predict_diff_widget" native="true">
1130+
<layout class="QGridLayout" name="gridLayout_28">
1131+
<item row="0" column="0">
1132+
<widget class="QCheckBox" name="show_difference_to_predicted_scalar">
1133+
<property name="text">
1134+
<string>Show difference to predicted scalar</string>
1135+
</property>
1136+
</widget>
1137+
</item>
1138+
<item row="0" column="1">
1139+
<spacer name="horizontalSpacer_9">
1140+
<property name="orientation">
1141+
<enum>Qt::Horizontal</enum>
1142+
</property>
1143+
<property name="sizeHint" stdset="0">
1144+
<size>
1145+
<width>40</width>
1146+
<height>20</height>
1147+
</size>
1148+
</property>
1149+
</spacer>
1150+
</item>
1151+
<item row="1" column="0">
1152+
<widget class="QCheckBox" name="show_predicted_scalar">
1153+
<property name="text">
1154+
<string>Show predicted scalar</string>
1155+
</property>
1156+
</widget>
1157+
</item>
1158+
</layout>
1159+
</widget>
1160+
</item>
1161+
<item row="1" column="1">
1162+
<widget class="QSpinBox" name="sampleSpinBox">
11271163
<property name="enabled">
11281164
<bool>false</bool>
11291165
</property>
11301166
<property name="toolTip">
1131-
<string>Show median sample</string>
1132-
</property>
1133-
<property name="text">
1134-
<string>Median</string>
1167+
<string>Sample selection</string>
11351168
</property>
11361169
</widget>
11371170
</item>
1171+
<item row="4" column="0">
1172+
<spacer name="verticalSpacer_3">
1173+
<property name="orientation">
1174+
<enum>Qt::Vertical</enum>
1175+
</property>
1176+
<property name="sizeHint" stdset="0">
1177+
<size>
1178+
<width>20</width>
1179+
<height>40</height>
1180+
</size>
1181+
</property>
1182+
</spacer>
1183+
</item>
11381184
</layout>
11391185
</widget>
11401186
<widget class="QWidget" name="pca_tab">

Studio/Data/Session.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1138,11 +1138,23 @@ bool Session::get_image_thickness_feature() { return params_.get("image_thicknes
11381138
void Session::set_feature_map(std::string feature_map) {
11391139
if (feature_map != get_feature_map() || is_loading()) {
11401140
params_.set("feature_map", feature_map);
1141+
Q_EMIT feature_map_changed();
11411142
}
11421143
}
11431144

11441145
//---------------------------------------------------------------------------
1145-
std::string Session::get_feature_map() { return params_.get("feature_map", ""); }
1146+
std::string Session::get_feature_map() {
1147+
std::string feature_map = params_.get("feature_map", "");
1148+
1149+
// confirm that this is a valid feature map
1150+
auto feature_maps = get_project()->get_feature_names();
1151+
for (const std::string& feature : feature_maps) {
1152+
if (feature_map == feature) {
1153+
return feature_map;
1154+
}
1155+
}
1156+
return "";
1157+
}
11461158

11471159
//---------------------------------------------------------------------------
11481160
bool Session::has_constraints() {
@@ -1281,6 +1293,14 @@ Eigen::MatrixXd Session::get_all_scalars(std::string target_feature) {
12811293

12821294
Eigen::VectorXd scalars = shapes[i]->get_point_features(target_feature);
12831295

1296+
// check that the scalars are the right size
1297+
if (scalars.size() != num_particles) {
1298+
SW_ERROR("scalars.size() : {}", scalars.size());
1299+
SW_ERROR("num_particles : {}", num_particles);
1300+
SW_ERROR("Error: scalars size does not match number of particles");
1301+
return Eigen::MatrixXd();
1302+
}
1303+
12841304
// write into all_scalars
12851305
all_scalars.row(i) = scalars.transpose();
12861306
}

Studio/Data/Session.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ class Session : public QObject, public QEnableSharedFromThis<Session> {
285285
void planes_changed();
286286
void ffc_changed();
287287
void update_display();
288+
void feature_map_changed();
288289
void reset_stats();
289290
void new_mesh();
290291
void feature_range_changed();

Studio/Interface/ShapeWorksStudioApp.cpp

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ void ShapeWorksStudioApp::import_files(QStringList file_names) {
423423

424424
if (first_load) {
425425
// On first load, we can check if there was an active scalar on loaded meshes
426-
set_feature_map(session_->get_default_feature_map());
426+
session_->set_feature_map(session_->get_default_feature_map());
427427
}
428428
} catch (std::runtime_error& e) {
429429
handle_error(e.what());
@@ -970,6 +970,7 @@ void ShapeWorksStudioApp::new_session() {
970970
connect(session_.data(), &Session::reset_stats, this, &ShapeWorksStudioApp::handle_reset_stats);
971971
connect(session_.data(), &Session::update_display, this, &ShapeWorksStudioApp::handle_display_setting_changed);
972972
connect(session_.data(), &Session::update_view_mode, this, &ShapeWorksStudioApp::update_view_mode);
973+
connect(session_.data(), &Session::feature_map_changed, this, &ShapeWorksStudioApp::update_view_mode);
973974
connect(session_.data(), &Session::new_mesh, this, &ShapeWorksStudioApp::handle_new_mesh);
974975
connect(session_.data(), &Session::reinsert_shapes, this, [&]() { update_display(true); });
975976
connect(session_.data(), &Session::save, this, &ShapeWorksStudioApp::on_action_save_project_triggered);
@@ -1087,7 +1088,7 @@ void ShapeWorksStudioApp::update_view_mode() {
10871088
ui_->view_mode_combobox->setCurrentText(QString::fromStdString(display_mode_to_string(view_mode)));
10881089
update_view_combo();
10891090

1090-
auto feature_map = get_feature_map();
1091+
auto feature_map = session_->get_feature_map();
10911092
ui_->features->setCurrentText(QString::fromStdString(feature_map));
10921093

10931094
if (visualizer_) {
@@ -2041,7 +2042,7 @@ QString ShapeWorksStudioApp::get_mesh_file_filter() {
20412042
//---------------------------------------------------------------------------
20422043
void ShapeWorksStudioApp::update_feature_map_selection(int index) {
20432044
QString feature_map = ui_->features->itemText(index);
2044-
set_feature_map(feature_map.toStdString());
2045+
session_->set_feature_map(feature_map.toStdString());
20452046
}
20462047

20472048
//---------------------------------------------------------------------------
@@ -2065,30 +2066,6 @@ void ShapeWorksStudioApp::image_combo_changed(int index) {
20652066
session_->set_image_name(ui_->image_combo_->itemText(index).toStdString());
20662067
}
20672068

2068-
//---------------------------------------------------------------------------
2069-
bool ShapeWorksStudioApp::set_feature_map(std::string feature_map) {
2070-
if (feature_map != get_feature_map()) {
2071-
session_->set_feature_map(feature_map);
2072-
update_view_mode();
2073-
return true;
2074-
}
2075-
return false;
2076-
}
2077-
2078-
//---------------------------------------------------------------------------
2079-
std::string ShapeWorksStudioApp::get_feature_map() {
2080-
std::string feature_map = session_->get_feature_map();
2081-
2082-
// confirm that this is a valid feature map
2083-
auto feature_maps = session_->get_project()->get_feature_names();
2084-
for (const std::string& feature : feature_maps) {
2085-
if (feature_map == feature) {
2086-
return feature_map;
2087-
}
2088-
}
2089-
return "";
2090-
}
2091-
20922069
//---------------------------------------------------------------------------
20932070
bool ShapeWorksStudioApp::get_feature_uniform_scale() {
20942071
return session_->parameters().get("feature_uniform_scale", true);

Studio/Interface/ShapeWorksStudioApp.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,6 @@ class ShapeWorksStudioApp : public QMainWindow {
195195

196196
void display_mode_shape();
197197

198-
bool set_feature_map(std::string feature_map);
199-
std::string get_feature_map();
200-
201198
bool get_feature_uniform_scale();
202199
void set_feature_uniform_scale(bool value);
203200

0 commit comments

Comments
 (0)