From ce31460ca1a74170492fb0baff217fd0e7a40b80 Mon Sep 17 00:00:00 2001 From: Patrick Sadil Date: Tue, 1 Oct 2024 22:32:48 -0400 Subject: [PATCH 1/7] FIX: Repair search for precomputed transforms (#3369) --- fmriprep/data/io_spec.json | 4 +-- fmriprep/utils/bids.py | 17 ++++++--- fmriprep/utils/tests/test_derivative_cache.py | 36 +++++++++++++++++++ 3 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 fmriprep/utils/tests/test_derivative_cache.py diff --git a/fmriprep/data/io_spec.json b/fmriprep/data/io_spec.json index 5d90f184c..364cff7e3 100644 --- a/fmriprep/data/io_spec.json +++ b/fmriprep/data/io_spec.json @@ -33,7 +33,7 @@ }, "boldref2anat": { "datatype": "func", - "from": "orig", + "from": "boldref", "to": "anat", "mode": "image", "suffix": "xfm", @@ -41,7 +41,7 @@ }, "boldref2fmap": { "datatype": "func", - "from": "orig", + "from": "boldref", "mode": "image", "suffix": "xfm", "extension": ".txt" diff --git a/fmriprep/utils/bids.py b/fmriprep/utils/bids.py index 0bdc03ff1..b29275475 100644 --- a/fmriprep/utils/bids.py +++ b/fmriprep/utils/bids.py @@ -68,14 +68,21 @@ def collect_derivatives( continue derivs_cache[f'{k}_boldref'] = item[0] if len(item) == 1 else item + transforms_cache = {} for xfm, q in spec['transforms'].items(): - query = {**q, **entities} - if xfm == 'boldref2fmap': - query['to'] = fieldmap_id - item = layout.get(return_type='filename', **q) + # Transform extension will often not match provided entities + # (e.g., ".nii.gz" vs ".txt"). + # And transform suffixes will be "xfm", + # whereas relevant src file will be "bold". + query = {**entities, **q} + if xfm == 'boldref2fmap' and fieldmap_id: + # fieldmaps have ids like auto_00000 + query['to'] = fieldmap_id.replace('_', '') + item = layout.get(return_type='filename', **query) if not item: continue - derivs_cache[xfm] = item[0] if len(item) == 1 else item + transforms_cache[xfm] = item[0] if len(item) == 1 else item + derivs_cache['transforms'] = transforms_cache return derivs_cache diff --git a/fmriprep/utils/tests/test_derivative_cache.py b/fmriprep/utils/tests/test_derivative_cache.py new file mode 100644 index 000000000..1a2c59acc --- /dev/null +++ b/fmriprep/utils/tests/test_derivative_cache.py @@ -0,0 +1,36 @@ +from pathlib import Path + +import pytest + +from fmriprep.utils import bids + + +@pytest.mark.parametrize('xfm', ['boldref2fmap', 'boldref2anat', 'hmc']) +def test_transforms_found_as_str(tmp_path: Path, xfm: str): + subject = '0' + task = 'rest' + fromto = { + 'hmc': 'from-orig_to-boldref', + 'boldref2fmap': 'from-boldref_to-auto00000', + 'boldref2anat': 'from-boldref_to-anat', + }[xfm] + + to_find = tmp_path.joinpath( + f'sub-{subject}', 'func', f'sub-{subject}_task-{task}_{fromto}_mode-image_xfm.txt' + ) + to_find.parent.mkdir(parents=True) + to_find.touch() + + entities = { + 'subject': subject, + 'task': task, + 'suffix': 'bold', + 'extension': '.nii.gz', + } + + derivs = bids.collect_derivatives( + derivatives_dir=tmp_path, + entities=entities, + fieldmap_id='auto_00000', + ) + assert derivs == {'transforms': {xfm: str(to_find)}} From 565d1a97b40d0cea0422850c4a17c7df908ba6c9 Mon Sep 17 00:00:00 2001 From: Patrick Sadil Date: Wed, 2 Oct 2024 11:00:23 -0400 Subject: [PATCH 2/7] FIX: Repair and test query for precalculated baseline/boldref files (#3370) --- fmriprep/utils/bids.py | 4 ++-- fmriprep/utils/tests/test_derivative_cache.py | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/fmriprep/utils/bids.py b/fmriprep/utils/bids.py index b29275475..5ca78d91c 100644 --- a/fmriprep/utils/bids.py +++ b/fmriprep/utils/bids.py @@ -41,7 +41,7 @@ def collect_derivatives( derivatives_dir: Path, entities: dict, - fieldmap_id: str | None, + fieldmap_id: str | None = None, spec: dict | None = None, patterns: list[str] | None = None, ): @@ -62,7 +62,7 @@ def collect_derivatives( # search for both boldrefs for k, q in spec['baseline'].items(): - query = {**q, **entities} + query = {**entities, **q} item = layout.get(return_type='filename', **query) if not item: continue diff --git a/fmriprep/utils/tests/test_derivative_cache.py b/fmriprep/utils/tests/test_derivative_cache.py index 1a2c59acc..87382f73f 100644 --- a/fmriprep/utils/tests/test_derivative_cache.py +++ b/fmriprep/utils/tests/test_derivative_cache.py @@ -5,6 +5,28 @@ from fmriprep.utils import bids +@pytest.mark.parametrize('desc', ['hmc', 'coreg']) +def test_baseline_found_as_str(tmp_path: Path, desc: str): + subject = '0' + task = 'rest' + + to_find = tmp_path.joinpath( + f'sub-{subject}', 'func', f'sub-{subject}_task-{task}_desc-{desc}_boldref.nii.gz' + ) + to_find.parent.mkdir(parents=True) + to_find.touch() + + entities = { + 'subject': subject, + 'task': task, + 'suffix': 'bold', + 'extension': '.nii.gz', + } + + derivs = bids.collect_derivatives(derivatives_dir=tmp_path, entities=entities) + assert dict(derivs) == {f'{desc}_boldref': str(to_find), 'transforms': {}} + + @pytest.mark.parametrize('xfm', ['boldref2fmap', 'boldref2anat', 'hmc']) def test_transforms_found_as_str(tmp_path: Path, xfm: str): subject = '0' From 08933bf8bd3917774d750c1c0b15500749bb6309 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Wed, 2 Oct 2024 12:53:02 -0400 Subject: [PATCH 3/7] DOC: Update changelog --- CHANGES.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 6bc4c2eed..0540c355e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,12 @@ +24.1.1 (To be determined) +========================= +Bug fix release in the 24.1.x series. + +Precomputed functional derivatives were not being correcly detected. + + * FIX: Repair search for precomputed bold references (#3370) + * FIX: Repair search for precomputed transforms (#3369) + 24.1.0 (September 16, 2024) =========================== New feature release in the 24.1.x series. From 23c4636e290277fb24a2e8de783ae41049fc74f4 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Wed, 9 Oct 2024 14:52:37 -0400 Subject: [PATCH 4/7] fix: Accept warps with isotropic spacing --- fmriprep/utils/transforms.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fmriprep/utils/transforms.py b/fmriprep/utils/transforms.py index 4c9850fa3..035d78f88 100644 --- a/fmriprep/utils/transforms.py +++ b/fmriprep/utils/transforms.py @@ -78,11 +78,11 @@ def load_ants_h5(filename: Path) -> nt.base.TransformBase: spacing = transform2['TransformFixedParameters'][6:9] direction = transform2['TransformFixedParameters'][9:].reshape((3, 3)) - # We are not yet confident that we handle non-unit spacing + # We are not yet confident that we handle anisotropic spacing # or direction cosine ordering correctly. # If we confirm or fix, we can remove these checks. - if not np.allclose(spacing, 1): - raise ValueError(f'Unexpected spacing: {spacing}') + if not np.allclose(spacing, spacing[0]): + raise ValueError(f'Anisotropic spacing: {spacing}') if not np.allclose(direction, direction.T): raise ValueError(f'Asymmetric direction matrix: {direction}') From 1607996f759835e4ebbc60d15875a7401e7e3b56 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Wed, 9 Oct 2024 20:19:52 -0400 Subject: [PATCH 5/7] FIX: Drop safeguard errors; manually verified weird references --- fmriprep/utils/transforms.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/fmriprep/utils/transforms.py b/fmriprep/utils/transforms.py index 035d78f88..0b105d837 100644 --- a/fmriprep/utils/transforms.py +++ b/fmriprep/utils/transforms.py @@ -49,7 +49,8 @@ def load_ants_h5(filename: Path) -> nt.base.TransformBase: # * Always return a nitransforms TransformBase # * Construct warp affine from fixed parameters # - # This should be upstreamed into nitransforms + # This has been upstreamed into nitransforms. + # Future versions should switch to using nitransforms directly. h = h5py.File(filename) xform = ITKCompositeH5.from_h5obj(h) @@ -78,14 +79,6 @@ def load_ants_h5(filename: Path) -> nt.base.TransformBase: spacing = transform2['TransformFixedParameters'][6:9] direction = transform2['TransformFixedParameters'][9:].reshape((3, 3)) - # We are not yet confident that we handle anisotropic spacing - # or direction cosine ordering correctly. - # If we confirm or fix, we can remove these checks. - if not np.allclose(spacing, spacing[0]): - raise ValueError(f'Anisotropic spacing: {spacing}') - if not np.allclose(direction, direction.T): - raise ValueError(f'Asymmetric direction matrix: {direction}') - # ITK uses LPS affines lps_affine = compose_affine(T=origin, R=direction, Z=spacing) ras_affine = np.diag([-1, -1, 1, 1]) @ lps_affine From 106cf0cbd2bf509f3e4d0b08a836854ff084e592 Mon Sep 17 00:00:00 2001 From: Patrick Sadil Date: Wed, 2 Oct 2024 19:38:03 -0400 Subject: [PATCH 6/7] FIX: Stop excluding FS minc_modify_header used during fallback registration (#3372) --- docker/files/freesurfer7.3.2-exclude.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/docker/files/freesurfer7.3.2-exclude.txt b/docker/files/freesurfer7.3.2-exclude.txt index 1d1442092..00cc27dba 100644 --- a/docker/files/freesurfer7.3.2-exclude.txt +++ b/docker/files/freesurfer7.3.2-exclude.txt @@ -795,7 +795,6 @@ freesurfer/mni/bin/minclookup freesurfer/mni/bin/mincmakescalar freesurfer/mni/bin/mincmakevector freesurfer/mni/bin/mincmath -freesurfer/mni/bin/minc_modify_header freesurfer/mni/bin/mincpik freesurfer/mni/bin/mincstats freesurfer/mni/bin/minctoecat From 1248b6323358dfe94f627963dc7c4aa15ebc68da Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 10 Oct 2024 11:41:37 -0400 Subject: [PATCH 7/7] REL: 24.1.1 --- CHANGES.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 0540c355e..d04bde359 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,9 +1,12 @@ -24.1.1 (To be determined) +24.1.1 (October 10, 2024) ========================= Bug fix release in the 24.1.x series. -Precomputed functional derivatives were not being correcly detected. +Precomputed functional derivatives were not being correcly detected, +and a couple fixes for rare issues. + * FIX: Remove checks for unit zooms and symmetric rotations in template warp (#3376) + * FIX: Stop excluding FS minc_modify_header used during fallback registration (#3372) * FIX: Repair search for precomputed bold references (#3370) * FIX: Repair search for precomputed transforms (#3369)