// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include #include #include #include #include #include #include #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(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 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(*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(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); }