Skip to content

Commit 92773f5

Browse files
authored
Merge pull request #370 from effigies/enh/fit-msmsulc
ENH: Add sphere registration to fit workflow, check for precomputed
2 parents f6b842f + 3b5b230 commit 92773f5

File tree

8 files changed

+449
-267
lines changed

8 files changed

+449
-267
lines changed

.circleci/config.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ _machine_defaults: &machine_defaults
1212
_python_defaults: &python_defaults
1313
docker:
1414
- image: cimg/python:3.10.9
15+
auth:
16+
username: $DOCKER_USER
17+
password: $DOCKER_PAT
1518
working_directory: /tmp/src/smriprep
1619

1720
_docker_auth: &docker_auth
@@ -43,6 +46,9 @@ _pull_from_registry: &pull_from_registry
4346
docs_deploy: &docs
4447
docker:
4548
- image: node:8.10.0
49+
auth:
50+
username: $DOCKER_USER
51+
password: $DOCKER_PAT
4652
working_directory: /tmp/gh-pages
4753
steps:
4854
- run:

.circleci/ds005_outputs.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ smriprep/sub-01/anat/sub-01_desc-brain_mask.json
1616
smriprep/sub-01/anat/sub-01_desc-brain_mask.nii.gz
1717
smriprep/sub-01/anat/sub-01_desc-preproc_T1w.json
1818
smriprep/sub-01/anat/sub-01_desc-preproc_T1w.nii.gz
19+
smriprep/sub-01/anat/sub-01_desc-ribbon_mask.json
1920
smriprep/sub-01/anat/sub-01_desc-ribbon_mask.nii.gz
2021
smriprep/sub-01/anat/sub-01_dseg.nii.gz
2122
smriprep/sub-01/anat/sub-01_from-fsnative_to-T1w_mode-image_xfm.txt
@@ -27,6 +28,7 @@ smriprep/sub-01/anat/sub-01_hemi-L_midthickness.surf.gii
2728
smriprep/sub-01/anat/sub-01_hemi-L_pial.surf.gii
2829
smriprep/sub-01/anat/sub-01_hemi-L_space-fsLR_desc-msmsulc_sphere.surf.gii
2930
smriprep/sub-01/anat/sub-01_hemi-L_space-fsLR_desc-reg_sphere.surf.gii
31+
smriprep/sub-01/anat/sub-01_hemi-L_sphere.surf.gii
3032
smriprep/sub-01/anat/sub-01_hemi-L_sulc.shape.gii
3133
smriprep/sub-01/anat/sub-01_hemi-L_thickness.shape.gii
3234
smriprep/sub-01/anat/sub-01_hemi-L_white.surf.gii
@@ -37,6 +39,7 @@ smriprep/sub-01/anat/sub-01_hemi-R_midthickness.surf.gii
3739
smriprep/sub-01/anat/sub-01_hemi-R_pial.surf.gii
3840
smriprep/sub-01/anat/sub-01_hemi-R_space-fsLR_desc-msmsulc_sphere.surf.gii
3941
smriprep/sub-01/anat/sub-01_hemi-R_space-fsLR_desc-reg_sphere.surf.gii
42+
smriprep/sub-01/anat/sub-01_hemi-R_sphere.surf.gii
4043
smriprep/sub-01/anat/sub-01_hemi-R_sulc.shape.gii
4144
smriprep/sub-01/anat/sub-01_hemi-R_thickness.shape.gii
4245
smriprep/sub-01/anat/sub-01_hemi-R_white.surf.gii

smriprep/data/io_spec.json

Lines changed: 64 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -70,68 +70,91 @@
7070
"mode": "image"
7171
}
7272
},
73-
"std_xfms": {
74-
"anat2std_xfm": {
73+
"surfaces": {
74+
"white": {
7575
"datatype": "anat",
76-
"extension": "h5",
77-
"from": "T1w",
78-
"to": [],
79-
"suffix": "xfm",
80-
"mode": "image"
76+
"hemi": ["L", "R"],
77+
"space": null,
78+
"suffix": "white",
79+
"extension": ".surf.gii"
8180
},
82-
"std2anat_xfm": {
81+
"pial": {
8382
"datatype": "anat",
84-
"extension": "h5",
85-
"from": [],
86-
"to": "T1w",
87-
"suffix": "xfm",
88-
"mode": "image"
89-
}
90-
},
91-
"surfaces": {
92-
"t1w_aseg": {
83+
"hemi": ["L", "R"],
84+
"space": null,
85+
"suffix": "pial",
86+
"extension": ".surf.gii"
87+
},
88+
"midthickness": {
9389
"datatype": "anat",
94-
"desc": "aseg",
95-
"suffix": "dseg"
90+
"hemi": ["L", "R"],
91+
"space": null,
92+
"suffix": "midthickness",
93+
"extension": ".surf.gii"
9694
},
97-
"t1w_aparc": {
95+
"sphere": {
9896
"datatype": "anat",
99-
"desc": "aparcaseg",
100-
"suffix": "dseg"
97+
"hemi": ["L", "R"],
98+
"space": null,
99+
"desc": null,
100+
"suffix": "sphere",
101+
"extension": ".surf.gii"
101102
},
102-
"t1w2fsnative_xfm": {
103+
"thickness": {
103104
"datatype": "anat",
104-
"from": "T1w",
105-
"to": "fsnative",
106-
"extension": "txt",
107-
"suffix": "xfm",
108-
"mode": "image"
105+
"hemi": ["L", "R"],
106+
"space": null,
107+
"suffix": "thickness",
108+
"extension": ".shape.gii"
109109
},
110-
"fsnative2t1w_xfm": {
110+
"sulc": {
111111
"datatype": "anat",
112-
"from": "fsnative",
113-
"to": "T1w",
114-
"extension": "txt",
115-
"suffix": "xfm",
116-
"mode": "image"
112+
"hemi": ["L", "R"],
113+
"space": null,
114+
"suffix": "sulc",
115+
"extension": ".shape.gii"
117116
},
118-
"surfaces": {
117+
"curv": {
119118
"datatype": "anat",
120119
"hemi": ["L", "R"],
121-
"extension": "surf.gii",
122-
"suffix": [ "inflated", "midthickness", "pial", "white"]
120+
"space": null,
121+
"suffix": "curv",
122+
"extension": ".shape.gii"
123123
},
124-
"morphometrics": {
124+
"sphere_reg": {
125125
"datatype": "anat",
126126
"hemi": ["L", "R"],
127-
"extension": "shape.gii",
128-
"suffix": ["thickness", "sulc", "curv"]
127+
"space": null,
128+
"desc": "reg",
129+
"suffix": "sphere",
130+
"extension": ".surf.gii"
129131
},
132+
"sphere_reg_fsLR": {
133+
"datatype": "anat",
134+
"hemi": ["L", "R"],
135+
"space": "fsLR",
136+
"desc": "reg",
137+
"suffix": "sphere",
138+
"extension": ".surf.gii"
139+
},
140+
"sphere_reg_msm": {
141+
"datatype": "anat",
142+
"hemi": ["L", "R"],
143+
"space": "fsLR",
144+
"desc": "msmsulc",
145+
"suffix": "sphere",
146+
"extension": ".surf.gii"
147+
}
148+
},
149+
"masks": {
130150
"anat_ribbon": {
131151
"datatype": "anat",
132152
"desc": "ribbon",
133153
"suffix": "mask",
134-
"extension": "nii.gz"
154+
"extension": [
155+
".nii.gz",
156+
".nii"
157+
]
135158
}
136159
}
137160
},

smriprep/utils/bids.py

Lines changed: 8 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -21,39 +21,13 @@
2121
# https://www.nipreps.org/community/licensing/
2222
#
2323
"""Utilities to handle BIDS inputs."""
24-
from collections import defaultdict
2524
from pathlib import Path
2625
from json import loads
2726
from pkg_resources import resource_filename as pkgrf
2827
from bids.layout import BIDSLayout
29-
from bids.layout.writing import build_path
3028

3129

32-
def get_outputnode_spec():
33-
"""
34-
Generate outputnode's fields from I/O spec file.
35-
36-
Examples
37-
--------
38-
>>> get_outputnode_spec() # doctest: +NORMALIZE_WHITESPACE
39-
['t1w_preproc', 't1w_mask', 't1w_dseg', 't1w_tpms',
40-
'std_preproc', 'std_mask', 'std_dseg', 'std_tpms',
41-
'anat2std_xfm', 'std2anat_xfm',
42-
't1w_aseg', 't1w_aparc',
43-
't1w2fsnative_xfm', 'fsnative2t1w_xfm',
44-
'surfaces', 'morphometrics', 'anat_ribbon']
45-
46-
"""
47-
spec = loads(Path(pkgrf("smriprep", "data/io_spec.json")).read_text())["queries"]
48-
fields = ["_".join((m, s)) for m in ("t1w", "std") for s in spec["baseline"].keys()]
49-
fields += [s for s in spec["std_xfms"].keys()]
50-
fields += [s for s in spec["surfaces"].keys()]
51-
return fields
52-
53-
54-
def collect_derivatives(
55-
derivatives_dir, subject_id, std_spaces, freesurfer, spec=None, patterns=None
56-
):
30+
def collect_derivatives(derivatives_dir, subject_id, std_spaces, spec=None, patterns=None):
5731
"""Gather existing derivatives and compose a cache."""
5832
if spec is None or patterns is None:
5933
_spec, _patterns = tuple(
@@ -65,27 +39,9 @@ def collect_derivatives(
6539
if patterns is None:
6640
patterns = _patterns
6741

68-
derivs_cache = defaultdict(list, {})
6942
layout = BIDSLayout(derivatives_dir, config=["bids", "derivatives"], validate=False)
70-
derivatives_dir = Path(derivatives_dir)
71-
72-
def _check_item(item):
73-
if not item:
74-
return None
75-
76-
if isinstance(item, str):
77-
item = [item]
78-
79-
result = []
80-
for i in item:
81-
if not (derivatives_dir / i).exists():
82-
i = i.rstrip(".gz")
83-
if not (derivatives_dir / i).exists():
84-
return None
85-
result.append(str(derivatives_dir / i))
86-
87-
return result
8843

44+
derivs_cache = {}
8945
for k, q in spec["baseline"].items():
9046
q["subject"] = subject_id
9147
item = layout.get(return_type='filename', **q)
@@ -94,18 +50,6 @@ def _check_item(item):
9450

9551
derivs_cache["t1w_%s" % k] = item[0] if len(item) == 1 else item
9652

97-
for space in std_spaces:
98-
for k, q in spec["std_xfms"].items():
99-
q["subject"] = subject_id
100-
q["from"] = q["from"] or space
101-
q["to"] = q["to"] or space
102-
item = layout.get(return_type='filename', **q)
103-
if not item:
104-
continue
105-
derivs_cache[k] += item
106-
107-
derivs_cache = dict(derivs_cache) # Back to a standard dictionary
108-
10953
transforms = derivs_cache.setdefault('transforms', {})
11054
for space in std_spaces:
11155
for k, q in spec["transforms"].items():
@@ -118,18 +62,14 @@ def _check_item(item):
11862
continue
11963
transforms.setdefault(space, {})[k] = item[0] if len(item) == 1 else item
12064

121-
if freesurfer:
122-
for k, q in spec["surfaces"].items():
123-
q["subject"] = subject_id
124-
item = _check_item(build_path(q, patterns))
125-
if not item:
126-
continue
65+
for k, q in spec["surfaces"].items():
66+
q["subject"] = subject_id
67+
item = layout.get(return_type='filename', **q)
68+
if not item or len(item) != 2:
69+
continue
12770

128-
if len(item) == 1:
129-
item = item[0]
130-
derivs_cache[k] = item
71+
derivs_cache[k] = sorted(item)
13172

132-
derivs_cache["template"] = std_spaces
13373
return derivs_cache
13474

13575

0 commit comments

Comments
 (0)