Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d69c5e6
Add docstrings to t1_maps/utils.py
finsberg Mar 6, 2026
676edad
Add tests for t1_maps/utils.py
finsberg Mar 6, 2026
bdb8248
Add another function for comparing arrays
finsberg Mar 6, 2026
f01ecc6
Add tests for t1 to r1
finsberg Mar 6, 2026
2baf833
Add more docstrings in t1_to_r1
finsberg Mar 6, 2026
5c47ddc
Fix failing test
finsberg Mar 6, 2026
8921a4e
Add script for generating test data from gonzo
finsberg Mar 6, 2026
ba4772b
Fix deprecated argument in scikit-image
finsberg Mar 6, 2026
35e429d
Add tests for dicom
finsberg Mar 6, 2026
a877de2
Refactor stats
finsberg Mar 6, 2026
ee07b31
Restructure t1 maps
finsberg Mar 7, 2026
890a96f
Update docs
finsberg Mar 7, 2026
e482b18
Separate concentration and r1
finsberg Mar 7, 2026
55cb213
More restructuring
finsberg Mar 7, 2026
cab0e07
Add cli
finsberg Mar 7, 2026
c3dcdac
Add documentation
finsberg Mar 7, 2026
fe4cf7f
Remove .flake8 file
finsberg Mar 7, 2026
e7b429d
Update README
finsberg Mar 7, 2026
342ece8
Start adding better logging
finsberg Mar 8, 2026
217641b
More logging
finsberg Mar 9, 2026
11d4258
Refactor masks - and add tests
finsberg Mar 9, 2026
d752c9e
Add seed to test
finsberg Mar 9, 2026
ecbdfe5
More logging
finsberg Mar 9, 2026
922f207
Add suggestions from Cecile
finsberg Mar 9, 2026
772c1ba
Fix more logging and add gonzo commands
finsberg Mar 9, 2026
d75dd1e
Run isort
finsberg Mar 9, 2026
587e379
More docs
finsberg Mar 9, 2026
7774535
Refactor stats
finsberg Mar 9, 2026
e5d57dc
Refactor segmentation
finsberg Mar 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions .flake8

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/setup-data.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
path: data/ # The folder you want to cache
# The key determines if we have a match.
# Change 'v1' to 'v2' manually to force a re-download in the future.
key: test-data-v4
key: test-data-v5


# 2. DOWNLOAD ONLY IF CACHE MISS
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
test/FreeSurferColorLUT.txt
.DS_Store
.jupyter_cache/
# Created by https://www.toptal.com/developers/gitignore/api/python
# Edit at https://www.toptal.com/developers/gitignore?templates=python

Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ repos:
rev: 'v0.14.7'
hooks:
# Run the linter.
- id: ruff
- id: ruff-check
args: [ --fix ]
# Run the formatter.
- id: ruff-format
Expand Down
34 changes: 27 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# MRI-Toolkit

`MRI-toolkit` provides a set of features dedicated to human MRI data post-processing and analysis. The implementation is based on [gMRI2FEM](https://github.com/jorgenriseth/gMRI2FEM).
`MRI-toolkit` provides a set of features dedicated to MRI data post-processing and analysis.

The implementation is inspired by [gMRI2FEM](https://github.com/jorgenriseth/gMRI2FEM), and some of the code is taken from that project. However, `MRI-toolkit` is designed to be more modular and extensible, with a focus on providing a user-friendly command-line interface (CLI) for common MRI processing tasks.

## Installation

Expand All @@ -22,9 +24,27 @@ To get started with `mri-toolkit`, you can use the command-line interface (CLI)

## Features

* **File Inspection**: detailed NIfTI header analysis (affine, voxel size, shape).
* **Statistics**: Compute comprehensive statistics (volume, mean, median, std, percentiles) for MRI regions based on segmentation maps.
* **Visualization**:
* **Terminal**: View orthogonal slices (Sagittal, Coronal, Axial) directly in your console.
* **Napari**: Launch the Napari viewer for interactive 3D inspection.
* **Data Management**: Utilities to download test datasets.

- File Inspection: detailed NIfTI header analysis (affine, voxel size, shape).

- $T_1$ Mapping: Estimate $T_1$ relaxation times using Look-Locker or Mixed sequences, and seamlessly merge them into comprehensive Hybrid $T_1$ maps.

- $R_1$ Relaxation Rates: Convert $T_1$ maps into $R_1$ relaxation rate maps for linear scaling with tracer concentrations.

- Concentration Mapping: Calculate the spatial distribution of contrast agents (e.g., gadobutrol) utilizing pre- and post-contrast $T_1$ or $R_1$ maps.

- Statistics: Compute comprehensive statistics (volume, mean, median, std, percentiles) for MRI regions based on segmentation maps.

- Visualization:

- Terminal: View orthogonal slices (Sagittal, Coronal, Axial) directly in your console.

- Napari: Launch the Napari viewer for interactive 3D inspection.

- Data Management: Utilities to download datasets.

## Contributing
Contributions to `MRI-toolkit` are welcome! If you have an idea for a new feature, improvement, or bug fix, please open an issue or submit a pull request on GitHub. For more details on how to contribute, please see the [Contributing Guide](CONTRIBUTING.md).

## License
`MRI-toolkit` is licensed under the MIT License. See the [LICENSE](LICENSE) file for more information.
5 changes: 5 additions & 0 deletions _toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ parts:
- file: "docs/info.md" # About the mritk info command
- file: "docs/show.md" # About the mritk show command
- file: "docs/napari.md" # About the mritk napari command
- file: "docs/looklocker.md" # About the mritk looklocker command
- file: "docs/mixed.md" # About the mritk mixed command
- file: "docs/r1.md" # About the mritk r1 command
- file: "docs/hybrid.md" # About the mritk hybrid command
- file: "docs/concentration.md" # About the mritk concentration command

- caption: Community
chapters:
Expand Down
7 changes: 6 additions & 1 deletion conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@
"third_party/*",
"jupyter_execute/",
"**.jupyter_cache",
"venv/*",
"test-*htmlcov/*",
"new-test-data/*",
"mritk-test-data/*",
]
extensions = [
"sphinx_togglebutton",
"sphinx_copybutton",
"myst_parser",
"myst_nb",
"sphinx_comments",
"sphinx_external_toc",
"sphinx.ext.intersphinx",
Expand All @@ -35,6 +39,7 @@
"sphinxcontrib.bibtex",
"sphinx_codeautolink",
"sphinx_multitoc_numbering",
"sphinxcontrib.mermaid",
]
myst_enable_extensions = [
"amsmath",
Expand Down
45 changes: 28 additions & 17 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,47 +39,58 @@ show
:members:
:inherited-members:

concentration
-------------

statistics
----------

.. automodule:: mritk.statistics
.. automodule:: mritk.concentration
:members:
:inherited-members:

.. automodule:: mritk.statistics.utils
:members:
:inherited-members:
mixed
-----

.. automodule:: mritk.statistics.compute_stats
.. automodule:: mritk.mixed
:members:
:inherited-members:

.. automodule:: mritk.statistics.cli
looklocker
----------

.. automodule:: mritk.looklocker
:members:
:inherited-members:

utils
-----

data
----

.. automodule:: mritk.data
.. automodule:: mritk.utils
:members:
:inherited-members:

.. automodule:: mritk.data.io
hybrid
------

.. automodule:: mritk.hybrid
:members:
:inherited-members:

.. automodule:: mritk.data.orientation


statistics
----------

.. automodule:: mritk.stats
:members:
:inherited-members:

.. automodule:: mritk.data.base

data
----

.. automodule:: mritk.data
:members:
:inherited-members:


segmentation
------------

Expand Down
88 changes: 88 additions & 0 deletions docs/concentration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
jupytext:
formats: md:myst
text_representation:
extension: .md
format_name: myst
kernelspec:
display_name: Python 3
language: python
name: python3
---
# Concentration Mapping

The Concentration module calculates the spatial distribution of a contrast agent (like gadobutrol) in the brain.

Concentration $C$ can be estimated voxel-wise from longitudinal relaxation data comparing a post-contrast session to a pre-contrast (baseline) session. mritk supports two calculation pathways depending on whether you are working with $T_1$ times or $R_1$ rates (see R1 Maps).

$$\frac{1}{T_1} = \frac{1}{T_{10}} + r_1 C \quad \implies \quad C = \frac{1}{r_1} \left(R_1 - R_{10}\right)$$

where $r_1$ is the relaxivity of the contrast agent (default: 3.2 to 4.5 $\text{s}^{-1}\text{mmol}^{-1}$).

## Pipeline Overview

```{mermaid}
graph TD
A[Pre-Contrast Hybrid T1] -->|T1 method| C{Compute Concentration}
B[Post-Contrast Hybrid T1] -->|T1 method| C

A2[Pre-Contrast R1] -->|R1 method| C
B2[Post-Contrast R1] -->|R1 method| C

M[Brain/Intracranial Mask] -.->|Optional| C

C --> D(Tracer Concentration Map NIfTI)
```

## Commands

```{code-cell} shell
!mritk concentration --help
```


### 1. From $T_1$ Maps (t1)

Calculates concentration directly from $T_1$ maps (in milliseconds). The command handles the inversion safely and avoids division-by-zero errors for background voxels.

```{code-cell} shell
!mritk concentration t1 --help
```

#### Example Command

```shell
mritk concentration t1 -i path/to/post_t1.nii.gz -r path/to/pre_t1.nii.gz -o path/to/concentration.nii.gz --r1 0.0045 --mask path/to/intracranial_mask.nii.gz
```

Gonzo:

```shell
mritk concentration t1 \
-i gonzo/mri-processed/mri_processed_data/sub-01/T1maps/sub-01_ses-02_T1map_hybrid.nii.gz \
-r gonzo/mri-processed/mri_processed_data/sub-01/T1maps/sub-01_ses-01_T1map_hybrid.nii.gz \
-o sub-01_ses-02_concentration.nii.gz \
--r1 0.0032 \
--mask gonzo/mri-processed/mri_processed_data/sub-01/segmentations/sub-01_seg-intracranial_binary.nii.gz
```

mritk concentration t1 \
-i new-test-data/mri-processed/mri_processed_data/sub-01/T1maps/sub-01_ses-02_T1map_hybrid.nii.gz \
-r new-test-data/mri-processed/mri_processed_data/sub-01/T1maps/sub-01_ses-01_T1map_hybrid.nii.gz \
-o sub-01_ses-02_concentration.nii.gz \
--r1 0.0032 \
--mask new-test-data/mri-processed/mri_processed_data/sub-01/segmentations/sub-01_seg-intracranial_binary.nii.gz

### 2. From $R_1$ Maps (r1)

Calculates concentration from pre-computed $R_1$ maps. This is mathematically equivalent but slightly faster if $R_1$ maps are already available.

```{code-cell} shell
!mritk concentration r1 --help
```

#### Example Command

```shell
mritk concentration r1 -i path/to/post_r1.nii.gz -r path/to/pre_r1.nii.gz -o path/to/concentration.nii.gz --r1 0.0045
```
17 changes: 17 additions & 0 deletions docs/datasets.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
---
jupytext:
formats: md:myst
text_representation:
extension: .md
format_name: myst
kernelspec:
display_name: Python 3
language: python
name: python3
---

# Datasets

The `datasets` subcommand provides tools for listing and downloading example datasets.


```{code-cell} shell
!mritk datasets --help
```

To list available datasets, use:

```bash
Expand Down
57 changes: 57 additions & 0 deletions docs/hybrid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
jupytext:
formats: md:myst
text_representation:
extension: .md
format_name: myst
kernelspec:
display_name: Python 3
language: python
name: python3
---

# Hybrid $T_1$ Maps

To achieve accurate $T_1$ measurements across the entire brain space, mritk combines the Look-Locker (LL) and Mixed sequence $T_1$ maps into a single Hybrid map.

Look-Locker is used for short $T_1$ values (brain tissue and regions with high tracer concentrations).

Mixed Sequence is used for long $T_1$ values (CSF).

The hybrid command seamlessly merges the two images based on a user-defined threshold (default: 1500 ms) and a specific anatomical mask (typically a CSF mask).

## Pipeline Overview

```{mermaid}
graph LR
A(Look-Locker T1 Map) --> D{Hybrid Merge}
B(Mixed T1 Map) --> D
C(CSF Mask) --> D
D -->|Threshold > 1500ms| E(Hybrid T1 Map)
```

## Command Usage


```{code-cell} shell
!mritk hybrid --help
```

## Example Command

```shell
mritk hybrid -l path/to/ll_t1.nii.gz -m path/to/mixed_t1.nii.gz -c path/to/csf_mask.nii.gz -o path/to/hybrid_t1.nii.gz --threshold 1500.0
```


Gonzo:

```shell
mritk hybrid \
-l gonzo/mri-processed/mri_processed_data/sub-01/registered/sub-01_ses-02_acq-looklocker_T1map_registered.nii.gz \
-m gonzo/mri-processed/mri_processed_data/sub-01/registered/sub-01_ses-02_acq-mixed_T1map_registered.nii.gz \
-c gonzo/mri-processed/mri_processed_data/sub-01/segmentations/sub-01_seg-csf_binary.nii.gz \
-o sub-01_ses-02_T1map_hybrid.nii.gz \
--threshold 1500 \
--erode 1
```
24 changes: 18 additions & 6 deletions docs/info.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
---
jupytext:
formats: md:myst
text_representation:
extension: .md
format_name: myst
kernelspec:
display_name: Python 3
language: python
name: python3
---

# Info command

The `info` command allows you to quickly inspect the metadata of an MRI file. It displays the image shape, voxel size, data type, and the affine transformation matrix.

## Usage

```bash
mritk info <file_path> [OPTIONS]
```{code-cell} shell
!mritk info --help
```

**Arguments:**
* `file`: Path to the file to display information about.
### Example Command

**Options:**
* `--json`: Output information in JSON format. Useful for programmatic parsing.
```bash
mritk info path/to/image.nii.gz
```


![info](https://github.com/user-attachments/assets/fc0e734d-3c94-48fa-8e25-3e65bfc86ebe)
Loading
Loading