calibration: write the JSON before anything the poni can refuse

The orientation refusal added an hour ago throws out of WritePoniFile, which ran
first inside the same try - so the run aborted before WriteCalibrationJson, and
its own error text told the user "the .json beside it carries the full geometry"
where there was no .json at all.

The JSON is the file that can state everything: the verdict, the uncertainty, and
a geometry a PONI has no fields for. It goes first, so a poni that cannot be
written costs only the poni.

Found by the documentation audit, which went to write down what the failure
produces and found the two did not agree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-02 17:44:20 +02:00
co-authored by Claude Opus 5
parent 2456bbe7f6
commit b2cbf2723b
+11 -11
View File
@@ -2191,19 +2191,19 @@ static int RunRugnux(int argc, char **argv) {
const std::string poni_path = output_prefix + ".poni";
const std::string json_path = output_prefix + ".json";
try {
// A .poni file states where the detector is and nothing else. It has no field for doubt, so
// there is no honest way to write a geometry that is not a measurement into one - every
// program that reads it downstream would read it as if it were. Withholding it is the only
// thing the format allows. The JSON is written either way and carries the verdict, because
// it is where the evidence lives and it is wanted most exactly when the fit failed.
if (cal.converged)
WritePoniFile(poni_path, experiment, g);
// The same answer for whatever reads it next. A PONI file is what pyFAI and its neighbours
// take, but nothing in this system does, and it says nothing about how well the geometry is
// known - so write the JSON alongside it, with the geometry under dataset_settings' own
// property names and the quality beside it.
// The JSON FIRST, and ahead of anything the poni can refuse. It is the file that can state everything -
// the verdict, the uncertainty, and a geometry a PONI has no fields for - so it must exist
// even where the poni cannot be written, and it is wanted most exactly when the fit failed.
// WritePoniFile refuses a detector whose image orientation a PONI cannot express; refusing
// by throwing would otherwise take the JSON with it and leave a run whose own error text
// says "the .json beside it carries the full geometry" beside no .json at all.
WriteCalibrationJson(json_path, experiment, cal, calibrant_label,
calibration_method == CalibrationMethod::Rings ? "rings" : "spots");
// A .poni file states where the detector is and nothing else. It has no field for doubt, so
// there is no honest way to write a geometry that is not a measurement into one - every
// program that reads it downstream would read it as if it were.
if (cal.converged)
WritePoniFile(poni_path, experiment, g);
} catch (const std::exception &e) {
logger.Error("{}", e.what());
return 1;