Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NXmx: handle multidimensional arrays #612

Merged
merged 10 commits into from
Aug 11, 2023
1 change: 1 addition & 0 deletions newsfragments/612.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NeXus: handle dataset with multiple modules stored as multidimensional arrays
29 changes: 20 additions & 9 deletions src/dxtbx/nexus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import itertools
import logging
from typing import Literal, Optional, Tuple, cast
from typing import Literal, Optional

import h5py
import numpy as np
Expand Down Expand Up @@ -404,9 +404,13 @@ def equipment_component_key(dependency):
origin -= nxdetector.beam_center_y.magnitude * pixel_size[1] * slow_axis

# dxtbx requires image size in the order fast, slow - which is the reverse of what
# is stored in module.data_size
image_size = cast(Tuple[int, int], tuple(map(int, module.data_size[::-1])))
assert len(image_size) == 2
# is stored in module.data_size. Additionally, data_size can have more than 2
# dimensions, for multi-module detectors. So take the last two dimensions and reverse
# them. Examples:
# [1,2,3,4] --> (4, 3)
rjgildea marked this conversation as resolved.
Show resolved Hide resolved
# [1,2,3] --> (3, 2)
# [1,2] --> (2, 1)
image_size = (int(module.data_size[-1]), int(module.data_size[-2]))
underload = (
float(nxdetector.underload_value)
if nxdetector.underload_value is not None
Expand Down Expand Up @@ -475,13 +479,17 @@ def get_static_mask(nxdetector: nxmx.NXdetector) -> tuple[flex.bool, ...] | None
pixel_mask = nxdetector.pixel_mask
except KeyError:
return None
if pixel_mask is None or not pixel_mask.size or pixel_mask.ndim != 2:
if pixel_mask is None or not pixel_mask.size:
return None
all_slices = get_detector_module_slices(nxdetector)
return tuple(
flumpy.from_numpy(np.ascontiguousarray(pixel_mask[slices])) == 0
for slices in all_slices
)
all_mask_slices = []
for slices in all_slices:
mask_slice = flumpy.from_numpy(np.ascontiguousarray(pixel_mask[slices])) == 0
mask_slice.reshape(
flex.grid(mask_slice.all()[-2:])
) # handle 3 or 4 dimension arrays
all_mask_slices.append(mask_slice)
return tuple(all_mask_slices)


def _dataset_as_flex(
Expand Down Expand Up @@ -562,5 +570,8 @@ def get_raw_data(
data_as_flex = _dataset_as_flex(
sliced_outer, tuple(module_slices), bit_depth=bit_depth
)
data_as_flex.reshape(
flex.grid(data_as_flex.all()[-2:])
) # handle 3 or 4 dimension arrays
all_data.append(data_as_flex)
return tuple(all_data)