Source code for nxtomomill.app.h52nx

# 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.
#
# ###########################################################################*/

"""
Application to convert a bliss-hdf5 tomography dataset to Nexus - NXtomo (hdf5) format

.. code-block:: console

    usage: nxtomomill h52nx [-h] [--file-extension FILE_EXTENSION] [--single-file] [--overwrite] [--debug] [--entries ENTRIES] [--ignore-sub-entries IGNORE_SUB_ENTRIES] [--raises-error]
                            [--field-of-view FIELD_OF_VIEW] [--no-input] [--data-copy] [--x_trans_keys X_TRANS_KEYS] [--y_trans_keys Y_TRANS_KEYS] [--z_trans_keys Z_TRANS_KEYS]
                            [--sample-detector-distance-paths SAMPLE_DETECTOR_DISTANCE_PATHS] [--valid_camera_names VALID_CAMERA_NAMES] [--rot_angle_keys ROT_ANGLE_KEYS] [--acq_expo_time_keys ACQ_EXPO_TIME_KEYS]
                            [--x_pixel_size_key X_PIXEL_SIZE_KEY] [--y_pixel_size_key Y_PIXEL_SIZE_KEY] [--init_titles INIT_TITLES] [--init_zserie_titles INIT_ZSERIE_TITLES] [--dark_titles DARK_TITLES]
                            [--ref_titles REF_TITLES] [--proj_titles PROJ_TITLES] [--align_titles ALIGN_TITLES] [--set-params [SET_PARAMS [SET_PARAMS ...]]] [--format FORMAT] [--config CONFIG]
                            [input_file] [output_file]

    convert data acquired as hdf5 from bliss to nexus `NXtomo` classes. For `zseries` it will create one entry per `z`

    positional arguments:
      input_file            master file of the acquisition
      output_file           output .nx or .h5 file

    optional arguments:
      -h, --help            show this help message and exit
      --file-extension FILE_EXTENSION, --file_extension FILE_EXTENSION
                            extension of the output file. Valid values are .h5/.hdf5/.nx
      --single-file         merge all scan sequence to the same output file. By default create one file per sequence and group all sequence in the output file
      --overwrite           Do not ask for user permission to overwrite output files
      --debug               Set logs to debug mode
      --entries ENTRIES     Specify (root) entries to be converted. By default it will try to convert all existing entries.
      --ignore-sub-entries IGNORE_SUB_ENTRIES
                            Specify (none-root) sub entries to ignore.
      --raises-error        Raise errors if some data are not met instead of providing some default values
      --field-of-view FIELD_OF_VIEW
                            Force the output to be `Half` or `Full` acquisition. Otherwise parse raw data to find this information.
      --no-input, --no-input-for-missing-information
                            The user won't be ask for any inputs
      --data-copy, --copy-data
                            Force data duplication of frames. This will permit to have an 'all-embed' file. Otherwise the detector/data dataset will haves links to other files.
      --x_trans_keys X_TRANS_KEYS, --x-trans-keys X_TRANS_KEYS
                            x translation key in bliss HDF5 file
      --y_trans_keys Y_TRANS_KEYS, --y-trans-keys Y_TRANS_KEYS
                            y translation key in bliss HDF5 file
      --z_trans_keys Z_TRANS_KEYS, --z-trans-keys Z_TRANS_KEYS
                            z translation key in bliss HDF5 file
      --sample-detector-distance-paths SAMPLE_DETECTOR_DISTANCE_PATHS, --distance SAMPLE_DETECTOR_DISTANCE_PATHS
                            sample detector distance
      --valid_camera_names VALID_CAMERA_NAMES, --valid-camera-names VALID_CAMERA_NAMES
                            Valid NXDetector dataset name to be considered. Otherwise willtry to deduce them from NX_class attibute (value should beNXdetector) or from instrument group child structure.
      --rot_angle_keys ROT_ANGLE_KEYS, --rot-angle-keys ROT_ANGLE_KEYS
                            Valid dataset name for rotation angle
      --acq_expo_time_keys ACQ_EXPO_TIME_KEYS, --acq-expo-time-keys ACQ_EXPO_TIME_KEYS
                            Valid dataset name for acquisition exposure time
      --x_pixel_size_key X_PIXEL_SIZE_KEY, --x-pixel-size-key X_PIXEL_SIZE_KEY
                            X pixel size key to read
      --y_pixel_size_key Y_PIXEL_SIZE_KEY, --y-pixel-size-key Y_PIXEL_SIZE_KEY
                            Y pixel size key to read
      --init_titles INIT_TITLES, --init-titles INIT_TITLES
                            Titles corresponding to init scans
      --init_zserie_titles INIT_ZSERIE_TITLES, --init-zserie-titles INIT_ZSERIE_TITLES
                            Titles corresponding to zserie init scans
      --dark_titles DARK_TITLES, --dark-titles DARK_TITLES
                            Titles corresponding to dark scans
      --flat_titles --flat-titles --ref_titles REF_TITLES, --ref-titles FLAT_TITLES
                            Titles corresponding to ref scans
      --proj_titles PROJ_TITLES, --proj-titles PROJ_TITLES
                            Titles corresponding to projection scans
      --align_titles ALIGN_TITLES, --align-titles ALIGN_TITLES
                            Titles corresponding to alignment scans
      --set-params [SET_PARAMS [SET_PARAMS ...]]
                            Allow manual definition of some parameters. Valid parameters (and expected input unit) are: energy (kev), x_pixel_size (m), y_pixel_size (m). Should be added at the end of the command
                            line because will try to cover all text set after this option.
      --format FORMAT       Input format. Standard by default. Should be 'xrd-ct' otherwise
      --config CONFIG, --config-file CONFIG, --configuration CONFIG, --configuration-file CONFIG
                            file containing the full configuration to convert from h5 bliss to nexus

For a complete tutorial you can have a look at: :ref:`Tomoh52nx`

"""

__authors__ = ["C. Nemoz", "H. Payno", "A.Sole"]
__license__ = "MIT"
__date__ = "16/01/2020"

import argparse
import logging
from collections.abc import Iterable

from nxtomomill import utils
from nxtomomill.converter import from_h5_to_nx
from nxtomomill.io.config.confighandler import (
    SETTABLE_PARAMETERS_UNITS,
    TomoHDF5ConfigHandler,
)
from nxtomomill.utils import Format, Progress

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(f"{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 "
        f"or 'Cancel' to stop translation ({det_grps})"
    )
    if res == "Cancel":
        return None
    elif res in det_grps:
        return res
    else:
        # warning: this is not a debug log !!!
        print("detector name not recognized.")
        return _ask_for_selecting_detector(det_grps)


[docs]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, # default is None and not False for the ConfigHandler so it can knows when set by the user or not ) parser.add_argument( "--overwrite", help="Do not ask for user permission to overwrite output files", action="store_true", default=None, # default is None and not False for the ConfigHandler so it can knows when set by the user or not ) parser.add_argument( "--debug", help="Set logs to debug mode", action="store_true", default=None, # default is None and not False for the ConfigHandler so it can knows when set by the user or not ) 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, # default is None and not False for the ConfigHandler so it can knows when set by the user or not ) 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, # default is None and not False for the ConfigHandler so it can knows when set by the user or not ) parser.add_argument( "--data-copy", "--copy-data", help="Force data duplication of frames. This will permit to have an " "'all-embed' file. Otherwise the detector/data dataset will haves " "links to other files.", action="store_true", dest="duplicate_data", default=None, # default is None and not False for the ConfigHandler so it can knows when set by the user or not ) 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( "--sample-detector-distance-paths", "--distance-paths", default=None, help="sample detector distance paths", ) 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( "--init_pcotomo_titles", "--init-pcotomo-titles", default=None, help="Titles corresponding to pcotomo init scans", ) parser.add_argument( "--dark_titles", "--dark-titles", default=None, help="Titles corresponding to dark scans", ) parser.add_argument( "--flat_titles" "--flat-titles" "--ref_titles", "--ref-titles", default=None, help="Titles corresponding to ref scans", dest="flat_titles", ) 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) " f"are: {_getPossibleInputParams()}. Should be added at the end of the command line because " "will try to cover all text set after this option.", ) parser.add_argument( "--format", default=None, help="Input format. Standard by default. Should be 'xrd-ct' otherwise", ) # config file 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 try: configuration_handler = TomoHDF5ConfigHandler(options, raise_error=True) except Exception as e: _logger.error(e) return else: if options.format is not None: try: configuration_handler.configuration.format = Format.from_value( options.format ) except ValueError: raise RuntimeError(f"Invalid format provided: {options.format}") for title in configuration_handler.configuration.init_titles: assert title != "" logging.getLogger("nxtomomill").setLevel( configuration_handler.configuration.log_level ) from_h5_to_nx( configuration=configuration_handler.configuration, progress=Progress(""), input_callback=None, detector_sel_callback=callback_det_sel, )