The factor multiplied into each integrated intensity was called rlp, for reciprocal Lorentz-polarization, and until this week that is all it held. It now also carries the sensor efficiency at the angle the beam arrives, and on the stills path it holds that efficiency and the polarization with no Lorentz term at all - correctly, since the Lorentz factor of a still is one. Three different products under one name that promises exactly one of them, in code where the neighbouring member is the total correction. Rename it prescaling_corr: multiplicative, applied before scaling, therefore not a scale, and silent about its contents - which is the point, since the contents have now grown twice. It is also what DIALS calls the same product. The stills refinement member spelled "1 / rlp" becomes inv_corr, and the comments and usage text that promised "the Lorentz-polarization factor and nothing else" now say what is actually there. The Lorentz term keeps its own name where it is computed, because that name is correct. The two external spellings are untouched: the CBOR key and the reflection dataset are a published format, and a reader that meets an unknown key would take the factor as zero, which both the merge key and the ingest treat as a reflection to drop - so every reflection would vanish and the run would still exit zero. No output changes: the merged and unmerged files of two full runs are byte for byte what the previous binary wrote, four stored files from before the efficiency correction still re-scale identically, and the reflection datasets of the process file are unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
70 lines
2.8 KiB
C++
70 lines
2.8 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 var_bkg; // non-signal (background) part of sigma^2, carried to the merge
|
|
float sigma;
|
|
float dist_ewald;
|
|
// Everything known a priori that multiplies the raw integrated count on its way to a quantity
|
|
// proportional to |F|^2: the reciprocal Lorentz factor, the reciprocal polarization factor and
|
|
// the sensor's angle-dependent efficiency, whichever of them the path that filled it applies.
|
|
// It is deliberately NOT an enumeration of those terms - it is the product of every deterministic
|
|
// per-reflection correction, and that set has grown before and will grow again. What it is not is
|
|
// a scale: the fitted per-image scale and the partiality stay out of it and are divided in
|
|
// separately below. (Named after DIALS's prescaling_correction, which holds the same product.)
|
|
float prescaling_corr;
|
|
float partiality; // fraction of the reflection recorded in the sampled (rocking) slice
|
|
float zeta;
|
|
float image_scale_corr; // I_true = image_scale_corr * I; = prescaling_corr / (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;
|
|
float F = NAN; // French-Wilson amplitude |F| (filled by ApplyFrenchWilson at end of merge)
|
|
float sigmaF = NAN; // its sigma
|
|
// Anomalous (Bijvoet) split of this reflection's own observations, kept even when the merge is
|
|
// Friedel-averaged (I above is the Friedel mean). Lets I(+)/I(-) be written and CCano reported by
|
|
// default without scaling anomalously; NaN when a hand was not measured or for centrics.
|
|
float I_plus = NAN;
|
|
float sigma_plus = NAN;
|
|
float I_minus = NAN;
|
|
float sigma_minus = NAN;
|
|
// French-Wilson amplitudes of the two hands (filled by ApplyFrenchWilson from I_plus/I_minus).
|
|
float F_plus = NAN;
|
|
float sigmaF_plus = NAN;
|
|
float F_minus = NAN;
|
|
float sigmaF_minus = NAN;
|
|
};
|
|
|
|
|