rugnux: always write both MTZ and CIF; drop --scaling-output

The merged reflections were written in one of mtz/cif/txt selected by
--scaling-output. Write both an MTZ and an mmCIF unconditionally instead - each
has its uses downstream (MTZ for the CCP4/phenix tools, mmCIF for deposition) -
and remove the format selector, the plain-text .hkl writer, and the now-unused
IntensityFormat enum / ScalingSettings::FileFormat plumbing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-16 10:45:08 +02:00
co-authored by Claude Opus 4.8
parent ce12d69751
commit eae7ea90dc
7 changed files with 7 additions and 67 deletions
-9
View File
@@ -212,15 +212,6 @@ double ScalingSettings::GetMinCapturedFraction() const {
return min_captured_fraction;
}
ScalingSettings &ScalingSettings::FileFormat(IntensityFormat input) {
intensity_format = input;
return *this;
}
IntensityFormat ScalingSettings::GetFileFormat() const {
return intensity_format;
}
ScalingSettings &ScalingSettings::RfreeFraction(double input) {
if (input < 0.0 || input > 1.0)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "R-free fraction must be between 0 and 1");
-5
View File
@@ -6,8 +6,6 @@
#include <optional>
#include "JFJochException.h"
enum class IntensityFormat { Text, mmCIF, MTZ};
// How the high-resolution cutoff for the written reflections and the reported shell table is chosen
// when no explicit --scaling-high-resolution is given. Off = keep the full (detector-edge) range;
// CCHalfLogistic = fit the CC1/2 fall-off and cut one shell past cc_target (DIALS-style, generous).
@@ -56,7 +54,6 @@ class ScalingSettings {
double smooth_g_deg = 0.0;
double rfree_fraction = 0.05;
IntensityFormat intensity_format = IntensityFormat::mmCIF;
// Automatic high-resolution cutoff for the written reflections + reported shells (not the scaling
// or the error model, and not the per-image _process.h5). Applied only when no explicit
@@ -86,7 +83,6 @@ public:
ScalingSettings& SmoothGDegrees(double input);
ScalingSettings& RfreeFraction(double input);
ScalingSettings& FileFormat(IntensityFormat input);
ScalingSettings& ScalingRegularize(bool input);
ScalingSettings& ResolutionCutoff(ResolutionCutoffMethod input);
@@ -124,7 +120,6 @@ public:
[[nodiscard]] double GetSmoothGDegrees() const;
[[nodiscard]] double GetRfreeFraction() const;
[[nodiscard]] IntensityFormat GetFileFormat() const;
[[nodiscard]] bool GetScalingRegularize() const;
[[nodiscard]] ResolutionCutoffMethod GetResolutionCutoff() const;
+1
View File
@@ -21,6 +21,7 @@ This is an UNSTABLE release. It includes many experimental features, as well as
* Reader: Treat a negative `total_flux` in a stored dataset as unknown/absent rather than a real (invalid) flux.
* Packaging: Build the self-contained Linux viewer against a static libdbus with glib disabled, so the `.tgz` no longer drags a tail of system `.so` dependencies; add parallel image-build and in-container viewer-verification scripts.
* rugnux: Write anomalous data as a standard CCP4 anomalous MTZ - one row per reflection with `IMEAN`, `I(+)`/`I(-)` (and the matching `F`/`F(+)`/`F(-)` amplitudes) - instead of two `IMEAN` rows per Bijvoet pair, so `aimless`/`mtz2sca`/ANODE read it directly. The non-anomalous MTZ output is unchanged.
* rugnux: Always write the merged reflections as both `<prefix>.mtz` and `<prefix>.cif` (each has its uses downstream - MTZ for the CCP4/phenix tools, mmCIF for deposition). The `--scaling-output` format selector and the plain-text `.hkl` output are removed.
### 1.0.0-rc.159
This is an UNSTABLE release. It includes many experimental features, as well as many AI generated fixes. We recommend using rc.152 for production use.
+2 -3
View File
@@ -45,8 +45,8 @@ the first pass.
[HDF5 / NeXus data format](HDF5.md) for the layout. Written by default only when **not** merging
(i.e. under `--no-merge`); add `--write-process-h5` to also write it when merging.
- Merging is **on by default** (`--no-merge` disables it). The merged reflections are written as
`<prefix>.cif` (mmCIF — the default), or `<prefix>.mtz` / `<prefix>.hkl` depending on
`--scaling-output`. Both the mmCIF and the MTZ carry the **refined unit cell** (from rotation
**both** `<prefix>.mtz` and `<prefix>.cif` (mmCIF) — each has its uses downstream (MTZ for the
CCP4 / phenix tools, mmCIF for deposition). Both carry the **refined unit cell** (from rotation
indexing) and the **space group determined from systematic absences** (constrained to the indexed
lattice symmetry). No-reference scaling additionally emits per-iteration `<prefix>_iterN_scale.dat`.
@@ -212,7 +212,6 @@ Scaling and merging:
| `--min-image-cc <num>` | Per-image CC limit, percent (default: no limit) |
| `--mosaicity <num>` | Diagnostic: fix the scaling mosaicity (°) instead of using the per-image seed |
| `--scaling-iterations <num>` | Scaling iterations with no reference data (default: 3) |
| `--scaling-output <txt>` | Reflection output format: `cif` (mmCIF, default) \| `mtz` \| `txt` |
| `-z, --reference-mtz <file>` | Reference MTZ (enables reference-driven scaling) |
| `--reference-column <label>` | Reference MTZ column to use (default: auto — F-model, else IMEAN/I/…) |
| `--write-process-h5` | Also write the (large) `_process.h5` when merging (default: only `.mtz`/`.cif`) |
+4 -26
View File
@@ -334,21 +334,6 @@ void WriteMtzReflections(const std::vector<MergedReflection> &reflections,
mtz.write_to_file(filename);
}
void WriteHKLReflections(const std::vector<MergedReflection> &reflections,
const std::string &filename) {
std::ofstream hkl_file(filename);
if (!hkl_file)
throw JFJochException(JFJochExceptionCategory::FileWriteError, "Cannot open file " + filename + " for writing");
for (const auto &r: reflections)
hkl_file << r.h << " " << r.k << " " << r.l << " "
<< r.I << " " << r.sigma << " "
<< (r.rfree_flag ? 1 : 0) << " "
<< r.F << " " << r.sigmaF << std::endl;
hkl_file.close();
}
void WriteReflections(const std::vector<MergedReflection> &reflections,
const UnitCell &unitCell,
const DiffractionExperiment &experiment,
@@ -356,15 +341,8 @@ void WriteReflections(const std::vector<MergedReflection> &reflections,
const std::string &isa,
const TwinningAnalysisResult &twinning,
const std::string &filename) {
switch (experiment.GetScalingSettings().GetFileFormat()) {
case IntensityFormat::Text:
WriteHKLReflections(reflections, filename + ".hkl");
break;
case IntensityFormat::mmCIF:
WriteMmcifReflections(reflections, unitCell, experiment, statistics, isa, twinning, filename + ".cif");
break;
case IntensityFormat::MTZ:
WriteMtzReflections(reflections, unitCell, experiment, filename + ".mtz");
break;
}
// Always write both an MTZ and an mmCIF - each has its uses downstream (MTZ for the CCP4 /
// phenix reflection tools, mmCIF for deposition and as the self-describing native format).
WriteMtzReflections(reflections, unitCell, experiment, filename + ".mtz");
WriteMmcifReflections(reflections, unitCell, experiment, statistics, isa, twinning, filename + ".cif");
}
-3
View File
@@ -26,9 +26,6 @@ void WriteMtzReflections(const std::vector<MergedReflection> &reflections,
const DiffractionExperiment &experiment,
const std::string &filename);
void WriteHKLReflections(const std::vector<MergedReflection> &reflections,
const std::string &filename);
void WriteReflections(const std::vector<MergedReflection> &reflections,
const UnitCell &unitCell,
const DiffractionExperiment &experiment,
-21
View File
@@ -103,7 +103,6 @@ void print_usage() {
std::cout << " --reject-delta-cchalf <num> Per-crystal CC1/2-delta rejection: drop images with deltaCChalf below mean - N*stddev (default: off; e.g. 2.5)" << std::endl;
std::cout << " --min-image-cc <num> Per-image CC limit in percent (default: no limit)" << std::endl;
std::cout << " --scaling-iterations <num> Number of scaling iterations with no reference data (default: 3)" << std::endl;
std::cout << " --scaling-output <txt> Output format for scaling results mtz|cif|txt (default: cif)" << std::endl;
std::cout << " -z, --reference-mtz <file> Reference MTZ file" << std::endl;
std::cout << " --reference-column <label> Reference MTZ column to use (default: auto - F-model, else IMEAN/I, else FP/FOBS/F)" << std::endl;
std::cout << " --model <file.pdb> After merging, validate vs this model: R-free + 2Fo-Fc/Fo-Fc maps" << std::endl;
@@ -146,7 +145,6 @@ enum {
OPT_RESOLUTION_CUTOFF,
OPT_RESOLUTION_CC_TARGET,
OPT_RESOLUTION_SHELLS,
OPT_SCALING_OUTPUT,
OPT_SINGLE_PASS_ROTATION,
OPT_REDO_ROTATION_SPOTS,
OPT_FORCE_ROTATION_LATTICE,
@@ -252,7 +250,6 @@ static option long_options[] = {
{"resolution-cutoff", required_argument, nullptr, OPT_RESOLUTION_CUTOFF},
{"resolution-cc-target", required_argument, nullptr, OPT_RESOLUTION_CC_TARGET},
{"resolution-shells", required_argument, nullptr, OPT_RESOLUTION_SHELLS},
{"scaling-output", required_argument, nullptr, OPT_SCALING_OUTPUT},
{"bandwidth", required_argument, nullptr, OPT_BANDWIDTH},
{"integration-radius", required_argument, nullptr, OPT_INTEGRATION_RADIUS},
{"integrator", required_argument, nullptr, OPT_INTEGRATOR},
@@ -519,8 +516,6 @@ int main(int argc, char **argv) {
IndexingAlgorithmEnum indexing_algorithm = IndexingAlgorithmEnum::Auto;
GeomRefinementAlgorithmEnum refinement_algorithm = GeomRefinementAlgorithmEnum::BeamCenter;
std::optional<IntensityFormat> intensity_format; // --scaling-output override; default lives in ScalingSettings (mmCIF)
float d_min_spot_finding = 1.5;
float d_max_spot_finding = 0; // 0 = keep the SpotFindingSettings default (50 A)
std::optional<float> d_min_scale_merge;
@@ -833,18 +828,6 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE);
}
break;
case OPT_SCALING_OUTPUT:
if (strcmp(optarg, "mtz") == 0) {
intensity_format = IntensityFormat::MTZ;
} else if (strcmp(optarg, "cif") == 0) {
intensity_format = IntensityFormat::mmCIF;
} else if (strcmp(optarg, "txt") == 0) {
intensity_format = IntensityFormat::Text;
} else {
logger.Error("Invalid intensity format: {}", optarg);
exit(EXIT_FAILURE);
}
break;
case OPT_FORCE_STILL:
force_still = true;
break;
@@ -1063,8 +1046,6 @@ int main(int argc, char **argv) {
scaling_settings.OutlierRejectNsigma(
outlier_reject_nsigma.value_or(
(experiment.GetGoniometer().has_value() && !force_still) ? REJECT_OUTLIERS_DEFAULT_NSIGMA : 0.0));
if (intensity_format)
scaling_settings.FileFormat(intensity_format.value());
experiment.ImportScalingSettings(scaling_settings);
if (!experiment.GetUnitCell()) {
@@ -1376,8 +1357,6 @@ int main(int argc, char **argv) {
scaling_settings.MinCCForImage(min_image_cc / 100.0); // --min-image-cc is in percent; the setting is a fraction
scaling_settings.OutlierRejectNsigma(
outlier_reject_nsigma.value_or(rotation_indexing ? REJECT_OUTLIERS_DEFAULT_NSIGMA : 0.0));
if (intensity_format)
scaling_settings.FileFormat(intensity_format.value());
experiment.ImportScalingSettings(scaling_settings);