rugnux: report the geometry in the form the broker takes it in

A rotation run post-refines the detector distance and the beam centre, and that
is usually the best measurement of them anyone has - but the only way back into
the instrument was to read two numbers off the report by eye and retype them
into a collection.

Write them once more, as the object jfjoch_broker takes: the four required
properties of dataset_settings in broker/jfjoch_api.yaml, spelled the way the
API spells them, on one line of valid JSON that a script can lift with a grep
and POST. The existing DETECTOR_DISTANCE and BEAM_CENTRE keys are unchanged and
stay the ones a person reads. REPORT_VERSION is not bumped: a new key breaks no
consumer of the old ones.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FBumeJVx4oeXxiBRpkrE5H
This commit is contained in:
2026-08-28 10:49:18 +02:00
co-authored by Claude Opus 5
parent 42add7c0e2
commit fe1f3ba96e
3 changed files with 32 additions and 1 deletions
+1
View File
@@ -1,6 +1,7 @@
# Changelog
## 1.0.0
### 1.0.0-rc.166
* The rugnux results report carries `JFJOCH_DATASET_SETTINGS=`, the geometry the run integrated at written as one line of JSON in the form `jfjoch_broker` takes it, so a refined beam centre and distance can be carried back to the instrument.
* `/entry/MX/strongPixels` and the strong-pixel plot are filled on the CPU/GPU analysis path, not only behind the FPGA, so an image the spot finder gave up on can be told from one that did not diffract.
* The spot-finding resolution estimate is no longer capped at the corner of the detector, so a crystal that diffracts past the edge is reported as reaching past it, and a run where the estimate is finer than what was merged is a detector-limited run.
* Spot finding no longer throws away a whole image when it holds many strong pixels: the limit follows the detector (one pixel in 64) instead of standing at the 65535 that suited a 4-megapixel detector, which a strongly diffracting crystal on an 18-megapixel one passes on its best frames.
+16 -1
View File
@@ -564,7 +564,22 @@ keep their numbers.
**`SPOT_RESOLUTION_ESTIMATE=`** in section 1 is how far the merged data are expected to reach, read
off the found spots alone — no lattice, no integration, no merge — so it is there on a run that never
merges, and on a run that does it can be read against `INCLUDE_RESOLUTION_RANGE` in section 5. It is a
prediction, good to about 0.2 Å on rotation data; nothing is cut on it.
prediction, good to about 0.2 Å on rotation data; nothing is cut on it. It is **not** limited to what
the detector records: where it reads finer than the high-resolution end of `INCLUDE_RESOLUTION_RANGE`,
the crystal diffracts past the corner and the run was detector-limited.
**`JFJOCH_DATASET_SETTINGS=`** in section 1 is the geometry the run integrated at — on a rotation run
the post-refined one — written as the object `jfjoch_broker` takes it in: the four required properties
of `dataset_settings` in `broker/jfjoch_api.yaml`, on one line of valid JSON, so a refined beam centre
and distance can go back to the instrument for the next collection without anyone retyping them.
```
JFJOCH_DATASET_SETTINGS= {"beam_x_pxl": 2078.24, "beam_y_pxl": 2233.92, "detector_distance_mm": 190.311, "incident_energy_keV": 12.4000}
```
```bash
grep '^JFJOCH_DATASET_SETTINGS=' out_report.txt | cut -d' ' -f2- > geometry.json
```
**Which pass.** A rotation run integrates twice — once at the geometry in the input file, then again
at the post-refined geometry — and can integrate a third time if a guard rejects the second pass.
+15
View File
@@ -95,6 +95,21 @@ std::string RenderResultReport(const std::string &output_prefix,
<< " The distance and beam centre above are the ones this result was integrated at, which on\n"
<< " a rotation run is the post-refined geometry rather than the values in the input file.\n";
// The same geometry once more, as the object jfjoch_broker takes it in: the four required
// properties of dataset_settings in broker/jfjoch_api.yaml, spelled the way the API spells them.
// A run that refined the geometry is usually the best measurement of it anyone has, and without
// this the only way back into the instrument is to read two numbers off this report by eye and
// retype them. One line, valid JSON, so a script can lift it with a grep and POST it.
os << "\n";
Key(os, "JFJOCH_DATASET_SETTINGS",
fmt::format(R"({{"beam_x_pxl": {:.2f}, "beam_y_pxl": {:.2f}, "detector_distance_mm": {:.3f}, )"
R"("incident_energy_keV": {:.4f}}})",
result.used_beam_x_pxl, result.used_beam_y_pxl, result.used_distance_mm,
experiment.GetDatasetSettings().GetPhotonEnergy_keV()));
os << "\n"
<< " The geometry above as jfjoch_broker's dataset_settings, to carry a refined beam centre and\n"
<< " distance back to the instrument for the next collection.\n";
if (result.spot_resolution_estimate_A.has_value()) {
os << "\n";
Key(os, "SPOT_RESOLUTION_ESTIMATE", fmt::format("{:.2f}", *result.spot_resolution_estimate_A));