dcccpy 0.2.0__tar.gz → 0.3.0a2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dcccpy
3
- Version: 0.2.0
3
+ Version: 0.3.0a2
4
4
  Summary: Python wrapper for the DCCCcore PET biomarker command-line tool
5
5
  Author: DCCCSlicer contributors
6
6
  License-Expression: CC-BY-NC-ND-4.0
@@ -17,17 +17,17 @@ Requires-Python: >=3.9
17
17
  Description-Content-Type: text/markdown
18
18
  Requires-Dist: nibabel>=5
19
19
  Provides-Extra: linux-runtime
20
- Requires-Dist: dcccpy-linux-runtime==0.1.2; (sys_platform == "linux" and platform_machine == "x86_64") and extra == "linux-runtime"
21
- Requires-Dist: dcccpy-linux-arm64-runtime==0.1.2; (sys_platform == "linux" and platform_machine == "aarch64") and extra == "linux-runtime"
20
+ Requires-Dist: dcccpy-linux-runtime==0.2.0a1; (sys_platform == "linux" and platform_machine == "x86_64") and extra == "linux-runtime"
21
+ Requires-Dist: dcccpy-linux-arm64-runtime==0.2.0a1; (sys_platform == "linux" and platform_machine == "aarch64") and extra == "linux-runtime"
22
22
  Provides-Extra: windows-runtime
23
- Requires-Dist: dcccpy-windows-runtime==0.1.2; (sys_platform == "win32" and platform_machine == "AMD64") and extra == "windows-runtime"
23
+ Requires-Dist: dcccpy-windows-runtime==0.2.0a1; (sys_platform == "win32" and platform_machine == "AMD64") and extra == "windows-runtime"
24
24
  Provides-Extra: macos-runtime
25
- Requires-Dist: dcccpy-macos-runtime==0.1.2; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "macos-runtime"
25
+ Requires-Dist: dcccpy-macos-runtime==0.2.0a1; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "macos-runtime"
26
26
  Provides-Extra: runtime
27
- Requires-Dist: dcccpy-linux-runtime==0.1.2; (sys_platform == "linux" and platform_machine == "x86_64") and extra == "runtime"
28
- Requires-Dist: dcccpy-linux-arm64-runtime==0.1.2; (sys_platform == "linux" and platform_machine == "aarch64") and extra == "runtime"
29
- Requires-Dist: dcccpy-windows-runtime==0.1.2; (sys_platform == "win32" and platform_machine == "AMD64") and extra == "runtime"
30
- Requires-Dist: dcccpy-macos-runtime==0.1.2; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "runtime"
27
+ Requires-Dist: dcccpy-linux-runtime==0.2.0a1; (sys_platform == "linux" and platform_machine == "x86_64") and extra == "runtime"
28
+ Requires-Dist: dcccpy-linux-arm64-runtime==0.2.0a1; (sys_platform == "linux" and platform_machine == "aarch64") and extra == "runtime"
29
+ Requires-Dist: dcccpy-windows-runtime==0.2.0a1; (sys_platform == "win32" and platform_machine == "AMD64") and extra == "runtime"
30
+ Requires-Dist: dcccpy-macos-runtime==0.2.0a1; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "runtime"
31
31
 
32
32
  # dcccpy
33
33
 
@@ -138,6 +138,23 @@ dcccpy centiloid --input amyloid_pet.nii --output result.nii
138
138
  dcccpy adni-pet-core --input fdg.nii --output fdg_adni.nii --tracer fdg
139
139
  ```
140
140
 
141
+ The Python helper accepts the same staged exports. Pass one integer or a
142
+ sequence; only the requested stages are saved:
143
+
144
+ ```python
145
+ dcccpy.adni_pet_core(
146
+ "dynamic_pet.nii.gz",
147
+ "standardized.nii.gz",
148
+ tracer="fdg",
149
+ level=(1, 3),
150
+ )
151
+ ```
152
+
153
+ Level 1 is the motion-corrected dynamic PET, Level 2 is its 3D average, and
154
+ Level 3 is the standardized ADNI-style image. The output argument names the
155
+ highest selected level, while selected lower levels receive `_Coreg` or
156
+ `_Coreg_Avg` suffixes.
157
+
141
158
  `adni_pet_core` deliberately has no default tracer. Use `abeta`, `tau`, or
142
159
  `fdg`; FDG selects ADNI's iterative masked global-mean normalization, while
143
160
  Aβ and tau retain cerebellar gray normalization.
@@ -189,7 +206,7 @@ the calculation again.
189
206
  Release wheels should vendor the matching `DCCCcore` runtime tree before build:
190
207
 
191
208
  ```bash
192
- python scripts/vendor_dccccore.py --version 4.4.0 --release-platform ubuntu-latest-x64
209
+ python scripts/vendor_dccccore.py --version 4.5.0-alpha --release-platform ubuntu-latest-x64
193
210
  python -m build --wheel
194
211
  ```
195
212
 
@@ -197,7 +214,7 @@ The Linux ARM64 runtime package uses the corresponding release asset:
197
214
 
198
215
  ```bash
199
216
  cd python/dcccpy-linux-arm64-runtime
200
- python scripts/vendor_dccccore.py --version 4.4.0 --release-platform ubuntu-latest-arm64
217
+ python scripts/vendor_dccccore.py --version 4.5.0-alpha --release-platform ubuntu-latest-arm64
201
218
  python -m build --wheel
202
219
  ```
203
220
 
@@ -215,11 +232,11 @@ The preferred distribution layout is:
215
232
 
216
233
  ## Packaging note
217
234
 
218
- The runtime wheels use a PyPI-size profile for DCCCcore version 4.4.0. They omit the
235
+ The current optional runtime wheels use a PyPI-size profile for DCCCcore version 4.5.0-alpha. They omit the
219
236
  `fast_and_acc` registration model/config and the ADAD decoupler ONNX ensemble,
220
237
  while keeping the default spatial normalization model and assets needed by
221
238
  common Centiloid/CenTauR/CenTauRz workflows.
222
239
 
223
- The plain `dcccpy` package remains slim and downloads the full matching
224
- `DCCCcore` release package from GitHub on first use when no installed runtime is
225
- available.
240
+ Each runtime package declares its bundled DCCCcore version. The wrapper ignores
241
+ an installed runtime whose native version does not match, preventing an older
242
+ runtime package from shadowing the requested release.
@@ -107,6 +107,23 @@ dcccpy centiloid --input amyloid_pet.nii --output result.nii
107
107
  dcccpy adni-pet-core --input fdg.nii --output fdg_adni.nii --tracer fdg
108
108
  ```
109
109
 
110
+ The Python helper accepts the same staged exports. Pass one integer or a
111
+ sequence; only the requested stages are saved:
112
+
113
+ ```python
114
+ dcccpy.adni_pet_core(
115
+ "dynamic_pet.nii.gz",
116
+ "standardized.nii.gz",
117
+ tracer="fdg",
118
+ level=(1, 3),
119
+ )
120
+ ```
121
+
122
+ Level 1 is the motion-corrected dynamic PET, Level 2 is its 3D average, and
123
+ Level 3 is the standardized ADNI-style image. The output argument names the
124
+ highest selected level, while selected lower levels receive `_Coreg` or
125
+ `_Coreg_Avg` suffixes.
126
+
110
127
  `adni_pet_core` deliberately has no default tracer. Use `abeta`, `tau`, or
111
128
  `fdg`; FDG selects ADNI's iterative masked global-mean normalization, while
112
129
  Aβ and tau retain cerebellar gray normalization.
@@ -158,7 +175,7 @@ the calculation again.
158
175
  Release wheels should vendor the matching `DCCCcore` runtime tree before build:
159
176
 
160
177
  ```bash
161
- python scripts/vendor_dccccore.py --version 4.4.0 --release-platform ubuntu-latest-x64
178
+ python scripts/vendor_dccccore.py --version 4.5.0-alpha --release-platform ubuntu-latest-x64
162
179
  python -m build --wheel
163
180
  ```
164
181
 
@@ -166,7 +183,7 @@ The Linux ARM64 runtime package uses the corresponding release asset:
166
183
 
167
184
  ```bash
168
185
  cd python/dcccpy-linux-arm64-runtime
169
- python scripts/vendor_dccccore.py --version 4.4.0 --release-platform ubuntu-latest-arm64
186
+ python scripts/vendor_dccccore.py --version 4.5.0-alpha --release-platform ubuntu-latest-arm64
170
187
  python -m build --wheel
171
188
  ```
172
189
 
@@ -184,11 +201,11 @@ The preferred distribution layout is:
184
201
 
185
202
  ## Packaging note
186
203
 
187
- The runtime wheels use a PyPI-size profile for DCCCcore version 4.4.0. They omit the
204
+ The current optional runtime wheels use a PyPI-size profile for DCCCcore version 4.5.0-alpha. They omit the
188
205
  `fast_and_acc` registration model/config and the ADAD decoupler ONNX ensemble,
189
206
  while keeping the default spatial normalization model and assets needed by
190
207
  common Centiloid/CenTauR/CenTauRz workflows.
191
208
 
192
- The plain `dcccpy` package remains slim and downloads the full matching
193
- `DCCCcore` release package from GitHub on first use when no installed runtime is
194
- available.
209
+ Each runtime package declares its bundled DCCCcore version. The wrapper ignores
210
+ an installed runtime whose native version does not match, preventing an older
211
+ runtime package from shadowing the requested release.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dcccpy"
7
- version = "0.2.0"
7
+ version = "0.3.0a2"
8
8
  description = "Python wrapper for the DCCCcore PET biomarker command-line tool"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -31,16 +31,16 @@ Issues = "https://github.com/tctco/DCCCSlicer/issues"
31
31
 
32
32
  [project.optional-dependencies]
33
33
  linux-runtime = [
34
- "dcccpy-linux-runtime==0.1.2; sys_platform == 'linux' and platform_machine == 'x86_64'",
35
- "dcccpy-linux-arm64-runtime==0.1.2; sys_platform == 'linux' and platform_machine == 'aarch64'",
34
+ "dcccpy-linux-runtime==0.2.0a1; sys_platform == 'linux' and platform_machine == 'x86_64'",
35
+ "dcccpy-linux-arm64-runtime==0.2.0a1; sys_platform == 'linux' and platform_machine == 'aarch64'",
36
36
  ]
37
- windows-runtime = ["dcccpy-windows-runtime==0.1.2; sys_platform == 'win32' and platform_machine == 'AMD64'"]
38
- macos-runtime = ["dcccpy-macos-runtime==0.1.2; sys_platform == 'darwin' and platform_machine == 'arm64'"]
37
+ windows-runtime = ["dcccpy-windows-runtime==0.2.0a1; sys_platform == 'win32' and platform_machine == 'AMD64'"]
38
+ macos-runtime = ["dcccpy-macos-runtime==0.2.0a1; sys_platform == 'darwin' and platform_machine == 'arm64'"]
39
39
  runtime = [
40
- "dcccpy-linux-runtime==0.1.2; sys_platform == 'linux' and platform_machine == 'x86_64'",
41
- "dcccpy-linux-arm64-runtime==0.1.2; sys_platform == 'linux' and platform_machine == 'aarch64'",
42
- "dcccpy-windows-runtime==0.1.2; sys_platform == 'win32' and platform_machine == 'AMD64'",
43
- "dcccpy-macos-runtime==0.1.2; sys_platform == 'darwin' and platform_machine == 'arm64'",
40
+ "dcccpy-linux-runtime==0.2.0a1; sys_platform == 'linux' and platform_machine == 'x86_64'",
41
+ "dcccpy-linux-arm64-runtime==0.2.0a1; sys_platform == 'linux' and platform_machine == 'aarch64'",
42
+ "dcccpy-windows-runtime==0.2.0a1; sys_platform == 'win32' and platform_machine == 'AMD64'",
43
+ "dcccpy-macos-runtime==0.2.0a1; sys_platform == 'darwin' and platform_machine == 'arm64'",
44
44
  ]
45
45
 
46
46
  [project.scripts]
@@ -411,12 +411,23 @@ def adni_pet_core(
411
411
  output: str | os.PathLike[str] | None = None,
412
412
  *,
413
413
  tracer: str,
414
+ level: int | Sequence[int] = 3,
414
415
  **kwargs: object,
415
416
  ) -> DCCCResult:
416
- """Run tracer-specific ADNI PET Core preprocessing."""
417
+ """Run tracer-specific ADNI PET Core preprocessing.
418
+
419
+ ``level`` accepts one level or a sequence: 1 exports Coreg, 2 exports
420
+ Coreg/Avg, and 3 exports the standardized image. Multiple levels produce
421
+ multiple files while ``output`` identifies the deepest requested level.
422
+ """
417
423
 
418
424
  extra_args = list(kwargs.pop("extra_args", ()))
419
425
  extra_args.extend(["--tracer", tracer])
426
+ levels = (level,) if isinstance(level, int) else tuple(level)
427
+ if not levels or any(value not in (1, 2, 3) for value in levels):
428
+ raise ValueError("level must contain one or more of: 1, 2, 3")
429
+ if levels != (3,):
430
+ extra_args.extend(["--level", *(str(value) for value in levels)])
420
431
  return _spatial_command("adni-pet-core", input, output, extra_args=extra_args, **kwargs)
421
432
 
422
433
 
@@ -12,7 +12,7 @@ from pathlib import Path
12
12
  from typing import Iterable
13
13
 
14
14
 
15
- DCCCCORE_VERSION = "4.4.0"
15
+ DCCCCORE_VERSION = "4.5.0-alpha"
16
16
  RELEASE_REPO = "tctco/DCCCSlicer"
17
17
 
18
18
 
@@ -99,35 +99,39 @@ def _main_package_vendor_dirs() -> list[Path]:
99
99
  return [vendor_root / key, vendor_root]
100
100
 
101
101
 
102
- def _runtime_package_dirs() -> list[Path]:
102
+ def _runtime_package_dirs(version: str = DCCCCORE_VERSION) -> list[Path]:
103
103
  roots: list[Path] = []
104
104
  try:
105
105
  import dcccpy_linux_runtime
106
106
  except Exception:
107
107
  pass
108
108
  else:
109
- roots.append(Path(dcccpy_linux_runtime.dccccore_root()))
109
+ if getattr(dcccpy_linux_runtime, "DCCCCORE_VERSION", None) == version:
110
+ roots.append(Path(dcccpy_linux_runtime.dccccore_root()))
110
111
 
111
112
  try:
112
113
  import dcccpy_linux_arm64_runtime
113
114
  except Exception:
114
115
  pass
115
116
  else:
116
- roots.append(Path(dcccpy_linux_arm64_runtime.dccccore_root()))
117
+ if getattr(dcccpy_linux_arm64_runtime, "DCCCCORE_VERSION", None) == version:
118
+ roots.append(Path(dcccpy_linux_arm64_runtime.dccccore_root()))
117
119
 
118
120
  try:
119
121
  import dcccpy_windows_runtime
120
122
  except Exception:
121
123
  pass
122
124
  else:
123
- roots.append(Path(dcccpy_windows_runtime.dccccore_root()))
125
+ if getattr(dcccpy_windows_runtime, "DCCCCORE_VERSION", None) == version:
126
+ roots.append(Path(dcccpy_windows_runtime.dccccore_root()))
124
127
 
125
128
  try:
126
129
  import dcccpy_macos_runtime
127
130
  except Exception:
128
131
  pass
129
132
  else:
130
- roots.append(Path(dcccpy_macos_runtime.dccccore_root()))
133
+ if getattr(dcccpy_macos_runtime, "DCCCCORE_VERSION", None) == version:
134
+ roots.append(Path(dcccpy_macos_runtime.dccccore_root()))
131
135
 
132
136
  return roots
133
137
 
@@ -141,7 +145,7 @@ def find_existing_dccccore(version: str = DCCCCORE_VERSION) -> Path | None:
141
145
  if candidate.exists():
142
146
  return candidate
143
147
 
144
- for candidate in candidate_executables(_runtime_package_dirs()):
148
+ for candidate in candidate_executables(_runtime_package_dirs(version)):
145
149
  if candidate.exists():
146
150
  return candidate
147
151
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dcccpy
3
- Version: 0.2.0
3
+ Version: 0.3.0a2
4
4
  Summary: Python wrapper for the DCCCcore PET biomarker command-line tool
5
5
  Author: DCCCSlicer contributors
6
6
  License-Expression: CC-BY-NC-ND-4.0
@@ -17,17 +17,17 @@ Requires-Python: >=3.9
17
17
  Description-Content-Type: text/markdown
18
18
  Requires-Dist: nibabel>=5
19
19
  Provides-Extra: linux-runtime
20
- Requires-Dist: dcccpy-linux-runtime==0.1.2; (sys_platform == "linux" and platform_machine == "x86_64") and extra == "linux-runtime"
21
- Requires-Dist: dcccpy-linux-arm64-runtime==0.1.2; (sys_platform == "linux" and platform_machine == "aarch64") and extra == "linux-runtime"
20
+ Requires-Dist: dcccpy-linux-runtime==0.2.0a1; (sys_platform == "linux" and platform_machine == "x86_64") and extra == "linux-runtime"
21
+ Requires-Dist: dcccpy-linux-arm64-runtime==0.2.0a1; (sys_platform == "linux" and platform_machine == "aarch64") and extra == "linux-runtime"
22
22
  Provides-Extra: windows-runtime
23
- Requires-Dist: dcccpy-windows-runtime==0.1.2; (sys_platform == "win32" and platform_machine == "AMD64") and extra == "windows-runtime"
23
+ Requires-Dist: dcccpy-windows-runtime==0.2.0a1; (sys_platform == "win32" and platform_machine == "AMD64") and extra == "windows-runtime"
24
24
  Provides-Extra: macos-runtime
25
- Requires-Dist: dcccpy-macos-runtime==0.1.2; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "macos-runtime"
25
+ Requires-Dist: dcccpy-macos-runtime==0.2.0a1; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "macos-runtime"
26
26
  Provides-Extra: runtime
27
- Requires-Dist: dcccpy-linux-runtime==0.1.2; (sys_platform == "linux" and platform_machine == "x86_64") and extra == "runtime"
28
- Requires-Dist: dcccpy-linux-arm64-runtime==0.1.2; (sys_platform == "linux" and platform_machine == "aarch64") and extra == "runtime"
29
- Requires-Dist: dcccpy-windows-runtime==0.1.2; (sys_platform == "win32" and platform_machine == "AMD64") and extra == "runtime"
30
- Requires-Dist: dcccpy-macos-runtime==0.1.2; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "runtime"
27
+ Requires-Dist: dcccpy-linux-runtime==0.2.0a1; (sys_platform == "linux" and platform_machine == "x86_64") and extra == "runtime"
28
+ Requires-Dist: dcccpy-linux-arm64-runtime==0.2.0a1; (sys_platform == "linux" and platform_machine == "aarch64") and extra == "runtime"
29
+ Requires-Dist: dcccpy-windows-runtime==0.2.0a1; (sys_platform == "win32" and platform_machine == "AMD64") and extra == "runtime"
30
+ Requires-Dist: dcccpy-macos-runtime==0.2.0a1; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "runtime"
31
31
 
32
32
  # dcccpy
33
33
 
@@ -138,6 +138,23 @@ dcccpy centiloid --input amyloid_pet.nii --output result.nii
138
138
  dcccpy adni-pet-core --input fdg.nii --output fdg_adni.nii --tracer fdg
139
139
  ```
140
140
 
141
+ The Python helper accepts the same staged exports. Pass one integer or a
142
+ sequence; only the requested stages are saved:
143
+
144
+ ```python
145
+ dcccpy.adni_pet_core(
146
+ "dynamic_pet.nii.gz",
147
+ "standardized.nii.gz",
148
+ tracer="fdg",
149
+ level=(1, 3),
150
+ )
151
+ ```
152
+
153
+ Level 1 is the motion-corrected dynamic PET, Level 2 is its 3D average, and
154
+ Level 3 is the standardized ADNI-style image. The output argument names the
155
+ highest selected level, while selected lower levels receive `_Coreg` or
156
+ `_Coreg_Avg` suffixes.
157
+
141
158
  `adni_pet_core` deliberately has no default tracer. Use `abeta`, `tau`, or
142
159
  `fdg`; FDG selects ADNI's iterative masked global-mean normalization, while
143
160
  Aβ and tau retain cerebellar gray normalization.
@@ -189,7 +206,7 @@ the calculation again.
189
206
  Release wheels should vendor the matching `DCCCcore` runtime tree before build:
190
207
 
191
208
  ```bash
192
- python scripts/vendor_dccccore.py --version 4.4.0 --release-platform ubuntu-latest-x64
209
+ python scripts/vendor_dccccore.py --version 4.5.0-alpha --release-platform ubuntu-latest-x64
193
210
  python -m build --wheel
194
211
  ```
195
212
 
@@ -197,7 +214,7 @@ The Linux ARM64 runtime package uses the corresponding release asset:
197
214
 
198
215
  ```bash
199
216
  cd python/dcccpy-linux-arm64-runtime
200
- python scripts/vendor_dccccore.py --version 4.4.0 --release-platform ubuntu-latest-arm64
217
+ python scripts/vendor_dccccore.py --version 4.5.0-alpha --release-platform ubuntu-latest-arm64
201
218
  python -m build --wheel
202
219
  ```
203
220
 
@@ -215,11 +232,11 @@ The preferred distribution layout is:
215
232
 
216
233
  ## Packaging note
217
234
 
218
- The runtime wheels use a PyPI-size profile for DCCCcore version 4.4.0. They omit the
235
+ The current optional runtime wheels use a PyPI-size profile for DCCCcore version 4.5.0-alpha. They omit the
219
236
  `fast_and_acc` registration model/config and the ADAD decoupler ONNX ensemble,
220
237
  while keeping the default spatial normalization model and assets needed by
221
238
  common Centiloid/CenTauR/CenTauRz workflows.
222
239
 
223
- The plain `dcccpy` package remains slim and downloads the full matching
224
- `DCCCcore` release package from GitHub on first use when no installed runtime is
225
- available.
240
+ Each runtime package declares its bundled DCCCcore version. The wrapper ignores
241
+ an installed runtime whose native version does not match, preventing an older
242
+ runtime package from shadowing the requested release.
@@ -3,31 +3,31 @@ nibabel>=5
3
3
  [linux-runtime]
4
4
 
5
5
  [linux-runtime:sys_platform == "linux" and platform_machine == "aarch64"]
6
- dcccpy-linux-arm64-runtime==0.1.2
6
+ dcccpy-linux-arm64-runtime==0.2.0a1
7
7
 
8
8
  [linux-runtime:sys_platform == "linux" and platform_machine == "x86_64"]
9
- dcccpy-linux-runtime==0.1.2
9
+ dcccpy-linux-runtime==0.2.0a1
10
10
 
11
11
  [macos-runtime]
12
12
 
13
13
  [macos-runtime:sys_platform == "darwin" and platform_machine == "arm64"]
14
- dcccpy-macos-runtime==0.1.2
14
+ dcccpy-macos-runtime==0.2.0a1
15
15
 
16
16
  [runtime]
17
17
 
18
18
  [runtime:sys_platform == "darwin" and platform_machine == "arm64"]
19
- dcccpy-macos-runtime==0.1.2
19
+ dcccpy-macos-runtime==0.2.0a1
20
20
 
21
21
  [runtime:sys_platform == "linux" and platform_machine == "aarch64"]
22
- dcccpy-linux-arm64-runtime==0.1.2
22
+ dcccpy-linux-arm64-runtime==0.2.0a1
23
23
 
24
24
  [runtime:sys_platform == "linux" and platform_machine == "x86_64"]
25
- dcccpy-linux-runtime==0.1.2
25
+ dcccpy-linux-runtime==0.2.0a1
26
26
 
27
27
  [runtime:sys_platform == "win32" and platform_machine == "AMD64"]
28
- dcccpy-windows-runtime==0.1.2
28
+ dcccpy-windows-runtime==0.2.0a1
29
29
 
30
30
  [windows-runtime]
31
31
 
32
32
  [windows-runtime:sys_platform == "win32" and platform_machine == "AMD64"]
33
- dcccpy-windows-runtime==0.1.2
33
+ dcccpy-windows-runtime==0.2.0a1
@@ -142,7 +142,7 @@ def test_dccccore_path_can_disable_auto_download(tmp_path: Path, monkeypatch: py
142
142
 
143
143
 
144
144
  def test_dccccore_path_auto_downloads_to_cache(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
145
- asset_root = tmp_path / "asset" / "DCCCcore-4.4.0-ubuntu-latest-x64"
145
+ asset_root = tmp_path / "asset" / "DCCCcore-4.5.0-alpha-ubuntu-latest-x64"
146
146
  asset_root.mkdir(parents=True)
147
147
  exe = asset_root / "DCCCcore"
148
148
  exe.write_text("#!/usr/bin/env sh\nprintf 'fake dccccore\\n'\n")
@@ -150,7 +150,7 @@ def test_dccccore_path_auto_downloads_to_cache(tmp_path: Path, monkeypatch: pyte
150
150
 
151
151
  archive = tmp_path / "DCCCcore.zip"
152
152
  with zipfile.ZipFile(archive, "w") as zf:
153
- zf.write(exe, "DCCCcore-4.4.0-ubuntu-latest-x64/DCCCcore")
153
+ zf.write(exe, "DCCCcore-4.5.0-alpha-ubuntu-latest-x64/DCCCcore")
154
154
 
155
155
  monkeypatch.delenv("DCCCPY_DCCCCORE", raising=False)
156
156
  monkeypatch.setenv("DCCCPY_AUTO_DOWNLOAD", "1")
@@ -175,7 +175,7 @@ def test_find_existing_dccccore_checks_macos_runtime_package(
175
175
  exe.write_text("#!/usr/bin/env sh\n")
176
176
  exe.chmod(0o755)
177
177
 
178
- module = types.SimpleNamespace(dccccore_root=lambda: root)
178
+ module = types.SimpleNamespace(DCCCCORE_VERSION="4.5.0-alpha", dccccore_root=lambda: root)
179
179
  monkeypatch.setitem(sys.modules, "dcccpy_macos_runtime", module)
180
180
  monkeypatch.setenv("PATH", str(tmp_path / "empty-path"))
181
181
 
@@ -186,13 +186,30 @@ def test_linux_arm64_release_platform() -> None:
186
186
  assert release_platform("linux-arm64") == "ubuntu-latest-arm64"
187
187
 
188
188
 
189
- def test_default_release_targets_dccccore_440() -> None:
190
- assert DCCCCORE_VERSION == "4.4.0"
189
+ def test_default_release_targets_dccccore_450_alpha() -> None:
190
+ assert DCCCCORE_VERSION == "4.5.0-alpha"
191
191
  assert release_url(platform_name="ubuntu-latest-x64").endswith(
192
- "/releases/download/v4.4.0/DCCCcore-4.4.0-ubuntu-latest-x64.zip"
192
+ "/releases/download/v4.5.0-alpha/DCCCcore-4.5.0-alpha-ubuntu-latest-x64.zip"
193
193
  )
194
194
 
195
195
 
196
+ def test_alpha_ignores_incompatible_stable_runtime_package(
197
+ tmp_path: Path,
198
+ monkeypatch: pytest.MonkeyPatch,
199
+ ) -> None:
200
+ root = tmp_path / "stable-runtime"
201
+ root.mkdir()
202
+ exe = root / "DCCCcore"
203
+ exe.write_text("#!/usr/bin/env sh\n")
204
+ exe.chmod(0o755)
205
+
206
+ module = types.SimpleNamespace(DCCCCORE_VERSION="4.4.0", dccccore_root=lambda: root)
207
+ monkeypatch.setitem(sys.modules, "dcccpy_linux_runtime", module)
208
+ monkeypatch.setenv("PATH", str(tmp_path / "empty-path"))
209
+
210
+ assert find_existing_dccccore() is None
211
+
212
+
196
213
  def test_find_existing_dccccore_checks_linux_arm64_runtime_package(
197
214
  tmp_path: Path,
198
215
  monkeypatch: pytest.MonkeyPatch,
@@ -203,7 +220,7 @@ def test_find_existing_dccccore_checks_linux_arm64_runtime_package(
203
220
  exe.write_text("#!/usr/bin/env sh\n")
204
221
  exe.chmod(0o755)
205
222
 
206
- module = types.SimpleNamespace(dccccore_root=lambda: root)
223
+ module = types.SimpleNamespace(DCCCCORE_VERSION="4.5.0-alpha", dccccore_root=lambda: root)
207
224
  monkeypatch.setitem(sys.modules, "dcccpy_linux_arm64_runtime", module)
208
225
  monkeypatch.setenv("PATH", str(tmp_path / "empty-path"))
209
226
 
@@ -293,6 +310,43 @@ def test_adni_pet_core_python_api_has_no_default_tracer() -> None:
293
310
  dcccpy.adni_pet_core("pet.nii")
294
311
 
295
312
 
313
+ def test_adni_pet_core_forwards_combined_export_levels(
314
+ tmp_path: Path,
315
+ monkeypatch: pytest.MonkeyPatch,
316
+ ) -> None:
317
+ fake_args = tmp_path / "args.txt"
318
+ fake_exe = make_fake_dccccore(tmp_path)
319
+ input_path = tmp_path / "pet.nii"
320
+ output_path = tmp_path / "adni.nii"
321
+ input_path.write_text("fake PET")
322
+ monkeypatch.setenv("DCCCPY_DCCCCORE", str(fake_exe))
323
+ monkeypatch.setenv("DCCCPY_FAKE_ARGS", str(fake_args))
324
+
325
+ result = dcccpy.adni_pet_core(
326
+ input_path, output_path, tracer="fdg", level=(1, 2)
327
+ )
328
+
329
+ assert result.returncode == 0
330
+ assert fake_args.read_text().splitlines() == [
331
+ "adni-pet-core",
332
+ "--input",
333
+ str(input_path),
334
+ "--output",
335
+ str(output_path),
336
+ "--tracer",
337
+ "fdg",
338
+ "--level",
339
+ "1",
340
+ "2",
341
+ ]
342
+
343
+
344
+ @pytest.mark.parametrize("level", [(), 0, 4, (1, 4)])
345
+ def test_adni_pet_core_rejects_invalid_export_levels(level: object) -> None:
346
+ with pytest.raises(ValueError, match="level must contain"):
347
+ dcccpy.adni_pet_core("pet.nii", tracer="fdg", level=level) # type: ignore[arg-type]
348
+
349
+
296
350
  def test_run_adds_macos_security_hint_for_blocked_runtime(
297
351
  tmp_path: Path,
298
352
  monkeypatch: pytest.MonkeyPatch,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes