Merging: export the XDS-comparable ISa under jfjoch_diffrn_ISa

The mmCIF's _reflns.jfjoch_diffrn_ISa carried the strong-reflection asymptote, a tier XDS has no
equivalent of, while the name invites comparison with XDS's ISa - which is the whole-range
1/sqrt(a*b). rugnux_vs_xds.py reads that item for the battery's ISa column, so the comparison that
column exists to make was between two different quantities, flattering rugnux by the difference
between the tiers.

Write the whole-range value there, move the asymptote to _reflns.jfjoch_diffrn_ISa_asymptotic, and
add _reflns.jfjoch_error_model_a and _b in XDS's convention so the number can be re-derived from the
file rather than taken on trust.

On a broadband rotation dataset the battery column now reads 13.25 against XDS's 21.18 where it read
15.6 before, and the two error models can be compared term by term for the first time: a 1.538 vs
1.249 and b 3.71e-03 vs 1.78e-03, so the gap is in BOTH the counting and the systematic term
(1.23x and 2.08x, and sqrt(1.23*2.08) = 1.60 = 21.18/13.25).

This is a deliberate redefinition of an exported item, not an addition: a file written by an earlier
version carries the asymptote under the old name and there is no version marker to tell them apart.
Noted in the changelog and in docs/CPU_DATA_ANALYSIS.md. Nothing reads the item back into the
pipeline - it is written and never parsed by rugnux itself - so no stored file is reinterpreted in a
way that changes a result.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-10 18:55:46 +02:00
co-authored by Claude Opus 5
parent ac06b5c64f
commit adf87e8675
9 changed files with 88 additions and 19 deletions
+16 -4
View File
@@ -148,7 +148,7 @@ void WriteMmcifReflections(const std::vector<MergedReflection> &reflections,
const UnitCell &unitCell,
const DiffractionExperiment &experiment,
const MergeStatistics &statistics,
const std::string &isa,
const ErrorModelReport &error_model,
const TwinningAnalysisResult &twinning,
const std::string &filename) {
@@ -237,7 +237,19 @@ void WriteMmcifReflections(const std::vector<MergedReflection> &reflections,
if (has_anom)
out << "_reflns.pdbx_absDiff_over_sigma_anomalous " << Fmt(ov.abs_diff_over_sigma_anomalous, 3)
<< " # SigAno = <|dano|>/<sigma(dano)>\n";
out << "_reflns.jfjoch_diffrn_ISa " << CifStr(isa) << " # asymptotic I/sigma (Diederichs)\n";
// ISa in XDS's sense: the whole-range 1/sqrt(a*b) of the error model below, so this item can
// be read straight against a CORRECT.LP. The strong-reflection asymptote - a tier XDS does not
// have, and always the more optimistic of the two - is written separately rather than here.
out << "_reflns.jfjoch_diffrn_ISa " << CifStr(error_model.isa)
<< " # 1/sqrt(a*b), the XDS convention\n";
if (!error_model.isa_asymptotic.empty())
out << "_reflns.jfjoch_diffrn_ISa_asymptotic " << CifStr(error_model.isa_asymptotic)
<< " # strong-reflection asymptote (Diederichs); rotation path only\n";
if (!error_model.a.empty())
out << "_reflns.jfjoch_error_model_a " << CifStr(error_model.a)
<< " # sigma^2 = a*(sigma0^2 + b*I^2), XDS convention\n";
if (!error_model.b.empty())
out << "_reflns.jfjoch_error_model_b " << CifStr(error_model.b) << "\n";
// Dataset-wide isotropic Wilson B-factor estimate (standard PDBx item), analogous to XDS's
// "WILSON LINE ... B=". Emitted only when the log-linear fit succeeded.
if (std::isfinite(statistics.wilson_b) && statistics.wilson_b > 0.0)
@@ -468,13 +480,13 @@ void WriteReflections(const std::vector<MergedReflection> &reflections,
const UnitCell &unitCell,
const DiffractionExperiment &experiment,
const MergeStatistics &statistics,
const std::string &isa,
const ErrorModelReport &error_model,
const TwinningAnalysisResult &twinning,
const std::string &filename) {
// Write an MTZ, an mmCIF and a SHELX HKLF-4 .hkl - each has its uses downstream (MTZ for the CCP4 /
// phenix reflection tools, mmCIF for deposition and as the self-describing native format, HKLF-4 as
// the SHELXC / ANODE substructure-solution input).
WriteMtzReflections(reflections, unitCell, experiment, filename + ".mtz");
WriteMmcifReflections(reflections, unitCell, experiment, statistics, isa, twinning, filename + ".cif");
WriteMmcifReflections(reflections, unitCell, experiment, statistics, error_model, twinning, filename + ".cif");
WriteShelxHklReflections(reflections, experiment, filename + ".hkl");
}