Skip to content

Commit

Permalink
Merge branch 'main' into Unit_Testing_Tolerances
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverchampion authored Jan 4, 2025
2 parents 1d26bad + c679a0f commit 9beef6d
Show file tree
Hide file tree
Showing 38 changed files with 4,341 additions and 1,493 deletions.
78 changes: 78 additions & 0 deletions .github/workflows/docker-build-and-run.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Build and Run Docker
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, edited]
branches:
- main
- "docker/**"
jobs:
build-and-run-docker:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Generate input files
run: |
python -m Docker.generate_signal_docker_test
- name: Verify input files
run: |
for file in ivim_simulation.nii.gz ivim_simulation.bval ivim_simulation.bvec; do
if [ ! -f "$file" ]; then
echo "Error: $file not found"
exit 1
fi
done
echo "All input files generated successfully"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Docker image
run: |
docker build -t tf2.4_ivim-mri_codecollection -f Docker/Dockerfile .
- name: Run Docker container
run: |
docker run --rm --name TF2.4_IVIM-MRI_CodeCollection \
-v ${{ github.workspace }}:/usr/src/app \
-v ${{ github.workspace }}:/usr/app/output \
tf2.4_ivim-mri_codecollection ivim_simulation.nii.gz ivim_simulation.bvec ivim_simulation.bval
- name: Verify output files
run: |
for file in f.nii.gz dp.nii.gz d.nii.gz; do
if [ ! -f "$file" ]; then
echo "Error: $file not found"
exit 1
fi
done
echo "All output files generated successfully"
- name: Clean up artifacts and Docker image
run: |
docker rmi tf2.4_ivim-mri_codecollection || true
rm -f tf2.4_ivim-mri_codecollection.tar.gz
rm -f ${{ github.workspace }}/f.nii.gz
rm -f ${{ github.workspace }}/dp.nii.gz
rm -f ${{ github.workspace }}/d.nii.gz
rm -f ${{ github.workspace }}/ivim_simulation.nii.gz
rm -f ${{ github.workspace }}/ivim_simulation.bval
rm -f ${{ github.workspace }}/ivim_simulation.bvec
- name: Cleanup Docker
run: |
docker system prune -a --force
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build & Deploy Documentation
name: Build & Deploy Website

on:
workflow_run:
Expand Down Expand Up @@ -33,25 +33,50 @@ jobs:
run: |
pip install -r requirements.txt
# Action to download artifacts from a different workflow (analysis.yml)
# Action Figures artifact
- name: 'Download artifact'
if: ${{ github.event.workflow_run.conclusion == 'success' }}
uses: ./.github/actions/download-artifact
with:
name: 'Figures'
# Action analysis data artifact
- name: 'Download analysis data'
if: ${{ github.event.workflow_run.conclusion == 'success' }}
uses: ./.github/actions/download-artifact
with:
name: 'Data'

- name: Run the test that generates the plots report.
run: |
pytest tests/IVIMmodels/unit_tests/test_ivim_fit.py --json-report
mv .report.json utilities/
python utilities/report-summary.py .report.json report-summary.json
- name: 'Filter and compress results file.'
run: python utilities/reduce_output_size.py test_output.csv test_output.csv.gz

- name: Build html
- name: move data to the dashboard folder
run: |
mv test_output.csv.gz website/dashboard
mv report-summary.json website/dashboard
- name: Build documentation
run: |
mkdir docs/_static
mv *.pdf docs/_static/
sphinx-apidoc -o docs src
cd docs/
make html
- name: move data to the website folder
run: |
mv "docs/_build/html" "website/documentation"
- name: Upload docs artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'docs/_build/html'
path: 'website'

deploy:
needs: build
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ __pycache__/
*.raw
bvals.txt
download
.Introduction_to_TF24_IVIM-MRI_CodeCollection_github_and_IVIM_Analysis_using_Python.ipynb
.ipynb_checkpoints
md5sums.txt
*.gz
*.zip
Expand Down
42 changes: 42 additions & 0 deletions Docker/generate_signal_docker_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import numpy as np
import nibabel as nib
from utilities.data_simulation.GenerateData import GenerateData
from WrapImage.nifti_wrapper import save_nifti_file


def save_bval_bvec(filename, values):
if filename.endswith('.bval'):
# Convert list to a space-separated string for bval
values_string = ' '.join(map(str, values))
elif filename.endswith('.bvec'):
# Convert 2D list to a line-separated, space-separated string for bvec
values_string = '\n'.join(' '.join(map(str, row)) for row in values)
else:
raise ValueError("Unsupported file extension. Use '.bval' or '.bvec'.")

with open(filename, 'w') as file:
file.write(values_string)

# Set random seed for reproducibility
np.random.seed(42)
# Create GenerateData instance
gd = GenerateData()

# Generate random input data
shape = (10, 10, 5)
f_in = np.random.uniform(low=0, high=1, size=shape)
D_in = np.random.uniform(low=0, high=1e-3, size=shape)
Dp_in = np.random.uniform(low=0, high=1e-1, size=shape)
S0 = 1000 # Setting a constant S0 for simplicity
bvals = np.array([0, 50, 100, 500, 1000])
bvals_reshaped = np.broadcast_to(bvals, shape)

# Generate IVIM signal
signals = gd.ivim_signal(D_in, Dp_in, f_in, S0, bvals_reshaped)

# Save the generated image as a NIfTI file
save_nifti_file(signals, "ivim_simulation.nii.gz")
# Save the bval in a file
save_bval_bvec("ivim_simulation.bval", [0, 50, 100, 500, 1000])
# Save the bvec value
save_bval_bvec("ivim_simulation.bvec", [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The ISMRM Open Science Initiative for Perfusion Imaging (OSIPI) is an initiative
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/).

We have some useful tools and further documentation on https://osipi.github.io/TF2.4_IVIM-MRI_CodeCollection/.

## How to contribute

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

If you would like to use code from the repository and/or are new to Github or IVIM, please see the jupyter notebook below:
* [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)

## Repository Organization

The repository is organized in four main folders along with configuration files for automated testing.
Expand All @@ -32,4 +37,4 @@ The **utils** folder contains various helpful tools.
## View Testing Reports
[![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)
[![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)
[![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)
[![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)
12 changes: 7 additions & 5 deletions WrapImage/nifti_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ def save_nifti_file(data, output_file, affine=None, **kwargs):
For saving the 3d nifti images of the output of the algorithm
"""
if affine is None:
affine = np.eye(data.ndim + 1)
affine = np.eye(4)
else:
affine = np.array(affine.reshape(4, 4))
output_img = nib.nifti1.Nifti1Image(data, affine , **kwargs)
nib.save(output_img, output_file)

Expand Down Expand Up @@ -107,10 +109,10 @@ def loop_over_first_n_minus_1_dimensions(arr):
n = data.ndim
total_iteration = np.prod(data.shape[:n-1])
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):
[f_fit, Dp_fit, D_fit] = fit.osipi_fit(view, bvals)
f_image.append(f_fit)
Dp_image.append(Dp_fit)
D_image.append(D_fit)
fit_result = fit.osipi_fit(view, bvals)
f_image.append(fit_result["f"])
Dp_image.append(fit_result["D*"])
D_image.append(fit_result["D"])

# Convert lists to NumPy arrays
f_image = np.array(f_image)
Expand Down

Large diffs are not rendered by default.

Loading

0 comments on commit 9beef6d

Please sign in to comment.