From 6ead87fcce6bf3cebcfcb36b085e7c98da28d869 Mon Sep 17 00:00:00 2001 From: leonarski_f Date: Tue, 23 Jun 2026 16:07:35 +0200 Subject: [PATCH] viewer: per-image plot reuses the dataset-info combo (no second combo) In per-image mode the embedded chart brought its own combo box, so the plot panel showed two. Drop the per-image chart's combo and drive it from the one dataset-info combo: - JFJochViewerSidePanelChart loses its combo; it exposes PlotTypes() (the available profiles) and a setPlotType(code) slot, driven externally. - JFJochViewerDatasetInfo fills its single combo with the per-image plot types while in per-image mode (per-dataset metrics otherwise) and routes the selection to the chart; dataset/runs/live updates leave the per-image combo and plot untouched. Co-Authored-By: Claude Opus 4.8 --- viewer/JFJochViewerDatasetInfo.cpp | 29 ++++- viewer/widgets/JFJochViewerSidePanelChart.cpp | 113 ++++++++---------- viewer/widgets/JFJochViewerSidePanelChart.h | 23 ++-- 3 files changed, 90 insertions(+), 75 deletions(-) diff --git a/viewer/JFJochViewerDatasetInfo.cpp b/viewer/JFJochViewerDatasetInfo.cpp index 57f999c7..cd426c11 100644 --- a/viewer/JFJochViewerDatasetInfo.cpp +++ b/viewer/JFJochViewerDatasetInfo.cpp @@ -105,7 +105,9 @@ JFJochViewerDatasetInfo::JFJochViewerDatasetInfo(QWidget *parent) : QWidget(pare [this]() { if (image_button->isChecked()) grid_button->setChecked(false); - combo_box->setEnabled(!image_button->isChecked()); // the metric combo is for the dataset plot + UpdateLabels(); // swap the one combo's contents for the mode + combo_box->setCurrentIndex(0); + comboBoxSelected(0); // apply the first option of the new mode UpdateView(); }); connect(image_chart, &JFJochViewerSidePanelChart::writeStatusBar, @@ -121,6 +123,13 @@ void JFJochViewerDatasetInfo::UpdateLabels() { combo_box->clear(); + // In per-image mode the one combo selects which per-image profile to show (no second combo). + if (image_button && image_button->isChecked()) { + for (const auto &pt : JFJochViewerSidePanelChart::PlotTypes()) + combo_box->addItem(pt.first, pt.second); + return; + } + if (this->dataset) { combo_box->addItem("Background estimate", 0); combo_box->addItem("Resolution estimate", 7); @@ -173,6 +182,12 @@ void JFJochViewerDatasetInfo::UpdateLabels() { void JFJochViewerDatasetInfo::datasetLoaded(std::shared_ptr dataset) { this->dataset = dataset; + // Per-image mode: the combo holds plot types and the chart follows the displayed image, so a + // new dataset must not repopulate the combo or run the per-dataset plot. + if (image_button && image_button->isChecked()) { + UpdateView(); + return; + } if (dataset) { UpdateLabels(); if (last_selection < combo_box->count()) @@ -312,6 +327,8 @@ void JFJochViewerDatasetInfo::UpdateView() { void JFJochViewerDatasetInfo::runsChanged(QVector runs, QString active_id) { runs_ = std::move(runs); active_id_ = std::move(active_id); + if (image_button && image_button->isChecked()) + return; // per-image mode: runs/overlays are a per-dataset concern UpdateLabels(); if (last_selection < combo_box->count()) combo_box->setCurrentIndex(last_selection); @@ -320,11 +337,19 @@ void JFJochViewerDatasetInfo::runsChanged(QVector runs, QString active_ void JFJochViewerDatasetInfo::liveRunUpdated(std::shared_ptr in_dataset) { live_run_ = std::move(in_dataset); + if (image_button && image_button->isChecked()) + return; UpdatePlot(); // lightweight refresh; no combo rebuild on every live tick } void JFJochViewerDatasetInfo::comboBoxSelected(int index) { - UpdatePlot(); + // The one combo means per-dataset metrics in normal mode, per-image plot types in image mode. + if (image_button && image_button->isChecked()) { + if (image_chart && index >= 0 && index < combo_box->count()) + image_chart->setPlotType(combo_box->itemData(index).toInt()); + } else { + UpdatePlot(); + } } void JFJochViewerDatasetInfo::setColorMap(int color_map) { diff --git a/viewer/widgets/JFJochViewerSidePanelChart.cpp b/viewer/widgets/JFJochViewerSidePanelChart.cpp index ed3cea47..a4cb3c79 100644 --- a/viewer/widgets/JFJochViewerSidePanelChart.cpp +++ b/viewer/widgets/JFJochViewerSidePanelChart.cpp @@ -6,78 +6,71 @@ JFJochViewerSidePanelChart::JFJochViewerSidePanelChart(QWidget *parent) : QWidget(parent) { auto layout = new QVBoxLayout(this); - - combo_box = new QComboBox(this); - combo_box->addItem("Azimuthal integration (1D)", 0); - combo_box->addItem("Wilson plot", 1); - combo_box->addItem("I/sigma", 2); - combo_box->addItem("Spots (count)", 5); - combo_box->addItem("Spots (intensity)", 6); - combo_box->addItem("X-ray fluorescence spectrum", 4); - - layout->addWidget(combo_box); - - connect(combo_box, &QComboBox::currentIndexChanged, - this, &JFJochViewerSidePanelChart::comboBoxSelected); + layout->setContentsMargins(0, 0, 0, 0); azint_plot = new JFJochSimpleChartView(this); - - layout->addWidget(azint_plot); // index 0 + layout->addWidget(azint_plot); setLayout(layout); + connect(azint_plot, &JFJochSimpleChartView::writeStatusBar, - [&](QString string, int timeout_ms) { - emit writeStatusBar(string, timeout_ms); - }); + [&](QString string, int timeout_ms) { emit writeStatusBar(string, timeout_ms); }); } -void JFJochViewerSidePanelChart::comboBoxSelected(int val) { +QList> JFJochViewerSidePanelChart::PlotTypes() { + return { + {"Azimuthal integration (1D)", 0}, + {"Wilson plot", 1}, + {"I/sigma", 2}, + {"Spots (count)", 5}, + {"Spots (intensity)", 6}, + {"X-ray fluorescence spectrum", 4}, + }; +} + +void JFJochViewerSidePanelChart::setPlotType(int code) { + plot_type_ = code; redrawPlot(); } void JFJochViewerSidePanelChart::redrawPlot() { + if (!image) + return; + std::vector x, y; - - if (image) { - auto index = combo_box->currentIndex(); - switch (combo_box->itemData(index).toInt()) { - case 0: - x = image->GetAzInt1D_BinToQ(); - y = image->GetAzInt1D(); - azint_plot->UpdateData(x, y, "Q [Å^-1]", "", false); - break; - case 1: - x = image->ImageData().integration_B_one_over_d_square; - y = image->ImageData().integration_B_logI; - azint_plot->UpdateData(x, y, "d [Å]", "ln(<I>)", true); - - break; - case 2: - x = image->ImageData().integration_Isigma_one_over_d_square; - y = image->ImageData().integration_Isigma; - azint_plot->UpdateData(x, y, "d [Å]", "I/sigma", true); - - break; - case 4: - x = image->Dataset().experiment.GetFluorescenceSpectrum().GetEnergy_eV(); - y = image->Dataset().experiment.GetFluorescenceSpectrum().GetData(); - for (auto &iter: x) - iter /= 1000.0; // Convert eV to keV - azint_plot->UpdateData(x, y, "E [keV]", "", false); - break; - case 5: - x = image->ImageData().spot_plot_one_over_d_square; - y = image->ImageData().spot_plot_count; - azint_plot->UpdateData(x, y, "d [Å]", "Count", true); - - break; - case 6: - x = image->ImageData().spot_plot_one_over_d_square; - y = image->ImageData().spot_plot_intensity; - azint_plot->UpdateData(x, y, "d [Å]", "Count", true); - break; - } + switch (plot_type_) { + case 0: + x = image->GetAzInt1D_BinToQ(); + y = image->GetAzInt1D(); + azint_plot->UpdateData(x, y, "Q [Å^-1]", "", false); + break; + case 1: + x = image->ImageData().integration_B_one_over_d_square; + y = image->ImageData().integration_B_logI; + azint_plot->UpdateData(x, y, "d [Å]", "ln(<I>)", true); + break; + case 2: + x = image->ImageData().integration_Isigma_one_over_d_square; + y = image->ImageData().integration_Isigma; + azint_plot->UpdateData(x, y, "d [Å]", "I/sigma", true); + break; + case 4: + x = image->Dataset().experiment.GetFluorescenceSpectrum().GetEnergy_eV(); + y = image->Dataset().experiment.GetFluorescenceSpectrum().GetData(); + for (auto &iter: x) + iter /= 1000.0; // Convert eV to keV + azint_plot->UpdateData(x, y, "E [keV]", "", false); + break; + case 5: + x = image->ImageData().spot_plot_one_over_d_square; + y = image->ImageData().spot_plot_count; + azint_plot->UpdateData(x, y, "d [Å]", "Count", true); + break; + case 6: + x = image->ImageData().spot_plot_one_over_d_square; + y = image->ImageData().spot_plot_intensity; + azint_plot->UpdateData(x, y, "d [Å]", "Count", true); + break; } - } void JFJochViewerSidePanelChart::loadImage(std::shared_ptr in_image) { diff --git a/viewer/widgets/JFJochViewerSidePanelChart.h b/viewer/widgets/JFJochViewerSidePanelChart.h index 42e2ad4a..74141bd2 100644 --- a/viewer/widgets/JFJochViewerSidePanelChart.h +++ b/viewer/widgets/JFJochViewerSidePanelChart.h @@ -4,35 +4,32 @@ #pragma once #include -#include -#include +#include +#include +#include #include "../../reader/JFJochReaderImage.h" #include "../charts/JFJochSimpleChartView.h" -#include "../image_viewer/JFJochAzIntImage.h" +// Per-image profile plot (azimuthal 1D, Wilson, I/sigma, spots, fluorescence). It has no selector +// of its own — the host (dataset-info dock) drives the plot type via setPlotType, reusing its one +// combo box. class JFJochViewerSidePanelChart : public QWidget { Q_OBJECT - QStackedWidget *stack = nullptr; - JFJochSimpleChartView *azint_plot = nullptr; - std::shared_ptr image; - QComboBox *combo_box; + int plot_type_ = 0; void redrawPlot(); signals: void writeStatusBar(QString string, int timeout_ms = 0); -private slots: - void comboBoxSelected(int val); - public: JFJochViewerSidePanelChart(QWidget *parent); + // The available per-image plots as (label, code), so the host can fill its own combo. + static QList> PlotTypes(); public slots: void loadImage(std::shared_ptr image); + void setPlotType(int code); }; - - -