Skip to content

Commit

Permalink
Additional methods for FormatISISSXD to extract proton charge, goniom…
Browse files Browse the repository at this point in the history
…eter angles, and data flattened along the ToF direction.
  • Loading branch information
toastisme committed Aug 9, 2024
1 parent 3102224 commit 772bfcc
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 10 deletions.
1 change: 1 addition & 0 deletions newsfragments/XXX.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Additional methods for FormatISISSXD to extract proton charge, goniometer angles, and data flattened along the ToF direction.
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 772bfcc

Please sign in to comment.