Skip to content

Commit 9beef6d

Browse files
Merge branch 'main' into Unit_Testing_Tolerances
2 parents 1d26bad + c679a0f commit 9beef6d

38 files changed

+4341
-1493
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Build and Run Docker
2+
on:
3+
push:
4+
branches:
5+
- main
6+
pull_request:
7+
types: [opened, synchronize, edited]
8+
branches:
9+
- main
10+
- "docker/**"
11+
jobs:
12+
build-and-run-docker:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
18+
- name: Set up Python
19+
uses: actions/setup-python@v4
20+
with:
21+
python-version: '3.x'
22+
23+
- name: Install Python dependencies
24+
run: |
25+
python -m pip install --upgrade pip
26+
pip install -r requirements.txt
27+
28+
- name: Generate input files
29+
run: |
30+
python -m Docker.generate_signal_docker_test
31+
32+
- name: Verify input files
33+
run: |
34+
for file in ivim_simulation.nii.gz ivim_simulation.bval ivim_simulation.bvec; do
35+
if [ ! -f "$file" ]; then
36+
echo "Error: $file not found"
37+
exit 1
38+
fi
39+
done
40+
echo "All input files generated successfully"
41+
42+
- name: Set up Docker Buildx
43+
uses: docker/setup-buildx-action@v3
44+
45+
- name: Build Docker image
46+
run: |
47+
docker build -t tf2.4_ivim-mri_codecollection -f Docker/Dockerfile .
48+
49+
- name: Run Docker container
50+
run: |
51+
docker run --rm --name TF2.4_IVIM-MRI_CodeCollection \
52+
-v ${{ github.workspace }}:/usr/src/app \
53+
-v ${{ github.workspace }}:/usr/app/output \
54+
tf2.4_ivim-mri_codecollection ivim_simulation.nii.gz ivim_simulation.bvec ivim_simulation.bval
55+
56+
- name: Verify output files
57+
run: |
58+
for file in f.nii.gz dp.nii.gz d.nii.gz; do
59+
if [ ! -f "$file" ]; then
60+
echo "Error: $file not found"
61+
exit 1
62+
fi
63+
done
64+
echo "All output files generated successfully"
65+
66+
- name: Clean up artifacts and Docker image
67+
run: |
68+
docker rmi tf2.4_ivim-mri_codecollection || true
69+
rm -f tf2.4_ivim-mri_codecollection.tar.gz
70+
rm -f ${{ github.workspace }}/f.nii.gz
71+
rm -f ${{ github.workspace }}/dp.nii.gz
72+
rm -f ${{ github.workspace }}/d.nii.gz
73+
rm -f ${{ github.workspace }}/ivim_simulation.nii.gz
74+
rm -f ${{ github.workspace }}/ivim_simulation.bval
75+
rm -f ${{ github.workspace }}/ivim_simulation.bvec
76+
- name: Cleanup Docker
77+
run: |
78+
docker system prune -a --force

.github/workflows/documentation.yml renamed to .github/workflows/website.yml

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build & Deploy Documentation
1+
name: Build & Deploy Website
22

33
on:
44
workflow_run:
@@ -33,25 +33,50 @@ jobs:
3333
run: |
3434
pip install -r requirements.txt
3535
36-
# Action to download artifacts from a different workflow (analysis.yml)
36+
# Action Figures artifact
3737
- name: 'Download artifact'
3838
if: ${{ github.event.workflow_run.conclusion == 'success' }}
3939
uses: ./.github/actions/download-artifact
4040
with:
4141
name: 'Figures'
42+
# Action analysis data artifact
43+
- name: 'Download analysis data'
44+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
45+
uses: ./.github/actions/download-artifact
46+
with:
47+
name: 'Data'
48+
49+
- name: Run the test that generates the plots report.
50+
run: |
51+
pytest tests/IVIMmodels/unit_tests/test_ivim_fit.py --json-report
52+
mv .report.json utilities/
53+
python utilities/report-summary.py .report.json report-summary.json
54+
55+
- name: 'Filter and compress results file.'
56+
run: python utilities/reduce_output_size.py test_output.csv test_output.csv.gz
4257

43-
- name: Build html
58+
- name: move data to the dashboard folder
59+
run: |
60+
mv test_output.csv.gz website/dashboard
61+
mv report-summary.json website/dashboard
62+
63+
64+
- name: Build documentation
4465
run: |
4566
mkdir docs/_static
4667
mv *.pdf docs/_static/
4768
sphinx-apidoc -o docs src
4869
cd docs/
4970
make html
5071
72+
- name: move data to the website folder
73+
run: |
74+
mv "docs/_build/html" "website/documentation"
75+
5176
- name: Upload docs artifact
5277
uses: actions/upload-pages-artifact@v3
5378
with:
54-
path: 'docs/_build/html'
79+
path: 'website'
5580

5681
deploy:
5782
needs: build

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ __pycache__/
1010
*.raw
1111
bvals.txt
1212
download
13+
.Introduction_to_TF24_IVIM-MRI_CodeCollection_github_and_IVIM_Analysis_using_Python.ipynb
14+
.ipynb_checkpoints
1315
md5sums.txt
1416
*.gz
1517
*.zip

Docker/generate_signal_docker_test.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import numpy as np
2+
import nibabel as nib
3+
from utilities.data_simulation.GenerateData import GenerateData
4+
from WrapImage.nifti_wrapper import save_nifti_file
5+
6+
7+
def save_bval_bvec(filename, values):
8+
if filename.endswith('.bval'):
9+
# Convert list to a space-separated string for bval
10+
values_string = ' '.join(map(str, values))
11+
elif filename.endswith('.bvec'):
12+
# Convert 2D list to a line-separated, space-separated string for bvec
13+
values_string = '\n'.join(' '.join(map(str, row)) for row in values)
14+
else:
15+
raise ValueError("Unsupported file extension. Use '.bval' or '.bvec'.")
16+
17+
with open(filename, 'w') as file:
18+
file.write(values_string)
19+
20+
# Set random seed for reproducibility
21+
np.random.seed(42)
22+
# Create GenerateData instance
23+
gd = GenerateData()
24+
25+
# Generate random input data
26+
shape = (10, 10, 5)
27+
f_in = np.random.uniform(low=0, high=1, size=shape)
28+
D_in = np.random.uniform(low=0, high=1e-3, size=shape)
29+
Dp_in = np.random.uniform(low=0, high=1e-1, size=shape)
30+
S0 = 1000 # Setting a constant S0 for simplicity
31+
bvals = np.array([0, 50, 100, 500, 1000])
32+
bvals_reshaped = np.broadcast_to(bvals, shape)
33+
34+
# Generate IVIM signal
35+
signals = gd.ivim_signal(D_in, Dp_in, f_in, S0, bvals_reshaped)
36+
37+
# Save the generated image as a NIfTI file
38+
save_nifti_file(signals, "ivim_simulation.nii.gz")
39+
# Save the bval in a file
40+
save_bval_bvec("ivim_simulation.bval", [0, 50, 100, 500, 1000])
41+
# Save the bvec value
42+
save_bval_bvec("ivim_simulation.bvec", [[1, 0, 0], [0, 1, 0], [0, 0, 1]])

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ The ISMRM Open Science Initiative for Perfusion Imaging (OSIPI) is an initiative
66
77
This **IVIM code collection** code library is maintained by OSIPI [Taskforce 2.4](https://www.osipi.org/task-force-2-4/) (*currently not available*) and aims to collect, test and share open-source code related to intravoxel incoherent motion (IVIM) analysis of diffusion encoded MRI data to be used in research and software development. Code contributions can include any code related IVIM analysis (denoising, motion correction, model fitting, etc.), but at an initial phase, development of tests and other features of the repository will predominantly focus on fitting algorithms. A goal of the IVIM OSIPI task force is to develop a fully tested and harmonized code library, building upon the contributions obtained through this initiative. Documentation and analysis are available on the [OSIPI TF2.4](https://osipi.github.io/TF2.4_IVIM-MRI_CodeCollection/).
88

9+
We have some useful tools and further documentation on https://osipi.github.io/TF2.4_IVIM-MRI_CodeCollection/.
10+
911
## How to contribute
1012

1113
If you would like to get involve in OSIPI and work within the task force, please email the contacts listed on our website.
@@ -17,6 +19,9 @@ If you would like to contribute with code, please follow the instructions below:
1719
* [Guidelines for IVIM code contribution](doc/guidelines_for_contributions.md)
1820
* [Guidelines to creating a test file](doc/creating_test.md)
1921

22+
If you would like to use code from the repository and/or are new to Github or IVIM, please see the jupyter notebook below:
23+
* [Introduction to TF2.4_IVIM-MRI_CodeCollection github and IVIM Analysis using Python](doc/Introduction_to_TF24_IVIM-MRI_CodeCollection_github_and_IVIM_Analysis_using_Python.ipynb)
24+
2025
## Repository Organization
2126

2227
The repository is organized in four main folders along with configuration files for automated testing.
@@ -32,4 +37,4 @@ The **utils** folder contains various helpful tools.
3237
## View Testing Reports
3338
[![Unit tests](https://github.com/OSIPI/TF2.4_IVIM-MRI_CodeCollection/actions/workflows/unit_test.yml/badge.svg?branch=main)](https://github.com/OSIPI/TF2.4_IVIM-MRI_CodeCollection/actions/workflows/unit_test.yml)
3439
[![Algorithm Analysis](https://github.com/OSIPI/TF2.4_IVIM-MRI_CodeCollection/actions/workflows/analysis.yml/badge.svg?branch=main)](https://github.com/OSIPI/TF2.4_IVIM-MRI_CodeCollection/actions/workflows/analysis.yml)
35-
[![Build & Deploy Documentation](https://github.com/OSIPI/TF2.4_IVIM-MRI_CodeCollection/actions/workflows/documentation.yml/badge.svg?branch=main)](https://github.com/OSIPI/TF2.4_IVIM-MRI_CodeCollection/actions/workflows/documentation.yml)
40+
[![Build & Deploy Website](https://github.com/OSIPI/TF2.4_IVIM-MRI_CodeCollection/actions/workflows/website.yml/badge.svg?branch=main)](https://github.com/OSIPI/TF2.4_IVIM-MRI_CodeCollection/actions/workflows/website.yml)

WrapImage/nifti_wrapper.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ def save_nifti_file(data, output_file, affine=None, **kwargs):
5656
For saving the 3d nifti images of the output of the algorithm
5757
"""
5858
if affine is None:
59-
affine = np.eye(data.ndim + 1)
59+
affine = np.eye(4)
60+
else:
61+
affine = np.array(affine.reshape(4, 4))
6062
output_img = nib.nifti1.Nifti1Image(data, affine , **kwargs)
6163
nib.save(output_img, output_file)
6264

@@ -107,10 +109,10 @@ def loop_over_first_n_minus_1_dimensions(arr):
107109
n = data.ndim
108110
total_iteration = np.prod(data.shape[:n-1])
109111
for idx, view in tqdm(loop_over_first_n_minus_1_dimensions(data), desc=f"{args.algorithm} is fitting", dynamic_ncols=True, total=total_iteration):
110-
[f_fit, Dp_fit, D_fit] = fit.osipi_fit(view, bvals)
111-
f_image.append(f_fit)
112-
Dp_image.append(Dp_fit)
113-
D_image.append(D_fit)
112+
fit_result = fit.osipi_fit(view, bvals)
113+
f_image.append(fit_result["f"])
114+
Dp_image.append(fit_result["D*"])
115+
D_image.append(fit_result["D"])
114116

115117
# Convert lists to NumPy arrays
116118
f_image = np.array(f_image)

doc/Introduction_to_TF24_IVIM-MRI_CodeCollection_github_and_IVIM_Analysis_using_Python.ipynb

Lines changed: 1082 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)