253 lines
9.6 KiB
C++
253 lines
9.6 KiB
C++
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
||
// SPDX-License-Identifier: GPL-3.0-only
|
||
|
||
#include <QVBoxLayout>
|
||
#include <QGroupBox>
|
||
#include <QLabel>
|
||
#include <QPushButton>
|
||
#include <QDialogButtonBox>
|
||
#include <QCloseEvent>
|
||
#include <QMessageBox>
|
||
|
||
#include "JFJochViewerMetadataWindow.h"
|
||
|
||
JFJochViewerMetadataWindow::JFJochViewerMetadataWindow(QWidget *parent) : QMainWindow(parent) {
|
||
|
||
setWindowTitle("Dataset metadata");
|
||
|
||
QWidget *centralWidget = new QWidget(this);
|
||
setCentralWidget(centralWidget);
|
||
|
||
auto mainLayout = new QVBoxLayout(centralWidget);
|
||
|
||
auto detectorGroup = new QGroupBox(tr("Diffraction geometry"), this);
|
||
mainLayout->addWidget(detectorGroup);
|
||
|
||
auto detectorLayout = new QGridLayout(detectorGroup);
|
||
|
||
detectorLayout->addWidget(new QLabel(tr("Detector Distance:")), 0, 0);
|
||
det_distance_mm = new NumberLineEdit(1.0, 10000, 100.0, 2, "mm", this);
|
||
detectorLayout->addWidget(det_distance_mm, 0, 1, 1, 2);
|
||
|
||
detectorLayout->addWidget(new QLabel(tr("Wavelength:")), 2, 0);
|
||
wavelength_A = new NumberLineEdit(0.01, 10.0, 1.0, 4, "Å", this);
|
||
detectorLayout->addWidget(wavelength_A, 2, 1, 1, 2);
|
||
|
||
auto beam_center_label = new QLabel(tr("Beam center/PONI:"));
|
||
beam_center_label->setToolTip("For tilted geometry, this is point perpendicular to the beam (Point Of Nominal Interaction), not beam center.");
|
||
detectorLayout->addWidget(beam_center_label, 1, 0);
|
||
beam_center_x = new NumberLineEdit(-10000, 10000, 0.0, 2, "pxl", this);
|
||
beam_center_y = new NumberLineEdit(-10000, 10000, 0.0, 2, "pxl", this);
|
||
detectorLayout->addWidget(beam_center_x, 1, 1);
|
||
detectorLayout->addWidget(beam_center_y, 1, 2);
|
||
|
||
auto poni_rot1_label = new QLabel(tr("Rotation 1 (PONI):"));
|
||
poni_rot1_label->setToolTip("Rotates detector rightwards");
|
||
detectorLayout->addWidget(poni_rot1_label, 3, 0);
|
||
poni_rot1_deg = new NumberLineEdit(-180, 180, 0.0, 2, "deg", this);
|
||
detectorLayout->addWidget(poni_rot1_deg, 3, 1, 1, 2);
|
||
|
||
auto poni_rot2_label = new QLabel(tr("Rotation 2 (PONI):"));
|
||
poni_rot2_label->setToolTip("Rotates detector downwards");
|
||
detectorLayout->addWidget(poni_rot2_label, 4, 0);
|
||
poni_rot2_deg = new NumberLineEdit(-180, 180, 0.0, 2, "deg", this);
|
||
detectorLayout->addWidget(poni_rot2_deg, 4, 1, 1, 2);
|
||
|
||
auto poni_rot3_label = new QLabel(tr("Rotation 3 (PONI):"));
|
||
poni_rot3_label->setToolTip("Rotates detector clockwise");
|
||
detectorLayout->addWidget(poni_rot3_label, 5, 0);
|
||
poni_rot3_deg = new NumberLineEdit(-180, 180, 0.0, 2, "deg", this);
|
||
detectorLayout->addWidget(poni_rot3_deg, 5, 1, 1, 2);
|
||
|
||
auto unitCellGroup = new QGroupBox(tr("Unit cell"), this);
|
||
mainLayout->addWidget(unitCellGroup);
|
||
|
||
auto unitCellLayout = new QGridLayout(unitCellGroup);
|
||
|
||
unit_cell_enabled = new QCheckBox(tr("Enable unit cell"), this);
|
||
unit_cell_enabled->setChecked(true); // Default to enabled
|
||
unitCellLayout->addWidget(unit_cell_enabled, 0, 0, 1, 3);
|
||
|
||
connect(unit_cell_enabled, &QCheckBox::toggled, this, &JFJochViewerMetadataWindow::toggleUnitCellFields);
|
||
|
||
unit_cell_a = new NumberLineEdit(1.0, 10000.0, 39.0, 2, "Å", this);
|
||
unit_cell_b = new NumberLineEdit(1.0, 10000.0, 78.0, 2, "Å", this);
|
||
unit_cell_c = new NumberLineEdit(1.0, 10000.0, 78.0, 2, "Å", this);
|
||
|
||
unit_cell_alpha = new NumberLineEdit(15.0, 345.0, 90, 2, "°", this);
|
||
unit_cell_beta = new NumberLineEdit(15.0, 345.0, 90, 2, "°", this);
|
||
unit_cell_gamma = new NumberLineEdit(15.0, 345.0, 90, 2, "°", this);
|
||
|
||
unitCellLayout->addWidget(unit_cell_a, 1, 0);
|
||
unitCellLayout->addWidget(unit_cell_b, 1, 1);
|
||
unitCellLayout->addWidget(unit_cell_c, 1, 2);
|
||
|
||
unitCellLayout->addWidget(unit_cell_alpha, 2, 0);
|
||
unitCellLayout->addWidget(unit_cell_beta, 2, 1);
|
||
unitCellLayout->addWidget(unit_cell_gamma, 2, 2);
|
||
|
||
// Symmetry (optional)
|
||
auto symmGroup = new QGroupBox(tr("Symmetry"), this);
|
||
mainLayout->addWidget(symmGroup);
|
||
auto symmLayout = new QGridLayout(symmGroup);
|
||
|
||
space_group_enabled = new QCheckBox(tr("Set space group"), this);
|
||
symmLayout->addWidget(space_group_enabled, 0, 0, 1, 2);
|
||
|
||
symmLayout->addWidget(new QLabel(tr("Space group number:")), 1, 0);
|
||
space_group_number = new NumberLineEdit(1, 230, 1, 0, "", this);
|
||
symmLayout->addWidget(space_group_number, 1, 1);
|
||
|
||
symmLayout->addWidget(new QLabel(tr("Name:")), 2, 0);
|
||
space_group_name = new QLabel("-", this);
|
||
symmLayout->addWidget(space_group_name, 2, 1);
|
||
|
||
connect(space_group_enabled, &QCheckBox::toggled, this, [this](bool en){
|
||
space_group_number->setEnabled(en);
|
||
space_group_name->setEnabled(en);
|
||
updateSpaceGroupName();
|
||
});
|
||
connect(space_group_number, &NumberLineEdit::editingFinished, this, [this](){ updateSpaceGroupName(); });
|
||
|
||
auto otherGroup = new QGroupBox(tr("Others"), this);
|
||
mainLayout->addWidget(otherGroup);
|
||
auto otherLayout = new QGridLayout(otherGroup);
|
||
|
||
detect_ice_rings = new QCheckBox(tr("Detect Ice Rings"), this);
|
||
detect_ice_rings->setChecked(true);
|
||
otherLayout->addWidget(detect_ice_rings, 0, 0);
|
||
|
||
QFrame *line = new QFrame();
|
||
line->setFrameShape(QFrame::HLine);
|
||
line->setFrameShadow(QFrame::Sunken);
|
||
mainLayout->addWidget(line);
|
||
|
||
auto *updateButton = new QPushButton("Update");
|
||
connect(updateButton, &QPushButton::clicked, this, &JFJochViewerMetadataWindow::datasetUpdate);
|
||
mainLayout->addWidget(updateButton);
|
||
}
|
||
|
||
void JFJochViewerMetadataWindow::open() {
|
||
show();
|
||
raise();
|
||
activateWindow();
|
||
}
|
||
|
||
void JFJochViewerMetadataWindow::datasetUpdate() {
|
||
if (dataset) {
|
||
try {
|
||
DiffractionExperiment tmp = dataset->experiment;
|
||
tmp.DetectorDistance_mm(det_distance_mm->value());
|
||
tmp.BeamX_pxl(beam_center_x->value());
|
||
tmp.BeamY_pxl(beam_center_y->value());
|
||
tmp.IncidentEnergy_keV(WVL_1A_IN_KEV / wavelength_A->value());
|
||
tmp.PoniRot1_rad(poni_rot1_deg->value() * M_PI / 180.0);
|
||
tmp.PoniRot2_rad(poni_rot2_deg->value() * M_PI / 180.0);
|
||
tmp.DetectIceRings(detect_ice_rings->isChecked());
|
||
|
||
if (unit_cell_enabled->isChecked()) {
|
||
UnitCell uc;
|
||
uc.a = unit_cell_a->value();
|
||
uc.b = unit_cell_b->value();
|
||
uc.c = unit_cell_c->value();
|
||
uc.alpha = unit_cell_alpha->value();
|
||
uc.beta = unit_cell_beta->value();
|
||
uc.gamma = unit_cell_gamma->value();
|
||
tmp.SetUnitCell(uc);
|
||
} else {
|
||
tmp.SetUnitCell({});
|
||
}
|
||
|
||
if (space_group_enabled->isChecked()) {
|
||
int64_t n = static_cast<int64_t>(space_group_number->value());
|
||
tmp.SpaceGroupNumber(n);
|
||
} else {
|
||
tmp.SpaceGroupNumber(std::nullopt);
|
||
}
|
||
|
||
emit datasetUpdated(tmp);
|
||
} catch (const std::exception &e) {
|
||
QMessageBox::critical(this, "Error", e.what());
|
||
}
|
||
}
|
||
}
|
||
|
||
void JFJochViewerMetadataWindow::datasetLoaded(std::shared_ptr<const JFJochReaderDataset> in_dataset) {
|
||
dataset = std::move(in_dataset);
|
||
|
||
if (!dataset)
|
||
return;
|
||
|
||
det_distance_mm->setValue(dataset->experiment.GetDetectorDistance_mm());
|
||
beam_center_x->setValue(dataset->experiment.GetBeamX_pxl());
|
||
beam_center_y->setValue(dataset->experiment.GetBeamY_pxl());
|
||
wavelength_A->setValue(dataset->experiment.GetWavelength_A());
|
||
poni_rot1_deg->setValue(dataset->experiment.GetPoniRot1_rad() * 180.0 / M_PI);
|
||
poni_rot2_deg->setValue(dataset->experiment.GetPoniRot2_rad() * 180.0 / M_PI);
|
||
detect_ice_rings->setChecked(dataset->experiment.IsDetectIceRings());
|
||
|
||
auto unit_cell = dataset->experiment.GetUnitCell();
|
||
if (unit_cell) {
|
||
unit_cell_enabled->setChecked(true);
|
||
|
||
unit_cell_a->setValue(unit_cell->a);
|
||
unit_cell_b->setValue(unit_cell->b);
|
||
unit_cell_c->setValue(unit_cell->c);
|
||
|
||
unit_cell_alpha->setValue(unit_cell->alpha);
|
||
unit_cell_beta->setValue(unit_cell->beta);
|
||
unit_cell_gamma->setValue(unit_cell->gamma);
|
||
|
||
toggleUnitCellFields(true);
|
||
} else {
|
||
unit_cell_enabled->setChecked(false);
|
||
|
||
toggleUnitCellFields(false);
|
||
}
|
||
|
||
// Space group
|
||
auto sg = dataset->experiment.GetSpaceGroupNumber();
|
||
if (sg && *sg >= 1 && *sg <= 230) {
|
||
space_group_enabled->setChecked(true);
|
||
space_group_number->setValue(static_cast<double>(*sg));
|
||
} else {
|
||
space_group_enabled->setChecked(false);
|
||
}
|
||
space_group_number->setEnabled(space_group_enabled->isChecked());
|
||
space_group_name->setEnabled(space_group_enabled->isChecked());
|
||
updateSpaceGroupName();
|
||
}
|
||
|
||
void JFJochViewerMetadataWindow::updateSpaceGroupName() {
|
||
if (!space_group_enabled->isChecked()) {
|
||
space_group_name->setText("-");
|
||
return;
|
||
}
|
||
int n = static_cast<int>(space_group_number->value());
|
||
if (n >= 1 && n <= 230) {
|
||
try {
|
||
const auto& sg = gemmi::get_spacegroup_by_number(n);
|
||
// Hermann–Mauguin short symbol
|
||
space_group_name->setText(QString::fromStdString(sg.short_name()));
|
||
} catch (...) {
|
||
space_group_name->setText(tr("Invalid"));
|
||
}
|
||
} else {
|
||
space_group_name->setText(tr("Invalid"));
|
||
}
|
||
}
|
||
|
||
void JFJochViewerMetadataWindow::closeEvent(QCloseEvent *event) {
|
||
event->accept();
|
||
emit closing();
|
||
}
|
||
|
||
void JFJochViewerMetadataWindow::toggleUnitCellFields(bool enabled) {
|
||
unit_cell_a->setEnabled(enabled);
|
||
unit_cell_b->setEnabled(enabled);
|
||
unit_cell_c->setEnabled(enabled);
|
||
unit_cell_alpha->setEnabled(enabled);
|
||
unit_cell_beta->setEnabled(enabled);
|
||
unit_cell_gamma->setEnabled(enabled);
|
||
}
|