@@ -1156,9 +1156,9 @@ def init_hcp_morphometrics_wf(
1156
1156
return workflow
1157
1157
1158
1158
1159
- def init_cortex_mask_wf (
1159
+ def init_cortex_masks_wf (
1160
1160
* ,
1161
- name : str = 'cortex_mask_wf ' ,
1161
+ name : str = 'cortex_masks_wf ' ,
1162
1162
):
1163
1163
"""Create a cortical surface mask from a surface file.
1164
1164
@@ -1167,55 +1167,100 @@ def init_cortex_mask_wf(
1167
1167
:graph2use: orig
1168
1168
:simple_form: yes
1169
1169
1170
- from smriprep.workflows.surfaces import init_cortex_mask_wf
1171
- wf = init_cortex_mask_wf ()
1170
+ from smriprep.workflows.surfaces import init_cortex_masks_wf
1171
+ wf = init_cortex_masks_wf ()
1172
1172
1173
1173
Inputs
1174
1174
------
1175
- midthickness : str
1176
- One hemisphere's FreeSurfer midthickness surface file in GIFTI format
1177
- thickness : str
1178
- One hemisphere's FreeSurfer thickness file in GIFTI format
1179
- hemi : {'L', 'R'}
1180
- Hemisphere indicator
1175
+ midthickness : list of str
1176
+ Each hemisphere's FreeSurfer midthickness surface file in GIFTI format
1177
+ thickness : list of str
1178
+ Each hemisphere's FreeSurfer thickness file in GIFTI format
1181
1179
1182
1180
Outputs
1183
1181
-------
1184
- roi : str
1185
- Cortical surface mask in GIFTI format
1182
+ cortex_masks : list of str
1183
+ Cortical surface mask in GIFTI format for each hemisphere
1186
1184
"""
1187
1185
DEFAULT_MEMORY_MIN_GB = 0.01
1188
1186
1189
1187
workflow = Workflow (name = name )
1190
1188
1191
1189
inputnode = pe .Node (
1192
- niu .IdentityInterface (fields = ['midthickness' , 'thickness' , 'hemi' ]),
1190
+ niu .IdentityInterface (fields = ['midthickness' , 'thickness' ]),
1193
1191
name = 'inputnode' ,
1194
1192
)
1195
- outputnode = pe .Node (niu .IdentityInterface (fields = ['roi' ]), name = 'outputnode' )
1196
-
1197
- # Thickness is presumably already positive, but HCP uses abs(-thickness)
1198
- abs_thickness = pe .Node (MetricMath (metric = 'thickness' , operation = 'abs' ), name = 'abs_thickness' )
1199
-
1200
- # Native ROI is thickness > 0, with holes and islands filled
1201
- initial_roi = pe .Node (MetricMath (metric = 'roi' , operation = 'bin' ), name = 'initial_roi' )
1202
- fill_holes = pe .Node (MetricFillHoles (), name = 'fill_holes' , mem_gb = DEFAULT_MEMORY_MIN_GB )
1203
- native_roi = pe .Node (MetricRemoveIslands (), name = 'native_roi' , mem_gb = DEFAULT_MEMORY_MIN_GB )
1193
+ outputnode = pe .Node (niu .IdentityInterface (fields = ['cortex_masks' ]), name = 'outputnode' )
1204
1194
1195
+ # Combine the inputs into a list
1196
+ combine_sources = pe .Node (
1197
+ niu .Merge (2 , no_flatten = True ),
1198
+ name = 'combine_sources' ,
1199
+ )
1205
1200
workflow .connect ([
1206
- (inputnode , abs_thickness , [
1207
- ('hemi ' , 'hemisphere ' ),
1208
- ('thickness' , 'metric_file ' ),
1201
+ (inputnode , combine_sources , [
1202
+ ('midthickness ' , 'in1 ' ),
1203
+ ('thickness' , 'in2 ' ),
1209
1204
]),
1210
- (inputnode , initial_roi , [('hemi' , 'hemisphere' )]),
1211
- (abs_thickness , initial_roi , [('metric_file' , 'metric_file' )]),
1212
- (inputnode , fill_holes , [('midthickness' , 'surface_file' )]),
1213
- (inputnode , native_roi , [('midthickness' , 'surface_file' )]),
1214
- (initial_roi , fill_holes , [('metric_file' , 'metric_file' )]),
1215
- (fill_holes , native_roi , [('out_file' , 'metric_file' )]),
1216
- (native_roi , outputnode , [('out_file' , 'roi' )]),
1205
+ (combine_sources , outputnode , [(('out' , _transpose_lol ), 'source_files' )]),
1217
1206
]) # fmt:skip
1218
1207
1208
+ combine_masks = pe .Node (
1209
+ niu .Merge (2 ),
1210
+ name = 'combine_masks' ,
1211
+ )
1212
+ workflow .connect ([(combine_masks , outputnode , [('out' , 'cortex_masks' )])])
1213
+
1214
+ for i_hemi , hemi in enumerate (['L' , 'R' ]):
1215
+ select_midthickness = pe .Node (
1216
+ niu .Select (index = i_hemi ),
1217
+ name = f'select_midthickness_{ hemi } ' ,
1218
+ )
1219
+ select_thickness = pe .Node (
1220
+ niu .Select (index = i_hemi ),
1221
+ name = f'select_thickness_{ hemi } ' ,
1222
+ )
1223
+ workflow .connect ([
1224
+ (inputnode , select_midthickness , [('midthickness' , 'inlist' )]),
1225
+ (inputnode , select_thickness , [('thickness' , 'inlist' )]),
1226
+ ]) # fmt:skip
1227
+
1228
+ # Thickness is presumably already positive, but HCP uses abs(-thickness)
1229
+ abs_thickness = pe .Node (
1230
+ MetricMath (metric = 'thickness' , operation = 'abs' ),
1231
+ name = f'abs_thickness_{ hemi } ' ,
1232
+ )
1233
+
1234
+ # Native ROI is thickness > 0, with holes and islands filled
1235
+ initial_roi = pe .Node (
1236
+ MetricMath (metric = 'roi' , operation = 'bin' ),
1237
+ name = f'initial_roi_{ hemi } ' ,
1238
+ )
1239
+ fill_holes = pe .Node (
1240
+ MetricFillHoles (),
1241
+ name = f'fill_holes_{ hemi } ' ,
1242
+ mem_gb = DEFAULT_MEMORY_MIN_GB ,
1243
+ )
1244
+ native_roi = pe .Node (
1245
+ MetricRemoveIslands (),
1246
+ name = f'native_roi_{ hemi } ' ,
1247
+ mem_gb = DEFAULT_MEMORY_MIN_GB ,
1248
+ )
1249
+
1250
+ workflow .connect ([
1251
+ (inputnode , abs_thickness , [
1252
+ ('hemi' , 'hemisphere' ),
1253
+ ('thickness' , 'metric_file' ),
1254
+ ]),
1255
+ (inputnode , initial_roi , [('hemi' , 'hemisphere' )]),
1256
+ (abs_thickness , initial_roi , [('metric_file' , 'metric_file' )]),
1257
+ (inputnode , fill_holes , [('midthickness' , 'surface_file' )]),
1258
+ (inputnode , native_roi , [('midthickness' , 'surface_file' )]),
1259
+ (initial_roi , fill_holes , [('metric_file' , 'metric_file' )]),
1260
+ (fill_holes , native_roi , [('out_file' , 'metric_file' )]),
1261
+ (native_roi , combine_masks , [('out_file' , f'in{ i_hemi + 1 } ' )]),
1262
+ ]) # fmt:skip
1263
+
1219
1264
return workflow
1220
1265
1221
1266
@@ -1758,3 +1803,8 @@ def _select_seg(in_files, segmentation):
1758
1803
1759
1804
def _repeat (seq : list , count : int ) -> list :
1760
1805
return seq * count
1806
+
1807
+
1808
+ def _transpose_lol (inlist ):
1809
+ """Transpose a list of lists."""
1810
+ return list (map (list , zip (* inlist , strict = False )))
0 commit comments