anu-ctlab-io 1.0.0__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.
Files changed (55) hide show
  1. anu_ctlab_io-1.0.0/.github/workflows/ci.yml +40 -0
  2. anu_ctlab_io-1.0.0/.github/workflows/publish.yml +40 -0
  3. anu_ctlab_io-1.0.0/.gitignore +12 -0
  4. anu_ctlab_io-1.0.0/.pre-commit-config.yaml +57 -0
  5. anu_ctlab_io-1.0.0/.prettierignore +1 -0
  6. anu_ctlab_io-1.0.0/.python-version +1 -0
  7. anu_ctlab_io-1.0.0/CHANGELOG.md +65 -0
  8. anu_ctlab_io-1.0.0/LICENSE.md +9 -0
  9. anu_ctlab_io-1.0.0/PKG-INFO +44 -0
  10. anu_ctlab_io-1.0.0/README.rst +1 -0
  11. anu_ctlab_io-1.0.0/_typos.toml +6 -0
  12. anu_ctlab_io-1.0.0/docs/conf.py +30 -0
  13. anu_ctlab_io-1.0.0/docs/index.rst +15 -0
  14. anu_ctlab_io-1.0.0/docs/introduction.rst +19 -0
  15. anu_ctlab_io-1.0.0/justfile +7 -0
  16. anu_ctlab_io-1.0.0/pyproject.toml +88 -0
  17. anu_ctlab_io-1.0.0/src/anu_ctlab_io/__init__.py +22 -0
  18. anu_ctlab_io-1.0.0/src/anu_ctlab_io/_dataset.py +189 -0
  19. anu_ctlab_io-1.0.0/src/anu_ctlab_io/_datatype.py +130 -0
  20. anu_ctlab_io-1.0.0/src/anu_ctlab_io/_parse_history.py +75 -0
  21. anu_ctlab_io-1.0.0/src/anu_ctlab_io/_version.py +3 -0
  22. anu_ctlab_io-1.0.0/src/anu_ctlab_io/_voxel_properties.py +57 -0
  23. anu_ctlab_io-1.0.0/src/anu_ctlab_io/netcdf/__init__.py +89 -0
  24. anu_ctlab_io-1.0.0/src/anu_ctlab_io/py.typed +0 -0
  25. anu_ctlab_io-1.0.0/src/anu_ctlab_io/zarr/__init__.py +52 -0
  26. anu_ctlab_io-1.0.0/tests/data/README.md +18 -0
  27. anu_ctlab_io-1.0.0/tests/data/generate_test_data_zarr.py +49 -0
  28. anu_ctlab_io-1.0.0/tests/data/tomoHiRes.zarr/c.1.0.0 +0 -0
  29. anu_ctlab_io-1.0.0/tests/data/tomoHiRes.zarr/c.2.0.0 +0 -0
  30. anu_ctlab_io-1.0.0/tests/data/tomoHiRes.zarr/c.3.0.0 +0 -0
  31. anu_ctlab_io-1.0.0/tests/data/tomoHiRes.zarr/zarr.json +83 -0
  32. anu_ctlab_io-1.0.0/tests/data/tomoHiRes_SS_nc/block00000000.nc +0 -0
  33. anu_ctlab_io-1.0.0/tests/data/tomoHiRes_SS_nc/block00000001.nc +0 -0
  34. anu_ctlab_io-1.0.0/tests/data/tomoHiRes_SS_nc/block00000002.nc +0 -0
  35. anu_ctlab_io-1.0.0/tests/data/tomoHiRes_SS_nc/block00000003.nc +0 -0
  36. anu_ctlab_io-1.0.0/tests/data/tomoHiRes_SS_nc/block00000004.nc +0 -0
  37. anu_ctlab_io-1.0.0/tests/data/tomoHiRes_SS_nc/block00000005.nc +0 -0
  38. anu_ctlab_io-1.0.0/tests/data/tomoLoRes.zarr/c.0.0.0 +0 -0
  39. anu_ctlab_io-1.0.0/tests/data/tomoLoRes.zarr/c.1.0.0 +0 -0
  40. anu_ctlab_io-1.0.0/tests/data/tomoLoRes.zarr/c.2.0.0 +0 -0
  41. anu_ctlab_io-1.0.0/tests/data/tomoLoRes.zarr/c.3.0.0 +0 -0
  42. anu_ctlab_io-1.0.0/tests/data/tomoLoRes.zarr/zarr.json +83 -0
  43. anu_ctlab_io-1.0.0/tests/data/tomoLoRes_SS.nc +0 -0
  44. anu_ctlab_io-1.0.0/tests/data/tomoLoRes_SS_AM.zarr/0/c/0/0/0 +0 -0
  45. anu_ctlab_io-1.0.0/tests/data/tomoLoRes_SS_AM.zarr/0/zarr.json +78 -0
  46. anu_ctlab_io-1.0.0/tests/data/tomoLoRes_SS_AM.zarr/zarr.json +171 -0
  47. anu_ctlab_io-1.0.0/tests/schema/anu_ctlab_zarr_1_0_example.json +20 -0
  48. anu_ctlab_io-1.0.0/tests/test_datatype.py +19 -0
  49. anu_ctlab_io-1.0.0/tests/test_manual_read.py +78 -0
  50. anu_ctlab_io-1.0.0/tests/test_netcdf.py +53 -0
  51. anu_ctlab_io-1.0.0/tests/test_parse_history.py +77 -0
  52. anu_ctlab_io-1.0.0/tests/test_voxel_unit.py +12 -0
  53. anu_ctlab_io-1.0.0/tests/test_zarr.py +41 -0
  54. anu_ctlab_io-1.0.0/tox.ini +26 -0
  55. anu_ctlab_io-1.0.0/uv.lock +1008 -0
@@ -0,0 +1,40 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - main
10
+
11
+ concurrency:
12
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ test:
17
+ name: test
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - name: checkout
21
+ uses: actions/checkout@v4
22
+ - name: install uv
23
+ uses: astral-sh/setup-uv@v3
24
+ with:
25
+ version: "0.6.3"
26
+ - name: run tests
27
+ run: uvx --with tox-uv tox
28
+ lint:
29
+ name: lint
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - name: checkout
33
+ uses: actions/checkout@v4
34
+ - name: install uv
35
+ uses: astral-sh/setup-uv@v3
36
+ with:
37
+ version: "0.6.3"
38
+ - name: run pre-commit checks
39
+ run: |
40
+ uv run pre-commit run --all-files --show-diff-on-failure
@@ -0,0 +1,40 @@
1
+ name: publish
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v[0-9]+.[0-9]+.[0-9]+"
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v5
13
+ - name: Install UV
14
+ uses: astral-sh/setup-uv@v6
15
+ with:
16
+ version: "0.6.3"
17
+ - name: Build source distribution
18
+ run: uv build
19
+ - uses: actions/upload-artifact@v4
20
+ with:
21
+ name: pypi-files-sdist
22
+ path: dist
23
+
24
+ pypi-publish:
25
+ name: "build and publish release"
26
+ needs: [build]
27
+ runs-on: ubuntu-latest
28
+ environment:
29
+ name: pypi
30
+ permissions:
31
+ id-token: write
32
+ steps:
33
+ - uses: actions/download-artifact@v5
34
+ with:
35
+ pattern: pypi-files-*
36
+ merge-multiple: true
37
+ path: dist/
38
+ - run: ls -lh dist/
39
+ - name: Publish package distributions to PyPI
40
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,12 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+ docs/_autosummary/
9
+ docs/_build/
10
+
11
+ # Virtual environments
12
+ .venv
@@ -0,0 +1,57 @@
1
+ ci:
2
+ autoupdate_commit_msg: "chore: update pre-commit hooks"
3
+
4
+ repos:
5
+ - repo: https://github.com/pre-commit/pre-commit-hooks
6
+ rev: v5.0.0
7
+ hooks:
8
+ - id: check-yaml
9
+ - id: check-toml
10
+ - id: end-of-file-fixer
11
+ exclude: "^tests/(data|schema)/"
12
+ - id: trailing-whitespace
13
+ - repo: https://github.com/pre-commit/mirrors-prettier
14
+ rev: "v3.1.0"
15
+ hooks:
16
+ - id: prettier
17
+ exclude: "^tests/(data|schema)/"
18
+ types_or: [yaml, markdown, html, css, scss, javascript, json]
19
+ - repo: https://github.com/astral-sh/ruff-pre-commit
20
+ # Ruff version.
21
+ rev: v0.9.2
22
+ hooks:
23
+ # Run the linter.
24
+ - id: ruff
25
+ args: ["--fix", "--show-fixes"]
26
+ # Run the formatter.
27
+ - id: ruff-format
28
+ - repo: https://github.com/pre-commit/mirrors-mypy
29
+ rev: v1.15.0
30
+ hooks:
31
+ - id: mypy
32
+ pass_filenames: false
33
+ always_run: true
34
+ args: [src]
35
+ additional_dependencies:
36
+ - pandas-stubs
37
+ - numpy
38
+ - xarray
39
+ - matplotlib
40
+ - lark
41
+ - zarr
42
+ - dask
43
+ - deprecation
44
+ - repo: https://github.com/adamchainz/blacken-docs
45
+ rev: "v1.12.1"
46
+ hooks:
47
+ - id: blacken-docs
48
+ additional_dependencies:
49
+ - black==22.12.0
50
+ - repo: https://github.com/crate-ci/typos
51
+ rev: v1.36.2
52
+ hooks:
53
+ - id: typos
54
+ - repo: https://github.com/rbubley/mirrors-prettier
55
+ rev: "v3.6.2"
56
+ hooks:
57
+ - id: prettier
@@ -0,0 +1 @@
1
+ tests/data/*
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,65 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.0.0] - 2025-09-12
11
+
12
+ ### Added
13
+
14
+ - Github CI for build and release to PyPI
15
+ - Documentation using Sphinx
16
+ - justfile to build docs and run tests
17
+ - Support for units to `VoxelUnit` to match MANGO support: `angstrom`, `centimeters`, `voxels`
18
+ - Tests for `DataType.from_basename`
19
+
20
+ ### Changed
21
+
22
+ - Replace README.md with README.rst
23
+ - Improve typehinting
24
+ - Privatise unintentionally public modules: `dataset`, `datatype`, `parse_history`, `version`, `voxel_properties`
25
+ - Privatise objects not intended to be public:
26
+ - `_datatype.DataTypeProperties`
27
+ - `_datatype.DATATYPE_PROPERTIES`
28
+ - `netcdf._read_netcdf`
29
+ - Rename `_datatype.storage_dtypes` to `_datatype.StorageDType` (PEP8)
30
+ - Capitalise `DataType` members (PEP8)
31
+ - Capitalise `VoxelUnit` members (PEP8)
32
+ - Move zarr and netcdf dependencies to extras
33
+ - Improve `tox` testing configuration, including testing with and without extras
34
+ - Update changelog formatting to better match the Keep a Changelog format.
35
+
36
+ ### Removed
37
+
38
+ - Remove features which were deprecated in 0.2.0:
39
+ - NetCDFDataset
40
+ - Xarray dataset support
41
+ - Remove `UnknownVoxelUnitException`
42
+ - Remove `DatasetFormatException`
43
+
44
+ ## [0.2.0] - 2025-09-07
45
+
46
+ ### Added
47
+
48
+ - Support for reading ANU CTLab Zarr files
49
+ - Direct access to the data loaded as Dask arrays
50
+
51
+ ### Changed
52
+
53
+ - Interface changed to use the Dataset class for both Zarr and NetCDF files
54
+ - Xarray output deprecated (to be removed in 1.0.0)
55
+
56
+ ## [0.0.1]
57
+
58
+ ### Added
59
+
60
+ - Support for reading ANU CTLab NetCDF files
61
+ - Support for outputting Xarray data
62
+
63
+ [unreleased]: https://github.com/MaterialsPhysicsANU/anu_ctlab_io/compare/v1.0.0...HEAD
64
+ [1.0.0]: https://github.com/MaterialsPhysicsANU/anu_ctlab_io/releases/tag/v1.0.0
65
+ [0.2.0]: https://github.com/MaterialsPhysicsANU/anu_ctlab_io/releases/tag/v0.2.0
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025, the Australian National University (ANU)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,44 @@
1
+ Metadata-Version: 2.4
2
+ Name: anu-ctlab-io
3
+ Version: 1.0.0
4
+ Summary: python I/O for the ANU CTLab array storage format(s)
5
+ Project-URL: Repository, https://github.com/MaterialsPhysicsANU/anu_ctlab_io
6
+ Project-URL: Issues, https://github.com/MaterialsPhysicsANU/anu_ctlab_io/issues
7
+ Project-URL: Changelog, https://github.com/MaterialsPhysicsANU/anu_ctlab_io/main/CHANGELOG.md
8
+ Author-email: Owen Dowley <owen.dowley@anu.edu.au>, Bogdan Maviichuk <bogdan.maviichuk@anu.edu.au>, Lachlan Deakin <lachlan.deakin@anu.edu.au>
9
+ Maintainer-email: Owen Dowley <owen.dowley@anu.edu.au>
10
+ License-Expression: MIT
11
+ License-File: LICENSE.md
12
+ Requires-Python: >=3.12
13
+ Requires-Dist: dask[array]>=2025.2.0
14
+ Requires-Dist: deprecation>=2.1.0
15
+ Requires-Dist: dictdiffer>=0.9.0
16
+ Requires-Dist: lark>=1.2.2
17
+ Requires-Dist: numpy>=2.2.3
18
+ Requires-Dist: xarray>=2025.1.2
19
+ Provides-Extra: netcdf
20
+ Requires-Dist: netcdf4>=1.7.2; extra == 'netcdf'
21
+ Requires-Dist: scipy>=1.16.1; extra == 'netcdf'
22
+ Provides-Extra: zarr
23
+ Requires-Dist: zarr>=3.1.1; extra == 'zarr'
24
+ Description-Content-Type: text/x-rst
25
+
26
+ Introduction
27
+ ------------
28
+ python I/O for the ANU CTLab array storage format(s).
29
+
30
+ This package loads data provided in the specific NetCDF and Zarr formats produced by the ANU CTLab.
31
+ The intention is that the consumers of the data we produce should be able to load that data and then
32
+ work with that directly in standard scientific python workflows, rather than needing to use the
33
+ pre-existing MANGO toolchain.
34
+
35
+ Examples
36
+ --------
37
+ .. code-block :: python3
38
+
39
+ import anu_ctlab_io
40
+ from dask_image import ndfilters
41
+
42
+ dataset = anu_ctlab_io.Dataset.from_path(<path-to-your-data>)
43
+ blurred = ndfilters.gaussian_filter(dataset.data, sigma=3)
44
+ print(blurred.mean().compute())
@@ -0,0 +1 @@
1
+ docs/introduction.rst
@@ -0,0 +1,6 @@
1
+ [files]
2
+ extend-exclude = ["tests/data/*"]
3
+
4
+ [default.extend-words]
5
+ # Don't correct "ome" to "some"
6
+ ome = "ome"
@@ -0,0 +1,30 @@
1
+ import importlib.metadata
2
+
3
+ # Sphinx configuration for anu-ctlab-io docs
4
+ project = "anu-ctlab-io"
5
+ copyright = "2025, the Australian National University (ANU)"
6
+ author = "Materials Physics, ANU" # Can only be a single author, so can't match pyproject.toml. Find actual authors there.
7
+ release = importlib.metadata.version("anu_ctlab_io")
8
+ extensions = [
9
+ # 'myst_parser',
10
+ "sphinx_rtd_theme",
11
+ "sphinx.ext.autodoc",
12
+ # "sphinx.ext.napoleon",
13
+ "sphinx.ext.autosummary",
14
+ "sphinx_autodoc_typehints",
15
+ ]
16
+ html_theme = "sphinx_rtd_theme"
17
+ autosummary_generate = True
18
+ source_suffix = {
19
+ # '.md': 'markdown',
20
+ ".rst": "restructuredtext",
21
+ }
22
+ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
23
+ autodoc_default_options = {
24
+ "members": True,
25
+ "undoc-members": True,
26
+ "member-order": "bysource",
27
+ "show-inheritance": True,
28
+ "inherited-members": True,
29
+ "special-members": "__init__",
30
+ }
@@ -0,0 +1,15 @@
1
+ anu_ctlab_io package
2
+ ====================
3
+ .. toctree::
4
+ introduction
5
+
6
+ .. .. automodule:: anu_ctlab_io
7
+ .. :members:
8
+ .. :undoc-members:
9
+ .. :show-inheritance:
10
+
11
+ .. autosummary::
12
+ :toctree: _autosummary
13
+ :recursive:
14
+
15
+ anu_ctlab_io
@@ -0,0 +1,19 @@
1
+ Introduction
2
+ ------------
3
+ python I/O for the ANU CTLab array storage format(s).
4
+
5
+ This package loads data provided in the specific NetCDF and Zarr formats produced by the ANU CTLab.
6
+ The intention is that the consumers of the data we produce should be able to load that data and then
7
+ work with that directly in standard scientific python workflows, rather than needing to use the
8
+ pre-existing MANGO toolchain.
9
+
10
+ Examples
11
+ --------
12
+ .. code-block :: python3
13
+
14
+ import anu_ctlab_io
15
+ from dask_image import ndfilters
16
+
17
+ dataset = anu_ctlab_io.Dataset.from_path(<path-to-your-data>)
18
+ blurred = ndfilters.gaussian_filter(dataset.data, sigma=3)
19
+ print(blurred.mean().compute())
@@ -0,0 +1,7 @@
1
+ docs:
2
+ rm -rf docs/_autosummary
3
+ rm -rf docs/_build
4
+ uv run sphinx-build -M html docs docs/_build
5
+
6
+ test:
7
+ uvx --with tox-uv tox
@@ -0,0 +1,88 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "anu-ctlab-io"
7
+ version = "1.0.0"
8
+ description = "python I/O for the ANU CTLab array storage format(s)"
9
+ readme = "README.rst"
10
+ requires-python = ">=3.12"
11
+ dependencies = [
12
+ "dask[array]>=2025.2.0",
13
+ "xarray>=2025.1.2",
14
+ "numpy>=2.2.3",
15
+ "lark>=1.2.2",
16
+ "dictdiffer>=0.9.0",
17
+ "deprecation>=2.1.0",
18
+ ]
19
+ default-optional-dependency-keys = [
20
+ "netcdf",
21
+ "zarr",
22
+ ]
23
+
24
+ license = "MIT"
25
+ license-files = ["LICENSE.md"]
26
+ authors = [
27
+ {name = "Owen Dowley", email = "owen.dowley@anu.edu.au"},
28
+ {name = "Bogdan Maviichuk", email = "bogdan.maviichuk@anu.edu.au"},
29
+ {name = "Lachlan Deakin", email = "lachlan.deakin@anu.edu.au"},
30
+ ]
31
+ maintainers = [
32
+ {name = "Owen Dowley", email = "owen.dowley@anu.edu.au"},
33
+ ]
34
+
35
+ [project.optional-dependencies]
36
+ netcdf = [
37
+ "netcdf4>=1.7.2",
38
+ "scipy>=1.16.1", # netCDF 3 support
39
+ ]
40
+ zarr = [
41
+ "zarr>=3.1.1",
42
+ ]
43
+
44
+ [project.urls]
45
+ # FIXME: Add Homepage on v1.0.0 release
46
+ Repository = "https://github.com/MaterialsPhysicsANU/anu_ctlab_io"
47
+ Issues = "https://github.com/MaterialsPhysicsANU/anu_ctlab_io/issues"
48
+ Changelog = "https://github.com/MaterialsPhysicsANU/anu_ctlab_io/main/CHANGELOG.md"
49
+
50
+ [dependency-groups]
51
+ dev = [
52
+ "pre-commit>=4.1.0",
53
+ "ruff>=0.9.5",
54
+ "pytest>=8.3.5",
55
+ "sphinx>=8.2.3",
56
+ "sphinx-rtd-theme>=3.0.2",
57
+ "sphinx-autodoc-typehints>=3.2.0",
58
+ ]
59
+
60
+ [tool.pytest.ini_options]
61
+ filterwarnings = [
62
+ # known behaviour, caused by numpy changes which are ABI compatible with older versions,
63
+ # but which cython flags as a warning despite everything being fine
64
+ # See https://github.com/cython/cython/issues/2498, https://github.com/cython/cython/issues/4366
65
+ 'ignore:numpy.ndarray size changed, may indicate binary incompatibility.'
66
+ ]
67
+ addopts = [
68
+ "--import-mode=importlib", # recommended by pytest
69
+ "-ra",
70
+ "--strict-config",
71
+ "--strict-markers"
72
+ ]
73
+ minversion = "7.0"
74
+ testpaths = ["tests"]
75
+ log_cli_level = "INFO"
76
+ xfail_strict = true
77
+
78
+ [tool.mypy]
79
+ strict = true
80
+ warn_unreachable = true
81
+ enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
82
+
83
+ [tool.ruff.lint]
84
+ extend-select = [
85
+ "B", # flake8-bugbear
86
+ "I", # isort
87
+ "UP", # pyupgrade
88
+ ]
@@ -0,0 +1,22 @@
1
+ from contextlib import suppress
2
+
3
+ from anu_ctlab_io._dataset import Dataset
4
+ from anu_ctlab_io._datatype import DataType, StorageDType
5
+ from anu_ctlab_io._version import version as __version__
6
+ from anu_ctlab_io._voxel_properties import VoxelUnit
7
+
8
+ with suppress(ImportError):
9
+ import anu_ctlab_io.netcdf as netcdf
10
+
11
+ with suppress(ImportError):
12
+ import anu_ctlab_io.zarr as zarr
13
+
14
+ __all__ = [
15
+ "Dataset", # out of sorted order so it comes first in the docs
16
+ "DataType",
17
+ "StorageDType",
18
+ "VoxelUnit",
19
+ "__version__",
20
+ "netcdf",
21
+ "zarr",
22
+ ]
@@ -0,0 +1,189 @@
1
+ from abc import ABC, abstractmethod, abstractproperty
2
+ from importlib import import_module
3
+ from pathlib import Path
4
+ from types import ModuleType
5
+ from typing import Any, Self
6
+
7
+ import dask.array as da
8
+ import numpy as np
9
+
10
+ from anu_ctlab_io._datatype import DataType, StorageDType
11
+ from anu_ctlab_io._voxel_properties import VoxelUnit
12
+
13
+
14
+ class AbstractDataset(ABC):
15
+ @classmethod
16
+ @abstractmethod
17
+ def from_path(
18
+ cls, path: Path, *, parse_history: bool = True, **kwargs: Any
19
+ ) -> Self:
20
+ pass
21
+
22
+ @abstractproperty
23
+ def voxel_size(self) -> tuple[np.float32, np.float32, np.float32]:
24
+ pass
25
+
26
+ @abstractproperty
27
+ def voxel_unit(self) -> VoxelUnit:
28
+ pass
29
+
30
+ @abstractproperty
31
+ def dimension_names(self) -> tuple[str, ...]:
32
+ pass
33
+
34
+ @abstractproperty
35
+ def history(self) -> dict[Any, Any] | str:
36
+ pass
37
+
38
+ @abstractproperty
39
+ def mask_value(self) -> StorageDType | None:
40
+ pass
41
+
42
+ @abstractproperty
43
+ def data(self) -> da.Array:
44
+ pass
45
+
46
+
47
+ class Dataset(AbstractDataset):
48
+ """A :any:`Dataset`, containing the data and metadata read from one of the ANU CTLab file formats.
49
+
50
+ :any:`Dataset`\\ s are the primary interface to the :py:mod:`anu_ctlab_io` package, and should generally be
51
+ constructed by users via the :any:`Dataset.from_path` classmethod.
52
+
53
+ The initializer of this class should only be used when manually constructing a :any:`Dataset`, which is not
54
+ the primary usage of this library.
55
+ """
56
+
57
+ _data: da.Array
58
+ _datatype: DataType
59
+ _voxel_unit: VoxelUnit
60
+ _voxel_size: tuple[np.float32, np.float32, np.float32]
61
+ _history: dict[Any, Any] | str
62
+
63
+ def __init__(
64
+ self,
65
+ data: da.Array,
66
+ *,
67
+ dimension_names: tuple[str, ...],
68
+ voxel_unit: VoxelUnit,
69
+ voxel_size: tuple[np.float32, np.float32, np.float32],
70
+ datatype: DataType,
71
+ history: dict[str, Any] | None = None,
72
+ ) -> None:
73
+ """
74
+ Manually constructs a :any:`Dataset`.
75
+
76
+ :param data: The data contained in the :any:`Dataset`.
77
+ :param dimension_names: The names of the dimensions of the :any:`Dataset`.
78
+ :param voxel_unit: The unit the `voxel_size` is in terms of.
79
+ :param voxel_size: The size of each voxel in the :any:`Dataset`.
80
+ :param datatype: The mango datatype of the data. This is an implementation detail only required for parsing NetCDF files.
81
+ :param history: The history of the :any:`Dataset`.
82
+ """
83
+ if history is None:
84
+ history = {}
85
+
86
+ self._data = data
87
+ self._dimension_names = dimension_names
88
+ self._datatype = datatype
89
+ self._voxel_unit = voxel_unit
90
+ self._voxel_size = voxel_size
91
+ self._history = history
92
+
93
+ @staticmethod
94
+ def _import_with_extra(module: str, extra: str) -> ModuleType:
95
+ try:
96
+ return import_module(module)
97
+ except ImportError as e:
98
+ raise ImportError(
99
+ f"{module} is missing. Please install with the '{extra}' extra: pip install anu-ctlab-io[{extra}]"
100
+ ) from e
101
+
102
+ @classmethod
103
+ def from_path(
104
+ cls,
105
+ path: Path | str,
106
+ *,
107
+ filetype: str = "auto",
108
+ parse_history: bool = True,
109
+ **kwargs: Any,
110
+ ) -> "Dataset":
111
+ """Creates a :any:`Dataset` from the data at the given ``path``.
112
+
113
+ The data at ``path`` must be in one of the ANU mass data storage formats, and the optional dependencies required for the specific
114
+ file format must be installed.
115
+
116
+ :param path: The ``path`` to read data from.
117
+ :rtype: :any:`Dataset`
118
+ """
119
+ if isinstance(path, str):
120
+ path = Path(path)
121
+
122
+ match filetype:
123
+ case "NetCDF":
124
+ netcdf_mod = cls._import_with_extra("anu_ctlab_io.netcdf", "netcdf")
125
+ return netcdf_mod.dataset_from_netcdf( # type: ignore[no-any-return]
126
+ path, parse_history=parse_history, **kwargs
127
+ )
128
+ case "zarr":
129
+ zarr_mod = cls._import_with_extra("anu_ctlab_io.zarr", "zarr")
130
+ return zarr_mod.dataset_from_zarr( # type: ignore[no-any-return]
131
+ path, parse_history=parse_history, **kwargs
132
+ )
133
+ case "auto":
134
+ if path.name[-2:] == "nc":
135
+ netcdf_mod = cls._import_with_extra("anu_ctlab_io.netcdf", "netcdf")
136
+ return netcdf_mod.dataset_from_netcdf( # type: ignore[no-any-return]
137
+ path, parse_history=parse_history, **kwargs
138
+ )
139
+
140
+ if path.name[-4:] == "zarr":
141
+ zarr_mod = cls._import_with_extra("anu_ctlab_io.zarr", "zarr")
142
+ return zarr_mod.dataset_from_zarr( # type: ignore[no-any-return]
143
+ path, parse_history=parse_history, **kwargs
144
+ )
145
+
146
+ raise (
147
+ ValueError(
148
+ "Unable to construct Dataset from given `path`, perhaps specify `filetype`?",
149
+ path,
150
+ )
151
+ )
152
+
153
+ @property
154
+ def voxel_size(self) -> tuple[np.float32, np.float32, np.float32]:
155
+ """The voxel size of the data."""
156
+ return self._voxel_size
157
+
158
+ @property
159
+ def voxel_unit(self) -> VoxelUnit:
160
+ """The unit the data's voxel size is in."""
161
+ return self._voxel_unit
162
+
163
+ @property
164
+ def dimension_names(self) -> tuple[str, ...]:
165
+ """The names of the data's dimensions. Usually ``("z", "y", "x")``."""
166
+ return self._dimension_names
167
+
168
+ @property
169
+ def history(self) -> dict[Any, Any] | str:
170
+ """The history metadata associated with the :any:`Dataset`.
171
+
172
+ If parsing is enabled this will be a nested dict, otherwise it will be a dictionary
173
+ without any guaranteed structure."""
174
+ return self._history
175
+
176
+ @property
177
+ def mask_value(self) -> StorageDType | None:
178
+ """The mask value being used by the data."""
179
+ return self._datatype.mask_value
180
+
181
+ @property
182
+ def data(self) -> da.Array:
183
+ """The data contained within the :any:`Dataset`.
184
+
185
+ This is a `Dask Array <https://docs.dask.org/en/stable/array.html>`_."""
186
+ return self._data
187
+
188
+
189
+ AbstractDataset.register(Dataset)