cmpl 0.2.2__tar.gz → 0.2.3__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.
- {cmpl-0.2.2/src/cmpl.egg-info → cmpl-0.2.3}/PKG-INFO +234 -134
- {cmpl-0.2.2 → cmpl-0.2.3}/README.md +234 -134
- {cmpl-0.2.2 → cmpl-0.2.3}/pyproject.toml +3 -1
- cmpl-0.2.3/src/cmpl/cli/__init__.py +3 -0
- cmpl-0.2.3/src/cmpl/cli/dicom_to_nifti.py +113 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/dicom/enhanced_dicom.py +205 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/utilities/io.py +745 -23
- {cmpl-0.2.2 → cmpl-0.2.3/src/cmpl.egg-info}/PKG-INFO +234 -134
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl.egg-info/SOURCES.txt +3 -0
- cmpl-0.2.3/src/cmpl.egg-info/entry_points.txt +2 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/LICENSE +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/setup.cfg +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/__init__.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/_version.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/dicom/__init__.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/dicom/geometry.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/dicom/metadata.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/quantitative_MRI/__init__.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/quantitative_MRI/mapping.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/reconstruction/__init__.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/reconstruction/grappa/__init__.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/reconstruction/grappa/grappa_1D.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/reconstruction/grappa/grappa_2D.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/reconstruction/grappa/utils.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/reconstruction/sense/__init__.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/reconstruction/sense/cg.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/segmentation/MRISegmentationTool.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/segmentation/__init__.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/segmentation/tools.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/utilities/__init__.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/utilities/df_build.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/utilities/numerical.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/utilities/utils.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/visualization/__init__.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl/visualization/visualization.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl.egg-info/dependency_links.txt +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl.egg-info/requires.txt +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/src/cmpl.egg-info/top_level.txt +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/tests/test_data.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/tests/test_installation.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/tests/test_io.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/tests/test_qmr.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/tests/test_reconstruction.py +0 -0
- {cmpl-0.2.2 → cmpl-0.2.3}/tests/test_visualization.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cmpl
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: CMRR MRI Processing Libraries
|
|
5
5
|
Author: Eisa Hedayati
|
|
6
6
|
License: Copyright (c) 2025 Eisa Hedayati
|
|
@@ -71,23 +71,31 @@ Dynamic: license-file
|
|
|
71
71
|
|
|
72
72
|
# CMPL — CMRR MRI Processing Libraries
|
|
73
73
|
|
|
74
|
-
[](https://pypi.org/project/cmpl/)
|
|
75
|
-
[](https://pypi.org/project/cmpl/)
|
|
74
|
+
[](https://pypi.org/project/cmpl/)
|
|
75
|
+
[](https://pypi.org/project/cmpl/)
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
PyPI: https://pypi.org/project/cmpl/
|
|
78
|
+
|
|
79
|
+
GitHub: https://github.com/ehedayati/cmpl
|
|
80
|
+
|
|
81
|
+
CMPL is a Python package for MRI processing workflows developed at CMRR. It provides tools for MRI reconstruction, quantitative MRI, visualization, DICOM/NIfTI conversion and I/O, and supporting numerical and data utilities.
|
|
78
82
|
|
|
79
83
|
CMPL is organized as a modular library: the base installation stays lightweight, while larger or domain-specific dependencies are installed only when the corresponding functionality is needed.
|
|
80
84
|
|
|
81
85
|
## Highlights
|
|
82
86
|
|
|
87
|
+
- Direct, geometry-aware conventional and Enhanced DICOM to NIfTI conversion with JSON metadata sidecars
|
|
88
|
+
- Multi-echo DICOM support, including 4D NIfTI output ordered by echo time
|
|
89
|
+
- Packaged `cmpl-dicom-to-nifti` command-line converter
|
|
90
|
+
- DICOM geometry and acquisition-metadata utilities
|
|
83
91
|
- Parallel MRI reconstruction with 1D/2D GRAPPA and conjugate-gradient SENSE
|
|
84
92
|
- Quantitative MRI tools for T2* fitting, signal reconstruction, and fitting-error analysis
|
|
85
|
-
- MRI visualization utilities for 2D comparisons
|
|
86
|
-
-
|
|
93
|
+
- MRI visualization utilities for 2D comparisons and 3D volume browsing
|
|
94
|
+
- Conventional and Enhanced DICOM, NIfTI, HDF5, and SimpleITK utilities
|
|
87
95
|
- Lightweight numerical utilities shared across CMPL
|
|
88
96
|
- Optional pandas-based indexing for CMPL-style medical-data directory structures
|
|
89
97
|
- Lazy package imports so `import cmpl` does not eagerly load large optional dependencies
|
|
90
|
-
-
|
|
98
|
+
- Convenient aliases such as `cmpl.recon`, `cmpl.qmr`, `cmpl.vis`, and `cmpl.io`
|
|
91
99
|
|
|
92
100
|
## Requirements
|
|
93
101
|
|
|
@@ -149,144 +157,192 @@ CMPL exposes convenient aliases for commonly used subpackages:
|
|
|
149
157
|
cmpl.recon # reconstruction
|
|
150
158
|
cmpl.qmr # quantitative MRI
|
|
151
159
|
cmpl.vis # visualization
|
|
152
|
-
cmpl.utils # utilities
|
|
153
160
|
cmpl.io # I/O utilities
|
|
161
|
+
cmpl.dicom # DICOM metadata and geometry utilities
|
|
162
|
+
cmpl.utils # utilities
|
|
154
163
|
```
|
|
155
164
|
|
|
156
165
|
The aliases are resolved lazily, so importing CMPL itself does not require every optional dependency to be loaded.
|
|
157
166
|
|
|
158
|
-
##
|
|
167
|
+
## DICOM and NIfTI I/O
|
|
159
168
|
|
|
160
|
-
Install the
|
|
169
|
+
Install the I/O extra:
|
|
161
170
|
|
|
162
171
|
```bash
|
|
163
|
-
python -m pip install "cmpl[
|
|
172
|
+
python -m pip install "cmpl[io]"
|
|
164
173
|
```
|
|
165
174
|
|
|
166
|
-
###
|
|
175
|
+
### Convert a DICOM series directly to NIfTI
|
|
176
|
+
|
|
177
|
+
CMPL includes direct DICOM-series to NIfTI conversion for both conventional and Enhanced DICOM. The converter detects the DICOM representation automatically, preserves spatial geometry, supports single- and multi-echo acquisitions, writes the NIfTI image, and creates a matching JSON sidecar containing acquisition metadata and source geometry.
|
|
167
178
|
|
|
168
179
|
```python
|
|
169
|
-
|
|
180
|
+
import cmpl
|
|
170
181
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
alpha=0.5,
|
|
175
|
-
direction="sagittal",
|
|
176
|
-
cmap="gray",
|
|
177
|
-
vmin=0,
|
|
178
|
-
vmax=1,
|
|
179
|
-
dpi=300,
|
|
182
|
+
metadata = cmpl.io.dicom_to_nifti(
|
|
183
|
+
"/path/to/dicom_series",
|
|
184
|
+
"output.nii.gz",
|
|
180
185
|
)
|
|
181
186
|
```
|
|
182
187
|
|
|
183
|
-
|
|
188
|
+
This creates:
|
|
184
189
|
|
|
190
|
+
```text
|
|
191
|
+
output.nii.gz
|
|
192
|
+
output.json
|
|
193
|
+
```
|
|
185
194
|
|
|
186
|
-
|
|
195
|
+
If the output path does not end in `.nii` or `.nii.gz`, CMPL appends `.nii.gz` automatically.
|
|
187
196
|
|
|
188
|
-
|
|
189
|
-
from cmpl.visualization import side_by_side_view
|
|
197
|
+
For a single echo, the output is a 3D image. When multiple echoes are present, CMPL groups volumes by DICOM `EchoTime`, orders them by echo time, and writes a 4D NIfTI image.
|
|
190
198
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
199
|
+
The JSON sidecar includes:
|
|
200
|
+
|
|
201
|
+
- selected acquisition metadata
|
|
202
|
+
- echo time or echo times in milliseconds
|
|
203
|
+
- original DICOM slice-plane geometry in LPS coordinates
|
|
204
|
+
- the SimpleITK image size, origin, spacing, and direction used for conversion
|
|
205
|
+
|
|
206
|
+
The returned value is the same metadata dictionary written to the JSON sidecar.
|
|
207
|
+
|
|
208
|
+
If a directory contains multiple DICOM series, a specific `SeriesInstanceUID` can be selected:
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
metadata = cmpl.io.dicom_to_nifti(
|
|
212
|
+
"/path/to/dicom_directory",
|
|
213
|
+
"output.nii.gz",
|
|
214
|
+
series_id="1.2.840...",
|
|
196
215
|
)
|
|
197
216
|
```
|
|
198
217
|
|
|
199
|
-
###
|
|
218
|
+
### Command-line DICOM conversion
|
|
200
219
|
|
|
201
|
-
|
|
202
|
-
from cmpl.visualization import visualize_segmentation_slice
|
|
220
|
+
Installing the I/O extra also installs the `cmpl-dicom-to-nifti` command:
|
|
203
221
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
segmentation,
|
|
207
|
-
slice_number=20,
|
|
208
|
-
dimension="axial",
|
|
209
|
-
)
|
|
222
|
+
```bash
|
|
223
|
+
python -m pip install "cmpl[io]"
|
|
210
224
|
```
|
|
211
225
|
|
|
212
|
-
|
|
226
|
+
Convert a DICOM series with automatic conventional/Enhanced-DICOM detection:
|
|
213
227
|
|
|
214
|
-
|
|
228
|
+
```bash
|
|
229
|
+
cmpl-dicom-to-nifti /path/to/dicom_series
|
|
230
|
+
```
|
|
215
231
|
|
|
216
|
-
|
|
217
|
-
|
|
232
|
+
The same CLI can also be invoked as a Python module:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
python -m cmpl.cli.dicom_to_nifti /path/to/dicom_series
|
|
218
236
|
```
|
|
219
237
|
|
|
220
|
-
|
|
238
|
+
If the output path is omitted, CMPL writes the NIfTI image and JSON sidecar to the current directory using the DICOM directory name:
|
|
239
|
+
|
|
240
|
+
```text
|
|
241
|
+
./<series_directory_name>.nii.gz
|
|
242
|
+
./<series_directory_name>.json
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
An explicit output path can also be supplied:
|
|
221
246
|
|
|
222
247
|
```bash
|
|
223
|
-
|
|
248
|
+
cmpl-dicom-to-nifti \
|
|
249
|
+
/path/to/dicom_series \
|
|
250
|
+
/path/to/output.nii.gz
|
|
224
251
|
```
|
|
225
252
|
|
|
226
|
-
|
|
253
|
+
Progress output is enabled by default. Disable it with:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
cmpl-dicom-to-nifti /path/to/dicom_series --no-verbose
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
The same CLI handles conventional single-frame DICOM series and Enhanced multi-frame DICOM series. For multi-echo data, echo volumes are ordered by EchoTime and written as a 4D NIfTI image.
|
|
260
|
+
|
|
261
|
+
### Read a NIfTI file
|
|
227
262
|
|
|
228
263
|
```python
|
|
229
|
-
|
|
264
|
+
from cmpl.utilities.io import nifti_read
|
|
230
265
|
|
|
231
|
-
|
|
266
|
+
nifti_image, data = nifti_read("image.nii.gz")
|
|
267
|
+
```
|
|
232
268
|
|
|
233
|
-
|
|
234
|
-
s0 = np.full((64, 64, 8), 100.0, dtype=np.float32)
|
|
235
|
-
echo_times = np.array([0.0, 5.0, 10.0, 15.0], dtype=np.float32)
|
|
269
|
+
### Replace NIfTI data while preserving geometry
|
|
236
270
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
271
|
+
```python
|
|
272
|
+
from cmpl.utilities.io import update_nifti_data
|
|
273
|
+
|
|
274
|
+
updated = update_nifti_data(
|
|
275
|
+
"reference.nii.gz",
|
|
276
|
+
new_data,
|
|
277
|
+
output_path="updated.nii.gz",
|
|
243
278
|
)
|
|
279
|
+
```
|
|
244
280
|
|
|
245
|
-
|
|
246
|
-
|
|
281
|
+
### Load a DICOM directory as a NumPy array
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
from cmpl.utilities.io import load_dicom_scan_from_dir
|
|
285
|
+
|
|
286
|
+
volume = load_dicom_scan_from_dir(
|
|
287
|
+
"/path/to/dicom_directory",
|
|
288
|
+
reshape=True,
|
|
289
|
+
)
|
|
247
290
|
```
|
|
248
291
|
|
|
249
|
-
|
|
292
|
+
For multi-echo data, the loader can return data arranged as:
|
|
250
293
|
|
|
251
294
|
```text
|
|
252
|
-
|
|
295
|
+
x, y, z, echo
|
|
253
296
|
```
|
|
254
297
|
|
|
255
|
-
|
|
298
|
+
depending on the acquisition metadata and requested reshaping behavior.
|
|
256
299
|
|
|
257
|
-
|
|
258
|
-
from cmpl.quantitative_MRI import t2_star_two_parametric_3D
|
|
300
|
+
### Read a DICOM series as SimpleITK
|
|
259
301
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
images,
|
|
263
|
-
num_iterations=1000,
|
|
264
|
-
initial_lr=0.01,
|
|
265
|
-
initial_T2_star=20.0,
|
|
266
|
-
plot_error=False,
|
|
267
|
-
device="cpu",
|
|
268
|
-
)
|
|
302
|
+
```python
|
|
303
|
+
from cmpl.utilities.io import dicom_to_SimpleITK
|
|
269
304
|
|
|
270
|
-
|
|
271
|
-
s0_map = result["S0_map"]
|
|
305
|
+
image = dicom_to_SimpleITK("/path/to/dicom_directory")
|
|
272
306
|
```
|
|
273
307
|
|
|
274
|
-
|
|
308
|
+
The returned image is 3D for a single echo and 4D when multiple echoes are detected.
|
|
275
309
|
|
|
276
|
-
###
|
|
310
|
+
### Write a SimpleITK image as NIfTI
|
|
277
311
|
|
|
278
312
|
```python
|
|
279
|
-
from cmpl.
|
|
313
|
+
from cmpl.utilities.io import itk_to_nifti
|
|
280
314
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
s0_map,
|
|
285
|
-
return_numpy=True,
|
|
315
|
+
output_path = itk_to_nifti(
|
|
316
|
+
image,
|
|
317
|
+
"output.nii.gz",
|
|
286
318
|
)
|
|
287
319
|
```
|
|
288
320
|
|
|
289
|
-
|
|
321
|
+
### DICOM geometry and metadata helpers
|
|
322
|
+
|
|
323
|
+
CMPL separates DICOM geometry and acquisition-metadata handling into dedicated modules under `cmpl.dicom`.
|
|
324
|
+
|
|
325
|
+
```python
|
|
326
|
+
from cmpl.dicom import (
|
|
327
|
+
extract_slice_geometry,
|
|
328
|
+
get_slice_position,
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
geometry = extract_slice_geometry("slice001.dcm")
|
|
332
|
+
position = get_slice_position("slice001.dcm")
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Enhanced-DICOM helpers remain available as well:
|
|
336
|
+
|
|
337
|
+
```python
|
|
338
|
+
from cmpl.dicom.enhanced_dicom import (
|
|
339
|
+
get_slice_thickness,
|
|
340
|
+
get_spacing_between_slices,
|
|
341
|
+
voxel_sizes_detailed,
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
details = voxel_sizes_detailed(dataset)
|
|
345
|
+
```
|
|
290
346
|
|
|
291
347
|
## Reconstruction
|
|
292
348
|
|
|
@@ -338,7 +394,7 @@ reconstructed_kspace = grappa_2d_recon(
|
|
|
338
394
|
### Conjugate-gradient SENSE
|
|
339
395
|
|
|
340
396
|
```python
|
|
341
|
-
from cmpl.reconstruction.sense import CG_sense_2D
|
|
397
|
+
from cmpl.reconstruction.sense.cg import CG_sense_2D
|
|
342
398
|
|
|
343
399
|
reconstructed_image = CG_sense_2D(
|
|
344
400
|
undersampled_image_space,
|
|
@@ -348,82 +404,123 @@ reconstructed_image = CG_sense_2D(
|
|
|
348
404
|
|
|
349
405
|
Inputs to the current SENSE implementation are PyTorch tensors.
|
|
350
406
|
|
|
351
|
-
##
|
|
407
|
+
## Quantitative MRI
|
|
352
408
|
|
|
353
|
-
|
|
409
|
+
Quantitative MRI functionality is available under:
|
|
354
410
|
|
|
355
|
-
```
|
|
356
|
-
|
|
411
|
+
```python
|
|
412
|
+
cmpl.qmr
|
|
357
413
|
```
|
|
358
414
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
```python
|
|
362
|
-
from cmpl.utilities.io import nifti_read
|
|
415
|
+
Install the PyTorch and visualization dependencies:
|
|
363
416
|
|
|
364
|
-
|
|
417
|
+
```bash
|
|
418
|
+
python -m pip install "cmpl[torch,viz]"
|
|
365
419
|
```
|
|
366
420
|
|
|
367
|
-
###
|
|
421
|
+
### Reconstruct a multi-echo signal from T2* and S0 maps
|
|
368
422
|
|
|
369
423
|
```python
|
|
370
|
-
|
|
424
|
+
import numpy as np
|
|
371
425
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
426
|
+
from cmpl.quantitative_MRI import reconstruct_images
|
|
427
|
+
|
|
428
|
+
t2_star = np.full((64, 64, 8), 20.0, dtype=np.float32)
|
|
429
|
+
s0 = np.full((64, 64, 8), 100.0, dtype=np.float32)
|
|
430
|
+
echo_times = np.array([0.0, 5.0, 10.0, 15.0], dtype=np.float32)
|
|
431
|
+
|
|
432
|
+
images = reconstruct_images(
|
|
433
|
+
t2_star,
|
|
434
|
+
s0,
|
|
435
|
+
echo_times,
|
|
436
|
+
device="cpu",
|
|
437
|
+
return_numpy=True,
|
|
376
438
|
)
|
|
439
|
+
|
|
440
|
+
print(images.shape)
|
|
441
|
+
# (64, 64, 8, 4)
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
The signal model is:
|
|
445
|
+
|
|
446
|
+
```text
|
|
447
|
+
S(TE) = S0 * exp(-TE / T2*)
|
|
377
448
|
```
|
|
378
449
|
|
|
379
|
-
###
|
|
450
|
+
### Fit a 3D two-parameter T2* model
|
|
380
451
|
|
|
381
452
|
```python
|
|
382
|
-
from cmpl.
|
|
453
|
+
from cmpl.quantitative_MRI import t2_star_two_parametric_3D
|
|
383
454
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
455
|
+
result = t2_star_two_parametric_3D(
|
|
456
|
+
echo_times,
|
|
457
|
+
images,
|
|
458
|
+
num_iterations=1000,
|
|
459
|
+
initial_lr=0.01,
|
|
460
|
+
initial_T2_star=20.0,
|
|
461
|
+
plot_error=False,
|
|
462
|
+
device="cpu",
|
|
387
463
|
)
|
|
464
|
+
|
|
465
|
+
t2_star_map = result["T2_star_map"]
|
|
466
|
+
s0_map = result["S0_map"]
|
|
388
467
|
```
|
|
389
468
|
|
|
390
|
-
|
|
469
|
+
If CUDA is available and no device is supplied, the function can select a CUDA device automatically. CUDA usage can significantly accelerate fitting.
|
|
391
470
|
|
|
392
|
-
|
|
393
|
-
|
|
471
|
+
### Calculate normalized fitting error
|
|
472
|
+
|
|
473
|
+
```python
|
|
474
|
+
from cmpl.quantitative_MRI import calculate_rmse_percentage_s0
|
|
475
|
+
|
|
476
|
+
rmse_pct, rse_pct = calculate_rmse_percentage_s0(
|
|
477
|
+
original_images,
|
|
478
|
+
reconstructed_images,
|
|
479
|
+
s0_map,
|
|
480
|
+
return_numpy=True,
|
|
481
|
+
)
|
|
394
482
|
```
|
|
395
483
|
|
|
396
|
-
|
|
484
|
+
CMPL also contains two- and three-parameter 2D/3D T2* fitting functions.
|
|
397
485
|
|
|
398
|
-
|
|
486
|
+
## Visualization
|
|
399
487
|
|
|
400
|
-
|
|
401
|
-
from cmpl.utilities.io import dicom_to_SimpleITK
|
|
488
|
+
Install the visualization extra:
|
|
402
489
|
|
|
403
|
-
|
|
490
|
+
```bash
|
|
491
|
+
python -m pip install "cmpl[viz]"
|
|
404
492
|
```
|
|
405
493
|
|
|
406
|
-
###
|
|
494
|
+
### Browse or display a 3D MRI volume
|
|
407
495
|
|
|
408
496
|
```python
|
|
409
|
-
from cmpl.
|
|
497
|
+
from cmpl.visualization import plot_3D_mri
|
|
410
498
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
499
|
+
plot_3D_mri(
|
|
500
|
+
volume,
|
|
501
|
+
slice_number=volume.shape[2] // 2,
|
|
502
|
+
alpha=0.5,
|
|
503
|
+
direction="sagittal",
|
|
504
|
+
cmap="gray",
|
|
505
|
+
vmin=0,
|
|
506
|
+
vmax=1,
|
|
507
|
+
dpi=300,
|
|
414
508
|
)
|
|
415
509
|
```
|
|
416
510
|
|
|
417
|
-
|
|
511
|
+
If an interactive Matplotlib backend is available, `plot_3D_mri` can use interactive controls. Otherwise it falls back to static redraw mode.
|
|
512
|
+
|
|
513
|
+
### Compare images side by side
|
|
418
514
|
|
|
419
515
|
```python
|
|
420
|
-
from cmpl.
|
|
421
|
-
get_slice_thickness,
|
|
422
|
-
get_spacing_between_slices,
|
|
423
|
-
voxel_sizes_detailed,
|
|
424
|
-
)
|
|
516
|
+
from cmpl.visualization import side_by_side_view
|
|
425
517
|
|
|
426
|
-
|
|
518
|
+
side_by_side_view(
|
|
519
|
+
image_a,
|
|
520
|
+
image_b,
|
|
521
|
+
titles=["Reference", "Reconstruction"],
|
|
522
|
+
color_palette="gray",
|
|
523
|
+
)
|
|
427
524
|
```
|
|
428
525
|
|
|
429
526
|
## Numerical utilities
|
|
@@ -472,12 +569,8 @@ root/
|
|
|
472
569
|
├── Study001/
|
|
473
570
|
│ ├── Dicoms/
|
|
474
571
|
│ │ └── <contrast>/
|
|
475
|
-
│
|
|
476
|
-
│
|
|
477
|
-
│ └── Segmentations/
|
|
478
|
-
│ └── <contrast>/
|
|
479
|
-
│ └── <group>/
|
|
480
|
-
│ └── <segmentation>.nii.gz
|
|
572
|
+
│ └── h5_files/
|
|
573
|
+
│ └── <contrast>.h5
|
|
481
574
|
└── Study002/
|
|
482
575
|
└── ...
|
|
483
576
|
```
|
|
@@ -494,7 +587,7 @@ For example:
|
|
|
494
587
|
import cmpl
|
|
495
588
|
```
|
|
496
589
|
|
|
497
|
-
does not immediately
|
|
590
|
+
does not immediately import PyTorch, Matplotlib, pandas, nibabel, pydicom, SimpleITK, h5py, or the Jupyter visualization stack.
|
|
498
591
|
|
|
499
592
|
Optional functionality is loaded when its corresponding module or function is accessed. This keeps startup lightweight and allows users to install only the dependencies required for their workflow.
|
|
500
593
|
|
|
@@ -525,6 +618,8 @@ The test suite includes:
|
|
|
525
618
|
- GRAPPA and SENSE reconstruction tests
|
|
526
619
|
- visualization smoke tests
|
|
527
620
|
- synthetic NIfTI, DICOM, and SimpleITK I/O tests
|
|
621
|
+
- conventional and Enhanced multi-echo DICOM-to-NIfTI conversion and JSON-sidecar tests
|
|
622
|
+
- DICOM geometry and metadata tests
|
|
528
623
|
- data-indexing tests
|
|
529
624
|
|
|
530
625
|
### Build the package
|
|
@@ -538,8 +633,13 @@ python -m twine check dist/*
|
|
|
538
633
|
|
|
539
634
|
```text
|
|
540
635
|
src/cmpl/
|
|
636
|
+
├── _version.py
|
|
637
|
+
├── cli/
|
|
638
|
+
│ └── dicom_to_nifti.py
|
|
541
639
|
├── dicom/
|
|
542
|
-
│
|
|
640
|
+
│ ├── enhanced_dicom.py
|
|
641
|
+
│ ├── geometry.py
|
|
642
|
+
│ └── metadata.py
|
|
543
643
|
├── quantitative_MRI/
|
|
544
644
|
│ └── mapping.py
|
|
545
645
|
├── reconstruction/
|