Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 5 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ dependencies = [
"matplotlib >= 2.2.0",
"nibabel >= 4.0.1",
"nipype >= 1.7.0",
"niworkflows >= 1.8.0",
"niworkflows @ git+https://github.com/nipreps/niworkflows.git@master",
"numpy",
"packaging",
"pybids >= 0.11.1",
Expand Down Expand Up @@ -138,6 +138,8 @@ source = [

[tool.ruff]
line-length = 99

[tool.ruff.lint]
extend-select = [
"F",
"E",
Expand All @@ -162,10 +164,10 @@ extend-select = [
"Q",
]

[tool.ruff.flake8-quotes]
[tool.ruff.lint.flake8-quotes]
inline-quotes = "single"

[tool.ruff.extend-per-file-ignores]
[tool.ruff.lint.extend-per-file-ignores]
"*/test_*.py" = ["S101"]

[tool.ruff.format]
Expand Down
8 changes: 4 additions & 4 deletions smriprep/data/io_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
"forward": {
"datatype": "anat",
"extension": [
"h5",
"txt"
".h5",
".txt"
],
"from": "T1w",
"to": null,
Expand All @@ -61,8 +61,8 @@
"reverse": {
"datatype": "anat",
"extension": [
"h5",
"txt"
".h5",
".txt"
],
"from": null,
"to": "T1w",
Expand Down
37 changes: 20 additions & 17 deletions smriprep/utils/bids.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from pathlib import Path

from bids.layout import BIDSLayout
from niworkflows.data import load as nwf_load

from ..data import load_resource

Expand All @@ -39,36 +40,38 @@ def collect_derivatives(derivatives_dir, subject_id, std_spaces, spec=None, patt
if patterns is None:
patterns = _patterns

layout = BIDSLayout(derivatives_dir, config=['bids', 'derivatives'], validate=False)
deriv_config = nwf_load('nipreps.json')
layout = BIDSLayout(derivatives_dir, config=deriv_config, validate=False)

derivs_cache = {}
for k, q in spec['baseline'].items():
q['subject'] = subject_id
item = layout.get(return_type='filename', **q)
for key, qry in spec['baseline'].items():
qry['subject'] = subject_id
item = layout.get(return_type='filename', **qry)
if not item:
continue

derivs_cache['t1w_%s' % k] = item[0] if len(item) == 1 else item
derivs_cache[f't1w_{key}'] = item[0] if len(item) == 1 else item

transforms = derivs_cache.setdefault('transforms', {})
for space in std_spaces:
for k, q in spec['transforms'].items():
q = q.copy()
q['subject'] = subject_id
q['from'] = q['from'] or space
q['to'] = q['to'] or space
item = layout.get(return_type='filename', **q)
for _space in std_spaces:
space = _space.replace(':cohort-', '+')
for key, qry in spec['transforms'].items():
qry = qry.copy()
qry['subject'] = subject_id
qry['from'] = qry['from'] or space
qry['to'] = qry['to'] or space
item = layout.get(return_type='filename', **qry)
if not item:
continue
transforms.setdefault(space, {})[k] = item[0] if len(item) == 1 else item
transforms.setdefault(_space, {})[key] = item[0] if len(item) == 1 else item

for k, q in spec['surfaces'].items():
q['subject'] = subject_id
item = layout.get(return_type='filename', **q)
for key, qry in spec['surfaces'].items():
qry['subject'] = subject_id
item = layout.get(return_type='filename', **qry)
if not item or len(item) != 2:
continue

derivs_cache[k] = sorted(item)
derivs_cache[key] = sorted(item)

return derivs_cache

Expand Down
5 changes: 5 additions & 0 deletions smriprep/utils/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from niworkflows.data import Loader

load_data = Loader(__package__)

DERIV_SKELETON = load_data('derivatives.yml')
101 changes: 101 additions & 0 deletions smriprep/utils/tests/derivatives.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
dataset_description:
Name: smriprep-outputs
BIDSVersion: 1.9.0
DatasetType: derivative
'01':
anat:
- suffix: mask
desc: brain
- suffix: T1w
desc: preproc
- suffix: dseg
- suffix: probseg
label: CSF
- suffix: probseg
label: GM
- suffix: probseg
label: WM
- suffix: xfm
from: MNI152NLin2009cAsym
to: T1w
mode: image
extension: .h5
- suffix: xfm
from: T1w
to: MNI152NLin2009cAsym
mode: image
extension: .h5
- suffix: xfm
from: T1w
to: MNIPediatricAsym+3
mode: image
extension: .h5
- suffix: xfm
from: MNIPediatricAsym+3
to: T1w
mode: image
extension: .h5
- suffix: white
hemi: L
extension: .surf.gii
- suffix: white
hemi: R
extension: .surf.gii
- suffix: pial
hemi: L
extension: .surf.gii
- suffix: pial
hemi: R
extension: .surf.gii
- suffix: midthickness
hemi: L
extension: .surf.gii
- suffix: midthickness
hemi: R
extension: .surf.gii
- suffix: sphere
hemi: L
extension: .surf.gii
- suffix: sphere
hemi: R
extension: .surf.gii
- suffix: sphere
hemi: L
desc: reg
extension: .surf.gii
- suffix: sphere
hemi: R
desc: reg
extension: .surf.gii
- suffix: sphere
hemi: L
space: fsLR
desc: reg
extension: .surf.gii
- suffix: sphere
hemi: R
space: fsLR
desc: reg
extension: .surf.gii
- suffix: sphere
hemi: L
space: fsLR
desc: msmsulc
extension: .surf.gii
- suffix: sphere
hemi: R
space: fsLR
desc: msmsulc
extension: .surf.gii
- suffix: thickness
hemi: L
extension: .shape.gii
- suffix: thickness
hemi: R
extension: .shape.gii
- suffix: sulc
hemi: L
extension: .shape.gii
- suffix: sulc
hemi: R
extension: .shape.gii
30 changes: 30 additions & 0 deletions smriprep/utils/tests/test_bids.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from niworkflows.utils.testing import generate_bids_skeleton

from ..bids import collect_derivatives
from . import DERIV_SKELETON


def test_collect_derivatives(tmp_path):
deriv_dir = tmp_path / 'derivatives'
generate_bids_skeleton(deriv_dir, str(DERIV_SKELETON))
output_spaces = ['MNI152NLin2009cAsym', 'MNIPediatricAsym:cohort-3']
collected = collect_derivatives(deriv_dir, '01', output_spaces)
for suffix in ('preproc', 'mask', 'dseg'):
assert collected[f't1w_{suffix}']
assert len(collected['t1w_tpms']) == 3
xfms = collected['transforms']
for space in output_spaces:
assert xfms[space]['reverse']
assert xfms[space]['forward']
for surface in (
'white',
'pial',
'midthickness',
'sphere',
'thickness',
'sulc',
'sphere_reg',
'sphere_reg_fsLR',
'sphere_reg_msm',
):
assert len(collected[surface]) == 2
19 changes: 18 additions & 1 deletion smriprep/workflows/fit/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,12 @@ def init_register_template_wf(
mem_gb=2,
)

fmt_cohort = pe.Node(
niu.Function(function=_fmt_cohort, output_names=['template', 'spec']),
name='fmt_cohort',
run_without_submitting=True,
)

# fmt:off
workflow.connect([
(inputnode, split_desc, [('template', 'template')]),
Expand All @@ -202,8 +208,12 @@ def init_register_template_wf(
]),
(trunc_mov, registration, [
('output_image', 'moving_image')]),
(split_desc, outputnode, [
(split_desc, fmt_cohort, [
('name', 'template'),
('spec', 'spec'),
]),
(fmt_cohort, outputnode, [
('template', 'template'),
('spec', 'template_spec'),
]),
(registration, outputnode, [
Expand All @@ -225,3 +235,10 @@ def _make_outputnode(workflow, out_fields, joinsource):
workflow.connect([(pout, out, [(f, f) for f in out_fields])])
return pout
return pe.Node(niu.IdentityInterface(fields=out_fields), name='outputnode')


def _fmt_cohort(template, spec):
cohort = spec.pop('cohort', None)
if cohort is not None:
template = f'{template}:cohort-{cohort}'
return template, spec