// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include #include #include #include #include #include #include "../JFJochProcessController.h" #include "../JFJochImageReadingWorker.h" // ReprocessingInputs class QTableWidget; class QProgressBar; class QStackedWidget; class QToolBar; class QToolButton; // Makes processing a first-class GUI activity: a dockable panel with a table of processing jobs run // on the current dataset. A job can be run locally (off the GUI thread, via JFJochProcessController) // or its rugnux command line copied for a cluster. A finished local run is registered as a // reader snapshot so its results become a selectable view of the dataset. Re-processing reads a // stored HDF5 file, so the panel shows an explanatory message while connected to a live HTTP stream. class JFJochProcessingJobsWindow : public QWidget { Q_OBJECT public: explicit JFJochProcessingJobsWindow(JFJochImageReadingWorker *worker, QWidget *parent = nullptr); signals: void registerSnapshot(QString id, QString label, QString master_path); void activateSnapshot(QString id); void renameRun(QString id, QString label); void removeRun(QString id); void writeStatusBar(QString message, int timeout_ms = 0); // Live per-image results while a job runs, for the dataset-info plots (nullptr clears it). void liveDataset(std::shared_ptr dataset); void jobStarted(); // a reprocessing job was launched — reveal the (hidden-by-default) panel public slots: void onHttpConnectionChanged(bool connected, QString addr); void clearJobs(); // reset the table on a new file (re-adds the Original row) void setActiveRun(QString active_id); // bold the row of the run currently shown in the plots void newJob(bool azint = false); // the panel's "Analyze dataset" action; azint = AzInt page private slots: void cancelJob(); void removeResult(); void viewResults(); void onPhase(QString phase); void onProgress(quint64 done, quint64 total); void onFinished(ProcessResult result); void onFailed(QString error); private: struct JobInfo { QString id; // stable reader-snapshot key QString label; // editable display name (legend / table) QString snapshot_path; // empty unless saved bool has_result = false; // Merge statistics captured when a scaling/merging job finished (drive the analysis window). bool has_merge_stats = false; MergeStatistics merge_stats; double isa = 0.0; bool merge_has_reference = false; TwinningAnalysisResult twinning; // twinning test of the merged intensities std::optional space_group_number; // final space group (searched or fixed) std::optional space_group_search; // ranked candidates, when a search ran std::vector> merged_i_sigma; // ISa diagnostic scatter QToolButton *graph_btn = nullptr; // per-row "show statistics" button (enabled once stats exist) }; struct JobSpec { ProcessMode mode = ProcessMode::FullAnalysis; int start_image = 0; int end_image = 0; // 0 == to the end int threads = 4; bool save_h5 = true; // write the per-image _process.h5 (also drives the viewer snapshot) bool save_merged = true; // write the merged .mtz/.cif QString prefix; bool rotation = false; int rotation_images = 30; // images used to find the rotation lattice (first pass) bool scaling = false; bool refine_geometry = false; // stills-only global geometry bundle-adjust (needs a known cell) int refine_geometry_frames = 200; // strong indexed frames fed to that bundle adjustment bool rotation_postrefine = true; // rotation-only two-pass geometry post-refine (default on) }; // Returns 0 = cancel, 1 = run locally, 2 = copy command line; fills spec from the dialog. int askJob(const ReprocessingInputs &inputs, JobSpec &spec, bool azint); ProcessConfig buildConfig(const JobSpec &spec, const ReprocessingInputs &inputs) const; void setStatus(int row, const QString &text); void addOriginalRow(); // the file's own data as the first, always-present run void addRowActions(int row, const QString &id); // per-row graph (stats) + trash (remove) buttons void showStats(const QString &id); // open the merge-statistics window for a run void removeRunById(const QString &id); // remove a run from the table + reader JFJochImageReadingWorker *worker_; JFJochProcessController *controller_; QToolBar *toolbar_; QStackedWidget *stack_; // page 0: jobs table, page 1: HTTP-mode message QTableWidget *table_; QProgressBar *running_bar_ = nullptr; // lives in the running row's Status cell QElapsedTimer job_timer_; // running job wall-clock, for rate + ETA int running_row_ = -1; int job_counter_ = 0; std::vector jobs_; };