writer: the direct beam is absent where there is no geometry, not fatal

Computing it needs a DiffractionGeometry, and that refuses a detector distance under 1 mm or a pixel
size of zero. A start message can legitimately carry neither: the writer's own pre-flight check asks
it to prove it can create the files for a dataset that never describes a detector, and the master
write then threw where it used to succeed - Preflight_TCP fails at rc.166 and passes at rc.165.

The dataset is a convenience for whoever reads the file later, so where the geometry is not there to
compute it from it is simply not written. Everything else in the master 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:
2026-09-01 18:58:38 +02:00
co-authored by Claude Opus 5
parent 8650ac1c59
commit 4026ebc6ab
+22 -15
View File
@@ -659,21 +659,28 @@ void NXmx::Metrology(const StartMessage &start, const EndMessage &end) {
// the sample - so on a tilted detector it is not the beam position, and a program that wants the
// beam position (XDS's ORGX/ORGY, for one) would otherwise have to redo the tilt arithmetic. Built
// from the very values written just above and just below, so the three can never disagree.
DiffractionGeometry geometry;
geometry.BeamX_pxl(beam_center_x)
.BeamY_pxl(beam_center_y)
.DetectorDistance_mm(start.detector_distance * 1e3f)
.PixelSize_mm(start.pixel_size_x * 1e3f)
.Orientation(DetectorOrientation(start.detector_orientation_mirror_y,
start.detector_orientation_quarter_turns))
.PoniRot1_rad(static_cast<float>(rot1))
.PoniRot2_rad(static_cast<float>(rot2))
.PoniRot3_rad(static_cast<float>(rot3));
const auto direct_beam = geometry.GetDirectBeam_pxl();
SaveScalar(*hdf5_file, "/entry/instrument/detector/detectorSpecific/direct_beam_x",
direct_beam.first)->Units("pixel");
SaveScalar(*hdf5_file, "/entry/instrument/detector/detectorSpecific/direct_beam_y",
direct_beam.second)->Units("pixel");
//
// Only where there is a geometry to compute it from. DiffractionGeometry refuses a distance under
// 1 mm or a pixel size of zero, and a message can legitimately carry neither - a writer told to
// prove it can create the files never describes a detector. This dataset is a convenience for
// whoever reads the file later, so it is absent there rather than fatal.
if (start.detector_distance * 1e3f >= 1.0f && start.pixel_size_x > 0.0f) {
DiffractionGeometry geometry;
geometry.BeamX_pxl(beam_center_x)
.BeamY_pxl(beam_center_y)
.DetectorDistance_mm(start.detector_distance * 1e3f)
.PixelSize_mm(start.pixel_size_x * 1e3f)
.Orientation(DetectorOrientation(start.detector_orientation_mirror_y,
start.detector_orientation_quarter_turns))
.PoniRot1_rad(static_cast<float>(rot1))
.PoniRot2_rad(static_cast<float>(rot2))
.PoniRot3_rad(static_cast<float>(rot3));
const auto direct_beam = geometry.GetDirectBeam_pxl();
SaveScalar(*hdf5_file, "/entry/instrument/detector/detectorSpecific/direct_beam_x",
direct_beam.first)->Units("pixel");
SaveScalar(*hdf5_file, "/entry/instrument/detector/detectorSpecific/direct_beam_y",
direct_beam.second)->Units("pixel");
}
HDF5Group transformations(*hdf5_file, "/entry/instrument/detector/transformations");
transformations.NXClass("NXtransformations");