Skip to content

Commit 573331d

Browse files
committed
Adding feature to compute PCA on subgroups
1 parent bd163b3 commit 573331d

File tree

3 files changed

+200
-100
lines changed

3 files changed

+200
-100
lines changed

Studio/Analysis/AnalysisTool.cpp

Lines changed: 123 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,15 @@ AnalysisTool::AnalysisTool(Preferences& prefs) : preferences_(prefs) {
122122
&AnalysisTool::handle_group_animate_state_changed);
123123
connect(&group_animate_timer_, &QTimer::timeout, this, &AnalysisTool::handle_group_timer);
124124

125-
connect(ui_->group_box, qOverload<int>(&QComboBox::currentIndexChanged), this, &AnalysisTool::update_group_values);
125+
connect(ui_->group_combo, qOverload<int>(&QComboBox::currentIndexChanged), this, &AnalysisTool::update_group_values);
126126
connect(ui_->group_left, qOverload<int>(&QComboBox::currentIndexChanged), this, &AnalysisTool::group_changed);
127127
connect(ui_->group_right, qOverload<int>(&QComboBox::currentIndexChanged), this, &AnalysisTool::group_changed);
128128
connect(ui_->group_p_values_checkbox, &QPushButton::clicked, this, &AnalysisTool::group_p_values_clicked);
129129

130+
connect(ui_->pca_group_combo, qOverload<int>(&QComboBox::currentIndexChanged), this,
131+
&AnalysisTool::update_pca_group_options);
132+
connect(ui_->pca_group_list, &QListWidget::itemChanged, this, &AnalysisTool::handle_pca_group_list_item_changed);
133+
130134
// network analysis
131135
connect(ui_->network_analysis_button, &QPushButton::clicked, this, &AnalysisTool::network_analysis_clicked);
132136
connect(ui_->network_analysis_display, &QCheckBox::stateChanged, this, &AnalysisTool::update_view);
@@ -136,6 +140,8 @@ AnalysisTool::AnalysisTool(Preferences& prefs) : preferences_(prefs) {
136140
connect(ui_->reference_domain, qOverload<int>(&QComboBox::currentIndexChanged), this,
137141
&AnalysisTool::handle_alignment_changed);
138142

143+
connect(ui_->tabWidget, &QTabWidget::currentChanged, this, &AnalysisTool::handle_tab_changed);
144+
139145
ui_->surface_open_button->setChecked(false);
140146
ui_->metrics_open_button->setChecked(false);
141147

@@ -275,6 +281,27 @@ void AnalysisTool::on_reconstructionButton_clicked() {
275281
Q_EMIT progress(15);
276282
}
277283

284+
//---------------------------------------------------------------------------
285+
QStringList AnalysisTool::get_checked_pca_groups() {
286+
QStringList checked_items;
287+
288+
// Get the number of items in the list
289+
int count = ui_->pca_group_list->count();
290+
291+
// Iterate through all items
292+
for (int i = 0; i < count; ++i) {
293+
QListWidgetItem* item = ui_->pca_group_list->item(i);
294+
295+
// Check if the item is checked
296+
if (item && item->checkState() == Qt::Checked) {
297+
// Add the text of the checked item to our list
298+
checked_items.append(item->text());
299+
}
300+
}
301+
302+
return checked_items;
303+
}
304+
278305
//---------------------------------------------------------------------------
279306
int AnalysisTool::get_pca_mode() { return ui_->pcaModeSpinBox->value() - 1; }
280307

@@ -344,7 +371,7 @@ bool AnalysisTool::group_pvalues_valid() {
344371
}
345372

346373
//---------------------------------------------------------------------------
347-
bool AnalysisTool::groups_on() { return ui_->group_box->currentText() != "-None-"; }
374+
bool AnalysisTool::groups_on() { return ui_->group_combo->currentText() != "-None-"; }
348375

349376
//---------------------------------------------------------------------------
350377
void AnalysisTool::handle_analysis_options() {
@@ -493,7 +520,7 @@ void AnalysisTool::group_p_values_clicked() {
493520
//---------------------------------------------------------------------------
494521
void AnalysisTool::network_analysis_clicked() {
495522
network_analysis_job_ =
496-
QSharedPointer<NetworkAnalysisJob>::create(session_->get_project(), ui_->group_box->currentText().toStdString(),
523+
QSharedPointer<NetworkAnalysisJob>::create(session_->get_project(), ui_->group_combo->currentText().toStdString(),
497524
ui_->network_feature->currentText().toStdString());
498525
network_analysis_job_->set_pvalue_of_interest(ui_->network_pvalue_of_interest->text().toDouble());
499526
network_analysis_job_->set_pvalue_threshold(ui_->network_pvalue_threshold->text().toDouble());
@@ -524,11 +551,11 @@ bool AnalysisTool::compute_stats() {
524551
std::vector<Eigen::VectorXd> points;
525552
std::vector<int> group_ids;
526553

527-
std::string group_set = ui_->group_box->currentText().toStdString();
554+
std::string group_set = ui_->group_combo->currentText().toStdString();
528555
std::string left_group = ui_->group_left->currentText().toStdString();
529556
std::string right_group = ui_->group_right->currentText().toStdString();
530557

531-
bool groups_enabled = groups_active();
558+
auto pca_groups = get_checked_pca_groups();
532559

533560
group1_list_.clear();
534561
group2_list_.clear();
@@ -571,19 +598,35 @@ bool AnalysisTool::compute_stats() {
571598
if (particles.size() == 0) {
572599
continue; // skip any that don't have particles
573600
}
574-
if (groups_enabled) {
575-
auto value = shape->get_subject()->get_group_value(group_set);
576-
if (value == left_group) {
601+
if (groups_active()) {
602+
auto group = shape->get_subject()->get_group_value(group_set);
603+
if (group == left_group) {
577604
points.push_back(particles);
578605
group_ids.push_back(1);
579606
group1_list_.push_back(shape);
580-
} else if (value == right_group) {
607+
} else if (group == right_group) {
581608
points.push_back(particles);
582609
group_ids.push_back(2);
583610
group2_list_.push_back(shape);
584611
} else {
585612
// we don't include it
586613
}
614+
} else if (pca_groups_active()) {
615+
auto group = shape->get_subject()->get_group_value(ui_->pca_group_combo->currentText().toStdString());
616+
// see if it is in the list of groups
617+
bool found = false;
618+
for (auto&& pca_group : pca_groups) {
619+
if (group == pca_group.toStdString()) {
620+
found = true;
621+
break;
622+
}
623+
}
624+
if (found) {
625+
points.push_back(particles);
626+
group_ids.push_back(1);
627+
} else {
628+
// excluded
629+
}
587630
} else {
588631
points.push_back(particles);
589632
group_ids.push_back(1);
@@ -633,7 +676,7 @@ bool AnalysisTool::compute_stats() {
633676
/// Set this to true to export long format sample data (e.g. for import into R)
634677
const bool export_long_format = false;
635678

636-
if (export_long_format && groups_enabled) {
679+
if (export_long_format && groups_active()) {
637680
auto feature_names = session_->get_project()->get_feature_names();
638681
std::ofstream file;
639682
file.open("/tmp/stats.csv");
@@ -671,6 +714,7 @@ bool AnalysisTool::compute_stats() {
671714
//-----------------------------------------------------------------------------
672715
Particles AnalysisTool::get_mean_shape_points() {
673716
if (!compute_stats()) {
717+
std::cerr << "Non buenas, returning empty particles\n";
674718
return Particles();
675719
}
676720

@@ -858,7 +902,8 @@ void AnalysisTool::load_settings() {
858902
ui_->mesh_warp_sample_spinbox->setValue(params.get(MESH_WARP_TEMPLATE_INDEX, -1));
859903
update_group_boxes();
860904

861-
ui_->group_box->setCurrentText(QString::fromStdString(params.get("current_group", "-None-")));
905+
ui_->group_combo->setCurrentText(QString::fromStdString(params.get("current_group", "-None-")));
906+
ui_->pca_group_combo->setCurrentText(QString::fromStdString(params.get("current_pca_group", "-None-")));
862907
}
863908

864909
//---------------------------------------------------------------------------
@@ -1383,22 +1428,28 @@ void AnalysisTool::update_group_boxes() {
13831428
auto group_names = session_->get_project()->get_group_names();
13841429

13851430
ui_->group_widget->setEnabled(!group_names.empty());
1431+
ui_->pca_group_box->setVisible(!group_names.empty());
13861432

13871433
if (group_names != current_group_names_) { // only update if different
1388-
ui_->group_box->clear();
1389-
ui_->group_box->addItem("-None-");
1434+
ui_->group_combo->clear();
1435+
ui_->pca_group_combo->clear();
1436+
ui_->group_combo->addItem("-None-");
1437+
ui_->pca_group_combo->addItem("-None-");
13901438
for (const std::string& group : group_names) {
1391-
ui_->group_box->addItem(QString::fromStdString(group));
1439+
ui_->group_combo->addItem(QString::fromStdString(group));
1440+
ui_->pca_group_combo->addItem(QString::fromStdString(group));
13921441
}
1442+
13931443
current_group_names_ = group_names;
13941444
group_changed();
13951445
}
1446+
update_pca_group_options();
13961447
}
13971448

13981449
//---------------------------------------------------------------------------
13991450
void AnalysisTool::update_group_values() {
14001451
block_group_change_ = true;
1401-
auto values = session_->get_project()->get_group_values(ui_->group_box->currentText().toStdString());
1452+
auto values = session_->get_project()->get_group_values(ui_->group_combo->currentText().toStdString());
14021453

14031454
if (values != current_group_values_) {
14041455
// populate group values
@@ -1457,6 +1508,45 @@ void AnalysisTool::update_domain_alignment_box() {
14571508
}
14581509
}
14591510

1511+
//---------------------------------------------------------------------------
1512+
void AnalysisTool::update_pca_group_options() {
1513+
auto values = session_->get_project()->get_group_values(ui_->pca_group_combo->currentText().toStdString());
1514+
1515+
if (values != current_pca_group_values_) {
1516+
// populate group values
1517+
ui_->pca_group_list->clear();
1518+
for (const std::string& value : values) {
1519+
QString item = QString::fromStdString(value);
1520+
// add checkable item
1521+
ui_->pca_group_list->addItem(item);
1522+
auto item_widget = ui_->pca_group_list->item(ui_->pca_group_list->count() - 1);
1523+
item_widget->setFlags(item_widget->flags() | Qt::ItemIsUserCheckable);
1524+
item_widget->setCheckState(Qt::Checked);
1525+
}
1526+
}
1527+
1528+
int count = ui_->pca_group_list->count();
1529+
// clamp the items to 2-10
1530+
count = std::max(2, std::min(count, 10));
1531+
1532+
// resize the list widget to fit the items
1533+
ui_->pca_group_list->setMinimumHeight(ui_->pca_group_list->sizeHintForRow(0) * count + 2);
1534+
ui_->pca_group_list->setMaximumHeight(ui_->pca_group_list->sizeHintForRow(0) * count + 2);
1535+
1536+
current_pca_group_values_ = values;
1537+
1538+
stats_ready_ = false;
1539+
compute_stats();
1540+
}
1541+
1542+
//---------------------------------------------------------------------------
1543+
void AnalysisTool::handle_pca_group_list_item_changed() {
1544+
stats_ready_ = false;
1545+
compute_stats();
1546+
// update display
1547+
Q_EMIT update_view();
1548+
}
1549+
14601550
//---------------------------------------------------------------------------
14611551
void AnalysisTool::update_lda_graph() {
14621552
if (groups_active()) {
@@ -1545,7 +1635,18 @@ bool AnalysisTool::groups_active() {
15451635
return false;
15461636
}
15471637

1548-
std::string group_set = ui_->group_box->currentText().toStdString();
1638+
std::string group_set = ui_->group_combo->currentText().toStdString();
1639+
bool groups_enabled = group_set != "" && group_set != "-None-";
1640+
return groups_enabled;
1641+
}
1642+
1643+
//---------------------------------------------------------------------------
1644+
bool AnalysisTool::pca_groups_active() {
1645+
if (ui_->tabWidget->currentWidget() != ui_->pca_tab) {
1646+
return false;
1647+
}
1648+
1649+
std::string group_set = ui_->pca_group_combo->currentText().toStdString();
15491650
bool groups_enabled = group_set != "" && group_set != "-None-";
15501651
return groups_enabled;
15511652
}
@@ -1572,44 +1673,6 @@ void AnalysisTool::on_metrics_open_button_toggled() {
15721673
}
15731674
}
15741675

1575-
//---------------------------------------------------------------------------
1576-
bool AnalysisTool::is_group_active(int shape_index) {
1577-
std::string group_set = ui_->group_box->currentText().toStdString();
1578-
std::string left_group = ui_->group_left->currentText().toStdString();
1579-
std::string right_group = ui_->group_right->currentText().toStdString();
1580-
1581-
bool groups_enabled = groups_active();
1582-
1583-
auto shapes = session_->get_non_excluded_shapes();
1584-
auto shape = shapes[shape_index];
1585-
1586-
bool left = false;
1587-
bool right = false;
1588-
bool both = true;
1589-
if (ui_->group1_button->isChecked()) {
1590-
both = false;
1591-
left = true;
1592-
} else if (ui_->group2_button->isChecked()) {
1593-
both = false;
1594-
right = true;
1595-
}
1596-
1597-
if (groups_enabled) {
1598-
auto value = shape->get_subject()->get_group_value(group_set);
1599-
if (left && value == left_group) {
1600-
return true;
1601-
} else if (right && value == right_group) {
1602-
return true;
1603-
} else if (both) {
1604-
return true;
1605-
} else {
1606-
return false;
1607-
}
1608-
}
1609-
1610-
return true;
1611-
}
1612-
16131676
//---------------------------------------------------------------------------
16141677
void AnalysisTool::initialize_mesh_warper() {
16151678
if (session_->particles_present() && session_->get_groomed_present()) {
@@ -2007,6 +2070,12 @@ void AnalysisTool::mesh_warp_run_clicked() {
20072070
Q_EMIT reconstruction_complete();
20082071
}
20092072

2073+
//---------------------------------------------------------------------------
2074+
void AnalysisTool::handle_tab_changed() {
2075+
stats_ready_ = false;
2076+
compute_stats();
2077+
}
2078+
20102079
//---------------------------------------------------------------------------
20112080
void AnalysisTool::reconstruction_method_changed() {
20122081
ui_->reconstruction_options->setVisible(ui_->distance_transform_radio_button->isChecked());

Studio/Analysis/AnalysisTool.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,15 @@ class AnalysisTool : public QWidget {
156156
void group_changed();
157157

158158
bool groups_active();
159+
bool pca_groups_active();
160+
QStringList get_checked_pca_groups();
159161

160162
void on_view_open_button_toggled();
161163

162164
void on_surface_open_button_toggled();
163165

164166
void on_metrics_open_button_toggled();
165167

166-
bool is_group_active(int shape_index);
167-
168168
void reconstruction_method_changed();
169169

170170
void initialize_mesh_warper();
@@ -209,6 +209,8 @@ class AnalysisTool : public QWidget {
209209
void mesh_warp_sample_changed();
210210
void mesh_warp_run_clicked();
211211

212+
void handle_tab_changed();
213+
212214
Q_SIGNALS:
213215

214216
void update_view();
@@ -235,6 +237,8 @@ class AnalysisTool : public QWidget {
235237
void update_group_boxes();
236238
void update_group_values();
237239
void update_domain_alignment_box();
240+
void update_pca_group_options();
241+
void handle_pca_group_list_item_changed();
238242

239243
void update_lda_graph();
240244

@@ -282,6 +286,7 @@ class AnalysisTool : public QWidget {
282286

283287
std::vector<std::string> current_group_names_;
284288
std::vector<std::string> current_group_values_;
289+
std::vector<std::string> current_pca_group_values_;
285290

286291
std::vector<vtkSmartPointer<vtkTransform>> reconstruction_transforms_;
287292

0 commit comments

Comments
 (0)