From 7c9decff0e4709b6e0f11fd47a024d0086113cbc Mon Sep 17 00:00:00 2001 From: payno Date: Thu, 29 Apr 2021 08:24:10 +0200 Subject: [PATCH 1/8] [settings] create a namespace Tomo and Tomo.H5, Tomo.EDF # Conflicts: # nxtomomill/io/config.py # nxtomomill/settings.py --- nxtomomill/app/edf2nx.py | 22 +-- nxtomomill/converter/edf/edfconverter.py | 23 +-- nxtomomill/converter/hdf5/hdf5converter.py | 36 ++-- nxtomomill/io/config.py | 34 ++-- nxtomomill/io/test/test_config.py | 44 +++-- nxtomomill/settings.py | 219 +++++++++++---------- 6 files changed, 200 insertions(+), 178 deletions(-) diff --git a/nxtomomill/app/edf2nx.py b/nxtomomill/app/edf2nx.py index 453a1ad..fc27459 100644 --- a/nxtomomill/app/edf2nx.py +++ b/nxtomomill/app/edf2nx.py @@ -38,19 +38,19 @@ import logging from nxtomomill import utils from nxtomomill import converter from nxtomomill.utils import Progress -from nxtomomill.settings import ( - EDF_MOTOR_POS, - EDF_MOTOR_MNE, - EDF_REFS_NAMES, - EDF_TO_IGNORE, - EDF_ROT_ANGLE, - EDF_DARK_NAMES, - EDF_X_TRANS, - EDF_Y_TRANS, - EDF_Z_TRANS, -) +from nxtomomill.settings import Tomo from tomoscan.esrf.edfscan import EDFTomoScan +EDF_MOTOR_POS = Tomo.EDF.EDF_MOTOR_POS +EDF_MOTOR_MNE = Tomo.EDF.EDF_MOTOR_MNE +EDF_REFS_NAMES = Tomo.EDF.EDF_REFS_NAMES +EDF_TO_IGNORE = Tomo.EDF.EDF_TO_IGNORE +EDF_ROT_ANGLE = Tomo.EDF.EDF_ROT_ANGLE +EDF_DARK_NAMES = Tomo.EDF.EDF_DARK_NAMES +EDF_X_TRANS = Tomo.EDF.EDF_X_TRANS +EDF_Y_TRANS = Tomo.EDF.EDF_Y_TRANS +EDF_Z_TRANS = Tomo.EDF.EDF_Z_TRANS + logging.basicConfig(level=logging.INFO) _logger = logging.getLogger(__name__) diff --git a/nxtomomill/converter/edf/edfconverter.py b/nxtomomill/converter/edf/edfconverter.py index 493561a..abb1257 100644 --- a/nxtomomill/converter/edf/edfconverter.py +++ b/nxtomomill/converter/edf/edfconverter.py @@ -38,23 +38,24 @@ from collections import namedtuple from nxtomomill import utils from nxtomomill.utils import ImageKey from nxtomomill.converter.version import version as converter_version -from nxtomomill.settings import ( - EDF_DARK_NAMES, - EDF_MOTOR_MNE, - EDF_MOTOR_POS, - EDF_REFS_NAMES, - EDF_ROT_ANGLE, - EDF_TO_IGNORE, - EDF_X_TRANS, - EDF_Y_TRANS, - EDF_Z_TRANS, -) +from nxtomomill.settings import Tomo from tomoscan.esrf.edfscan import EDFTomoScan from tomoscan.unitsystem import metricsystem from tomoscan.io import HDF5File import fabio import numpy import os + +EDF_MOTOR_POS = Tomo.EDF.EDF_MOTOR_POS +EDF_MOTOR_MNE = Tomo.EDF.EDF_MOTOR_MNE +EDF_REFS_NAMES = Tomo.EDF.EDF_REFS_NAMES +EDF_TO_IGNORE = Tomo.EDF.EDF_TO_IGNORE +EDF_ROT_ANGLE = Tomo.EDF.EDF_ROT_ANGLE +EDF_DARK_NAMES = Tomo.EDF.EDF_DARK_NAMES +EDF_X_TRANS = Tomo.EDF.EDF_X_TRANS +EDF_Y_TRANS = Tomo.EDF.EDF_Y_TRANS +EDF_Z_TRANS = Tomo.EDF.EDF_Z_TRANS + import logging _logger = logging.getLogger(__name__) diff --git a/nxtomomill/converter/hdf5/hdf5converter.py b/nxtomomill/converter/hdf5/hdf5converter.py index a3499ff..7821192 100644 --- a/nxtomomill/converter/hdf5/hdf5converter.py +++ b/nxtomomill/converter/hdf5/hdf5converter.py @@ -66,24 +66,24 @@ except ImportError: from nxtomomill.converter.hdf5.utils import H5FileKeys from nxtomomill.converter.hdf5.utils import H5ScanTitles -from nxtomomill.settings import ( - H5_ROT_ANGLE_KEYS, - H5_VALID_CAMERA_NAMES, - H5_X_TRANS_KEYS, - H5_Y_TRANS_KEYS, - H5_Z_TRANS_KEYS, - H5_ALIGNMENT_TITLES, - H5_ACQ_EXPO_TIME_KEYS, - H5_X_PIXEL_SIZE, - H5_Y_PIXEL_SIZE, - H5_DARK_TITLES, - H5_INIT_TITLES, - H5_ZSERIE_INIT_TITLES, - H5_PROJ_TITLES, - H5_REF_TITLES, - H5_Y_ROT_KEY, - H5_DIODE_KEYS, -) +from nxtomomill.settings import Tomo + +H5_ROT_ANGLE_KEYS = Tomo.H5.H5_ROT_ANGLE_KEYS +H5_VALID_CAMERA_NAMES = Tomo.H5.H5_VALID_CAMERA_NAMES +H5_X_TRANS_KEYS = Tomo.H5.H5_X_TRANS_KEYS +H5_Y_TRANS_KEYS = Tomo.H5.H5_Y_TRANS_KEYS +H5_Z_TRANS_KEYS = Tomo.H5.H5_Z_TRANS_KEYS +H5_ALIGNMENT_TITLES = Tomo.H5.H5_ALIGNMENT_TITLES +H5_ACQ_EXPO_TIME_KEYS = Tomo.H5.H5_ACQ_EXPO_TIME_KEYS +H5_X_PIXEL_SIZE = Tomo.H5.H5_X_PIXEL_SIZE +H5_Y_PIXEL_SIZE = Tomo.H5.H5_Y_PIXEL_SIZE +H5_DARK_TITLES = Tomo.H5.H5_DARK_TITLES +H5_INIT_TITLES = Tomo.H5.H5_INIT_TITLES +H5_ZSERIE_INIT_TITLES = Tomo.H5.H5_ZSERIE_INIT_TITLES +H5_PROJ_TITLES = Tomo.H5.H5_PROJ_TITLES +H5_REF_TITLES = Tomo.H5.H5_REF_TITLES +H5_Y_ROT_KEY = Tomo.H5.H5_Y_ROT_KEY +H5_DIODE_KEYS = Tomo.H5.H5_DIODE_KEYS DEFAULT_SCAN_TITLES = H5ScanTitles( H5_INIT_TITLES, diff --git a/nxtomomill/io/config.py b/nxtomomill/io/config.py index c60bf91..0e9dc06 100644 --- a/nxtomomill/io/config.py +++ b/nxtomomill/io/config.py @@ -291,27 +291,27 @@ class HDF5Config: self._field_of_view = None # information regarding keys and paths - self._valid_camera_names = settings.H5_VALID_CAMERA_NAMES - self._rot_angle_keys = settings.H5_ROT_ANGLE_KEYS - self._x_trans_keys = settings.H5_X_TRANS_KEYS - self._y_trans_keys = settings.H5_Y_TRANS_KEYS - self._z_trans_keys = settings.H5_Z_TRANS_KEYS - self._y_rot_key = settings.H5_Y_ROT_KEY - self._diode_keys = settings.H5_DIODE_KEYS - self._expo_time_keys = settings.H5_ACQ_EXPO_TIME_KEYS - self._sample_detector_distance_keys = settings.H5_DISTANCE_KEYS + self._valid_camera_names = settings.Tomo.H5.H5_VALID_CAMERA_NAMES + self._rot_angle_keys = settings.Tomo.H5.H5_ROT_ANGLE_KEYS + self._x_trans_keys = settings.Tomo.H5.H5_X_TRANS_KEYS + self._y_trans_keys = settings.Tomo.H5.H5_Y_TRANS_KEYS + self._z_trans_keys = settings.Tomo.H5.H5_Z_TRANS_KEYS + self._y_rot_key = settings.Tomo.H5.H5_Y_ROT_KEY + self._diode_keys = settings.Tomo.H5.H5_DIODE_KEYS + self._expo_time_keys = settings.Tomo.H5.H5_ACQ_EXPO_TIME_KEYS + self._sample_detector_distance_keys = settings.Tomo.H5.H5_DISTANCE_KEYS # information regarding titles self._entries = None self._sub_entries_to_ignore = None - self._init_titles = settings.H5_INIT_TITLES - self._zserie_init_titles = settings.H5_ZSERIE_INIT_TITLES - self._dark_titles = settings.H5_DARK_TITLES - self._flat_titles = settings.H5_REF_TITLES - self._projection_titles = settings.H5_PROJ_TITLES - self._alignment_titles = settings.H5_ALIGNMENT_TITLES - self._x_pixel_size_paths = settings.H5_X_PIXEL_SIZE - self._y_pixel_size_paths = settings.H5_Y_PIXEL_SIZE + self._init_titles = settings.Tomo.H5.H5_INIT_TITLES + self._zserie_init_titles = settings.Tomo.H5.H5_ZSERIE_INIT_TITLES + self._dark_titles = settings.Tomo.H5.H5_DARK_TITLES + self._flat_titles = settings.Tomo.H5.H5_REF_TITLES + self._projection_titles = settings.Tomo.H5.H5_PROJ_TITLES + self._alignment_titles = settings.Tomo.H5.H5_ALIGNMENT_TITLES + self._x_pixel_size_paths = settings.Tomo.H5.H5_X_PIXEL_SIZE + self._y_pixel_size_paths = settings.Tomo.H5.H5_Y_PIXEL_SIZE # information regarding frames types definition self._data_grps_urls = tuple() diff --git a/nxtomomill/io/test/test_config.py b/nxtomomill/io/test/test_config.py index 397951d..40a958d 100644 --- a/nxtomomill/io/test/test_config.py +++ b/nxtomomill/io/test/test_config.py @@ -60,53 +60,63 @@ class TestH5Config(unittest.TestCase): # check titles values titles_dict = output[HDF5Config.ENTRIES_AND_TITLES_SECTION_DK] self.assertEqual( - titles_dict[HDF5Config.INIT_TITLES_DK], settings.H5_INIT_TITLES + titles_dict[HDF5Config.INIT_TITLES_DK], settings.Tomo.H5.H5_INIT_TITLES ) self.assertEqual( titles_dict[HDF5Config.ZSERIE_INIT_TITLES_DK], - settings.H5_ZSERIE_INIT_TITLES, + settings.Tomo.H5.H5_ZSERIE_INIT_TITLES, ) self.assertEqual( - titles_dict[HDF5Config.PROJ_TITLES_DK], settings.H5_PROJ_TITLES + titles_dict[HDF5Config.PROJ_TITLES_DK], settings.Tomo.H5.H5_PROJ_TITLES ) - self.assertEqual(titles_dict[HDF5Config.REF_TITLES_DK], settings.H5_REF_TITLES) self.assertEqual( - titles_dict[HDF5Config.DARK_TITLES_DK], settings.H5_DARK_TITLES + titles_dict[HDF5Config.REF_TITLES_DK], settings.Tomo.H5.H5_REF_TITLES ) self.assertEqual( - titles_dict[HDF5Config.ALIGNMENT_TITLES_DK], settings.H5_ALIGNMENT_TITLES + titles_dict[HDF5Config.DARK_TITLES_DK], settings.Tomo.H5.H5_DARK_TITLES + ) + self.assertEqual( + titles_dict[HDF5Config.ALIGNMENT_TITLES_DK], + settings.Tomo.H5.H5_ALIGNMENT_TITLES, ) # check pixel size keys_dict = output[HDF5Config.KEYS_SECTION_DK] self.assertEqual( - keys_dict[HDF5Config.X_PIXEL_SIZE_KEYS_DK], settings.H5_X_PIXEL_SIZE + keys_dict[HDF5Config.X_PIXEL_SIZE_KEYS_DK], settings.Tomo.H5.H5_X_PIXEL_SIZE ) self.assertEqual( - keys_dict[HDF5Config.Y_PIXEL_SIZE_KEYS_DK], settings.H5_Y_PIXEL_SIZE + keys_dict[HDF5Config.Y_PIXEL_SIZE_KEYS_DK], settings.Tomo.H5.H5_Y_PIXEL_SIZE ) # check translation self.assertEqual( - keys_dict[HDF5Config.X_TRANS_KEYS_DK], settings.H5_X_TRANS_KEYS + keys_dict[HDF5Config.X_TRANS_KEYS_DK], settings.Tomo.H5.H5_X_TRANS_KEYS ) self.assertEqual( - keys_dict[HDF5Config.Y_TRANS_KEYS_DK], settings.H5_Y_TRANS_KEYS + keys_dict[HDF5Config.Y_TRANS_KEYS_DK], settings.Tomo.H5.H5_Y_TRANS_KEYS ) self.assertEqual( - keys_dict[HDF5Config.Z_TRANS_KEYS_DK], settings.H5_Z_TRANS_KEYS + keys_dict[HDF5Config.Z_TRANS_KEYS_DK], settings.Tomo.H5.H5_Z_TRANS_KEYS ) # others - if settings.H5_VALID_CAMERA_NAMES is None: + if settings.Tomo.H5.H5_VALID_CAMERA_NAMES is None: self.assertEqual(keys_dict[HDF5Config.VALID_CAMERA_DK], "") else: self.assertEqual( - keys_dict[HDF5Config.VALID_CAMERA_DK], settings.H5_VALID_CAMERA_NAMES + keys_dict[HDF5Config.VALID_CAMERA_DK], + settings.Tomo.H5.H5_VALID_CAMERA_NAMES, ) - self.assertEqual(keys_dict[HDF5Config.ROT_ANGLE_DK], settings.H5_ROT_ANGLE_KEYS) - self.assertEqual(keys_dict[HDF5Config.DIODE_KEYS_DK], settings.H5_DIODE_KEYS) - self.assertEqual(keys_dict[HDF5Config.Y_ROT_KEYS_DK], settings.H5_Y_ROT_KEY) + self.assertEqual( + keys_dict[HDF5Config.ROT_ANGLE_DK], settings.Tomo.H5.H5_ROT_ANGLE_KEYS + ) + self.assertEqual( + keys_dict[HDF5Config.DIODE_KEYS_DK], settings.Tomo.H5.H5_DIODE_KEYS + ) + self.assertEqual( + keys_dict[HDF5Config.Y_ROT_KEYS_DK], settings.Tomo.H5.H5_Y_ROT_KEY + ) self.assertEqual( keys_dict[HDF5Config.ACQUISITION_EXPO_TIME_KEYS_DK], - settings.H5_ACQ_EXPO_TIME_KEYS, + settings.Tomo.H5.H5_ACQ_EXPO_TIME_KEYS, ) # check input and output file diff --git a/nxtomomill/settings.py b/nxtomomill/settings.py index c84da78..c8b466b 100644 --- a/nxtomomill/settings.py +++ b/nxtomomill/settings.py @@ -32,107 +32,118 @@ __license__ = "MIT" __date__ = "13/05/2020" -### HDF5 settings - -H5_VALID_CAMERA_NAMES = None -# now camera names are deduce using converter `get_nx_detectors` -# and `guess_nx_detector` functions. But you can provide A LIST of -# detector name (unix shell-style wildcards are managed) like -# ("pcolinux*", "basler", "frelon*", ...) - -H5_ROT_ANGLE_KEYS = ( - "rotm", - "mhsrot", - "hsrot", - "mrsrot", - "hrsrot", - "srot", - "diffrz", - "hrrz_trig", - "rot", -) - -H5_X_TRANS_KEYS = ("sx", "d3tx", "tfx", "px") -"""Keys used to find the x translation""" - -H5_Y_TRANS_KEYS = ("sy", "d3ty", "hry", "py") -"""Keys used by bliss to store y translation""" - -H5_Z_TRANS_KEYS = ("sz", "d3tz", "hrz", "pz") -"""Keys used by bliss to store translation""" - -H5_Y_ROT_KEY = "instrument/positioners/yrot" -"""Key used by bliss to store the estimated center of rotation for half -acquisition""" - -H5_DIODE_KEYS = ("fpico3",) -"""keys used by bliss to store diode dataset""" - -H5_DISTANCE_KEYS = ("technique/scan/sample_detector_distance",) -"""keys used by bliss to store the sample to detector distance""" - -H5_ACQ_EXPO_TIME_KEYS = ("acq_expo_time",) - -H5_INIT_TITLES = ( - "pcotomo:basic", - "tomo:basic", - "tomo:fullturn", - "sequence_of_scans", - "tomo:halfturn", - "tomo:multiturn", -) -"""if a scan starts by one of those string then is considered as -initialization scan""" - -H5_ZSERIE_INIT_TITLES = ("tomo:zseries",) -"""specific titles for zserie. Will extend H5_INIT_TITLES""" - -H5_DARK_TITLES = ("dark images", "dark") -"""if a scan starts by one of those string then is considered as -dark scan""" -H5_REF_TITLES = ("reference images", "ref", "refend") -"""if a scan starts by one of those string then is considered as -reference scan""" -H5_PROJ_TITLES = ("projections", "ascan rot 0 ", "ascan diffrz 0 180 1600 0.1") -"""if a scan starts by one of those string then is considered as -projection scan""" -H5_ALIGNMENT_TITLES = ("static images", "ascan diffrz 180 0 4 0.1") -"""if a scan starts by one of those string then is considered as -alignment scan""" - -H5_X_PIXEL_SIZE = ( - "technique/optic/sample_pixel_size ", - "technique/optic/sample_pixel_size", - "technique/detector/pixel_size", - "hry_step_size", -) -"""Possible path to th pixel size.""" -# warning: we can have two cases: one with an empty space at the end or not - -H5_Y_PIXEL_SIZE = ( - "technique/optic/sample_pixel_size ", - "technique/optic/sample_pixel_size", - "technique/detector/pixel_size", - "hry_step_size", -) - -### EDF settings - -EDF_MOTOR_POS = "motor_pos" - -EDF_MOTOR_MNE = "motor_mne" - -EDF_ROT_ANGLE = "srot" - -EDF_X_TRANS = "sx" - -EDF_Y_TRANS = "sy" - -EDF_Z_TRANS = "sz" - -# EDF_TO_IGNORE = ['HST', '_slice_'] -EDF_TO_IGNORE = ("_slice_",) - -EDF_DARK_NAMES = ("darkend", "dark") - -EDF_REFS_NAMES = ("ref", "refHST") +class Tomo: + class H5: + """HDF5 settings for tomography""" + + H5_VALID_CAMERA_NAMES = None + # now camera names are deduce using converter `get_nx_detectors` + # and `guess_nx_detector` functions. But you can provide A LIST of + # detector name (unix shell-style wildcards are managed) like + # ("pcolinux*", "basler", "frelon*", ...) + + H5_ROT_ANGLE_KEYS = ( + "rotm", + "mhsrot", + "hsrot", + "mrsrot", + "hrsrot", + "srot", + "diffrz", + "hrrz_trig", + "rot", + ) + + H5_X_TRANS_KEYS = ("sx", "d3tx", "tfx", "px") + """Keys used to find the x translation""" + + H5_Y_TRANS_KEYS = ("sy", "d3ty", "hry", "py") + """Keys used by bliss to store y translation""" + + H5_Z_TRANS_KEYS = ("sz", "d3tz", "hrz", "pz") + """Keys used by bliss to store translation""" + + H5_Y_ROT_KEY = "instrument/positioners/yrot" + """Key used by bliss to store the estimated center of rotation for half + acquisition""" + + H5_DIODE_KEYS = ("fpico3",) + """keys used by bliss to store diode dataset""" + + H5_ACQ_EXPO_TIME_KEYS = ("acq_expo_time",) + + H5_INIT_TITLES = ( + "pcotomo:basic", + "tomo:basic", + "tomo:fullturn", + "sequence_of_scans", + "tomo:halfturn", + "tomo:multiturn", + ) + """if a scan starts by one of those string then is considered as + initialization scan""" + + H5_ZSERIE_INIT_TITLES = ("tomo:zseries",) + """specific titles for zserie. Will extend H5_INIT_TITLES""" + + H5_DARK_TITLES = ("dark images", "dark") + """if a scan starts by one of those string then is considered as + dark scan""" + H5_REF_TITLES = ("reference images", "ref", "refend") + """if a scan starts by one of those string then is considered as + reference scan""" + H5_PROJ_TITLES = ("projections", "ascan rot 0 ", "ascan diffrz 0 180 1600 0.1") + """if a scan starts by one of those string then is considered as + projection scan""" + H5_ALIGNMENT_TITLES = ("static images", "ascan diffrz 180 0 4 0.1") + """if a scan starts by one of those string then is considered as + alignment scan""" + + H5_X_PIXEL_SIZE = ( + "technique/optic/sample_pixel_size ", + "technique/optic/sample_pixel_size", + "technique/detector/pixel_size", + "hry_step_size", + ) + """Possible path to th pixel size.""" + # warning: we can have two cases: one with an empty space at the end or not + + H5_Y_PIXEL_SIZE = ( + "technique/optic/sample_pixel_size ", + "technique/optic/sample_pixel_size", + "technique/detector/pixel_size", + "hry_step_size", + ) + + H5_DISTANCE_KEYS = ("technique/scan/sample_detector_distance",) + """keys used by bliss to store the sample to detector distance""" + + class EDF: + """EDF settings for tomography""" + + EDF_MOTOR_POS = "motor_pos" + + EDF_MOTOR_MNE = "motor_mne" + + EDF_ROT_ANGLE = "srot" + + EDF_X_TRANS = "sx" + + EDF_Y_TRANS = "sy" + + EDF_Z_TRANS = "sz" + + # EDF_TO_IGNORE = ['HST', '_slice_'] + EDF_TO_IGNORE = ("_slice_",) + + EDF_DARK_NAMES = ("darkend", "dark") + + EDF_REFS_NAMES = ("ref", "refHST") + + +class XRD3D(Tomo): + class H5(Tomo.H5): + ROCKING_KEYS = (None,) + + BASE_TILT_KEYS = (None,) +>>>>>>> 4ce9671... [settings] create a namespace Tomo and Tomo.H5, Tomo.EDF -- GitLab From 0f9141362f7d5af6b357d1d863a19b980d0d77da Mon Sep 17 00:00:00 2001 From: payno Date: Thu, 29 Apr 2021 08:26:49 +0200 Subject: [PATCH 2/8] [converter] start adding the 3d-xrd format # Conflicts: # nxtomomill/io/config.py # nxtomomill/io/confighandler.py # nxtomomill/settings.py --- nxtomomill/__main__.py | 13 +- nxtomomill/app/h52nx.py | 4 +- nxtomomill/app/h5_3dxrd2nx.py | 286 ++++++++++++++++++ nxtomomill/app/h5quickstart.py | 8 +- .../hdf5/acquisition/baseaquisition.py | 6 +- .../hdf5/acquisition/standardacquisition.py | 4 +- .../hdf5/acquisition/test/test_acquisition.py | 4 +- .../converter/hdf5/acquisition/utils.py | 4 +- .../hdf5/acquisition/xrd3dacquisition.py | 105 +++++++ .../hdf5/acquisition/xrdctacquisition.py | 4 +- .../hdf5/acquisition/zseriesacquisition.py | 8 +- nxtomomill/converter/hdf5/hdf5converter.py | 25 +- nxtomomill/converter/hdf5/test/test_h52nx.py | 10 +- nxtomomill/io/config.py | 166 +++++----- nxtomomill/io/confighandler.py | 199 ++++++++---- nxtomomill/io/test/test_config.py | 127 ++++---- nxtomomill/io/test/test_confighandler.py | 36 +-- nxtomomill/settings.py | 5 +- nxtomomill/utils.py | 1 + 19 files changed, 763 insertions(+), 252 deletions(-) create mode 100644 nxtomomill/app/h5_3dxrd2nx.py create mode 100644 nxtomomill/converter/hdf5/acquisition/xrd3dacquisition.py diff --git a/nxtomomill/__main__.py b/nxtomomill/__main__.py index 11bf68f..a2d1e87 100644 --- a/nxtomomill/__main__.py +++ b/nxtomomill/__main__.py @@ -180,8 +180,7 @@ def main(): launcher.add_command( "tomoedf2nx", module_name="nxtomomill.app.edf2nx", - description="Deprecated. convert some scan acquire with edf file " - "format to nx compliant file format", + description="convert spec-edf acquisition to nexus - hdf5", deprecated=True, deprecated_reason="remove `tomo` repetition. The shorter the better", deprecated_replacement="edf2nx", @@ -190,14 +189,13 @@ def main(): launcher.add_command( "edf2nx", module_name="nxtomomill.app.edf2nx", - description="convert some scan acquire with edf file " + description="convert spec-edf acquisition to nexus - hdf5" "format to nx compliant file format", ) launcher.add_command( "tomoh52nx", module_name="nxtomomill.app.h52nx", - description="Deprecated. Compute center of rotation of a scan or " - "between two projections", + description="convert bliss hdf5 to nexus hdf5", deprecated=True, deprecated_reason="remove `tomo` repetition. The shorter the better", deprecated_replacement="h52nx", @@ -206,6 +204,11 @@ def main(): launcher.add_command( "h52nx", module_name="nxtomomill.app.h52nx", + description="convert bliss hdf5 to nexus hdf5", + ) + launcher.add_command( + "h5-3dxrd-2nx", + module_name="nxtomomill.app.h5_3dxrd2nx", description="Compute center of rotation of a scan or " "between two projections", ) diff --git a/nxtomomill/app/h52nx.py b/nxtomomill/app/h52nx.py index 6c8d49c..7fbe7c2 100644 --- a/nxtomomill/app/h52nx.py +++ b/nxtomomill/app/h52nx.py @@ -36,7 +36,7 @@ import logging from nxtomomill import utils from nxtomomill.utils import Progress from nxtomomill.converter import from_h5_to_nx -from nxtomomill.io.confighandler import HDF5ConfigHandler +from nxtomomill.io.confighandler import TomoHDF5ConfigHandler from nxtomomill.io.confighandler import SETTABLE_PARAMETERS_UNITS from collections.abc import Iterable import argparse @@ -280,7 +280,7 @@ def main(argv): else: callback_det_sel = None try: - configuration_handler = HDF5ConfigHandler(options, raise_error=True) + configuration_handler = TomoHDF5ConfigHandler(options, raise_error=True) except Exception as e: _logger.error(e) return diff --git a/nxtomomill/app/h5_3dxrd2nx.py b/nxtomomill/app/h5_3dxrd2nx.py new file mode 100644 index 0000000..a4fbb32 --- /dev/null +++ b/nxtomomill/app/h5_3dxrd2nx.py @@ -0,0 +1,286 @@ +# coding: utf-8 +# /*########################################################################## +# +# Copyright (c) 2015-2020 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ###########################################################################*/ + +""" +This module provides global definitions and methods to transform +a tomo dataset written in edf into and hdf5/nexus file +""" + +__authors__ = ["C. Nemoz", "H. Payno", "A.Sole"] +__license__ = "MIT" +__date__ = "16/01/2020" + +import logging +from nxtomomill import utils +from nxtomomill.utils import Progress +from nxtomomill.converter import from_h5_to_nx +from nxtomomill.io.confighandler import XRD3DHDF5ConfigHandler +from nxtomomill.io.confighandler import SETTABLE_PARAMETERS_UNITS +from collections.abc import Iterable +from nxtomomill.utils import Format +import argparse + + +logging.basicConfig(level=logging.INFO) +_logger = logging.getLogger(__name__) + + +def _getPossibleInputParams(): + """ + + :return: string with param1 (expected unit) ... + """ + res = [] + for key, value in SETTABLE_PARAMETERS_UNITS.items(): + res.append("{} ({})".format(key, value)) + return ", ".join(res) + + +def _ask_for_selecting_detector(det_grps: Iterable): + res = input( + "Several detector found. Only one detector is managed at the " + "time. Please enter the name of the detector you want to use " + 'or "Cancel" to stop translation ({})'.format(det_grps) + ) + if res == "Cancel": + return None + elif res in det_grps: + return res + else: + print("detector name not recognized.") + return _ask_for_selecting_detector(det_grps) + + +def main(argv): + """""" + parser = argparse.ArgumentParser( + description="convert data acquired as " + "hdf5 from bliss to nexus " + "`NXtomo` classes. For `zseries` it will create one entry per `z`" + ) + parser.add_argument( + "input_file", help="master file of the " "acquisition", default=None, nargs="?" + ) + parser.add_argument( + "output_file", help="output .nx or .h5 file", default=None, nargs="?" + ) + parser.add_argument( + "--file-extension", + "--file_extension", + default=None, + help="extension of the output file. Valid values are " + "" + "/".join(utils.FileExtension.values()), + ) + parser.add_argument( + "--single-file", + help="merge all scan sequence to the same output file. " + "By default create one file per sequence and " + "group all sequence in the output file", + dest="single_file", + action="store_true", + default=None, + ) + parser.add_argument( + "--overwrite", + help="Do not ask for user permission to overwrite output files", + action="store_true", + default=None, + ) + parser.add_argument( + "--debug", + help="Set logs to debug mode", + action="store_true", + default=None, + ) + parser.add_argument( + "--entries", + help="Specify (root) entries to be converted. By default it will try " + "to convert all existing entries.", + default=None, + ) + parser.add_argument( + "--ignore-sub-entries", + help="Specify (none-root) sub entries to ignore.", + default=None, + ) + parser.add_argument( + "--raises-error", + help="Raise errors if some data are not met instead of providing some" + " default values", + action="store_true", + default=None, + ) + parser.add_argument( + "--field-of-view", + help="Force the output to be `Half` or `Full` acquisition. Otherwise " + "parse raw data to find this information.", + default=None, + ) + parser.add_argument( + "--no-input", + "--no-input-for-missing-information", + help="The user won't be ask for any inputs", + dest="request_input", + action="store_false", + default=None, + ) + parser.add_argument( + "--x_trans_keys", + "--x-trans-keys", + default=None, + help="x translation key in bliss HDF5 file", + ) + parser.add_argument( + "--y_trans_keys", + "--y-trans-keys", + default=None, + help="y translation key in bliss HDF5 file", + ) + parser.add_argument( + "--z_trans_keys", + "--z-trans-keys", + default=None, + help="z translation key in bliss HDF5 file", + ) + parser.add_argument( + "--valid_camera_names", + "--valid-camera-names", + default=None, + help="Valid NXDetector dataset name to be considered. Otherwise will" + "try to deduce them from NX_class attibute (value should be" + "NXdetector) or from instrument group child structure.", + ) + parser.add_argument( + "--rot_angle_keys", + "--rot-angle-keys", + default=None, + help="Valid dataset name for rotation angle", + ) + parser.add_argument( + "--acq_expo_time_keys", + "--acq-expo-time-keys", + default=None, + help="Valid dataset name for acquisition exposure time", + ) + parser.add_argument( + "--x_pixel_size_key", + "--x-pixel-size-key", + default=None, + help="X pixel size key to read", + ) + parser.add_argument( + "--y_pixel_size_key", + "--y-pixel-size-key", + default=None, + help="Y pixel size key to read", + ) + + # scan titles + parser.add_argument( + "--init_titles", + "--init-titles", + default=None, + help="Titles corresponding to init scans", + ) + parser.add_argument( + "--init_zserie_titles", + "--init-zserie-titles", + default=None, + help="Titles corresponding to zserie init scans", + ) + parser.add_argument( + "--dark_titles", + "--dark-titles", + default=None, + help="Titles corresponding to dark scans", + ) + parser.add_argument( + "--ref_titles", + "--ref-titles", + default=None, + help="Titles corresponding to ref scans", + ) + parser.add_argument( + "--proj_titles", + "--proj-titles", + default=None, + help="Titles corresponding to projection scans", + ) + parser.add_argument( + "--align_titles", + "--align-titles", + default=None, + help="Titles corresponding to alignment scans", + ) + parser.add_argument( + "--set-params", + default=None, + nargs="*", + help="Allow manual definition of some parameters. " + "Valid parameters (and expected input unit) " + "are: {}. Should be added at the end of the command line because " + "will try to cover all text set after this " + "option.".format(_getPossibleInputParams()), + ) + # TODO: add base tilt and rocking settings + + parser.add_argument( + "--config", + "--config-file", + "--configuration", + "--configuration-file", + default=None, + help="file containing the full configuration to convert from h5 " + "bliss to nexus", + ) + options = parser.parse_args(argv[1:]) + if options.request_input: + callback_det_sel = _ask_for_selecting_detector + else: + callback_det_sel = None + configuration_handler = XRD3DHDF5ConfigHandler(options, raise_error=True) + try: + configuration_handler = XRD3DHDF5ConfigHandler(options, raise_error=True) + except Exception as e: + _logger.error(e) + return + else: + configuration = configuration_handler.configuration + for title in configuration.init_titles: + assert title != "" + configuration.format = Format.XRD_3D + from_h5_to_nx( + configuration=configuration_handler.configuration, + progress=Progress(""), + input_callback=None, + detector_sel_callback=callback_det_sel, + ) + exit(0) + + +if __name__ == "__main__": + import sys + + main(sys.argv[1:]) diff --git a/nxtomomill/app/h5quickstart.py b/nxtomomill/app/h5quickstart.py index 5c0cb6a..4de9ee1 100644 --- a/nxtomomill/app/h5quickstart.py +++ b/nxtomomill/app/h5quickstart.py @@ -36,7 +36,7 @@ __date__ = "23/02/2021" import logging import argparse from nxtomomill.io import generate_default_h5_config -from nxtomomill.io import HDF5Config +from nxtomomill.io import TomoHDF5Config logging.basicConfig(level=logging.INFO) _logger = logging.getLogger(__name__) @@ -70,7 +70,7 @@ def main(argv): raise ValueError( "`from-title-names` and `from-scan-urls` are " "exclusive options" ) - del configuration[HDF5Config.FRAME_TYPE_SECTION_DK] + del configuration[TomoHDF5Config.FRAME_TYPE_SECTION_DK] elif options.from_scan_urls: - del configuration[HDF5Config.ENTRIES_AND_TITLES_SECTION_DK] - HDF5Config.dict_to_cfg(file_path=options.output_file, dict_=configuration) + del configuration[TomoHDF5Config.ENTRIES_AND_TITLES_SECTION_DK] + TomoHDF5Config.dict_to_cfg(file_path=options.output_file, dict_=configuration) diff --git a/nxtomomill/converter/hdf5/acquisition/baseaquisition.py b/nxtomomill/converter/hdf5/acquisition/baseaquisition.py index 6fc7b85..5fd872b 100644 --- a/nxtomomill/converter/hdf5/acquisition/baseaquisition.py +++ b/nxtomomill/converter/hdf5/acquisition/baseaquisition.py @@ -41,7 +41,7 @@ except ImportError: pass from nxtomomill.plugins import get_plugins_positioners_resources from silx.io.url import DataUrl -from nxtomomill.io.config import HDF5Config +from nxtomomill.io.config import TomoHDF5Config from silx.io.utils import h5py_read_dataset from tomoscan.unitsystem import metricsystem from tomoscan.io import HDF5File @@ -122,7 +122,7 @@ class BaseAcquisition: def __init__( self, root_url: typing.Union[DataUrl, None], - configuration: HDF5Config, + configuration: TomoHDF5Config, detector_sel_callback, ): self._root_url = root_url @@ -369,7 +369,7 @@ class BaseAcquisition: return 0, "m" @staticmethod - def get_z_translation_frm(root_node, n_frame: int, configuration: HDF5Config): + def get_z_translation_frm(root_node, n_frame: int, configuration: TomoHDF5Config): for grp in BaseAcquisition._get_positioners_node(root_node), root_node: try: z_tr, unit = BaseAcquisition._get_node_values_for_frame_array( diff --git a/nxtomomill/converter/hdf5/acquisition/standardacquisition.py b/nxtomomill/converter/hdf5/acquisition/standardacquisition.py index 66205ca..9e02be0 100644 --- a/nxtomomill/converter/hdf5/acquisition/standardacquisition.py +++ b/nxtomomill/converter/hdf5/acquisition/standardacquisition.py @@ -58,7 +58,7 @@ import logging import fnmatch import numpy import os -from nxtomomill.io.config import HDF5Config +from nxtomomill.io.config import TomoHDF5Config _logger = logging.getLogger(__name__) @@ -76,7 +76,7 @@ class StandardAcquisition(BaseAcquisition): def __init__( self, root_url: Union[DataUrl, None], - configuration: HDF5Config, + configuration: TomoHDF5Config, detector_sel_callback, ): super().__init__( diff --git a/nxtomomill/converter/hdf5/acquisition/test/test_acquisition.py b/nxtomomill/converter/hdf5/acquisition/test/test_acquisition.py index a7a4886..870f6bb 100644 --- a/nxtomomill/converter/hdf5/acquisition/test/test_acquisition.py +++ b/nxtomomill/converter/hdf5/acquisition/test/test_acquisition.py @@ -32,7 +32,7 @@ import unittest import shutil import os from silx.io.url import DataUrl -from nxtomomill.io.config import HDF5Config +from nxtomomill.io.config import TomoHDF5Config import tempfile import h5py @@ -53,7 +53,7 @@ class TestBaseAcquisition(unittest.TestCase): url = DataUrl(file_path=file_path, data_path="/data/toto", scheme="silx") std_acq = BaseAcquisition( - root_url=url, configuration=HDF5Config(), detector_sel_callback=None + root_url=url, configuration=TomoHDF5Config(), detector_sel_callback=None ) with std_acq.read_entry() as entry: self.assertTrue("dataset" in entry) diff --git a/nxtomomill/converter/hdf5/acquisition/utils.py b/nxtomomill/converter/hdf5/acquisition/utils.py index eb73240..ce32394 100644 --- a/nxtomomill/converter/hdf5/acquisition/utils.py +++ b/nxtomomill/converter/hdf5/acquisition/utils.py @@ -30,7 +30,7 @@ Utils related to bliss-HDF5 from nxtomomill.io.acquisitionstep import AcquisitionStep from silx.io.utils import h5py_read_dataset -from nxtomomill.io.config import HDF5Config +from nxtomomill.io.config import TomoHDF5Config from silx.io.url import DataUrl from tomoscan.io import HDF5File import typing @@ -60,7 +60,7 @@ def has_valid_detector(node, detectors_names): def get_entry_type( - url: DataUrl, configuration: HDF5Config + url: DataUrl, configuration: TomoHDF5Config ) -> typing.Union[None, AcquisitionStep]: """ :return: return the step of the acquisition or None if cannot find it. diff --git a/nxtomomill/converter/hdf5/acquisition/xrd3dacquisition.py b/nxtomomill/converter/hdf5/acquisition/xrd3dacquisition.py new file mode 100644 index 0000000..808b629 --- /dev/null +++ b/nxtomomill/converter/hdf5/acquisition/xrd3dacquisition.py @@ -0,0 +1,105 @@ +# coding: utf-8 +# /*########################################################################## +# +# Copyright (c) 2015-2020 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ###########################################################################*/ + +""" +module to define a standard tomography acquisition (made by bliss) +""" + +__authors__ = [ + "H. Payno", + "J. Garriga", +] +__license__ = "MIT" +__date__ = "19/04/2021" + + +from nxtomomill.converter.hdf5.acquisition.standardacquisition import ( + StandardAcquisition, +) + + +class XRD3DAcquisition(StandardAcquisition): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._base_tilt = None + self._rocking = None + + @property + def base_tilt(self): + return self._base_tilt + + @base_tilt.setter + def base_tilt(self, base_tilt): + self._base_tilt = base_tilt + + @property + def rocking(self): + return self._rocking + + @rocking.setter + def rocking(self, rocking): + self._rocking = rocking + + def _get_rocking_dataset(self, entry, n_frames): + raise NotImplementedError() + + def _get_base_tilt_dataset(self, entry, n_frames): + raise NotImplementedError() + + def __treate_valid_camera( + self, + detector_node, + entry, + frame_type, + input_file_path, + output_file, + entry_path, + entry_url, + ): + super().__treate_valid_camera( + detector_node=detector_node, + entry=entry, + frame_type=frame_type, + input_file_path=input_file_path, + output_file=output_file, + entry_path=entry_path, + entry_url=entry_url, + ) + # store base tilt information + if not self._ignore_sample_output("base_tilt"): + rots = self._get_base_tilt_dataset(entry=entry, n_frames=self._n_frames)[0] + self._base_tilt.extend(rots) + else: + self._base_tilt = None + + def _preprocess_registered_entries(self, output_file): + super()._preprocess_register_entries(output_file=output_file) + self._base_tilt = [] + self._rocking = [] + + def _write_instrument(self, root_node): + super()._write_instrument(root_node) + instrument_node = root_node.create_group("instrument") + raise NotImplementedError() diff --git a/nxtomomill/converter/hdf5/acquisition/xrdctacquisition.py b/nxtomomill/converter/hdf5/acquisition/xrdctacquisition.py index 99f3ccb..cc767e5 100644 --- a/nxtomomill/converter/hdf5/acquisition/xrdctacquisition.py +++ b/nxtomomill/converter/hdf5/acquisition/xrdctacquisition.py @@ -35,7 +35,7 @@ __date__ = "27/11/2020" from .standardacquisition import StandardAcquisition -from nxtomomill.io.config import HDF5Config +from nxtomomill.io.config import TomoHDF5Config from nxtomomill.io.acquisitionstep import AcquisitionStep from .utils import has_valid_detector import h5py @@ -74,7 +74,7 @@ class XRDCTAcquisition(StandardAcquisition): def __init__( self, root_url: DataUrl, - configuration: HDF5Config, + configuration: TomoHDF5Config, detector_sel_callback, copy_frames: bool = False, ): diff --git a/nxtomomill/converter/hdf5/acquisition/zseriesacquisition.py b/nxtomomill/converter/hdf5/acquisition/zseriesacquisition.py index e1d295f..2a62d81 100644 --- a/nxtomomill/converter/hdf5/acquisition/zseriesacquisition.py +++ b/nxtomomill/converter/hdf5/acquisition/zseriesacquisition.py @@ -37,7 +37,7 @@ __date__ = "27/11/2020" from .baseaquisition import BaseAcquisition from .baseaquisition import EntryReader from .standardacquisition import StandardAcquisition -from nxtomomill.io.config import HDF5Config +from nxtomomill.io.config import TomoHDF5Config from silx.io.utils import h5py_read_dataset from silx.utils.proxy import docstring from typing import Iterable @@ -51,7 +51,7 @@ except ImportError: pass -def is_z_series_frm_titles(entry: h5py.Group, configuration: HDF5Config) -> bool: +def is_z_series_frm_titles(entry: h5py.Group, configuration: TomoHDF5Config) -> bool: """ is the provided h5py Group is tomography z series acquisition. the entry should be an 'initialization' entry. We will look on @@ -65,7 +65,9 @@ def is_z_series_frm_titles(entry: h5py.Group, configuration: HDF5Config) -> bool return title in configuration.zserie_init_titles -def is_z_series_frm_z_translation(projection_urls: Iterable, configuration: HDF5Config): +def is_z_series_frm_z_translation( + projection_urls: Iterable, configuration: TomoHDF5Config +): """ :param Iterable projection_urls: list of DataUrl pointing to projection diff --git a/nxtomomill/converter/hdf5/hdf5converter.py b/nxtomomill/converter/hdf5/hdf5converter.py index 7821192..e9f39d1 100644 --- a/nxtomomill/converter/hdf5/hdf5converter.py +++ b/nxtomomill/converter/hdf5/hdf5converter.py @@ -42,9 +42,10 @@ from .acquisition.zseriesacquisition import ZSeriesBaseAcquisition from .acquisition.zseriesacquisition import is_z_series_frm_titles from .acquisition.zseriesacquisition import is_z_series_frm_z_translation from .acquisition.xrdctacquisition import XRDCTAcquisition +from .acquisition.xrd3dacquisition import XRD3DAcquisition from nxtomomill.utils import Format from silx.utils.deprecation import deprecated -from nxtomomill.io.config import HDF5Config +from nxtomomill.io.config import TomoHDF5Config from nxtomomill.io.framegroup import FrameGroup from silx.io.url import DataUrl from tomoscan.io import HDF5File @@ -123,7 +124,7 @@ class _H5ToNxConverter: :param configuration: configuration for the translation. such as the input and output file, keys... - :type configuration: HDF5Config + :type configuration: TomoHDF5Config :param input_callback: possible callback in case of missing information :param progress: progress bar to be updated if provided :param detector_sel_callback: callback for the detector selection if any @@ -144,12 +145,12 @@ class _H5ToNxConverter: def __init__( self, - configuration: HDF5Config, + configuration: TomoHDF5Config, input_callback=None, progress=None, detector_sel_callback=None, ): - if not isinstance(configuration, HDF5Config): + if not isinstance(configuration, TomoHDF5Config): raise TypeError( "configuration should be an instance of HDFConfig" " not {}".format(type(configuration)) @@ -291,12 +292,18 @@ class _H5ToNxConverter: configuration=self.configuration, detector_sel_callback=self.detector_sel_callback, ) - elif current_format is Format.XRD_CT: + elif current_format is Format.XRD_3D: root_acquisition = XRDCTAcquisition( configuration=self.configuration, detector_sel_callback=self.detector_sel_callback, copy_frames=frame_grp.copy, ) + elif current_format is Format.XRD_CT: + root_acquisition = XRD3DAcquisition( + configuration=self.configuration, + detector_sel_callback=self.detector_sel_callback, + copy_frames=frame_grp.copy, + ) else: raise ValueError("Format {} is not handled".format(current_format)) self.acquisitions.append(root_acquisition) @@ -682,7 +689,7 @@ def h5_to_nx( raise_error_if_issue=False, detector_sel_callback=None, ): - configuration = HDF5Config() + configuration = TomoHDF5Config() configuration.input_file = input_file_path configuration.output_file = output_file configuration.single_file = single_file @@ -726,7 +733,7 @@ def h5_to_nx( def from_h5_to_nx( - configuration: HDF5Config, + configuration: TomoHDF5Config, input_callback=None, progress=None, detector_sel_callback=None, @@ -748,9 +755,9 @@ def from_h5_to_nx( return converter.convert() -def get_bliss_tomo_entries(input_file_path: str, configuration: HDF5Config): +def get_bliss_tomo_entries(input_file_path: str, configuration: TomoHDF5Config): """Util function. Used by tomwer for example""" - if not isinstance(configuration, HDF5Config): + if not isinstance(configuration, TomoHDF5Config): raise TypeError("configuration is expected to be a HDF5Config") with HDF5File(input_file_path, "r") as h5d: diff --git a/nxtomomill/converter/hdf5/test/test_h52nx.py b/nxtomomill/converter/hdf5/test/test_h52nx.py index aead506..267437d 100644 --- a/nxtomomill/converter/hdf5/test/test_h52nx.py +++ b/nxtomomill/converter/hdf5/test/test_h52nx.py @@ -39,7 +39,7 @@ from nxtomomill.converter.hdf5.acquisition.utils import get_nx_detectors from nxtomomill.converter.hdf5.acquisition.utils import guess_nx_detector from nxtomomill.converter.hdf5.acquisition.baseaquisition import EntryReader from nxtomomill.converter.hdf5.acquisition.baseaquisition import DatasetReader -from nxtomomill.io.config import HDF5Config +from nxtomomill.io.config import TomoHDF5Config from tomoscan.esrf.hdf5scan import HDF5TomoScan from nxtomomill.test.utils.bliss import MockBlissAcquisition from silx.io.url import DataUrl @@ -69,7 +69,7 @@ def url_has_been_copied(file_path: str, url: DataUrl): class TestH5ToNxConverter(unittest.TestCase): def setUp(self) -> None: self.folder = tempfile.mkdtemp() - self.config = HDF5Config() + self.config = TomoHDF5Config() def tearDown(self) -> None: shutil.rmtree(self.folder) @@ -372,7 +372,7 @@ class TestDetectorDetection(unittest.TestCase): class TestXRDCTConversion(unittest.TestCase): def setUp(self) -> None: self.folder = tempfile.mkdtemp() - self.config = HDF5Config() + self.config = TomoHDF5Config() def tearDown(self) -> None: shutil.rmtree(self.folder) @@ -423,7 +423,7 @@ class TestStandardAcqConversionWithExternalUrls(unittest.TestCase): def setUp(self) -> None: self.folder = tempfile.mkdtemp() - self.config = HDF5Config() + self.config = TomoHDF5Config() self.config.output_file = os.path.join(self.folder, "output.nx") def create_scan(self, n_projection_scans, n_flats, n_darks, output_dir): @@ -648,7 +648,7 @@ class TestZSeriesConversionWithExternalUrls(unittest.TestCase): def setUp(self) -> None: self.folder = tempfile.mkdtemp() - self.config = HDF5Config() + self.config = TomoHDF5Config() self.config.output_file = os.path.join(self.folder, "output.nx") camera_name = "frelon" diff --git a/nxtomomill/io/config.py b/nxtomomill/io/config.py index 0e9dc06..bedcf58 100644 --- a/nxtomomill/io/config.py +++ b/nxtomomill/io/config.py @@ -99,7 +99,7 @@ def _example_fg_list(with_comment=True, with_prefix=False) -> str: ) -class HDF5Config: +class TomoHDF5Config: """ Configuration class to provide to the convert from h5 to nx """ @@ -822,31 +822,31 @@ class HDF5Config: else "", }, self.KEYS_SECTION_DK: { - HDF5Config.VALID_CAMERA_DK: self.valid_camera_names or "", - HDF5Config.ROT_ANGLE_DK: self.rotation_angle_keys, - HDF5Config.X_TRANS_KEYS_DK: self.x_trans_keys, - HDF5Config.Y_TRANS_KEYS_DK: self.y_trans_keys, - HDF5Config.Z_TRANS_KEYS_DK: self.z_trans_keys, - HDF5Config.Y_ROT_KEYS_DK: self.y_rot_key, - HDF5Config.DIODE_KEYS_DK: self.diode_keys, - HDF5Config.ACQUISITION_EXPO_TIME_KEYS_DK: self.exposition_time_keys, - HDF5Config.X_PIXEL_SIZE_KEYS_DK: self.x_pixel_size_paths, - HDF5Config.Y_PIXEL_SIZE_KEYS_DK: self.y_pixel_size_paths, - HDF5Config.SAMPLE_DETECTOR_DISTANCE_DK: self.sample_detector_distance_paths, + TomoHDF5Config.VALID_CAMERA_DK: self.valid_camera_names or "", + TomoHDF5Config.ROT_ANGLE_DK: self.rotation_angle_keys, + TomoHDF5Config.X_TRANS_KEYS_DK: self.x_trans_keys, + TomoHDF5Config.Y_TRANS_KEYS_DK: self.y_trans_keys, + TomoHDF5Config.Z_TRANS_KEYS_DK: self.z_trans_keys, + TomoHDF5Config.Y_ROT_KEYS_DK: self.y_rot_key, + TomoHDF5Config.DIODE_KEYS_DK: self.diode_keys, + TomoHDF5Config.ACQUISITION_EXPO_TIME_KEYS_DK: self.exposition_time_keys, + TomoHDF5Config.X_PIXEL_SIZE_KEYS_DK: self.x_pixel_size_paths, + TomoHDF5Config.Y_PIXEL_SIZE_KEYS_DK: self.y_pixel_size_paths, + TomoHDF5Config.SAMPLE_DETECTOR_DISTANCE_DK: self.sample_detector_distance_paths, }, self.ENTRIES_AND_TITLES_SECTION_DK: { - HDF5Config.ENTRIES_DK: self.entries or "", - HDF5Config.SUB_ENTRIES_TO_IGNORE: self.sub_entries_to_ignore or "", - HDF5Config.INIT_TITLES_DK: self.init_titles or "", - HDF5Config.ZSERIE_INIT_TITLES_DK: self.zserie_init_titles or "", - HDF5Config.DARK_TITLES_DK: self.dark_titles or "", - HDF5Config.REF_TITLES_DK: self.flat_titles or "", - HDF5Config.PROJ_TITLES_DK: self.projections_titles or "", - HDF5Config.ALIGNMENT_TITLES_DK: self.alignment_titles or "", + TomoHDF5Config.ENTRIES_DK: self.entries or "", + TomoHDF5Config.SUB_ENTRIES_TO_IGNORE: self.sub_entries_to_ignore or "", + TomoHDF5Config.INIT_TITLES_DK: self.init_titles or "", + TomoHDF5Config.ZSERIE_INIT_TITLES_DK: self.zserie_init_titles or "", + TomoHDF5Config.DARK_TITLES_DK: self.dark_titles or "", + TomoHDF5Config.REF_TITLES_DK: self.flat_titles or "", + TomoHDF5Config.PROJ_TITLES_DK: self.projections_titles or "", + TomoHDF5Config.ALIGNMENT_TITLES_DK: self.alignment_titles or "", }, self.FRAME_TYPE_SECTION_DK: { - HDF5Config.DATA_DK: FrameGroup.list_to_str(self.data_frame_grps), - HDF5Config.DEFAULT_DATA_COPY_DK: self.default_copy_behavior, + TomoHDF5Config.DATA_DK: FrameGroup.list_to_str(self.data_frame_grps), + TomoHDF5Config.DEFAULT_DATA_COPY_DK: self.default_copy_behavior, }, self.EXTRA_PARAMS_SECTION_DK: self._param_already_defined, } @@ -859,56 +859,60 @@ class HDF5Config: :param dict dict_: settings dictionary :return: HDF5Config """ - config = HDF5Config() + config = TomoHDF5Config() config.load_from_dict(dict_) return config def load_from_dict(self, dict_: dict) -> None: """Load the configuration from a dictionary""" # general section - if HDF5Config.GENERAL_SECTION_DK in dict_: - self.load_general_section(dict_[HDF5Config.GENERAL_SECTION_DK]) + if TomoHDF5Config.GENERAL_SECTION_DK in dict_: + self.load_general_section(dict_[TomoHDF5Config.GENERAL_SECTION_DK]) else: - _logger.error("No {} section found".format(HDF5Config.GENERAL_SECTION_DK)) + _logger.error( + "No {} section found".format(TomoHDF5Config.GENERAL_SECTION_DK) + ) # keys section - if HDF5Config.KEYS_SECTION_DK in dict_: - self.load_keys_section(dict_[HDF5Config.KEYS_SECTION_DK]) + if TomoHDF5Config.KEYS_SECTION_DK in dict_: + self.load_keys_section(dict_[TomoHDF5Config.KEYS_SECTION_DK]) else: - mess = "No {} section found".format(HDF5Config.KEYS_SECTION_DK) - if HDF5Config.ENTRIES_AND_TITLES_SECTION_DK not in dict_: + mess = "No {} section found".format(TomoHDF5Config.KEYS_SECTION_DK) + if TomoHDF5Config.ENTRIES_AND_TITLES_SECTION_DK not in dict_: _logger.error(mess) else: _logger.info(mess) # entries and titles section - if HDF5Config.ENTRIES_AND_TITLES_SECTION_DK in dict_: + if TomoHDF5Config.ENTRIES_AND_TITLES_SECTION_DK in dict_: self.load_entries_titles_section( - dict_[HDF5Config.ENTRIES_AND_TITLES_SECTION_DK] + dict_[TomoHDF5Config.ENTRIES_AND_TITLES_SECTION_DK] ) else: mess = "No {} section found".format( - HDF5Config.ENTRIES_AND_TITLES_SECTION_DK + TomoHDF5Config.ENTRIES_AND_TITLES_SECTION_DK ) - if HDF5Config.KEYS_SECTION_DK not in dict_: + if TomoHDF5Config.KEYS_SECTION_DK not in dict_: _logger.error(mess) else: _logger.info(mess) # frame type section - if HDF5Config.FRAME_TYPE_SECTION_DK in dict_: - self.load_frame_type_section(dict_[HDF5Config.FRAME_TYPE_SECTION_DK]) + if TomoHDF5Config.FRAME_TYPE_SECTION_DK in dict_: + self.load_frame_type_section(dict_[TomoHDF5Config.FRAME_TYPE_SECTION_DK]) else: _logger.error( - "No {} section found".format(HDF5Config.FRAME_TYPE_SECTION_DK) + "No {} section found".format(TomoHDF5Config.FRAME_TYPE_SECTION_DK) ) # extra params section - if HDF5Config.EXTRA_PARAMS_SECTION_DK in dict_: - self.load_extra_params_section(dict_[HDF5Config.EXTRA_PARAMS_SECTION_DK]) + if TomoHDF5Config.EXTRA_PARAMS_SECTION_DK in dict_: + self.load_extra_params_section( + dict_[TomoHDF5Config.EXTRA_PARAMS_SECTION_DK] + ) else: _logger.error( - "No {} section found".format(HDF5Config.EXTRA_PARAMS_SECTION_DK) + "No {} section found".format(TomoHDF5Config.EXTRA_PARAMS_SECTION_DK) ) def load_general_section(self, dict_): @@ -922,32 +926,32 @@ class HDF5Config: else: raise TypeError("value should be a string") - self.input_file = dict_.get(HDF5Config.INPUT_FILE_DK, None) - self.output_file = dict_.get(HDF5Config.OUTPUT_FILE_DK, None) - overwrite = dict_.get(HDF5Config.OVERWRITE_DK, None) + self.input_file = dict_.get(TomoHDF5Config.INPUT_FILE_DK, None) + self.output_file = dict_.get(TomoHDF5Config.OUTPUT_FILE_DK, None) + overwrite = dict_.get(TomoHDF5Config.OVERWRITE_DK, None) if overwrite is not None: self.overwrite = cast_bool(overwrite) - file_extension = dict_.get(HDF5Config.FILE_EXTENSION_DK, None) + file_extension = dict_.get(TomoHDF5Config.FILE_EXTENSION_DK, None) if file_extension is not None: self.file_extension = filter_str_def(file_extension) - log_level = dict_.get(HDF5Config.LOG_LEVEL_DK, None) + log_level = dict_.get(TomoHDF5Config.LOG_LEVEL_DK, None) if log_level is not None: self.log_level = log_level - raises_error = dict_.get(HDF5Config.RAISES_ERROR_DK, None) + raises_error = dict_.get(TomoHDF5Config.RAISES_ERROR_DK, None) if raises_error is not None: self.raises_error = cast_bool(raises_error) - no_input = dict_.get(HDF5Config.NO_INPUT_DK, None) + no_input = dict_.get(TomoHDF5Config.NO_INPUT_DK, None) if no_input is not None: self.no_input = cast_bool(no_input) - single_file = dict_.get(HDF5Config.SINGLE_FILE_DK, None) + single_file = dict_.get(TomoHDF5Config.SINGLE_FILE_DK, None) if single_file is not None: self.single_file = cast_bool(single_file) - input_format = dict_.get(HDF5Config.INPUT_FORMAT_DK, None) + input_format = dict_.get(TomoHDF5Config.INPUT_FORMAT_DK, None) if input_format is not None: if input_format == "": input_format = None self.format = filter_str_def(input_format) - field_of_view = dict_.get(HDF5Config.FIELD_OF_VIEW_DK, None) + field_of_view = dict_.get(TomoHDF5Config.FIELD_OF_VIEW_DK, None) if field_of_view is not None: if field_of_view == "": field_of_view = None @@ -955,7 +959,7 @@ class HDF5Config: def load_keys_section(self, dict_): # handle valid camera names. empty string is consider as a valid value - valid_camera_names = dict_.get(HDF5Config.VALID_CAMERA_DK, None) + valid_camera_names = dict_.get(TomoHDF5Config.VALID_CAMERA_DK, None) if valid_camera_names == "": valid_camera_names = None else: @@ -964,52 +968,54 @@ class HDF5Config: ) self.valid_camera_names = valid_camera_names # handle rotation angles. - rotation_angle_keys = dict_.get(HDF5Config.ROT_ANGLE_DK, None) + rotation_angle_keys = dict_.get(TomoHDF5Config.ROT_ANGLE_DK, None) if rotation_angle_keys is not None: rotation_angle_keys = convert_str_to_tuple( rotation_angle_keys, none_if_empty=True ) self.rotation_angle_keys = rotation_angle_keys # handle x translation - x_trans_keys = dict_.get(HDF5Config.X_TRANS_KEYS_DK, None) + x_trans_keys = dict_.get(TomoHDF5Config.X_TRANS_KEYS_DK, None) if x_trans_keys is not None: x_trans_keys = convert_str_to_tuple(x_trans_keys, none_if_empty=True) self.x_trans_keys = x_trans_keys # handle y translation - y_trans_keys = dict_.get(HDF5Config.Y_TRANS_KEYS_DK, None) + y_trans_keys = dict_.get(TomoHDF5Config.Y_TRANS_KEYS_DK, None) if y_trans_keys is not None: y_trans_keys = convert_str_to_tuple(y_trans_keys, none_if_empty=True) self.y_trans_keys = y_trans_keys # handle z translation - z_trans_keys = dict_.get(HDF5Config.Z_TRANS_KEYS_DK, None) + z_trans_keys = dict_.get(TomoHDF5Config.Z_TRANS_KEYS_DK, None) if z_trans_keys is not None: z_trans_keys = convert_str_to_tuple(z_trans_keys, none_if_empty=True) self.z_trans_keys = z_trans_keys # handle y rotation keys - y_rot_key = dict_.get(HDF5Config.Y_ROT_KEYS_DK, None) + y_rot_key = dict_.get(TomoHDF5Config.Y_ROT_KEYS_DK, None) if y_rot_key is not None: self.y_rot_key = y_rot_key # handle diode keys - diode_keys = dict_.get(HDF5Config.DIODE_KEYS_DK, None) + diode_keys = dict_.get(TomoHDF5Config.DIODE_KEYS_DK, None) if diode_keys is not None: diode_keys = convert_str_to_tuple(diode_keys, none_if_empty=True) self.diode_keys = diode_keys # handle exposure time - exposition_time_keys = dict_.get(HDF5Config.ACQUISITION_EXPO_TIME_KEYS_DK, None) + exposition_time_keys = dict_.get( + TomoHDF5Config.ACQUISITION_EXPO_TIME_KEYS_DK, None + ) if exposition_time_keys is not None: exposition_time_keys = convert_str_to_tuple( exposition_time_keys, none_if_empty=True ) self.exposition_time_keys = exposition_time_keys # handle x pixel paths - x_pixel_size_paths = dict_.get(HDF5Config.X_PIXEL_SIZE_KEYS_DK, None) + x_pixel_size_paths = dict_.get(TomoHDF5Config.X_PIXEL_SIZE_KEYS_DK, None) if x_pixel_size_paths is not None: x_pixel_size_paths = convert_str_to_tuple( x_pixel_size_paths, none_if_empty=True ) self.x_pixel_size_paths = x_pixel_size_paths # handle y pixel paths - y_pixel_size_paths = dict_.get(HDF5Config.Y_PIXEL_SIZE_KEYS_DK, None) + y_pixel_size_paths = dict_.get(TomoHDF5Config.Y_PIXEL_SIZE_KEYS_DK, None) if y_pixel_size_paths is not None: y_pixel_size_paths = convert_str_to_tuple( y_pixel_size_paths, none_if_empty=True @@ -1017,7 +1023,7 @@ class HDF5Config: self.y_pixel_size_paths = y_pixel_size_paths # handle sample detector distance sample_detector_distance = dict_.get( - HDF5Config.SAMPLE_DETECTOR_DISTANCE_DK, None + TomoHDF5Config.SAMPLE_DETECTOR_DISTANCE_DK, None ) if sample_detector_distance is not None: sample_detector_distance = convert_str_to_tuple( @@ -1027,39 +1033,39 @@ class HDF5Config: def load_entries_titles_section(self, dict_): # handle entries to convert - entries = dict_.get(HDF5Config.ENTRIES_DK) + entries = dict_.get(TomoHDF5Config.ENTRIES_DK) if entries is not None: entries = convert_str_to_tuple(entries, none_if_empty=True) self.entries = entries # handle init titles. empty string is consider as a valid value - init_titles = dict_.get(HDF5Config.INIT_TITLES_DK, None) + init_titles = dict_.get(TomoHDF5Config.INIT_TITLES_DK, None) if init_titles is not None: init_titles = convert_str_to_tuple(init_titles, none_if_empty=True) self.init_titles = init_titles # handle zserie init titles. empty string is consider as a valid value - zserie_init_titles = dict_.get(HDF5Config.ZSERIE_INIT_TITLES_DK, None) + zserie_init_titles = dict_.get(TomoHDF5Config.ZSERIE_INIT_TITLES_DK, None) if zserie_init_titles is not None: zserie_init_titles = convert_str_to_tuple( zserie_init_titles, none_if_empty=True ) self.zserie_init_titles = zserie_init_titles # handle dark titles. empty string is consider as a valid value - dark_titles = dict_.get(HDF5Config.DARK_TITLES_DK, None) + dark_titles = dict_.get(TomoHDF5Config.DARK_TITLES_DK, None) if dark_titles is not None: dark_titles = convert_str_to_tuple(dark_titles, none_if_empty=True) self.dark_titles = dark_titles # handle ref titles. empty string is consider as a valid value - flat_titles = dict_.get(HDF5Config.REF_TITLES_DK, None) + flat_titles = dict_.get(TomoHDF5Config.REF_TITLES_DK, None) if flat_titles is not None: flat_titles = convert_str_to_tuple(flat_titles, none_if_empty=True) self.flat_titles = flat_titles # handle projection titles. empty string is consider as a valid value - proj_titles = dict_.get(HDF5Config.PROJ_TITLES_DK, None) + proj_titles = dict_.get(TomoHDF5Config.PROJ_TITLES_DK, None) if proj_titles is not None: proj_titles = convert_str_to_tuple(proj_titles, none_if_empty=True) self.projections_titles = proj_titles # handle alignment titles. empty string is consider as a valid value - alignment_titles = dict_.get(HDF5Config.ALIGNMENT_TITLES_DK, None) + alignment_titles = dict_.get(TomoHDF5Config.ALIGNMENT_TITLES_DK, None) if alignment_titles is not None: alignment_titles = convert_str_to_tuple( alignment_titles, none_if_empty=True @@ -1068,17 +1074,17 @@ class HDF5Config: def load_frame_type_section(self, dict_): # urls - data_urls = dict_.get(HDF5Config.DATA_DK, None) + data_urls = dict_.get(TomoHDF5Config.DATA_DK, None) if data_urls is not None: data_urls = convert_str_to_frame_grp(data_urls) self.data_frame_grps = data_urls - default_copy_behavior = dict_.get(HDF5Config.DEFAULT_DATA_COPY_DK, None) + default_copy_behavior = dict_.get(TomoHDF5Config.DEFAULT_DATA_COPY_DK, None) if default_copy_behavior is not None: self.default_copy_behavior = default_copy_behavior == "True" def load_extra_params_section(self, dict_): for key, value in dict_.items(): - if key in HDF5Config.EXTRA_PARAMS_ENERGY_VALID_KEYS: + if key in TomoHDF5Config.EXTRA_PARAMS_ENERGY_VALID_KEYS: self._param_already_defined.update( { key: value, @@ -1103,10 +1109,12 @@ class HDF5Config: config = configparser.ConfigParser(allow_no_value=True) for section_name, values in dict_.items(): config.add_section(section_name) - config.set(section_name, "# " + HDF5Config.get_comments(section_name), None) + config.set( + section_name, "# " + TomoHDF5Config.get_comments(section_name), None + ) for key, value in values.items(): # adopt nabu design: comments are set prior to the key - config.set(section_name, "# " + HDF5Config.get_comments(key), None) + config.set(section_name, "# " + TomoHDF5Config.get_comments(key), None) config.set(section_name, key, str(value)) with open(file_path, "w") as config_file: @@ -1114,18 +1122,24 @@ class HDF5Config: @staticmethod def from_cfg_file(file_path: str, encoding=None): + assert file_path is not None, "file_path should not be None" config_parser = configparser.ConfigParser(allow_no_value=True) config_parser.read(file_path, encoding=encoding) - return HDF5Config.from_dict(config_parser) + return TomoHDF5Config.from_dict(config_parser) @staticmethod def get_comments(key): - return HDF5Config.COMMENTS[key] + return TomoHDF5Config.COMMENTS[key] def __str__(self): return str(self.to_dict()) +class XRD3DHDF5Config(TomoHDF5Config): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def generate_default_h5_config() -> dict: """generate a default configuration for converting hdf5 to nx""" - return HDF5Config().to_dict() + return TomoHDF5Config().to_dict() diff --git a/nxtomomill/io/confighandler.py b/nxtomomill/io/confighandler.py index dd6cebd..8589fd6 100644 --- a/nxtomomill/io/confighandler.py +++ b/nxtomomill/io/confighandler.py @@ -34,7 +34,8 @@ __license__ = "MIT" __date__ = "08/03/2021" -from .config import HDF5Config +from .config import TomoHDF5Config +from .config import XRD3DHDF5Config from nxtomomill import utils from nxtomomill.utils import Format from nxtomomill.io.utils import filter_str_def @@ -96,30 +97,49 @@ def _extract_param_value(key_values): return res -class HDF5ConfigHandler: +class _BaseHDF5ConfigHandler: """Class to handle inputs to HDF5Config. And insure there is no opposite Information """ + @staticmethod + def get_tuple_of_keys_from_cmd(cmd_value): + return utils.get_tuple_of_keys_from_cmd(cmd_value) + + @staticmethod + def conv_str_to_bool(bstr): + return bstr in ("True", True) + + @staticmethod + def conv_log_level(bool_debug): + if bool_debug is True: + return "debug" + else: + return "warning" + + @staticmethod + def conv_xrd_ct_to_format(str_bool): + if str_bool in ("True", True): + return Format.XRD_CT + elif str_bool in ("False", False): + return Format.STANDARD + else: + return None + def __init__(self, argparse_options, raise_error=True): self._argparse_options = argparse_options self._config = None self.build_configuration(raise_error=raise_error) @property - def configuration(self) -> Union[None, HDF5Config]: + def configuration(self) -> Union[None, TomoHDF5Config]: return self._config @property def argparse_options(self): return self._argparse_options - def build_configuration(self, raise_error) -> bool: - """ - :param bool raise_error: raise error if encounter some errors. Else - display a log message - :return: True if the settings are valid - """ + def _check_argparse_options(self, raise_error): if self.argparse_options is None: err = "No argparse options provided" if raise_error: @@ -173,10 +193,19 @@ class HDF5ConfigHandler: _logger.error(err) return False - if options.config: - config = HDF5Config.from_cfg_file(options.config) - else: - config = HDF5Config() + def _create_HDF5_config(self): + raise NotImplementedError("BAse class") + + def build_configuration(self, raise_error) -> bool: + """ + :param bool raise_error: raise error if encounter some errors. Else + display a log message + :return: True if the settings are valid + """ + self._check_argparse_options(raise_error=raise_error) + options = self.argparse_options + config = self._create_HDF5_config() + # check input and output file if config.input_file is None: config.input_file = options.input_file @@ -215,52 +244,61 @@ class HDF5ConfigHandler: # key is the name of the argparse option. # value is a tuple: (name of the setter in the HDF5Config, # function to format the input) - # TODO: map all values - conv = utils.get_tuple_of_keys_from_cmd + self._config = self._map_option_to_config_param(config, options) - def conv_str_to_bool(bstr): - return bstr in ("True", True) + def _map_option_to_config_param(self, config, options): + raise NotImplementedError("Base class") - def conv_log_level(bool_debug): - if bool_debug is True: - return "debug" - else: - return "warning" + def __str__(self): + raise NotImplementedError("") - def conv_xrd_ct_to_format(str_bool): - if str_bool in ("True", True): - return Format.XRD_CT - elif str_bool in ("False", False): - return Format.STANDARD - else: - return None +class TomoHDF5ConfigHandler(_BaseHDF5ConfigHandler): + def _create_HDF5_config(self): + if self.argparse_options.config: + return TomoHDF5Config.from_cfg_file(self.argparse_options.config) + else: + return TomoHDF5Config() + + def _map_option_to_config_param(self, config, options): mapping = { - "valid_camera_names": ("valid_camera_names", conv), - "overwrite": ("overwrite", conv_str_to_bool), + "valid_camera_names": ( + "valid_camera_names", + self.get_tuple_of_keys_from_cmd, + ), + "overwrite": ("overwrite", self.conv_str_to_bool), "file_extension": ("file_extension", filter_str_def), - "single_file": ("single_file", conv_str_to_bool), - "debug": ("log_level", conv_log_level), - "entries": ("entries", conv), - "ignore_sub_entries": ("sub_entries_to_ignore", conv), - "raises_error": ("raises_error", conv_str_to_bool), + "single_file": ("single_file", self.conv_str_to_bool), + "debug": ("log_level", self.conv_log_level), + "entries": ("entries", self.get_tuple_of_keys_from_cmd), + "ignore_sub_entries": ( + "sub_entries_to_ignore", + self.get_tuple_of_keys_from_cmd, + ), + "raises_error": ("raises_error", self.conv_str_to_bool), "field_of_view": ("field_of_view", filter_str_def), - "request_input": ("request_input", conv_str_to_bool), - "is_xrd_ct_format": ("format", conv_xrd_ct_to_format), - "x_trans_keys": ("x_trans_keys", conv), - "y_trans_keys": ("y_trans_keys", conv), - "z_trans_keys": ("z_trans_keys", conv), - "rot_angle_keys": ("rotation_angle_keys", conv), - "sample_detector_distance": ("sample_detector_distance", conv), - "acq_expo_time_keys": ("exposition_time_keys", conv), - "x_pixel_size_key": ("x_pixel_size_paths", conv), - "y_pixel_size_key": ("y_pixel_size_paths", conv), - "init_titles": ("init_titles", conv), - "init_zserie_titles": ("zserie_init_titles", conv), - "dark_titles": ("dark_titles", conv), - "ref_titles": ("flat_titles", conv), - "proj_titles": ("projections_titles", conv), - "align_titles": ("alignment_titles", conv), + "request_input": ("request_input", self.conv_str_to_bool), + "is_xrd_ct_format": ("format", self.conv_xrd_ct_to_format), + "x_trans_keys": ("x_trans_keys", self.get_tuple_of_keys_from_cmd), + "y_trans_keys": ("y_trans_keys", self.get_tuple_of_keys_from_cmd), + "z_trans_keys": ("z_trans_keys", self.get_tuple_of_keys_from_cmd), + "rot_angle_keys": ("rotation_angle_keys", self.get_tuple_of_keys_from_cmd), + "sample_detector_distance": ("sample_detector_distance", self.get_tuple_of_keys_from_cmd), + "acq_expo_time_keys": ( + "exposition_time_keys", + self.get_tuple_of_keys_from_cmd, + ), + "x_pixel_size_key": ("x_pixel_size_paths", self.get_tuple_of_keys_from_cmd), + "y_pixel_size_key": ("y_pixel_size_paths", self.get_tuple_of_keys_from_cmd), + "init_titles": ("init_titles", self.get_tuple_of_keys_from_cmd), + "init_zserie_titles": ( + "zserie_init_titles", + self.get_tuple_of_keys_from_cmd, + ), + "dark_titles": ("dark_titles", self.get_tuple_of_keys_from_cmd), + "ref_titles": ("flat_titles", self.get_tuple_of_keys_from_cmd), + "proj_titles": ("projections_titles", self.get_tuple_of_keys_from_cmd), + "align_titles": ("alignment_titles", self.get_tuple_of_keys_from_cmd), "set_params": ("param_already_defined", _extract_param_value), } for argparse_name, (config_name, format_fct) in mapping.items(): @@ -268,7 +306,58 @@ class HDF5ConfigHandler: if argparse_value is not None: value = format_fct(argparse_value) setattr(config, config_name, value) - self._config = config + return config - def __str__(self): - raise NotImplementedError("") + +class XRD3DHDF5ConfigHandler(_BaseHDF5ConfigHandler): + def _create_HDF5_config(self): + if self.argparse_options.config: + return XRD3DHDF5Config.from_cfg_file(self.argparse_options.config) + else: + return XRD3DHDF5Config() + + def _map_option_to_config_param(self, config, options): + mapping = { + "valid_camera_names": ( + "valid_camera_names", + self.get_tuple_of_keys_from_cmd, + ), + "overwrite": ("overwrite", self.conv_str_to_bool), + "file_extension": ("file_extension", filter_str_def), + "single_file": ("single_file", self.conv_str_to_bool), + "debug": ("log_level", self.conv_log_level), + "entries": ("entries", self.get_tuple_of_keys_from_cmd), + "ignore_sub_entries": ( + "sub_entries_to_ignore", + self.get_tuple_of_keys_from_cmd, + ), + "raises_error": ("raises_error", self.conv_str_to_bool), + "field_of_view": ("field_of_view", filter_str_def), + "request_input": ("request_input", self.conv_str_to_bool), + "x_trans_keys": ("x_trans_keys", self.get_tuple_of_keys_from_cmd), + "y_trans_keys": ("y_trans_keys", self.get_tuple_of_keys_from_cmd), + "z_trans_keys": ("z_trans_keys", self.get_tuple_of_keys_from_cmd), + "rot_angle_keys": ("rotation_angle_keys", self.get_tuple_of_keys_from_cmd), + "acq_expo_time_keys": ( + "exposition_time_keys", + self.get_tuple_of_keys_from_cmd, + ), + "x_pixel_size_key": ("x_pixel_size_paths", self.get_tuple_of_keys_from_cmd), + "y_pixel_size_key": ("y_pixel_size_paths", self.get_tuple_of_keys_from_cmd), + "init_titles": ("init_titles", self.get_tuple_of_keys_from_cmd), + "init_zserie_titles": ( + "zserie_init_titles", + self.get_tuple_of_keys_from_cmd, + ), + "dark_titles": ("dark_titles", self.get_tuple_of_keys_from_cmd), + "ref_titles": ("flat_titles", self.get_tuple_of_keys_from_cmd), + "proj_titles": ("projections_titles", self.get_tuple_of_keys_from_cmd), + "align_titles": ("alignment_titles", self.get_tuple_of_keys_from_cmd), + "set_params": ("param_already_defined", _extract_param_value), + } + for argparse_name, (config_name, format_fct) in mapping.items(): + argparse_value = getattr(options, argparse_name) + if argparse_value is not None: + value = format_fct(argparse_value) + setattr(config, config_name, value) + return config diff --git a/nxtomomill/io/test/test_config.py b/nxtomomill/io/test/test_config.py index 40a958d..cb74e3a 100644 --- a/nxtomomill/io/test/test_config.py +++ b/nxtomomill/io/test/test_config.py @@ -31,7 +31,7 @@ __date__ = "23/02/2021" import unittest import shutil import tempfile -from nxtomomill.io.config import HDF5Config, generate_default_h5_config +from nxtomomill.io.config import TomoHDF5Config, generate_default_h5_config from nxtomomill import settings import os @@ -51,143 +51,148 @@ class TestH5Config(unittest.TestCase): """ Insure we can generate a default configuration """ - config = HDF5Config() + config = TomoHDF5Config() config.input_file = "toto.h5" config.output_file = "toto.nx" output = config.to_dict() self.assertEqual(type(output), dict) # check titles values - titles_dict = output[HDF5Config.ENTRIES_AND_TITLES_SECTION_DK] + titles_dict = output[TomoHDF5Config.ENTRIES_AND_TITLES_SECTION_DK] self.assertEqual( - titles_dict[HDF5Config.INIT_TITLES_DK], settings.Tomo.H5.H5_INIT_TITLES + titles_dict[TomoHDF5Config.INIT_TITLES_DK], settings.Tomo.H5.H5_INIT_TITLES ) self.assertEqual( - titles_dict[HDF5Config.ZSERIE_INIT_TITLES_DK], + titles_dict[TomoHDF5Config.ZSERIE_INIT_TITLES_DK], settings.Tomo.H5.H5_ZSERIE_INIT_TITLES, ) self.assertEqual( - titles_dict[HDF5Config.PROJ_TITLES_DK], settings.Tomo.H5.H5_PROJ_TITLES + titles_dict[TomoHDF5Config.PROJ_TITLES_DK], settings.Tomo.H5.H5_PROJ_TITLES ) self.assertEqual( - titles_dict[HDF5Config.REF_TITLES_DK], settings.Tomo.H5.H5_REF_TITLES + titles_dict[TomoHDF5Config.REF_TITLES_DK], settings.Tomo.H5.H5_REF_TITLES ) self.assertEqual( - titles_dict[HDF5Config.DARK_TITLES_DK], settings.Tomo.H5.H5_DARK_TITLES + titles_dict[TomoHDF5Config.DARK_TITLES_DK], settings.Tomo.H5.H5_DARK_TITLES ) self.assertEqual( - titles_dict[HDF5Config.ALIGNMENT_TITLES_DK], + titles_dict[TomoHDF5Config.ALIGNMENT_TITLES_DK], settings.Tomo.H5.H5_ALIGNMENT_TITLES, ) # check pixel size - keys_dict = output[HDF5Config.KEYS_SECTION_DK] + keys_dict = output[TomoHDF5Config.KEYS_SECTION_DK] self.assertEqual( - keys_dict[HDF5Config.X_PIXEL_SIZE_KEYS_DK], settings.Tomo.H5.H5_X_PIXEL_SIZE + keys_dict[TomoHDF5Config.X_PIXEL_SIZE_KEYS_DK], + settings.Tomo.H5.H5_X_PIXEL_SIZE, ) self.assertEqual( - keys_dict[HDF5Config.Y_PIXEL_SIZE_KEYS_DK], settings.Tomo.H5.H5_Y_PIXEL_SIZE + keys_dict[TomoHDF5Config.Y_PIXEL_SIZE_KEYS_DK], + settings.Tomo.H5.H5_Y_PIXEL_SIZE, ) # check translation self.assertEqual( - keys_dict[HDF5Config.X_TRANS_KEYS_DK], settings.Tomo.H5.H5_X_TRANS_KEYS + keys_dict[TomoHDF5Config.X_TRANS_KEYS_DK], settings.Tomo.H5.H5_X_TRANS_KEYS ) self.assertEqual( - keys_dict[HDF5Config.Y_TRANS_KEYS_DK], settings.Tomo.H5.H5_Y_TRANS_KEYS + keys_dict[TomoHDF5Config.Y_TRANS_KEYS_DK], settings.Tomo.H5.H5_Y_TRANS_KEYS ) self.assertEqual( - keys_dict[HDF5Config.Z_TRANS_KEYS_DK], settings.Tomo.H5.H5_Z_TRANS_KEYS + keys_dict[TomoHDF5Config.Z_TRANS_KEYS_DK], settings.Tomo.H5.H5_Z_TRANS_KEYS ) # others if settings.Tomo.H5.H5_VALID_CAMERA_NAMES is None: - self.assertEqual(keys_dict[HDF5Config.VALID_CAMERA_DK], "") + self.assertEqual(keys_dict[TomoHDF5Config.VALID_CAMERA_DK], "") else: self.assertEqual( - keys_dict[HDF5Config.VALID_CAMERA_DK], + keys_dict[TomoHDF5Config.VALID_CAMERA_DK], settings.Tomo.H5.H5_VALID_CAMERA_NAMES, ) self.assertEqual( - keys_dict[HDF5Config.ROT_ANGLE_DK], settings.Tomo.H5.H5_ROT_ANGLE_KEYS + keys_dict[TomoHDF5Config.ROT_ANGLE_DK], settings.Tomo.H5.H5_ROT_ANGLE_KEYS ) self.assertEqual( - keys_dict[HDF5Config.DIODE_KEYS_DK], settings.Tomo.H5.H5_DIODE_KEYS + keys_dict[TomoHDF5Config.DIODE_KEYS_DK], settings.Tomo.H5.H5_DIODE_KEYS ) self.assertEqual( - keys_dict[HDF5Config.Y_ROT_KEYS_DK], settings.Tomo.H5.H5_Y_ROT_KEY + keys_dict[TomoHDF5Config.Y_ROT_KEYS_DK], settings.Tomo.H5.H5_Y_ROT_KEY ) self.assertEqual( - keys_dict[HDF5Config.ACQUISITION_EXPO_TIME_KEYS_DK], + keys_dict[TomoHDF5Config.ACQUISITION_EXPO_TIME_KEYS_DK], settings.Tomo.H5.H5_ACQ_EXPO_TIME_KEYS, ) # check input and output file - general_information = output[HDF5Config.GENERAL_SECTION_DK] - self.assertEqual(general_information[HDF5Config.INPUT_FILE_DK], "toto.h5") - self.assertEqual(general_information[HDF5Config.OUTPUT_FILE_DK], "toto.nx") + general_information = output[TomoHDF5Config.GENERAL_SECTION_DK] + self.assertEqual(general_information[TomoHDF5Config.INPUT_FILE_DK], "toto.h5") + self.assertEqual(general_information[TomoHDF5Config.OUTPUT_FILE_DK], "toto.nx") def test_to_dict(self): """test the `to_dict` function""" - config = HDF5Config() + config = TomoHDF5Config() output_dict = config.to_dict() self.assertEqual(type(output_dict), dict) # check sections for section in ( - HDF5Config.GENERAL_SECTION_DK, - HDF5Config.KEYS_SECTION_DK, - HDF5Config.EXTRA_PARAMS_SECTION_DK, - HDF5Config.FRAME_TYPE_SECTION_DK, - HDF5Config.ENTRIES_AND_TITLES_SECTION_DK, + TomoHDF5Config.GENERAL_SECTION_DK, + TomoHDF5Config.KEYS_SECTION_DK, + TomoHDF5Config.EXTRA_PARAMS_SECTION_DK, + TomoHDF5Config.FRAME_TYPE_SECTION_DK, + TomoHDF5Config.ENTRIES_AND_TITLES_SECTION_DK, ): with self.subTest(section=section): self.assertTrue(section in output_dict) # check titles keys for key in ( - HDF5Config.ALIGNMENT_TITLES_DK, - HDF5Config.PROJ_TITLES_DK, - HDF5Config.ZSERIE_INIT_TITLES_DK, - HDF5Config.INIT_TITLES_DK, - HDF5Config.REF_TITLES_DK, - HDF5Config.DARK_TITLES_DK, + TomoHDF5Config.ALIGNMENT_TITLES_DK, + TomoHDF5Config.PROJ_TITLES_DK, + TomoHDF5Config.ZSERIE_INIT_TITLES_DK, + TomoHDF5Config.INIT_TITLES_DK, + TomoHDF5Config.REF_TITLES_DK, + TomoHDF5Config.DARK_TITLES_DK, ): with self.subTest(key=key): self.assertTrue( - key in output_dict[HDF5Config.ENTRIES_AND_TITLES_SECTION_DK] + key in output_dict[TomoHDF5Config.ENTRIES_AND_TITLES_SECTION_DK] ) # check pixel size - for key in (HDF5Config.X_PIXEL_SIZE_KEYS_DK, HDF5Config.Y_PIXEL_SIZE_KEYS_DK): + for key in ( + TomoHDF5Config.X_PIXEL_SIZE_KEYS_DK, + TomoHDF5Config.Y_PIXEL_SIZE_KEYS_DK, + ): with self.subTest(key=key): - self.assertTrue(key in output_dict[HDF5Config.KEYS_SECTION_DK]) + self.assertTrue(key in output_dict[TomoHDF5Config.KEYS_SECTION_DK]) # translation keys for key in ( - HDF5Config.X_TRANS_KEYS_DK, - HDF5Config.Y_TRANS_KEYS_DK, - HDF5Config.Z_TRANS_KEYS_DK, + TomoHDF5Config.X_TRANS_KEYS_DK, + TomoHDF5Config.Y_TRANS_KEYS_DK, + TomoHDF5Config.Z_TRANS_KEYS_DK, ): with self.subTest(key=key): - self.assertTrue(key in output_dict[HDF5Config.KEYS_SECTION_DK]) + self.assertTrue(key in output_dict[TomoHDF5Config.KEYS_SECTION_DK]) # others for key in ( - HDF5Config.VALID_CAMERA_DK, - HDF5Config.ROT_ANGLE_DK, - HDF5Config.Y_ROT_KEYS_DK, - HDF5Config.DIODE_KEYS_DK, - HDF5Config.ACQUISITION_EXPO_TIME_KEYS_DK, + TomoHDF5Config.VALID_CAMERA_DK, + TomoHDF5Config.ROT_ANGLE_DK, + TomoHDF5Config.Y_ROT_KEYS_DK, + TomoHDF5Config.DIODE_KEYS_DK, + TomoHDF5Config.ACQUISITION_EXPO_TIME_KEYS_DK, ): with self.subTest(key=key): - self.assertTrue(key in output_dict[HDF5Config.KEYS_SECTION_DK]) + self.assertTrue(key in output_dict[TomoHDF5Config.KEYS_SECTION_DK]) def test_from_dict(self): """test the `from_dict` function""" valid_camera_names = ("frelon", "totocam") alignment_titles = ("this is an alignment",) x_trans_keys = ("tx", "x") - config = HDF5Config.from_dict( + config = TomoHDF5Config.from_dict( { - HDF5Config.KEYS_SECTION_DK: { - HDF5Config.VALID_CAMERA_DK: valid_camera_names, - HDF5Config.X_TRANS_KEYS_DK: x_trans_keys, + TomoHDF5Config.KEYS_SECTION_DK: { + TomoHDF5Config.VALID_CAMERA_DK: valid_camera_names, + TomoHDF5Config.X_TRANS_KEYS_DK: x_trans_keys, }, - HDF5Config.ENTRIES_AND_TITLES_SECTION_DK: { - HDF5Config.ALIGNMENT_TITLES_DK: alignment_titles, + TomoHDF5Config.ENTRIES_AND_TITLES_SECTION_DK: { + TomoHDF5Config.ALIGNMENT_TITLES_DK: alignment_titles, }, } ) @@ -202,10 +207,10 @@ class TestH5Config(unittest.TestCase): :return: """ with self.assertRaises(TypeError): - HDF5Config.from_dict( + TomoHDF5Config.from_dict( { - HDF5Config.ENTRIES_AND_TITLES_SECTION_DK: { - HDF5Config.DARK_TITLES_DK: 1213, + TomoHDF5Config.ENTRIES_AND_TITLES_SECTION_DK: { + TomoHDF5Config.DARK_TITLES_DK: 1213, } } ) @@ -216,11 +221,11 @@ class TestH5Config(unittest.TestCase): can read it back """ file_path = os.path.join(self.folder, "output_file.cfg") - input_config = HDF5Config() + input_config = TomoHDF5Config() input_config.to_cfg_file(file_path) self.assertTrue(os.path.exists(file_path)) - loaded_config = HDF5Config.from_cfg_file(file_path=file_path) - self.assertTrue(isinstance(loaded_config, HDF5Config)) + loaded_config = TomoHDF5Config.from_cfg_file(file_path=file_path) + self.assertTrue(isinstance(loaded_config, TomoHDF5Config)) def suite(): diff --git a/nxtomomill/io/test/test_confighandler.py b/nxtomomill/io/test/test_confighandler.py index 997ecdd..56f43e1 100644 --- a/nxtomomill/io/test/test_confighandler.py +++ b/nxtomomill/io/test/test_confighandler.py @@ -28,8 +28,8 @@ __license__ = "MIT" __date__ = "10/03/2021" -from nxtomomill.io.confighandler import HDF5ConfigHandler -from nxtomomill.io.confighandler import HDF5Config +from nxtomomill.io.confighandler import TomoHDF5ConfigHandler +from nxtomomill.io.confighandler import TomoHDF5Config from nxtomomill.io.framegroup import FrameGroup from silx.io.url import DataUrl import configparser @@ -86,29 +86,29 @@ class TestH5Config(unittest.TestCase): def test_creation_from_config_file(self): options = _ARParseMock() with self.assertRaises(ValueError): - HDF5ConfigHandler(argparse_options=options) + TomoHDF5ConfigHandler(argparse_options=options) input_file_path = os.path.join(self.folder, "output_file.cfg") - input_config = HDF5Config() + input_config = TomoHDF5Config() input_config.to_cfg_file(input_file_path) options.config = input_file_path with self.assertRaises(ValueError): - HDF5ConfigHandler(argparse_options=options) + TomoHDF5ConfigHandler(argparse_options=options) # insure this is valid if we add an input file and an output file # from the command line options.input_file = "toto.h5" options.output_file = "toto.nx" - HDF5ConfigHandler(argparse_options=options) + TomoHDF5ConfigHandler(argparse_options=options) # try providing twice an input file input_config.input_file = "toto2.h5" input_config.to_cfg_file(input_file_path) with self.assertRaises(ValueError): - HDF5ConfigHandler(argparse_options=options) + TomoHDF5ConfigHandler(argparse_options=options) # or if we provide them from the configuration file options.input_file = None @@ -116,14 +116,14 @@ class TestH5Config(unittest.TestCase): input_config.input_file = "toto.h5" input_config.output_file = "toto.nx" input_config.to_cfg_file(input_file_path) - HDF5ConfigHandler(argparse_options=options) + TomoHDF5ConfigHandler(argparse_options=options) # try providing twice an output file input_config.input_file = None input_config.output_file = "toto2.nx" input_config.to_cfg_file(input_file_path) with self.assertRaises(ValueError): - HDF5ConfigHandler(argparse_options=options) + TomoHDF5ConfigHandler(argparse_options=options) # try another random para,eter input_config.output_file = None @@ -131,21 +131,21 @@ class TestH5Config(unittest.TestCase): options.x_trans_keys = "xtrans3" input_config.to_cfg_file(input_file_path) with self.assertRaises(ValueError): - HDF5ConfigHandler(argparse_options=options) + TomoHDF5ConfigHandler(argparse_options=options) def test_creation_from_cmd_line_opts(self): options = _ARParseMock() input_file_path = os.path.join(self.folder, "output_file.cfg") - input_config = HDF5Config() + input_config = TomoHDF5Config() input_config.to_cfg_file(input_file_path) options.input_file = "toto.h5" options.output_file = "toto.nx" options.debug = True - HDF5ConfigHandler(argparse_options=options) + TomoHDF5ConfigHandler(argparse_options=options) options.config = input_config with self.assertRaises(ValueError): - HDF5ConfigHandler(argparse_options=options) + TomoHDF5ConfigHandler(argparse_options=options) class TestFrameUrls(unittest.TestCase): @@ -158,18 +158,18 @@ class TestFrameUrls(unittest.TestCase): shutil.rmtree(self.folder) def write_and_read_configuration(self, data_urls): - configuration = HDF5Config().to_dict() - configuration[HDF5Config.FRAME_TYPE_SECTION_DK][ - HDF5Config.DATA_DK + configuration = TomoHDF5Config().to_dict() + configuration[TomoHDF5Config.FRAME_TYPE_SECTION_DK][ + TomoHDF5Config.DATA_DK ] = FrameGroup.list_to_str(data_urls) file_path = os.path.join(self.folder, "h52nx.cfg") - HDF5Config.dict_to_cfg(file_path=file_path, dict_=configuration) + TomoHDF5Config.dict_to_cfg(file_path=file_path, dict_=configuration) options = _ARParseMock() options.input_file = "toto.h5" options.output_file = "toto.nx" options.config = file_path - config_handler = HDF5ConfigHandler(options) + config_handler = TomoHDF5ConfigHandler(options) return config_handler.configuration def test_local_paths(self): diff --git a/nxtomomill/settings.py b/nxtomomill/settings.py index c8b466b..5348a6b 100644 --- a/nxtomomill/settings.py +++ b/nxtomomill/settings.py @@ -143,7 +143,6 @@ class Tomo: class XRD3D(Tomo): class H5(Tomo.H5): - ROCKING_KEYS = (None,) + ROCKING_KEYS = ("mcha4_raw",) - BASE_TILT_KEYS = (None,) ->>>>>>> 4ce9671... [settings] create a namespace Tomo and Tomo.H5, Tomo.EDF + BASE_TILT_KEYS = ("mcha5_raw",) diff --git a/nxtomomill/utils.py b/nxtomomill/utils.py index c165b9c..243ffe0 100644 --- a/nxtomomill/utils.py +++ b/nxtomomill/utils.py @@ -165,6 +165,7 @@ class FileExtension(Enum): class Format(Enum): STANDARD = "standard" XRD_CT = "xrd-ct" + XRD_3D = "3d-xrd" def get_file_name(file_name, extension, check=True): -- GitLab From bad5615a9527f600d2445d604c25863e58f9d325 Mon Sep 17 00:00:00 2001 From: payno Date: Thu, 29 Apr 2021 08:27:45 +0200 Subject: [PATCH 3/8] create XRD3DAcquisition # Conflicts: # nxtomomill/io/confighandler.py --- nxtomomill/app/h5_3dxrd2nx.py | 52 ++++-- .../hdf5/acquisition/standardacquisition.py | 7 +- .../hdf5/acquisition/xrd3dacquisition.py | 6 +- nxtomomill/converter/hdf5/hdf5converter.py | 6 +- nxtomomill/io/confighandler.py | 174 ++++++++++++------ 5 files changed, 163 insertions(+), 82 deletions(-) diff --git a/nxtomomill/app/h5_3dxrd2nx.py b/nxtomomill/app/h5_3dxrd2nx.py index a4fbb32..9c372d9 100644 --- a/nxtomomill/app/h5_3dxrd2nx.py +++ b/nxtomomill/app/h5_3dxrd2nx.py @@ -86,18 +86,19 @@ def main(argv): parser.add_argument( "output_file", help="output .nx or .h5 file", default=None, nargs="?" ) + parser.add_argument( "--file-extension", "--file_extension", default=None, help="extension of the output file. Valid values are " - "" + "/".join(utils.FileExtension.values()), + "" + "/".join(utils.FileExtension.values()), ) parser.add_argument( "--single-file", help="merge all scan sequence to the same output file. " - "By default create one file per sequence and " - "group all sequence in the output file", + "By default create one file per sequence and " + "group all sequence in the output file", dest="single_file", action="store_true", default=None, @@ -117,7 +118,7 @@ def main(argv): parser.add_argument( "--entries", help="Specify (root) entries to be converted. By default it will try " - "to convert all existing entries.", + "to convert all existing entries.", default=None, ) parser.add_argument( @@ -128,14 +129,14 @@ def main(argv): parser.add_argument( "--raises-error", help="Raise errors if some data are not met instead of providing some" - " default values", + " default values", action="store_true", default=None, ) parser.add_argument( "--field-of-view", help="Force the output to be `Half` or `Full` acquisition. Otherwise " - "parse raw data to find this information.", + "parse raw data to find this information.", default=None, ) parser.add_argument( @@ -146,6 +147,21 @@ def main(argv): action="store_false", default=None, ) + parser.add_argument( + "--standard-format", + help="Format of the input file is the 'standard' tomography format", + dest="is_xrd_ct_format", + action="store_false", + default=None, + ) + parser.add_argument( + "--xrd-ct-format", + help="Format of the input file is the 'XRD-CT' tomography format", + dest="is_xrd_ct_format", + action="store_true", + default=None, + ) + parser.add_argument( "--x_trans_keys", "--x-trans-keys", @@ -164,13 +180,19 @@ def main(argv): default=None, help="z translation key in bliss HDF5 file", ) + parser.add_argument( + "--sample-detector-distance", + "--distance", + default=None, + help="sample detector distance", + ) parser.add_argument( "--valid_camera_names", "--valid-camera-names", default=None, help="Valid NXDetector dataset name to be considered. Otherwise will" - "try to deduce them from NX_class attibute (value should be" - "NXdetector) or from instrument group child structure.", + "try to deduce them from NX_class attibute (value should be" + "NXdetector) or from instrument group child structure.", ) parser.add_argument( "--rot_angle_keys", @@ -239,12 +261,11 @@ def main(argv): default=None, nargs="*", help="Allow manual definition of some parameters. " - "Valid parameters (and expected input unit) " - "are: {}. Should be added at the end of the command line because " - "will try to cover all text set after this " - "option.".format(_getPossibleInputParams()), + "Valid parameters (and expected input unit) " + "are: {}. Should be added at the end of the command line because " + "will try to cover all text set after this " + "option.".format(_getPossibleInputParams()), ) - # TODO: add base tilt and rocking settings parser.add_argument( "--config", @@ -253,14 +274,13 @@ def main(argv): "--configuration-file", default=None, help="file containing the full configuration to convert from h5 " - "bliss to nexus", + "bliss to nexus", ) options = parser.parse_args(argv[1:]) if options.request_input: callback_det_sel = _ask_for_selecting_detector else: - callback_det_sel = None - configuration_handler = XRD3DHDF5ConfigHandler(options, raise_error=True) + callback_det_sel = _ask_for_selecting_detector try: configuration_handler = XRD3DHDF5ConfigHandler(options, raise_error=True) except Exception as e: diff --git a/nxtomomill/converter/hdf5/acquisition/standardacquisition.py b/nxtomomill/converter/hdf5/acquisition/standardacquisition.py index 9e02be0..b71c79d 100644 --- a/nxtomomill/converter/hdf5/acquisition/standardacquisition.py +++ b/nxtomomill/converter/hdf5/acquisition/standardacquisition.py @@ -503,7 +503,7 @@ class StandardAcquisition(BaseAcquisition): return values, unit def _write_beam(self, root_node, request_input, input_callback): - beam_node = root_node.create_group("beam") + beam_node = root_node.require_group("beam") if not self.has_diode: if "energy" in self.configuration.param_already_defined: energy = float(self.configuration.param_already_defined["energy"]) @@ -517,11 +517,11 @@ class StandardAcquisition(BaseAcquisition): beam_node["incident_energy"].attrs["unit"] = unit def _write_instrument(self, root_node): - instrument_node = root_node.create_group("instrument") + instrument_node = root_node.require_group("instrument") instrument_node.attrs["NX_class"] = "NXinstrument" instrument_node.attrs["default"] = "detector" - detector_node = instrument_node.create_group("detector") + detector_node = instrument_node.require_group("detector") detector_node.attrs["NX_class"] = "NXdetector" # write data if self._virtual_sources is not None: @@ -575,6 +575,7 @@ class StandardAcquisition(BaseAcquisition): detector_node["estimated_cor_from_motor"].attrs["unit"] = unit def _create_data_virtual_dataset(self, detector_node): + print("_create_data_virtual_dataset") if ( self.n_frames is None or self.dim_1 is None diff --git a/nxtomomill/converter/hdf5/acquisition/xrd3dacquisition.py b/nxtomomill/converter/hdf5/acquisition/xrd3dacquisition.py index 808b629..556011e 100644 --- a/nxtomomill/converter/hdf5/acquisition/xrd3dacquisition.py +++ b/nxtomomill/converter/hdf5/acquisition/xrd3dacquisition.py @@ -95,11 +95,11 @@ class XRD3DAcquisition(StandardAcquisition): self._base_tilt = None def _preprocess_registered_entries(self, output_file): - super()._preprocess_register_entries(output_file=output_file) + super()._preprocess_registered_entries(output_file=output_file) self._base_tilt = [] self._rocking = [] def _write_instrument(self, root_node): super()._write_instrument(root_node) - instrument_node = root_node.create_group("instrument") - raise NotImplementedError() + #instrument_node = root_node.create_group("instrument") + #raise NotImplementedError() diff --git a/nxtomomill/converter/hdf5/hdf5converter.py b/nxtomomill/converter/hdf5/hdf5converter.py index e9f39d1..c3dd257 100644 --- a/nxtomomill/converter/hdf5/hdf5converter.py +++ b/nxtomomill/converter/hdf5/hdf5converter.py @@ -292,17 +292,17 @@ class _H5ToNxConverter: configuration=self.configuration, detector_sel_callback=self.detector_sel_callback, ) - elif current_format is Format.XRD_3D: + elif current_format is Format.XRD_CT: root_acquisition = XRDCTAcquisition( configuration=self.configuration, detector_sel_callback=self.detector_sel_callback, copy_frames=frame_grp.copy, ) - elif current_format is Format.XRD_CT: + elif current_format is Format.XRD_3D: root_acquisition = XRD3DAcquisition( + root_url=frame_grp.url, configuration=self.configuration, detector_sel_callback=self.detector_sel_callback, - copy_frames=frame_grp.copy, ) else: raise ValueError("Format {} is not handled".format(current_format)) diff --git a/nxtomomill/io/confighandler.py b/nxtomomill/io/confighandler.py index 8589fd6..fa05069 100644 --- a/nxtomomill/io/confighandler.py +++ b/nxtomomill/io/confighandler.py @@ -140,58 +140,7 @@ class _BaseHDF5ConfigHandler: return self._argparse_options def _check_argparse_options(self, raise_error): - if self.argparse_options is None: - err = "No argparse options provided" - if raise_error: - raise ValueError(err) - else: - _logger.error(err) - return False - - options = self.argparse_options - if options.config is not None: - # check no other option are provided - duplicated_inputs = [] - for opt in ( - "set_params", - "align_titles", - "proj_titles", - "ref_titles", - "dark_titles", - "init_zserie_titles", - "init_titles", - "init_zserie_titles", - "x_pixel_size_key", - "y_pixel_size_key", - "acq_expo_time_keys", - "rot_angle_keys", - "valid_camera_names", - "z_trans_keys", - "y_trans_keys", - "x_trans_keys", - "is_xrd_ct_format", - "request_input", - "raises_error", - "ignore_sub_entries", - "entries", - "debug", - "overwrite", - "single_file", - "file_extension", - "field_of_view", - "sample_detector_distance", - ): - if getattr(options, opt): - duplicated_inputs.append(opt) - if len(duplicated_inputs) > 0: - err = "You provided a configuration file and inputs " "for {}".format( - duplicated_inputs - ) - if raise_error: - raise ValueError(err) - else: - _logger.error(err) - return False + raise NotImplementedError("BaseClass") def _create_HDF5_config(self): raise NotImplementedError("BAse class") @@ -308,6 +257,59 @@ class TomoHDF5ConfigHandler(_BaseHDF5ConfigHandler): setattr(config, config_name, value) return config + def _check_argparse_options(self, raise_error): + if self.argparse_options is None: + err = "No argparse options provided" + if raise_error: + raise ValueError(err) + else: + _logger.error(err) + return False + + options = self.argparse_options + if options.config is not None: + # check no other option are provided + duplicated_inputs = [] + for opt in ( + "set_params", + "align_titles", + "proj_titles", + "ref_titles", + "dark_titles", + "init_zserie_titles", + "init_titles", + "init_zserie_titles", + "x_pixel_size_key", + "y_pixel_size_key", + "acq_expo_time_keys", + "rot_angle_keys", + "valid_camera_names", + "z_trans_keys", + "y_trans_keys", + "x_trans_keys", + "is_xrd_ct_format", + "request_input", + "raises_error", + "ignore_sub_entries", + "entries", + "debug", + "overwrite", + "single_file", + "file_extension", + "field_of_view", + "sample_detector_distance", + ): + if getattr(options, opt): + duplicated_inputs.append(opt) + if len(duplicated_inputs) > 0: + err = "You provided a configuration file and inputs " "for {}".format( + duplicated_inputs + ) + if raise_error: + raise ValueError(err) + else: + _logger.error(err) + return False class XRD3DHDF5ConfigHandler(_BaseHDF5ConfigHandler): def _create_HDF5_config(self): @@ -337,13 +339,16 @@ class XRD3DHDF5ConfigHandler(_BaseHDF5ConfigHandler): "x_trans_keys": ("x_trans_keys", self.get_tuple_of_keys_from_cmd), "y_trans_keys": ("y_trans_keys", self.get_tuple_of_keys_from_cmd), "z_trans_keys": ("z_trans_keys", self.get_tuple_of_keys_from_cmd), - "rot_angle_keys": ("rotation_angle_keys", self.get_tuple_of_keys_from_cmd), + "rot_angle_keys": ( + "rotation_angle_keys", self.get_tuple_of_keys_from_cmd), "acq_expo_time_keys": ( "exposition_time_keys", self.get_tuple_of_keys_from_cmd, ), - "x_pixel_size_key": ("x_pixel_size_paths", self.get_tuple_of_keys_from_cmd), - "y_pixel_size_key": ("y_pixel_size_paths", self.get_tuple_of_keys_from_cmd), + "x_pixel_size_key": ( + "x_pixel_size_paths", self.get_tuple_of_keys_from_cmd), + "y_pixel_size_key": ( + "y_pixel_size_paths", self.get_tuple_of_keys_from_cmd), "init_titles": ("init_titles", self.get_tuple_of_keys_from_cmd), "init_zserie_titles": ( "zserie_init_titles", @@ -351,8 +356,10 @@ class XRD3DHDF5ConfigHandler(_BaseHDF5ConfigHandler): ), "dark_titles": ("dark_titles", self.get_tuple_of_keys_from_cmd), "ref_titles": ("flat_titles", self.get_tuple_of_keys_from_cmd), - "proj_titles": ("projections_titles", self.get_tuple_of_keys_from_cmd), - "align_titles": ("alignment_titles", self.get_tuple_of_keys_from_cmd), + "proj_titles": ( + "projections_titles", self.get_tuple_of_keys_from_cmd), + "align_titles": ( + "alignment_titles", self.get_tuple_of_keys_from_cmd), "set_params": ("param_already_defined", _extract_param_value), } for argparse_name, (config_name, format_fct) in mapping.items(): @@ -361,3 +368,56 @@ class XRD3DHDF5ConfigHandler(_BaseHDF5ConfigHandler): value = format_fct(argparse_value) setattr(config, config_name, value) return config + + def _check_argparse_options(self, raise_error): + if self.argparse_options is None: + err = "No argparse options provided" + if raise_error: + raise ValueError(err) + else: + _logger.error(err) + return False + + options = self.argparse_options + if options.config is not None: + # check no other option are provided + duplicated_inputs = [] + for opt in ( + "set_params", + "align_titles", + "proj_titles", + "ref_titles", + "dark_titles", + "init_zserie_titles", + "init_titles", + "init_zserie_titles", + "x_pixel_size_key", + "y_pixel_size_key", + "acq_expo_time_keys", + "rot_angle_keys", + "valid_camera_names", + "z_trans_keys", + "y_trans_keys", + "x_trans_keys", + "request_input", + "raises_error", + "ignore_sub_entries", + "entries", + "debug", + "overwrite", + "single_file", + "file_extension", + "field_of_view", + "sample_detector_distance", + ): + if getattr(options, opt): + duplicated_inputs.append(opt) + if len(duplicated_inputs) > 0: + err = "You provided a configuration file and inputs " "for {}".format( + duplicated_inputs + ) + if raise_error: + raise ValueError(err) + else: + _logger.error(err) + return False -- GitLab From f44914b0fdbed8e3010721ccde13353d81137741 Mon Sep 17 00:00:00 2001 From: payno Date: Thu, 29 Apr 2021 08:28:15 +0200 Subject: [PATCH 4/8] one more step on addinf 3D-XRD. Add rocking and base tilt datasets # Conflicts: # nxtomomill/io/confighandler.py --- nxtomomill/app/h5_3dxrd2nx.py | 28 +++---- .../hdf5/acquisition/standardacquisition.py | 6 +- .../hdf5/acquisition/xrd3dacquisition.py | 78 ++++++++++++++++--- nxtomomill/io/config.py | 43 ++++++++++ nxtomomill/io/confighandler.py | 70 ++++++++--------- nxtomomill/settings.py | 4 +- 6 files changed, 165 insertions(+), 64 deletions(-) diff --git a/nxtomomill/app/h5_3dxrd2nx.py b/nxtomomill/app/h5_3dxrd2nx.py index 9c372d9..187ff3e 100644 --- a/nxtomomill/app/h5_3dxrd2nx.py +++ b/nxtomomill/app/h5_3dxrd2nx.py @@ -40,6 +40,7 @@ from nxtomomill.io.confighandler import XRD3DHDF5ConfigHandler from nxtomomill.io.confighandler import SETTABLE_PARAMETERS_UNITS from collections.abc import Iterable from nxtomomill.utils import Format +from nxtomomill.io.config import XRD3DHDF5Config import argparse @@ -92,13 +93,13 @@ def main(argv): "--file_extension", default=None, help="extension of the output file. Valid values are " - "" + "/".join(utils.FileExtension.values()), + "" + "/".join(utils.FileExtension.values()), ) parser.add_argument( "--single-file", help="merge all scan sequence to the same output file. " - "By default create one file per sequence and " - "group all sequence in the output file", + "By default create one file per sequence and " + "group all sequence in the output file", dest="single_file", action="store_true", default=None, @@ -118,7 +119,7 @@ def main(argv): parser.add_argument( "--entries", help="Specify (root) entries to be converted. By default it will try " - "to convert all existing entries.", + "to convert all existing entries.", default=None, ) parser.add_argument( @@ -129,14 +130,14 @@ def main(argv): parser.add_argument( "--raises-error", help="Raise errors if some data are not met instead of providing some" - " default values", + " default values", action="store_true", default=None, ) parser.add_argument( "--field-of-view", help="Force the output to be `Half` or `Full` acquisition. Otherwise " - "parse raw data to find this information.", + "parse raw data to find this information.", default=None, ) parser.add_argument( @@ -191,8 +192,8 @@ def main(argv): "--valid-camera-names", default=None, help="Valid NXDetector dataset name to be considered. Otherwise will" - "try to deduce them from NX_class attibute (value should be" - "NXdetector) or from instrument group child structure.", + "try to deduce them from NX_class attibute (value should be" + "NXdetector) or from instrument group child structure.", ) parser.add_argument( "--rot_angle_keys", @@ -261,10 +262,10 @@ def main(argv): default=None, nargs="*", help="Allow manual definition of some parameters. " - "Valid parameters (and expected input unit) " - "are: {}. Should be added at the end of the command line because " - "will try to cover all text set after this " - "option.".format(_getPossibleInputParams()), + "Valid parameters (and expected input unit) " + "are: {}. Should be added at the end of the command line because " + "will try to cover all text set after this " + "option.".format(_getPossibleInputParams()), ) parser.add_argument( @@ -274,7 +275,7 @@ def main(argv): "--configuration-file", default=None, help="file containing the full configuration to convert from h5 " - "bliss to nexus", + "bliss to nexus", ) options = parser.parse_args(argv[1:]) if options.request_input: @@ -288,6 +289,7 @@ def main(argv): return else: configuration = configuration_handler.configuration + assert isinstance(configuration, XRD3DHDF5Config) for title in configuration.init_titles: assert title != "" configuration.format = Format.XRD_3D diff --git a/nxtomomill/converter/hdf5/acquisition/standardacquisition.py b/nxtomomill/converter/hdf5/acquisition/standardacquisition.py index b71c79d..8eb0be4 100644 --- a/nxtomomill/converter/hdf5/acquisition/standardacquisition.py +++ b/nxtomomill/converter/hdf5/acquisition/standardacquisition.py @@ -107,6 +107,7 @@ class StandardAcquisition(BaseAcquisition): self._acq_expo_time = None self._copied_dataset = {} "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 @property def image_key(self): @@ -284,7 +285,7 @@ class StandardAcquisition(BaseAcquisition): self._virtual_sources_len.append(n_frame) return n_frame - def __treate_valid_camera( + def _treate_valid_camera( self, detector_node, entry, @@ -388,6 +389,7 @@ class StandardAcquisition(BaseAcquisition): n_frame=n_frame, ) ) + self._current_scan_n_frame = n_frame def camera_is_valid(self, det_name): assert isinstance(det_name, str) @@ -449,7 +451,7 @@ class StandardAcquisition(BaseAcquisition): continue else: detector_node = instrument_grp[key] - self.__treate_valid_camera( + self._treate_valid_camera( detector_node, entry=entry, frame_type=type_, diff --git a/nxtomomill/converter/hdf5/acquisition/xrd3dacquisition.py b/nxtomomill/converter/hdf5/acquisition/xrd3dacquisition.py index 556011e..4a2d6ee 100644 --- a/nxtomomill/converter/hdf5/acquisition/xrd3dacquisition.py +++ b/nxtomomill/converter/hdf5/acquisition/xrd3dacquisition.py @@ -38,6 +38,9 @@ __date__ = "19/04/2021" from nxtomomill.converter.hdf5.acquisition.standardacquisition import ( StandardAcquisition, ) +import logging + +_logger = logging.getLogger(__name__) class XRD3DAcquisition(StandardAcquisition): @@ -63,12 +66,52 @@ class XRD3DAcquisition(StandardAcquisition): self._rocking = rocking def _get_rocking_dataset(self, entry, n_frames): - raise NotImplementedError() + for grp in self._get_positioners_node(entry), entry: + try: + rocking, unit = self._get_node_values_for_frame_array( + node=grp, + n_frame=n_frames, + keys=self.configuration.rocking_keys, + info_retrieve="rocking", + expected_unit=None, + ) + except (ValueError, KeyError): + pass + else: + return rocking, None + + mess = "Unable to find rocking for {}" "".format(self.root_url.path()) + if self.raise_error_if_issue: + raise ValueError(mess) + else: + mess += "default value will be set. (0)" + _logger.warning(mess) + return 0, None def _get_base_tilt_dataset(self, entry, n_frames): - raise NotImplementedError() + for grp in self._get_positioners_node(entry), entry: + try: + base_tilt, unit = self._get_node_values_for_frame_array( + node=grp, + n_frame=n_frames, + keys=self.configuration.base_tilt_keys, + info_retrieve="base tilt", + expected_unit=None, + ) + except (ValueError, KeyError): + pass + else: + return base_tilt, None + + mess = "Unable to find base tilt for {}" "".format(self.root_url.path()) + if self.raise_error_if_issue: + raise ValueError(mess) + else: + mess += "default value will be set. (0)" + _logger.warning(mess) + return 0, None - def __treate_valid_camera( + def _treate_valid_camera( self, detector_node, entry, @@ -78,7 +121,7 @@ class XRD3DAcquisition(StandardAcquisition): entry_path, entry_url, ): - super().__treate_valid_camera( + super()._treate_valid_camera( detector_node=detector_node, entry=entry, frame_type=frame_type, @@ -89,17 +132,30 @@ class XRD3DAcquisition(StandardAcquisition): ) # store base tilt information if not self._ignore_sample_output("base_tilt"): - rots = self._get_base_tilt_dataset(entry=entry, n_frames=self._n_frames)[0] - self._base_tilt.extend(rots) + base_tilt, _ = self._get_base_tilt_dataset( + entry=entry, n_frames=self._current_scan_n_frame + ) + self._base_tilt.extend(base_tilt) else: self._base_tilt = None + # store rocking information + if not self._ignore_sample_output("rocking"): + rocking, _ = self._get_rocking_dataset( + entry=entry, n_frames=self._current_scan_n_frame + ) + self._rocking.extend(rocking) + else: + self._rocking = None def _preprocess_registered_entries(self, output_file): - super()._preprocess_registered_entries(output_file=output_file) self._base_tilt = [] self._rocking = [] + super()._preprocess_registered_entries(output_file=output_file) - def _write_instrument(self, root_node): - super()._write_instrument(root_node) - #instrument_node = root_node.create_group("instrument") - #raise NotImplementedError() + def _write_sample(self, root_node): + super()._write_sample(root_node) + sample_node = root_node.require_group("sample") + if self._rocking is not None: + sample_node["rocking"] = self._rocking + if self._base_tilt is not None: + sample_node["base_tilt"] = self._base_tilt diff --git a/nxtomomill/io/config.py b/nxtomomill/io/config.py index bedcf58..751b2f1 100644 --- a/nxtomomill/io/config.py +++ b/nxtomomill/io/config.py @@ -1138,6 +1138,49 @@ class TomoHDF5Config: class XRD3DHDF5Config(TomoHDF5Config): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + self._rocking_keys = settings.XRD3D.H5.ROCKING_KEYS + self._base_tilt_keys = settings.XRD3D.H5.BASE_TILT_KEYS + + @property + def rocking_keys(self) -> Iterable: + return self._rocking_keys + + @rocking_keys.setter + def rocking_keys(self, keys) -> None: + if not isinstance(keys, Iterable): + raise TypeError("'keys' should be an Iterable") + else: + self._rocking_keys = keys + + @staticmethod + def from_cfg_file(file_path: str, encoding=None): + assert file_path is not None, "file_path should not be None" + config_parser = configparser.ConfigParser(allow_no_value=True) + config_parser.read(file_path, encoding=encoding) + return XRD3DHDF5Config.from_dict(config_parser) + + @staticmethod + def from_dict(dict_: dict): + """ + Create a HDF5Config object and set it from values contained in the + dictionary + :param dict dict_: settings dictionary + :return: HDF5Config + """ + config = XRD3DHDF5Config() + config.load_from_dict(dict_) + return config + + @property + def base_tilt_keys(self) -> Iterable: + return self._base_tilt_keys + + @base_tilt_keys.setter + def base_tilt_keys(self, keys) -> None: + if not isinstance(keys, Iterable): + raise TypeError("'keys' should be an Iterable") + else: + self._base_tilt_keys = keys def generate_default_h5_config() -> dict: diff --git a/nxtomomill/io/confighandler.py b/nxtomomill/io/confighandler.py index fa05069..c704824 100644 --- a/nxtomomill/io/confighandler.py +++ b/nxtomomill/io/confighandler.py @@ -204,6 +204,7 @@ class _BaseHDF5ConfigHandler: class TomoHDF5ConfigHandler(_BaseHDF5ConfigHandler): def _create_HDF5_config(self): + print("A") if self.argparse_options.config: return TomoHDF5Config.from_cfg_file(self.argparse_options.config) else: @@ -311,8 +312,10 @@ class TomoHDF5ConfigHandler(_BaseHDF5ConfigHandler): _logger.error(err) return False + class XRD3DHDF5ConfigHandler(_BaseHDF5ConfigHandler): def _create_HDF5_config(self): + print("B") if self.argparse_options.config: return XRD3DHDF5Config.from_cfg_file(self.argparse_options.config) else: @@ -339,16 +342,13 @@ class XRD3DHDF5ConfigHandler(_BaseHDF5ConfigHandler): "x_trans_keys": ("x_trans_keys", self.get_tuple_of_keys_from_cmd), "y_trans_keys": ("y_trans_keys", self.get_tuple_of_keys_from_cmd), "z_trans_keys": ("z_trans_keys", self.get_tuple_of_keys_from_cmd), - "rot_angle_keys": ( - "rotation_angle_keys", self.get_tuple_of_keys_from_cmd), + "rot_angle_keys": ("rotation_angle_keys", self.get_tuple_of_keys_from_cmd), "acq_expo_time_keys": ( "exposition_time_keys", self.get_tuple_of_keys_from_cmd, ), - "x_pixel_size_key": ( - "x_pixel_size_paths", self.get_tuple_of_keys_from_cmd), - "y_pixel_size_key": ( - "y_pixel_size_paths", self.get_tuple_of_keys_from_cmd), + "x_pixel_size_key": ("x_pixel_size_paths", self.get_tuple_of_keys_from_cmd), + "y_pixel_size_key": ("y_pixel_size_paths", self.get_tuple_of_keys_from_cmd), "init_titles": ("init_titles", self.get_tuple_of_keys_from_cmd), "init_zserie_titles": ( "zserie_init_titles", @@ -356,10 +356,8 @@ class XRD3DHDF5ConfigHandler(_BaseHDF5ConfigHandler): ), "dark_titles": ("dark_titles", self.get_tuple_of_keys_from_cmd), "ref_titles": ("flat_titles", self.get_tuple_of_keys_from_cmd), - "proj_titles": ( - "projections_titles", self.get_tuple_of_keys_from_cmd), - "align_titles": ( - "alignment_titles", self.get_tuple_of_keys_from_cmd), + "proj_titles": ("projections_titles", self.get_tuple_of_keys_from_cmd), + "align_titles": ("alignment_titles", self.get_tuple_of_keys_from_cmd), "set_params": ("param_already_defined", _extract_param_value), } for argparse_name, (config_name, format_fct) in mapping.items(): @@ -383,32 +381,32 @@ class XRD3DHDF5ConfigHandler(_BaseHDF5ConfigHandler): # check no other option are provided duplicated_inputs = [] for opt in ( - "set_params", - "align_titles", - "proj_titles", - "ref_titles", - "dark_titles", - "init_zserie_titles", - "init_titles", - "init_zserie_titles", - "x_pixel_size_key", - "y_pixel_size_key", - "acq_expo_time_keys", - "rot_angle_keys", - "valid_camera_names", - "z_trans_keys", - "y_trans_keys", - "x_trans_keys", - "request_input", - "raises_error", - "ignore_sub_entries", - "entries", - "debug", - "overwrite", - "single_file", - "file_extension", - "field_of_view", - "sample_detector_distance", + "set_params", + "align_titles", + "proj_titles", + "ref_titles", + "dark_titles", + "init_zserie_titles", + "init_titles", + "init_zserie_titles", + "x_pixel_size_key", + "y_pixel_size_key", + "acq_expo_time_keys", + "rot_angle_keys", + "valid_camera_names", + "z_trans_keys", + "y_trans_keys", + "x_trans_keys", + "request_input", + "raises_error", + "ignore_sub_entries", + "entries", + "debug", + "overwrite", + "single_file", + "file_extension", + "field_of_view", + "sample_detector_distance", ): if getattr(options, opt): duplicated_inputs.append(opt) diff --git a/nxtomomill/settings.py b/nxtomomill/settings.py index 5348a6b..82c6969 100644 --- a/nxtomomill/settings.py +++ b/nxtomomill/settings.py @@ -143,6 +143,6 @@ class Tomo: class XRD3D(Tomo): class H5(Tomo.H5): - ROCKING_KEYS = ("mcha4_raw",) + ROCKING_KEYS = ("nfdtx",) - BASE_TILT_KEYS = ("mcha5_raw",) + BASE_TILT_KEYS = ("ffdtilt",) -- GitLab From c1eac50feac24509030d9537f79e22b32d060a7d Mon Sep 17 00:00:00 2001 From: payno Date: Thu, 29 Apr 2021 07:36:50 +0200 Subject: [PATCH 5/8] black format --- nxtomomill/app/h5_3dxrd2nx.py | 2 +- nxtomomill/converter/hdf5/acquisition/standardacquisition.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/nxtomomill/app/h5_3dxrd2nx.py b/nxtomomill/app/h5_3dxrd2nx.py index 187ff3e..fc5b8d5 100644 --- a/nxtomomill/app/h5_3dxrd2nx.py +++ b/nxtomomill/app/h5_3dxrd2nx.py @@ -75,7 +75,7 @@ def _ask_for_selecting_detector(det_grps: Iterable): def main(argv): - """""" + """ """ parser = argparse.ArgumentParser( description="convert data acquired as " "hdf5 from bliss to nexus " diff --git a/nxtomomill/converter/hdf5/acquisition/standardacquisition.py b/nxtomomill/converter/hdf5/acquisition/standardacquisition.py index 8eb0be4..67b4255 100644 --- a/nxtomomill/converter/hdf5/acquisition/standardacquisition.py +++ b/nxtomomill/converter/hdf5/acquisition/standardacquisition.py @@ -577,7 +577,6 @@ class StandardAcquisition(BaseAcquisition): detector_node["estimated_cor_from_motor"].attrs["unit"] = unit def _create_data_virtual_dataset(self, detector_node): - print("_create_data_virtual_dataset") if ( self.n_frames is None or self.dim_1 is None -- GitLab From 02bed68dfaf4a1a33c03eb1514f9064355fc67f3 Mon Sep 17 00:00:00 2001 From: payno Date: Thu, 29 Apr 2021 08:29:16 +0200 Subject: [PATCH 6/8] [h52nx] handle xrd 3D from titles definition # Conflicts: # nxtomomill/converter/hdf5/hdf5converter.py --- nxtomomill/converter/hdf5/hdf5converter.py | 19 +++++++++++++------ nxtomomill/io/config.py | 6 +++++- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/nxtomomill/converter/hdf5/hdf5converter.py b/nxtomomill/converter/hdf5/hdf5converter.py index c3dd257..8804499 100644 --- a/nxtomomill/converter/hdf5/hdf5converter.py +++ b/nxtomomill/converter/hdf5/hdf5converter.py @@ -404,7 +404,7 @@ class _H5ToNxConverter: self.configuration.format = "standard" entry_type = get_entry_type(url=url, configuration=self.configuration) - if self.configuration.is_xrdc_ct: + if self.configuration.is_xrd_ct or self.configuration.is_3d_xrd: if entry_type is AcquisitionStep.INITIALIZATION: current_acquisition = None _logger.warning( @@ -418,11 +418,18 @@ class _H5ToNxConverter: and current_acquisition is None or current_acquisition.is_different_sequence(url) ): - current_acquisition = XRDCTAcquisition( - root_url=url, - configuration=self.configuration, - detector_sel_callback=self.detector_sel_callback, - ) + if self.configuration.is_xrd_ct: + current_acquisition = XRDCTAcquisition( + root_url=url, + configuration=self.configuration, + detector_sel_callback=self.detector_sel_callback, + ) + else: + current_acquisition = XRD3DAcquisition( + root_url=url, + configuration=self.configuration, + detector_sel_callback=self.detector_sel_callback, + ) acquisitions.append(current_acquisition) elif self._ignore_entry_frm_titles(group_name): current_acquisition = None diff --git a/nxtomomill/io/config.py b/nxtomomill/io/config.py index 751b2f1..2bf7509 100644 --- a/nxtomomill/io/config.py +++ b/nxtomomill/io/config.py @@ -420,9 +420,13 @@ class TomoHDF5Config: self._format = Format.from_value(format_) @property - def is_xrdc_ct(self): + def is_xrd_ct(self): return self._format == Format.XRD_CT + @property + def is_3d_xrd(self): + return self._format == Format.XRD_3D + @property def single_file(self): return self._single_file -- GitLab From 4ae7d41121d095c4955622ca492d40d889533fc8 Mon Sep 17 00:00:00 2001 From: payno Date: Thu, 29 Apr 2021 08:44:25 +0200 Subject: [PATCH 7/8] [xrt-3d-2nx] handle conversion from settings.h5 and without configuration file --- nxtomomill/converter/hdf5/hdf5converter.py | 53 ++++++++++++++++------ nxtomomill/io/confighandler.py | 5 +- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/nxtomomill/converter/hdf5/hdf5converter.py b/nxtomomill/converter/hdf5/hdf5converter.py index 8804499..8a43517 100644 --- a/nxtomomill/converter/hdf5/hdf5converter.py +++ b/nxtomomill/converter/hdf5/hdf5converter.py @@ -403,8 +403,9 @@ class _H5ToNxConverter: else: self.configuration.format = "standard" + # Handle XRD-CT dataset entry_type = get_entry_type(url=url, configuration=self.configuration) - if self.configuration.is_xrd_ct or self.configuration.is_3d_xrd: + if self.configuration.is_xrd_ct: if entry_type is AcquisitionStep.INITIALIZATION: current_acquisition = None _logger.warning( @@ -418,19 +419,43 @@ class _H5ToNxConverter: and current_acquisition is None or current_acquisition.is_different_sequence(url) ): - if self.configuration.is_xrd_ct: - current_acquisition = XRDCTAcquisition( - root_url=url, - configuration=self.configuration, - detector_sel_callback=self.detector_sel_callback, - ) - else: - current_acquisition = XRD3DAcquisition( - root_url=url, - configuration=self.configuration, - detector_sel_callback=self.detector_sel_callback, - ) + current_acquisition = XRDCTAcquisition( + root_url=url, + configuration=self.configuration, + detector_sel_callback=self.detector_sel_callback, + ) + acquisitions.append(current_acquisition) + elif self._ignore_entry_frm_titles(group_name): + current_acquisition = None + elif not self._ignore_sub_entry(url): + current_acquisition.register_step( + url, AcquisitionStep.PROJECTION + ) + else: + _logger.warning("ignore entry {}".format(entry)) + # Handle 3D - XRD dataset + elif self.configuration.is_3d_xrd: + if entry_type is AcquisitionStep.INITIALIZATION: + current_acquisition = None + _logger.warning( + "Found several acquisition type " + "in the same file. Stop conversion at" + " {}".format(url) + ) + break + elif ( + not self._ignore_entry_frm_titles(group_name) + and current_acquisition is None + ): + current_acquisition = XRD3DAcquisition( + root_url=url, + configuration=self.configuration, + detector_sel_callback=self.detector_sel_callback, + ) acquisitions.append(current_acquisition) + current_acquisition.register_step( + url, AcquisitionStep.PROJECTION + ) elif self._ignore_entry_frm_titles(group_name): current_acquisition = None elif not self._ignore_sub_entry(url): @@ -439,6 +464,7 @@ class _H5ToNxConverter: ) else: _logger.warning("ignore entry {}".format(entry)) + # Handle "standard" tomo dataset elif entry_type is AcquisitionStep.INITIALIZATION: if self._ignore_entry_frm_titles(group_name): current_acquisition = None @@ -460,6 +486,7 @@ class _H5ToNxConverter: ) acquisitions.append(current_acquisition) + # continue "standard" tomo dataset handling elif current_acquisition is not None and not self._ignore_sub_entry( url ): diff --git a/nxtomomill/io/confighandler.py b/nxtomomill/io/confighandler.py index c704824..4a736ba 100644 --- a/nxtomomill/io/confighandler.py +++ b/nxtomomill/io/confighandler.py @@ -233,7 +233,10 @@ class TomoHDF5ConfigHandler(_BaseHDF5ConfigHandler): "y_trans_keys": ("y_trans_keys", self.get_tuple_of_keys_from_cmd), "z_trans_keys": ("z_trans_keys", self.get_tuple_of_keys_from_cmd), "rot_angle_keys": ("rotation_angle_keys", self.get_tuple_of_keys_from_cmd), - "sample_detector_distance": ("sample_detector_distance", self.get_tuple_of_keys_from_cmd), + "sample_detector_distance": ( + "sample_detector_distance", + self.get_tuple_of_keys_from_cmd, + ), "acq_expo_time_keys": ( "exposition_time_keys", self.get_tuple_of_keys_from_cmd, -- GitLab From 7e501249072c0776cbf715a34d57bd8dd064efeb Mon Sep 17 00:00:00 2001 From: payno Date: Thu, 29 Apr 2021 09:46:24 +0200 Subject: [PATCH 8/8] [settings] rename settings. Remove prefix 'H5_' and 'EDF_' since they are now part of a namespace --- nxtomomill/app/edf2nx.py | 18 ++++---- nxtomomill/converter/edf/edfconverter.py | 18 ++++---- nxtomomill/converter/hdf5/hdf5converter.py | 32 ++++++------- nxtomomill/io/config.py | 34 +++++++------- nxtomomill/io/test/test_config.py | 34 +++++++------- nxtomomill/settings.py | 52 +++++++++++----------- 6 files changed, 94 insertions(+), 94 deletions(-) diff --git a/nxtomomill/app/edf2nx.py b/nxtomomill/app/edf2nx.py index fc27459..75e6878 100644 --- a/nxtomomill/app/edf2nx.py +++ b/nxtomomill/app/edf2nx.py @@ -41,15 +41,15 @@ from nxtomomill.utils import Progress from nxtomomill.settings import Tomo from tomoscan.esrf.edfscan import EDFTomoScan -EDF_MOTOR_POS = Tomo.EDF.EDF_MOTOR_POS -EDF_MOTOR_MNE = Tomo.EDF.EDF_MOTOR_MNE -EDF_REFS_NAMES = Tomo.EDF.EDF_REFS_NAMES -EDF_TO_IGNORE = Tomo.EDF.EDF_TO_IGNORE -EDF_ROT_ANGLE = Tomo.EDF.EDF_ROT_ANGLE -EDF_DARK_NAMES = Tomo.EDF.EDF_DARK_NAMES -EDF_X_TRANS = Tomo.EDF.EDF_X_TRANS -EDF_Y_TRANS = Tomo.EDF.EDF_Y_TRANS -EDF_Z_TRANS = Tomo.EDF.EDF_Z_TRANS +EDF_MOTOR_POS = Tomo.EDF.MOTOR_POS +EDF_MOTOR_MNE = Tomo.EDF.MOTOR_MNE +EDF_REFS_NAMES = Tomo.EDF.REFS_NAMES +EDF_TO_IGNORE = Tomo.EDF.TO_IGNORE +EDF_ROT_ANGLE = Tomo.EDF.ROT_ANGLE +EDF_DARK_NAMES = Tomo.EDF.DARK_NAMES +EDF_X_TRANS = Tomo.EDF.X_TRANS +EDF_Y_TRANS = Tomo.EDF.Y_TRANS +EDF_Z_TRANS = Tomo.EDF.Z_TRANS logging.basicConfig(level=logging.INFO) _logger = logging.getLogger(__name__) diff --git a/nxtomomill/converter/edf/edfconverter.py b/nxtomomill/converter/edf/edfconverter.py index abb1257..366cd18 100644 --- a/nxtomomill/converter/edf/edfconverter.py +++ b/nxtomomill/converter/edf/edfconverter.py @@ -46,15 +46,15 @@ import fabio import numpy import os -EDF_MOTOR_POS = Tomo.EDF.EDF_MOTOR_POS -EDF_MOTOR_MNE = Tomo.EDF.EDF_MOTOR_MNE -EDF_REFS_NAMES = Tomo.EDF.EDF_REFS_NAMES -EDF_TO_IGNORE = Tomo.EDF.EDF_TO_IGNORE -EDF_ROT_ANGLE = Tomo.EDF.EDF_ROT_ANGLE -EDF_DARK_NAMES = Tomo.EDF.EDF_DARK_NAMES -EDF_X_TRANS = Tomo.EDF.EDF_X_TRANS -EDF_Y_TRANS = Tomo.EDF.EDF_Y_TRANS -EDF_Z_TRANS = Tomo.EDF.EDF_Z_TRANS +EDF_MOTOR_POS = Tomo.EDF.MOTOR_POS +EDF_MOTOR_MNE = Tomo.EDF.MOTOR_MNE +EDF_REFS_NAMES = Tomo.EDF.REFS_NAMES +EDF_TO_IGNORE = Tomo.EDF.TO_IGNORE +EDF_ROT_ANGLE = Tomo.EDF.ROT_ANGLE +EDF_DARK_NAMES = Tomo.EDF.DARK_NAMES +EDF_X_TRANS = Tomo.EDF.X_TRANS +EDF_Y_TRANS = Tomo.EDF.Y_TRANS +EDF_Z_TRANS = Tomo.EDF.Z_TRANS import logging diff --git a/nxtomomill/converter/hdf5/hdf5converter.py b/nxtomomill/converter/hdf5/hdf5converter.py index 8a43517..70c54c0 100644 --- a/nxtomomill/converter/hdf5/hdf5converter.py +++ b/nxtomomill/converter/hdf5/hdf5converter.py @@ -69,22 +69,22 @@ from nxtomomill.converter.hdf5.utils import H5ScanTitles from nxtomomill.settings import Tomo -H5_ROT_ANGLE_KEYS = Tomo.H5.H5_ROT_ANGLE_KEYS -H5_VALID_CAMERA_NAMES = Tomo.H5.H5_VALID_CAMERA_NAMES -H5_X_TRANS_KEYS = Tomo.H5.H5_X_TRANS_KEYS -H5_Y_TRANS_KEYS = Tomo.H5.H5_Y_TRANS_KEYS -H5_Z_TRANS_KEYS = Tomo.H5.H5_Z_TRANS_KEYS -H5_ALIGNMENT_TITLES = Tomo.H5.H5_ALIGNMENT_TITLES -H5_ACQ_EXPO_TIME_KEYS = Tomo.H5.H5_ACQ_EXPO_TIME_KEYS -H5_X_PIXEL_SIZE = Tomo.H5.H5_X_PIXEL_SIZE -H5_Y_PIXEL_SIZE = Tomo.H5.H5_Y_PIXEL_SIZE -H5_DARK_TITLES = Tomo.H5.H5_DARK_TITLES -H5_INIT_TITLES = Tomo.H5.H5_INIT_TITLES -H5_ZSERIE_INIT_TITLES = Tomo.H5.H5_ZSERIE_INIT_TITLES -H5_PROJ_TITLES = Tomo.H5.H5_PROJ_TITLES -H5_REF_TITLES = Tomo.H5.H5_REF_TITLES -H5_Y_ROT_KEY = Tomo.H5.H5_Y_ROT_KEY -H5_DIODE_KEYS = Tomo.H5.H5_DIODE_KEYS +H5_ROT_ANGLE_KEYS = Tomo.H5.ROT_ANGLE_KEYS +H5_VALID_CAMERA_NAMES = Tomo.H5.VALID_CAMERA_NAMES +H5_X_TRANS_KEYS = Tomo.H5.X_TRANS_KEYS +H5_Y_TRANS_KEYS = Tomo.H5.Y_TRANS_KEYS +H5_Z_TRANS_KEYS = Tomo.H5.Z_TRANS_KEYS +H5_ALIGNMENT_TITLES = Tomo.H5.ALIGNMENT_TITLES +H5_ACQ_EXPO_TIME_KEYS = Tomo.H5.ACQ_EXPO_TIME_KEYS +H5_X_PIXEL_SIZE = Tomo.H5.X_PIXEL_SIZE +H5_Y_PIXEL_SIZE = Tomo.H5.Y_PIXEL_SIZE +H5_DARK_TITLES = Tomo.H5.DARK_TITLES +H5_INIT_TITLES = Tomo.H5.INIT_TITLES +H5_ZSERIE_INIT_TITLES = Tomo.H5.ZSERIE_INIT_TITLES +H5_PROJ_TITLES = Tomo.H5.PROJ_TITLES +H5_REF_TITLES = Tomo.H5.REF_TITLES +H5_Y_ROT_KEY = Tomo.H5.Y_ROT_KEY +H5_DIODE_KEYS = Tomo.H5.DIODE_KEYS DEFAULT_SCAN_TITLES = H5ScanTitles( H5_INIT_TITLES, diff --git a/nxtomomill/io/config.py b/nxtomomill/io/config.py index 2bf7509..ef103b4 100644 --- a/nxtomomill/io/config.py +++ b/nxtomomill/io/config.py @@ -291,27 +291,27 @@ class TomoHDF5Config: self._field_of_view = None # information regarding keys and paths - self._valid_camera_names = settings.Tomo.H5.H5_VALID_CAMERA_NAMES - self._rot_angle_keys = settings.Tomo.H5.H5_ROT_ANGLE_KEYS - self._x_trans_keys = settings.Tomo.H5.H5_X_TRANS_KEYS - self._y_trans_keys = settings.Tomo.H5.H5_Y_TRANS_KEYS - self._z_trans_keys = settings.Tomo.H5.H5_Z_TRANS_KEYS - self._y_rot_key = settings.Tomo.H5.H5_Y_ROT_KEY - self._diode_keys = settings.Tomo.H5.H5_DIODE_KEYS - self._expo_time_keys = settings.Tomo.H5.H5_ACQ_EXPO_TIME_KEYS - self._sample_detector_distance_keys = settings.Tomo.H5.H5_DISTANCE_KEYS + self._valid_camera_names = settings.Tomo.H5.VALID_CAMERA_NAMES + self._rot_angle_keys = settings.Tomo.H5.ROT_ANGLE_KEYS + self._x_trans_keys = settings.Tomo.H5.X_TRANS_KEYS + self._y_trans_keys = settings.Tomo.H5.Y_TRANS_KEYS + self._z_trans_keys = settings.Tomo.H5.Z_TRANS_KEYS + self._y_rot_key = settings.Tomo.H5.Y_ROT_KEY + self._diode_keys = settings.Tomo.H5.DIODE_KEYS + self._expo_time_keys = settings.Tomo.H5.ACQ_EXPO_TIME_KEYS + self._sample_detector_distance_keys = settings.Tomo.H5.DISTANCE_KEYS # information regarding titles self._entries = None self._sub_entries_to_ignore = None - self._init_titles = settings.Tomo.H5.H5_INIT_TITLES - self._zserie_init_titles = settings.Tomo.H5.H5_ZSERIE_INIT_TITLES - self._dark_titles = settings.Tomo.H5.H5_DARK_TITLES - self._flat_titles = settings.Tomo.H5.H5_REF_TITLES - self._projection_titles = settings.Tomo.H5.H5_PROJ_TITLES - self._alignment_titles = settings.Tomo.H5.H5_ALIGNMENT_TITLES - self._x_pixel_size_paths = settings.Tomo.H5.H5_X_PIXEL_SIZE - self._y_pixel_size_paths = settings.Tomo.H5.H5_Y_PIXEL_SIZE + self._init_titles = settings.Tomo.H5.INIT_TITLES + self._zserie_init_titles = settings.Tomo.H5.ZSERIE_INIT_TITLES + self._dark_titles = settings.Tomo.H5.DARK_TITLES + self._flat_titles = settings.Tomo.H5.REF_TITLES + self._projection_titles = settings.Tomo.H5.PROJ_TITLES + 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 # information regarding frames types definition self._data_grps_urls = tuple() diff --git a/nxtomomill/io/test/test_config.py b/nxtomomill/io/test/test_config.py index cb74e3a..ae644ae 100644 --- a/nxtomomill/io/test/test_config.py +++ b/nxtomomill/io/test/test_config.py @@ -60,65 +60,65 @@ class TestH5Config(unittest.TestCase): # check titles values titles_dict = output[TomoHDF5Config.ENTRIES_AND_TITLES_SECTION_DK] self.assertEqual( - titles_dict[TomoHDF5Config.INIT_TITLES_DK], settings.Tomo.H5.H5_INIT_TITLES + titles_dict[TomoHDF5Config.INIT_TITLES_DK], settings.Tomo.H5.INIT_TITLES ) self.assertEqual( titles_dict[TomoHDF5Config.ZSERIE_INIT_TITLES_DK], - settings.Tomo.H5.H5_ZSERIE_INIT_TITLES, + settings.Tomo.H5.ZSERIE_INIT_TITLES, ) self.assertEqual( - titles_dict[TomoHDF5Config.PROJ_TITLES_DK], settings.Tomo.H5.H5_PROJ_TITLES + titles_dict[TomoHDF5Config.PROJ_TITLES_DK], settings.Tomo.H5.PROJ_TITLES ) self.assertEqual( - titles_dict[TomoHDF5Config.REF_TITLES_DK], settings.Tomo.H5.H5_REF_TITLES + titles_dict[TomoHDF5Config.REF_TITLES_DK], settings.Tomo.H5.REF_TITLES ) self.assertEqual( - titles_dict[TomoHDF5Config.DARK_TITLES_DK], settings.Tomo.H5.H5_DARK_TITLES + titles_dict[TomoHDF5Config.DARK_TITLES_DK], settings.Tomo.H5.DARK_TITLES ) self.assertEqual( titles_dict[TomoHDF5Config.ALIGNMENT_TITLES_DK], - settings.Tomo.H5.H5_ALIGNMENT_TITLES, + settings.Tomo.H5.ALIGNMENT_TITLES, ) # check pixel size keys_dict = output[TomoHDF5Config.KEYS_SECTION_DK] self.assertEqual( keys_dict[TomoHDF5Config.X_PIXEL_SIZE_KEYS_DK], - settings.Tomo.H5.H5_X_PIXEL_SIZE, + settings.Tomo.H5.X_PIXEL_SIZE, ) self.assertEqual( keys_dict[TomoHDF5Config.Y_PIXEL_SIZE_KEYS_DK], - settings.Tomo.H5.H5_Y_PIXEL_SIZE, + settings.Tomo.H5.Y_PIXEL_SIZE, ) # check translation self.assertEqual( - keys_dict[TomoHDF5Config.X_TRANS_KEYS_DK], settings.Tomo.H5.H5_X_TRANS_KEYS + keys_dict[TomoHDF5Config.X_TRANS_KEYS_DK], settings.Tomo.H5.X_TRANS_KEYS ) self.assertEqual( - keys_dict[TomoHDF5Config.Y_TRANS_KEYS_DK], settings.Tomo.H5.H5_Y_TRANS_KEYS + keys_dict[TomoHDF5Config.Y_TRANS_KEYS_DK], settings.Tomo.H5.Y_TRANS_KEYS ) self.assertEqual( - keys_dict[TomoHDF5Config.Z_TRANS_KEYS_DK], settings.Tomo.H5.H5_Z_TRANS_KEYS + keys_dict[TomoHDF5Config.Z_TRANS_KEYS_DK], settings.Tomo.H5.Z_TRANS_KEYS ) # others - if settings.Tomo.H5.H5_VALID_CAMERA_NAMES is None: + if settings.Tomo.H5.VALID_CAMERA_NAMES is None: self.assertEqual(keys_dict[TomoHDF5Config.VALID_CAMERA_DK], "") else: self.assertEqual( keys_dict[TomoHDF5Config.VALID_CAMERA_DK], - settings.Tomo.H5.H5_VALID_CAMERA_NAMES, + settings.Tomo.H5.VALID_CAMERA_NAMES, ) self.assertEqual( - keys_dict[TomoHDF5Config.ROT_ANGLE_DK], settings.Tomo.H5.H5_ROT_ANGLE_KEYS + keys_dict[TomoHDF5Config.ROT_ANGLE_DK], settings.Tomo.H5.ROT_ANGLE_KEYS ) self.assertEqual( - keys_dict[TomoHDF5Config.DIODE_KEYS_DK], settings.Tomo.H5.H5_DIODE_KEYS + keys_dict[TomoHDF5Config.DIODE_KEYS_DK], settings.Tomo.H5.DIODE_KEYS ) self.assertEqual( - keys_dict[TomoHDF5Config.Y_ROT_KEYS_DK], settings.Tomo.H5.H5_Y_ROT_KEY + keys_dict[TomoHDF5Config.Y_ROT_KEYS_DK], settings.Tomo.H5.Y_ROT_KEY ) self.assertEqual( keys_dict[TomoHDF5Config.ACQUISITION_EXPO_TIME_KEYS_DK], - settings.Tomo.H5.H5_ACQ_EXPO_TIME_KEYS, + settings.Tomo.H5.ACQ_EXPO_TIME_KEYS, ) # check input and output file diff --git a/nxtomomill/settings.py b/nxtomomill/settings.py index 82c6969..c20414a 100644 --- a/nxtomomill/settings.py +++ b/nxtomomill/settings.py @@ -36,13 +36,13 @@ class Tomo: class H5: """HDF5 settings for tomography""" - H5_VALID_CAMERA_NAMES = None + VALID_CAMERA_NAMES = None # now camera names are deduce using converter `get_nx_detectors` # and `guess_nx_detector` functions. But you can provide A LIST of # detector name (unix shell-style wildcards are managed) like # ("pcolinux*", "basler", "frelon*", ...) - H5_ROT_ANGLE_KEYS = ( + ROT_ANGLE_KEYS = ( "rotm", "mhsrot", "hsrot", @@ -54,25 +54,25 @@ class Tomo: "rot", ) - H5_X_TRANS_KEYS = ("sx", "d3tx", "tfx", "px") + X_TRANS_KEYS = ("sx", "d3tx", "tfx", "px") """Keys used to find the x translation""" - H5_Y_TRANS_KEYS = ("sy", "d3ty", "hry", "py") + Y_TRANS_KEYS = ("sy", "d3ty", "hry", "py") """Keys used by bliss to store y translation""" - H5_Z_TRANS_KEYS = ("sz", "d3tz", "hrz", "pz") + Z_TRANS_KEYS = ("sz", "d3tz", "hrz", "pz") """Keys used by bliss to store translation""" - H5_Y_ROT_KEY = "instrument/positioners/yrot" + Y_ROT_KEY = "instrument/positioners/yrot" """Key used by bliss to store the estimated center of rotation for half acquisition""" - H5_DIODE_KEYS = ("fpico3",) + DIODE_KEYS = ("fpico3",) """keys used by bliss to store diode dataset""" - H5_ACQ_EXPO_TIME_KEYS = ("acq_expo_time",) + ACQ_EXPO_TIME_KEYS = ("acq_expo_time",) - H5_INIT_TITLES = ( + INIT_TITLES = ( "pcotomo:basic", "tomo:basic", "tomo:fullturn", @@ -83,23 +83,23 @@ class Tomo: """if a scan starts by one of those string then is considered as initialization scan""" - H5_ZSERIE_INIT_TITLES = ("tomo:zseries",) + ZSERIE_INIT_TITLES = ("tomo:zseries",) """specific titles for zserie. Will extend H5_INIT_TITLES""" - H5_DARK_TITLES = ("dark images", "dark") + DARK_TITLES = ("dark images", "dark") """if a scan starts by one of those string then is considered as dark scan""" - H5_REF_TITLES = ("reference images", "ref", "refend") + REF_TITLES = ("reference images", "ref", "refend") """if a scan starts by one of those string then is considered as reference scan""" - H5_PROJ_TITLES = ("projections", "ascan rot 0 ", "ascan diffrz 0 180 1600 0.1") + PROJ_TITLES = ("projections", "ascan rot 0 ", "ascan diffrz 0 180 1600 0.1") """if a scan starts by one of those string then is considered as projection scan""" - H5_ALIGNMENT_TITLES = ("static images", "ascan diffrz 180 0 4 0.1") + ALIGNMENT_TITLES = ("static images", "ascan diffrz 180 0 4 0.1") """if a scan starts by one of those string then is considered as alignment scan""" - H5_X_PIXEL_SIZE = ( + X_PIXEL_SIZE = ( "technique/optic/sample_pixel_size ", "technique/optic/sample_pixel_size", "technique/detector/pixel_size", @@ -108,37 +108,37 @@ class Tomo: """Possible path to th pixel size.""" # warning: we can have two cases: one with an empty space at the end or not - H5_Y_PIXEL_SIZE = ( + Y_PIXEL_SIZE = ( "technique/optic/sample_pixel_size ", "technique/optic/sample_pixel_size", "technique/detector/pixel_size", "hry_step_size", ) - H5_DISTANCE_KEYS = ("technique/scan/sample_detector_distance",) + DISTANCE_KEYS = ("technique/scan/sample_detector_distance",) """keys used by bliss to store the sample to detector distance""" class EDF: """EDF settings for tomography""" - EDF_MOTOR_POS = "motor_pos" + MOTOR_POS = "motor_pos" - EDF_MOTOR_MNE = "motor_mne" + MOTOR_MNE = "motor_mne" - EDF_ROT_ANGLE = "srot" + ROT_ANGLE = "srot" - EDF_X_TRANS = "sx" + X_TRANS = "sx" - EDF_Y_TRANS = "sy" + Y_TRANS = "sy" - EDF_Z_TRANS = "sz" + Z_TRANS = "sz" # EDF_TO_IGNORE = ['HST', '_slice_'] - EDF_TO_IGNORE = ("_slice_",) + TO_IGNORE = ("_slice_",) - EDF_DARK_NAMES = ("darkend", "dark") + DARK_NAMES = ("darkend", "dark") - EDF_REFS_NAMES = ("ref", "refHST") + REFS_NAMES = ("ref", "refHST") class XRD3D(Tomo): -- GitLab