From 4026ebc6ab5c150ef13338ceee03a98f7a4a3d0d Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Tue, 1 Sep 2026 18:58:38 +0200 Subject: [PATCH] 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) Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N --- writer/HDF5NXmx.cpp | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/writer/HDF5NXmx.cpp b/writer/HDF5NXmx.cpp index e3bb7b837..1010833a8 100644 --- a/writer/HDF5NXmx.cpp +++ b/writer/HDF5NXmx.cpp @@ -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(rot1)) - .PoniRot2_rad(static_cast(rot2)) - .PoniRot3_rad(static_cast(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(rot1)) + .PoniRot2_rad(static_cast(rot2)) + .PoniRot3_rad(static_cast(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");