nxtomomill 2.2.0.dev0__tar.gz → 2.2.0.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nxtomomill-2.2.0.dev0/nxtomomill.egg-info → nxtomomill-2.2.0.dev1}/PKG-INFO +2 -2
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/__main__.py +1 -1
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/h52nx.py +19 -2
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/baseacquisition.py +27 -6
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/standardacquisition.py +16 -13
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/tests/test_acquisition.py +33 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/utils/_context.py +7 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/hdf5converter.py +7 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/tests/test_h52nx_utils.py +14 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/tests/test_hdf5converter.py +165 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/io/config/confighandler.py +1 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/io/config/tests/test_confighandler.py +1 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/h52nx/general_section.py +22 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/h52nx/h52nx.py +1 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1/nxtomomill.egg-info}/PKG-INFO +2 -2
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill.egg-info/SOURCES.txt +0 -1
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill.egg-info/requires.txt +1 -1
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/pyproject.toml +2 -2
- nxtomomill-2.2.0.dev0/nxtomomill/converter/edf/_Blosc2Jp2kWrapper.py +0 -63
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/LICENSE +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/README.md +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/doc/conf.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/blissfluo2nx.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/blissfluoconfig.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/dxfile2nx.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/edf2nx.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/edf2nx_check.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/edfconfig.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/fluo2nx.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/fluoconfig.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/fscan2nx.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/h5config.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/nxcopy.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/patch_nx.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/split_nxfile.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/tests/test_bliss_fluo2nx_app.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/tests/test_dxfile2nx_app.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/tests/test_edf2nx_app.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/tests/test_edf_config_app.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/tests/test_fluo2nx_app.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/tests/test_h52nx_app.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/tests/test_h5_config_app.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/tests/test_nx_copy.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/tests/test_patch_nx_app.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/tests/test_split_nxfile_app.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/z_concatenate_scans.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/app/zstages2nxs.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/baseconverter.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/dxfile/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/dxfile/dxfileconverter.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/dxfile/tests/test_dxfile.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/edf/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/edf/checks.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/edf/edfconverter.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/edf/tests/test_checks.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/edf/tests/test_edf2nx.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/edf/tests/test_edf2nx_check.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/fluo/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/fluo/blissfluoscan.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/fluo/fluoconverter.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/fluo/fluoscan.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/fluo/tests/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/fluo/tests/test_fluoscan2D.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/fluo/tests/test_fluoscan3D.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/fscan/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/fscan/fscanconverter.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/_bliss_activeconfig.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/backandforth.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/blisstomoconfig.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/multitomo.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/pcotomoacquisition.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/tests/bliss_tomo_datasets.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/tests/test_acquisition_utils.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/tests/test_back_and_forth.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/tests/test_bliss_tomo_config.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/tests/test_holotomo.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/tests/test_legacy.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/tests/test_multitomo_zseries.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/tests/test_multitomoacquisition.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/utils/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/utils/_keys.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/utils/_scan_type_finder.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/utils/bliss_scan_type.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/utils/detector.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/utils/machine_current.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/utils/series.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/utils/timestamps.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisition/zseriesacquisition.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/acquisitionConstructor.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/post_processing/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/post_processing/dark_flat_copy.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/tests/test_frame_flip.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/utils.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/version.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/io/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/io/config/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/io/config/configbase.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/io/config/dxconfig.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/io/config/edfconfig.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/io/config/fluoconfig.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/io/config/hdf5config.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/io/config/tests/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/io/tests/test_frame_group.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/io/tests/utils.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/base/ConfigBase.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/base/FrmFlatToNestedBase.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/base/NestedModelBase.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/base/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/base/general_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/base/instrument_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/base/source_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/blissfluo2nx/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/blissfluo2nx/blissfluo2nx.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/blissfluo2nx/general_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/dx2nx.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/edf2nx/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/edf2nx/dark_and_flat_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/edf2nx/detector_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/edf2nx/edf2nx.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/edf2nx/general_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/edf2nx/keys_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/edf2nx/sample_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/edf2nx/unit_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/fluo2nx/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/fluo2nx/fluo2nx.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/fluo2nx/general_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/h52nx/FrameGroup.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/h52nx/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/h52nx/_acquisitionstep.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/h52nx/_context.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/h52nx/entries_and_title_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/h52nx/extra_params_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/h52nx/frame_type_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/h52nx/keys_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/h52nx/multitomo_section.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/tests/test_context.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/tests/test_edf2nx_model.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/tests/test_fluo2nx_model.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/tests/test_h52nx_model.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/tests/test_io_utils.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/models/utils.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/settings.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/test.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/tests/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/tests/datasets.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/tests/resources/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/tests/resources/edf2nx_config_files/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/tests/resources/fluo2nx_config_files/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/tests/resources/h52nx_config_files/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/tests/test_version.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/tests/utils/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/tests/utils/bliss.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/tests/utils/dxfile.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/__init__.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/_os.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/flat_reducer.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/h5pyutils.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/hdf5.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/io.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/nexus.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/pintutils.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/tests/test_flat_reducer.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/tests/test_h5pyutils.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/tests/test_nexus_utils.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/tests/test_utils.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/utils/utils.py +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill.egg-info/dependency_links.txt +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill.egg-info/entry_points.txt +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill.egg-info/top_level.txt +0 -0
- {nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nxtomomill
|
|
3
|
-
Version: 2.2.0.
|
|
3
|
+
Version: 2.2.0.dev1
|
|
4
4
|
Summary: applications and library to convert raw format to NXtomo format
|
|
5
5
|
Author-email: Henri Payno <henri.payno@esrf.fr>, Pierre Paleo <pierre.paleo@esrf.fr>, Pierre-Olivier Autran <pierre-olivier.autran@esrf.fr>, Jérôme Lesaint <jerome.lesaint@esrf.fr>, Alessandro Mirone <mirone@esrf.fr>
|
|
6
6
|
License:
|
|
@@ -58,7 +58,7 @@ Requires-Dist: silx>=2.0
|
|
|
58
58
|
Requires-Dist: nxtomo>=3.1.0dev1
|
|
59
59
|
Requires-Dist: pint
|
|
60
60
|
Requires-Dist: packaging
|
|
61
|
-
Requires-Dist: tomoscan
|
|
61
|
+
Requires-Dist: tomoscan>=3.0.0dev0
|
|
62
62
|
Requires-Dist: tomobase>=0.0.0dev0
|
|
63
63
|
Requires-Dist: tqdm
|
|
64
64
|
Requires-Dist: pydantic
|
|
@@ -15,7 +15,7 @@ import logging
|
|
|
15
15
|
from tqdm import tqdm
|
|
16
16
|
|
|
17
17
|
from nxtomomill import utils
|
|
18
|
-
from nxtomomill.converter import
|
|
18
|
+
from nxtomomill.converter.hdf5.hdf5converter import _H5ToNxConverter
|
|
19
19
|
from nxtomomill.io.config.confighandler import (
|
|
20
20
|
SETTABLE_PARAMETERS_UNITS,
|
|
21
21
|
TomoHDF5ConfigHandler,
|
|
@@ -317,6 +317,20 @@ def main(argv):
|
|
|
317
317
|
"Sometime relative link cannot be solved (GPFS vs NFS). "
|
|
318
318
|
"In this case you might be forced to use absolute path.",
|
|
319
319
|
)
|
|
320
|
+
parser.add_argument(
|
|
321
|
+
"--no-resolve-vds",
|
|
322
|
+
"--no-resolve-vds-links",
|
|
323
|
+
"--no_resolve_vds",
|
|
324
|
+
dest="resolve_vds",
|
|
325
|
+
action="store_false",
|
|
326
|
+
default=None,
|
|
327
|
+
help="Do not resolve external links and virtual datasets (VDS) down to "
|
|
328
|
+
"their final source when building the output NXtomo. Can speed up the "
|
|
329
|
+
"conversion for datasets with many nested links, at the cost of the "
|
|
330
|
+
"output file containing VDS pointing to other VDS instead of direct "
|
|
331
|
+
"links to the raw data. Defaults to the 'NXTOMOMILL_RESOLVE_VDS' "
|
|
332
|
+
"environment variable if set, else resolving is enabled.",
|
|
333
|
+
)
|
|
320
334
|
options = parser.parse_args(argv[1:])
|
|
321
335
|
if options.request_input:
|
|
322
336
|
callback_det_sel = _ask_for_selecting_detector
|
|
@@ -335,9 +349,12 @@ def main(argv):
|
|
|
335
349
|
configuration_handler.configuration.log_level
|
|
336
350
|
)
|
|
337
351
|
with tqdm(desc="h52nx", delay=1, bar_format="{l_bar}{bar}") as progress:
|
|
338
|
-
|
|
352
|
+
converter = _H5ToNxConverter(
|
|
339
353
|
configuration=configuration_handler.configuration,
|
|
340
354
|
progress=progress,
|
|
341
355
|
input_callback=None,
|
|
342
356
|
detector_sel_callback=callback_det_sel,
|
|
343
357
|
)
|
|
358
|
+
converter.convert()
|
|
359
|
+
if converter.has_failed_acquisitions:
|
|
360
|
+
return 1
|
|
@@ -31,7 +31,7 @@ from silx.io.utils import h5py_read_dataset
|
|
|
31
31
|
|
|
32
32
|
from nxtomomill.models.h52nx.h52nx import H52nxModel
|
|
33
33
|
from .utils._keys import keys_to_str_tuple
|
|
34
|
-
from .utils._context import read_key, MissingValue
|
|
34
|
+
from .utils._context import read_key, MissingValue, InvalidValue
|
|
35
35
|
|
|
36
36
|
_ureg = pint.get_application_registry()
|
|
37
37
|
_logger = logging.getLogger(__name__)
|
|
@@ -300,6 +300,7 @@ class BaseAcquisition:
|
|
|
300
300
|
file_path=output_file,
|
|
301
301
|
data_path=data_path,
|
|
302
302
|
use_abs_path_for_vds=self.configuration.use_abs_path_for_vds,
|
|
303
|
+
overwrite=self.configuration.overwrite,
|
|
303
304
|
)
|
|
304
305
|
# check rotation angle
|
|
305
306
|
if nx_tomo.sample.rotation_angle is not None:
|
|
@@ -408,6 +409,11 @@ class BaseAcquisition:
|
|
|
408
409
|
except MissingValue:
|
|
409
410
|
# skip values containing '*DIS*'
|
|
410
411
|
continue
|
|
412
|
+
except InvalidValue:
|
|
413
|
+
# dataset reports an 'ERR' value: let it propagate, the
|
|
414
|
+
# caller decides how to handle it (e.g. translations
|
|
415
|
+
# fall back to None instead of trying other keys)
|
|
416
|
+
raise
|
|
411
417
|
except KeyError as e:
|
|
412
418
|
_logger.info(
|
|
413
419
|
f"Cannot solve key {key}. Most likely one dataset is not there. Error is {e}"
|
|
@@ -697,7 +703,7 @@ class BaseAcquisition:
|
|
|
697
703
|
_logger.warning(mess)
|
|
698
704
|
return ([0] * n_frame) * _ureg.meter
|
|
699
705
|
|
|
700
|
-
def _get_translation_x(self, root_node, n_frame) -> pint.
|
|
706
|
+
def _get_translation_x(self, root_node, n_frame) -> pint.Quantity | None:
|
|
701
707
|
"""return the list of translation for each frame"""
|
|
702
708
|
for grp in self._get_positioners_node(root_node), root_node:
|
|
703
709
|
try:
|
|
@@ -708,6 +714,11 @@ class BaseAcquisition:
|
|
|
708
714
|
info_retrieve="x base translation",
|
|
709
715
|
expected_unit=_ureg.mm,
|
|
710
716
|
)
|
|
717
|
+
except InvalidValue:
|
|
718
|
+
_logger.error(
|
|
719
|
+
f"translation x reports an 'ERR' value for {root_node.name}. Translation x will be set to None."
|
|
720
|
+
)
|
|
721
|
+
return None
|
|
711
722
|
except (ValueError, KeyError):
|
|
712
723
|
pass
|
|
713
724
|
else:
|
|
@@ -721,7 +732,7 @@ class BaseAcquisition:
|
|
|
721
732
|
_logger.warning(mess)
|
|
722
733
|
return ([0] * n_frame) * _ureg.meter
|
|
723
734
|
|
|
724
|
-
def _get_translation_y(self, root_node, n_frame) -> pint.
|
|
735
|
+
def _get_translation_y(self, root_node, n_frame) -> pint.Quantity | None:
|
|
725
736
|
"""return the list of translation for each frame"""
|
|
726
737
|
for grp in self._get_positioners_node(root_node), root_node:
|
|
727
738
|
try:
|
|
@@ -732,6 +743,11 @@ class BaseAcquisition:
|
|
|
732
743
|
info_retrieve="y base translation",
|
|
733
744
|
expected_unit=_ureg.mm,
|
|
734
745
|
)
|
|
746
|
+
except InvalidValue:
|
|
747
|
+
_logger.error(
|
|
748
|
+
f"translation y reports an 'ERR' value for {root_node.name}. Translation y will be set to None."
|
|
749
|
+
)
|
|
750
|
+
return None
|
|
735
751
|
except (ValueError, KeyError):
|
|
736
752
|
pass
|
|
737
753
|
else:
|
|
@@ -748,7 +764,7 @@ class BaseAcquisition:
|
|
|
748
764
|
@staticmethod
|
|
749
765
|
def get_translation_z_frm(
|
|
750
766
|
root_node, n_frame: int, configuration: H52nxModel
|
|
751
|
-
) -> pint.Quantity:
|
|
767
|
+
) -> pint.Quantity | None:
|
|
752
768
|
for grp in BaseAcquisition._get_positioners_node(root_node), root_node:
|
|
753
769
|
try:
|
|
754
770
|
z_tr, unit = BaseAcquisition._get_node_values_for_frame_array(
|
|
@@ -758,6 +774,11 @@ class BaseAcquisition:
|
|
|
758
774
|
info_retrieve="z translation",
|
|
759
775
|
expected_unit=_ureg.mm,
|
|
760
776
|
)
|
|
777
|
+
except InvalidValue:
|
|
778
|
+
_logger.error(
|
|
779
|
+
f"translation z reports an 'ERR' value for {root_node.name}. Translation z will be set to None."
|
|
780
|
+
)
|
|
781
|
+
return None
|
|
761
782
|
except (ValueError, KeyError):
|
|
762
783
|
pass
|
|
763
784
|
else:
|
|
@@ -771,7 +792,7 @@ class BaseAcquisition:
|
|
|
771
792
|
_logger.warning(mess)
|
|
772
793
|
return ([0] * n_frame) * _ureg.meter
|
|
773
794
|
|
|
774
|
-
def _get_translation_z(self, root_node, n_frame) -> pint.Quantity:
|
|
795
|
+
def _get_translation_z(self, root_node, n_frame) -> pint.Quantity | None:
|
|
775
796
|
"""return the list of translation z for each frame"""
|
|
776
797
|
return self.get_translation_z_frm(
|
|
777
798
|
root_node=root_node,
|
|
@@ -804,7 +825,7 @@ class BaseAcquisition:
|
|
|
804
825
|
else:
|
|
805
826
|
mess += "default value will be set. (0)"
|
|
806
827
|
_logger.warning(mess)
|
|
807
|
-
return
|
|
828
|
+
return numpy.zeros(n_frame) * _ureg.second
|
|
808
829
|
|
|
809
830
|
def get_axis_scale_types(self):
|
|
810
831
|
"""
|
|
@@ -346,19 +346,22 @@ class StandardAcquisition(BaseAcquisition):
|
|
|
346
346
|
image_key_control = frame_type.to_image_key_control()
|
|
347
347
|
self._image_key_control.extend([image_key_control.value] * n_frame)
|
|
348
348
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
349
|
+
if self.configuration.resolve_vds:
|
|
350
|
+
try:
|
|
351
|
+
solved_camera_dataset_urls = resolve_link(
|
|
352
|
+
dataset_url=camera_dataset_url,
|
|
353
|
+
dataset=data_dataset,
|
|
354
|
+
dataset_link=data_dataset_link,
|
|
355
|
+
open_mode_for_reading=self.configuration.open_mode_for_reading,
|
|
356
|
+
)
|
|
357
|
+
except OSError as e:
|
|
358
|
+
# This can happen if one fine cannot be found. In test for example where we are only using the master file
|
|
359
|
+
# and low level bliss / tango .h5 files are not existing
|
|
360
|
+
_logger.warning(
|
|
361
|
+
"Fail to solve camera dataset links and VDS. Error is %s", e
|
|
362
|
+
)
|
|
363
|
+
solved_camera_dataset_urls = (camera_dataset_url,)
|
|
364
|
+
else:
|
|
362
365
|
solved_camera_dataset_urls = (camera_dataset_url,)
|
|
363
366
|
|
|
364
367
|
n_total_frame_solved = 0
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import os
|
|
4
4
|
import tempfile
|
|
5
5
|
|
|
6
|
+
import h5py
|
|
6
7
|
import pytest
|
|
7
8
|
from silx.io.url import DataUrl
|
|
8
9
|
|
|
@@ -52,6 +53,38 @@ def test_get_dataset_name_from_motor():
|
|
|
52
53
|
get_dataset_name_from_motor(set_3, "rotation")
|
|
53
54
|
|
|
54
55
|
|
|
56
|
+
@pytest.mark.parametrize("raises_error", (True, False))
|
|
57
|
+
def test_translation_with_err_value(tmp_path, raises_error):
|
|
58
|
+
"""
|
|
59
|
+
Test that translation x, y and z are set to None (instead of failing)
|
|
60
|
+
when the corresponding dataset reports an 'ERR' value.
|
|
61
|
+
"""
|
|
62
|
+
file_path = os.path.join(tmp_path, "test.h5")
|
|
63
|
+
with HDF5File(file_path, mode="w") as h5f:
|
|
64
|
+
h5f["/entry/instrument/positioners/tx"] = "ERR"
|
|
65
|
+
h5f["/entry/instrument/positioners/ty"] = "ERR"
|
|
66
|
+
h5f["/entry/instrument/positioners/tz"] = "ERR"
|
|
67
|
+
|
|
68
|
+
config = TomoHDF5Config()
|
|
69
|
+
config.raises_error = raises_error
|
|
70
|
+
config.translation_x_keys = ("tx",)
|
|
71
|
+
config.translation_y_keys = ("ty",)
|
|
72
|
+
config.translation_z_keys = ("tz",)
|
|
73
|
+
|
|
74
|
+
url = DataUrl(file_path=file_path, data_path="/entry", scheme="silx")
|
|
75
|
+
std_acq = BaseAcquisition(
|
|
76
|
+
root_url=url,
|
|
77
|
+
configuration=config,
|
|
78
|
+
detector_sel_callback=None,
|
|
79
|
+
start_index=0,
|
|
80
|
+
)
|
|
81
|
+
with h5py.File(file_path, mode="r") as h5f:
|
|
82
|
+
root_node = h5f["/entry"]
|
|
83
|
+
assert std_acq._get_translation_x(root_node=root_node, n_frame=1) is None
|
|
84
|
+
assert std_acq._get_translation_y(root_node=root_node, n_frame=1) is None
|
|
85
|
+
assert std_acq._get_translation_z(root_node=root_node, n_frame=1) is None
|
|
86
|
+
|
|
87
|
+
|
|
55
88
|
def test_frame_flips(tmp_path, monkeypatch):
|
|
56
89
|
# make sure the result is obtained by using the "instrument/{active_config_tomo_detector}/data_axes" path.
|
|
57
90
|
monkeypatch.setattr(
|
|
@@ -163,6 +163,10 @@ class MissingValue(ValueError):
|
|
|
163
163
|
"""Raised if a dataset contains 'DIS' - not saved"""
|
|
164
164
|
|
|
165
165
|
|
|
166
|
+
class InvalidValue(ValueError):
|
|
167
|
+
"""Raised if a dataset contains 'ERR' - value could not be read from the hardware"""
|
|
168
|
+
|
|
169
|
+
|
|
166
170
|
def read_key(
|
|
167
171
|
key: str,
|
|
168
172
|
node: h5py.Group,
|
|
@@ -210,6 +214,9 @@ def read_key(
|
|
|
210
214
|
# skip values containing '*DIS*'
|
|
211
215
|
if isinstance(values, str) and values == "*DIS*":
|
|
212
216
|
raise MissingValue(f"dataset {dataset_name} has not been recorded")
|
|
217
|
+
# dataset reports an 'ERR' value if the hardware failed to record it
|
|
218
|
+
if isinstance(values, str) and values == "ERR":
|
|
219
|
+
raise InvalidValue(f"dataset {dataset_name} reports an 'ERR' value")
|
|
213
220
|
|
|
214
221
|
first_dataset = dataset_names[0]
|
|
215
222
|
result_unit = dataset_units[first_dataset] or expected_unit
|
|
@@ -146,6 +146,7 @@ class _H5ToNxConverter(BaseConverter):
|
|
|
146
146
|
self._detector_sel_callback = detector_sel_callback
|
|
147
147
|
self._acquisitions = []
|
|
148
148
|
self._entries_created = []
|
|
149
|
+
self._conversion_errors: list[tuple[str, Exception]] = []
|
|
149
150
|
self._z_series_v2_v3: list[list[ZSeriesBaseAcquisition]] = []
|
|
150
151
|
# bliss z-series for version 2 and 3. Can be used for post-processing
|
|
151
152
|
self.preprocess()
|
|
@@ -176,6 +177,11 @@ class _H5ToNxConverter(BaseConverter):
|
|
|
176
177
|
def acquisitions(self):
|
|
177
178
|
return self._acquisitions
|
|
178
179
|
|
|
180
|
+
@property
|
|
181
|
+
def has_failed_acquisitions(self) -> bool:
|
|
182
|
+
"""True if at least one acquisition failed to be converted (and the error was not raised, see 'raises_error')"""
|
|
183
|
+
return len(self._conversion_errors) > 0
|
|
184
|
+
|
|
179
185
|
def preprocess(self):
|
|
180
186
|
self._preprocess_urls()
|
|
181
187
|
self._check_conversion_is_possible()
|
|
@@ -311,6 +317,7 @@ class _H5ToNxConverter(BaseConverter):
|
|
|
311
317
|
exc_info=e,
|
|
312
318
|
)
|
|
313
319
|
acquisition_to_nxtomo[acquisition] = None
|
|
320
|
+
self._conversion_errors.append((root_location, e))
|
|
314
321
|
else:
|
|
315
322
|
res.extend(new_entries)
|
|
316
323
|
acquisition_to_nxtomo[acquisition] = new_entries
|
{nxtomomill-2.2.0.dev0 → nxtomomill-2.2.0.dev1}/nxtomomill/converter/hdf5/tests/test_h52nx_utils.py
RENAMED
|
@@ -18,6 +18,7 @@ from nxtomomill.converter.hdf5.acquisition.utils._context import (
|
|
|
18
18
|
update_config_keys_from_tomo_config_context,
|
|
19
19
|
read_key,
|
|
20
20
|
MissingValue,
|
|
21
|
+
InvalidValue,
|
|
21
22
|
)
|
|
22
23
|
from nxtomomill.converter.hdf5.acquisition.blisstomoconfig import TomoConfig
|
|
23
24
|
from nxtomomill.converter.hdf5.acquisition.utils._keys import _Key
|
|
@@ -151,6 +152,10 @@ def read_key_datasets(tmp_path):
|
|
|
151
152
|
f.create_dataset("missing_data/dataset9", data="*DIS*")
|
|
152
153
|
f.create_dataset("missing_data/dataset10", data=numpy.random.random(10))
|
|
153
154
|
|
|
155
|
+
# Create datasets with 'ERR' (hardware failed to record the value)
|
|
156
|
+
f.create_dataset("invalid_data/dataset22", data="ERR")
|
|
157
|
+
f.create_dataset("invalid_data/dataset23", data=numpy.random.random(10))
|
|
158
|
+
|
|
154
159
|
# Create datasets with coherent units (but different)
|
|
155
160
|
f.create_dataset("with_coherent_units/dataset11", data=numpy.ones(10))
|
|
156
161
|
f["with_coherent_units/dataset11"].attrs["unit"] = "meter"
|
|
@@ -214,6 +219,15 @@ def test_read_key(read_key_datasets, caplog):
|
|
|
214
219
|
expected_unit=_ureg.meter,
|
|
215
220
|
)
|
|
216
221
|
|
|
222
|
+
# test with dataset reporting an 'ERR' value
|
|
223
|
+
with pytest.raises(InvalidValue):
|
|
224
|
+
read_key(
|
|
225
|
+
key="dataset22+dataset23",
|
|
226
|
+
node=h5f["invalid_data"],
|
|
227
|
+
info_retrieve="",
|
|
228
|
+
expected_unit=_ureg.meter,
|
|
229
|
+
)
|
|
230
|
+
|
|
217
231
|
# test with dataset with coherent size and no unit
|
|
218
232
|
quantity: pint.Quantity = read_key(
|
|
219
233
|
key="dataset7+dataset8",
|
|
@@ -1415,6 +1415,171 @@ def test_id16a_use_case(tmp_path):
|
|
|
1415
1415
|
transformation.transformation_values.magnitude == numpy.array([0.0])
|
|
1416
1416
|
|
|
1417
1417
|
|
|
1418
|
+
def test_resolve_vds_option(tmp_path, monkeypatch):
|
|
1419
|
+
"""
|
|
1420
|
+
Test that the 'resolve_vds' configuration option correctly enables /
|
|
1421
|
+
disables the resolving of external links and virtual datasets (VDS)
|
|
1422
|
+
when building the camera dataset of the output NXtomo.
|
|
1423
|
+
"""
|
|
1424
|
+
import nxtomomill.converter.hdf5.acquisition.standardacquisition as standardacquisition_module
|
|
1425
|
+
|
|
1426
|
+
folder = tmp_path / "output_test_resolve_vds_option"
|
|
1427
|
+
folder.mkdir()
|
|
1428
|
+
bliss_mock = MockBlissAcquisition(
|
|
1429
|
+
n_sample=1,
|
|
1430
|
+
n_sequence=1,
|
|
1431
|
+
n_scan_per_sequence=2,
|
|
1432
|
+
n_darks=1,
|
|
1433
|
+
n_flats=1,
|
|
1434
|
+
with_nx_detector_attr=True,
|
|
1435
|
+
output_dir=folder,
|
|
1436
|
+
detector_name="pcolinux",
|
|
1437
|
+
create_tomo_config=False,
|
|
1438
|
+
)
|
|
1439
|
+
sample = bliss_mock.samples[0]
|
|
1440
|
+
|
|
1441
|
+
call_counter = {"n": 0}
|
|
1442
|
+
original_resolve_link = standardacquisition_module.resolve_link
|
|
1443
|
+
|
|
1444
|
+
def _counting_resolve_link(*args, **kwargs):
|
|
1445
|
+
call_counter["n"] += 1
|
|
1446
|
+
return original_resolve_link(*args, **kwargs)
|
|
1447
|
+
|
|
1448
|
+
monkeypatch.setattr(
|
|
1449
|
+
standardacquisition_module, "resolve_link", _counting_resolve_link
|
|
1450
|
+
)
|
|
1451
|
+
|
|
1452
|
+
config = TomoHDF5Config()
|
|
1453
|
+
config.input_file = sample.sample_file
|
|
1454
|
+
config.single_file = True
|
|
1455
|
+
config.sample_x_keys = ("sx",)
|
|
1456
|
+
config.sample_y_keys = ("sy",)
|
|
1457
|
+
config.translation_x_keys = ("tx",)
|
|
1458
|
+
|
|
1459
|
+
# by default (and with 'resolve_vds' explicitly set to True) links / VDS are resolved
|
|
1460
|
+
config.resolve_vds = True
|
|
1461
|
+
config.output_file = str(tmp_path / "output_resolve_vds_true.nx")
|
|
1462
|
+
converter.from_h5_to_nx(configuration=config)
|
|
1463
|
+
assert call_counter["n"] > 0
|
|
1464
|
+
assert os.path.exists(config.output_file)
|
|
1465
|
+
|
|
1466
|
+
# disabling 'resolve_vds' must skip the resolving step entirely
|
|
1467
|
+
call_counter["n"] = 0
|
|
1468
|
+
config.resolve_vds = False
|
|
1469
|
+
config.output_file = str(tmp_path / "output_resolve_vds_false.nx")
|
|
1470
|
+
converter.from_h5_to_nx(configuration=config)
|
|
1471
|
+
assert call_counter["n"] == 0
|
|
1472
|
+
assert os.path.exists(config.output_file)
|
|
1473
|
+
|
|
1474
|
+
|
|
1475
|
+
def test_single_file_and_overwrite_from_cli(tmp_path):
|
|
1476
|
+
"""
|
|
1477
|
+
Test that the `--single-file` and `--overwrite` options provided from
|
|
1478
|
+
the CLI are correctly propagated down to the NXtomo saving step.
|
|
1479
|
+
"""
|
|
1480
|
+
folder = tmp_path / "output_test_single_file_and_overwrite_from_cli"
|
|
1481
|
+
folder.mkdir()
|
|
1482
|
+
bliss_mock = MockBlissAcquisition(
|
|
1483
|
+
n_sample=1,
|
|
1484
|
+
n_sequence=1,
|
|
1485
|
+
n_scan_per_sequence=2,
|
|
1486
|
+
n_darks=1,
|
|
1487
|
+
n_flats=1,
|
|
1488
|
+
with_nx_detector_attr=True,
|
|
1489
|
+
output_dir=folder,
|
|
1490
|
+
detector_name="pcolinux",
|
|
1491
|
+
create_tomo_config=False,
|
|
1492
|
+
)
|
|
1493
|
+
sample = bliss_mock.samples[0]
|
|
1494
|
+
output_file = sample.sample_file.replace(".h5", ".nx")
|
|
1495
|
+
|
|
1496
|
+
config = H52nxModel()
|
|
1497
|
+
config.input_file = sample.sample_file
|
|
1498
|
+
config.output_file = output_file
|
|
1499
|
+
config.single_file = True
|
|
1500
|
+
config.request_input = False
|
|
1501
|
+
config.raises_error = True
|
|
1502
|
+
config.overwrite = False
|
|
1503
|
+
config.sample_x_keys = ("sx",)
|
|
1504
|
+
config.sample_y_keys = ("sy",)
|
|
1505
|
+
config.translation_x_keys = ("tx",)
|
|
1506
|
+
|
|
1507
|
+
config_file = tmp_path / "config.cfg"
|
|
1508
|
+
config.to_cfg_file(file_path=str(config_file))
|
|
1509
|
+
|
|
1510
|
+
cmd = (
|
|
1511
|
+
sys.executable,
|
|
1512
|
+
"-m",
|
|
1513
|
+
"nxtomomill",
|
|
1514
|
+
"h52nx",
|
|
1515
|
+
sample.sample_file,
|
|
1516
|
+
output_file,
|
|
1517
|
+
"--config",
|
|
1518
|
+
config_file,
|
|
1519
|
+
)
|
|
1520
|
+
|
|
1521
|
+
# first call creates the output file
|
|
1522
|
+
assert subprocess.call(cmd, cwd=tmp_path) == 0 # nosec B603
|
|
1523
|
+
assert os.path.exists(output_file)
|
|
1524
|
+
|
|
1525
|
+
# calling it again without `--overwrite` must fail as the output file already exists
|
|
1526
|
+
# and 'overwrite' is set to False in the configuration
|
|
1527
|
+
assert subprocess.call(cmd, cwd=tmp_path) != 0 # nosec B603
|
|
1528
|
+
|
|
1529
|
+
# calling it again with `--overwrite` provided from the CLI must succeed: the option must be
|
|
1530
|
+
# forwarded to the NXtomo saving step even in `--single-file` mode
|
|
1531
|
+
assert subprocess.call((*cmd, "--overwrite"), cwd=tmp_path) == 0 # nosec B603
|
|
1532
|
+
|
|
1533
|
+
|
|
1534
|
+
def test_cli_exit_code_on_failed_entry(tmp_path):
|
|
1535
|
+
"""
|
|
1536
|
+
Test that the CLI exits with a non-zero status code when an entry fails
|
|
1537
|
+
to be converted, even though 'raises_error' is left to its default value
|
|
1538
|
+
(False), in which case the error is logged and the conversion carries on
|
|
1539
|
+
with the other entries instead of raising.
|
|
1540
|
+
"""
|
|
1541
|
+
folder = tmp_path / "output_test_cli_exit_code_on_failed_entry"
|
|
1542
|
+
folder.mkdir()
|
|
1543
|
+
bliss_mock = MockBlissAcquisition(
|
|
1544
|
+
n_sample=1,
|
|
1545
|
+
n_sequence=1,
|
|
1546
|
+
n_scan_per_sequence=2,
|
|
1547
|
+
n_darks=1,
|
|
1548
|
+
n_flats=1,
|
|
1549
|
+
with_nx_detector_attr=True,
|
|
1550
|
+
output_dir=folder,
|
|
1551
|
+
detector_name="pcolinux",
|
|
1552
|
+
create_tomo_config=False,
|
|
1553
|
+
)
|
|
1554
|
+
sample = bliss_mock.samples[0]
|
|
1555
|
+
output_file = sample.sample_file.replace(".h5", ".nx")
|
|
1556
|
+
|
|
1557
|
+
cmd = (
|
|
1558
|
+
sys.executable,
|
|
1559
|
+
"-m",
|
|
1560
|
+
"nxtomomill",
|
|
1561
|
+
"h52nx",
|
|
1562
|
+
sample.sample_file,
|
|
1563
|
+
output_file,
|
|
1564
|
+
"--single-file",
|
|
1565
|
+
"--no-input",
|
|
1566
|
+
"--sample_x_keys",
|
|
1567
|
+
"sx",
|
|
1568
|
+
"--sample_y_keys",
|
|
1569
|
+
"sy",
|
|
1570
|
+
)
|
|
1571
|
+
|
|
1572
|
+
# first call creates the output file and must succeed
|
|
1573
|
+
assert subprocess.call(cmd, cwd=tmp_path) == 0 # nosec B603
|
|
1574
|
+
assert os.path.exists(output_file)
|
|
1575
|
+
|
|
1576
|
+
# calling it again (without `--overwrite` nor `--raises-error`) makes the
|
|
1577
|
+
# entry conversion fail internally (it is logged and the conversion is
|
|
1578
|
+
# not interrupted), the CLI must still report the failure through its
|
|
1579
|
+
# exit code
|
|
1580
|
+
assert subprocess.call(cmd, cwd=tmp_path) != 0 # nosec B603
|
|
1581
|
+
|
|
1582
|
+
|
|
1418
1583
|
def test_warning(tmp_path, caplog):
|
|
1419
1584
|
"""Test that the application raises a warning if bliss acquisition has 'end_reason' different than 'SUCCESS'"""
|
|
1420
1585
|
config = TomoHDF5Config()
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import os
|
|
3
4
|
from typing import Literal
|
|
4
5
|
from collections import deque
|
|
5
6
|
from pydantic import Field, field_serializer, field_validator, ConfigDict
|
|
@@ -14,6 +15,15 @@ from nxtomomill.models.utils import (
|
|
|
14
15
|
from ..base.general_section import GeneralSection as _GeneralSectionBase
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
def _default_resolve_vds() -> bool:
|
|
19
|
+
"""
|
|
20
|
+
Default value for 'resolve_vds'. Fallback on the 'NXTOMOMILL_RESOLVE_VDS'
|
|
21
|
+
environment variable when set, else defaults to True.
|
|
22
|
+
"""
|
|
23
|
+
env_value = os.environ.get("NXTOMOMILL_RESOLVE_VDS", True)
|
|
24
|
+
return convert_str_to_bool(env_value)
|
|
25
|
+
|
|
26
|
+
|
|
17
27
|
class GeneralSection(_GeneralSectionBase):
|
|
18
28
|
model_config = ConfigDict(validate_assignment=True, validate_by_name=True)
|
|
19
29
|
|
|
@@ -69,6 +79,17 @@ class GeneralSection(_GeneralSectionBase):
|
|
|
69
79
|
default="robust",
|
|
70
80
|
description="How to open the HDF5 file for reading. Either 'robust' mode (disabling file locking) or 'safe'(with file locking)",
|
|
71
81
|
)
|
|
82
|
+
resolve_vds: bool = Field(
|
|
83
|
+
default_factory=_default_resolve_vds,
|
|
84
|
+
description=(
|
|
85
|
+
"Resolve external links and virtual datasets (VDS) down to their final "
|
|
86
|
+
"source when building the output NXtomo. Disabling this can speed up "
|
|
87
|
+
"the conversion for datasets with many nested links, at the cost of "
|
|
88
|
+
"the output file containing VDS pointing to other VDS instead of "
|
|
89
|
+
"direct links to the raw data. Defaults to the 'NXTOMOMILL_RESOLVE_VDS' "
|
|
90
|
+
"environment variable if set, else True."
|
|
91
|
+
),
|
|
92
|
+
)
|
|
72
93
|
|
|
73
94
|
@property
|
|
74
95
|
def request_input(self) -> bool:
|
|
@@ -147,6 +168,7 @@ class GeneralSection(_GeneralSectionBase):
|
|
|
147
168
|
"create_control_data",
|
|
148
169
|
"mechanical_lr_flip",
|
|
149
170
|
"mechanical_ud_flip",
|
|
171
|
+
"resolve_vds",
|
|
150
172
|
mode="before",
|
|
151
173
|
)
|
|
152
174
|
@classmethod
|
|
@@ -57,6 +57,7 @@ class H52nxModel(
|
|
|
57
57
|
mechanical_ud_flip=self.mechanical_ud_flip,
|
|
58
58
|
open_mode_for_reading=self.open_mode_for_reading,
|
|
59
59
|
output_entries=self.output_entries,
|
|
60
|
+
resolve_vds=self.resolve_vds,
|
|
60
61
|
),
|
|
61
62
|
keys_section=KeysSection(
|
|
62
63
|
valid_camera_names=self.valid_camera_names,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nxtomomill
|
|
3
|
-
Version: 2.2.0.
|
|
3
|
+
Version: 2.2.0.dev1
|
|
4
4
|
Summary: applications and library to convert raw format to NXtomo format
|
|
5
5
|
Author-email: Henri Payno <henri.payno@esrf.fr>, Pierre Paleo <pierre.paleo@esrf.fr>, Pierre-Olivier Autran <pierre-olivier.autran@esrf.fr>, Jérôme Lesaint <jerome.lesaint@esrf.fr>, Alessandro Mirone <mirone@esrf.fr>
|
|
6
6
|
License:
|
|
@@ -58,7 +58,7 @@ Requires-Dist: silx>=2.0
|
|
|
58
58
|
Requires-Dist: nxtomo>=3.1.0dev1
|
|
59
59
|
Requires-Dist: pint
|
|
60
60
|
Requires-Dist: packaging
|
|
61
|
-
Requires-Dist: tomoscan
|
|
61
|
+
Requires-Dist: tomoscan>=3.0.0dev0
|
|
62
62
|
Requires-Dist: tomobase>=0.0.0dev0
|
|
63
63
|
Requires-Dist: tqdm
|
|
64
64
|
Requires-Dist: pydantic
|
|
@@ -45,7 +45,6 @@ nxtomomill/converter/version.py
|
|
|
45
45
|
nxtomomill/converter/dxfile/__init__.py
|
|
46
46
|
nxtomomill/converter/dxfile/dxfileconverter.py
|
|
47
47
|
nxtomomill/converter/dxfile/tests/test_dxfile.py
|
|
48
|
-
nxtomomill/converter/edf/_Blosc2Jp2kWrapper.py
|
|
49
48
|
nxtomomill/converter/edf/__init__.py
|
|
50
49
|
nxtomomill/converter/edf/checks.py
|
|
51
50
|
nxtomomill/converter/edf/edfconverter.py
|
|
@@ -7,7 +7,7 @@ authors = [
|
|
|
7
7
|
{ name = "Jérôme Lesaint", email = "jerome.lesaint@esrf.fr" },
|
|
8
8
|
{ name = "Alessandro Mirone", email = "mirone@esrf.fr" }
|
|
9
9
|
]
|
|
10
|
-
version = "2.2.
|
|
10
|
+
version = "2.2.0dev1"
|
|
11
11
|
description = "applications and library to convert raw format to NXtomo format"
|
|
12
12
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
13
13
|
|
|
@@ -39,7 +39,7 @@ dependencies = [
|
|
|
39
39
|
"nxtomo>=3.1.0dev1",
|
|
40
40
|
"pint",
|
|
41
41
|
"packaging",
|
|
42
|
-
"tomoscan
|
|
42
|
+
"tomoscan>=3.0.0dev0",
|
|
43
43
|
"tomobase>=0.0.0dev0",
|
|
44
44
|
"tqdm",
|
|
45
45
|
"pydantic",
|