Files
Jungfraujoch/common/Reflection.h
T
leonarski_fandClaude Fable 5 8c084021e6 ice rings: exclude from scaling, keep in the final merge (recover completeness)
--detect-ice-rings previously dropped ice-ring reflections outright before
scaling, which also removed them from the merge and gutted low/mid-resolution
completeness on crystals that merge them fine (e.g. lysoC 80% -> the ice bands
show as jagged shell completeness). Instead flag them (new Reflection.on_ice_ring,
set in JFJochProcess, carried through the 3D combine) and exclude the flag only
where a model is fit: the per-image scale (ScaleOnTheFly::Accept + the per-image
CC), and - for the de-novo P1 pass - the space-group search and error model
(MergeOnTheFly::ExcludeIceRings, on for for_search). The final in-symmetry merge
and its statistics keep them, so completeness is preserved.

/data/rotation_test battery vs the previous drop-from-merge behaviour: space
group correct on all 18; completeness recovered broadly with CC1/2 and ISa held
(cytC_2 82->99.7%, cytC_3 73->99.7%, InsI3 76->99.5%, lysoC 80->99.7%, MyoB
80->99.7%, InsH3 78->99%). Excluding ice from the P1 search merge is what keeps
the space group correct: without it InsI3 flipped I23->P1 and EP_cs_01-17 P2->P1.

Known limitation: on heavy-ice crystals (EP_cs_01-17) the strong ice is garbage
and keeping it in the final merge collapses CC1/2 in the ice shells (91.7->6.9%).
Distinguishing strong vs weak/absent rings per crystal needs data-driven,
per-ring ice detection (azimuthal radial profile) - the planned next step.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:29:37 +02:00

49 lines
1.4 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <cstdint>
#include <optional>
#include <cmath>
#include "SpotToSave.h"
struct Reflection {
int32_t h;
int32_t k;
int32_t l;
float image_number; // Can be in-between for 3D integration
float delta_phi_deg; // phi angle from XDS - difference from middle of current frame (NOT an absolute angle)
float predicted_x;
float predicted_y;
float observed_x;
float observed_y;
float d;
float I;
float bkg;
float sigma;
float dist_ewald;
float rlp;
float partiality; // fraction of the reflection recorded in the sampled (rocking) slice
float completeness = 1.0f; // fraction of the spot footprint on live pixels (1 = not clipped by edge/gap/mask)
float zeta;
float image_scale_corr; // I_true = scaling_correction * I; scaling_correction = rlp / (partiality * image_scale)
bool observed = false;
bool on_ice_ring = false; // sits on a hexagonal-ice powder ring: excluded from scaling, kept for merging
};
struct MergedReflection {
int32_t h = 0;
int32_t k = 0;
int32_t l = 0;
float I = NAN;
float sigma = NAN;
float I_half[2] = {NAN, NAN};
float sigma_half[2] = {NAN, NAN};
float d = 0.0;
bool rfree_flag = false;
};