@@ -52,7 +52,7 @@ def init_fmriprep_wf():
52
52
Build *fMRIPrep*'s pipeline.
53
53
54
54
This workflow organizes the execution of FMRIPREP, with a sub-workflow for
55
- each subject .
55
+ each processing group .
56
56
57
57
If FreeSurfer's ``recon-all`` is to be run, a corresponding folder is created
58
58
and populated with any needed template subjects under the derivatives folder.
@@ -91,12 +91,27 @@ def init_fmriprep_wf():
91
91
if config .execution .fs_subjects_dir is not None :
92
92
fsdir .inputs .subjects_dir = str (config .execution .fs_subjects_dir .absolute ())
93
93
94
- for subject_id in config .execution .participant_label :
95
- single_subject_wf = init_single_subject_wf (subject_id )
94
+ for subject_id , session_ids in config .execution .processing_groups :
95
+ log_dir = config .execution .fmriprep_dir / f'sub-{ subject_id } '
96
+ sessions = listify (session_ids )
97
+ ses_str = ''
96
98
97
- single_subject_wf .config ['execution' ]['crashdump_dir' ] = str (
98
- config .execution .fmriprep_dir / f'sub-{ subject_id } ' / 'log' / config .execution .run_uuid
99
+ if isinstance (sessions , list ):
100
+ from smriprep .utils .misc import stringify_sessions
101
+
102
+ ses_str = stringify_sessions (sessions )
103
+ log_dir /= f'ses-{ ses_str } '
104
+
105
+ log_dir /= 'log' / config .execution .run_uuid
106
+
107
+ wf_name = '_' .join (
108
+ ('sub' , subject_id ,) +
109
+ (('ses' , ses_str ) if ses_str else ()) +
110
+ ('wf' ,)
99
111
)
112
+ single_subject_wf = init_single_subject_wf (subject_id , sessions , name = wf_name )
113
+
114
+ single_subject_wf .config ['execution' ]['crashdump_dir' ] = str (log_dir )
100
115
for node in single_subject_wf ._get_all_nodes ():
101
116
node .config = deepcopy (single_subject_wf .config )
102
117
if freesurfer :
@@ -105,16 +120,17 @@ def init_fmriprep_wf():
105
120
fmriprep_wf .add_nodes ([single_subject_wf ])
106
121
107
122
# Dump a copy of the config file into the log directory
108
- log_dir = (
109
- config .execution .fmriprep_dir / f'sub-{ subject_id } ' / 'log' / config .execution .run_uuid
110
- )
111
123
log_dir .mkdir (exist_ok = True , parents = True )
112
124
config .to_filename (log_dir / 'fmriprep.toml' )
113
125
114
126
return fmriprep_wf
115
127
116
128
117
- def init_single_subject_wf (subject_id : str ):
129
+ def init_single_subject_wf (
130
+ subject_id : str ,
131
+ session_id : str | list [str ] | None = None ,
132
+ name : str | None = None ,
133
+ ):
118
134
"""
119
135
Organize the preprocessing pipeline for a single subject.
120
136
@@ -139,6 +155,12 @@ def init_single_subject_wf(subject_id: str):
139
155
----------
140
156
subject_id : :obj:`str`
141
157
Subject label for this single-subject workflow.
158
+ session_id
159
+ Session label(s) for this workflow.
160
+ name
161
+ Name of the workflow.
162
+ If not provided, will be set to ``sub_{subject_id}_ses_{session_id}_wf``.
163
+
142
164
143
165
Inputs
144
166
------
@@ -169,7 +191,10 @@ def init_single_subject_wf(subject_id: str):
169
191
170
192
from fmriprep .workflows .bold .base import init_bold_wf
171
193
172
- workflow = Workflow (name = f'sub_{ subject_id } _wf' )
194
+ if name is None :
195
+ name = f'sub_{ subject_id } _wf'
196
+
197
+ workflow = Workflow (name = name )
173
198
workflow .__desc__ = f"""
174
199
Results included in this manuscript come from preprocessing
175
200
performed using *fMRIPrep* { config .environment .version }
@@ -204,6 +229,7 @@ def init_single_subject_wf(subject_id: str):
204
229
subject_data = collect_data (
205
230
config .execution .layout ,
206
231
subject_id ,
232
+ session_id = session_id ,
207
233
task = config .execution .task_id ,
208
234
echo = config .execution .echo_idx ,
209
235
bids_filters = config .execution .bids_filters ,
@@ -255,6 +281,7 @@ def init_single_subject_wf(subject_id: str):
255
281
derivatives_dir = deriv_dir ,
256
282
subject_id = subject_id ,
257
283
std_spaces = std_spaces ,
284
+ session_id = session_id ,
258
285
)
259
286
)
260
287
@@ -265,7 +292,7 @@ def init_single_subject_wf(subject_id: str):
265
292
subject_data = subject_data ,
266
293
anat_only = config .workflow .anat_only ,
267
294
subject_id = subject_id ,
268
- anat_derivatives = anatomical_cache if anatomical_cache else None ,
295
+ anat_derivatives = anatomical_cache or None ,
269
296
),
270
297
name = 'bidssrc' ,
271
298
)
@@ -363,7 +390,7 @@ def init_single_subject_wf(subject_id: str):
363
390
('roi' , 'inputnode.roi' ),
364
391
('flair' , 'inputnode.flair' ),
365
392
]),
366
- (bids_info , anat_fit_wf , [(('subject' , _prefix ), 'inputnode.subject_id' )]),
393
+ (bids_info , anat_fit_wf , [(('subject' , _prefix , 'session' ), 'inputnode.subject_id' )]),
367
394
# Reporting connections
368
395
(inputnode , summary , [('subjects_dir' , 'subjects_dir' )]),
369
396
(bidssrc , summary , [('t2w' , 't2w' ), ('bold' , 'bold' )]),
@@ -929,8 +956,21 @@ def map_fieldmap_estimation(
929
956
return fmap_estimators , estimator_map
930
957
931
958
932
- def _prefix (subid ):
933
- return subid if subid .startswith ('sub-' ) else f'sub-{ subid } '
959
+ def _prefix (subject_id , session_id = None ):
960
+ """Create FreeSurfer subject ID."""
961
+ if not subject_id .startswith ('sub-' ):
962
+ subject_id = f'sub-{ subject_id } '
963
+
964
+ if session_id :
965
+ ses_str = session_id
966
+ if isinstance (session_id , list ):
967
+ from smriprep .utils .misc import stringify_sessions
968
+
969
+ ses_str = stringify_sessions (session_id )
970
+ if not ses_str .startswith ('ses-' ):
971
+ ses_str = f'ses-{ ses_str } '
972
+ subject_id += f'_{ ses_str } '
973
+ return subject_id
934
974
935
975
936
976
def clean_datasinks (workflow : pe .Workflow ) -> pe .Workflow :
0 commit comments