From 456f3a8d8c5f9a6b9b26c324fb0f4b3758971889 Mon Sep 17 00:00:00 2001 From: Clatlan Date: Wed, 22 May 2024 18:02:28 +0200 Subject: [PATCH 01/13] implement geometry for NanoMAX beamline --- cdiutils/geometry.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cdiutils/geometry.py b/cdiutils/geometry.py index 8d846a69..02c8c084 100644 --- a/cdiutils/geometry.py +++ b/cdiutils/geometry.py @@ -39,7 +39,7 @@ def from_setup(cls, beamline_setup: str) -> None: """Create a Geometry instance using a beamline name.""" # Note that we use CXI convention here - if beamline_setup in ("ID01", "ID01SPEC", "ID01BLISS"): + if beamline_setup.lower() in ("id01", "id01spec", "id01bliss"): return cls( sample_circles=["x-", "y-"], # eta, phi detector_circles=["y-", "x-"], # delta, nu @@ -47,7 +47,7 @@ def from_setup(cls, beamline_setup: str) -> None: detector_horizontal_orientation="x+", beam_direction=[1, 0, 0] ) - if "P10" in beamline_setup: + if "p10" in beamline_setup.lower(): return cls( sample_circles=["x-", "y-"], # om (or samth), phi detector_circles=["y+", "x-"], # del (or e2_t02), gam @@ -55,7 +55,7 @@ def from_setup(cls, beamline_setup: str) -> None: detector_horizontal_orientation="x+", beam_direction=[1, 0, 0] ) - if beamline_setup == "SIXS2022": + if beamline_setup.lower() == "sixs2022": return cls( sample_circles=["x-", "y+"], # mu, omega detector_circles=["y+", "x-"], # gamma, delta @@ -63,6 +63,14 @@ def from_setup(cls, beamline_setup: str) -> None: detector_horizontal_orientation="x+", beam_direction=[1, 0, 0] ) + if beamline_setup.lower() == "nanomax": + return cls( + sample_circles=["x-", "y-"], # gontheta, gonphi + detector_circles=["y-", "x-"], # delta, gamma + detector_vertical_orientation="y-", + detector_horizontal_orientation="x+", + beam_direction=[1, 0, 0] + ) raise NotImplementedError( f"The beamline_setup {beamline_setup} is not valid. Available:\n" "'ID01', 'ID01SPEC', 'ID01BLISS', 'P10' , 'SIXS2022'" From 7e09ba3ece253c5ec733bcf259a15ad0af725034 Mon Sep 17 00:00:00 2001 From: Clatlan Date: Wed, 22 May 2024 18:03:14 +0200 Subject: [PATCH 02/13] general edits to remove repeated code block --- cdiutils/load/bliss.py | 16 +++++----------- cdiutils/load/loader.py | 34 ++++++++++++++++++++++++++++++++++ cdiutils/load/p10.py | 5 +---- cdiutils/load/sixs.py | 5 +---- cdiutils/load/spec.py | 5 +---- 5 files changed, 42 insertions(+), 23 deletions(-) diff --git a/cdiutils/load/bliss.py b/cdiutils/load/bliss.py index 3a15aa7d..de8464c3 100644 --- a/cdiutils/load/bliss.py +++ b/cdiutils/load/bliss.py @@ -4,7 +4,6 @@ import hdf5plugin import silx.io.h5py_utils -from cdiutils.utils import CroppingHandler from cdiutils.load import Loader @@ -23,10 +22,10 @@ class BlissLoader(Loader): """ angle_names = { - "sample_outofplane_angle": "eta", - "sample_inplane_angle": "phi", - "detector_outofplane_angle": "delta", - "detector_inplane_angle": "nu" + "sample_outofplane_angle": "eta", + "sample_inplane_angle": "phi", + "detector_outofplane_angle": "delta", + "detector_inplane_angle": "nu" } def __init__( @@ -79,12 +78,7 @@ def load_detector_data( + f".1/measurement/{self.detector_name}" ) - if roi is None: - roi = tuple(slice(None) for i in range(3)) - elif len(roi) == 2: - roi = tuple([slice(None), roi[0], roi[1]]) - elif all(isinstance(e, int) for e in roi): - roi = CroppingHandler.roi_list_to_slices(roi) + roi = self._check_roi(roi) try: if binning_along_axis0: diff --git a/cdiutils/load/loader.py b/cdiutils/load/loader.py index 3e59ebe8..cd1d6723 100644 --- a/cdiutils/load/loader.py +++ b/cdiutils/load/loader.py @@ -2,6 +2,8 @@ import numpy as np +from cdiutils.utils import CroppingHandler + class Loader: """A generic class for loaders.""" @@ -86,6 +88,38 @@ def _check_load(data_or_path: np.ndarray | str) -> np.ndarray: "parameter provide a path, np.ndarray or leave it to None" ) + def _check_roi(self, roi: tuple = None) -> tuple[slice]: + """ + Utility function to check if a region of interest (roi) was + parsed correctly. + + Args: + roi (tuple, optional): the roi, a tuple of slices. + len = 2 or len = 3 if tuple of slices. len = 4 or + len = 6 if tuple of int. Defaults to None. + + Raises: + ValueError: if roi does not correspond to tuple of slices + with len 2 or 3 or tuple of int wit len 4 or 6. + + Returns: + tuple[slice]: the prepared roi. + """ + usage_text = ( + "Wrong value for roi (roi={}), roi should be:\n" + "\t - either a tuple of slices with len = 2 or len = 3" + "\t - either a tuple of int with len = 4 or len = 6" + ) + if roi is None: + return tuple(slice(None) for _ in range(3)) + elif len(roi) == 2 or len(roi) == 3: + if all(isinstance(e, slice) for e in roi): + return tuple([slice(None), roi[0], roi[1]]) + elif len(roi) == 4 or len(roi) == 6: + if all(isinstance(e, int) for e in roi): + return CroppingHandler.roi_list_to_slices(roi) + raise ValueError(usage_text.format(roi)) + @staticmethod def get_mask( channel: int = None, diff --git a/cdiutils/load/p10.py b/cdiutils/load/p10.py index 544255d8..9f5e0417 100644 --- a/cdiutils/load/p10.py +++ b/cdiutils/load/p10.py @@ -127,10 +127,7 @@ def load_detector_data( path = self._get_file_path(scan, sample_name) key_path = "entry/data/data_000001" - if roi is None: - roi = tuple(slice(None) for i in range(3)) - elif len(roi) == 2: - roi = tuple([slice(None), roi[0], roi[1]]) + roi = self._check_roi(roi) with silx.io.h5py_utils.File(path) as h5file: if binning_along_axis0: diff --git a/cdiutils/load/sixs.py b/cdiutils/load/sixs.py index 0a47d327..51fcffc4 100644 --- a/cdiutils/load/sixs.py +++ b/cdiutils/load/sixs.py @@ -107,10 +107,7 @@ def load_detector_data( path = self._get_file_path(scan, sample_name) key_path = "com/scan_data/test_image" - if roi is None: - roi = tuple(slice(None) for i in range(3)) - elif len(roi) == 2: - roi = tuple([slice(None), roi[0], roi[1]]) + roi = self._check_roi(roi) with silx.io.h5py_utils.File(path) as h5file: if binning_along_axis0: diff --git a/cdiutils/load/spec.py b/cdiutils/load/spec.py index 3c7145ab..a8b0d98d 100644 --- a/cdiutils/load/spec.py +++ b/cdiutils/load/spec.py @@ -66,10 +66,7 @@ def load_detector_data( roi: tuple[slice] = None, binning_along_axis0=None ): - if roi is None: - roi = tuple(slice(None) for i in range(3)) - elif len(roi) == 2: - roi = tuple([slice(None), roi[0], roi[1]]) + roi = self._check_roi(roi) # TODO: implement flat_field consideration and binning_along_axis0 frame_ids = specfile[f"{scan}.1/measurement/{self.detector_name}"][...] From bfc53ed5098ed28799ffa962f043c64133a2ea7d Mon Sep 17 00:00:00 2001 From: Clatlan Date: Wed, 22 May 2024 18:03:27 +0200 Subject: [PATCH 03/13] initial commit --- cdiutils/load/nanomax.py | 106 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 cdiutils/load/nanomax.py diff --git a/cdiutils/load/nanomax.py b/cdiutils/load/nanomax.py new file mode 100644 index 00000000..37baa953 --- /dev/null +++ b/cdiutils/load/nanomax.py @@ -0,0 +1,106 @@ +""" + Loader for the Nanomax beamlien at MAXIV. + See: + https://www.maxiv.lu.se/beamlines-accelerators/beamlines/nanomax/ +""" + +import numpy as np + +from cdiutils.load import Loader +from cdiutils.load.bliss import safe + + +class NanoMaxLoader(Loader): + """ + A class to handle loading/reading .h5 files that were created using + on the NanoMax beamline. + + Args: + experiment_file_path (str): path to the master file + used for the experiment. + detector_name (str): name of the detector. + sample_name (str, optional): name of the sample. Defaults + to None. + flat_field (np.ndarray | str, optional): flat field to + account for the non homogeneous counting of the + detector. Defaults to None. + alien_mask (np.ndarray | str, optional): array to mask the + aliens. Defaults to None. + """ + + angle_names = { + "sample_outofplane_angle": "gontheta", + "sample_inplane_angle": "gonphi", + "detector_outofplane_angle": "delta", + "detector_inplane_angle": "nu" + } + + def __init__( + self, + experiment_file_path: str, + detector_name: str = "eiger500k", + sample_name: str = None, + flat_field: np.ndarray | str = None, + alien_mask: np.ndarray | str = None, + **kwargs + ) -> None: + """ + Initialise NanoMaxLoader with experiment data file path and + detector information. + + Args: + experiment_file_path (str): path to the master file + used for the experiment. + detector_name (str): name of the detector. + sample_name (str, optional): name of the sample. Defaults + to None. + flat_field (np.ndarray | str, optional): flat field to + account for the non homogeneous counting of the + detector. Defaults to None. + alien_mask (np.ndarray | str, optional): array to mask the + aliens. Defaults to None. + """ + super(NanoMaxLoader, self).__init__(flat_field, alien_mask) + self.experiment_file_path = experiment_file_path + self.detector_name = detector_name + self.sample_name = sample_name + + @safe + def load_detector_data( + self, + scan: int, + sample_name: str = None, + roi: tuple[slice] = None, + binning_along_axis0: int = None, + binnig_method: str = "sum" + ) -> np.ndarray: + """ + Main method to load the detector data (collected intensity). + + Args: + scan (int): the scan number you want to load the data from. + sample_name (str, optional): the sample name for this scan. + Only used if self.sample_name is None. Defaults to None. + roi (tuple[slice], optional): the region of interest of the + detector to load. Defaults to None. + binning_along_axis0 (int, optional): whether to bin the data + along the rocking curve axis. Defaults to None. + binnig_method (str, optional): the method employed for the + binning. It can be sum or "mean". Defaults to "sum". + + Returns: + np.ndarray: the detector data. + """ + # The self.h5file is initialised by the @safe decorator. + h5file = self.h5file + if sample_name is None: + sample_name = self.sample_name + + # Where to find the data. + key_path = ( + "_".join((sample_name, str(scan))) + + f"/entry/measurement/{self.detector_name}" + ) + + roi = self._check_roi(roi) + From 2c2e19d6f05fe4e651320620601730d72c56ab5c Mon Sep 17 00:00:00 2001 From: Clatlan Date: Tue, 4 Jun 2024 10:16:33 +0200 Subject: [PATCH 04/13] change default values of post_expand --- cdiutils/process/parameters.py | 2 +- cdiutils/process/phaser.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cdiutils/process/parameters.py b/cdiutils/process/parameters.py index ff0c7af6..ade23c6b 100644 --- a/cdiutils/process/parameters.py +++ b/cdiutils/process/parameters.py @@ -62,7 +62,7 @@ "support_update_period": 20, "support_smooth_width_begin": 2, "support_smooth_width_end": 1, - "support_post_expand": None, + "support_post_expand": None, # (-1, 1) "psf": "pseudo-voigt,0.5,0.1,10", "nb_raar": 500, "nb_hio": 300, diff --git a/cdiutils/process/phaser.py b/cdiutils/process/phaser.py index 325dec13..6ede6177 100644 --- a/cdiutils/process/phaser.py +++ b/cdiutils/process/phaser.py @@ -47,8 +47,8 @@ # support-related params "support_threshold": (0.15, 0.40), "smooth_width": (2, 0.5, 600), + "post_expand": None, # (-1, 1) "support_update_period": 50, - "post_expand": (1, -2, 1), "method": "rms", "force_shrink": False, "update_border_n": 0, From 356862ee00b84575122ba59ddc2847daca8c8574 Mon Sep 17 00:00:00 2001 From: Clatlan Date: Wed, 5 Jun 2024 14:50:00 +0200 Subject: [PATCH 05/13] update Nanomax geometry --- cdiutils/geometry.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cdiutils/geometry.py b/cdiutils/geometry.py index 02c8c084..befc4df3 100644 --- a/cdiutils/geometry.py +++ b/cdiutils/geometry.py @@ -67,13 +67,14 @@ def from_setup(cls, beamline_setup: str) -> None: return cls( sample_circles=["x-", "y-"], # gontheta, gonphi detector_circles=["y-", "x-"], # delta, gamma - detector_vertical_orientation="y-", - detector_horizontal_orientation="x+", + detector_vertical_orientation="y+", + detector_horizontal_orientation="x-", beam_direction=[1, 0, 0] ) raise NotImplementedError( f"The beamline_setup {beamline_setup} is not valid. Available:\n" - "'ID01', 'ID01SPEC', 'ID01BLISS', 'P10' , 'SIXS2022'" + "'ID01', 'ID01SPEC', 'ID01BLISS', 'P10', 'P10EH2', 'SIXS2022'" + "and NanoMAX." ) def cxi_to_xu(self) -> None: From c8fbdc1e488412f6d08ded63649ced4b1fe52152 Mon Sep 17 00:00:00 2001 From: Clatlan Date: Wed, 5 Jun 2024 14:51:09 +0200 Subject: [PATCH 06/13] docstring change --- cdiutils/load/nanomax.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cdiutils/load/nanomax.py b/cdiutils/load/nanomax.py index 37baa953..37004efa 100644 --- a/cdiutils/load/nanomax.py +++ b/cdiutils/load/nanomax.py @@ -12,8 +12,8 @@ class NanoMaxLoader(Loader): """ - A class to handle loading/reading .h5 files that were created using - on the NanoMax beamline. + A class to handle loading/reading .h5 files that were created at the + NanoMax beamline. Args: experiment_file_path (str): path to the master file From 1d0c770220aa7364fe17af4b6315c218f3e65e37 Mon Sep 17 00:00:00 2001 From: Clatlan Date: Thu, 6 Jun 2024 13:50:12 +0200 Subject: [PATCH 07/13] make geometry and converter available at the module level --- cdiutils/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cdiutils/__init__.py b/cdiutils/__init__.py index e8014125..9ef091fc 100755 --- a/cdiutils/__init__.py +++ b/cdiutils/__init__.py @@ -1,7 +1,11 @@ from . import load, plot, process +from .geometry import Geometry +from .converter import SpaceConverter __all__ = [ "load", "plot", - "process" + "process", + "Geometry", + "SpaceConverter" ] \ No newline at end of file From fb59672b4a45eb3982a0a466afa6c79c377a6ddc Mon Sep 17 00:00:00 2001 From: Clatlan Date: Thu, 6 Jun 2024 13:54:02 +0200 Subject: [PATCH 08/13] add more flexibility in parsing shape in init_interpolator --- cdiutils/converter.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cdiutils/converter.py b/cdiutils/converter.py index a76cbe1f..83dc19d6 100644 --- a/cdiutils/converter.py +++ b/cdiutils/converter.py @@ -366,7 +366,7 @@ def _check_shape(self, shape: tuple) -> None: def init_interpolator( self, detector_data: np.ndarray, - direct_space_data_shape: tuple = None, + direct_space_data_shape: tuple | np.ndarray | list = None, direct_space_voxel_size: tuple | np.ndarray | list | float = None, space: str = "direct", shift_voxel: tuple = None @@ -414,6 +414,7 @@ def init_interpolator( "if space is 'direct' direct_space_data_shape must be " "provided." ) + direct_space_data_shape = tuple(direct_space_data_shape) if shape != direct_space_data_shape: raise ValueError( "The cropped_raw_data should have the same shape as the " From 36c649122b0eb437824e41f6c5d4d3b3c8d64ced Mon Sep 17 00:00:00 2001 From: Clatlan Date: Thu, 6 Jun 2024 15:21:22 +0200 Subject: [PATCH 09/13] add CRISTAL geometry and edit the comments that were wrong --- cdiutils/geometry.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/cdiutils/geometry.py b/cdiutils/geometry.py index befc4df3..f59de453 100644 --- a/cdiutils/geometry.py +++ b/cdiutils/geometry.py @@ -42,7 +42,7 @@ def from_setup(cls, beamline_setup: str) -> None: if beamline_setup.lower() in ("id01", "id01spec", "id01bliss"): return cls( sample_circles=["x-", "y-"], # eta, phi - detector_circles=["y-", "x-"], # delta, nu + detector_circles=["y-", "x-"], # nu, delta detector_vertical_orientation="y-", detector_horizontal_orientation="x+", beam_direction=[1, 0, 0] @@ -50,7 +50,7 @@ def from_setup(cls, beamline_setup: str) -> None: if "p10" in beamline_setup.lower(): return cls( sample_circles=["x-", "y-"], # om (or samth), phi - detector_circles=["y+", "x-"], # del (or e2_t02), gam + detector_circles=["y+", "x-"], # gam, del (or e2_t02) detector_vertical_orientation="y-", detector_horizontal_orientation="x+", beam_direction=[1, 0, 0] @@ -58,7 +58,7 @@ def from_setup(cls, beamline_setup: str) -> None: if beamline_setup.lower() == "sixs2022": return cls( sample_circles=["x-", "y+"], # mu, omega - detector_circles=["y+", "x-"], # gamma, delta + detector_circles=["y+", "x-"], # gamma, delta NOT SURE OF THE COMMENT detector_vertical_orientation="y-", detector_horizontal_orientation="x+", beam_direction=[1, 0, 0] @@ -66,14 +66,22 @@ def from_setup(cls, beamline_setup: str) -> None: if beamline_setup.lower() == "nanomax": return cls( sample_circles=["x-", "y-"], # gontheta, gonphi - detector_circles=["y-", "x-"], # delta, gamma + detector_circles=["y-", "x-"], # gamma, delta detector_vertical_orientation="y+", detector_horizontal_orientation="x-", beam_direction=[1, 0, 0] ) + if beamline_setup.lower() == "cristal": + return cls( + sample_circles=["x-", "y+"], # omega, phi + detector_circles=["y+", "x-"], # gamma, delta OK FOR omega/delta but not for the two others + detector_vertical_orientation="y-", + detector_horizontal_orientation="x+", + beam_direction=[1, 0, 0] + ) raise NotImplementedError( f"The beamline_setup {beamline_setup} is not valid. Available:\n" - "'ID01', 'ID01SPEC', 'ID01BLISS', 'P10', 'P10EH2', 'SIXS2022'" + "'ID01', 'ID01SPEC', 'ID01BLISS', 'P10', 'P10EH2', 'SIXS2022' " "and NanoMAX." ) From 9d660805d2aad04cf45a0cdd025888d6611f0566 Mon Sep 17 00:00:00 2001 From: Clatlan Date: Fri, 7 Jun 2024 09:35:12 +0200 Subject: [PATCH 10/13] decorate _check_roi method with staticmethod --- cdiutils/load/loader.py | 3 ++- cdiutils/plot/formatting.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cdiutils/load/loader.py b/cdiutils/load/loader.py index cd1d6723..b75b51b3 100644 --- a/cdiutils/load/loader.py +++ b/cdiutils/load/loader.py @@ -88,7 +88,8 @@ def _check_load(data_or_path: np.ndarray | str) -> np.ndarray: "parameter provide a path, np.ndarray or leave it to None" ) - def _check_roi(self, roi: tuple = None) -> tuple[slice]: + @staticmethod + def _check_roi(roi: tuple = None) -> tuple[slice]: """ Utility function to check if a region of interest (roi) was parsed correctly. diff --git a/cdiutils/plot/formatting.py b/cdiutils/plot/formatting.py index d9f8fc20..d5405c0d 100755 --- a/cdiutils/plot/formatting.py +++ b/cdiutils/plot/formatting.py @@ -38,7 +38,7 @@ def get_extents( to the y-axis extent in the matshow/imshow plot. """ absolute_extents = [ - voxel_size[i] * shape[i] // (2 if zero_centered else 1) + voxel_size[i] * shape[i] / (2 if zero_centered else 1) for i in range(3) ] return ( From 30c46e337d20df0b73402479e2ac297bdc64b842 Mon Sep 17 00:00:00 2001 From: Clatlan Date: Fri, 7 Jun 2024 09:36:19 +0200 Subject: [PATCH 11/13] cleanup --- cdiutils/load/loader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cdiutils/load/loader.py b/cdiutils/load/loader.py index b75b51b3..59cf1635 100644 --- a/cdiutils/load/loader.py +++ b/cdiutils/load/loader.py @@ -113,10 +113,10 @@ def _check_roi(roi: tuple = None) -> tuple[slice]: ) if roi is None: return tuple(slice(None) for _ in range(3)) - elif len(roi) == 2 or len(roi) == 3: + if len(roi) == 2 or len(roi) == 3: if all(isinstance(e, slice) for e in roi): return tuple([slice(None), roi[0], roi[1]]) - elif len(roi) == 4 or len(roi) == 6: + if len(roi) == 4 or len(roi) == 6: if all(isinstance(e, int) for e in roi): return CroppingHandler.roi_list_to_slices(roi) raise ValueError(usage_text.format(roi)) From 71f172eae95ae27dc8570869676d10935b132fa3 Mon Sep 17 00:00:00 2001 From: Clatlan Date: Fri, 7 Jun 2024 09:37:53 +0200 Subject: [PATCH 12/13] cleanup --- cdiutils/load/nanomax.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/cdiutils/load/nanomax.py b/cdiutils/load/nanomax.py index 37004efa..9104fb4c 100644 --- a/cdiutils/load/nanomax.py +++ b/cdiutils/load/nanomax.py @@ -1,7 +1,7 @@ """ - Loader for the Nanomax beamlien at MAXIV. - See: - https://www.maxiv.lu.se/beamlines-accelerators/beamlines/nanomax/ +Loader for the Nanomax beamlien at MAXIV. +See: +https://www.maxiv.lu.se/beamlines-accelerators/beamlines/nanomax/ """ import numpy as np @@ -91,16 +91,16 @@ def load_detector_data( Returns: np.ndarray: the detector data. """ - # The self.h5file is initialised by the @safe decorator. - h5file = self.h5file - if sample_name is None: - sample_name = self.sample_name + # # The self.h5file is initialised by the @safe decorator. + # h5file = self.h5file + # if sample_name is None: + # sample_name = self.sample_name - # Where to find the data. - key_path = ( - "_".join((sample_name, str(scan))) - + f"/entry/measurement/{self.detector_name}" - ) - - roi = self._check_roi(roi) + # # Where to find the data. + # key_path = ( + # "_".join((sample_name, str(scan))) + # + f"/entry/measurement/{self.detector_name}" + # ) + # roi = self._check_roi(roi) + pass From f767295d269493b8d45c461e39cbc1ebb6e65d02 Mon Sep 17 00:00:00 2001 From: Clatlan Date: Fri, 7 Jun 2024 09:43:09 +0200 Subject: [PATCH 13/13] cleanup --- cdiutils/load/loader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdiutils/load/loader.py b/cdiutils/load/loader.py index 59cf1635..a1d8159f 100644 --- a/cdiutils/load/loader.py +++ b/cdiutils/load/loader.py @@ -115,7 +115,7 @@ def _check_roi(roi: tuple = None) -> tuple[slice]: return tuple(slice(None) for _ in range(3)) if len(roi) == 2 or len(roi) == 3: if all(isinstance(e, slice) for e in roi): - return tuple([slice(None), roi[0], roi[1]]) + return (slice(None), roi[0], roi[1]) if len(roi) == 4 or len(roi) == 6: if all(isinstance(e, int) for e in roi): return CroppingHandler.roi_list_to_slices(roi)