From 96edee9b2d8e6fe08d305f54d5b3c5027adac7a3 Mon Sep 17 00:00:00 2001 From: leonarski_f Date: Mon, 8 Jun 2026 15:47:12 +0200 Subject: [PATCH] jfjoch_writer: Add incident_wavelength_spread --- common/DiffractionExperiment.cpp | 5 +++++ common/JFJochMessages.h | 1 + docs/CBOR.md | 1 + frame_serialize/CBORStream2Deserializer.cpp | 2 ++ frame_serialize/CBORStream2Serializer.cpp | 1 + writer/HDF5NXmx.cpp | 2 ++ 6 files changed, 12 insertions(+) diff --git a/common/DiffractionExperiment.cpp b/common/DiffractionExperiment.cpp index 6b1a3b66..3fac1a9c 100644 --- a/common/DiffractionExperiment.cpp +++ b/common/DiffractionExperiment.cpp @@ -641,6 +641,11 @@ void DiffractionExperiment::FillMessage(StartMessage &message) const { message.beam_center_y = GetBeamY_pxl(); message.detector_distance = GetDetectorDistance_mm() * 1e-3f; message.incident_wavelength = GetWavelength_A(); + // NXmx incident_wavelength_spread is the FWHM of the wavelength distribution, + // in wavelength units. We store bandwidth as a relative FWHM (dlambda/lambda), + // so convert to absolute: dlambda = (dlambda/lambda) * lambda. + if (const auto bw = GetBandwidthFWHM()) + message.incident_wavelength_spread = bw.value() * GetWavelength_A(); message.incident_energy = GetIncidentEnergy_keV() * 1e3f; message.image_size_x = GetXPixelsNum(); message.image_size_y = GetYPixelsNum(); diff --git a/common/JFJochMessages.h b/common/JFJochMessages.h index aa0b703f..067f938c 100644 --- a/common/JFJochMessages.h +++ b/common/JFJochMessages.h @@ -208,6 +208,7 @@ struct StartMessage { float incident_energy; float incident_wavelength; + std::optional incident_wavelength_spread; // NXmx incident_wavelength_spread: FWHM of dlambda (Angstrom) float frame_time; float count_time; diff --git a/docs/CBOR.md b/docs/CBOR.md index bdca03d4..58339cc6 100644 --- a/docs/CBOR.md +++ b/docs/CBOR.md @@ -27,6 +27,7 @@ There are minor differences at the moment: | image_size_y | uint64 | Image height \[pixels\] | X | | incident_energy | float | X-ray energy \[eV\] | X | | incident_wavelength | float | X-ray wavelength \[Angstrom\] | X | +| incident_wavelength_spread | float (optional) | FWHM of the X-ray wavelength distribution \[Angstrom\] (NXmx incident_wavelength_spread); omitted when the beam is monochromatic | | | frame_time | float | Frame time, if multiple frames per trigger \[s\] | X | | count_time | float | Exposure time \[s\] | X | | saturation_value | int64 | Maximum valid sample value | X | diff --git a/frame_serialize/CBORStream2Deserializer.cpp b/frame_serialize/CBORStream2Deserializer.cpp index 0d2c70ae..2a598de6 100644 --- a/frame_serialize/CBORStream2Deserializer.cpp +++ b/frame_serialize/CBORStream2Deserializer.cpp @@ -1182,6 +1182,8 @@ namespace { message.incident_energy = GetCBORFloat(value); else if (key == "incident_wavelength") message.incident_wavelength = GetCBORFloat(value); + else if (key == "incident_wavelength_spread") + message.incident_wavelength_spread = GetCBORFloat(value); else if (key == "frame_time") message.frame_time = GetCBORFloat(value); else if (key == "count_time") diff --git a/frame_serialize/CBORStream2Serializer.cpp b/frame_serialize/CBORStream2Serializer.cpp index 6debfc5c..a79370f1 100644 --- a/frame_serialize/CBORStream2Serializer.cpp +++ b/frame_serialize/CBORStream2Serializer.cpp @@ -632,6 +632,7 @@ void CBORStream2Serializer::SerializeSequenceStart(const StartMessage& message) CBOR_ENC(mapEncoder, "incident_energy", message.incident_energy); CBOR_ENC(mapEncoder, "incident_wavelength", message.incident_wavelength); + CBOR_ENC(mapEncoder, "incident_wavelength_spread", message.incident_wavelength_spread); CBOR_ENC(mapEncoder, "frame_time", message.frame_time); CBOR_ENC(mapEncoder, "count_time", message.count_time); diff --git a/writer/HDF5NXmx.cpp b/writer/HDF5NXmx.cpp index d2a3372d..2196dd56 100644 --- a/writer/HDF5NXmx.cpp +++ b/writer/HDF5NXmx.cpp @@ -480,6 +480,8 @@ void NXmx::Beam(const StartMessage &start) { HDF5Group group(*hdf5_file, "/entry/instrument/beam"); group.NXClass("NXbeam"); SaveScalar(group, "incident_wavelength", start.incident_wavelength)->Units("angstrom"); + if (start.incident_wavelength_spread) + SaveScalar(group, "incident_wavelength_spread", start.incident_wavelength_spread.value())->Units("angstrom"); if (start.total_flux) SaveScalar(group, "total_flux", start.total_flux.value())->Units("Hz"); }