Source code for nxtomomill.app.dxfile2nx

# 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 from dx file (HDF5) to NXTomo (HDF5) file

.. code-block:: bash

    usage: nxtomomill dxfile2nx [-h] [--input_entry INPUT_ENTRY] [--output_entry OUTPUT_ENTRY] [--file_extension FILE_EXTENSION] [--scan-range SCAN_RANGE] [--pixel-size PIXEL_SIZE] [--fov FIELD_OF_VIEW]
                                [--distance DISTANCE] [--energy ENERGY] [--overwrite] [--data-copy]
                                input_file output_file

    convert acquisition contained in provided dx file to NXTomo entry

    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
      --input_entry INPUT_ENTRY
                            h5py group path to be converted
      --output_entry OUTPUT_ENTRY
                            h5py group path to store the NXTomo
      --file_extension FILE_EXTENSION
                            extension of the output file. Valid values are .h5/.hdf5/.nx
      --scan-range SCAN_RANGE
                            scan range of the projections. Dark and flat will always be considered with rotation angle == scan_range[0]
      --pixel-size PIXEL_SIZE
                            pixel size in meter as (x pixel size, y pixel size)
      --fov FIELD_OF_VIEW, --field-of-view FIELD_OF_VIEW
                            field of view. Can be Full or Half
      --distance DISTANCE, --detector-sample-distance DISTANCE
                            sample to detector distance (in meter)
      --energy ENERGY, --incident-beam-energy ENERGY
                            incident beam energy in keV
      --overwrite           Do not ask for user permission to overwrite output files
      --data-copy           Force data duplication of frames. This will permit to have an 'all-embed' file. Otherwise we will have link between the dxfile and the NXTomo.

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

"""

__authors__ = [
    "H. Payno",
]
__license__ = "MIT"
__date__ = "18/05/2021"


import argparse
import logging

from pyunitsystem import metricsystem

from nxtomomill import utils
from nxtomomill.converter.dxfile.dxfileconverter import from_dx_to_nx

_logger = logging.getLogger(__name__)


[docs]def convert_2elmts__tuple_to_float(input_str) -> tuple: if input_str == (None, None): return input_str try: tmp_str = input_str.replace(" ", "") tmp_str = tmp_str.replace(";", ",") if tmp_str.startswith("("): tmp_str = tmp_str[1:] if tmp_str.startswith(")"): tmp_str = tmp_str[:-1] v1, v2 = tmp_str.split(",") except Exception as e: raise ValueError( f"Unable to convert {input_str} to a tuple of two float. Reason is {e}" ) else: return float(v1), float(v2)
def _get_pixel_size(input_str) -> tuple: try: values = convert_2elmts__tuple_to_float(input_str) except ValueError: try: value = float(input_str) except Exception: raise ValueError( f"Unable to convert {input_str} to pixel size." f"Should be provided as a tuple (x_pixel_size, y_pixel_size) " f"or as a single value pixel_size" ) else: return value, value else: return values
[docs]def main(argv): """ """ parser = argparse.ArgumentParser( description="convert acquisition contained in provided dx file to " "NXTomo entry" ) parser.add_argument("input_file", help="master file of the " "acquisition") parser.add_argument("output_file", help="output .nx or .h5 file", default=None) # usually it looks like the dxfile contains only one acquisition at the # root level parser.add_argument( "--input_entry", help="h5py group path to be converted", default="/", ) parser.add_argument( "--output_entry", help="h5py group path to store the NXTomo", default="entry0000", ) parser.add_argument( "--file_extension", default=".nx", help="extension of the output file. Valid values are " "" + "/".join(utils.FileExtension.values()), ) # as scan range or rotation angle are not stored in dxfile we # provide the default value which is the "standard" case parser.add_argument( "--scan-range", default="0,180", help="scan range of the projections. Dark and flat will always be " "considered with rotation angle == scan_range[0]", ) # as pixel sizes are not stored in the dxfile and requested for paganin # we provide some default value parser.add_argument( "--pixel-size", default=(None, None), help="pixel size in meter as (x pixel size, y pixel size) or as a single value", ) parser.add_argument( "--fov", "--field-of-view", default=None, help="field of view. Can be Full or Half", dest="field_of_view", ) # as distance is not stored in the dxfile and requested for paganin # we provide some default value parser.add_argument( "--distance", "--detector-sample-distance", default=None, help="sample to detector distance (in meter)", dest="distance", ) parser.add_argument( "--energy", "--incident-beam-energy", default=None, help="incident beam energy in keV", dest="energy", ) parser.add_argument( "--overwrite", help="Do not ask for user permission to overwrite output files", action="store_true", default=False, ) parser.add_argument( "--data-copy", help="Force data duplication of frames. This will permit to have an " "'all-embed' file. Otherwise we will have link between the dxfile " "and the NXTomo.", action="store_true", dest="duplicate_data", default=False, ) options = parser.parse_args(argv[1:]) distance = options.distance if distance is not None: distance = float(options.distance) energy = options.energy if energy is not None: energy = float(options.energy) * metricsystem.EnergySI.KILOELECTRONVOLT.value if options.duplicate_data is False: _logger.warning( "Generated file will contain relative links to the " "(dxfile) source file. You should insure the " "relative position of the input file and the output " "stay constant to protect links. (use --copy-data) " "option to avoid links" ) from_dx_to_nx( input_file=options.input_file, output_file=options.output_file, file_extension=options.file_extension, input_entry=options.input_entry, output_entry=options.output_entry, scan_range=convert_2elmts__tuple_to_float(options.scan_range), pixel_size=_get_pixel_size(options.pixel_size), field_of_view=options.field_of_view, distance=distance, overwrite=options.overwrite, duplicate_data=options.duplicate_data, energy=energy, )