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

Additional methods for FormatISISSXD to extract data more efficiently. #743

Merged
merged 10 commits into from
Aug 12, 2024
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])
Loading