2
2
import sys
3
3
import os
4
4
from packaging .version import Version
5
- from collections import OrderedDict
6
5
from copy import deepcopy
7
6
8
7
from nipype import __version__ as nipype_ver
@@ -28,17 +27,18 @@ def init_dmriprep_wf(
28
27
debug ,
29
28
force_syn ,
30
29
freesurfer ,
30
+ fs_subjects_dir ,
31
31
hires ,
32
32
ignore ,
33
33
layout ,
34
34
longitudinal ,
35
35
low_mem ,
36
36
omp_nthreads ,
37
37
output_dir ,
38
- output_spaces ,
39
38
run_uuid ,
40
39
skull_strip_fixed_seed ,
41
40
skull_strip_template ,
41
+ spaces ,
42
42
subject_list ,
43
43
use_syn ,
44
44
work_dir ,
@@ -59,25 +59,30 @@ def init_dmriprep_wf(
59
59
from collections import namedtuple, OrderedDict
60
60
BIDSLayout = namedtuple('BIDSLayout', ['root'])
61
61
from dmriprep.workflows.base import init_dmriprep_wf
62
+ from niworkflows.utils.spaces import Reference, SpatialReferences
62
63
os.environ['FREESURFER_HOME'] = os.getcwd()
63
64
wf = init_dmriprep_wf(
64
65
anat_only=False,
65
66
debug=False,
66
67
force_syn=True,
67
68
freesurfer=True,
69
+ fs_subjects_dir=None,
68
70
hires=True,
69
71
ignore=[],
70
72
layout=BIDSLayout('.'),
71
73
longitudinal=False,
72
74
low_mem=False,
73
75
omp_nthreads=1,
74
76
output_dir='.',
75
- output_spaces=OrderedDict([
76
- ('MNI152Lin', {}), ('fsaverage', {'density': '10k'}),
77
- ('T1w', {}), ('fsnative', {})]),
78
77
run_uuid='X',
79
78
skull_strip_fixed_seed=False,
80
- skull_strip_template=('OASIS30ANTs', {}),
79
+ skull_strip_template=Reference('OASIS30ANTs'),
80
+ spaces=SpatialReferences(
81
+ spaces=['MNI152Lin',
82
+ ('fsaverage', {'density': '10k'}),
83
+ 'T1w',
84
+ 'fsnative'],
85
+ checkpoint=True),
81
86
subject_list=['dmripreptest'],
82
87
use_syn=True,
83
88
work_dir='.',
@@ -93,6 +98,9 @@ def init_dmriprep_wf(
93
98
**Temporary**: Always run SyN-based SDC
94
99
freesurfer : bool
95
100
Enable FreeSurfer surface reconstruction (may increase runtime)
101
+ fs_subjects_dir : :obj:`~pathlib.Path` or :obj:`str`
102
+ Designates a custom FreeSurfer subjects directory, other than
103
+ ``<derivatives>/freesurfer/``.
96
104
hires : bool
97
105
Enable sub-millimeter preprocessing in FreeSurfer
98
106
ignore : list
@@ -108,22 +116,22 @@ def init_dmriprep_wf(
108
116
Maximum number of threads an individual process may use
109
117
output_dir : str
110
118
Directory in which to save derivatives
111
- output_spaces : OrderedDict
112
- Ordered dictionary where keys are TemplateFlow ID strings (e.g., ``MNI152Lin``,
113
- ``MNI152NLin6Asym``, ``MNI152NLin2009cAsym``, or ``fsLR``) strings designating
114
- nonstandard references (e.g., ``T1w`` or ``anat``, ``sbref``, ``run``, etc.),
115
- or paths pointing to custom templates organized in a TemplateFlow-like structure.
116
- Values of the dictionary aggregate modifiers (e.g., the value for the key ``MNI152Lin``
117
- could be ``{'resolution': 2}`` if one wants the resampling to be done on the 2mm
118
- resolution version of the selected template).
119
119
run_uuid : str
120
120
Unique identifier for execution instance
121
- skull_strip_template : tuple
122
- Name of target template for brain extraction with ANTs' ``antsBrainExtraction``,
123
- and corresponding dictionary of output-space modifiers.
121
+ skull_strip_template : :py:class:`~niworkflows.utils.space.Reference`
122
+ Target template for brain extraction with ANTs' ``antsBrainExtraction``.
124
123
skull_strip_fixed_seed : bool
125
124
Do not use a random seed for skull-stripping - will ensure
126
125
run-to-run replicability when used with --omp-nthreads 1
126
+ spaces : :py:class:`~niworkflows.utils.spaces.SpatialReferences`
127
+ A container for storing, organizing, and parsing spatial normalizations. Composed of
128
+ :py:class:`~niworkflows.utils.spaces.Reference` objects representing spatial references.
129
+ Each ``Reference`` contains a space, which is a string of either TemplateFlow template IDs
130
+ (e.g., ``MNI152Lin``, ``MNI152NLin6Asym``, ``MNIPediatricAsym``), nonstandard references
131
+ (e.g., ``T1w`` or ``anat``, ``sbref``, ``run``, etc.), or a custom template located in
132
+ the TemplateFlow root directory. Each ``Reference`` may also contain a spec, which is a
133
+ dictionary with template specifications (e.g., a specification of ``{'resolution': 2}``
134
+ would lead to resampling on a 2mm resolution of the space).
127
135
subject_list : list
128
136
List of subject labels
129
137
use_syn : bool
@@ -141,9 +149,10 @@ def init_dmriprep_wf(
141
149
BIDSFreeSurferDir (
142
150
derivatives = output_dir ,
143
151
freesurfer_home = os .getenv ('FREESURFER_HOME' ),
144
- spaces = [s for s in output_spaces .keys () if s .startswith ('fsaverage' )] + [
145
- 'fsnative' ] * ('fsnative' in output_spaces )),
152
+ spaces = spaces .get_fs_spaces ()),
146
153
name = 'fsdir_run_' + run_uuid .replace ('-' , '_' ), run_without_submitting = True )
154
+ if fs_subjects_dir is not None :
155
+ fsdir .inputs .subjects_dir = str (fs_subjects_dir .absolute ())
147
156
148
157
reportlets_dir = os .path .join (work_dir , 'reportlets' )
149
158
for subject_id in subject_list :
@@ -160,10 +169,10 @@ def init_dmriprep_wf(
160
169
name = "single_subject_" + subject_id + "_wf" ,
161
170
omp_nthreads = omp_nthreads ,
162
171
output_dir = output_dir ,
163
- output_spaces = output_spaces ,
164
172
reportlets_dir = reportlets_dir ,
165
173
skull_strip_fixed_seed = skull_strip_fixed_seed ,
166
174
skull_strip_template = skull_strip_template ,
175
+ spaces = spaces ,
167
176
subject_id = subject_id ,
168
177
use_syn = use_syn ,
169
178
)
@@ -195,10 +204,10 @@ def init_single_subject_wf(
195
204
name ,
196
205
omp_nthreads ,
197
206
output_dir ,
198
- output_spaces ,
199
207
reportlets_dir ,
200
208
skull_strip_fixed_seed ,
201
209
skull_strip_template ,
210
+ spaces ,
202
211
subject_id ,
203
212
use_syn ,
204
213
):
@@ -220,8 +229,9 @@ def init_single_subject_wf(
220
229
:graph2use: orig
221
230
:simple_form: yes
222
231
232
+ from collections import namedtuple
233
+ from niworkflows.utils.spaces import Reference, SpatialReferences
223
234
from dmriprep.workflows.base import init_single_subject_wf
224
- from collections import namedtuple, OrderedDict
225
235
BIDSLayout = namedtuple('BIDSLayout', ['root'])
226
236
wf = init_single_subject_wf(
227
237
anat_only=False,
@@ -236,12 +246,15 @@ def init_single_subject_wf(
236
246
name='single_subject_wf',
237
247
omp_nthreads=1,
238
248
output_dir='.',
239
- output_spaces=OrderedDict([
240
- ('MNI152Lin', {}), ('fsaverage', {'density': '10k'}),
241
- ('T1w', {}), ('fsnative', {})]),
242
249
reportlets_dir='.',
243
250
skull_strip_fixed_seed=False,
244
- skull_strip_template=('OASIS30ANTs', {}),
251
+ skull_strip_template=Reference('OASIS30ANTs'),
252
+ spaces=SpatialReferences(
253
+ spaces=['MNI152Lin',
254
+ ('fsaverage', {'density': '10k'}),
255
+ 'T1w',
256
+ 'fsnative'],
257
+ checkpoint=True),
245
258
subject_id='test',
246
259
use_syn=True,
247
260
)
@@ -273,22 +286,22 @@ def init_single_subject_wf(
273
286
Maximum number of threads an individual process may use
274
287
output_dir : str
275
288
Directory in which to save derivatives
276
- output_spaces : OrderedDict
277
- Ordered dictionary where keys are TemplateFlow ID strings (e.g., ``MNI152Lin``,
278
- ``MNI152NLin6Asym``, ``MNI152NLin2009cAsym``, or ``fsLR``) strings designating
279
- nonstandard references (e.g., ``T1w`` or ``anat``, ``sbref``, ``run``, etc.),
280
- or paths pointing to custom templates organized in a TemplateFlow-like structure.
281
- Values of the dictionary aggregate modifiers (e.g., the value for the key ``MNI152Lin``
282
- could be ``{'resolution': 2}`` if one wants the resampling to be done on the 2mm
283
- resolution version of the selected template).
284
289
reportlets_dir : str
285
290
Directory in which to save reportlets
286
291
skull_strip_fixed_seed : bool
287
292
Do not use a random seed for skull-stripping - will ensure
288
293
run-to-run replicability when used with --omp-nthreads 1
289
- skull_strip_template : tuple
290
- Name of target template for brain extraction with ANTs' ``antsBrainExtraction``,
291
- and corresponding dictionary of output-space modifiers.
294
+ skull_strip_template : :py:class:`~niworkflows.utils.space.Reference`
295
+ Target template for brain extraction with ANTs' ``antsBrainExtraction``.
296
+ spaces : :py:class:`~niworkflows.utils.spaces.SpatialReferences`
297
+ A container for storing, organizing, and parsing spatial normalizations. Composed of
298
+ :py:class:`~niworkflows.utils.spaces.Reference` objects representing spatial references.
299
+ Each ``Reference`` contains a space, which is a string of either TemplateFlow template IDs
300
+ (e.g., ``MNI152Lin``, ``MNI152NLin6Asym``, ``MNIPediatricAsym``), nonstandard references
301
+ (e.g., ``T1w`` or ``anat``, ``sbref``, ``run``, etc.), or a custom template located in
302
+ the TemplateFlow root directory. Each ``Reference`` may also contain a spec, which is a
303
+ dictionary with template specifications (e.g., a specification of ``{'resolution': 2}``
304
+ would lead to resampling on a 2mm resolution of the space).
292
305
subject_id : str
293
306
List of subject labels
294
307
use_syn : bool
@@ -301,7 +314,6 @@ def init_single_subject_wf(
301
314
FreeSurfer's ``$SUBJECTS_DIR``
302
315
303
316
"""
304
- from ..config import NONSTANDARD_REFERENCES
305
317
if name in ('single_subject_wf' , 'single_subject_dmripreptest_wf' ):
306
318
# for documentation purposes
307
319
subject_data = {
@@ -349,11 +361,6 @@ def init_single_subject_wf(
349
361
350
362
""" .format (dmriprep_ver = Version (__version__ ).public )
351
363
352
- # Filter out standard spaces to a separate dict
353
- std_spaces = OrderedDict ([
354
- (key , modifiers ) for key , modifiers in output_spaces .items ()
355
- if key not in NONSTANDARD_REFERENCES ])
356
-
357
364
inputnode = pe .Node (niu .IdentityInterface (fields = ['subjects_dir' ]),
358
365
name = 'inputnode' )
359
366
@@ -363,10 +370,9 @@ def init_single_subject_wf(
363
370
bids_info = pe .Node (BIDSInfo (
364
371
bids_dir = layout .root , bids_validate = False ), name = 'bids_info' )
365
372
366
- summary = pe .Node (SubjectSummary (
367
- std_spaces = list (std_spaces .keys ()),
368
- nstd_spaces = list (set (NONSTANDARD_REFERENCES ).intersection (output_spaces .keys ()))),
369
- name = 'summary' , run_without_submitting = True )
373
+ summary = pe .Node (SubjectSummary (std_spaces = spaces .get_spaces (nonstandard = False ),
374
+ nstd_spaces = spaces .get_spaces (standard = False )),
375
+ name = 'summary' , run_without_submitting = True )
370
376
371
377
about = pe .Node (AboutSummary (version = __version__ ,
372
378
command = ' ' .join (sys .argv )),
@@ -385,18 +391,18 @@ def init_single_subject_wf(
385
391
# Preprocessing of T1w (includes registration to MNI)
386
392
anat_preproc_wf = init_anat_preproc_wf (
387
393
bids_root = layout .root ,
388
- debug = debug ,
389
394
freesurfer = freesurfer ,
390
395
hires = hires ,
391
396
longitudinal = longitudinal ,
392
- name = "anat_preproc_wf" ,
393
397
num_t1w = len (subject_data ['t1w' ]),
394
398
omp_nthreads = omp_nthreads ,
395
399
output_dir = output_dir ,
396
- output_spaces = std_spaces ,
397
400
reportlets_dir = reportlets_dir ,
398
- skull_strip_fixed_seed = skull_strip_fixed_seed ,
399
401
skull_strip_template = skull_strip_template ,
402
+ spaces = spaces ,
403
+ debug = debug ,
404
+ name = "anat_preproc_wf" ,
405
+ skull_strip_fixed_seed = skull_strip_fixed_seed ,
400
406
)
401
407
402
408
workflow .connect ([
0 commit comments