--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>
49 lines
1.4 KiB
C++
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;
|
|
};
|
|
|
|
|