Files
Jungfraujoch/viewer/windows/JFJochAzIntWindow.cpp
T

171 lines
5.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "JFJochAzIntWindow.h"
#include <QGroupBox>
#include <QButtonGroup>
#include <QFormLayout>
JFJochAzIntWindow::JFJochAzIntWindow(
const AzimuthalIntegrationSettings &settings,
QWidget *parent)
: JFJochHelperWindow(parent),
m_settings(settings)
{
setWindowTitle("Azimuthal integration settings");
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
auto mainLayout = new QVBoxLayout(centralWidget);
// Group box similar to TS Paper + stacked inputs
auto group = new QGroupBox("Azimuthal integration", this);
auto formLayout = new QFormLayout(group);
// Q spacing
m_qSpacing = new SliderPlusBox(0.01, 1.0, 0.001, 3, this);
m_qSpacing->setValue(m_settings.GetQSpacing_recipA());
formLayout->addRow(tr("Q spacing [Å⁻¹]:"), m_qSpacing);
// Low Q
m_lowQ = new SliderPlusBox(0.001, 10.0, 0.001, 3, this);
m_lowQ->setValue(m_settings.GetLowQ_recipA());
formLayout->addRow(tr("Low Q [Å⁻¹]:"), m_lowQ);
// High Q
m_highQ = new SliderPlusBox(0.001, 10.0, 0.001, 3, this);
m_highQ->setValue(m_settings.GetHighQ_recipA());
formLayout->addRow(tr("High Q [Å⁻¹]:"), m_highQ);
// Solid angle / polarization correction checkboxes
m_solidAngleCheckBox = new QCheckBox(tr("Solid angle correction"), this);
m_solidAngleCheckBox->setChecked(m_settings.IsSolidAngleCorrection());
formLayout->addRow(QString(), m_solidAngleCheckBox);
m_polarizationCheckBox = new QCheckBox(tr("Polarization correction"), this);
m_polarizationCheckBox->setChecked(m_settings.IsPolarizationCorrection());
formLayout->addRow(QString(), m_polarizationCheckBox);
// Azimuthal bins (radio buttons like TS frontend)
auto azimGroupBox = new QGroupBox(tr("Azimuthal bins"), this);
auto azimLayout = new QHBoxLayout(azimGroupBox);
m_azimuthalBinsGroup = new QButtonGroup(this);
const QList<int> binOptions = {1, 2, 4, 8, 16, 32, 64, 128};
const int currentBins = m_settings.GetAzimuthalBinCount();
for (int bins : binOptions) {
auto *btn = new QRadioButton(QString::number(bins), azimGroupBox);
m_azimuthalBinsGroup->addButton(btn, bins);
m_azimuthalBinButtons.push_back(btn);
azimLayout->addWidget(btn);
if (bins == currentBins) {
btn->setChecked(true);
}
}
group->setLayout(formLayout);
mainLayout->addWidget(group);
mainLayout->addWidget(azimGroupBox);
// Error label at bottom (no buttons)
m_errorLabel = new QLabel(this);
m_errorLabel->setStyleSheet("color: rgb(200, 0, 0);"); // red-ish text for errors
m_errorLabel->setWordWrap(true);
mainLayout->addWidget(m_errorLabel);
// Connections on change, update errors, settings, and emit
connect(m_qSpacing, &SliderPlusBox::valueChanged, [this](double val) {
m_qSpacingError = (val < 0.01);
Update();
});
connect(m_lowQ, &SliderPlusBox::valueChanged, [this](double val) {
m_lowQError = (val < 0.001 || val > 10.0);
Update();
});
connect(m_highQ, &SliderPlusBox::valueChanged, [this](double val) {
m_highQError = (val < 0.001 || val > 10.0);
Update();
});
connect(m_solidAngleCheckBox, &QCheckBox::toggled, [this](bool /*checked*/) {
Update();
});
connect(m_polarizationCheckBox, &QCheckBox::toggled, [this](bool /*checked*/) {
Update();
});
connect(m_azimuthalBinsGroup,
QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked),
[this](QAbstractButton * /*btn*/) {
Update();
});
Update();
}
void JFJochAzIntWindow::UpdateErrorLabel() {
const double lowQ = m_lowQ->value();
const double highQ = m_highQ->value();
QStringList messages;
if (m_qSpacingError) {
messages << tr("Q spacing must be ≥ 0.01 Å⁻¹.");
}
if (m_lowQError) {
messages << tr("Low Q must be between 0.001 and 10 Å⁻¹.");
}
if (m_highQError) {
messages << tr("High Q must be between 0.001 and 10 Å⁻¹.");
}
if (highQ <= lowQ) {
messages << tr("High Q must be greater than Low Q.");
}
if (messages.isEmpty()) {
m_errorLabel->clear();
} else {
m_errorLabel->setText(messages.join(' '));
}
}
void JFJochAzIntWindow::ApplyToSettings() {
const float lowQ = static_cast<float>(m_lowQ->value());
const float highQ = static_cast<float>(m_highQ->value());
const float qSpacing = static_cast<float>(m_qSpacing->value());
m_settings.SolidAngleCorrection(m_solidAngleCheckBox->isChecked());
m_settings.PolarizationCorrection(m_polarizationCheckBox->isChecked());
m_settings.QRange_recipA(lowQ, highQ);
m_settings.QSpacing_recipA(qSpacing);
const int bins = m_azimuthalBinsGroup->checkedId();
if (bins > 0) {
m_settings.AzimuthalBinCount(bins);
}
}
void JFJochAzIntWindow::Update() {
// Update error label first
UpdateErrorLabel();
// If there are validation errors, do not update settings / emit
const double lowQ = m_lowQ->value();
const double highQ = m_highQ->value();
const bool rangeError = (highQ <= lowQ);
const bool anyError = m_lowQError || m_highQError || m_qSpacingError || rangeError;
if (anyError)
return;
// Update internal settings from widgets
ApplyToSettings();
// Emit updated settings when valid
emit settingsChanged(m_settings);
}