nabu 2025.1.0rc4__tar.gz → 2025.1.0rc6__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.
- {nabu-2025.1.0rc4/nabu.egg-info → nabu-2025.1.0rc6}/PKG-INFO +1 -1
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/__init__.py +1 -1
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/cli_configs.py +15 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/estimate_motion.py +21 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/io/reader.py +12 -4
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/io/tests/test_readers.py +37 -34
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/estimators.py +7 -2
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/fullfield/chunked.py +23 -9
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/fullfield/processconfig.py +2 -1
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/flatfield.py +3 -3
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/azim.py +7 -3
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/mlem.py +2 -2
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/dataset_analyzer.py +35 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/nxflatfield.py +1 -1
- nabu-2025.1.0rc6/nabu/resources/tests/test_dataset_analyzer.py +37 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/testutils.py +34 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6/nabu.egg-info}/PKG-INFO +1 -1
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu.egg-info/SOURCES.txt +1 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/LICENSE +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/README.md +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/doc/conf.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/doc/create_conf_doc.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/doc/get_mathjax.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/bootstrap.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/bootstrap_stitching.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/cast_volume.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/compare_volumes.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/composite_cor.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/create_distortion_map_from_poly.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/diag_to_pix.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/diag_to_rot.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/double_flatfield.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/generate_header.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/histogram.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/multicor.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/nx_z_splitter.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/parse_reconstruction_log.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/pcaflats.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/prepare_weights_double.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/reconstruct.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/reconstruct_helical.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/reduce_dark_flat.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/rotate.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/shrink_dataset.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/stitching.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/tests/test_reduce_dark_flat.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/app/validator.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/convolution.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/fft.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/kernel.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/medfilt.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/padding.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/processing.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/ElementOp.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/backproj.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/backproj_polar.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/boundary.h +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/cone.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/convolution.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/dfi_fftshift.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/flatfield.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/fourier_wavelets.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/halftomo.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/helical_padding.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/hierarchical_backproj.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/histogram.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/interpolation.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/medfilt.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/normalization.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/padding.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/proj.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/rotation.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/src/transpose.cu +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/cuda/utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/alignment.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/cor.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/cor_sino.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/distortion.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/focus.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/motion.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/tests/test_alignment.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/tests/test_cor.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/tests/test_focus.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/tests/test_motion_estimation.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/tests/test_tilt.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/tests/test_translation.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/tilt.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/translation.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/estimation/utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/io/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/io/cast_volume.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/io/detector_distortion.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/io/reader_helical.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/io/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/io/tests/test_cast_volume.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/io/tests/test_remove_volume.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/io/tests/test_writers.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/io/utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/io/writer.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/binning.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/fftshift.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/filters.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/fourier_filters.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/histogram.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/histogram_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/kernel_base.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/padding.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/padding_base.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/processing_base.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/rotation.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/rotation_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/tests/test_binning.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/tests/test_interpolation.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/transpose.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/unsharp.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/unsharp_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/unsharp_opencl.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/misc/utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/fft.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/kernel.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/memcpy.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/padding.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/processing.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/src/ElementOp.cl +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/src/backproj.cl +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/src/fftshift.cl +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/src/halftomo.cl +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/src/padding.cl +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/src/roll.cl +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/src/transpose.cl +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/opencl/utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/config.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/config_validators.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/datadump.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/dataset_validator.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/detector_distortion_provider.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/fullfield/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/fullfield/chunked_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/fullfield/computations.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/fullfield/dataset_validator.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/fullfield/get_double_flatfield.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/fullfield/nabu_config.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/fullfield/reconstruction.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/dataset_validator.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/fbp.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/filtering.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/gridded_accumulator.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/helical_chunked_regridded.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/helical_chunked_regridded_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/helical_reconstruction.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/helical_utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/nabu_config.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/processconfig.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/span_strategy.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/helical/weight_balancer.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/params.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/processconfig.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/reader.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/tests/test_estimators.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/writer.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/pipeline/xrdct/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/alignment.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/ccd.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/ccd_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/ctf.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/ctf_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/distortion.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/double_flatfield.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/double_flatfield_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/double_flatfield_variable_region.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/flatfield_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/flatfield_variable_region.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/phase.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/phase_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/shift.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/shift_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/tests/test_ccd_corr.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/tests/test_ctf.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/tests/test_double_flatfield.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/tests/test_flatfield.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/tests/test_paganin.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/tests/test_pcaflats.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/preproc/tests/test_vshift.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/convolution_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/fft_base.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/fft_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/fft_opencl.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/fftshift.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/histogram.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/histogram_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/kernel_base.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/medfilt_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/muladd.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/muladd_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/padding_base.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/padding_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/padding_opencl.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/processing_base.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/roll_opencl.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/rotation.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/rotation_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/tests/test_fft.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/tests/test_fftshift.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/tests/test_histogram.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/tests/test_medfilt.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/tests/test_muladd.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/tests/test_padding.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/tests/test_roll.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/tests/test_rotation.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/tests/test_transpose.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/tests/test_unsharp.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/transpose.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/unsharp.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/unsharp_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/processing/unsharp_opencl.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/cone.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/fbp.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/fbp_base.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/fbp_opencl.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/filtering.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/filtering_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/filtering_opencl.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/hbp.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/projection.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/reconstructor.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/reconstructor_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/rings.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/rings_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/sinogram.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/sinogram_cuda.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/sinogram_opencl.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/tests/test_cone.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/tests/test_deringer.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/tests/test_fbp.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/tests/test_filtering.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/tests/test_halftomo.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/tests/test_mlem.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/tests/test_projector.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/tests/test_reconstructor.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/reconstruction/tests/test_sino_normalization.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/cli/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/cor.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/gpu.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/logger.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/templates/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/templates/bm05_pag.conf +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/templates/id16_ctf.conf +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/templates/id16_holo.conf +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/templates/id16a_fluo.conf +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/templates/id19_pag.conf +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/tests/test_extract.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/tests/test_nxflatfield.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/tests/test_units.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/resources/utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/alignment.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/config.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/definitions.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/frame_composition.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/overlap.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/sample_normalization.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/single_axis_stitching.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/slurm_utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher/base.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher/dumper/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher/dumper/base.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher/dumper/postprocessing.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher/dumper/preprocessing.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher/post_processing.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher/pre_processing.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher/single_axis.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher/stitcher.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher/y_stitcher.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher/z_stitcher.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/stitcher_2D.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/tests/test_alignment.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/tests/test_config.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/tests/test_frame_composition.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/tests/test_overlap.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/tests/test_sample_normalization.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/tests/test_slurm_utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/tests/test_utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/tests/test_y_preprocessing_stitching.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/tests/test_z_postprocessing_stitching.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/tests/test_z_preprocessing_stitching.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/utils/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/utils/post_processing.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/utils/tests/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/utils/tests/test_post-processing.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/utils/utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/y_stitching.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/stitching/z_stitching.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/tests.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/thirdparty/__init__.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/thirdparty/algotom_convert_sino.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/thirdparty/pore3d_deringer_munch.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/thirdparty/tomocupy_remove_stripe.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/thirdparty/tomopy_phase.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/thirdparty/tomwer_load_flats_darks.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu/utils.py +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu.egg-info/dependency_links.txt +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu.egg-info/entry_points.txt +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu.egg-info/requires.txt +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/nabu.egg-info/top_level.txt +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/pyproject.toml +0 -0
- {nabu-2025.1.0rc4 → nabu-2025.1.0rc6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: nabu
|
3
|
-
Version: 2025.1.
|
3
|
+
Version: 2025.1.0rc6
|
4
4
|
Summary: Nabu - Tomography software
|
5
5
|
Author-email: Pierre Paleo <pierre.paleo@esrf.fr>, Henri Payno <henri.payno@esrf.fr>, Alessandro Mirone <mirone@esrf.fr>, Jérôme Lesaint <jerome.lesaint@esrf.fr>
|
6
6
|
Maintainer-email: Pierre Paleo <pierre.paleo@esrf.fr>
|
@@ -353,6 +353,11 @@ EstimateMotionConfig = {
|
|
353
353
|
"default": 2,
|
354
354
|
"type": int,
|
355
355
|
},
|
356
|
+
"win_size": {
|
357
|
+
"help": "Size of the look-up window for half-tomography",
|
358
|
+
"default": 300,
|
359
|
+
"type": int,
|
360
|
+
},
|
356
361
|
"verbose": {
|
357
362
|
"help": "Whether to plot the movement estimation fit",
|
358
363
|
"default": 1,
|
@@ -365,6 +370,16 @@ EstimateMotionConfig = {
|
|
365
370
|
"help": "Whether to only generate motion file for horizontal or vertical movement: --only horizontal or --only vertical",
|
366
371
|
"default": "",
|
367
372
|
},
|
373
|
+
"ccd_filter_size": {
|
374
|
+
"help": "Size of conditional median filter to apply on radios. Default is zero (disabled)",
|
375
|
+
"default": 0,
|
376
|
+
"type": int,
|
377
|
+
},
|
378
|
+
"ccd_filter_threshold": {
|
379
|
+
"help": "Threshold for median filter, 'ccd_filter_size' is not zero. Default is 0.04",
|
380
|
+
"default": 0.04,
|
381
|
+
"type": float,
|
382
|
+
},
|
368
383
|
}
|
369
384
|
|
370
385
|
# Default configuration for "stitching" command
|
@@ -1,8 +1,11 @@
|
|
1
1
|
from os import path
|
2
|
+
from multiprocessing.pool import ThreadPool
|
2
3
|
|
4
|
+
from ..utils import get_num_threads
|
3
5
|
from ..resources.nxflatfield import update_dataset_info_flats_darks
|
4
6
|
from ..resources.logger import LoggerOrPrint
|
5
7
|
from ..resources.dataset_analyzer import analyze_dataset
|
8
|
+
from ..preproc.ccd import CCDFilter
|
6
9
|
from ..pipeline.config_validators import convert_to_bool
|
7
10
|
from ..pipeline.estimators import TranslationsEstimator
|
8
11
|
from .utils import parse_params_values
|
@@ -26,6 +29,22 @@ def estimate_motion():
|
|
26
29
|
if do_ff:
|
27
30
|
update_dataset_info_flats_darks(dataset_info, True, loading_mode="load_if_present")
|
28
31
|
|
32
|
+
radios_filter = None
|
33
|
+
do_ccd_filter = args["ccd_filter_size"] > 0
|
34
|
+
if do_ccd_filter:
|
35
|
+
radios_filter_obj = CCDFilter(
|
36
|
+
dataset_info.radio_dims[::-1],
|
37
|
+
kernel_size=args["ccd_filter_size"],
|
38
|
+
median_clip_thresh=args["ccd_filter_threshold"],
|
39
|
+
)
|
40
|
+
|
41
|
+
def radios_filter(images):
|
42
|
+
def _apply_median_clip(img):
|
43
|
+
radios_filter_obj.median_clip_correction(img, output=img)
|
44
|
+
|
45
|
+
with ThreadPool(get_num_threads()) as tp:
|
46
|
+
tp.map(_apply_median_clip, images)
|
47
|
+
|
29
48
|
est = TranslationsEstimator(
|
30
49
|
dataset_info,
|
31
50
|
do_flatfield=do_ff,
|
@@ -34,6 +53,8 @@ def estimate_motion():
|
|
34
53
|
deg_xy=args["deg_xy"],
|
35
54
|
deg_z=args["deg_z"],
|
36
55
|
shifts_estimator="phase_cross_correlation",
|
56
|
+
radios_filter=radios_filter,
|
57
|
+
extra_options={"window_size": args["win_size"]},
|
37
58
|
)
|
38
59
|
|
39
60
|
estimated_shifts_h, estimated_shifts_v, cor = est.estimate_motion()
|
@@ -556,7 +556,11 @@ class VolReaderBase:
|
|
556
556
|
slice_x = None
|
557
557
|
if isinstance(sub_region, (tuple, list)):
|
558
558
|
slice_angle, slice_z, slice_x = sub_region
|
559
|
-
self.sub_region = (
|
559
|
+
self.sub_region = (
|
560
|
+
slice_angle if slice_angle is not None else slice(None, None),
|
561
|
+
slice_z if slice_z is not None else slice(None, None),
|
562
|
+
slice_x if slice_x is not None else slice(None, None),
|
563
|
+
)
|
560
564
|
|
561
565
|
def _set_processing_function(self, processing_func, processing_func_args, processing_func_kwargs):
|
562
566
|
self.processing_func = processing_func
|
@@ -682,9 +686,13 @@ class NXTomoReader(VolReaderBase):
|
|
682
686
|
# In this case, we can use h5py read_direct() to avoid extraneous memory consumption
|
683
687
|
image_key_slice = self._image_key_slices[0]
|
684
688
|
# merge image key selection and user selection (if any)
|
685
|
-
|
686
|
-
|
687
|
-
|
689
|
+
angles_slice = self.sub_region[0]
|
690
|
+
if isinstance(angles_slice, slice) or angles_slice is None:
|
691
|
+
angles_slice = merge_slices(image_key_slice, self.sub_region[0] or slice(None, None))
|
692
|
+
else: # assuming numpy array
|
693
|
+
# TODO more elegant
|
694
|
+
angles_slice = np.arange(self.data_shape_total[0], dtype=np.uint64)[image_key_slice][angles_slice]
|
695
|
+
self._source_selection = (angles_slice,) + self.sub_region[1:]
|
688
696
|
else:
|
689
697
|
user_selection_dim0 = self.sub_region[0]
|
690
698
|
indices = np.arange(self.data_shape_total[0])
|
@@ -1,41 +1,23 @@
|
|
1
1
|
from math import ceil
|
2
2
|
from tempfile import TemporaryDirectory
|
3
|
-
from dataclasses import dataclass
|
4
3
|
from tomoscan.io import HDF5File
|
5
4
|
import pytest
|
6
5
|
import numpy as np
|
7
6
|
from nxtomo.application.nxtomo import ImageKey
|
8
7
|
from tomoscan.esrf import EDFVolume
|
9
8
|
from nabu.pipeline.reader import NXTomoReaderBinning
|
10
|
-
from nabu.testutils import utilstest, __do_long_tests__, get_file
|
9
|
+
from nabu.testutils import utilstest, __do_long_tests__, get_file, get_dummy_nxtomo_info
|
11
10
|
from nabu.utils import indices_to_slices, merge_slices
|
12
11
|
from nabu.io.reader import EDFStackReader, NXTomoReader, NXDarksFlats
|
13
|
-
|
14
|
-
|
15
|
-
@dataclass
|
16
|
-
class SimpleNXTomoDescription:
|
17
|
-
n_darks: int = 0
|
18
|
-
n_flats1: int = 0
|
19
|
-
n_projs: int = 0
|
20
|
-
n_flats2: int = 0
|
21
|
-
n_align: int = 0
|
22
|
-
frame_shape: tuple = None
|
23
|
-
dtype: np.dtype = np.uint16
|
12
|
+
from nabu.resources.dataset_analyzer import analyze_dataset
|
24
13
|
|
25
14
|
|
26
15
|
@pytest.fixture(scope="class")
|
27
16
|
def bootstrap_nx_reader(request):
|
28
17
|
cls = request.cls
|
29
|
-
|
30
|
-
|
31
|
-
cls.nx_data_path = "entry/instrument/detector/data"
|
32
|
-
cls.data_desc = SimpleNXTomoDescription(
|
33
|
-
n_darks=10, n_flats1=11, n_projs=100, n_flats2=11, n_align=12, frame_shape=(11, 10), dtype=np.uint16
|
18
|
+
cls.nx_fname, cls.data_desc, cls.image_key, cls.projs_vals, cls.darks_vals, cls.flats1_vals, cls.flats2_vals = (
|
19
|
+
get_dummy_nxtomo_info()
|
34
20
|
)
|
35
|
-
cls.projs_vals = np.arange(cls.data_desc.n_projs) + cls.data_desc.n_flats1 + cls.data_desc.n_darks
|
36
|
-
cls.darks_vals = np.arange(cls.data_desc.n_darks)
|
37
|
-
cls.flats1_vals = np.arange(cls.data_desc.n_darks, cls.data_desc.n_darks + cls.data_desc.n_flats1)
|
38
|
-
cls.flats2_vals = np.arange(cls.data_desc.n_darks, cls.data_desc.n_darks + cls.data_desc.n_flats2)
|
39
21
|
|
40
22
|
yield
|
41
23
|
# teardown
|
@@ -45,7 +27,7 @@ def bootstrap_nx_reader(request):
|
|
45
27
|
class TestNXReader:
|
46
28
|
def test_incorrect_path(self):
|
47
29
|
with pytest.raises(FileNotFoundError):
|
48
|
-
reader = NXTomoReader("/invalid/path"
|
30
|
+
reader = NXTomoReader("/invalid/path")
|
49
31
|
with pytest.raises(KeyError):
|
50
32
|
reader = NXTomoReader(self.nx_fname, "/bad/data/path") # noqa: F841
|
51
33
|
|
@@ -53,7 +35,7 @@ class TestNXReader:
|
|
53
35
|
"""
|
54
36
|
Test NXTomoReader with simplest settings
|
55
37
|
"""
|
56
|
-
reader1 = NXTomoReader(self.nx_fname
|
38
|
+
reader1 = NXTomoReader(self.nx_fname)
|
57
39
|
data1 = reader1.load_data()
|
58
40
|
assert data1.shape == (self.data_desc.n_projs,) + self.data_desc.frame_shape
|
59
41
|
assert np.allclose(data1[:, 0, 0], self.projs_vals)
|
@@ -62,15 +44,15 @@ class TestNXReader:
|
|
62
44
|
"""
|
63
45
|
Test the data selection using "image_key".
|
64
46
|
"""
|
65
|
-
reader_projs = NXTomoReader(self.nx_fname,
|
47
|
+
reader_projs = NXTomoReader(self.nx_fname, image_key=ImageKey.PROJECTION.value)
|
66
48
|
data = reader_projs.load_data()
|
67
49
|
assert np.allclose(data[:, 0, 0], self.projs_vals)
|
68
50
|
|
69
|
-
reader_darks = NXTomoReader(self.nx_fname,
|
51
|
+
reader_darks = NXTomoReader(self.nx_fname, image_key=ImageKey.DARK_FIELD.value)
|
70
52
|
data_darks = reader_darks.load_data()
|
71
53
|
assert np.allclose(data_darks[:, 0, 0], self.darks_vals)
|
72
54
|
|
73
|
-
reader_flats = NXTomoReader(self.nx_fname,
|
55
|
+
reader_flats = NXTomoReader(self.nx_fname, image_key=ImageKey.FLAT_FIELD.value)
|
74
56
|
data_flats = reader_flats.load_data()
|
75
57
|
assert np.allclose(data_flats[:, 0, 0], np.concatenate([self.flats1_vals, self.flats2_vals]))
|
76
58
|
|
@@ -83,10 +65,10 @@ class TestNXReader:
|
|
83
65
|
def _check_correct_shape_succeeds(shape, sub_region, test_description=""):
|
84
66
|
err_msg = "Something wrong with the following test:" + test_description
|
85
67
|
data_buffer = np.zeros(shape, dtype="f")
|
86
|
-
reader1 = NXTomoReader(self.nx_fname,
|
68
|
+
reader1 = NXTomoReader(self.nx_fname, sub_region=sub_region)
|
87
69
|
data1 = reader1.load_data(output=data_buffer)
|
88
70
|
assert id(data1) == id(data_buffer), err_msg
|
89
|
-
reader2 = NXTomoReader(self.nx_fname,
|
71
|
+
reader2 = NXTomoReader(self.nx_fname, sub_region=sub_region)
|
90
72
|
data2 = reader2.load_data()
|
91
73
|
assert np.allclose(data1, data2), err_msg
|
92
74
|
|
@@ -124,7 +106,6 @@ class TestNXReader:
|
|
124
106
|
data_buffer_wrong_shape = np.zeros(wrong_shape, dtype="f")
|
125
107
|
reader = NXTomoReader(
|
126
108
|
self.nx_fname,
|
127
|
-
self.nx_data_path,
|
128
109
|
sub_region=test_case["sub_region"],
|
129
110
|
)
|
130
111
|
reader.load_data(output=data_buffer_wrong_shape)
|
@@ -148,7 +129,7 @@ class TestNXReader:
|
|
148
129
|
]
|
149
130
|
|
150
131
|
for test_case in test_cases:
|
151
|
-
reader = NXTomoReader(self.nx_fname,
|
132
|
+
reader = NXTomoReader(self.nx_fname, sub_region=test_case["sub_region"])
|
152
133
|
data = reader.load_data()
|
153
134
|
assert data.shape == test_case["expected_shape"]
|
154
135
|
assert np.allclose(data[:, 0, 0], test_case["expected_values"])
|
@@ -156,7 +137,7 @@ class TestNXReader:
|
|
156
137
|
def test_reading_with_binning_(self):
|
157
138
|
from nabu.pipeline.reader import NXTomoReaderBinning
|
158
139
|
|
159
|
-
reader_with_binning = NXTomoReaderBinning((2, 2), self.nx_fname
|
140
|
+
reader_with_binning = NXTomoReaderBinning((2, 2), self.nx_fname)
|
160
141
|
data = reader_with_binning.load_data()
|
161
142
|
assert data.shape == (self.data_desc.n_projs,) + tuple(n // 2 for n in self.data_desc.frame_shape)
|
162
143
|
|
@@ -177,7 +158,6 @@ class TestNXReader:
|
|
177
158
|
reader_distortion_corr = NXTomoReaderDistortionCorrection(
|
178
159
|
distortion_corrector,
|
179
160
|
self.nx_fname,
|
180
|
-
self.nx_data_path,
|
181
161
|
sub_region=sub_region,
|
182
162
|
)
|
183
163
|
|
@@ -220,7 +200,7 @@ class TestNXReader:
|
|
220
200
|
for test_case in test_cases:
|
221
201
|
binning = test_case.get("binning", None)
|
222
202
|
reader_cls = NXTomoReader
|
223
|
-
init_args = [self.nx_fname
|
203
|
+
init_args = [self.nx_fname]
|
224
204
|
init_kwargs = {"sub_region": test_case["sub_region"]}
|
225
205
|
if binning is not None:
|
226
206
|
reader_cls = NXTomoReaderBinning
|
@@ -231,6 +211,29 @@ class TestNXReader:
|
|
231
211
|
assert data.shape == test_case["expected_shape"], err_msg
|
232
212
|
assert np.allclose(data[:, 0, 0], test_case["expected_values"]), err_msg
|
233
213
|
|
214
|
+
def test_load_exclude_projections(self):
|
215
|
+
n_z, n_x = self.data_desc.frame_shape
|
216
|
+
# projs_idx = np.where(self.image_key == 0)[0]
|
217
|
+
projs_idx = np.arange(self.data_desc.n_projs, dtype=np.int64)
|
218
|
+
excluded_projs_idx_1 = projs_idx[10:20]
|
219
|
+
excluded_projs_idx_2 = np.concatenate([projs_idx[10:14], projs_idx[50:57]])
|
220
|
+
|
221
|
+
set_to_nparray = lambda x: np.array(sorted(list(x)))
|
222
|
+
|
223
|
+
projs_idx1 = set_to_nparray(set(projs_idx) - set(excluded_projs_idx_1))
|
224
|
+
projs_idx2 = set_to_nparray(set(projs_idx) - set(excluded_projs_idx_2))
|
225
|
+
|
226
|
+
sub_regions_to_test = (
|
227
|
+
(projs_idx1, None, None),
|
228
|
+
(projs_idx1, slice(0, n_z // 2), None),
|
229
|
+
(projs_idx2, None, None),
|
230
|
+
(projs_idx2, slice(3, n_z // 2), None),
|
231
|
+
)
|
232
|
+
for sub_region in sub_regions_to_test:
|
233
|
+
reader = NXTomoReader(self.nx_fname, sub_region=sub_region)
|
234
|
+
data = reader.load_data()
|
235
|
+
assert np.allclose(data[:, 0, 0], self.projs_vals[sub_region[0]])
|
236
|
+
|
234
237
|
|
235
238
|
@pytest.fixture(scope="class")
|
236
239
|
def bootstrap_edf_reader(request):
|
@@ -1000,7 +1000,7 @@ def estimate_translations(dataset_info, do_flatfield=True): ...
|
|
1000
1000
|
class TranslationsEstimator:
|
1001
1001
|
|
1002
1002
|
_default_extra_options = {
|
1003
|
-
"window_size":
|
1003
|
+
"window_size": 300,
|
1004
1004
|
}
|
1005
1005
|
|
1006
1006
|
def __init__(
|
@@ -1013,6 +1013,7 @@ class TranslationsEstimator:
|
|
1013
1013
|
deg_xy=2,
|
1014
1014
|
deg_z=2,
|
1015
1015
|
shifts_estimator="phase_cross_correlation",
|
1016
|
+
radios_filter=None,
|
1016
1017
|
extra_options=None,
|
1017
1018
|
):
|
1018
1019
|
self._configure_extra_options(extra_options)
|
@@ -1021,6 +1022,7 @@ class TranslationsEstimator:
|
|
1021
1022
|
self.angular_subsampling = angular_subsampling
|
1022
1023
|
self.do_360 = self.dataset_info.is_360
|
1023
1024
|
self.do_flatfield = do_flatfield
|
1025
|
+
self.radios_filter = radios_filter
|
1024
1026
|
self.radios = None
|
1025
1027
|
self._deg_xy = deg_xy
|
1026
1028
|
self._deg_z = deg_z
|
@@ -1163,6 +1165,9 @@ class TranslationsEstimator:
|
|
1163
1165
|
def estimate_motion(self):
|
1164
1166
|
self._load_data()
|
1165
1167
|
self._apply_flatfield()
|
1168
|
+
if self.radios_filter is not None:
|
1169
|
+
self.logger.debug("[MotionEstimation] applying radios filter")
|
1170
|
+
self.radios_filter(self.radios)
|
1166
1171
|
|
1167
1172
|
n_projs_tot = self.dataset_info.n_angles
|
1168
1173
|
if self.do_360:
|
@@ -1210,7 +1215,7 @@ class TranslationsEstimator:
|
|
1210
1215
|
self.sample_shifts_z = estimated_shifts_v
|
1211
1216
|
if self._cor is None:
|
1212
1217
|
self.logger.info(
|
1213
|
-
"[MotionEstimation] Estimated center of rotation (relative to
|
1218
|
+
"[MotionEstimation] Estimated center of rotation (relative to left-most pixel): %.2f" % cor
|
1214
1219
|
)
|
1215
1220
|
return estimated_shifts_h, estimated_shifts_v, cor
|
1216
1221
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from os import path
|
2
2
|
from time import time
|
3
|
-
from math import ceil
|
4
3
|
import numpy as np
|
5
4
|
from silx.io.url import DataUrl
|
6
5
|
|
@@ -127,10 +126,10 @@ class ChunkedPipeline:
|
|
127
126
|
if len(chunk_shape) != 3:
|
128
127
|
raise ValueError("Expected chunk_shape to be a tuple of length 3 in the form (n_z, n_y, n_x)")
|
129
128
|
self.chunk_shape = tuple(int(c) for c in chunk_shape) # cast to int, as numpy.int64 can make pycuda crash
|
130
|
-
|
129
|
+
ss_start = getattr(self.process_config, "subsampling_start", 0)
|
131
130
|
# (n_a, n_z, n_x)
|
132
131
|
self.radios_shape = (
|
133
|
-
|
132
|
+
np.arange(self.chunk_shape[0])[ss_start :: self.process_config.subsampling_factor].size,
|
134
133
|
self.chunk_shape[1] // self.process_config.binning[1],
|
135
134
|
self.chunk_shape[2] // self.process_config.binning[0],
|
136
135
|
)
|
@@ -340,13 +339,28 @@ class ChunkedPipeline:
|
|
340
339
|
subs_z = None
|
341
340
|
subs_x = None
|
342
341
|
angular_sub_region = slice(*(self.sub_region[0]))
|
342
|
+
|
343
|
+
# exclude(subsample(.)) != subsample(exclude(.))
|
344
|
+
# Here we want the latter: first exclude the user-defined angular range, and then subsample the remaining indices
|
345
|
+
if len(self.dataset_info.get_excluded_projections_indices()) > 0:
|
346
|
+
angular_sub_region = np.array(
|
347
|
+
[
|
348
|
+
self.dataset_info.index_to_proj_number(i)
|
349
|
+
for i in sorted(list(self.dataset_info.projections.keys()))
|
350
|
+
]
|
351
|
+
)
|
343
352
|
if self.process_config.subsampling_factor:
|
344
353
|
subs_angles = self.process_config.subsampling_factor
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
354
|
+
start = getattr(self.process_config, "subsampling_start", 0) + self.sub_region[0][0]
|
355
|
+
if isinstance(angular_sub_region, slice):
|
356
|
+
angular_sub_region = slice(
|
357
|
+
start,
|
358
|
+
self.sub_region[0][1],
|
359
|
+
subs_angles,
|
360
|
+
)
|
361
|
+
else:
|
362
|
+
angular_sub_region = angular_sub_region[start::subs_angles]
|
363
|
+
|
350
364
|
reader_sub_region = (
|
351
365
|
angular_sub_region,
|
352
366
|
slice(*(self.sub_region[1]) + ((subs_z,) if subs_z else ())),
|
@@ -363,7 +377,7 @@ class ChunkedPipeline:
|
|
363
377
|
if self.dataset_info.kind == "nx":
|
364
378
|
self.chunk_reader = NXTomoReader(
|
365
379
|
self.dataset_info.dataset_hdf5_url.file_path(),
|
366
|
-
self.dataset_info.dataset_hdf5_url.data_path(),
|
380
|
+
data_path=self.dataset_info.dataset_hdf5_url.data_path(),
|
367
381
|
sub_region=reader_sub_region,
|
368
382
|
image_key=0,
|
369
383
|
**other_reader_kwargs,
|
@@ -12,6 +12,7 @@ from ...resources.nxflatfield import update_dataset_info_flats_darks
|
|
12
12
|
from ...resources.utils import get_quantities_and_units
|
13
13
|
from ..estimators import estimate_cor
|
14
14
|
from ..processconfig import ProcessConfigBase
|
15
|
+
from ..config_validators import convert_to_bool
|
15
16
|
from .nabu_config import nabu_config, renamed_keys
|
16
17
|
from .dataset_validator import FullFieldDatasetValidator
|
17
18
|
from nxtomo.nxobject.nxdetector import ImageKey
|
@@ -475,7 +476,7 @@ class ProcessConfig(ProcessConfigBase):
|
|
475
476
|
# Double flat field
|
476
477
|
#
|
477
478
|
# ---- COMPAT ----
|
478
|
-
if nabu_config["preproc"].get("double_flatfield_enabled", False):
|
479
|
+
if convert_to_bool(nabu_config["preproc"].get("double_flatfield_enabled", False))[0]:
|
479
480
|
deprecation_warning(
|
480
481
|
"'double_flatfield_enabled' has been renamed to 'double_flatfield'. Please update your configuration file"
|
481
482
|
)
|
@@ -456,10 +456,10 @@ class FlatFieldDataUrls(FlatField):
|
|
456
456
|
|
457
457
|
|
458
458
|
class PCAFlatsNormalizer:
|
459
|
-
"""This class implement a flatfield normalization based on a PCA of a series of
|
459
|
+
"""This class implement a flatfield normalization based on a PCA of a series of acquired flatfields.
|
460
460
|
The PCA decomposition is handled by a PCAFlatsDecomposer object.
|
461
461
|
|
462
|
-
This implementation was proposed by Jailin C. et al in https://
|
462
|
+
This implementation was proposed by Jailin C. et al in https://journals.iucr.org/s/issues/2017/01/00/fv5055/
|
463
463
|
|
464
464
|
Code initially written by ID11 @ ESRF staff.
|
465
465
|
Jonathan Wright - Implementation based on research paper
|
@@ -619,7 +619,7 @@ class PCAFlatsDecomposer:
|
|
619
619
|
"""This class implements a PCA decomposition of a serie of acquired flatfields.
|
620
620
|
The PCA decomposition is used to normalize the projections through a PCAFLatNormalizer object.
|
621
621
|
|
622
|
-
This implementation was proposed by Jailin C. et al in https://
|
622
|
+
This implementation was proposed by Jailin C. et al in https://journals.iucr.org/s/issues/2017/01/00/fv5055/
|
623
623
|
|
624
624
|
Code initially written by ID11 @ ESRF staff.
|
625
625
|
Jonathan Wright - Implementation based on research paper
|
@@ -96,8 +96,11 @@ def do_radial_distribution(ip, X0, Y0, mR, nBins=None, use_calibration=False, ca
|
|
96
96
|
Accumulator = np.zeros((2, nBins))
|
97
97
|
|
98
98
|
# Define the bounding box
|
99
|
-
|
100
|
-
|
99
|
+
height, width = ip.shape
|
100
|
+
xmin = max(int(X0 - mR), 0)
|
101
|
+
xmax = min(int(X0 + mR), width)
|
102
|
+
ymin = max(int(Y0 - mR), 0)
|
103
|
+
ymax = min(int(Y0 + mR), height)
|
101
104
|
|
102
105
|
# Create grid of coordinates
|
103
106
|
x = np.arange(xmin, xmax)
|
@@ -112,10 +115,11 @@ def do_radial_distribution(ip, X0, Y0, mR, nBins=None, use_calibration=False, ca
|
|
112
115
|
bins = np.clip(bins - 1, 0, nBins - 1) # Adjust bins to be in range [0, nBins-1]
|
113
116
|
|
114
117
|
# Accumulate values
|
118
|
+
sub_image = ip[xmin:xmax, ymin:ymax] # prevent issue on non-square images
|
115
119
|
for b in range(nBins):
|
116
120
|
mask = bins == b
|
117
121
|
Accumulator[0, b] = np.sum(mask)
|
118
|
-
Accumulator[1, b] = np.sum(
|
122
|
+
Accumulator[1, b] = np.sum(sub_image[mask])
|
119
123
|
|
120
124
|
# Normalize integrated intensity
|
121
125
|
Accumulator[1] /= Accumulator[0]
|
@@ -104,7 +104,7 @@ class MLEMReconstructor:
|
|
104
104
|
def reset_rot_center(self, cor):
|
105
105
|
self.cor = -cor + (self.sinos_shape[-1] - 1) / 2.0
|
106
106
|
|
107
|
-
def reconstruct(self, data_vwu):
|
107
|
+
def reconstruct(self, data_vwu, x0=None):
|
108
108
|
"""
|
109
109
|
data_align_vwu: numpy.ndarray or pycuda.gpuarray
|
110
110
|
Raw data, with shape (n_sinograms, n_angles, width)
|
@@ -134,5 +134,5 @@ class MLEMReconstructor:
|
|
134
134
|
with cct.projectors.ProjectorUncorrected(
|
135
135
|
self.vol_geom_align, self.angles_rad, rot_axis_shift_pix=self.cor, prj_geom=self.prj_geom_align
|
136
136
|
) as A:
|
137
|
-
rec, _ = solver(A, data_vwu, iterations=self.n_iterations, **self.solver_opts)
|
137
|
+
rec, _ = solver(A, data_vwu, iterations=self.n_iterations, x0=x0, **self.solver_opts)
|
138
138
|
return rec * self.scale_factor
|
@@ -396,6 +396,11 @@ class EDFDatasetAnalyzer(DatasetAnalyzer):
|
|
396
396
|
def scan_dirname(self):
|
397
397
|
return self.dataset_scanner.path
|
398
398
|
|
399
|
+
def get_excluded_projections_indices(self, including_other_frames_types=True):
|
400
|
+
if not (including_other_frames_types):
|
401
|
+
raise NotImplementedError
|
402
|
+
return self.dataset_scanner.get_ignored_projection_indices()
|
403
|
+
|
399
404
|
|
400
405
|
class HDF5DatasetAnalyzer(DatasetAnalyzer):
|
401
406
|
"""
|
@@ -606,6 +611,36 @@ class HDF5DatasetAnalyzer(DatasetAnalyzer):
|
|
606
611
|
def get_frame(self, idx):
|
607
612
|
return get_data(self.dataset_scanner.frames[idx].url)
|
608
613
|
|
614
|
+
def get_frames_indices(self, frame_type):
|
615
|
+
return self._select_according_to_frame_type(np.arange(self.dataset_scanner.image_key_control.size), frame_type)
|
616
|
+
|
617
|
+
def index_to_proj_number(self, proj_index):
|
618
|
+
"""
|
619
|
+
Return the projection *number*, from its frame *index*.
|
620
|
+
|
621
|
+
For example if there are 11 flats before projections,
|
622
|
+
then projections will have indices [11, 12, .....] (possibly not contiguous)
|
623
|
+
while their number is [0, 1, ..., ] (contiguous, starts from 0)
|
624
|
+
"""
|
625
|
+
all_projs_indices = self.get_frames_indices("projection")
|
626
|
+
return search_sorted(all_projs_indices, proj_index)
|
627
|
+
|
628
|
+
def get_excluded_projections_indices(self, including_other_frames_types=True):
|
629
|
+
# Get indices of ALL projections (even excluded ones)
|
630
|
+
# the index accounts for flats/darks !
|
631
|
+
# Get indices of excluded projs (again, accounting for flats/darks)
|
632
|
+
ignored_projs_indices = self.dataset_scanner.get_ignored_projection_indices()
|
633
|
+
ignored_projs_indices = [
|
634
|
+
idx for idx in ignored_projs_indices if self.dataset_scanner.frames[idx].is_control is False
|
635
|
+
]
|
636
|
+
if including_other_frames_types:
|
637
|
+
return ignored_projs_indices
|
638
|
+
# Get indices of excluded projs, now relative to the pure projections stack
|
639
|
+
ignored_projs_indices_rel = [
|
640
|
+
self.index_to_proj_number(ignored_proj_idx_abs) for ignored_proj_idx_abs in ignored_projs_indices
|
641
|
+
]
|
642
|
+
return ignored_projs_indices_rel
|
643
|
+
|
609
644
|
|
610
645
|
def get_angle_at_index(all_angles, index):
|
611
646
|
"""
|
@@ -71,7 +71,7 @@ def save_reduced_frames(dataset_info, reduced_frames_arrays, reduced_frames_urls
|
|
71
71
|
darks_flats_dir_url = reduced_frames_urls.get("user", None)
|
72
72
|
if darks_flats_dir_url is not None:
|
73
73
|
output_url = darks_flats_dir_url
|
74
|
-
elif is_writeable(os.path.dirname(reduced_frames_urls["dataset"]["flats"].file_path())):
|
74
|
+
elif is_writeable(os.path.abspath(os.path.dirname(reduced_frames_urls["dataset"]["flats"].file_path()))):
|
75
75
|
output_url = reduced_frames_urls["dataset"]
|
76
76
|
else:
|
77
77
|
output_url = reduced_frames_urls["output"]
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import pytest
|
2
|
+
import numpy as np
|
3
|
+
from nabu.testutils import get_dummy_nxtomo_info
|
4
|
+
from nabu.resources.dataset_analyzer import analyze_dataset
|
5
|
+
|
6
|
+
|
7
|
+
@pytest.fixture(scope="class")
|
8
|
+
def bootstrap_nx(request):
|
9
|
+
cls = request.cls
|
10
|
+
cls.nx_fname, cls.data_desc, cls.image_key, cls.projs_vals, cls.darks_vals, cls.flats1_vals, cls.flats2_vals = (
|
11
|
+
get_dummy_nxtomo_info()
|
12
|
+
)
|
13
|
+
|
14
|
+
|
15
|
+
@pytest.mark.usefixtures("bootstrap_nx")
|
16
|
+
class TestNXDataset:
|
17
|
+
|
18
|
+
def test_exclude_projs_angular_range(self):
|
19
|
+
dataset_info_with_all_projs = analyze_dataset(self.nx_fname)
|
20
|
+
|
21
|
+
# Test exclude angular range - angles min and max in degrees
|
22
|
+
angular_ranges_to_test = [(0, 15), (5, 6), (50, 58.5)]
|
23
|
+
for angular_range in angular_ranges_to_test:
|
24
|
+
angle_min, angle_max = angular_range
|
25
|
+
dataset_info = analyze_dataset(
|
26
|
+
self.nx_fname,
|
27
|
+
extra_options={"exclude_projections": {"type": "angular_range", "range": [angle_min, angle_max]}},
|
28
|
+
)
|
29
|
+
excluded_projs_indices = dataset_info.get_excluded_projections_indices()
|
30
|
+
# Check that get_excluded_projections_indices() angles are correct
|
31
|
+
for excluded_proj_index in excluded_projs_indices:
|
32
|
+
frame_angle_deg = dataset_info.dataset_scanner.frames[excluded_proj_index].rotation_angle
|
33
|
+
assert angle_min <= frame_angle_deg and frame_angle_deg <= angle_max
|
34
|
+
|
35
|
+
assert set(dataset_info_with_all_projs.projections.keys()) - set(dataset_info.projections.keys()) == set(
|
36
|
+
excluded_projs_indices
|
37
|
+
)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
from dataclasses import dataclass
|
1
2
|
from itertools import product
|
2
3
|
import tarfile
|
3
4
|
import os
|
@@ -5,6 +6,7 @@ import numpy as np
|
|
5
6
|
from scipy.signal.windows import gaussian
|
6
7
|
from silx.resources import ExternalResources
|
7
8
|
from silx.io.dictdump import nxtodict, dicttonx
|
9
|
+
from nxtomo.application.nxtomo import ImageKey
|
8
10
|
|
9
11
|
utilstest = ExternalResources(
|
10
12
|
project="nabu", url_base="http://www.silx.org/pub/nabu/data/", env_key="NABU_DATA", timeout=60
|
@@ -56,6 +58,38 @@ def get_data(*dataset_path):
|
|
56
58
|
return np.load(dataset_downloaded_path)
|
57
59
|
|
58
60
|
|
61
|
+
@dataclass
|
62
|
+
class SimpleNXTomoDescription:
|
63
|
+
n_darks: int = 0
|
64
|
+
n_flats1: int = 0
|
65
|
+
n_projs: int = 0
|
66
|
+
n_flats2: int = 0
|
67
|
+
n_align: int = 0
|
68
|
+
frame_shape: tuple = None
|
69
|
+
dtype: np.dtype = np.uint16
|
70
|
+
|
71
|
+
|
72
|
+
def get_dummy_nxtomo_info():
|
73
|
+
nx_fname = utilstest.getfile("dummy_nxtomo.nx")
|
74
|
+
data_desc = SimpleNXTomoDescription(
|
75
|
+
n_darks=10, n_flats1=11, n_projs=100, n_flats2=11, n_align=12, frame_shape=(11, 10), dtype=np.uint16
|
76
|
+
)
|
77
|
+
image_key = np.concatenate(
|
78
|
+
[
|
79
|
+
np.zeros(data_desc.n_darks, dtype=np.int32) + ImageKey.DARK_FIELD.value,
|
80
|
+
np.zeros(data_desc.n_flats1, dtype=np.int32) + ImageKey.FLAT_FIELD.value,
|
81
|
+
np.zeros(data_desc.n_projs, dtype=np.int32) + ImageKey.PROJECTION.value,
|
82
|
+
np.zeros(data_desc.n_flats2, dtype=np.int32) + ImageKey.FLAT_FIELD.value,
|
83
|
+
np.zeros(data_desc.n_align, dtype=np.int32) + ImageKey.ALIGNMENT.value,
|
84
|
+
]
|
85
|
+
)
|
86
|
+
projs_vals = np.arange(data_desc.n_projs) + data_desc.n_flats1 + data_desc.n_darks
|
87
|
+
darks_vals = np.arange(data_desc.n_darks)
|
88
|
+
flats1_vals = np.arange(data_desc.n_darks, data_desc.n_darks + data_desc.n_flats1)
|
89
|
+
flats2_vals = np.arange(data_desc.n_darks, data_desc.n_darks + data_desc.n_flats2)
|
90
|
+
return nx_fname, data_desc, image_key, projs_vals, darks_vals, flats1_vals, flats2_vals
|
91
|
+
|
92
|
+
|
59
93
|
def get_array_of_given_shape(img, shape, dtype):
|
60
94
|
"""
|
61
95
|
From a given image, returns an array of the wanted shape and dtype.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: nabu
|
3
|
-
Version: 2025.1.
|
3
|
+
Version: 2025.1.0rc6
|
4
4
|
Summary: Nabu - Tomography software
|
5
5
|
Author-email: Pierre Paleo <pierre.paleo@esrf.fr>, Henri Payno <henri.payno@esrf.fr>, Alessandro Mirone <mirone@esrf.fr>, Jérôme Lesaint <jerome.lesaint@esrf.fr>
|
6
6
|
Maintainer-email: Pierre Paleo <pierre.paleo@esrf.fr>
|
@@ -278,6 +278,7 @@ nabu/resources/templates/id16_holo.conf
|
|
278
278
|
nabu/resources/templates/id16a_fluo.conf
|
279
279
|
nabu/resources/templates/id19_pag.conf
|
280
280
|
nabu/resources/tests/__init__.py
|
281
|
+
nabu/resources/tests/test_dataset_analyzer.py
|
281
282
|
nabu/resources/tests/test_extract.py
|
282
283
|
nabu/resources/tests/test_nxflatfield.py
|
283
284
|
nabu/resources/tests/test_units.py
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|