A deposited structure-factor mmCIF marks the free set with _refln.status 'f', and the reader took that mark over _refln.pdbx_r_free_flag. Where the flags are classes (0-19), the status can mark a class the depositors' refinement did not hold out: the deposited model then fits the marked class like working data, R-work comes out above R-free, and refinement seems to make the model worse. The reader now keeps the numeric classes beside the status (RugnuxReflections::free_class, an extra FreeR_class column in the conversion). Where there are more than two classes, RunRefineOnly scores the model as given on each class (score-only, untwinned, no solvent build), within the resolution range the model file records its refinement to, and counts each class's reflections in that range: - STATUS: the marked class is the one the model fits worst, or its count is the nearest to the model file's test-set count (REMARK 3 FREE R VALUE TEST SET COUNT / _refine.ls_number_reflns_R_free); - REMARK3_COUNT: else the worst-fit class, where its count is the nearest; - WORST_FIT: else the worst-fit class, where it is above the marked one by more than twice the scatter of the other classes' R (the marked class is fitted like a working one); otherwise the mark stands. The count is corroboration only: over the battery's PDB cache (106 files with 20 classes) the marked class is within a few reflections of the count on nearly all, and another class has the count exactly on about 7 of them (20 classes of about the same size), so the count alone would move correct marks. The choice is logged with R per class and reported as REFINE_FREE_SET_SOURCE / REFINE_FREE_SET_CLASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HVeDQqN9qRD57vnShzTC37
55 lines
3.1 KiB
C++
55 lines
3.1 KiB
C++
// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#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 <name>"
|
|
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<MergedReflection> 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;
|
|
// A structure-factor mmCIF's numeric free-set classes (_refln.pdbx_r_free_flag) per reflection, -1 where it
|
|
// gives none; empty for an MTZ or where the file has no such column. free_column marks one class of them
|
|
// (_refln.status 'f', or the flag by the convention above), which need not be the depositors' test set.
|
|
std::vector<int> free_class;
|
|
};
|
|
|
|
// 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);
|