251 lines
9.9 KiB
C++
251 lines
9.9 KiB
C++
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include "JFJochViewerProcessingWindow.h"
|
|
|
|
#include <QHBoxLayout>
|
|
#include <QGroupBox>
|
|
#include <QFormLayout>
|
|
#include <QCloseEvent>
|
|
|
|
JFJochViewerProcessingWindow::JFJochViewerProcessingWindow(const SpotFindingSettings &settings, const IndexingSettings& indexing,QWidget *parent)
|
|
: QMainWindow(parent), m_settings(settings), m_indexing(indexing) {
|
|
|
|
setWindowTitle("Processing settings");
|
|
|
|
QWidget *centralWidget = new QWidget(this);
|
|
setCentralWidget(centralWidget);
|
|
|
|
auto mainLayout = new QVBoxLayout(centralWidget);
|
|
|
|
auto generalGroup = new QGroupBox("Spot finding", this);
|
|
auto generalLayout = new QFormLayout(generalGroup);
|
|
|
|
m_enableCheckBox = new QCheckBox("Enable", this);
|
|
m_enableCheckBox->setChecked(m_settings.enable);
|
|
generalLayout->addRow("", m_enableCheckBox);
|
|
|
|
m_signalToNoise = new SliderPlusBox(1.0, 10.0, 0.1, 1, this);
|
|
m_signalToNoise->setValue(m_settings.signal_to_noise_threshold);
|
|
generalLayout->addRow("Signal to Noise threshold:", m_signalToNoise);
|
|
|
|
m_photonCount = new SliderPlusBox(0.0, 100.0, 1.0, 0, this);
|
|
m_photonCount->setValue(std::lround(m_settings.photon_count_threshold));
|
|
generalLayout->addRow("Photon count threshold:", m_photonCount);
|
|
|
|
m_minPixPerSpot = new SliderPlusBox(1.0, 20.0, 1.0, 0, this);
|
|
m_minPixPerSpot->setValue(std::lround(m_settings.min_pix_per_spot));
|
|
generalLayout->addRow("Minimum pixels per spot:", m_minPixPerSpot);
|
|
|
|
m_maxPixPerSpot = new SliderPlusBox(10.0, 200.0, 1.0, 0, this);
|
|
m_maxPixPerSpot->setValue(std::lround(m_settings.max_pix_per_spot));
|
|
generalLayout->addRow("Maximum pixels per spot:", m_maxPixPerSpot);
|
|
|
|
// New: Max spot count slider [100 .. 2000]
|
|
m_maxSpotCount = new SliderPlusBox(100.0, 2000.0, 10.0, 0, this);
|
|
// If there is no existing value source, initialize to a sensible default
|
|
m_maxSpotCount->setValue(1000.0);
|
|
generalLayout->addRow("Maximum spots per image:", m_maxSpotCount);
|
|
|
|
m_highResolution = new SliderPlusBox(0.8, 10.0, 0.1, 1, this);
|
|
m_highResolution->setValue(m_settings.high_resolution_limit);
|
|
generalLayout->addRow("High resolution", m_highResolution);
|
|
|
|
m_lowResolution = new SliderPlusBox(10.0, 100.0, 0.1, 1, this);
|
|
m_lowResolution->setValue(m_settings.low_resolution_limit);
|
|
generalLayout->addRow("Low resolution", m_lowResolution);
|
|
|
|
// High-res spurious spot filter (gap in 1/d)
|
|
m_highResSpuriousFilterCheckBox = new QCheckBox("Enable high-res spurious spot filter", this);
|
|
const bool gapFilterEnabled = m_settings.high_res_gap_Q_recipA > 0.0f;
|
|
m_highResSpuriousFilterCheckBox->setChecked(m_settings.high_res_gap_Q_recipA.has_value());
|
|
generalLayout->addRow("", m_highResSpuriousFilterCheckBox);
|
|
|
|
m_highResSpuriousGapOneOverD = new SliderPlusBox(0.1, 5.0, 0.01, 2, this);
|
|
// If disabled by setting = 0, show a reasonable default on the slider but keep disabled
|
|
const double initialGap = m_settings.high_res_gap_Q_recipA.value_or(0.25);
|
|
m_highResSpuriousGapOneOverD->setValue(initialGap);
|
|
m_highResSpuriousGapOneOverD->setEnabled(gapFilterEnabled);
|
|
generalLayout->addRow("Gap threshold in Q-space [A^-1]:", m_highResSpuriousGapOneOverD);
|
|
|
|
auto processingGroup = new QGroupBox("Other steps", this);
|
|
auto processingLayout = new QFormLayout(processingGroup);
|
|
|
|
m_iceRingWidthQRecipA = new SliderPlusBox(0.0, 0.3, 0.001, 3, this);
|
|
m_iceRingWidthQRecipA->setValue(m_settings.ice_ring_width_Q_recipA);
|
|
generalLayout->addRow("Ice ring width in Q-space [A^-1]:", m_iceRingWidthQRecipA);
|
|
|
|
m_quickIntegrationCheckBox = new QCheckBox("Enable Bragg Integration", this);
|
|
m_quickIntegrationCheckBox->setChecked(m_settings.quick_integration);
|
|
processingLayout->addRow("", m_quickIntegrationCheckBox);
|
|
|
|
m_reanalyzeCheckBox = new QCheckBox("Reanalyze on changed settings", this);
|
|
m_reanalyzeCheckBox->setChecked(false);
|
|
processingLayout->addRow("", m_reanalyzeCheckBox);
|
|
|
|
// Indexing group
|
|
auto indexingGroup = new QGroupBox("Indexing", this);
|
|
auto indexingLayout = new QFormLayout(indexingGroup);
|
|
|
|
m_indexingCheckBox = new QCheckBox("Enable Indexing", this);
|
|
m_indexingCheckBox->setChecked(m_settings.indexing);
|
|
indexingLayout->addRow("", m_indexingCheckBox);
|
|
|
|
m_idxIndexIceRings = new QCheckBox("Index ice rings", this);
|
|
m_idxIndexIceRings->setChecked(m_indexing.GetIndexIceRings());
|
|
indexingLayout->addRow("", m_idxIndexIceRings);
|
|
|
|
m_geomRefinementCheckBox = new QCheckBox("Refine beam center", this);
|
|
m_geomRefinementCheckBox->setChecked(m_indexing.GetGeomRefinementAlgorithm() == GeomRefinementAlgorithmEnum::BeamCenter);
|
|
indexingLayout->addRow("", m_geomRefinementCheckBox);
|
|
|
|
// Indexing settings UI
|
|
m_idxTolerance = new SliderPlusBox(0.0, 0.5, 0.001, 3, this);
|
|
m_idxTolerance->setValue(m_indexing.GetTolerance());
|
|
indexingLayout->addRow("Indexing tolerance", m_idxTolerance);
|
|
|
|
m_idxUnitCellDistTolerance = new SliderPlusBox(0.001, 0.200, 0.001, 3, this);
|
|
m_idxUnitCellDistTolerance->setValue(m_indexing.GetUnitCellDistTolerance());
|
|
indexingLayout->addRow("Unit cell dist tol vs ref", m_idxUnitCellDistTolerance);
|
|
|
|
m_idxViableCellMinSpots = new SliderPlusBox(6.0, 200.0, 1.0, 0, this);
|
|
m_idxViableCellMinSpots->setValue(static_cast<double>(m_indexing.GetViableCellMinSpots()));
|
|
indexingLayout->addRow("Viable cell min spots", m_idxViableCellMinSpots);
|
|
|
|
auto buttonsLayout = new QHBoxLayout();
|
|
buttonsLayout->addStretch();
|
|
|
|
mainLayout->addWidget(generalGroup);
|
|
mainLayout->addWidget(indexingGroup);
|
|
mainLayout->addWidget(processingGroup);
|
|
mainLayout->addLayout(buttonsLayout);
|
|
|
|
connect(m_enableCheckBox, &QCheckBox::toggled, [this](bool checked) {
|
|
m_settings.enable = checked;
|
|
Update();
|
|
});
|
|
|
|
connect(m_signalToNoise, &SliderPlusBox::valueChanged, [this](double val) {
|
|
m_settings.signal_to_noise_threshold = val;
|
|
Update();
|
|
});
|
|
|
|
connect(m_photonCount, &SliderPlusBox::valueChanged, [this](double val) {
|
|
m_settings.photon_count_threshold = val;
|
|
Update();
|
|
});
|
|
|
|
connect(m_minPixPerSpot, &SliderPlusBox::valueChanged, [this](double val) {
|
|
m_settings.min_pix_per_spot = std::lround(val);
|
|
Update();
|
|
});
|
|
|
|
connect(m_maxPixPerSpot, &SliderPlusBox::valueChanged, [this](double val) {
|
|
m_settings.max_pix_per_spot = std::lround(val);
|
|
Update();
|
|
});
|
|
|
|
// New: update on max spot count change
|
|
connect(m_maxSpotCount, &SliderPlusBox::valueChanged, [this](double /*val*/) {
|
|
Update();
|
|
});
|
|
|
|
connect(m_highResolution, &SliderPlusBox::valueChanged, [this](double val) {
|
|
m_settings.high_resolution_limit = val;
|
|
Update();
|
|
});
|
|
|
|
connect(m_lowResolution, &SliderPlusBox::valueChanged, [this](double val) {
|
|
m_settings.low_resolution_limit = val;
|
|
Update();
|
|
});
|
|
|
|
// Toggle for high-res spurious spot filter
|
|
connect(m_highResSpuriousFilterCheckBox, &QCheckBox::toggled, [this](bool checked) {
|
|
m_highResSpuriousGapOneOverD->setEnabled(checked);
|
|
if (checked) {
|
|
// If currently disabled (zero), restore a sensible default
|
|
if (m_settings.high_res_gap_Q_recipA) {
|
|
m_settings.high_res_gap_Q_recipA = static_cast<float>(
|
|
m_highResSpuriousGapOneOverD->value());
|
|
}
|
|
} else
|
|
m_settings.high_res_gap_Q_recipA = std::nullopt;
|
|
|
|
Update();
|
|
});
|
|
|
|
// Gap slider handler
|
|
connect(m_highResSpuriousGapOneOverD, &SliderPlusBox::valueChanged, [this](double val) {
|
|
m_settings.high_res_gap_Q_recipA = static_cast<float>(val);
|
|
if (val > 0.0 && !m_highResSpuriousFilterCheckBox->isChecked()) {
|
|
m_highResSpuriousFilterCheckBox->setChecked(true);
|
|
}
|
|
Update();
|
|
});
|
|
|
|
// Indexing enable in its own group now
|
|
connect(m_indexingCheckBox, &QCheckBox::toggled, [this](bool checked) {
|
|
m_settings.indexing = checked;
|
|
Update();
|
|
});
|
|
|
|
connect(m_quickIntegrationCheckBox, &QCheckBox::toggled, [this](bool checked) {
|
|
m_settings.quick_integration = checked;
|
|
Update();
|
|
});
|
|
|
|
// Indexing settings signals
|
|
connect(m_idxTolerance, &SliderPlusBox::valueChanged, [this](double val) {
|
|
m_indexing.Tolerance(static_cast<float>(val));
|
|
Update();
|
|
});
|
|
|
|
connect(m_idxUnitCellDistTolerance, &SliderPlusBox::valueChanged, [this](double val) {
|
|
m_indexing.UnitCellDistTolerance(static_cast<float>(val));
|
|
Update();
|
|
});
|
|
|
|
connect(m_idxIndexIceRings, &QCheckBox::toggled, [this](bool checked) {
|
|
m_indexing.IndexIceRings(checked);
|
|
Update();
|
|
});
|
|
|
|
connect(m_geomRefinementCheckBox, &QCheckBox::toggled, [this](bool checked) {
|
|
if (checked)
|
|
m_indexing.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::BeamCenter);
|
|
else
|
|
m_indexing.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::None);
|
|
Update();
|
|
});
|
|
|
|
connect(m_idxViableCellMinSpots, &SliderPlusBox::valueChanged, [this](double val) {
|
|
m_indexing.ViableCellMinSpots(static_cast<int64_t>(std::lround(val)));
|
|
Update();
|
|
});
|
|
|
|
connect(m_iceRingWidthQRecipA, &SliderPlusBox::valueChanged, [this](double val) {
|
|
m_settings.ice_ring_width_Q_recipA = static_cast<float>(val);
|
|
Update();
|
|
});
|
|
|
|
connect(m_reanalyzeCheckBox, &QCheckBox::toggled, [this](bool checked) {
|
|
Update();
|
|
});
|
|
}
|
|
|
|
void JFJochViewerProcessingWindow::Update() {
|
|
const auto max_spots = std::lround(m_maxSpotCount->value());
|
|
emit settingsChanged(m_settings, m_indexing, max_spots, m_reanalyzeCheckBox->isChecked());
|
|
}
|
|
|
|
void JFJochViewerProcessingWindow::open() {
|
|
show();
|
|
raise();
|
|
activateWindow();
|
|
}
|
|
|
|
void JFJochViewerProcessingWindow::closeEvent(QCloseEvent *event) {
|
|
event->accept();
|
|
emit closing();
|
|
} |