Commit 7d378324 authored by Henri Payno's avatar Henri Payno
Browse files

H52nx: add sample pixel size to be able to compute scan and volume bounding box which has meaning

parent ae02d46b
Pipeline #74746 failed with stages
in 15 seconds
......@@ -82,6 +82,7 @@ class StandardAcquisition(BaseAcquisition):
configuration: TomoHDF5Config,
detector_sel_callback,
start_index,
parent=None,
):
super().__init__(
root_url=root_url,
......@@ -89,6 +90,8 @@ class StandardAcquisition(BaseAcquisition):
detector_sel_callback=detector_sel_callback,
start_index=start_index,
)
self._parent = parent
# possible parent. Like for z series
self._nx_tomos = [NXtomo("/")]
self._image_key_control = None
self._rotation_angle = None
......@@ -109,6 +112,12 @@ class StandardAcquisition(BaseAcquisition):
"register dataset copied. Key if the original location as" "DataUrl.path. Value is the DataUrl it has been moved to"
# self._current_scan_n_frame = None
def parent_root_url(self) -> Optional[DataUrl]:
if self._parent is not None:
return self._parent.root_url
else:
return None
def get_expected_nx_tomo(self):
return 1
......@@ -674,14 +683,26 @@ class StandardAcquisition(BaseAcquisition):
"""return tuple(pixel_size, unit)"""
if self.root_url is None:
return None, None
assert axis in ("x", "y")
if axis not in ("x", "y", "sample_x", "sample_y"):
raise ValueError
self._check_has_metadata()
keys = (
self.configuration.x_pixel_size_paths
if axis == "x"
else self.configuration.y_pixel_size_paths
)
with self.read_entry() as entry:
if axis == "x":
keys = self.configuration.x_pixel_size_paths
url = self.root_url
elif axis == "y":
keys = self.configuration.y_pixel_size_paths
url = self.root_url
elif axis == "sample_x":
keys = self.configuration.sample_x_pixel_size_paths
url = self.parent_root_url()
elif axis == "sample_y":
keys = self.configuration.sample_y_pixel_size_paths
url = self.parent_root_url()
else:
raise ValueError()
with EntryReader(url) as entry:
for key in keys:
if key in entry:
node = entry[key]
......@@ -821,6 +842,22 @@ class StandardAcquisition(BaseAcquisition):
if unit is not None:
nx_tomo.instrument.detector.y_pixel_size.unit = unit
# x and y sample pixel size
sample_x_pixel_size, unit = self._get_pixel_size(
axis="sample_x",
)
nx_tomo.instrument.detector.sample_x_pixel_size = sample_x_pixel_size
if unit is not None:
nx_tomo.instrument.detector.sample_x_pixel_size.unit = unit
sample_y_pixel_size, unit = self._get_pixel_size(
axis="sample_y",
)
nx_tomo.instrument.detector.sample_y_pixel_size = sample_y_pixel_size
if unit is not None:
nx_tomo.instrument.detector.sample_y_pixel_size.unit = unit
# fov
fov = self._get_field_of_fiew()
if fov is not None:
nx_tomo.instrument.detector.field_of_view = fov
......
......@@ -154,6 +154,7 @@ class ZSeriesBaseAcquisition(BaseAcquisition):
configuration=self.configuration,
detector_sel_callback=self._detector_sel_callback,
start_index=self.start_index + len(self._acquisitions),
parent=self,
)
self._acquisitions[z].register_step(
url=url, entry_type=entry_type, copy_frames=copy_frames
......
......@@ -348,6 +348,8 @@ class TomoHDF5Config(ConfigBase):
self._alignment_titles = settings.Tomo.H5.ALIGNMENT_TITLES
self._x_pixel_size_paths = settings.Tomo.H5.X_PIXEL_SIZE
self._y_pixel_size_paths = settings.Tomo.H5.Y_PIXEL_SIZE
self._sample_x_pixel_size_paths = settings.Tomo.H5.SAMPLE_X_PIXEL_SIZE_KEYS
self._sample_y_pixel_size_paths = settings.Tomo.H5.SAMPLE_Y_PIXEL_SIZE_KEYS
# information regarding frames types definition
self._data_grps_urls = tuple()
......@@ -663,6 +665,28 @@ class TomoHDF5Config(ConfigBase):
else:
self._y_pixel_size_paths = paths
@property
def sample_x_pixel_size_paths(self) -> Iterable:
return self._sample_x_pixel_size_paths
@sample_x_pixel_size_paths.setter
def sample_x_pixel_size_paths(self, paths):
if not isinstance(paths, Iterable):
raise TypeError("'paths should be an Iterable")
else:
self._sample_x_pixel_size_paths = paths
@property
def sample_y_pixel_size_paths(self) -> Iterable:
return self._sample_y_pixel_size_paths
@sample_y_pixel_size_paths.setter
def sample_y_pixel_size_paths(self, paths):
if not isinstance(paths, Iterable):
raise TypeError("'paths should be an Iterable")
else:
self._sample_y_pixel_size_paths = paths
@property
def sample_detector_distance_paths(self):
return self._sample_detector_distance_keys
......
......@@ -31,6 +31,7 @@ __date__ = "03/02/2022"
from functools import partial
from operator import is_not
from optparse import Option
from silx.utils.proxy import docstring
from silx.io.url import DataUrl
from h5py import VirtualSource
......@@ -84,7 +85,13 @@ class NXdetector(NXobject):
self._data = None
self.image_key_control = None
self._x_pixel_size = ElementWithUnit(default_unit=MetricSystem.METER)
# x detector size
self._y_pixel_size = ElementWithUnit(default_unit=MetricSystem.METER)
# y detector size
self._sample_x_pixel_size = ElementWithUnit(default_unit=MetricSystem.METER)
# x pixel size in sample ref
self._sample_y_pixel_size = ElementWithUnit(default_unit=MetricSystem.METER)
# y pixel size in sample ref
self._distance = ElementWithUnit(
default_unit=MetricSystem.METER
) # detector / sample distance
......@@ -153,6 +160,30 @@ class NXdetector(NXobject):
)
self._y_pixel_size.value = y_pixel_size
@property
def sample_x_pixel_size(self) -> Optional[float]:
return self._sample_x_pixel_size
@sample_x_pixel_size.setter
def sample_x_pixel_size(self, x_pixel_size: Optional[float]) -> None:
if not isinstance(x_pixel_size, (type(None), float)):
raise TypeError(
f"sample_x_pixel_size is expected ot be an instance of {float} or None. Not {type(x_pixel_size)}"
)
self._sample_x_pixel_size.value = x_pixel_size
@property
def sample_y_pixel_size(self) -> Optional[float]:
return self._sample_y_pixel_size
@sample_y_pixel_size.setter
def sample_y_pixel_size(self, y_pixel_size: Optional[float]) -> None:
if not isinstance(y_pixel_size, (type(None), float)):
raise TypeError(
f"sample_y_pixel_size is expected ot be an instance of {float} or None. Not {type(y_pixel_size)}"
)
self._sample_y_pixel_size.value = y_pixel_size
@property
def distance(self) -> Optional[float]:
"""
......@@ -261,6 +292,7 @@ class NXdetector(NXobject):
nx_dict = {}
# image key control
if self.image_key_control is not None:
path_img_key = f"{self.path}/{nexus_detector_paths.IMAGE_KEY}"
nx_dict[path_img_key] = [img_key.value for img_key in self.image_key]
......@@ -268,25 +300,49 @@ class NXdetector(NXobject):
nx_dict[path_img_key_ctrl] = [
img_key.value for img_key in self.image_key_control
]
# x pixel
if self.x_pixel_size.value is not None:
path_x_pixel_size = f"{self.path}/{nexus_detector_paths.X_PIXEL_SIZE}"
nx_dict[path_x_pixel_size] = self.x_pixel_size.value
nx_dict["@".join([path_x_pixel_size, "unit"])] = str(self.x_pixel_size.unit)
# y pixel
if self.y_pixel_size.value is not None:
path_y_pixel_size = f"{self.path}/{nexus_detector_paths.Y_PIXEL_SIZE}"
nx_dict[path_y_pixel_size] = self.y_pixel_size.value
nx_dict["@".join([path_y_pixel_size, "unit"])] = str(self.y_pixel_size.unit)
# sample x pixel
if self.sample_x_pixel_size.value is not None:
path_sample_x_pixel_size = (
f"{self.path}/{nexus_detector_paths.SAMPLE_X_PIXEL_SIZE}"
)
nx_dict[path_sample_x_pixel_size] = self.sample_x_pixel_size.value
nx_dict["@".join([path_sample_x_pixel_size, "unit"])] = str(
self.sample_x_pixel_size.unit
)
# sample y pixel
if self.sample_y_pixel_size.value is not None:
path_sample_y_pixel_size = (
f"{self.path}/{nexus_detector_paths.SAMPLE_Y_PIXEL_SIZE}"
)
nx_dict[path_sample_y_pixel_size] = self.sample_y_pixel_size.value
nx_dict["@".join([path_sample_y_pixel_size, "unit"])] = str(
self.sample_y_pixel_size.unit
)
# distance
if self.distance.value is not None:
path_distance = f"{self.path}/{nexus_detector_paths.DISTANCE}"
nx_dict[path_distance] = self.distance.value
nx_dict["@".join([path_distance, "unit"])] = str(self.distance.unit)
# FOV
if self.field_of_view is not None:
path_fov = f"{self.path}/{nexus_detector_paths.FOV}"
nx_dict[path_fov] = self.field_of_view.value
# count time
if self.count_time.value is not None:
path_count_time = f"{self.path}/{nexus_detector_paths.EXPOSURE_TIME}"
nx_dict[path_count_time] = self.count_time.value
nx_dict["@".join([path_count_time, "unit"])] = str(self.count_time.unit)
# tomo n
if self.tomo_n is not None:
tomo_n_fov_path = f"{nexus_paths.TOMO_N_SCAN}"
nx_dict[tomo_n_fov_path] = self.tomo_n
......@@ -422,6 +478,16 @@ class NXdetector(NXobject):
data_path="/".join([data_path, nexus_detector_paths.Y_PIXEL_SIZE]),
default_unit=MetricSystem.METER,
)
self.sample_x_pixel_size, self.sample_x_pixel_size.unit = get_data_and_unit(
file_path=file_path,
data_path="/".join([data_path, nexus_detector_paths.SAMPLE_X_PIXEL_SIZE]),
default_unit=MetricSystem.METER,
)
self.sample_y_pixel_size, self.sample_y_pixel_size.unit = get_data_and_unit(
file_path=file_path,
data_path="/".join([data_path, nexus_detector_paths.SAMPLE_Y_PIXEL_SIZE]),
default_unit=MetricSystem.METER,
)
self.distance, self.distance.unit = get_data_and_unit(
file_path=file_path,
data_path="/".join([data_path, nexus_detector_paths.DISTANCE]),
......
......@@ -104,8 +104,6 @@ class Tomo:
alignment scan"""
X_PIXEL_SIZE = (
"technique/optic/sample_pixel_size ",
"technique/optic/sample_pixel_size",
"technique/detector/pixel_size",
"hry_step_size",
)
......@@ -113,12 +111,22 @@ class Tomo:
# warning: we can have two cases: one with an empty space at the end or not
Y_PIXEL_SIZE = (
"technique/optic/sample_pixel_size ",
"technique/optic/sample_pixel_size",
"technique/detector/pixel_size",
"hry_step_size",
)
SAMPLE_X_PIXEL_SIZE_KEYS = (
"technique/optic/sample_pixel_size ",
"technique/optic/sample_pixel_size",
)
SAMPLE_Y_PIXEL_SIZE_KEYS = (
"technique/optic/sample_pixel_size ",
"technique/optic/sample_pixel_size",
)
MAGNIFICATION_KEYS = ("technique/optic/maginification",)
DISTANCE_KEYS = ("technique/scan/sample_detector_distance",)
"""keys used by bliss to store the sample to detector distance"""
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment