Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
12 changes: 12 additions & 0 deletions .github/workflows/book.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ jobs:
- name: Install project environment
run: pixi install --locked

- name: Prepare tutorial data
run: |
set -xeuo pipefail
data_dir="${{ github.workspace }}/data"
data_file="$data_dir/dwi_full_brainmask.h5"
mkdir -p "$data_dir"
curl -L \
https://files.osf.io/v1/resources/8k95s/providers/osfstorage/68e5464a451cf9cf1fc51a53 \
--output "$data_file"
test -s "$data_file"
echo "NIPREPS_TUTORIAL_DATA=$data_file" >> "$GITHUB_ENV"

# Build the page
- name: Build the book
run: pixi run build-book
Expand Down
22 changes: 5 additions & 17 deletions docs/tutorial/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ We must reload the dataset again to use it in this notebook.
```

```{code-cell} python
from nifreeze.data.dmri import DWI
from nifreeze.data.splitting import lovo_split
from nireports.reportlets.modality.dwi import plot_dwi
from tutorial_data import load_tutorial_dmri_dataset

dmri_dataset = DWI.from_filename("../../data/dwi.h5")
dmri_dataset = load_tutorial_dmri_dataset()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Make tutorial_data importable during notebook execution

The notebooks now rely on from tutorial_data import load_tutorial_dmri_dataset, but tutorial_data.py lives in the repository root and is neither installed nor added to PYTHONPATH. When the pages are executed from docs/tutorial (the default working directory for jupyter-book and for users running a single notebook), only that directory is on sys.path, so the import raises ModuleNotFoundError and the build fails before any cells run. Consider moving the helper into the docs tree or explicitly adding the repo root to sys.path before the import.

Useful? React with 👍 / 👎.

```

## Implementing a trivial model
Expand Down Expand Up @@ -190,21 +190,9 @@ We will use the wrap around DIPY's implementation that we distribute with `nifre
```{code-cell} python
:tags: [remove-cell]

from tempfile import mkstemp
from pathlib import Path
import requests

if dmri_dataset._filepath.exists():
dmri_dataset._filepath.unlink()
url = "https://files.osf.io/v1/resources/8k95s/providers/osfstorage/68e5464a451cf9cf1fc51a53"
datapath = Path(mkstemp(suffix=".h5")[1])
if datapath.stat().st_size == 0:
datapath.write_bytes(
requests.get(url, allow_redirects=True).content
)

dmri_dataset = DWI.from_filename(datapath)
datapath.unlink()
from tutorial_data import load_tutorial_dmri_dataset

dmri_dataset = load_tutorial_dmri_dataset()

# Let's generate index 88 of the dataset:
test_data, _, test_b = dmri_dataset[88]
Expand Down
17 changes: 4 additions & 13 deletions docs/tutorial/registration.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,18 @@ kernelspec:

import warnings
from IPython.display import HTML
import requests
from tempfile import mkstemp
from pathlib import Path
import numpy as np

import nibabel as nb
import numpy as np

from nifreeze.data.dmri import DWI
from nifreeze.data.filtering import advanced_clip
from nireports.reportlets.modality.dwi import plot_dwi
from tutorial_data import load_tutorial_dmri_dataset

warnings.filterwarnings("ignore")

url = "https://files.osf.io/v1/resources/8k95s/providers/osfstorage/68e5464a451cf9cf1fc51a53"
datapath = Path(mkstemp(suffix=".h5")[1])
if datapath.stat().st_size == 0:
datapath.write_bytes(
requests.get(url, allow_redirects=True).content
)

dmri_dataset = DWI.from_filename(datapath)
datapath.unlink()
dmri_dataset = load_tutorial_dmri_dataset()


def _to_nifti(
Expand Down
17 changes: 3 additions & 14 deletions docs/tutorial/solution.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,16 @@ kernelspec:
:tags: [remove-cell]

import warnings
from pathlib import Path

warnings.filterwarnings("ignore")

from tempfile import mkstemp
from pathlib import Path
import requests

from nifreeze.data.dmri import DWI
from nifreeze.utils.iterators import random_iterator
from tutorial_data import load_tutorial_dmri_dataset

url = "https://files.osf.io/v1/resources/8k95s/providers/osfstorage/68e5464a451cf9cf1fc51a53"
datapath = Path(mkstemp(suffix=".h5")[1])
if datapath.stat().st_size == 0:
datapath.write_bytes(
requests.get(url, allow_redirects=True).content
)

dmri_dataset = DWI.from_filename(datapath)
dmri_dataset = load_tutorial_dmri_dataset()
dmri_dataset.dataobj = dmri_dataset.dataobj[..., :32]
dmri_dataset.gradients = dmri_dataset.gradients[..., :32]
datapath.unlink()
```

Once we have finalized the main components of the solution, it is time for integration.
Expand Down
39 changes: 39 additions & 0 deletions tutorial_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Utilities for accessing shared tutorial datasets."""
from __future__ import annotations

import os
from pathlib import Path
from typing import Final

import requests

from nifreeze.data.dmri import DWI

__all__ = ["ensure_tutorial_dwi_path", "load_tutorial_dmri_dataset"]

_DATA_URL: Final[str] = (
"https://files.osf.io/v1/resources/8k95s/providers/osfstorage/68e5464a451cf9cf1fc51a53"
)
_DEFAULT_FILENAME: Final[str] = "dwi_full_brainmask.h5"
_ENV_VAR: Final[str] = "NIPREPS_TUTORIAL_DATA"


def _resolve_data_path(filename: str = _DEFAULT_FILENAME) -> Path:
env_path = os.environ.get(_ENV_VAR)
return Path(env_path) if env_path else Path("data") / filename


def ensure_tutorial_dwi_path(filename: str = _DEFAULT_FILENAME) -> Path:
"""Return the path to the cached tutorial DWI dataset, downloading it if needed."""
datapath = _resolve_data_path(filename)
if not datapath.exists():
datapath.parent.mkdir(parents=True, exist_ok=True)
response = requests.get(_DATA_URL, allow_redirects=True, timeout=60)
response.raise_for_status()
datapath.write_bytes(response.content)
return datapath


def load_tutorial_dmri_dataset(filename: str = _DEFAULT_FILENAME) -> DWI:
"""Load the tutorial DWI dataset from disk, ensuring it is available."""
return DWI.from_filename(ensure_tutorial_dwi_path(filename))
Loading