// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include #include #include "gemmi/mtz.hpp" #include "gemmi/unitcell.hpp" #include "../common/Reflection.h" // Merged reflections a refinement is given (rugnux --mode refine), as their file held them: an MTZ or a // structure-factor mmCIF (as the PDB holds them), gzipped or not, the format taken from the content. The // columns are found, not named: amplitudes with their sigmas where the file has them, else intensities (the // caller turns those into amplitudes), and the free-set flags where there are any. The caller parses; the // analysis reads no file. struct RugnuxReflections { std::string name; // what the report calls the file std::string source; // "MTZ" or "mmCIF block " gemmi::UnitCell cell; std::string space_group; // extended Hermann-Mauguin symbol double wavelength_A = 0; // 0: the file does not say // h, k, l and d, with F/sigmaF where amplitudes were read, I/sigma where intensities were; rfree_flag // where the file has free-set flags. std::vector reflections; bool amplitudes = true; // false: intensities, no amplitudes in the file std::string value_column, sigma_column; std::string free_column; // empty: the file has no free-set flags int n_free = 0; }; // The columns of `mtz` (an MTZ, or an mmCIF converted to one), found as RugnuxReflections describes: // - amplitudes: a type-F column followed by its type-Q sigma, by the usual names first (F, FP, FOBS, F-obs, // FMEAN, ...), then any such pair that is not a calculated or map coefficient (FC, FWT, DELFWT, F-model ...); // - else intensities: a type-J column with its type-Q sigma (IMEAN, I, IOBS, I-obs, ... first); the // anomalous pairs F(+)/F(-) (G/L) or I(+)/I(-) (K/M) averaged where there is nothing else; // - free flags: a type-I column named as a free set (FreeR_flag, FREE, R-free-flags, ...: any with "free" in // its name). The test set is flag 0 in the CCP4 convention (0-19 thin shells included); where 0 marks the // majority (1 marks the test set, as phenix and CNS write it), the minority is taken. // Throws where there is neither. RugnuxReflections RugnuxReflectionsFromMtz(const gemmi::Mtz &mtz, const std::string &name); // The reflections of a file's bytes, the format from the content (MTZ by its magic, else mmCIF: the first // merged block that holds amplitudes or intensities). Throws where the bytes hold none. RugnuxReflections ParseRugnuxReflections(const std::string &bytes, const std::string &name); // The file at `path`, named by it. RugnuxReflections ReadRugnuxReflectionFile(const std::string &path);