Files
Jungfraujoch/viewer/JFJochProcessController.h
T
leonarski_fandClaude Opus 5 84efb0666c viewer: open a miniCBF sweep, the same way rugnux already does
The native miniCBF reader added for rugnux is a plain JFJochReader, so the viewer
only needed to be told which one to open a file with. JFJochImageReadingWorker held
a concrete JFJochHDF5Reader; it now holds both readers and a JFJochReader* pointing
at whichever the open file needs, chosen by JFJochCBFReader::CanRead. Naming any
frame opens the whole sweep - the reader's own template matcher decides which frames
belong to it, so a directory holding two sweeps or XDS auxiliary files is not spliced
together. The previous file is closed before the new one is opened, so switching
format between HDF5 and CBF in one session leaves nothing behind.

Everything the viewer draws already goes through JFJochReader and
JFJochReaderDataset, so nothing else had to move. The two HDF5-only features stay on
the HDF5 reader: calibration images, and the reprocessing snapshots, which are
metadata read back over the same images the reader is serving and have nothing to
attach to for a directory of CBFs. A raw sweep therefore shows geometry and pictures
with an empty run list, which is the state a live HTTP stream is already in.

Reprocessing jobs run on a CBF sweep too - JFJochProcessController opens its own
reader the same way, and Rugnux has handled a CBF source since the reader landed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lc5JG6kJqZoCWaoZ43JGTW
2026-08-29 21:49:09 +02:00

71 lines
2.6 KiB
C++

// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <QObject>
#include <QString>
#include <atomic>
#include <chrono>
#include <memory>
#include <mutex>
#include <thread>
#include "../rugnux/Rugnux.h"
#include "../common/DiffractionExperiment.h"
#include "../common/PixelMask.h"
#include "../reader/JFJochReaderDataset.h"
Q_DECLARE_METATYPE(ProcessResult)
// Runs one Rugnux job off the GUI thread and reports back via queued Qt signals. The job
// opens its own private reader on the file (HDF5 access is globally serialized, so this
// is safe alongside the interactive reader), so the viewer becomes a processing frontend without
// blocking the UI. Cancel() is forwarded to Rugnux::Cancel() (atomic) and works from any
// thread / at any point of the run.
class JFJochProcessController : public QObject, private RugnuxObserver {
Q_OBJECT
public:
explicit JFJochProcessController(QObject *parent = nullptr);
~JFJochProcessController() override;
bool running() const { return running_; }
public slots:
// Start a job over `file_path` with the given (fully configured) experiment + mask + config.
// Ignored if a job is already running.
void start(const QString &file_path, DiffractionExperiment experiment,
PixelMask pixel_mask, ProcessConfig config);
void cancel();
signals:
void started();
void phaseChanged(QString phase);
void progress(quint64 done, quint64 total);
void finished(ProcessResult result);
void failed(QString error);
// Per-image results accumulated so far, for live dataset-info plots while a job runs (throttled).
void liveDataset(std::shared_ptr<const JFJochReaderDataset> dataset);
private:
// RugnuxObserver - called from worker threads, forwarded as queued signals.
void OnPhase(const std::string &phase) override;
void OnProgress(uint64_t done, uint64_t total) override;
void OnImageProcessed(const DataMessage &msg) override;
void run_(QString file_path, DiffractionExperiment experiment, PixelMask pixel_mask, ProcessConfig config);
void joinWorker_();
std::thread worker_;
std::atomic<Rugnux *> active_{nullptr};
std::atomic<bool> running_{false};
std::atomic<bool> cancel_pending_{false};
// Live per-image results, accumulated by OnImageProcessed (worker threads) and emitted as
// immutable copies. live_mutex_ guards both the dataset and the throttle timestamp.
std::mutex live_mutex_;
std::shared_ptr<JFJochReaderDataset> live_dataset_;
std::chrono::steady_clock::time_point last_live_emit_;
};