merged MTZ: FreeR_flag in the convention its own column name carries
The column was written with 1 for the test set and 0 for the working set - the phenix/CNS numbering - under FreeR_flag, which is CCP4's column name. CCP4's own freerflag writes 0..19 with 0 as the test bin, and REFMAC5's default FREE 0 reads it that way, so REFMAC5 stopped on every file we wrote: "more than half of reflections are in free R set", then "Cannot switch free R flag", exit 1. phenix auto-detects either numbering with equal confidence (measured on both, score 3 each), and rugnux's own reference-MTZ reader already takes flag 0 as the test set, so 0 = test is the numbering that works everywhere and the one the rest of the code assumes. This changes every merged .mtz we write: a script that reads FreeR_flag == 1 as the test set has to be inverted. The mmCIF's _refln.status_free is a separate item with its own convention and is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
* `rugnux` writes the unmerged MTZ by default, with a P1 merge beside it, so a wrong space group can be re-merged without reprocessing.
|
||||
* `rugnux` writes a batch header in the unmerged MTZ for every image the observations span, not only for the images that produced one, so a scaling program reads one run per sweep.
|
||||
* `rugnux` leaves an event out of the unmerged MTZ when less of its rocking curve was captured than `--min-captured-fraction`, as the merge does, since the exported rows are declared full.
|
||||
* `rugnux` writes `FreeR_flag` with 0 for the test set and 1 for the working set, the CCP4 convention REFMAC5 defaults to; it was the other way round.
|
||||
* `rugnux` handles symmetry better: the lattice, the point group, the setting and the systematic absences.
|
||||
* `rugnux` fits the direction of the goniometer axis and not its length, so the cell chosen by the first pass is the one its own refinement scored.
|
||||
* `rugnux` reports the detector geometry it measured - the direct beam, the tilt and the beam centre - and what a single sweep can and cannot determine.
|
||||
|
||||
@@ -74,7 +74,14 @@ struct MergedOutRow {
|
||||
int h = 0, k = 0, l = 0;
|
||||
float Imean = NAN, sImean = NAN, Ip = NAN, sIp = NAN, Im = NAN, sIm = NAN;
|
||||
float Fmean = NAN, sFmean = NAN, Fp = NAN, sFp = NAN, Fm = NAN, sFm = NAN;
|
||||
int rfree = 0;
|
||||
// The value written into FreeR_flag: 0 for the TEST set, 1 for the working set. That is the CCP4
|
||||
// convention the column NAME belongs to - CCP4's own freerflag writes 0..19 with 0 as the ~5%
|
||||
// test bin, and REFMAC's default FREE 0 reads it that way, so the opposite (phenix/CNS) numbering
|
||||
// under this name stops REFMAC dead: "more than half of reflections are in free R set", then
|
||||
// "Cannot switch free R flag", exit 1. phenix auto-detects either numbering with equal confidence
|
||||
// (measured on both), and rugnux's own reference-MTZ reader already takes 0 as the test set, so
|
||||
// this is the numbering that works everywhere and the one the rest of the code assumes.
|
||||
int rfree = 1;
|
||||
};
|
||||
|
||||
std::vector<MergedOutRow> BuildMergedRows(const std::vector<MergedReflection> &reflections,
|
||||
@@ -95,7 +102,7 @@ std::vector<MergedOutRow> BuildMergedRows(const std::vector<MergedReflection> &r
|
||||
for (const auto& r : reflections)
|
||||
out_rows.push_back({r.h, r.k, r.l, r.I, r.sigma, r.I_plus, r.sigma_plus, r.I_minus,
|
||||
r.sigma_minus, r.F, r.sigmaF, r.F_plus, r.sigmaF_plus, r.F_minus,
|
||||
r.sigmaF_minus, r.rfree_flag ? 1 : 0});
|
||||
r.sigmaF_minus, r.rfree_flag ? 0 : 1});
|
||||
} else {
|
||||
// Anomalous: group the two mates by their (shared) Friedel-merged ASU representative, then form
|
||||
// IMEAN / F as their inverse-variance Friedel mean. A single generator gives both the group key
|
||||
@@ -105,14 +112,14 @@ std::vector<MergedOutRow> BuildMergedRows(const std::vector<MergedReflection> &r
|
||||
int h = 0, k = 0, l = 0;
|
||||
float Ip = NAN, sIp = NAN, Im = NAN, sIm = NAN;
|
||||
float Fp = NAN, sFp = NAN, Fm = NAN, sFm = NAN;
|
||||
int rfree = 0;
|
||||
int rfree = 1;
|
||||
};
|
||||
std::map<std::tuple<int, int, int>, AnomRow> rows;
|
||||
for (const auto& r : reflections) {
|
||||
const HKLKey key = key_gen(r);
|
||||
AnomRow& row = rows[{key.h, key.k, key.l}];
|
||||
row.h = key.h; row.k = key.k; row.l = key.l;
|
||||
row.rfree = r.rfree_flag ? 1 : 0;
|
||||
row.rfree = r.rfree_flag ? 0 : 1;
|
||||
if (key.plus) { row.Ip = r.I; row.sIp = r.sigma; row.Fp = r.F; row.sFp = r.sigmaF; }
|
||||
else { row.Im = r.I; row.sIm = r.sigma; row.Fm = r.F; row.sFm = r.sigmaF; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user