From 2b372ba7948343e28511c1cbb61b5b9240d25eb4 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Thu, 6 Nov 2025 10:44:00 +0100 Subject: [PATCH] jfjoch_viewer: Clean-up user interface (let's follow if it is not too crowded) --- viewer/JFJochImageReadingWorker.cpp | 2 +- viewer/JFJochViewerImageROIStatistics.cpp | 73 +++++--- viewer/JFJochViewerImageROIStatistics.h | 7 +- viewer/JFJochViewerSidePanel.cpp | 200 ++++++++++++---------- 4 files changed, 160 insertions(+), 122 deletions(-) diff --git a/viewer/JFJochImageReadingWorker.cpp b/viewer/JFJochImageReadingWorker.cpp index 77b99386..a6a4cabf 100644 --- a/viewer/JFJochImageReadingWorker.cpp +++ b/viewer/JFJochImageReadingWorker.cpp @@ -271,7 +271,7 @@ void JFJochImageReadingWorker::FindCenter(const UnitCell& calibrant, bool guess) std::vector ring_Q = CalculateXtalRings(calibrant); QVector rings; - for (int i = 0; i < 6 && i < ring_Q.size(); i++) { + for (int i = 0; i < 10 && i < ring_Q.size(); i++) { rings.push_back(2 * M_PI / ring_Q[i]); } emit setRings(rings); diff --git a/viewer/JFJochViewerImageROIStatistics.cpp b/viewer/JFJochViewerImageROIStatistics.cpp index 48d270d9..164cac62 100644 --- a/viewer/JFJochViewerImageROIStatistics.cpp +++ b/viewer/JFJochViewerImageROIStatistics.cpp @@ -3,23 +3,26 @@ #include "JFJochViewerImageROIStatistics.h" -#include "QVBoxLayout" +#include +#include JFJochViewerImageROIStatistics::JFJochViewerImageROIStatistics(QWidget *parent) : QWidget(parent) { QVBoxLayout *layout = new QVBoxLayout(this); box_radio = new QRadioButton("Box", this); - layout->addWidget(box_radio); - box_settings = new JFJochViewerImageROIStatistics_Box(this); - layout->addWidget(box_settings); + QHBoxLayout *box_row = new QHBoxLayout(); + box_row->addWidget(box_radio); + box_row->addWidget(box_settings); + layout->addLayout(box_row); circle_radio = new QRadioButton("Circle", this); - layout->addWidget(circle_radio); - circle_settings = new JFJochViewerImageROIStatistics_Circle(this); - layout->addWidget(circle_settings); + QHBoxLayout *circle_row = new QHBoxLayout(); + circle_row->addWidget(circle_radio); + circle_row->addWidget(circle_settings); + layout->addLayout(circle_row); radio_group = new QButtonGroup(this); radio_group->addButton(box_radio, 1); @@ -35,39 +38,61 @@ JFJochViewerImageROIStatistics::JFJochViewerImageROIStatistics(QWidget *parent) circle_settings->Disable(); box_radio->setChecked(true); - layout->addWidget(new QLabel("", this)); - roi_label = new QLabel("", this); - layout->addWidget(roi_label); + QHBoxLayout *label_row = new QHBoxLayout(); + + roi_sum = new QLabel("", this); + label_row->addWidget(roi_sum); + roi_mean = new QLabel("", this); + label_row->addWidget(roi_mean); + roi_var = new QLabel("", this); + label_row->addWidget(roi_var); + roi_max = new QLabel("", this); + label_row->addWidget(roi_max); + roi_npixel = new QLabel("", this); + label_row->addWidget(roi_npixel); + layout->addLayout(label_row); QPushButton *add_button = new QPushButton("Add ROI to user mask", this); connect(add_button, &QPushButton::clicked, [this]() { emit AddROIToUserMask(); }); - layout->addWidget(add_button); QPushButton *sub_button = new QPushButton("Subtract ROI from user mask", this); connect(sub_button, &QPushButton::clicked, [this]() { emit SubtractROIFromUserMask(); }); - layout->addWidget(sub_button); + + QHBoxLayout *buttons_row = new QHBoxLayout(); + buttons_row->setSpacing(12); + buttons_row->addWidget(add_button); + buttons_row->addWidget(sub_button); + + layout->addLayout(buttons_row); + } void JFJochViewerImageROIStatistics::loadImage(std::shared_ptr image) { if (!image) { - roi_label->setText(""); + roi_sum->setText(""); + roi_mean->setText(""); + roi_var->setText(""); + roi_max->setText(""); + roi_npixel->setText(""); } else { auto roi = image->GetROI(); if (roi && roi->pixels > 0) { - auto roi_npixel = static_cast(roi->pixels); - double roi_mean_val = static_cast(roi->sum) / roi_npixel; - double variance = static_cast(roi->sum_square) / roi_npixel - roi_mean_val * roi_mean_val; + auto roi_npixel_val = static_cast(roi->pixels); + double roi_mean_val = static_cast(roi->sum) / roi_npixel_val; + double variance = static_cast(roi->sum_square) / roi_npixel_val - roi_mean_val * roi_mean_val; - QString text = QString("Sum %1 Mean %2 Var %3 Max %4 Pixels %5") - .arg(roi->sum) - .arg(QString::number(roi_mean_val, 'f', 3)) - .arg(QString::number(variance, 'f', 3)) - .arg(roi->max_count) - .arg(roi->pixels); - roi_label->setText(text); + roi_sum->setText(QString("Sum %1").arg(roi->sum)); + roi_mean->setText(QString("Mean %1").arg(QString::number(roi_mean_val, 'f', 3))); + roi_var->setText(QString("Var %1").arg(QString::number(variance, 'f', 3))); + roi_max->setText(QString("Max %1").arg(roi->max_count)); + roi_npixel->setText(QString("Pixels %1").arg(roi->pixels)); } else { - roi_label->setText(""); + roi_sum->setText(""); + roi_mean->setText(""); + roi_var->setText(""); + roi_max->setText(""); + roi_npixel->setText(""); } } } diff --git a/viewer/JFJochViewerImageROIStatistics.h b/viewer/JFJochViewerImageROIStatistics.h index 179a4b56..e5ebed96 100644 --- a/viewer/JFJochViewerImageROIStatistics.h +++ b/viewer/JFJochViewerImageROIStatistics.h @@ -25,8 +25,11 @@ class JFJochViewerImageROIStatistics : public QWidget { JFJochViewerImageROIStatistics_Box *box_settings; JFJochViewerImageROIStatistics_Circle *circle_settings; - QLabel *roi_pos; - QLabel *roi_label; + QLabel *roi_sum; + QLabel *roi_mean; + QLabel *roi_var; + QLabel *roi_max; + QLabel *roi_npixel; public: JFJochViewerImageROIStatistics(QWidget *parent); private slots: diff --git a/viewer/JFJochViewerSidePanel.cpp b/viewer/JFJochViewerSidePanel.cpp index f21f7f56..e7891ff0 100644 --- a/viewer/JFJochViewerSidePanel.cpp +++ b/viewer/JFJochViewerSidePanel.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include @@ -14,6 +14,7 @@ #include "JFJochViewerImageROIStatistics.h" #include "widgets/TitleLabel.h" #include "JFJochViewerImageStatistics.h" +#include "../image_analysis/geom_refinement/AssignSpotsToRings.h" JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent) { @@ -25,6 +26,97 @@ JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent) layout->addWidget(stats); connect(this, &JFJochViewerSidePanel::imageLoaded, stats, &JFJochViewerImageStatistics::loadImage); + layout->addWidget(new TitleLabel("Image features", this)); + + // Image features... + auto spotToggleCheckBox = new QCheckBox("Show spots", this); + spotToggleCheckBox->setCheckState(Qt::CheckState::Checked); + + connect(spotToggleCheckBox, &QCheckBox::toggled, this, &JFJochViewerSidePanel::spotsToggled); + + auto highlightIceRingToggleCheckBox = new QCheckBox("Highlight spots on ice rings", this); + highlightIceRingToggleCheckBox->setCheckState(Qt::CheckState::Checked); + connect(highlightIceRingToggleCheckBox, &QCheckBox::toggled, this,&JFJochViewerSidePanel::highlightIceRingsToggled); + + auto predictionsToggleCheckBox = new QCheckBox("Show predictions", this); + predictionsToggleCheckBox->setCheckState(Qt::CheckState::Unchecked); + + connect(predictionsToggleCheckBox, &QCheckBox::toggled, this, + &JFJochViewerSidePanel::predictionsToggled); + + resRingsCheckBox = new QCheckBox("Show resolution rings", this); + resRingsCheckBox->setCheckState(Qt::Unchecked); + + autoResRingsCheckBox = new QCheckBox("Resolution rings auto.", this); + res_rings_edit = new QLineEdit(this); + res_rings_edit->setPlaceholderText("Ring positions, e.g., 1.0,2.5,3.7"); + res_rings_edit->setEnabled(false); // Initially disabled as "Auto Res Rings" is checked by default + + auto highestPixelsComboBox = new QComboBox(this); + highestPixelsComboBox->addItem("Show 0 highest pixels", 0); + highestPixelsComboBox->addItem("Show 1 highest pixel", 1); + highestPixelsComboBox->addItem("Show 2 highest pixels", 2); + highestPixelsComboBox->addItem("Show 3 highest pixels", 3); + highestPixelsComboBox->addItem("Show 5 highest pixels", 5); + highestPixelsComboBox->addItem("Show 10 highest pixels", 10); + highestPixelsComboBox->setCurrentIndex(0); + + connect(highestPixelsComboBox, &QComboBox::currentIndexChanged, this, [this, highestPixelsComboBox](int index) { + int value = highestPixelsComboBox->itemData(index).toInt(); + emit showHighestPixels(value); + }); + + auto saturatedPixelsCheckBox = new QCheckBox("Show saturated pixels", this); + + connect(saturatedPixelsCheckBox, &QCheckBox::toggled, this, &JFJochViewerSidePanel::saturatedPixelsToggled); + + auto colorSelectButton = new QPushButton("Select feature color", this); + + connect(colorSelectButton, &QPushButton::clicked, this, [this]() { + QColor color = QColorDialog::getColor(Qt::magenta, this, "Select Feature Color"); + if (color.isValid()) { + emit setFeatureColor(color); + } + }); + + auto spotColorSelectButton = new QPushButton("Select spot color", this); + + connect(spotColorSelectButton, &QPushButton::clicked, this, [this]() { + QColor color = QColorDialog::getColor(Qt::green, this, "Select Spot Color"); + if (color.isValid()) { + emit setSpotColor(color); + } + }); + + auto image_feature_grid = new QGridLayout(); + image_feature_grid->addWidget(spotToggleCheckBox, 0, 0); + image_feature_grid->addWidget(highlightIceRingToggleCheckBox, 0, 1); + image_feature_grid->addWidget(predictionsToggleCheckBox, 1, 0); + image_feature_grid->addWidget(resRingsCheckBox, 2, 0); + image_feature_grid->addWidget(autoResRingsCheckBox, 2, 1); + image_feature_grid->addWidget(res_rings_edit, 3, 0, 1, 2); + image_feature_grid->addWidget(saturatedPixelsCheckBox, 4, 0); + image_feature_grid->addWidget(highestPixelsComboBox, 4, 1); + image_feature_grid->addWidget(colorSelectButton, 5, 0); + image_feature_grid->addWidget(spotColorSelectButton, 5, 1); + + layout->addLayout(image_feature_grid); + + connect(autoResRingsCheckBox, &QCheckBox::toggled, this, &JFJochViewerSidePanel::enableAutoResRings); + + connect(res_rings_edit, &QLineEdit::editingFinished, + this, &JFJochViewerSidePanel::editingFinished); + + connect(resRingsCheckBox, &QCheckBox::toggled, + this, &JFJochViewerSidePanel::enableResRings); + + layout->addWidget(new TitleLabel("Image statistics plot", this)); + chart = new JFJochViewerSidePanelChart(this); + layout->addWidget(chart); + + connect(this, &JFJochViewerSidePanel::imageLoaded, + chart, &JFJochViewerSidePanelChart::loadImage); + layout->addWidget(new TitleLabel("ROI", this)); roi = new JFJochViewerImageROIStatistics(this); @@ -42,96 +134,7 @@ JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent) connect(roi, &JFJochViewerImageROIStatistics::AddROIToUserMask, [this]() { emit AddROIToUserMask(); }); connect(roi, &JFJochViewerImageROIStatistics::SubtractROIFromUserMask, [this]() { emit SubtractROIFromUserMask(); }); - layout->addWidget(new TitleLabel("Image features", this)); - - auto spotToggleCheckBox = new QCheckBox("Show spots", this); - spotToggleCheckBox->setCheckState(Qt::CheckState::Checked); - - layout->addWidget(spotToggleCheckBox); // Add checkbox to the grid layout - - connect(spotToggleCheckBox, &QCheckBox::toggled, this, &JFJochViewerSidePanel::spotsToggled); - - auto highlightIceRingToggleCheckBox = new QCheckBox("Highlight spots on ice rings", this); - highlightIceRingToggleCheckBox->setCheckState(Qt::CheckState::Checked); - layout->addWidget(highlightIceRingToggleCheckBox); - connect(highlightIceRingToggleCheckBox, &QCheckBox::toggled, this,&JFJochViewerSidePanel::highlightIceRingsToggled); - - auto predictionsToggleCheckBox = new QCheckBox("Show predictions", this); - predictionsToggleCheckBox->setCheckState(Qt::CheckState::Unchecked); - - layout->addWidget(predictionsToggleCheckBox); // Add checkbox to the grid layout - - connect(predictionsToggleCheckBox, &QCheckBox::toggled, this, - &JFJochViewerSidePanel::predictionsToggled); - - resRingsCheckBox = new QCheckBox("Show resolution rings", this); - resRingsCheckBox->setCheckState(Qt::Unchecked); - layout->addWidget(resRingsCheckBox); - - autoResRingsCheckBox = new QCheckBox("Resolution rings auto.", this); - res_rings_edit = new QLineEdit(this); - res_rings_edit->setPlaceholderText("Enter non-negative floats, e.g., 1.0,2.5,3.7"); - res_rings_edit->setEnabled(false); // Initially disabled as "Auto Res Rings" is checked by default - - layout->addWidget(autoResRingsCheckBox); // Add the checkbox to the grid layout - layout->addWidget(res_rings_edit); // Add the line edit to the grid layout - - auto highestPixelsComboBox = new QComboBox(this); - highestPixelsComboBox->addItem("0 highest pixels", 0); - highestPixelsComboBox->addItem("1 highest pixel", 1); - highestPixelsComboBox->addItem("2 highest pixels", 2); - highestPixelsComboBox->addItem("3 highest pixels", 3); - highestPixelsComboBox->addItem("5 highest pixels", 5); - highestPixelsComboBox->addItem("10 highest pixels", 10); - highestPixelsComboBox->setCurrentIndex(0); - layout->addWidget(highestPixelsComboBox); - - connect(highestPixelsComboBox, &QComboBox::currentIndexChanged, this, [this, highestPixelsComboBox](int index) { - int value = highestPixelsComboBox->itemData(index).toInt(); - emit showHighestPixels(value); - }); - - auto saturatedPixelsCheckBox = new QCheckBox("Show saturated pixels", this); - layout->addWidget(saturatedPixelsCheckBox); - - connect(saturatedPixelsCheckBox, &QCheckBox::toggled, this, &JFJochViewerSidePanel::saturatedPixelsToggled); - - auto colorSelectButton = new QPushButton("Select feature color", this); - layout->addWidget(colorSelectButton); - - connect(colorSelectButton, &QPushButton::clicked, this, [this]() { - QColor color = QColorDialog::getColor(Qt::magenta, this, "Select Feature Color"); - if (color.isValid()) { - emit setFeatureColor(color); - } - }); - - auto spotColorSelectButton = new QPushButton("Select spot color", this); - layout->addWidget(spotColorSelectButton); - - connect(spotColorSelectButton, &QPushButton::clicked, this, [this]() { - QColor color = QColorDialog::getColor(Qt::green, this, "Select Spot Color"); - if (color.isValid()) { - emit setSpotColor(color); - } - }); - - connect(autoResRingsCheckBox, &QCheckBox::toggled, this, &JFJochViewerSidePanel::enableAutoResRings); - - connect(res_rings_edit, &QLineEdit::editingFinished, - this, &JFJochViewerSidePanel::editingFinished); - - connect(resRingsCheckBox, &QCheckBox::toggled, - this, &JFJochViewerSidePanel::enableResRings); - - layout->addWidget(new TitleLabel("Image statistics plot", this)); - chart = new JFJochViewerSidePanelChart(this); - layout->addWidget(chart); - - connect(this, &JFJochViewerSidePanel::imageLoaded, - chart, &JFJochViewerSidePanelChart::loadImage); - - layout->addWidget(new TitleLabel("Data analysis (experimental)", this)); + layout->addWidget(new TitleLabel("Data analysis", this)); auto analyzeButton = new QPushButton("Full analysis", this); connect(analyzeButton, &QPushButton::clicked,[this] {emit analyze();}); @@ -141,16 +144,13 @@ JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent) layout->addWidget(new TitleLabel("Powder geometry calibration", this)); calibrantCombo = new QComboBox(this); - layout->addWidget(calibrantCombo); updateCalibrantList(); auto findBeamCenterButton = new QPushButton("Guess detector calibration", this); connect(findBeamCenterButton, &QPushButton::clicked,this, &JFJochViewerSidePanel::findBeamCenterClicked); - layout->addWidget(findBeamCenterButton); auto optimizeBeamCenterButton = new QPushButton("Refine detector calibration", this); connect(optimizeBeamCenterButton, &QPushButton::clicked,this, &JFJochViewerSidePanel::optimizeBeamCenterClicked); - layout->addWidget(optimizeBeamCenterButton); // Add preset ice rings button below LaB6 calibration auto iceRingsButton = new QPushButton("Display ice rings", this); @@ -159,7 +159,17 @@ JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent) const QVector ice_rings(ICE_RING_RES_A.begin(), ICE_RING_RES_A.end()); setRings(ice_rings); }); - layout->addWidget(iceRingsButton); + + auto refine_row = new QGridLayout(); + refine_row->setSpacing(12); + refine_row->addWidget(new QLabel("Calibrant:"),0,0); + refine_row->addWidget(calibrantCombo,0,1); + refine_row->addWidget(findBeamCenterButton,1, 0); + refine_row->addWidget(optimizeBeamCenterButton,1, 1); + + refine_row->addWidget(iceRingsButton,2, 0,1,2); + + layout->addLayout(refine_row); layout->addStretch(); setLayout(layout); // Set the layout to the widget