Build Packages / build:windows:nocuda (push) Successful in 20m4s
Build Packages / Unit tests (push) Skipped
Build Packages / build:viewer-tgz:cpu (push) Successful in 16m5s
Build Packages / build:viewer-tgz:cuda (push) Successful in 17m26s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 27m46s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 20m17s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 26m13s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 23m17s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 28m11s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 19m30s
Build Packages / build:rpm (rocky8) (push) Successful in 24m34s
Build Packages / build:rpm (rocky9) (push) Successful in 21m30s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 23m33s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 20m18s
Build Packages / DIALS test (push) Successful in 18m23s
Build Packages / XDS test (durin plugin) (push) Successful in 11m30s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 10m16s
Build Packages / XDS test (neggia plugin) (push) Successful in 8m2s
Build Packages / Generate python client (push) Successful in 49s
Build Packages / Build documentation (push) Successful in 1m21s
Build Packages / Create release (push) Skipped
Build Packages / build:windows:cuda (push) Successful in 29m45s
This is an UNSTABLE release. It includes many experimental features, as well as many AI generated fixes. We recommend using rc.152 for production use. * **rugnux: significantly better quality of results, and faster.** A large rework of integration, scaling, merging, geometry refinement and space-group determination, together with measurements the program previously made no attempt at - the direct beam before indexing, the beam stop, the goniometer rotation scale, and the stretches of a sweep the crystal did not deliver. A rotation dataset typically gains observations at better <I/sigma> and R_meas, and every `mx` and `scale` run writes a `<prefix>_report.txt` results report modelled on XDS's `CORRECT.LP`. Many defaults moved with it: spot detection is self-calibrating, beam-stop detection and rotation geometry post-refinement are on, resolution limits default to as far as the detector reaches, and ice-ring handling engages only where the crystal is measured to have ice. * **jfjoch_viewer:** the beam-stop shadow, the detector calibration and the beam-centre measurement are reachable from "Analyze dataset"; the settings panel reports how the sample moved and how polarized the beam was; image rendering and interaction are faster. * **Performance:** bitshuffle+LZ4 images are decoded on the GPU rather than on the host, with the bitshuffle inverse fused into preprocessing so the decompressed frame is never held in device memory. * **Broker, writer, packaging and build:** image-slot lifetime and locking fixes, per-image datasets sized by the images actually written, the Debian/Ubuntu broker package renamed to `jfjoch`, and `image_analysis` compiling under MSVC again. **Breaking change to the rugnux command line:** * `--azint-only` and `--scale` are **removed**, replaced by `--mode azint` and `--mode scale`; the full pipeline is `--mode mx` and remains the default. A script passing the old flags now fails with the list of valid modes rather than silently running the wrong one. * `-t`/`--stride` is **refused on rotation data**: skipping frames cuts every reflection's rocking curve, so the combined fulls and their partiality would be measured over frames the sweep never recorded. Select a contiguous range with `-s`/`-e` instead. `--mode azint` and `--force-still` still take a stride. **Breaking changes to OpenAPI** - regenerate the client (`jfjoch-client` 1.0.0-rc.161, `frontend/src/client`) or read the affected fields as optional: * `image_scale_b` is removed from the `plot_type` enum, so a client requesting that plot now gets an error rather than a curve. * `azim_int_settings.high_q_recipA`, `spot_finding_settings.high_resolution_limit` and `spot_finding_settings.low_resolution_limit` are no longer `required`. All three mean "no limit at that end" when unset and are omitted from the response instead of carrying a placeholder value, which raises in a client generated from an rc.160-or-earlier spec. A value of 0 is still accepted and means the same thing. **Breaking changes to the stored formats** - a consumer reading these fields must treat them as optional: * The per-image image-scale B factor is no longer computed, so `/entry/MX/imageScaleBFactor` is absent from newly written HDF5 files and the corresponding key is absent from the CBOR DataMessage and END blocks. Files written by rc.160 and earlier still contain it and still open; nothing in the pipeline reads it any more. * `_reflns.jfjoch_diffrn_ISa` now carries the whole-range `1/sqrt(a*b)` that XDS's ISa denotes, and the error-model `a` and `b` are reported in XDS's convention; the strong-reflection asymptote moves to `_reflns.jfjoch_diffrn_ISa_asymptotic`. **A file written by an earlier version carries the asymptote under the plain `ISa` name.** Reviewed-on: #71 Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
145 lines
5.6 KiB
C++
145 lines
5.6 KiB
C++
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#pragma once
|
|
|
|
#include <QPainterPath>
|
|
|
|
#include "JFJochImage.h"
|
|
#include "../../reader/JFJochReaderImage.h"
|
|
#include "../../common/ROIDefinition.h"
|
|
|
|
class ROIAzimuthal;
|
|
class DiffractionGeometry;
|
|
|
|
class JFJochDiffractionImage : public JFJochImage {
|
|
Q_OBJECT
|
|
|
|
QColor spot_color = Qt::green;
|
|
QColor prediction_color = Qt::darkRed;
|
|
QColor ice_ring_color = Qt::cyan;
|
|
QColor second_lattice_color = QColor(0xFA, 0x72, 0x68); // coral, the viewer "finishing" accent
|
|
|
|
float hover_resolution = NAN;
|
|
// The "d = ... A" readout is painted in drawForeground() in viewport pixels rather than kept
|
|
// as a scene item, so updating it dirties only its own rect. hover_text_rect_ is where it
|
|
// currently sits, in viewport coordinates.
|
|
QRect hover_text_rect_;
|
|
[[nodiscard]] QString HoverResolutionLabel() const;
|
|
// Counts are exact integers: label them from the int32 image rather than from a float copy,
|
|
// which both avoids materialising that copy and cannot round large summed values.
|
|
[[nodiscard]] QString PixelLabel(int x, int y) const override;
|
|
|
|
// This is the view that has detector counts, so it is the one that offers an ROI
|
|
[[nodiscard]] bool AllowROI() const override { return true; }
|
|
|
|
void drawForeground(QPainter *painter, const QRectF &rect) override;
|
|
// The readout sits at a fixed viewport position, but QGraphicsView scrolls by blitting the
|
|
// viewport, which carries the painted text along with it - so its old and new places both have
|
|
// to be repainted when the view pans.
|
|
void scrollContentsBy(int dx, int dy) override;
|
|
public:
|
|
enum class RingMode {Auto, Estimation, Manual, None, IceRings};
|
|
Q_ENUM(RingMode)
|
|
|
|
JFJochDiffractionImage(QWidget *parent = nullptr);
|
|
private:
|
|
|
|
void addCustomOverlay() override;
|
|
void LoadImageInternal();
|
|
// Colour straight from the int32 detector image; no float copy of it is ever built
|
|
void ColorRow(size_t y, const PixelColorMap &map, QRgb *out) const override;
|
|
|
|
void DrawResolutionRings();
|
|
void DrawROIs();
|
|
void DrawAzimuthalROI(const ROIAzimuthal &az, const QColor &color, const DiffractionGeometry &geom);
|
|
void AddROILabel(const std::string &name, const QColor &color, float px, float py);
|
|
|
|
// Interactive editing of the selected (named) ROI: move box/circle for now.
|
|
bool roiEditPress(const QPointF &scenePos) override;
|
|
void roiEditMove(const QPointF &scenePos) override;
|
|
void roiEditRelease() override;
|
|
void roiScratchDrawn() override;
|
|
void keyPressEvent(QKeyEvent *event) override; // Delete removes the selected ROI
|
|
[[nodiscard]] ROIDefinition BuildEditedROIDefinition() const; // current ROIs with the edit applied
|
|
[[nodiscard]] ResizeHandle hitTestBoxHandle(const QRectF &r, const QPointF &p, qreal tol) const;
|
|
// Grab points for an azimuthal ROI: inner/outer arc (resize Q/d) and the two phi
|
|
// edges (rotate). The phi handles are only meaningful for a sector (HasPhi()).
|
|
void azimuthalHandles(const ROIAzimuthal &az, const DiffractionGeometry &geom,
|
|
QPointF &inner, QPointF &outer, QPointF &phimin, QPointF &phimax) const;
|
|
|
|
QString selected_roi_;
|
|
enum class RoiEdit { None, MoveBox, ResizeBox, MoveCircle, ResizeCircle,
|
|
AzimInner, AzimOuter, RotatePhiMin, RotatePhiMax };
|
|
RoiEdit roi_edit_ = RoiEdit::None;
|
|
ResizeHandle box_handle_ = ResizeHandle::None;
|
|
QString edit_name_;
|
|
QRectF edit_box_;
|
|
QPointF edit_center_;
|
|
double edit_radius_ = 0;
|
|
float edit_d_min_ = 0, edit_d_max_ = 0, edit_phi_min_ = 0, edit_phi_max_ = 0; // azimuthal edit state
|
|
bool edit_has_phi_ = false;
|
|
QPointF move_last_;
|
|
bool live_pending_ = false; // a live edit is being recomputed; throttles emissions
|
|
|
|
void DrawSpots();
|
|
void DrawPredictions();
|
|
void DrawBeamCenter();
|
|
void DrawTopPixels();
|
|
void DrawSaturation();
|
|
void DrawResolutionText();
|
|
void DrawCross(float x, float y, float size, float width, float z = 1);
|
|
|
|
void UpdateForeground();
|
|
void leaveEvent(QEvent *event) override;
|
|
|
|
std::shared_ptr<const JFJochReaderImage> image;
|
|
|
|
int32_t show_highest_pixels = 0;
|
|
|
|
QVector<float> res_ring = {};
|
|
|
|
// Constant-d contours traced for res_ring, kept across overlay rebuilds; see DrawResolutionRings
|
|
QVector<float> ring_cache_key_ = {};
|
|
QVector<std::pair<float, QPainterPath>> ring_cache_ = {};
|
|
|
|
RingMode ring_mode = RingMode::Estimation;
|
|
|
|
bool show_spots = false;
|
|
bool show_predictions = false;
|
|
|
|
bool show_roi_labels = false;
|
|
bool show_roi_fill = false;
|
|
|
|
bool highlight_ice_rings = true;
|
|
|
|
void mouseHover(const QPointF &scenePos, Qt::KeyboardModifiers modifiers) override;
|
|
|
|
signals:
|
|
void roiGeometryEdited(ROIDefinition rois);
|
|
void roiSelected(QString name); // user picked an ROI by clicking it on the image
|
|
public slots:
|
|
void setSelectedROI(QString name);
|
|
void loadImage(std::shared_ptr<const JFJochReaderImage> image);
|
|
void setAutoForeground(bool input);
|
|
void setResolutionRing(QVector<float> v);
|
|
void setResolutionRingMode(RingMode mode);
|
|
|
|
void showSpots(bool input);
|
|
void showPredictions(bool input);
|
|
|
|
void showROILabels(bool input);
|
|
void showROIFill(bool input);
|
|
|
|
void setSpotColor(QColor input);
|
|
void setPredictionColor(QColor input);
|
|
|
|
void showHighestPixels(int32_t v);
|
|
void showSaturation(bool input);
|
|
void showBeamStop(bool input);
|
|
|
|
void highlightIceRings(bool input);
|
|
void setHDRMode(bool input);
|
|
};
|
|
|