Skip to content

Commit

Permalink
Additional methods for FormatISISSXD to extract data more efficiently. (
Browse files Browse the repository at this point in the history
  • Loading branch information
toastisme authored Aug 12, 2024
1 parent 3102224 commit aebb3d9
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 10 deletions.
1 change: 1 addition & 0 deletions newsfragments/743.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Additional methods for FormatISISSXD to extract data more efficiently.
95 changes: 85 additions & 10 deletions src/dxtbx/format/FormatISISSXD.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import List, Tuple

import h5py
import numpy as np

import cctbx.array_family.flex as flex

Expand Down Expand Up @@ -44,6 +45,9 @@ def get_name(image_file: str) -> str:

return get_name(image_file) == "SXD"

def get_instrument_name(self) -> str:
return "SXD"

def get_experiment_title(self) -> str:
return self._nxs_file["raw_data_1"]["title"][0].decode()

Expand All @@ -55,23 +59,26 @@ def get_experiment_description(self) -> str:
run_number = self.get_experiment_run_number()
return f"{title} ({run_number})"

def get_goniometer(self, idx: int = None) -> Goniometer:
rotation_axis = (0.0, 1.0, 0.0)
fixed_rotation = (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
goniometer = GoniometerFactory.make_goniometer(rotation_axis, fixed_rotation)
def get_goniometer_phi_angle(self) -> float:
try:
experiment_title = self.get_experiment_title()
if "w=" in experiment_title:
angle = float(experiment_title().split("w=")[1].split()[0])
return float(experiment_title.split("w=")[1].split()[0])
elif "wccr" in experiment_title:
angle = float(experiment_title.split("wccr=")[1].split()[0])
return float(experiment_title.split("wccr=")[1].split()[0])
elif "wtl" in experiment_title:
angle = float(experiment_title.split("wtl=")[1].split()[0])
return float(experiment_title.split("wtl=")[1].split()[0])
else:
return goniometer
goniometer.rotate_around_origin(rotation_axis, angle)
return 0
except (ValueError, IndexError):
pass
return 0

def get_goniometer(self, idx: int = None) -> Goniometer:
rotation_axis = (0.0, 1.0, 0.0)
fixed_rotation = (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
goniometer = GoniometerFactory.make_goniometer(rotation_axis, fixed_rotation)
angle = self.get_goniometer_phi_angle()
goniometer.rotate_around_origin(rotation_axis, angle)
return goniometer

def get_detector(self, index: int = None) -> Detector:
Expand Down Expand Up @@ -313,3 +320,71 @@ def get_raw_data(self, index: int, use_loaded_data=True) -> Tuple[flex.int]:
raw_data.append(panel_data)

return tuple(raw_data)

def get_flattened_data(
self, image_range: None | Tuple = None, scale_data: bool = True
) -> Tuple[flex.int]:
"""
Image data summed along the time-of-flight direction
"""

panel_size = self._get_image_size()
total_pixels = panel_size[0] * panel_size[1]
# Panel positions are offset by 4 in raw_data array
# See p24 of https://www.isis.stfc.ac.uk/Pages/sxd-user-guide6683.pdf
idx_offset = 4
max_val = None
num_tof_bins = len(self._get_time_of_flight())
raw_data = []
for panel_idx in range(self._get_num_panels()):
start_idx = (panel_idx * total_pixels) + (panel_idx * idx_offset)
end_idx = start_idx + total_pixels
panel_data = self._nxs_file["raw_data_1/detector_1/counts"][
0, start_idx:end_idx, :
]
panel_data = np.reshape(
panel_data, (panel_size[0], panel_size[1], num_tof_bins)
)
if image_range is not None:
assert (
len(image_range) == 2
), "expected image_range to be only two values"
assert (
image_range[0] >= 0 and image_range[0] < image_range[1]
), "image_range[0] out of range"
assert image_range[1] <= num_tof_bins, "image_range[1] out of range"
panel_data = np.flipud(
np.sum(panel_data[:, :, image_range[0] : image_range[1]], axis=2)
)
else:
panel_data = np.flipud(np.sum(panel_data, axis=2))
if panel_idx == 0 and self._panel_0_flipped():
panel_data = np.flipud(panel_data)
panel_max_val = np.max(panel_data)
if max_val is None or max_val < panel_max_val:
max_val = panel_max_val
raw_data.append(panel_data)

if scale_data:
return tuple([(i / max_val).tolist() for i in raw_data])

return tuple([i.tolist() for i in raw_data])

def get_flattened_pixel_data(
self, panel_idx: int, x: int, y: int
) -> Tuple[Tuple, Tuple]:
time_channels = self._get_time_of_flight()
panel_size = self._get_image_size()
height = panel_size[1]
total_pixels = panel_size[0] * panel_size[1]
# Panel positions are offset by 4 in raw_data array
# See p24 of https://www.isis.stfc.ac.uk/Pages/sxd-user-guide6683.pdf
idx_offset = 4
idx = (panel_idx * total_pixels) + (panel_idx * idx_offset) + y * height + x
return (
time_channels,
tuple(self._nxs_file["raw_data_1/detector_1/counts"][0, idx, :].tolist()),
)

def get_proton_charge(self):
return float(self._nxs_file["raw_data_1/proton_charge"][0])

0 comments on commit aebb3d9

Please sign in to comment.