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
71 lines
2.6 KiB
C++
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_;
|
|
};
|