// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include #include #include #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 reflections; // h,k,l,I,d set (sigma stays NaN) std::optional cell; std::optional space_group_number; std::string space_group_name; // Hermann-Mauguin short symbol, for display 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 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) }; // Load reference reflections from an MTZ. 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& 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& data_cell, std::optional data_space_group_number);