From 834cb48e0f8787a875be6621edbe291efbbf4d3e Mon Sep 17 00:00:00 2001 From: "Aaron S. Brewster" Date: Wed, 30 Oct 2024 16:44:30 -0700 Subject: [PATCH] NXmx: read data_scale_factor (#756) New parameter as of nexusformat/definitions#1343. This is not full support of the parameter or of data_offset, but it's one of the use cases needed, namely reading a single gain value Co-authored-by: Nicholas Devenish --- dependencies.yaml | 2 +- newsfragments/756.feature | 1 + src/dxtbx/format/FormatNXmx.py | 6 ++++-- src/dxtbx/nexus/__init__.py | 4 ++++ tests/nexus/test_mpccd_nexus.py | 24 ++++++++++++++++++++++++ 5 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 newsfragments/756.feature create mode 100644 tests/nexus/test_mpccd_nexus.py diff --git a/dependencies.yaml b/dependencies.yaml index 3d0eb8790..6b7b1876b 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -74,7 +74,7 @@ run: - mrcfile - natsort - {{ pin_compatible('numpy') }} # [not bootstrap] - - nxmx + - nxmx >=0.0.4 - orderedset - pint - pycbf # [prebuilt_cctbx] diff --git a/newsfragments/756.feature b/newsfragments/756.feature new file mode 100644 index 000000000..3b3f6e056 --- /dev/null +++ b/newsfragments/756.feature @@ -0,0 +1 @@ +Add support for reading the detector gain for nexus files diff --git a/src/dxtbx/format/FormatNXmx.py b/src/dxtbx/format/FormatNXmx.py index 55b5879a5..c57e0de4f 100644 --- a/src/dxtbx/format/FormatNXmx.py +++ b/src/dxtbx/format/FormatNXmx.py @@ -68,10 +68,13 @@ def _start(self): nxinstrument = nxentry.instruments[0] nxdetector = nxinstrument.detectors[0] nxbeam = nxinstrument.beams[0] + nxdata = nxmx_obj.entries[0].data[0] self._goniometer_model = dxtbx.nexus.get_dxtbx_goniometer(nxsample) self._beam_factory = dxtbx.nexus.CachedWavelengthBeamFactory(nxbeam) wavelength = self._beam_factory.make_beam(index=0).get_wavelength() - self._detector_model = dxtbx.nexus.get_dxtbx_detector(nxdetector, wavelength) + self._detector_model = dxtbx.nexus.get_dxtbx_detector( + nxdetector, wavelength, nxdata + ) # if the detector is between the sample and the source, and perpendicular # to the beam, then invert the distance vector, as this is probably wrong @@ -86,7 +89,6 @@ def _start(self): if self._scan_model: self._num_images = len(self._scan_model) else: - nxdata = nxmx_obj.entries[0].data[0] if nxdata.signal: data = nxdata[nxdata.signal] else: diff --git a/src/dxtbx/nexus/__init__.py b/src/dxtbx/nexus/__init__.py index e506e3aca..2e3938e79 100644 --- a/src/dxtbx/nexus/__init__.py +++ b/src/dxtbx/nexus/__init__.py @@ -245,6 +245,7 @@ def get_dxtbx_scan( def get_dxtbx_detector( nxdetector: nxmx.NXdetector, wavelength: float, + nxdata: nxmx.NXdata | None = None, ) -> dxtbx.model.Detector: """Generate a dxtbx detector model from an NXdetector and NXbeam. @@ -461,6 +462,9 @@ def equipment_component_key(dependency): p.set_mu(mu) p.set_px_mm_strategy(px_mm) + if nxdata and nxdata.data_scale_factor and not nxdata.data_scale_factor.shape: + p.set_gain(1 / nxdata.data_scale_factor) + return detector diff --git a/tests/nexus/test_mpccd_nexus.py b/tests/nexus/test_mpccd_nexus.py new file mode 100644 index 000000000..433924b4b --- /dev/null +++ b/tests/nexus/test_mpccd_nexus.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +import dxtbx + + +def test_mpccd_nexus_gain(dials_data): + """ + Tests SACLA MPCCD image from CXI.DB 221 + Includes parameter data_scale_factor, which accounts for a gain of 10 + """ + + try: + h5path = ( + dials_data("image_examples", pathlib=True) + / "SACLA-MPCCD-run197287-0-nexus.h5" + ) + except Exception as e: + print(type(e), str(e)) + raise + img = dxtbx.load(h5path) + + d = img.get_detector() + + assert d[0].get_gain() == 10