NeuNorm 2.2.1__tar.gz → 2.2.2__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.
- {neunorm-2.2.1 → neunorm-2.2.2}/CHANGELOG.md +17 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/PKG-INFO +1 -1
- neunorm-2.2.2/src/neunorm/_version.py +1 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/processing/normalizer.py +44 -14
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_background_roi_pooled.py +96 -0
- neunorm-2.2.1/src/neunorm/_version.py +0 -1
- {neunorm-2.2.1 → neunorm-2.2.2}/.claude/agents/bug-hunter.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.claude/skills/bughunt/SKILL.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.claude/skills/post-merge/SKILL.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.claude/skills/release/SKILL.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.claude/skills/review-pipeline/SKILL.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.claude/workflows/bughunt-deep.js +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.claude/workflows/dual-family-review.js +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.gitattributes +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.github/CODEOWNERS +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.github/dependabot.yml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.github/release.yml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.github/workflows/codeql.yml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.github/workflows/dependency-scan.yml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.github/workflows/test_and_deploy.yaml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.github/workflows/update-lockfiles.yml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.gitignore +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.grype.yaml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.pre-commit-config.yaml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.readthedocs.yaml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/.zenodo.json +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/AGENTS.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/CITATION.cff +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/CLAUDE.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/CONTRIBUTING.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/LICENSE +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/README.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/SECURITY.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/NeuNorm/__init__.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/NeuNorm/_utilities.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/NeuNorm/exporter.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/NeuNorm/loader.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/NeuNorm/normalization.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/NeuNorm/roi.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/README.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/conda.recipe/meta.yaml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/df/DC0000.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/df/DC0001.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/df/DC0002.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0001.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0002.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0003.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0004.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0005.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0006.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0007.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0008.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0009.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0010.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0011.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0012.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0013.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0014.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/ob/0015.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0002.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0003.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0004.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0005.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0006.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0007.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0008.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0009.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0010.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0011.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0012.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0013.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0014.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/data/sample/0015.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/Makefile +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/readthedocs-environment.yml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/_static/normalization_equation.png +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/_static/normalization_principle.png +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/_static/progress_bar_loading.png +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/_static/progress_bar_normalization.png +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/conf.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/cropping_data.rst +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/dark_field_correction.rst +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/export_data.rst +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/index.rst +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/installation.rst +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/loading.rst +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/normalization.rst +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/notebook.rst +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/retrieve_normalized_data.rst +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/tutorial_normalization_with_fewer_ob_than_sample.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/tutorial_using_array_input.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/tutorial_using_folder_input.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/environment.yml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/notebooks/debugging_multi_roi_bug.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/notebooks/notebook_display_with_time_estimation.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/notebooks/testing_new_auto_gamma_filtering.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/notebooks/tutorial_normalization_with_fewer_ob_than_sample.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/notebooks/tutorial_normalization_with_fewer_ob_than_sample_MAYBE_BUG.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/notebooks/tutorial_using_array_input.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/notebooks/tutorial_using_array_input_and_export_array.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/notebooks/tutorial_using_array_input_and_several_roi.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/notebooks/tutorial_using_folder_input.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/paper/paper.bib +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/paper/paper.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/scripts/clean_build_artifacts.sh +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/NeuNorm/normalizing_test.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/NeuNorm/test_cropping.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/NeuNorm/test_export.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/NeuNorm/test_loading.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/NeuNorm/test_roi.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/NeuNorm/test_utilities.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/different_format/df001_4_by_4.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/different_format/image001_4_by_4.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/different_format/image001_with_gamma.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/different_format/not_supported_file.fake +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/different_format/ob001_4_by_4.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/fits/df/df001.fits +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/fits/ob/ob001.fits +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/fits/ob/ob002.fits +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/fits/ob/ob003.fits +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/fits/test_roi/ob.fits +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/fits/test_roi/sample.fits +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/format_not_suppored.txt +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/hdf5/dump_file.hdf5 +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/ob001.fits +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/tif/df/df001.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/tif/df/df002.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/tif/df/df003.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/tif/ob/ob001.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/tif/ob/ob002.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/tif/ob/ob003.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/tif/sample_with_gamma/image001.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/tif/special_ob/ob_0001_2rois.tiff +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/tif/special_sample/image_0001_2rois.tiff +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/tif/special_sample/image_0001_roi_no_ob.tiff +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/codecov.yaml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/docs/api.rst +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/docs/conf.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/docs/development/DEVELOPMENT_PLAN.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/docs/index.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/docs/migration.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/docs/workflows/README.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/docs/workflows/mars_ccd_cmos.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/docs/workflows/mars_tpx3.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/docs/workflows/venus_ccd_cmos.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/docs/workflows/venus_tpx1.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/docs/workflows/venus_tpx3.md +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/examples/pulse_reconstruction_explained.ipynb +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/pixi.lock +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/pyproject.toml +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/__init__.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/data_models/__init__.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/data_models/core.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/data_models/roi.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/data_models/tof.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/exporters/__init__.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/exporters/hdf5_writer.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/exporters/tiff_writer.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/filters/__init__.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/filters/gamma_filter.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/loaders/__init__.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/loaders/event_loader.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/loaders/fits_loader.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/loaders/metadata_loader.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/loaders/stack_loader.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/loaders/tiff_loader.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/pipelines/__init__.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/pipelines/mars_ccd.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/pipelines/mars_tpx3.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/pipelines/venus_ccd.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/pipelines/venus_tpx1.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/pipelines/venus_tpx3_event.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/pipelines/venus_tpx3_histogram.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/processing/__init__.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/processing/air_region_corrector.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/processing/dark_corrector.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/processing/reference_preparer.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/processing/roi_clipper.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/processing/run_combiner.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/processing/spatial_rebinner.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/processing/uncertainty_calculator.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/tof/__init__.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/tof/binning.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/tof/coordinate_converter.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/tof/event_converter.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/tof/histogram_rebinner.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/tof/pixel_detector.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/tof/pulse_reconstruction.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/tof/resonance.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/tof/statistics_analyzer.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/utils/__init__.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/utils/_numba_compat.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/src/neunorm/utils/constants.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/data/fits/sample/image001.fits +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/data/fits/sample/image002.fits +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/data/fits/sample/image003.fits +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/data/tif/sample/image001.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/data/tif/sample/image002.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/data/tif/sample/image003.tif +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/integration/test_tof_pipeline.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/neunorm/test_version.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_air_region_corrector.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_analyze_statistics.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_binning_config.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_binning_conversions.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_constants.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_dark_corrector.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_division_by_zero_guards.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_event_converter.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_event_loader.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_eventdata_auto_validation.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_fits_loader.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_gamma_filter.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_hdf5_writer.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_mars_ccd.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_mars_tpx3.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_metadata_loader.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_normalizer.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_numba_compat.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_parallel_processing.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_pixel_detector.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_pulse_reconstruction.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_rebin_spatial.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_rebin_tof.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_reference_preparer.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_refine_boundaries_jit.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_remaining_jit.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_resonance_detection.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_roi.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_roi_clipper.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_run_combiner.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_tiff_loader.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_tiff_writer.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_uncertainty.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_variance_propagation_fix.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_venus_ccd.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_venus_tpx1.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_venus_tpx3_event.py +0 -0
- {neunorm-2.2.1 → neunorm-2.2.2}/tests/unit/test_venus_tpx3_histogram.py +0 -0
|
@@ -5,6 +5,22 @@ All notable changes to NeuNorm are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.2.2] - 2026-07-02
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **`background_roi` can now reproduce legacy 1.x zero-count-ROI semantics** (completes the
|
|
13
|
+
downstream-superset goal of
|
|
14
|
+
[#172](https://github.com/ornlneutronimaging/NeuNorm/issues/172) /
|
|
15
|
+
[#159](https://github.com/ornlneutronimaging/NeuNorm/issues/159)): the pooled-mean
|
|
16
|
+
strictly-positive/finite guard can be opted out with
|
|
17
|
+
`apply_background_roi(..., strict=False)` or
|
|
18
|
+
`normalize_transmission(...)` / `normalize_with_dark(..., background_roi_strict=False)`,
|
|
19
|
+
letting a zero-count background ROI propagate `inf`/`nan` through the division exactly as
|
|
20
|
+
NeuNorm 1.x did (iBeatles pins this behavior). The default stays strict — a
|
|
21
|
+
non-positive/non-finite pooled mean raises `ValueError` — and structural errors (bad ROI
|
|
22
|
+
bounds, missing dims) always raise.
|
|
23
|
+
|
|
8
24
|
## [2.2.1] - 2026-07-01
|
|
9
25
|
|
|
10
26
|
### Added
|
|
@@ -196,6 +212,7 @@ documentation are archived under
|
|
|
196
212
|
[`archive/neunorm-1.x/`](archive/neunorm-1.x/); released 1.x versions remain
|
|
197
213
|
available on PyPI and the `conda-forge` channel (`pip install "NeuNorm<2"`).
|
|
198
214
|
|
|
215
|
+
[2.2.2]: https://github.com/ornlneutronimaging/NeuNorm/releases/tag/v2.2.2
|
|
199
216
|
[2.2.1]: https://github.com/ornlneutronimaging/NeuNorm/releases/tag/v2.2.1
|
|
200
217
|
[2.2.0]: https://github.com/ornlneutronimaging/NeuNorm/releases/tag/v2.2.0
|
|
201
218
|
[2.1.0]: https://github.com/ornlneutronimaging/NeuNorm/releases/tag/v2.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: NeuNorm
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: Neutron imaging normalization and TOF data processing for ORNL facilities
|
|
5
5
|
Project-URL: homepage, https://github.com/ornlneutronimaging/NeuNorm
|
|
6
6
|
Project-URL: repository, https://github.com/ornlneutronimaging/NeuNorm
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.2.2"
|
|
@@ -64,6 +64,7 @@ def _pooled_roi_coefficient(
|
|
|
64
64
|
data: sc.DataArray,
|
|
65
65
|
rois_bounds: list[tuple[int, int, int, int]],
|
|
66
66
|
name: str,
|
|
67
|
+
strict: bool = True,
|
|
67
68
|
) -> sc.Variable:
|
|
68
69
|
"""Per-image **pooled** background coefficient over one or more ROIs.
|
|
69
70
|
|
|
@@ -73,8 +74,11 @@ def _pooled_roi_coefficient(
|
|
|
73
74
|
the summed counts and the pixel count (spatial ``(x, y)`` masks assumed). ``x1``/``y1`` are
|
|
74
75
|
exclusive stops. Returns a variance-bearing scipp Variable (the variance of the pooled mean).
|
|
75
76
|
|
|
76
|
-
Raises ``ValueError`` on an invalid/out-of-bounds ROI
|
|
77
|
-
|
|
77
|
+
Raises ``ValueError`` on an invalid/out-of-bounds ROI or missing ``x``/``y`` dims. With
|
|
78
|
+
``strict`` (default) it also rejects a non-positive/non-finite pooled mean (which would
|
|
79
|
+
silently yield inf/nan output); ``strict=False`` skips only that guard and lets zeros
|
|
80
|
+
propagate through the division — the 1.x semantics, for downstreams reproducing legacy
|
|
81
|
+
outputs bit for bit.
|
|
78
82
|
"""
|
|
79
83
|
if "x" not in data.dims or "y" not in data.dims:
|
|
80
84
|
raise ValueError(f"{name} must have 'x' and 'y' dimensions for background_roi normalization")
|
|
@@ -99,7 +103,7 @@ def _pooled_roi_coefficient(
|
|
|
99
103
|
n_unmasked = roi_n if n_unmasked is None else n_unmasked + roi_n
|
|
100
104
|
|
|
101
105
|
coeff = total / n_unmasked
|
|
102
|
-
if not bool(sc.all(sc.isfinite(coeff)).value) or sc.min(coeff).value <= 0:
|
|
106
|
+
if strict and (not bool(sc.all(sc.isfinite(coeff)).value) or sc.min(coeff).value <= 0):
|
|
103
107
|
raise ValueError(
|
|
104
108
|
f"background_roi {name} pooled mean must be strictly positive and finite "
|
|
105
109
|
f"(min={sc.min(coeff).value}); the ROI(s) must contain positive counts in every image"
|
|
@@ -111,10 +115,11 @@ def _background_roi_means(
|
|
|
111
115
|
sample: sc.DataArray,
|
|
112
116
|
ob: sc.DataArray,
|
|
113
117
|
rois_bounds: list[tuple[int, int, int, int]],
|
|
118
|
+
strict: bool = True,
|
|
114
119
|
) -> tuple[sc.Variable, sc.Variable]:
|
|
115
120
|
"""Per-image pooled background means (cs, co) for sample and OB over the same ROI list."""
|
|
116
|
-
cs = _pooled_roi_coefficient(sample, rois_bounds, "sample")
|
|
117
|
-
co = _pooled_roi_coefficient(ob, rois_bounds, "ob")
|
|
121
|
+
cs = _pooled_roi_coefficient(sample, rois_bounds, "sample", strict=strict)
|
|
122
|
+
co = _pooled_roi_coefficient(ob, rois_bounds, "ob", strict=strict)
|
|
118
123
|
return cs, co
|
|
119
124
|
|
|
120
125
|
|
|
@@ -174,7 +179,9 @@ def _roi_dark_mean_covariance(
|
|
|
174
179
|
roi_var_sum = sc.variances(sc.sum(d_roi, dim=["x", "y"]).data) # counts**2 (scalar)
|
|
175
180
|
intersection_var_sum = roi_var_sum if intersection_var_sum is None else intersection_var_sum + roi_var_sum
|
|
176
181
|
|
|
177
|
-
# n_s, n_o > 0 is guaranteed upstream (_pooled_roi_coefficient raises on an
|
|
182
|
+
# n_s, n_o > 0 is guaranteed upstream under strict (_pooled_roi_coefficient raises on an
|
|
183
|
+
# all-masked ROI); with strict=False an all-masked ROI gives n=0 and the resulting
|
|
184
|
+
# non-finite covariance is zeroed by the isfinite guard on the over-count below.
|
|
178
185
|
return intersection_var_sum / (n_s * n_o)
|
|
179
186
|
|
|
180
187
|
|
|
@@ -185,6 +192,7 @@ def normalize_transmission( # noqa: C901
|
|
|
185
192
|
proton_charge_ob: Optional[Union[float, sc.Variable]] = None,
|
|
186
193
|
pc_uncertainty: float = 0.005,
|
|
187
194
|
background_roi: Optional[BackgroundROILike] = None,
|
|
195
|
+
background_roi_strict: bool = True,
|
|
188
196
|
) -> sc.DataArray:
|
|
189
197
|
"""
|
|
190
198
|
Normalize sample by open beam to compute transmission.
|
|
@@ -220,9 +228,15 @@ def normalize_transmission( # noqa: C901
|
|
|
220
228
|
spanning ``w+1`` pixels), use ``ROI(..., inclusive=True)``; see ``apply_background_roi`` for the
|
|
221
229
|
open-beam-less form. Mutually exclusive with ``proton_charge_sample`` / ``proton_charge_ob``.
|
|
222
230
|
Uncertainty is propagated first-order (the in-ROI sample/ROI-mean correlation is not
|
|
223
|
-
corrected).
|
|
224
|
-
every image. Indices are resolved against the passed
|
|
225
|
-
first, give ``background_roi`` in the post-crop
|
|
231
|
+
corrected). Unless ``background_roi_strict=False``, raises ``ValueError`` if the pooled mean
|
|
232
|
+
is not strictly positive and finite in every image. Indices are resolved against the passed
|
|
233
|
+
arrays; if a pipeline crops with ``roi`` first, give ``background_roi`` in the post-crop
|
|
234
|
+
frame.
|
|
235
|
+
background_roi_strict : bool, optional
|
|
236
|
+
With the default ``True``, a non-positive/non-finite pooled background mean raises
|
|
237
|
+
``ValueError``. ``False`` skips only that guard and lets zeros propagate through the
|
|
238
|
+
division (inf/nan output) — the legacy 1.x semantics, for downstreams reproducing 1.x
|
|
239
|
+
outputs bit for bit. Structural errors (bad ROI bounds, missing dims) always raise.
|
|
226
240
|
|
|
227
241
|
Returns
|
|
228
242
|
-------
|
|
@@ -263,7 +277,7 @@ def normalize_transmission( # noqa: C901
|
|
|
263
277
|
"background_roi is the flux-normalization proxy for when proton charge is unavailable."
|
|
264
278
|
)
|
|
265
279
|
logger.info("Applying background-ROI flux normalization with ROI(s) {}", roi_list)
|
|
266
|
-
cs, co = _background_roi_means(sample, ob, roi_list)
|
|
280
|
+
cs, co = _background_roi_means(sample, ob, roi_list, strict=background_roi_strict)
|
|
267
281
|
# scipp refuses to broadcast a variance-bearing scalar across the image (it would introduce
|
|
268
282
|
# correlations), so divide by the variance-free means and re-add their variance contribution
|
|
269
283
|
# below. Handle cs and co INDEPENDENTLY — the two inputs may carry variance on one side only
|
|
@@ -374,6 +388,7 @@ def normalize_with_dark(
|
|
|
374
388
|
proton_charge_ob: Optional[Union[float, sc.Variable]] = None,
|
|
375
389
|
pc_uncertainty: float = 0.005,
|
|
376
390
|
background_roi: Optional[BackgroundROILike] = None,
|
|
391
|
+
background_roi_strict: bool = True,
|
|
377
392
|
) -> sc.DataArray:
|
|
378
393
|
"""Dark-correct and normalize in one step, treating the shared dark frame correctly.
|
|
379
394
|
|
|
@@ -405,6 +420,9 @@ def normalize_with_dark(
|
|
|
405
420
|
covariance term ``2*T^2*Cov(cs,co)/(cs*co)`` (``Cov(cs,co) = Var(mean(D_roi))``) — the
|
|
406
421
|
ROI-mean analog of the pixel-level correction. (The in-ROI pixel/ROI-mean correlation
|
|
407
422
|
remains uncorrected, as documented on ``normalize_transmission``.)
|
|
423
|
+
background_roi_strict : bool, optional
|
|
424
|
+
See ``normalize_transmission``: ``False`` skips the strictly-positive/finite pooled-mean
|
|
425
|
+
guard and lets zeros propagate (legacy 1.x semantics).
|
|
408
426
|
|
|
409
427
|
Returns
|
|
410
428
|
-------
|
|
@@ -416,7 +434,13 @@ def normalize_with_dark(
|
|
|
416
434
|
sample_dc = subtract_dark(sample, dark)
|
|
417
435
|
ob_dc = subtract_dark(ob, dark)
|
|
418
436
|
transmission = normalize_transmission(
|
|
419
|
-
sample_dc,
|
|
437
|
+
sample_dc,
|
|
438
|
+
ob_dc,
|
|
439
|
+
proton_charge_sample,
|
|
440
|
+
proton_charge_ob,
|
|
441
|
+
pc_uncertainty,
|
|
442
|
+
background_roi=background_roi,
|
|
443
|
+
background_roi_strict=background_roi_strict,
|
|
420
444
|
)
|
|
421
445
|
|
|
422
446
|
# Correct the shared-dark double-count. normalize_transmission propagated
|
|
@@ -437,7 +461,7 @@ def normalize_with_dark(
|
|
|
437
461
|
# for proton charge, or k = co/cs (ratio of dark-corrected ROI means) for background_roi. Use
|
|
438
462
|
# the coefficient values only (variance-free) — this is a variance correction, first-order in k.
|
|
439
463
|
if background_roi is not None:
|
|
440
|
-
cs, co = _background_roi_means(sample_dc, ob_dc, roi_list)
|
|
464
|
+
cs, co = _background_roi_means(sample_dc, ob_dc, roi_list, strict=background_roi_strict)
|
|
441
465
|
cs_v, co_v = sc.values(cs), sc.values(co)
|
|
442
466
|
k_squared = (co_v / cs_v) ** 2
|
|
443
467
|
else:
|
|
@@ -493,6 +517,7 @@ def _proton_charge_ratio_squared(
|
|
|
493
517
|
def apply_background_roi(
|
|
494
518
|
data: sc.DataArray,
|
|
495
519
|
background_roi: BackgroundROILike,
|
|
520
|
+
strict: bool = True,
|
|
496
521
|
) -> sc.DataArray:
|
|
497
522
|
"""Flux-flatten a stack by its pooled background-ROI mean (no open beam).
|
|
498
523
|
|
|
@@ -504,7 +529,7 @@ def apply_background_roi(
|
|
|
504
529
|
First-order uncertainty from the pooled ROI mean is propagated
|
|
505
530
|
(``Var += corrected**2 * Var(coeff) / coeff**2``); the in-ROI pixel/ROI-mean correlation is not
|
|
506
531
|
corrected. Reductions are mask-aware. Raises ``ValueError`` if the pooled mean is not strictly
|
|
507
|
-
positive and finite in every image.
|
|
532
|
+
positive and finite in every image (unless ``strict=False``).
|
|
508
533
|
|
|
509
534
|
Parameters
|
|
510
535
|
----------
|
|
@@ -512,6 +537,11 @@ def apply_background_roi(
|
|
|
512
537
|
Image stack with ``x``/``y`` dims (e.g. ``(spectral, x, y)``), optionally carrying variance.
|
|
513
538
|
background_roi : ROI/tuple or a sequence of them
|
|
514
539
|
Sample-free background region(s), pooled.
|
|
540
|
+
strict : bool, optional
|
|
541
|
+
With the default ``True``, a non-positive/non-finite pooled mean raises ``ValueError``.
|
|
542
|
+
``False`` skips only that guard and lets zeros propagate through the division (inf/nan
|
|
543
|
+
output) — the legacy 1.x semantics, for downstreams reproducing 1.x outputs bit for bit.
|
|
544
|
+
Structural errors (bad ROI bounds, missing dims) always raise.
|
|
515
545
|
|
|
516
546
|
Returns
|
|
517
547
|
-------
|
|
@@ -520,7 +550,7 @@ def apply_background_roi(
|
|
|
520
550
|
"""
|
|
521
551
|
roi_list = as_roi_bounds_list(background_roi)
|
|
522
552
|
logger.info("Applying sample-only background-ROI flux flattening with ROI(s) {}", roi_list)
|
|
523
|
-
coeff = _pooled_roi_coefficient(data, roi_list, "data")
|
|
553
|
+
coeff = _pooled_roi_coefficient(data, roi_list, "data", strict=strict)
|
|
524
554
|
coeff_var = sc.variances(coeff) if coeff.variances is not None else None
|
|
525
555
|
coeff = coeff.copy()
|
|
526
556
|
coeff.variances = None
|
|
@@ -153,3 +153,99 @@ def test_apply_background_roi_propagates_first_order_variance():
|
|
|
153
153
|
np.testing.assert_allclose(out.values[7, 7], val, rtol=1e-6)
|
|
154
154
|
expected_var = s[7, 7] / pool**2 + val**2 * var_pool / pool**2
|
|
155
155
|
np.testing.assert_allclose(out.variances[7, 7], expected_var, rtol=1e-6)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def test_background_roi_nonstrict_zero_count_roi_propagates_inf():
|
|
159
|
+
"""strict=False skips the positivity guard: a zero-count ROI yields inf, not ValueError.
|
|
160
|
+
|
|
161
|
+
The 1.x / iBeatles semantics (a zero-count background ROI propagates inf in the sample-only
|
|
162
|
+
path) — the escape hatch that lets downstreams reproduce 1.x outputs bit for bit.
|
|
163
|
+
"""
|
|
164
|
+
import pytest
|
|
165
|
+
|
|
166
|
+
s = np.ones((2, 8, 8))
|
|
167
|
+
s[:, 0:2, 0:2] = 0.0 # ROI (0,0,2,2) pooled mean -> 0
|
|
168
|
+
da = sc.DataArray(sc.array(dims=["N_image", "x", "y"], values=s, unit="counts"))
|
|
169
|
+
|
|
170
|
+
# default remains strict: raises
|
|
171
|
+
with pytest.raises(ValueError, match="strictly positive"):
|
|
172
|
+
apply_background_roi(da, (0, 0, 2, 2))
|
|
173
|
+
|
|
174
|
+
# non-strict: 1.x placement exactly — in-ROI 0/0 = nan, outside 1/0 = inf
|
|
175
|
+
out = apply_background_roi(da, (0, 0, 2, 2), strict=False)
|
|
176
|
+
in_roi = np.zeros((2, 8, 8), dtype=bool)
|
|
177
|
+
in_roi[:, 0:2, 0:2] = True
|
|
178
|
+
assert np.isnan(out.values[in_roi]).all()
|
|
179
|
+
assert np.isinf(out.values[~in_roi]).all()
|
|
180
|
+
|
|
181
|
+
# matched-OB path: same opt-out on normalize_transmission, same placement
|
|
182
|
+
# (OB coefficient is 1, so T inherits the sample-side inf/nan layout)
|
|
183
|
+
ob = sc.DataArray(sc.array(dims=["N_image", "x", "y"], values=np.ones((2, 8, 8)), unit="counts"))
|
|
184
|
+
with pytest.raises(ValueError, match="strictly positive"):
|
|
185
|
+
normalize_transmission(da, ob, background_roi=(0, 0, 2, 2))
|
|
186
|
+
t = normalize_transmission(da, ob, background_roi=(0, 0, 2, 2), background_roi_strict=False)
|
|
187
|
+
assert np.isnan(t.values[in_roi]).all()
|
|
188
|
+
assert np.isinf(t.values[~in_roi]).all()
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def test_background_roi_nonstrict_variance_nonfiniteness_is_confined():
|
|
192
|
+
"""Non-strict with variances: the zero-mean frame goes non-finite, other frames stay intact."""
|
|
193
|
+
s = np.full((2, 8, 8), 4.0)
|
|
194
|
+
s[0, 0:2, 0:2] = 0.0 # frame 0 ROI mean -> 0; frame 1 ROI mean = 4
|
|
195
|
+
da = sc.DataArray(sc.array(dims=["N_image", "x", "y"], values=s, variances=np.ones((2, 8, 8)), unit="counts"))
|
|
196
|
+
|
|
197
|
+
out = apply_background_roi(da, (0, 0, 2, 2), strict=False) # must not raise
|
|
198
|
+
# frame 1 is untouched by the degenerate frame: finite values AND variances, exact values
|
|
199
|
+
assert np.isfinite(out.values[1]).all() and np.isfinite(out.variances[1]).all()
|
|
200
|
+
np.testing.assert_allclose(out.values[1], 1.0, rtol=1e-12) # uniform frame / its own mean
|
|
201
|
+
# frame 0 carries the non-finite result of the 1.x zero-mean division
|
|
202
|
+
assert not np.isfinite(out.values[0]).all()
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def test_normalize_with_dark_background_roi_strict_optout():
|
|
206
|
+
"""normalize_with_dark threads background_roi_strict through BOTH coefficient sites.
|
|
207
|
+
|
|
208
|
+
Variance-bearing inputs so the k=co/cs shared-dark correction branch (the second
|
|
209
|
+
_background_roi_means call) executes. Zero dark-corrected ROI mean: strict raises,
|
|
210
|
+
non-strict propagates non-finite values without raising. Positive ROI mean: strict and
|
|
211
|
+
non-strict results are identical.
|
|
212
|
+
"""
|
|
213
|
+
import pytest
|
|
214
|
+
|
|
215
|
+
from neunorm.processing.normalizer import normalize_with_dark
|
|
216
|
+
|
|
217
|
+
def _stack(vals):
|
|
218
|
+
vals = np.asarray(vals, dtype=float)
|
|
219
|
+
return sc.DataArray(sc.array(dims=["N_image", "x", "y"], values=vals, variances=vals + 1.0, unit="counts"))
|
|
220
|
+
|
|
221
|
+
def _frame(vals):
|
|
222
|
+
vals = np.asarray(vals, dtype=float)
|
|
223
|
+
return sc.DataArray(sc.array(dims=["x", "y"], values=vals, variances=vals + 1.0, unit="counts"))
|
|
224
|
+
|
|
225
|
+
dark = _frame(np.full((8, 8), 5.0))
|
|
226
|
+
ob = _stack(np.full((1, 8, 8), 100.0))
|
|
227
|
+
s = np.full((1, 8, 8), 80.0)
|
|
228
|
+
s[:, 0:2, 0:2] = 5.0 # dark-corrected sample ROI mean -> 0
|
|
229
|
+
sample = _stack(s)
|
|
230
|
+
|
|
231
|
+
with pytest.raises(ValueError, match="strictly positive"):
|
|
232
|
+
normalize_with_dark(sample, ob, dark, background_roi=(0, 0, 2, 2))
|
|
233
|
+
t = normalize_with_dark(sample, ob, dark, background_roi=(0, 0, 2, 2), background_roi_strict=False)
|
|
234
|
+
assert not np.isfinite(t.values).all() # 1.x zero-mean division propagates
|
|
235
|
+
|
|
236
|
+
# positive ROI mean: the flag must not change anything (values OR variances)
|
|
237
|
+
s_ok = np.full((1, 8, 8), 80.0)
|
|
238
|
+
sample_ok = _stack(s_ok)
|
|
239
|
+
t_strict = normalize_with_dark(sample_ok, ob, dark, background_roi=(0, 0, 2, 2))
|
|
240
|
+
t_lax = normalize_with_dark(sample_ok, ob, dark, background_roi=(0, 0, 2, 2), background_roi_strict=False)
|
|
241
|
+
np.testing.assert_array_equal(t_strict.values, t_lax.values)
|
|
242
|
+
np.testing.assert_array_equal(t_strict.variances, t_lax.variances)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def test_background_roi_nonstrict_still_raises_structural_errors():
|
|
246
|
+
"""strict=False relaxes ONLY the positivity guard — bad ROI bounds still raise."""
|
|
247
|
+
import pytest
|
|
248
|
+
|
|
249
|
+
da = sc.DataArray(sc.array(dims=["N_image", "x", "y"], values=np.ones((2, 8, 8)), unit="counts"))
|
|
250
|
+
with pytest.raises(ValueError, match="exceeds"):
|
|
251
|
+
apply_background_roi(da, (0, 0, 99, 99), strict=False)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.2.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/readthedocs-environment.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/documentation/source/dark_field_correction.rst
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/notebooks/testing_new_auto_gamma_filtering.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/notebooks/tutorial_using_array_input.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/notebooks/tutorial_using_folder_input.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/different_format/df001_4_by_4.tif
RENAMED
|
File without changes
|
{neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/different_format/image001_4_by_4.tif
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neunorm-2.2.1 → neunorm-2.2.2}/archive/neunorm-1.x/tests/data/different_format/ob001_4_by_4.tif
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|