Files
Jungfraujoch/image_analysis/LoadFCalcFromMtz.h
T
leonarski_fandClaude Opus 5.5 ae444437f4 rugnux: accept a PDB structure-factor mmCIF as the -z reference
-z (now also --reference; --reference-mtz still works) takes an SF-mmCIF
(e.g. a deposited -sf.cif, gzipped or not) as well as an MTZ. The format is
recognised by content: a file starting with "MTZ " is an MTZ, anything else
is parsed as CIF. The first merged reflection block with the requested
column (or, by default, one the auto choice accepts) is converted to a
gemmi::Mtz in memory with GEMMI's CifToMtz and then read by the unchanged
MTZ loader, so the in-memory reference is exactly what the MTZ path yields.
Unmerged (_diffrn_refln) and anomalous-only blocks are passed over; the log
names the block used.

The R-free set comes from _refln.status (f -> FreeR_flag 0, o -> 1: the
CCP4 convention the loader already reads) and is preferred to
_refln.pdbx_r_free_flag, whose convention varies by program; a status
column with no 'f' is ignored and pdbx_r_free_flag is used instead.

Checked on two open-arm sets in the deposited setting (one with F_meas_au
only, one with intensity_meas): reference loaded with the deposited cell and
group, the inherited free set agrees with the deposited status 'f' on every
common reflection, and the merge correlates at CC 0.99 with the deposition.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D1G8gJVAy6gp1K5Dz3NE5C
2026-09-25 20:17:03 +02:00

67 lines
3.9 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <optional>
#include <string>
#include <vector>
#include "../common/Reflection.h"
#include "../common/UnitCell.h"
// A column an MTZ offers as reference intensities/structure factors (type 'J' mean intensity or
// 'F' amplitude). Surfaced so the caller (CLI flag / viewer combo) can pick which one to scale
// against and report the choice, rather than the loader silently guessing.
struct ReferenceMtzColumn {
std::string label;
char type = '\0'; // 'J' = mean intensity, 'F' = structure-factor amplitude
};
// Reference reflections loaded from an MTZ, plus the metadata a user needs to judge whether the
// reference matches the data being scaled: which column was used, the cell / space group it was
// recorded in, its resolution range and reflection count.
struct ReferenceMtzData {
std::vector<MergedReflection> reflections; // h,k,l,I,d set (sigma stays NaN)
std::optional<UnitCell> cell;
std::optional<int> space_group_number;
std::string space_group_name; // Hermann-Mauguin short symbol, for display
std::string space_group_xhm; // the full symbol, which names the setting too
std::string point_group; // point-group symbol, for the consistency check
std::string used_column;
char used_column_type = '\0';
bool squared = false; // an 'F' column was squared to an intensity
bool default_column = true; // column was auto-selected, not user-specified
std::vector<ReferenceMtzColumn> candidate_columns;
double d_min = 0.0;
double d_max = 0.0;
// Cross-validation (free-R) flags, if the MTZ carried a FreeR_flag column. When present, the
// per-reflection rfree_flag above is set from it and a whole campaign can inherit one test set.
bool has_free_flags = false;
std::string free_column; // the FreeR column label used, for display
int n_free = 0; // number of reflections flagged free (test set)
std::string source; // "MTZ" or "SF-mmCIF block <name>", for display
};
// Load reference reflections from an MTZ or a PDB structure-factor mmCIF (SF-mmCIF), gzipped or not;
// the format is recognised by content. An SF-mmCIF block is converted to an MTZ in memory (FreeR_flag
// from _refln.status f/o, else _refln.pdbx_r_free_flag) and then read exactly like one. With no column requested the smart default is used:
// a calculated structure factor F-model (squared to an intensity), else a merged/observed
// intensity column (IMEAN/I/IOBS/...), else any mean-intensity (J) column - this also lets
// reference-based scaling be self-seeded from the data's own previous merge. A requested column overrides
// the default (an 'F'-type column is squared, a 'J'-type used directly). Throws if the requested
// column is missing or no usable column exists.
ReferenceMtzData LoadReferenceMtz(const std::string& path,
const std::optional<std::string>& column = std::nullopt);
// Compare a loaded reference against the data it will scale. Returns an empty string when they are
// consistent (or when the data cell / space group is unknown, so nothing can be said); otherwise a
// one-line, human-readable description of the mismatch to warn the user about. Reference intensities
// keyed in a different point group or cell do not correspond to the data, so this is the check that
// makes reference-based scaling and CCref trustworthy.
std::string ReferenceConsistencyWarning(const ReferenceMtzData& reference,
const std::optional<UnitCell>& data_cell,
std::optional<int> data_space_group_number);