CMPL — CMRR MRI Processing Libraries
PyPI: https://pypi.org/project/cmpl/
GitHub: https://github.com/ehedayati/cmpl
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.
The package is modular by design: the base installation remains lightweight, while larger or domain-specific dependencies are installed only when the corresponding functionality is needed.
Highlights
- Geometry-aware conventional and Enhanced DICOM to NIfTI conversion
- JSON metadata sidecars with acquisition and source-geometry information
- Multi-echo DICOM support with 4D NIfTI output ordered by echo time
- Packaged
cmpl-dicom-to-nifticommand-line converter - Packaged
cmpl-t2starcommand-line T2* and S0 mapper - DICOM geometry and acquisition-metadata utilities
- Parallel MRI reconstruction with 1D/2D GRAPPA and conjugate-gradient SENSE
- Quantitative MRI tools for T2* fitting, signal reconstruction, and fitting-error analysis
- MRI visualization utilities for 2D comparisons and 3D volume browsing
- Conventional and Enhanced DICOM, NIfTI, HDF5, and SimpleITK utilities
- Lightweight numerical utilities shared across CMPL
- Optional pandas-based indexing for CMPL-style medical-data directory structures
- Lazy imports so unrelated optional dependencies are not loaded unnecessarily
- Convenient aliases such as
cmpl.recon,cmpl.qmr,cmpl.vis, andcmpl.io
Requirements
CMPL requires:
- Python >= 3.10
- NumPy >= 1.26, < 3
- SciPy >= 1.13, < 2
- tqdm >= 4.66
Additional functionality is provided through optional dependency groups.
Installation
Install the lightweight base package:
python -m pip install cmpl
Install only the functionality you need:
| Extra | Purpose |
|---|---|
io |
DICOM, NIfTI, HDF5, and SimpleITK I/O |
data |
pandas-based data indexing |
viz |
Matplotlib and Jupyter visualization |
torch |
PyTorch-based reconstruction and quantitative MRI |
all |
All optional CMPL functionality |
dev |
Testing, linting, build, and release tools |
Examples:
python -m pip install "cmpl[io]"
python -m pip install "cmpl[torch]"
python -m pip install "cmpl[viz]"
python -m pip install "cmpl[io,torch]"
python -m pip install "cmpl[all]"
For NIfTI-based T2* mapping:
python -m pip install "cmpl[io,torch]"
Matplotlib is only required when plotting is explicitly requested:
python -m pip install "cmpl[viz]"
Quick start
import cmpl
print(cmpl.__version__)
CMPL exposes convenient aliases for commonly used subpackages:
cmpl.recon # reconstruction
cmpl.qmr # quantitative MRI
cmpl.vis # visualization
cmpl.io # I/O utilities
cmpl.dicom # DICOM metadata and geometry utilities
cmpl.utils # utilities
These aliases are resolved lazily so import cmpl does not require every optional dependency to be installed or imported.
DICOM and NIfTI I/O
Install the I/O extra:
python -m pip install "cmpl[io]"
Convert a DICOM series to NIfTI
CMPL supports direct conversion of both conventional and Enhanced DICOM series to NIfTI.
The converter:
- detects the DICOM representation automatically
- preserves spatial geometry
- supports single-echo and multi-echo acquisitions
- writes a NIfTI image
- writes a matching JSON metadata sidecar
- orders multi-echo volumes by echo time
import cmpl
metadata = cmpl.io.dicom_to_nifti(
"/path/to/dicom_series",
"output.nii.gz",
)
This creates:
output.nii.gz
output.json
If the output path does not end in .nii or .nii.gz, CMPL appends .nii.gz.
For a single echo, the output is a 3D image. For a multi-echo acquisition, CMPL writes a 4D NIfTI with echoes in the last dimension:
x, y, z, echo
The matching JSON sidecar contains acquisition metadata and source-geometry information. For multi-echo data, echo times are stored in milliseconds under:
{
"Acquisition": {
"EchoTimes": [2.5, 5.0, 7.5, 10.0],
"TimeUnit": "ms"
}
}
If a directory contains multiple DICOM series, select a specific SeriesInstanceUID:
metadata = cmpl.io.dicom_to_nifti(
"/path/to/dicom_directory",
"output.nii.gz",
series_id="1.2.840...",
)
Command-line DICOM conversion
The I/O extra installs:
cmpl-dicom-to-nifti
Convert a DICOM series with automatic conventional/Enhanced-DICOM detection:
cmpl-dicom-to-nifti /path/to/dicom_series
The same CLI can be invoked as a Python module:
python -m cmpl.cli.dicom_to_nifti /path/to/dicom_series
If the output path is omitted, CMPL writes the NIfTI and JSON sidecar to the current directory using the DICOM directory name:
./<series_directory_name>.nii.gz
./<series_directory_name>.json
Specify an explicit output path if needed:
cmpl-dicom-to-nifti \
/path/to/dicom_series \
/path/to/output.nii.gz
Progress output is enabled by default. Disable it with:
cmpl-dicom-to-nifti /path/to/dicom_series --no-verbose
The same command handles conventional single-frame DICOM and Enhanced multi-frame DICOM.
Read a NIfTI file
from cmpl.utilities.io import nifti_read
nifti_image, data = nifti_read("image.nii.gz")
Replace NIfTI data while preserving geometry
from cmpl.utilities.io import update_nifti_data
updated = update_nifti_data(
"reference.nii.gz",
new_data,
output_path="updated.nii.gz",
)
Save a scalar map using reference NIfTI geometry
from cmpl.utilities.io import save_scalar_map_like
save_scalar_map_like(
reference_image,
scalar_map,
"map.nii.gz",
)
This is useful for quantitative maps such as T2* and S0 because the spatial geometry of the source NIfTI is preserved.
Load a DICOM directory as a NumPy array
from cmpl.utilities.io import load_dicom_scan_from_dir
volume = load_dicom_scan_from_dir(
"/path/to/dicom_directory",
reshape=True,
)
For multi-echo data, the loader can return:
x, y, z, echo
depending on the acquisition metadata and requested reshaping behavior.
Read a DICOM series as SimpleITK
from cmpl.utilities.io import dicom_to_SimpleITK
image = dicom_to_SimpleITK("/path/to/dicom_directory")
The returned image is 3D for single-echo data and 4D when multiple echoes are detected.
Write a SimpleITK image as NIfTI
from cmpl.utilities.io import itk_to_nifti
output_path = itk_to_nifti(
image,
"output.nii.gz",
)
DICOM geometry and metadata helpers
CMPL separates DICOM geometry and acquisition-metadata handling into dedicated modules under cmpl.dicom.
from cmpl.dicom import (
extract_slice_geometry,
get_slice_position,
)
geometry = extract_slice_geometry("slice001.dcm")
position = get_slice_position("slice001.dcm")
Enhanced-DICOM helpers are also available:
from cmpl.dicom.enhanced_dicom import (
get_slice_thickness,
get_spacing_between_slices,
voxel_sizes_detailed,
)
details = voxel_sizes_detailed(dataset)
Quantitative MRI
Quantitative MRI functionality is available under:
cmpl.qmr
Install PyTorch support:
python -m pip install "cmpl[torch]"
For NIfTI-based quantitative MRI workflows:
python -m pip install "cmpl[io,torch]"
Signal model
The current two-parameter T2* implementation uses the mono-exponential signal model:
S(TE) = S0 * exp(-TE / T2*)
where:
S0is the extrapolated signal at TE = 0T2*is the transverse relaxation time- TE and T2* must use the same time unit
CMPL conventionally uses milliseconds for T2* workflows.
Fit a 3D two-parameter T2* model
from cmpl.quantitative_MRI import t2_star_two_parametric_3D
result = t2_star_two_parametric_3D(
echo_times,
images,
num_iterations=1000,
initial_lr=0.01,
initial_T2_star=20.0,
plot_error=False,
device="cpu",
)
t2_star_map = result["T2_star_map"]
s0_map = result["S0_map"]
The expected image layout is:
x, y, z, echo
If CUDA is available and no device is supplied, the fitter can select CUDA automatically.
Command-line 3D T2* mapping
CMPL includes a command-line interface for calculating T2* and S0 maps directly from a 4D multi-echo NIfTI file and its JSON metadata sidecar.
Install the required dependencies:
python -m pip install "cmpl[io,torch]"
Given:
multi_echo.nii.gz
multi_echo.json
run:
cmpl-t2star multi_echo.nii.gz
The JSON sidecar is detected automatically when it has the same basename as the NIfTI file.
The CLI reads echo times from:
{
"Acquisition": {
"EchoTimes": [2.5, 5.0, 7.5, 10.0],
"TimeUnit": "ms"
}
}
The input NIfTI must be 4D:
x, y, z, echo
and the number of entries in EchoTimes must match the number of volumes in the fourth dimension.
The command writes:
multi_echo_T2star.nii.gz
multi_echo_S0.nii.gz
The T2* map is written in milliseconds. The S0 map retains the signal-intensity units of the input data. Output maps preserve the spatial geometry of the source NIfTI.
Specify a different JSON file:
cmpl-t2star multi_echo.nii.gz \
--json metadata.json
Specify a custom output prefix:
cmpl-t2star multi_echo.nii.gz \
-o results/subject01
This creates:
results/subject01_T2star.nii.gz
results/subject01_S0.nii.gz
Request CUDA explicitly:
cmpl-t2star multi_echo.nii.gz --device cuda
If no device is specified, CMPL uses CUDA when available and otherwise uses CPU.
Optimization settings can also be adjusted:
cmpl-t2star multi_echo.nii.gz \
--device cuda \
--iterations 10000 \
--lr 0.01 \
--initial-t2star 20
If echo times are present but not ordered, the CLI sorts the echo times and their corresponding NIfTI volumes together before fitting.
Reconstruct a multi-echo signal from T2* and S0 maps
import numpy as np
from cmpl.quantitative_MRI import reconstruct_images
t2_star = np.full((64, 64, 8), 20.0, dtype=np.float32)
s0 = np.full((64, 64, 8), 100.0, dtype=np.float32)
echo_times = np.array(
[0.0, 5.0, 10.0, 15.0],
dtype=np.float32,
)
images = reconstruct_images(
t2_star,
s0,
echo_times,
device="cpu",
return_numpy=True,
)
print(images.shape)
# (64, 64, 8, 4)
Calculate normalized fitting error
from cmpl.quantitative_MRI import calculate_rmse_percentage_s0
rmse_pct, rse_pct = calculate_rmse_percentage_s0(
original_images,
reconstructed_images,
s0_map,
return_numpy=True,
)
CMPL also contains additional 2D/3D T2* fitting functions.
Plotting is optional. Matplotlib is imported only when plotting is requested.
Reconstruction
Reconstruction functionality is available under:
cmpl.recon
Install PyTorch support:
python -m pip install "cmpl[torch]"
1D GRAPPA
from cmpl.reconstruction.grappa import grappa_1d_recon
reconstructed_kspace = grappa_1d_recon(
calibration_kspace,
undersampled_kspace,
reduction_factor=2,
kx=3,
ky=3,
)
The current implementation expects coil-resolved k-space in the order:
frequency, phase, slice, coils
2D GRAPPA
from cmpl.reconstruction.grappa import grappa_2d_recon
reconstructed_kspace = grappa_2d_recon(
calibration_kspace,
undersampled_kspace,
kernel_size=(3, 3, 3),
reduction_factors=(2, 2),
)
Conjugate-gradient SENSE
from cmpl.reconstruction.sense.cg import CG_sense_2D
reconstructed_image = CG_sense_2D(
undersampled_image_space,
coil_sensitivity,
)
Inputs to the current SENSE implementation are PyTorch tensors.
Visualization
Install the visualization extra:
python -m pip install "cmpl[viz]"
Browse or display a 3D MRI volume
from cmpl.visualization import plot_3D_mri
plot_3D_mri(
volume,
slice_number=volume.shape[2] // 2,
alpha=0.5,
direction="sagittal",
cmap="gray",
vmin=0,
vmax=1,
dpi=300,
)
If an interactive Matplotlib backend is available, plot_3D_mri can use interactive controls. Otherwise it falls back to static redraw mode.
Compare images side by side
from cmpl.visualization import side_by_side_view
side_by_side_view(
image_a,
image_b,
titles=["Reference", "Reconstruction"],
color_palette="gray",
)
Numerical utilities
Lightweight numerical helpers are kept separate from heavier I/O modules.
from cmpl.utilities.numerical import resize_matrix
resized = resize_matrix(
image,
target_shape=(600, 600),
)
resize_matrix accepts NumPy arrays and PyTorch tensors. PyTorch is imported only when a Torch tensor is actually passed.
For backward compatibility:
from cmpl.utilities.utils import resize_matrix
continues to work.
Data indexing
Install the data extra:
python -m pip install "cmpl[data]"
CMPL includes a pandas-based utility for indexing directory trees that follow the CMPL medical-data convention:
from cmpl.utilities.df_build import build_medical_data_frame
df = build_medical_data_frame("/path/to/root")
The expected structure is similar to:
root/
├── Study001/
│ ├── Dicoms/
│ │ └── <contrast>/
│ └── h5_files/
│ └── <contrast>.h5
└── Study002/
└── ...
This utility is convention-specific rather than a general-purpose filesystem indexer.
Lazy loading and optional dependencies
CMPL is designed so unrelated optional packages are not imported simply because the top-level package is imported.
For example:
import cmpl
does not immediately import PyTorch, Matplotlib, pandas, nibabel, pydicom, SimpleITK, h5py, or the Jupyter visualization stack.
Optional functionality is loaded only when the corresponding module or function is accessed.
Within quantitative MRI, Matplotlib is also loaded lazily: non-plotting T2* workflows do not require Matplotlib.
Development
Clone the project and install it in editable mode with development dependencies:
python -m pip install -e ".[dev]"
For development across the main optional feature groups:
python -m pip install -e ".[dev,io,data,viz,torch]"
Run the full test suite:
python -m pytest tests/ -v
The test suite covers:
- lazy-import and dependency-boundary behavior
- qMRI numerical fitting
- T2* CLI validation and NIfTI output
- GRAPPA and SENSE reconstruction
- visualization smoke tests
- synthetic NIfTI, DICOM, and SimpleITK I/O
- conventional and Enhanced multi-echo DICOM-to-NIfTI conversion
- JSON sidecar generation
- DICOM geometry and metadata
- data indexing
Build the package
Build distributions:
rm -rf build dist *.egg-info
python -m build
Validate them:
python -m twine check dist/*
Before publishing, it is also useful to install the built wheel into a clean environment and verify the packaged CLI commands:
cmpl-dicom-to-nifti --help
cmpl-t2star --help
Package layout
src/cmpl/
├── _version.py
├── cli/
│ ├── __init__.py
│ ├── dicom_to_nifti.py
│ └── t2star.py
├── dicom/
│ ├── enhanced_dicom.py
│ ├── geometry.py
│ └── metadata.py
├── quantitative_MRI/
│ └── mapping.py
├── reconstruction/
│ ├── grappa/
│ │ ├── grappa_1D.py
│ │ ├── grappa_2D.py
│ │ └── utils.py
│ └── sense/
│ └── cg.py
├── utilities/
│ ├── df_build.py
│ ├── io.py
│ ├── numerical.py
│ └── utils.py
└── visualization/
└── visualization.py
License
See the LICENSE file included with the project for licensing terms.
Author
CMPL is developed by Eisa Hedayati at CMRR.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cmpl-0.2.4.tar.gz.
File metadata
- Download URL: cmpl-0.2.4.tar.gz
- Upload date:
- Size: 67.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7bd28d982b32f1180371524135a36e574dd3fb4e318782e0b83a38010f9055b9
|
|
| MD5 |
73d58468b26920210b60d19717679e07
|
|
| BLAKE2b-256 |
217e4125c1e42b856098825b5bc19917838a5c5a1dd36fceffac62ee7681ad37
|
File details
Details for the file cmpl-0.2.4-py3-none-any.whl.
File metadata
- Download URL: cmpl-0.2.4-py3-none-any.whl
- Upload date:
- Size: 63.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c2e4673661acb7a95a8472ccbb851f6ba57411f17a076412d8f48bf038253ec3
|
|
| MD5 |
1490f9fa5a8d770db4d0b203bef323f4
|
|
| BLAKE2b-256 |
a2d25fc4bb71764909f23c08b3dfc42160e456bc4097fd2c40bd420fc7c75543
|