Skip to content

Commit

Permalink
Merge branch 'main' into issue_138
Browse files Browse the repository at this point in the history
  • Loading branch information
fzimmermann89 authored Sep 28, 2024
2 parents d014b72 + f86717d commit 20f5460
Show file tree
Hide file tree
Showing 173 changed files with 3,879 additions and 3,303 deletions.
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
groups:
all-actions:
patterns: [ "*" ]
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
done
- name: Check if any notebooks have been changed
uses: tj-actions/verify-changed-files@v19
uses: tj-actions/verify-changed-files@v20
id: verify-changed-notebooks
with:
files: ./examples/*.ipynb
Expand Down Expand Up @@ -184,7 +184,7 @@ jobs:
run: sphinx-build -b html ./docs/source ./docs/build/html

- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
uses: peaceiris/actions-gh-pages@v4
with:
publish_branch: github-pages
github_token: ${{ secrets.GITHUB_TOKEN }}
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ name: PyTest

on:
pull_request:
paths-ignore:
- "**.md"

jobs:
get_dockerfiles:
Expand Down Expand Up @@ -81,7 +79,7 @@ jobs:
- name: Pytest coverage comment
id: coverageComment
uses: MishaKav/pytest-coverage-comment@v1.1.51
uses: MishaKav/pytest-coverage-comment@v1.1.52
with:
pytest-coverage-path: ./pytest-coverage.txt
junitxml-path: ./pytest.xml
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright [yyyy] [name of copyright owner]
Copyright 2023 Physikalisch-Technische Bundesanstalt

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
89 changes: 72 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,90 @@
# MRpro

MR image reconstruction and processing package specifically developed for PyTorch.

This package supports ismrmrd-format for MR raw data. All data containers utilize PyTorch tensors to ensure easy integration in PyTorch-based network schemes.

![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12-blue)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
![Coverage Bagde](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/ckolbPTB/48e334a10caf60e6708d7c712e56d241/raw/coverage.json)

If you want to give MRpro a try you can use
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/PTB-MR/mrpro.git/main?labpath=examples)
MR image reconstruction and processing package specifically developed for PyTorch.

- **Source code:** <https://github.com/PTB-MR/mrpro>
- **Documentation:** <https://ptb-mr.github.io/mrpro/>
- **Bug reports:** <https://github.com/PTB-MR/mrpro/issues>
- **Try it out:** [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/PTB-MR/mrpro.git/main?labpath=examples)

## Awards

- 2024 ISMRM QMRI Study Group Challenge, 2nd prize for Relaxometry (T2* and T1)

## Main features

- **ISMRMRD support** MRpro supports [ismrmrd-format](https://ismrmrd.readthedocs.io/en/latest/) for MR raw data.
- **PyTorch** All data containers utilize PyTorch tensors to ensure easy integration in PyTorch-based network schemes.
- **Cartesian and non-Cartesian trajectories** MRpro can reconstruct data obtained with Cartesian and non-Cartesian (e.g. radial, spiral...) sapling schemes. MRpro automatically detects if FFT or nuFFT is required to reconstruction the k-space data.
- **Pulseq support** If the data acquisition was carried out using a [pulseq-based](http://pulseq.github.io/) sequence, the seq-file can be provided to MRpro and the used trajectory is automatically calculated.
- **Signal models** A range of different MR signal models are implemented (e.g. T1 recovery, WASABI).
- **Regularised image reconstruction** Regularised image reconstruction algorithms including Wavelet-based compressed sensing or total variation regularised image reconstruction are available.

## Examples

In the following we show some code snippets to highlight the use of MRpro. Each code snippet only shows the main steps. A complete working notebook can be found in the provided link.

### Simple reconstruction

You find the documentation [here](https://ptb-mr.github.io/mrpro/)
Read in the data and trajectoy and reconstruct an image by applying a density compensation function and then the adjoint of the Fourier operator and the adjoint of the coil sensitivity operator.

```python
# Read the trajectory from the ISMRMRD file
trajectory = mrpro.data.traj_calculators.KTrajectoryIsmrmrd()
# Load in the Data from the ISMRMRD file
kdata = mrpro.data.KData.from_file(data_file.name, trajectory)
# Perform the reconstruction
reconstruction = mrpro.algorithms.reconstruction.DirectReconstruction.from_kdata(kdata)
img = reconstruction(kdata)
```

Full example: <https://github.com/PTB-MR/mrpro/blob/main/examples/direct_reconstruction.py>

### Estimate quantitative parameters

Quantitative parameter maps can be obtained by creating a functional to be minimised and calling a non-linear solver such as ADAM.

```python
# Define signal model
model = MagnitudeOp() @ InversionRecovery(ti=idata_multi_ti.header.ti)
# Define loss function and combine with signal model
mse = MSEDataDiscrepancy(idata_multi_ti.data.abs())
functional = mse @ model
[...]
# Run optimization
params_result = adam(functional, [m0_start, t1_start], max_iter=max_iter, lr=lr)
```

Full example: <https://github.com/PTB-MR/mrpro/blob/main/examples/qmri_sg_challenge_2024_t1.py>

### Pulseq support

The trajectory can be calculated directly from a provided pulseq-file.

```python
# Read raw data and calculate trajectory using KTrajectoryPulseq
kdata = KData.from_file(data_file.name, KTrajectoryPulseq(seq_path=seq_file.name))
```

Full example: <https://github.com/PTB-MR/mrpro/blob/main/examples/pulseq_2d_radial_golden_angle.py>

## Contributing

### Installation for developers

1. Clone the repo
1. Clone the MRpro repository
2. Create/select a python environment
3. Open a terminal in the "MRpro" main folder
4. Install "MRpro" in editable mode with linting and testing: ``` pip install -e ".[lint,test]" ```
5. Setup Pre-Commit Hook: ``` pre-commit install ```
3. Install "MRpro" in editable mode including test dependencies: ``` pip install -e ".[test]" ```
4. Setup pre-commit hook: ``` pre-commit install ```

### Recommended IDE and Extensions

We recommend to use [Microsoft Visual Studio Code](https://code.visualstudio.com/download).

A list of recommended extensions for VSCode is given in the [.vscode/extensions.json](.vscode\extensions.json)

We recommend to use [Microsoft Visual Studio Code](https://code.visualstudio.com/download). A list of recommended extensions for VSCode is given in the [.vscode/extensions.json](.vscode\extensions.json)

### Documentation
### Style

Please have a look at our [contributor guide](https://ptb-mr.github.io/mrpro/contributor_guide.html) for more information on the structure of the repository, naming conventions and other useful information.
Please have a look at our [contributor guide](https://ptb-mr.github.io/mrpro/contributor_guide.html) for more information on the structure of the repository, naming conventions and other useful information.
40 changes: 6 additions & 34 deletions examples/direct_reconstruction.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,18 @@
"cell_type": "code",
"execution_count": null,
"id": "0c08b3fd",
"metadata": {
"lines_to_next_cell": 0
},
"metadata": {},
"outputs": [],
"source": [
"# Download raw data\n",
"import shutil\n",
"import tempfile\n",
"from pathlib import Path\n",
"\n",
"import requests\n",
"\n",
"data_folder = Path(tempfile.mkdtemp())\n",
"data_file = tempfile.NamedTemporaryFile(dir=data_folder, mode='wb', delete=False, suffix='.h5')\n",
"data_file = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5')\n",
"response = requests.get(zenodo_url + fname, timeout=30)\n",
"data_file.write(response.content)"
"data_file.write(response.content)\n",
"data_file.flush()"
]
},
{
Expand Down Expand Up @@ -76,7 +72,7 @@
"# Load in the Data from the ISMRMRD file\n",
"kdata = mrpro.data.KData.from_file(data_file.name, trajectory)\n",
"# Perform the reconstruction\n",
"reconstruction = mrpro.algorithms.reconstruction.DirectReconstruction.from_kdata(kdata)\n",
"reconstruction = mrpro.algorithms.reconstruction.DirectReconstruction(kdata)\n",
"# Use this to run on gpu: kdata = kdata.cuda()\n",
"img = reconstruction(kdata)"
]
Expand Down Expand Up @@ -197,9 +193,7 @@
"cell_type": "code",
"execution_count": null,
"id": "52d306e3",
"metadata": {
"lines_to_next_cell": 0
},
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
Expand All @@ -208,28 +202,6 @@
"assert torch.allclose(img.data, img_manual.data)\n",
"assert torch.allclose(img.data, img_more_manual.data)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1c9c3378",
"metadata": {
"lines_to_next_cell": 0
},
"outputs": [],
"source": [
"# Clean-up by removing temporary directory\n",
"shutil.rmtree(data_folder)"
]
},
{
"cell_type": "markdown",
"id": "6b76b8d4",
"metadata": {},
"source": [
"Copyright 2024 Physikalisch-Technische Bundesanstalt\n",
"Apache License 2.0. See LICENSE file for details."
]
}
],
"metadata": {
Expand Down
15 changes: 4 additions & 11 deletions examples/direct_reconstruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@
fname = 'pulseq_radial_2D_402spokes_golden_angle_with_traj.h5'
# %%
# Download raw data
import shutil
import tempfile
from pathlib import Path

import requests

data_folder = Path(tempfile.mkdtemp())
data_file = tempfile.NamedTemporaryFile(dir=data_folder, mode='wb', delete=False, suffix='.h5')
data_file = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5')
response = requests.get(zenodo_url + fname, timeout=30)
data_file.write(response.content)
data_file.flush()

# %% [markdown]
# ### Image reconstruction
# We use the DirectReconstruction class to reconstruct images from 2D radial data.
Expand All @@ -30,7 +29,7 @@
# Load in the Data from the ISMRMRD file
kdata = mrpro.data.KData.from_file(data_file.name, trajectory)
# Perform the reconstruction
reconstruction = mrpro.algorithms.reconstruction.DirectReconstruction.from_kdata(kdata)
reconstruction = mrpro.algorithms.reconstruction.DirectReconstruction(kdata)
# Use this to run on gpu: kdata = kdata.cuda()
img = reconstruction(kdata)
# %%
Expand Down Expand Up @@ -97,9 +96,3 @@
# If the assert statement did not raise an exception, the results are equal.
assert torch.allclose(img.data, img_manual.data)
assert torch.allclose(img.data, img_more_manual.data)
# %%
# Clean-up by removing temporary directory
shutil.rmtree(data_folder)
# %% [markdown]
# Copyright 2024 Physikalisch-Technische Bundesanstalt
# Apache License 2.0. See LICENSE file for details.
Loading

0 comments on commit 20f5460

Please sign in to comment.