Files
Jungfraujoch/image_analysis/scale_merge/IceRingMask.h
T
leonarski_fandClaude Opus 5 ea667cb306
Build Packages / build:viewer-tgz:cpu (push) Successful in 7m11s
Build Packages / build:viewer-tgz:cuda (push) Successful in 7m42s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 9m36s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 10m35s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 11m20s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 9m14s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 10m40s
Build Packages / build:rpm (rocky8) (push) Successful in 11m41s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m38s
Build Packages / build:rpm (rocky9) (push) Successful in 11m41s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 12m42s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 11m18s
Build Packages / Generate python client (push) Successful in 26s
Build Packages / Build documentation (push) Successful in 1m0s
Build Packages / Create release (push) Skipped
Build Packages / XDS test (neggia plugin) (push) Successful in 7m7s
Build Packages / XDS test (durin plugin) (push) Successful in 7m31s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m53s
Build Packages / build:windows:nocuda (push) Successful in 16m47s
Build Packages / DIALS test (push) Successful in 10m22s
Build Packages / build:windows:cuda (push) Successful in 17m37s
Build Packages / Unit tests (push) Successful in 1h42m32s
rugnux: handle ice rings in --scale as the full pipeline does
--scale did none of the ice handling the run that wrote the _process.h5 had
done, so re-scaling a stored dataset silently produced a different - and
flatteringly more complete - answer than the pipeline it was meant to
reproduce. Three separate gaps:

  * --detect-ice-rings was accepted and ignored. The --scale block returns
    before the line that applies it.
  * Reflections were never flagged as sitting on an ice ring, so the per-image
    scale fit included them. The flag is not stored per reflection, so it has
    to be recomputed from the resolution.
  * RotationScaleMerge was constructed with the ice half-width hardcoded to
    zero. That is what turns a resolution into a ring index, so every ice test
    inside the merge was a no-op whatever was passed to it.

The CC1/2 ring test that decides which rings to drop moves into
FindDecorrelatedIceRings, shared with the full pipeline so both reach the same
verdict on the same data, and --scale now re-merges with the mask the way the
pipeline does. The stills branch re-runs only the merge: the scaling has
already been applied to the reflections and repeating it would compound it.

Measured on a rotation dataset with three decorrelated rings, --scale went
from 8765 unique / 36.3% completeness / R-meas 18.5% / <I/sig> 1.1 to
7638 / 31.6% / 18.0% / 1.3, against the full pipeline's 7692 / 31.8% / 17.9% /
1.3 - the reported completeness had been inflated by reflections the pipeline
drops. The full pipeline is bit-identical across the refactor.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 19:49:55 +02:00

21 lines
1.1 KiB
C++

// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <vector>
#include "../../common/Logger.h"
#include "../../common/Reflection.h" // MergedReflection
// Hexagonal-ice rings whose merged half-set CC1/2 has collapsed well below the resolution shoulders
// either side: ice has decorrelated them and their Bragg intensity is unrecoverable, so the caller
// should re-merge with them dropped. A weak or absent ring tracks its neighbours and is not
// returned, which is what keeps completeness on a clean crystal untouched.
//
// Returns a mask indexed like ICE_RING_RES_A, or an empty vector when no ring qualifies - so the
// caller can test emptiness rather than scanning. Shared by the full pipeline and the offline
// --scale path, which have to reach the same verdict on the same data.
std::vector<char> FindDecorrelatedIceRings(const std::vector<MergedReflection> &merged,
float half_width_q_recipA, Logger &logger);