This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
NiFreeze is a framework for estimation of volume-to-volume motion and volume-wise artifacts (such as eddy currents in diffusion-weighted volumes of dMRI) in 4D neuroimaging (dMRI, fMRI, PET). Part of the NiPreps ecosystem. Source lives under src/nifreeze/, tests under test/.
python -m hatch version # generates src/nifreeze/_version.py-
Some software needs to be installed prior to testing, for example ANTs
conda install -c conda-forge ants=2.4 libitk=5.3 libiconv
-
Notebooks generate figures with latex commands inside, therefore:
sudo apt install texlive texlive-latex-extra texlive-fonts-recommended cm-super dvipng
-
A number of tests use pre-existing data (stored in the git-annex-enabled GIN G-Node https://gin.g-node.org/nipreps-data/tests-nifreeze) that need be found at location indicated by the environment variable
TEST_DATA_HOME:uvx datalad-installer --sudo ok git-annex uv tool install --with=datalad-osf --with=datalad-next datalad uv tool install --with=datalad-next datalad-osf datalad wtf # check datalad is installed # Install the dataset if [[ ! -d "${TEST_DATA_HOME}" ]]; then datalad install -rg --source=https://gin.g-node.org/nipreps-data/tests-nifreeze ${TEST_DATA_HOME} else cd ${TEST_DATA_HOME} datalad update --merge -r . datalad get -r -J4 * fi
Files in GIN's annex can be retrieved using curl by composing the URL like this one for the
dmri_data/motion_test_data/dwi_motion.h5file -
Some test data comes from DIPY:
echo "from dipy.data import fetch_stanford_hardi; fetch_stanford_hardi()" > fetch.py uv tool install dipy uv add --script fetch.py dipy uv run fetch.py
Details about testing are found in .github/workflows/test.yml
pytest test/ # unit tests only
pytest --doctest-modules src/nifreeze # doctests only
pytest -sv --doctest-modules src test # both (what tox runs)
pytest test/test_model_dmri.py # single test file
pytest test/test_model_dmri.py::test_name # single test
pytest test/ -n auto # parallel executionFull test suite via tox: tox -v (install with uv tool install --with=tox-uv --with=tox-gh-actions tox)
Other tox environments: tox -e typecheck, tox -e spellcheck, tox -e docs
python -m ruff check --fix <files> # lint and auto-fix
python -m run ruff format <files> # reformatRuff config: line-length 99, target Python 3.10, rules: F, E, C, W, B, I, ICN. Import convention: nibabel aliased as nb.
tox -e typechecktox -e spellcheckmake -C docs/ htmlThree-layer design: Data → Model → Estimator
-
Data (
nifreeze/data/):BaseDataset(attrs-based) with modality subclasses indmri/(DWI) andpet/. Handles NIfTI/HDF5 I/O, brain masks, affine transforms, and train/test splitting (splitting.py). -
Model (
nifreeze/model/):BaseModelABC withfit_predict(index, **kwargs) → ndarray.ModelFactory.init(model_name)instantiates models. Implementations: DTI, DKI, AverageDWI, GP (indmri.py), BSpline PET (pet.py), Gaussian Process Regression (gpr.py). Models operate in Leave-One-Volume-Out (LOVO) mode or single-fit mode. -
Estimator (
nifreeze/estimator.py): Orchestrates model fitting + ANTs registration per volume. Core method:Estimator.run(dataset, ...). Supports chaining viaprev_model. Uses joblib for parallel execution. -
Registration (
nifreeze/registration/): ANTs wrappers via nipype. Config YAML files inregistration/config/. -
CLI: Entry point
nifreeze→nifreeze.cli.run:main, parser incli/parser.py. -
Utilities: Traversal strategies (
utils/iterators.py), image operations (utils/ndimage.py), visualization (viz/), analysis/filtering (analysis/).
- External test data from GIN (git-annex): location set by
TEST_DATA_HOME(default~/.nifreeze-tests). Some tests use DIPY's Stanford HARDI dataset (DIPY_HOME). TEST_OUTPUT_DIRandTEST_WORK_DIRcontrol artifact persistence (unset = discarded).conftest.pyprovides auto-use fixtures:random_number_generator(fixed seed 1234),setup_random_dwi_data,setup_random_pet_data,setup_random_base_data, etc. Tests use custom markers like@pytest.mark.random_dwi_data(b0_thres, vol_size, use_random_gtab).- ANTs must be installed for registration tests (
conda install -c conda-forge ants=2.4 libitk=5.3 libiconv). - Pytest is configured with
--doctest-modulesby default andPYTHONHASHSEED=0.
- Semantic commit format:
<type>[(<scope>)]: <message>— types:fix:,enh:,sty:,doc:,mnt:, etc. Scope parenthetical is optional. - Commit messages must be terse — as short as possible. Add a longer body only when the commit signals something genuinely important (something broken, a security-affecting change, major API/concern changes).
- PR titles use uppercase (e.g.,
FIX: <description>,ENH: <description>, description is title-case). PRs link existing issues and other PRs if necessary in the message body, using GitHub's keywords, e.g.,Resolves: #17,Fixes: #19,X-Refs: #29. - PR bodies can be less terse than commits, but must stay direct and to the point.
- Before opening a PR, always check that there is an open issue the PR responds to. If there is none, do not open the PR — offer to open an issue instead.
- Always open PRs as drafts, so humans do not start reviewing before the PR is ready for human review.
- Branch names follow the convention
<type>/<identifier>[-gh<issue-number>]. If the new branch addresses a bug/feature with an existing issue open, the issue is referenced with the optional suffix (e.g.,fix/memory-leak-gh127for a memory leak reported in issue #127).
- Calendar-based versioning (nipreps-calver) via hatch-vcs
- Python 3.10+ required; code targets
py310 - Uses
attrsfor data classes (not dataclasses) nibabelis always imported asnb