Files
Jungfraujoch/viewer/JFJochViewerSidePanel.cpp
2025-09-24 22:52:31 +02:00

216 lines
7.8 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include <QCheckBox>
#include <QLabel>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QColorDialog>
#include <QComboBox>
#include "JFJochViewerSidePanel.h"
#include "widgets/TitleLabel.h"
#include "JFJochViewerImageStatistics.h"
JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent) {
auto layout = new QVBoxLayout(this);
layout->addWidget(new TitleLabel("Image statistics", this));
auto stats = new JFJochViewerImageStatistics(this);
layout->addWidget(stats);
connect(this, &JFJochViewerSidePanel::imageLoaded,
stats, &JFJochViewerImageStatistics::loadImage);
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));
auto analyzeButton = new QPushButton("Full analysis", this);
connect(analyzeButton, &QPushButton::clicked,[this] {emit analyze();});
layout->addWidget(analyzeButton);
auto findBeamCenterButton = new QPushButton("Calibrate detector (LaB6)", this);
connect(findBeamCenterButton, &QPushButton::clicked,[this] {emit findBeamCenter();});
layout->addWidget(findBeamCenterButton);
// Add preset ice rings button below LaB6 calibration
auto iceRingsButton = new QPushButton("Display ice rings", this);
connect(iceRingsButton, &QPushButton::clicked, this, [this]() {
// Set manual rings and enable display
const QVector<float> ice_rings(ICE_RING_RES_A.begin(), ICE_RING_RES_A.end());
setRings(ice_rings);
});
layout->addWidget(iceRingsButton);
layout->addStretch();
setLayout(layout); // Set the layout to the widget
}
void JFJochViewerSidePanel::setRings(const QVector <float> &v) {
QString txt;
for (float i : v) {
txt += QString::number(i, 'f', 3) + ",";
}
resRingsCheckBox->setChecked(true);
autoResRingsCheckBox->setChecked(false);
res_rings_edit->setEnabled(true);
res_rings_edit->setText(txt);
emit setResRings(v);
}
void JFJochViewerSidePanel::enableAutoResRings(bool input) {
res_rings_edit->setEnabled(!input); // Enable line edit only if "Auto Res Rings" is unchecked
if (input) {
emit autoResRings();
} else {
editingFinished();
}
}
void JFJochViewerSidePanel::spotsToggled(bool input) {
emit showSpots(input);
}
void JFJochViewerSidePanel::predictionsToggled(bool input) {
emit showPredictions(input);
}
void JFJochViewerSidePanel::editingFinished() {
QString text = res_rings_edit->text();
QStringList stringList = text.split(',', Qt::SkipEmptyParts);
QVector<float> manualResRings;
bool validInput = true;
for (const QString &str: stringList) {
bool ok;
float value = str.toFloat(&ok);
if (ok && value >= 0) {
manualResRings.append(value);
} else {
validInput = false;
break;
}
}
if (!validInput) {
res_rings_edit->setStyleSheet("border: 1px solid red;"); // Highlight error
} else {
res_rings_edit->setStyleSheet(""); // Reset to default style
emit setResRings(manualResRings); // Update resolution ring vector
}
}
void JFJochViewerSidePanel::loadImage(std::shared_ptr<const JFJochReaderImage> image) {
emit imageLoaded(image);
}
void JFJochViewerSidePanel::enableResRings(bool input) {
if (!input) {
autoResRingsCheckBox->setEnabled(false);
res_rings_edit->setEnabled(false);
emit setResRings({});
} else {
autoResRingsCheckBox->setEnabled(true);
enableAutoResRings(autoResRingsCheckBox->isChecked());
}
}
void JFJochViewerSidePanel::saturatedPixelsToggled(bool input) {
emit showSaturatedPixels(input);
}
void JFJochViewerSidePanel::highlightIceRingsToggled(bool input) {
emit highlightIceRings(input);
}