Files
Jungfraujoch/viewer/JFJochViewerWindow.cpp
Filip Leonarski 9bc71cfddc
Some checks failed
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 9m27s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 8m51s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 7m45s
Build Packages / Generate python client (push) Successful in 28s
Build Packages / Build documentation (push) Successful in 57s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (rocky8) (push) Successful in 8m53s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 9m26s
Build Packages / build:rpm (rocky9) (push) Successful in 9m21s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 7m42s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 8m11s
Build Packages / build:rpm (rocky9_nocuda) (push) Failing after 7m7s
Build Packages / Unit tests (push) Has been skipped
v1.0.0-rc.111 (#17)
This is an UNSTABLE release.

* jfjoch_viewer: Remove 3D lattice viewer (not really useful at this moment)
* jfjoch_viewer: Fix auto contrast not refreshing image

Reviewed-on: #17
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
2025-11-28 16:22:18 +01:00

363 lines
16 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "JFJochViewerWindow.h"
#include <QSplitter>
#include <QThread>
#include <QDockWidget>
#include "JFJochImageReadingWorker.h"
#include "image_viewer/JFJochDiffractionImage.h"
#include "JFJochViewerSidePanel.h"
#include "JFJochViewerStatusBar.h"
#include "../common/CUDAWrapper.h"
#include "windows/JFJochViewerImageListWindow.h"
#include "windows/JFJochViewerMetadataWindow.h"
#include "dbus/JFJochViewerAdaptor.h"
#include "windows/JFJochViewerProcessingWindow.h"
#include "windows/JFJochViewerSpotListWindow.h"
#include "windows/JFJochViewerReflectionListWindow.h"
#include "windows/JFJochCalibrationWindow.h"
#include "toolbar/JFJochViewerToolbarDisplay.h"
#include "toolbar/JFJochViewerToolbarImage.h"
#include "windows/JFJoch2DAzintImageWindow.h"
#include "windows/JFJochAzIntWindow.h"
JFJochViewerWindow::JFJochViewerWindow(QWidget *parent, bool dbus, const QString &file) : QMainWindow(parent) {
menuBar = new JFJochViewerMenu(this);
setMenuBar(menuBar);
auto toolBarImage = new JFJochViewerToolbarImage(this);
addToolBar(Qt::TopToolBarArea, toolBarImage);
addToolBarBreak(Qt::TopToolBarArea);
toolBarDisplay = new JFJochViewerToolbarDisplay(this);
addToolBar(Qt::TopToolBarArea, toolBarDisplay);
statusbar = new JFJochViewerStatusBar(this);
setStatusBar(statusbar);
setDockOptions(dockOptions() & ~QMainWindow::DockOption::AllowTabbedDocks);
setStyleSheet(stylesheet);
setWindowTitle("Jungfraujoch image viewer");
resize(1200, 1200);
SpotFindingSettings spot_finding_settings = DiffractionExperiment::DefaultDataProcessingSettings();
spot_finding_settings.high_resolution_limit = 1.5;
spot_finding_settings.indexing = true;
IndexingSettings indexing_settings;
indexing_settings.IndexingThreads(1);
indexing_settings.Algorithm(IndexingAlgorithmEnum::Auto);
if (get_gpu_count() == 0) {
indexing_settings.Algorithm(IndexingAlgorithmEnum::FFTW);
indexing_settings.FFT_NumVectors(8 * 1024);
}
indexing_settings.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::BeamCenter);
DiffractionExperiment experiment;
experiment.ImportIndexingSettings(indexing_settings);
experiment.DetectIceRings(true);
// Central area: only the main horizontal splitter (image + side panel)
auto h_splitter = new QSplitter(this);
h_splitter->setOrientation(Qt::Horizontal);
setCentralWidget(h_splitter);
auto viewer = new JFJochDiffractionImage(this);
viewer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
h_splitter->addWidget(viewer);
auto side_panel = new JFJochViewerSidePanel(this);
auto side_panel_scroll = new QScrollArea(this);
side_panel_scroll->setWidget(side_panel);
side_panel_scroll->setWidgetResizable(true);
side_panel_scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
side_panel_scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
side_panel_scroll->setMinimumWidth(450);
side_panel_scroll->setMaximumWidth(600);
side_panel_scroll->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
h_splitter->addWidget(side_panel_scroll);
reading_worker = new JFJochImageReadingWorker(spot_finding_settings, experiment);
reading_thread = new QThread(this);
reading_worker->moveToThread(reading_thread);
reading_thread->start();
auto tableWindow = new JFJochViewerImageListWindow(this);
auto metadataWindow = new JFJochViewerMetadataWindow(this);
auto spotWindow = new JFJochViewerSpotListWindow(this);
auto reflectionWindow = new JFJochViewerReflectionListWindow(this);
auto processingWindow = new JFJochViewerProcessingWindow(spot_finding_settings, indexing_settings, this);
auto calibrationWindow = new JFJochCalibrationWindow(this);
auto azintWindow = new JFJochAzIntWindow(experiment.GetAzimuthalIntegrationSettings(), this);
auto azintImageWindow = new JFJoch2DAzintImageWindow(this);
menuBar->AddWindowEntry(tableWindow, "Image list");
menuBar->AddWindowEntry(spotWindow, "Spot list");
menuBar->AddWindowEntry(reflectionWindow, "Reflection list");
menuBar->AddWindowEntry(metadataWindow, "Image metadata");
menuBar->AddWindowEntry(processingWindow, "Image processing settings");
menuBar->AddWindowEntry(calibrationWindow, "Calibration image viewer");
menuBar->AddWindowEntry(azintWindow, "Azimuthal integration settings");
menuBar->AddWindowEntry(azintImageWindow, "Azimuthal integration 2D image");
if (dbus) {
// Create adaptor attached to this window
new JFJochViewerAdaptor(this);
QDBusConnection connection = QDBusConnection::sessionBus();
if (!connection.registerService("ch.psi.jfjoch_viewer")) {
qWarning("Failed to register D-Bus service: %s", qPrintable(connection.lastError().message()));
} else {
if (!connection.registerObject("/", this, QDBusConnection::ExportAdaptors)) {
qFatal("Failed to register D-Bus object: %s", qPrintable(connection.lastError().message()));
}
}
}
connect(this, &JFJochViewerWindow::LoadFileRequest,
reading_worker, &JFJochImageReadingWorker::LoadFile);
connect(this, &JFJochViewerWindow::LoadImageRequest,
reading_worker, &JFJochImageReadingWorker::LoadImage);
connect(menuBar, &JFJochViewerMenu::fileOpenSelected,
reading_worker, &JFJochImageReadingWorker::LoadFile);
connect(menuBar, &JFJochViewerMenu::fileCloseSelected,
reading_worker, &JFJochImageReadingWorker::CloseFile);
connect(reading_worker, &JFJochImageReadingWorker::imageLoaded,
viewer, &JFJochDiffractionImage::loadImage);
connect(reading_worker, &JFJochImageReadingWorker::imageLoaded,
side_panel, &JFJochViewerSidePanel::loadImage);
connect(reading_worker, &JFJochImageReadingWorker::imageStatsUpdated,
side_panel, &JFJochViewerSidePanel::loadImage);
connect(reading_worker, &JFJochImageReadingWorker::imageNumberChanged, toolBarImage,
&JFJochViewerToolbarImage::setImageNumber);
connect(toolBarImage, &JFJochViewerToolbarImage::loadImage, reading_worker, &JFJochImageReadingWorker::LoadImage);
connect(toolBarDisplay, &JFJochViewerToolbarDisplay::setForeground, viewer,
&JFJochDiffractionImage::changeForeground);
connect(viewer, &JFJochDiffractionImage::autoForegroundChanged,
toolBarDisplay, &JFJochViewerToolbarDisplay::updateAutoForeground);
connect(toolBarDisplay, &JFJochViewerToolbarDisplay::setAutoForeground, viewer,
&JFJochDiffractionImage::setAutoForeground);
connect(toolBarDisplay, &JFJochViewerToolbarDisplay::colorMapChanged, viewer,
&JFJochDiffractionImage::setColorMap);
connect(toolBarDisplay, &JFJochViewerToolbarDisplay::colorMapChanged, azintImageWindow,
&JFJoch2DAzintImageWindow::setColorMap);
connect(reading_worker, &JFJochImageReadingWorker::imageLoaded,
azintImageWindow, &JFJoch2DAzintImageWindow::imageLoaded);
connect(viewer, &JFJochDiffractionImage::foregroundChanged,
toolBarDisplay, &JFJochViewerToolbarDisplay::updateForeground);
connect(viewer, &JFJochDiffractionImage::roiBoxUpdated,
reading_worker, &JFJochImageReadingWorker::SetROIBox);
connect(viewer, &JFJochDiffractionImage::roiCircleUpdated,
reading_worker, &JFJochImageReadingWorker::SetROICircle);
connect(viewer, &JFJochDiffractionImage::roiBoxUpdated,
side_panel, &JFJochViewerSidePanel::SetROIBox);
connect(viewer, &JFJochDiffractionImage::roiCircleUpdated,
side_panel, &JFJochViewerSidePanel::SetROICircle);
connect(viewer, &JFJochDiffractionImage::roiCalculated,
side_panel, &JFJochViewerSidePanel::SetROIResult);
connect(side_panel, &JFJochViewerSidePanel::ROIBoxConfigured,
reading_worker, &JFJochImageReadingWorker::SetROIBox);
connect(side_panel, &JFJochViewerSidePanel::ROICircleConfigured,
reading_worker, &JFJochImageReadingWorker::SetROICircle);
connect(side_panel, &JFJochViewerSidePanel::ROIBoxConfigured,
viewer, &JFJochDiffractionImage::SetROIBox);
connect(side_panel, &JFJochViewerSidePanel::ROICircleConfigured,
viewer, &JFJochDiffractionImage::SetROICircle);
connect(side_panel, &JFJochViewerSidePanel::AddROIToUserMask,
reading_worker, &JFJochImageReadingWorker::AddROIToUserMask);
connect(side_panel, &JFJochViewerSidePanel::SubtractROIFromUserMask,
reading_worker, &JFJochImageReadingWorker::SubtractROIFromUserMask);
connect(menuBar, &JFJochViewerMenu::clearUserMaskSelected,
reading_worker, &JFJochImageReadingWorker::ClearUserMask);
connect(menuBar, &JFJochViewerMenu::saveUserMaskTiffSelected,
reading_worker, &JFJochImageReadingWorker::SaveUserMaskTIFF);
connect(menuBar, &JFJochViewerMenu::uploadUserMaskSelected,
reading_worker, &JFJochImageReadingWorker::UploadUserMask);
connect(reading_worker, &JFJochImageReadingWorker::datasetLoaded,
tableWindow, &JFJochViewerImageListWindow::datasetLoaded);
connect(reading_worker, &JFJochImageReadingWorker::datasetLoaded,
spotWindow, &JFJochViewerSpotListWindow::datasetLoaded);
connect(reading_worker, &JFJochImageReadingWorker::datasetLoaded,
metadataWindow, &JFJochViewerMetadataWindow::datasetLoaded);
connect(reading_worker, &JFJochImageReadingWorker::imageLoaded,
tableWindow, &JFJochViewerImageListWindow::imageLoaded);
connect(reading_worker, &JFJochImageReadingWorker::imageLoaded,
spotWindow, &JFJochViewerSpotListWindow::imageLoaded);
connect(tableWindow, &JFJochViewerImageListWindow::imageSelected,
reading_worker, &JFJochImageReadingWorker::LoadImage);
connect(reading_worker, &JFJochImageReadingWorker::autoloadChanged,
toolBarImage, &JFJochViewerToolbarImage::setAutoloadMode);
connect(toolBarImage, &JFJochViewerToolbarImage::autoLoadButtonPressed,
reading_worker, &JFJochImageReadingWorker::setAutoLoadMode);
connect(toolBarImage, &JFJochViewerToolbarImage::imageJumpChanged,
reading_worker, &JFJochImageReadingWorker::setAutoLoadJump);
connect(toolBarImage, &JFJochViewerToolbarImage::reanalyzeImages,
reading_worker, &JFJochImageReadingWorker::ReanalyzeImages);
connect(side_panel, &JFJochViewerSidePanel::analyze,
reading_worker, &JFJochImageReadingWorker::Analyze);
connect(side_panel, &JFJochViewerSidePanel::findBeamCenter,
reading_worker, &JFJochImageReadingWorker::FindCenter);
connect(reading_worker, &JFJochImageReadingWorker::datasetLoaded,
reflectionWindow, &JFJochViewerReflectionListWindow::datasetLoaded);
connect(reading_worker, &JFJochImageReadingWorker::imageLoaded,
reflectionWindow, &JFJochViewerReflectionListWindow::imageLoaded);
connect(processingWindow, &JFJochViewerProcessingWindow::settingsChanged,
reading_worker, &JFJochImageReadingWorker::UpdateSpotFindingSettings);
connect(reflectionWindow, &JFJochHelperWindow::zoom, viewer, &JFJochDiffractionImage::centerOnSpot);
connect(spotWindow, &JFJochHelperWindow::zoom, viewer, &JFJochDiffractionImage::centerOnSpot);
connect(side_panel, &JFJochViewerSidePanel::showSpots,
viewer, &JFJochDiffractionImage::showSpots);
connect(side_panel, &JFJochViewerSidePanel::showPredictions,
viewer, &JFJochDiffractionImage::showPredictions);
connect(side_panel, &JFJochViewerSidePanel::setFeatureColor,
viewer, &JFJochDiffractionImage::setFeatureColor);
connect(side_panel, &JFJochViewerSidePanel::setFeatureColor,
calibrationWindow, &JFJochCalibrationWindow::setFeatureColor);
connect(side_panel, &JFJochViewerSidePanel::setSpotColor,
viewer, &JFJochDiffractionImage::setSpotColor);
connect(side_panel, &JFJochViewerSidePanel::showHighestPixels,
viewer, &JFJochDiffractionImage::showHighestPixels);
connect(side_panel, &JFJochViewerSidePanel::showSaturatedPixels,
viewer, &JFJochDiffractionImage::showSaturation);
connect(viewer, &JFJochDiffractionImage::writeStatusBar,
statusbar, &JFJochViewerStatusBar::display);
connect(side_panel, &JFJochViewerSidePanel::writeStatusBar,
statusbar, &JFJochViewerStatusBar::display);
connect(metadataWindow, &JFJochViewerMetadataWindow::datasetUpdated,
reading_worker, &JFJochImageReadingWorker::UpdateDataset);
connect(reading_worker, &JFJochImageReadingWorker::setRings,
side_panel, &JFJochViewerSidePanel::SetRings);
connect(side_panel, &JFJochViewerSidePanel::resRingsSet,
viewer, &JFJochDiffractionImage::setResolutionRing);
connect(side_panel, &JFJochViewerSidePanel::ringModeSet,
viewer, &JFJochDiffractionImage::setResolutionRingMode);
connect(side_panel, &JFJochViewerSidePanel::highlightIceRings,
viewer, &JFJochDiffractionImage::highlightIceRings);
connect(calibrationWindow, &JFJochCalibrationWindow::loadCalibration,
reading_worker, &JFJochImageReadingWorker::LoadCalibration);
connect(reading_worker, &JFJochImageReadingWorker::datasetLoaded,
calibrationWindow, &JFJochCalibrationWindow::datasetLoaded);
connect(reading_worker, &JFJochImageReadingWorker::simpleImageLoaded,
calibrationWindow, &JFJochCalibrationWindow::calibrationLoaded);
connect(azintWindow, &JFJochAzIntWindow::settingsChanged,
reading_worker, &JFJochImageReadingWorker::UpdateAzintSettings);
connect(azintImageWindow, &JFJoch2DAzintImageWindow::zoomOnBin,
viewer, &JFJochDiffractionImage::centerOnSpot);
// Ensure worker is deleted in its own thread when the thread stops
connect(reading_thread, &QThread::finished, reading_worker, &QObject::deleteLater);
connect(reading_worker, &JFJochImageReadingWorker::datasetLoaded, this,
[this](std::shared_ptr<const JFJochReaderDataset> ds) { lastDataset = std::move(ds); });
connect(reading_worker, &JFJochImageReadingWorker::imageLoaded, this,
[this](std::shared_ptr<const JFJochReaderImage> im) { lastImage = std::move(im); });
connect(menuBar, &JFJochViewerMenu::openDatasetInfo, this, &JFJochViewerWindow::NewDatasetInfo);
NewDatasetInfo();
if (!file.isEmpty())
LoadFile(file, 0, 1);
}
JFJochViewerWindow::~JFJochViewerWindow() {
if (reading_thread && reading_thread->isRunning()) {
reading_thread->quit();
reading_thread->wait();
}
}
void JFJochViewerWindow::LoadFile(const QString &filename, qint64 image_number, qint64 summation) {
emit LoadFileRequest(filename, image_number, summation);
}
void JFJochViewerWindow::LoadImage(qint64 image_number, qint64 summation) {
emit LoadImageRequest(image_number, summation);
}
void JFJochViewerWindow::NewDatasetInfo() {
auto info = new JFJochViewerDatasetInfo(this);
info->datasetLoaded(lastDataset);
info->imageLoaded(lastImage);
auto dock = new QDockWidget(QString("Dataset info"), this);
dock->setAllowedAreas(Qt::BottomDockWidgetArea);
dock->setFeatures(
QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetClosable |
QDockWidget::DockWidgetVerticalTitleBar);
dock->setAttribute(Qt::WA_DeleteOnClose);
dock->setWidget(info);
addDockWidget(Qt::BottomDockWidgetArea, dock);
// Wire signals like the initial dataset_info
connect(reading_worker, &JFJochImageReadingWorker::datasetLoaded,
info, &JFJochViewerDatasetInfo::datasetLoaded);
connect(reading_worker, &JFJochImageReadingWorker::imageLoaded,
info, &JFJochViewerDatasetInfo::imageLoaded);
connect(info, &JFJochViewerDatasetInfo::imageSelected,
reading_worker, &JFJochImageReadingWorker::LoadImage);
connect(toolBarDisplay, &JFJochViewerToolbarDisplay::colorMapChanged,
info, &JFJochViewerDatasetInfo::setColorMap);
connect(info, &JFJochViewerDatasetInfo::writeStatusBar,
statusbar, &JFJochViewerStatusBar::display);
}