dcccpy 0.1.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.
@@ -0,0 +1,2 @@
1
+ include README.md
2
+ recursive-include src/dcccpy/vendor *
dcccpy-0.1.2/PKG-INFO ADDED
@@ -0,0 +1,152 @@
1
+ Metadata-Version: 2.4
2
+ Name: dcccpy
3
+ Version: 0.1.2
4
+ Summary: Python wrapper for the DCCCcore PET biomarker command-line tool
5
+ Author: DCCCSlicer contributors
6
+ License-Expression: CC-BY-NC-ND-4.0
7
+ Project-URL: Homepage, https://github.com/tctco/DCCCSlicer
8
+ Project-URL: Repository, https://github.com/tctco/DCCCSlicer
9
+ Project-URL: Issues, https://github.com/tctco/DCCCSlicer/issues
10
+ Keywords: PET,neuroimaging,centiloid,DCCC,DCCCSlicer
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ Requires-Dist: nibabel>=5
19
+ Provides-Extra: linux-runtime
20
+ Requires-Dist: dcccpy-linux-runtime==0.1.0; extra == "linux-runtime"
21
+
22
+ # dcccpy
23
+
24
+ `dcccpy` is a Python wrapper for the `DCCCcore` command-line tool from
25
+ DCCCSlicer. It keeps the native C++ core as the execution engine and provides a
26
+ small Python API for running common PET biomarker workflows.
27
+
28
+ ## Install
29
+
30
+ The default package is slim:
31
+
32
+ ```bash
33
+ pip install dcccpy
34
+ ```
35
+
36
+ The first call downloads the matching `DCCCcore` release package into the local
37
+ user cache if no native runtime is otherwise available. The slim package also
38
+ installs `nibabel` for image loading and nibabel-style image inputs.
39
+
40
+ For Linux users who prefer `pip install` to include the native runtime and avoid
41
+ first-run download:
42
+
43
+ ```bash
44
+ pip install "dcccpy[linux-runtime]"
45
+ ```
46
+
47
+ ## Python API
48
+
49
+ ```python
50
+ import dcccpy
51
+
52
+ result = dcccpy.centiloid("amyloid_pet.nii", skip_normalization=True)
53
+ print(result.metrics)
54
+ print(result.output)
55
+ ```
56
+
57
+ The `output` argument is optional for single-image Python calls. When omitted,
58
+ `dcccpy` creates a temporary output NIfTI path and returns it in the result.
59
+ Relative input and output paths are resolved from the current Python working
60
+ directory before `DCCCcore` is invoked.
61
+
62
+ ```python
63
+ result = dcccpy.centiloid("amyloid_pet.nii")
64
+ print(result.output) # temporary output path
65
+ print(result.metrics.get("fbp"))
66
+ ```
67
+
68
+ The wrapper accepts nibabel-style image objects with `to_filename()`:
69
+
70
+ ```python
71
+ import nibabel as nib
72
+ import dcccpy
73
+
74
+ image = nib.load("amyloid_pet.nii.gz")
75
+ result = dcccpy.centiloid(image, skip_normalization=True)
76
+ output_image = result.load_output()
77
+ ```
78
+
79
+ Common helpers mirror `DCCCcore` subcommands:
80
+
81
+ ```python
82
+ dcccpy.centiloid("amyloid.nii", suvr=True)
83
+ dcccpy.centaurz("tau.nii", report_detailed_regions=True)
84
+ dcccpy.fillstates("fdg.nii", tracer="fdg")
85
+ dcccpy.normalize("pet.nii", iterative=True)
86
+ dcccpy.run(["centiloid", "--input", "a.nii", "--output", "b.nii"])
87
+ ```
88
+
89
+ Each helper returns `DCCCResult` with:
90
+
91
+ - `returncode`
92
+ - `stdout` / `stderr`
93
+ - `output`
94
+ - `metrics`, parsed from numeric lines in stdout
95
+ - `load_output()`, which loads the output with nibabel
96
+
97
+ ## Command Line
98
+
99
+ `dcccpy` also forwards raw arguments to `DCCCcore`:
100
+
101
+ ```bash
102
+ dcccpy --help
103
+ dcccpy centiloid --input amyloid_pet.nii --output result.nii
104
+ ```
105
+
106
+ ## Runtime lookup
107
+
108
+ At runtime, `dcccpy` looks for `DCCCcore` in this order:
109
+
110
+ 1. `DCCCPY_DCCCCORE` environment variable.
111
+ 2. A vendored binary inside the installed `dcccpy` wheel.
112
+ 3. A binary from `dcccpy-linux-runtime`, installed by `dcccpy[linux-runtime]`.
113
+ 4. The local dcccpy cache populated by automatic download.
114
+ 5. `DCCCcore` on `PATH`.
115
+ 6. Automatic download from GitHub releases, unless disabled.
116
+
117
+ Useful environment variables:
118
+
119
+ - `DCCCPY_DCCCCORE`: exact path to a `DCCCcore` executable.
120
+ - `DCCCPY_AUTO_DOWNLOAD=0`: disable first-run automatic download.
121
+ - `DCCCPY_CACHE_DIR`: override the runtime cache directory.
122
+ - `DCCCPY_RELEASE_REPO`: override the GitHub release repository.
123
+ - `DCCCPY_DCCCCORE_URL`: override the release asset URL.
124
+
125
+ ## Runtime Packaging
126
+
127
+ Release wheels should vendor the matching `DCCCcore` runtime tree before build:
128
+
129
+ ```bash
130
+ python scripts/vendor_dccccore.py --version 4.2.3 --release-platform ubuntu-latest-x64
131
+ python -m build --wheel
132
+ ```
133
+
134
+ The source tree intentionally does not commit the vendored runtime because it
135
+ contains large ONNX model and NIfTI runtime assets.
136
+
137
+ The preferred distribution layout is:
138
+
139
+ - `dcccpy`: slim Python package with nibabel; downloads runtime on first use.
140
+ - `dcccpy-linux-runtime`: optional Linux runtime wheel.
141
+ - `dcccpy[linux-runtime]`: installs both packages.
142
+
143
+ ## Packaging note
144
+
145
+ The Linux `DCCCcore-4.2.3-ubuntu-latest-x64.zip` release asset contains the
146
+ native executable, `libtbb`, ONNX registration/decoupling models, configuration
147
+ files, and NIfTI template/mask assets. That full runtime is the correct unit to
148
+ vendor for a wheel that works immediately after `pip install dcccpy`.
149
+
150
+ The full Linux runtime wheel is about 167 MB for version 4.2.3, so a public
151
+ PyPI upload may require a file size limit increase unless a future release
152
+ splits a smaller runtime profile from the full `DCCCcore` package.
dcccpy-0.1.2/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # dcccpy
2
+
3
+ `dcccpy` is a Python wrapper for the `DCCCcore` command-line tool from
4
+ DCCCSlicer. It keeps the native C++ core as the execution engine and provides a
5
+ small Python API for running common PET biomarker workflows.
6
+
7
+ ## Install
8
+
9
+ The default package is slim:
10
+
11
+ ```bash
12
+ pip install dcccpy
13
+ ```
14
+
15
+ The first call downloads the matching `DCCCcore` release package into the local
16
+ user cache if no native runtime is otherwise available. The slim package also
17
+ installs `nibabel` for image loading and nibabel-style image inputs.
18
+
19
+ For Linux users who prefer `pip install` to include the native runtime and avoid
20
+ first-run download:
21
+
22
+ ```bash
23
+ pip install "dcccpy[linux-runtime]"
24
+ ```
25
+
26
+ ## Python API
27
+
28
+ ```python
29
+ import dcccpy
30
+
31
+ result = dcccpy.centiloid("amyloid_pet.nii", skip_normalization=True)
32
+ print(result.metrics)
33
+ print(result.output)
34
+ ```
35
+
36
+ The `output` argument is optional for single-image Python calls. When omitted,
37
+ `dcccpy` creates a temporary output NIfTI path and returns it in the result.
38
+ Relative input and output paths are resolved from the current Python working
39
+ directory before `DCCCcore` is invoked.
40
+
41
+ ```python
42
+ result = dcccpy.centiloid("amyloid_pet.nii")
43
+ print(result.output) # temporary output path
44
+ print(result.metrics.get("fbp"))
45
+ ```
46
+
47
+ The wrapper accepts nibabel-style image objects with `to_filename()`:
48
+
49
+ ```python
50
+ import nibabel as nib
51
+ import dcccpy
52
+
53
+ image = nib.load("amyloid_pet.nii.gz")
54
+ result = dcccpy.centiloid(image, skip_normalization=True)
55
+ output_image = result.load_output()
56
+ ```
57
+
58
+ Common helpers mirror `DCCCcore` subcommands:
59
+
60
+ ```python
61
+ dcccpy.centiloid("amyloid.nii", suvr=True)
62
+ dcccpy.centaurz("tau.nii", report_detailed_regions=True)
63
+ dcccpy.fillstates("fdg.nii", tracer="fdg")
64
+ dcccpy.normalize("pet.nii", iterative=True)
65
+ dcccpy.run(["centiloid", "--input", "a.nii", "--output", "b.nii"])
66
+ ```
67
+
68
+ Each helper returns `DCCCResult` with:
69
+
70
+ - `returncode`
71
+ - `stdout` / `stderr`
72
+ - `output`
73
+ - `metrics`, parsed from numeric lines in stdout
74
+ - `load_output()`, which loads the output with nibabel
75
+
76
+ ## Command Line
77
+
78
+ `dcccpy` also forwards raw arguments to `DCCCcore`:
79
+
80
+ ```bash
81
+ dcccpy --help
82
+ dcccpy centiloid --input amyloid_pet.nii --output result.nii
83
+ ```
84
+
85
+ ## Runtime lookup
86
+
87
+ At runtime, `dcccpy` looks for `DCCCcore` in this order:
88
+
89
+ 1. `DCCCPY_DCCCCORE` environment variable.
90
+ 2. A vendored binary inside the installed `dcccpy` wheel.
91
+ 3. A binary from `dcccpy-linux-runtime`, installed by `dcccpy[linux-runtime]`.
92
+ 4. The local dcccpy cache populated by automatic download.
93
+ 5. `DCCCcore` on `PATH`.
94
+ 6. Automatic download from GitHub releases, unless disabled.
95
+
96
+ Useful environment variables:
97
+
98
+ - `DCCCPY_DCCCCORE`: exact path to a `DCCCcore` executable.
99
+ - `DCCCPY_AUTO_DOWNLOAD=0`: disable first-run automatic download.
100
+ - `DCCCPY_CACHE_DIR`: override the runtime cache directory.
101
+ - `DCCCPY_RELEASE_REPO`: override the GitHub release repository.
102
+ - `DCCCPY_DCCCCORE_URL`: override the release asset URL.
103
+
104
+ ## Runtime Packaging
105
+
106
+ Release wheels should vendor the matching `DCCCcore` runtime tree before build:
107
+
108
+ ```bash
109
+ python scripts/vendor_dccccore.py --version 4.2.3 --release-platform ubuntu-latest-x64
110
+ python -m build --wheel
111
+ ```
112
+
113
+ The source tree intentionally does not commit the vendored runtime because it
114
+ contains large ONNX model and NIfTI runtime assets.
115
+
116
+ The preferred distribution layout is:
117
+
118
+ - `dcccpy`: slim Python package with nibabel; downloads runtime on first use.
119
+ - `dcccpy-linux-runtime`: optional Linux runtime wheel.
120
+ - `dcccpy[linux-runtime]`: installs both packages.
121
+
122
+ ## Packaging note
123
+
124
+ The Linux `DCCCcore-4.2.3-ubuntu-latest-x64.zip` release asset contains the
125
+ native executable, `libtbb`, ONNX registration/decoupling models, configuration
126
+ files, and NIfTI template/mask assets. That full runtime is the correct unit to
127
+ vendor for a wheel that works immediately after `pip install dcccpy`.
128
+
129
+ The full Linux runtime wheel is about 167 MB for version 4.2.3, so a public
130
+ PyPI upload may require a file size limit increase unless a future release
131
+ splits a smaller runtime profile from the full `DCCCcore` package.
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "dcccpy"
7
+ version = "0.1.2"
8
+ description = "Python wrapper for the DCCCcore PET biomarker command-line tool"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "CC-BY-NC-ND-4.0"
12
+ authors = [
13
+ { name = "DCCCSlicer contributors" }
14
+ ]
15
+ dependencies = [
16
+ "nibabel>=5",
17
+ ]
18
+ keywords = ["PET", "neuroimaging", "centiloid", "DCCC", "DCCCSlicer"]
19
+ classifiers = [
20
+ "Development Status :: 3 - Alpha",
21
+ "Intended Audience :: Science/Research",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3 :: Only",
24
+ "Topic :: Scientific/Engineering :: Medical Science Apps.",
25
+ ]
26
+
27
+ [project.urls]
28
+ Homepage = "https://github.com/tctco/DCCCSlicer"
29
+ Repository = "https://github.com/tctco/DCCCSlicer"
30
+ Issues = "https://github.com/tctco/DCCCSlicer/issues"
31
+
32
+ [project.optional-dependencies]
33
+ linux-runtime = ["dcccpy-linux-runtime==0.1.0"]
34
+
35
+ [project.scripts]
36
+ dcccpy = "dcccpy.cli:main"
37
+
38
+ [tool.setuptools]
39
+ package-dir = {"" = "src"}
40
+ include-package-data = true
41
+
42
+ [tool.setuptools.packages.find]
43
+ where = ["src"]
44
+
45
+ [tool.setuptools.package-data]
46
+ dcccpy = ["py.typed", "vendor/**/*"]
47
+
48
+ [tool.pytest.ini_options]
49
+ testpaths = ["tests"]
dcccpy-0.1.2/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
dcccpy-0.1.2/setup.py ADDED
@@ -0,0 +1,34 @@
1
+ from pathlib import Path
2
+
3
+ from setuptools import setup
4
+
5
+
6
+ try:
7
+ from wheel.bdist_wheel import bdist_wheel
8
+ except Exception: # pragma: no cover - wheel is provided by build-system.requires
9
+ bdist_wheel = None
10
+
11
+
12
+ if bdist_wheel is not None:
13
+ def has_vendored_runtime() -> bool:
14
+ vendor_root = Path(__file__).resolve().parent / "src" / "dcccpy" / "vendor" / "dccccore"
15
+ return vendor_root.exists() and any(vendor_root.rglob("DCCCcore*"))
16
+
17
+
18
+ class BinaryWheel(bdist_wheel):
19
+ """Mark wheels as platform-specific when vendored DCCCcore is present."""
20
+
21
+ def finalize_options(self):
22
+ super().finalize_options()
23
+ if has_vendored_runtime():
24
+ self.root_is_pure = False
25
+
26
+ def get_tag(self):
27
+ if not has_vendored_runtime():
28
+ return super().get_tag()
29
+ _, _, platform_tag = super().get_tag()
30
+ return "py3", "none", platform_tag
31
+
32
+ setup(cmdclass={"bdist_wheel": BinaryWheel})
33
+ else:
34
+ setup()
@@ -0,0 +1,42 @@
1
+ """Python wrapper for the native DCCCcore executable."""
2
+
3
+ from .core import (
4
+ DCCCResult,
5
+ adad,
6
+ abetaindex,
7
+ abetaload,
8
+ adni_pet_core,
9
+ centaur,
10
+ centaurz,
11
+ centiloid,
12
+ dccccore_path,
13
+ fillstates,
14
+ normalize,
15
+ parse_metrics,
16
+ rigid,
17
+ run,
18
+ suvr,
19
+ )
20
+ from .runtime import DCCCCORE_VERSION, DCCCcoreDownloadError, DCCCcoreNotFoundError, download_dccccore
21
+
22
+ __all__ = [
23
+ "DCCCResult",
24
+ "DCCCCORE_VERSION",
25
+ "DCCCcoreDownloadError",
26
+ "DCCCcoreNotFoundError",
27
+ "adad",
28
+ "abetaindex",
29
+ "abetaload",
30
+ "adni_pet_core",
31
+ "centaur",
32
+ "centaurz",
33
+ "centiloid",
34
+ "dccccore_path",
35
+ "download_dccccore",
36
+ "fillstates",
37
+ "normalize",
38
+ "parse_metrics",
39
+ "rigid",
40
+ "run",
41
+ "suvr",
42
+ ]
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+
5
+ from .core import run
6
+ from .runtime import DCCCcoreDownloadError, DCCCcoreNotFoundError
7
+
8
+
9
+ def main(argv: list[str] | None = None) -> int:
10
+ args = list(sys.argv[1:] if argv is None else argv)
11
+ try:
12
+ result = run(args, check=False)
13
+ except (DCCCcoreDownloadError, DCCCcoreNotFoundError) as exc:
14
+ print(str(exc), file=sys.stderr)
15
+ return 127
16
+
17
+ if result.stdout:
18
+ print(result.stdout, end="")
19
+ if result.stderr:
20
+ print(result.stderr, file=sys.stderr, end="")
21
+ return result.returncode