@@ -279,6 +279,7 @@ def init_bold_wf(
279
279
spaces = config .workflow .spaces
280
280
nonstd_spaces = set (spaces .get_nonstandard ())
281
281
freesurfer_spaces = spaces .get_fs_spaces ()
282
+ surf_std = [x for x in spaces .get_standard (dim = (2 ,)) if x .space != 'fsaverage' ]
282
283
283
284
#
284
285
# Resampling outputs workflow:
@@ -503,6 +504,39 @@ def init_bold_wf(
503
504
(merge_bold_sources , ds_bold_std_wf , [('out' , 'inputnode.source_files' )]),
504
505
]) # fmt:skip
505
506
507
+ # Goodvoxels mask might be needed in any surface resampling
508
+ if config .workflow .project_goodvoxels and (config .workflow .cifti_output or surf_std ):
509
+ from .resampling import init_goodvoxels_bold_mask_wf
510
+
511
+ goodvoxels_bold_mask_wf = init_goodvoxels_bold_mask_wf (mem_gb ['resampled' ])
512
+ ds_goodvoxels_mask = pe .Node (
513
+ DerivativesDataSink (
514
+ base_directory = fmriprep_dir ,
515
+ dismiss_entities = dismiss_echo (),
516
+ compress = True ,
517
+ space = 'T1w' ,
518
+ desc = 'goodvoxels' ,
519
+ suffix = 'mask' ,
520
+ ),
521
+ name = 'ds_goodvoxels_mask' ,
522
+ run_without_submitting = True ,
523
+ )
524
+ ds_goodvoxels_mask .inputs .source_file = bold_file
525
+
526
+ workflow .__postdesc__ += """\
527
+ A "goodvoxels" mask was applied during volume-to-surface sampling, excluding
528
+ voxels whose time-series have a locally high coefficient of variation.
529
+ """
530
+ workflow .connect ([
531
+ (inputnode , goodvoxels_bold_mask_wf , [('anat_ribbon' , 'inputnode.anat_ribbon' )]),
532
+ (bold_anat_wf , goodvoxels_bold_mask_wf , [
533
+ ('outputnode.bold_file' , 'inputnode.bold_file' ),
534
+ ]),
535
+ (goodvoxels_bold_mask_wf , ds_goodvoxels_mask , [
536
+ ('outputnode.goodvoxels_mask' , 'in_file' ),
537
+ ]),
538
+ ]) # fmt:skip
539
+
506
540
if config .workflow .run_reconall and freesurfer_spaces :
507
541
workflow .__postdesc__ += """\
508
542
Non-gridded (surface) resamplings were performed using `mri_vol2surf`
@@ -550,7 +584,6 @@ def init_bold_wf(
550
584
from .resampling import (
551
585
init_bold_fsLR_resampling_wf ,
552
586
init_bold_grayords_wf ,
553
- init_goodvoxels_bold_mask_wf ,
554
587
)
555
588
556
589
bold_MNI6_wf = init_bold_volumetric_resample_wf (
@@ -569,42 +602,12 @@ def init_bold_wf(
569
602
)
570
603
571
604
if config .workflow .project_goodvoxels :
572
- goodvoxels_bold_mask_wf = init_goodvoxels_bold_mask_wf (mem_gb ['resampled' ])
573
-
574
- workflow .connect ([
575
- (inputnode , goodvoxels_bold_mask_wf , [('anat_ribbon' , 'inputnode.anat_ribbon' )]),
576
- (bold_anat_wf , goodvoxels_bold_mask_wf , [
577
- ('outputnode.bold_file' , 'inputnode.bold_file' ),
578
- ]),
579
- ]) # fmt:skip
580
-
581
- ds_goodvoxels_mask = pe .Node (
582
- DerivativesDataSink (
583
- base_directory = fmriprep_dir ,
584
- dismiss_entities = dismiss_echo (),
585
- compress = True ,
586
- space = 'T1w' ,
587
- desc = 'goodvoxels' ,
588
- suffix = 'mask' ,
589
- ),
590
- name = 'ds_goodvoxels_mask' ,
591
- run_without_submitting = True ,
592
- )
593
- ds_goodvoxels_mask .inputs .source_file = bold_file
594
605
workflow .connect ([
595
- (goodvoxels_bold_mask_wf , ds_goodvoxels_mask , [
596
- ('outputnode.goodvoxels_mask' , 'in_file' ),
597
- ]),
598
606
(goodvoxels_bold_mask_wf , bold_fsLR_resampling_wf , [
599
607
('outputnode.goodvoxels_mask' , 'inputnode.volume_roi' ),
600
608
]),
601
609
]) # fmt:skip
602
610
603
- bold_fsLR_resampling_wf .__desc__ += """\
604
- A "goodvoxels" mask was applied during volume-to-surface sampling in fsLR space,
605
- excluding voxels whose time-series have a locally high coefficient of variation.
606
- """
607
-
608
611
bold_grayords_wf = init_bold_grayords_wf (
609
612
grayord_density = config .workflow .cifti_output ,
610
613
mem_gb = 1 ,
@@ -670,6 +673,105 @@ def init_bold_wf(
670
673
]),
671
674
]) # fmt:skip
672
675
676
+ if surf_std :
677
+ from smriprep .workflows .surfaces import init_resample_surfaces_wf
678
+
679
+ from .resampling import (
680
+ init_wb_surf_surf_wf ,
681
+ init_wb_vol_surf_wf ,
682
+ )
683
+
684
+ workflow .__postdesc__ += (
685
+ 'Non-gridded (surface) resamplings were performed using the Connectome Workbench.'
686
+ )
687
+ config .loggers .workflow .debug ('Creating BOLD surface workbench resampling workflow.' )
688
+
689
+ wb_vol_surf_wf = init_wb_vol_surf_wf (
690
+ omp_nthreads = omp_nthreads ,
691
+ mem_gb = mem_gb ['resampled' ],
692
+ dilate = True ,
693
+ )
694
+ workflow .connect ([
695
+ (inputnode , wb_vol_surf_wf ,[
696
+ ('white' , 'inputnode.white' ),
697
+ ('pial' , 'inputnode.pial' ),
698
+ ('midthickness' , 'inputnode.midthickness' ),
699
+ ]),
700
+ (bold_anat_wf , wb_vol_surf_wf , [
701
+ ('outputnode.bold_file' , 'inputnode.bold_file' ),
702
+ ]),
703
+ ]) # fmt:skip
704
+
705
+ if config .workflow .project_goodvoxels :
706
+ workflow .connect ([
707
+ (goodvoxels_bold_mask_wf , wb_vol_surf_wf , [
708
+ ('outputnode.goodvoxels_mask' , 'inputnode.volume_roi' ),
709
+ ]),
710
+ ]) # fmt:skip
711
+
712
+ for ref_ in surf_std :
713
+ template = ref_ .space
714
+ density = ref_ .spec .get ('density' ) or ref_ .spec .get ('den' ) or None
715
+ if density is None :
716
+ config .loggers .warning (f'Cannot resample { ref_ } without density specified.' )
717
+ continue
718
+
719
+ resample_surfaces_wf = init_resample_surfaces_wf (
720
+ name = f'resample_surfaces_wf_{ template } _{ density } ' ,
721
+ surfaces = ['midthickness' ],
722
+ template = template ,
723
+ density = density ,
724
+ )
725
+
726
+ wb_surf_surf_wf = init_wb_surf_surf_wf (
727
+ template = template ,
728
+ density = density ,
729
+ omp_nthreads = omp_nthreads ,
730
+ mem_gb = mem_gb ['resampled' ],
731
+ )
732
+
733
+ ds_bold_surf_wb = pe .Node (
734
+ DerivativesDataSink (
735
+ base_directory = fmriprep_dir ,
736
+ hemi = ['L' , 'R' ],
737
+ dismiss_entities = dismiss_echo (),
738
+ space = template ,
739
+ density = density ,
740
+ suffix = 'bold' ,
741
+ TaskName = all_metadata [0 ].get ('TaskName' ),
742
+ extension = '.func.gii' ,
743
+ ** prepare_timing_parameters (all_metadata [0 ]),
744
+ ),
745
+ iterfield = ('in_file' , 'hemi' ),
746
+ name = f'ds_bold_surf_wb_{ template } _{ density } ' ,
747
+ run_without_submitting = True ,
748
+ )
749
+ ds_bold_surf_wb .inputs .source_file = bold_file
750
+
751
+ workflow .connect ([
752
+ (inputnode , resample_surfaces_wf , [
753
+ ('midthickness' , 'inputnode.midthickness' ),
754
+ ('sphere_reg_fsLR' , 'inputnode.sphere_reg_fsLR' ),
755
+ ]),
756
+ (wb_vol_surf_wf , wb_surf_surf_wf , [
757
+ ('outputnode.bold_fsnative' , 'inputnode.bold_fsnative' ),
758
+ ]),
759
+ (inputnode , wb_surf_surf_wf , [
760
+ ('midthickness' , 'inputnode.midthickness' ),
761
+ ('sphere_reg_fsLR' , 'inputnode.sphere_reg_fsLR' ),
762
+ ]),
763
+ (resample_surfaces_wf , wb_surf_surf_wf , [
764
+ (
765
+ f'outputnode.midthickness_{ template } ' ,
766
+ 'inputnode.midthickness_resampled'
767
+ ),
768
+ ]),
769
+ (wb_surf_surf_wf , ds_bold_surf_wb , [
770
+ ('outputnode.bold_resampled' , 'in_file' ),
771
+ # TODO: json metadata?
772
+ ]),
773
+ ]) # fmt:skip
774
+
673
775
bold_confounds_wf = init_bold_confs_wf (
674
776
mem_gb = mem_gb ['largemem' ],
675
777
metadata = all_metadata [0 ],
0 commit comments