6
6
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7
7
8
8
.. autofunction:: init_func_preproc_wf
9
- .. autofunction:: init_func_reports_wf
10
9
.. autofunction:: init_func_derivatives_wf
11
10
12
11
"""
40
39
init_bold_surf_wf ,
41
40
init_bold_mni_trans_wf ,
42
41
init_bold_preproc_trans_wf ,
43
- init_bold_preproc_report_wf ,
44
42
)
45
43
from .util import init_bold_reference_wf
46
44
@@ -269,6 +267,12 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
269
267
"Using standard EPI-T1 coregistration." )
270
268
t2s_coreg = False
271
269
270
+ # Switch stc off
271
+ if multiecho and run_stc is True :
272
+ LOGGER .warning ('Slice-timing correction is not available for '
273
+ 'multiecho BOLD data (not implemented).' )
274
+ run_stc = False
275
+
272
276
# Build workflow
273
277
workflow = pe .Workflow (name = wf_name )
274
278
inputnode = pe .Node (niu .IdentityInterface (
@@ -298,20 +302,13 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
298
302
pe_direction = metadata .get ("PhaseEncodingDirection" )),
299
303
name = 'summary' , mem_gb = DEFAULT_MEMORY_MIN_GB , run_without_submitting = True )
300
304
301
- func_reports_wf = init_func_reports_wf (reportlets_dir = reportlets_dir ,
302
- freesurfer = freesurfer ,
303
- use_aroma = use_aroma ,
304
- use_syn = use_syn ,
305
- t2s_coreg = t2s_coreg )
306
-
307
305
func_derivatives_wf = init_func_derivatives_wf (output_dir = output_dir ,
308
306
output_spaces = output_spaces ,
309
307
template = template ,
310
308
freesurfer = freesurfer ,
311
309
use_aroma = use_aroma )
312
310
313
311
workflow .connect ([
314
- (inputnode , func_reports_wf , [('bold_file' , 'inputnode.source_file' )]),
315
312
(inputnode , func_derivatives_wf , [('bold_file' , 'inputnode.source_file' )]),
316
313
(outputnode , func_derivatives_wf , [
317
314
('bold_t1' , 'inputnode.bold_t1' ),
@@ -406,8 +403,10 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
406
403
(boldbuffer , bold_split , [('bold_file' , 'in_file' )]),
407
404
# Generate early reference
408
405
(inputnode , bold_reference_wf , [('bold_file' , 'inputnode.bold_file' )]),
409
- (bold_reference_wf , func_reports_wf , [
410
- ('outputnode.validation_report' , 'inputnode.validation_report' )]),
406
+ # HMC
407
+ (bold_reference_wf , bold_hmc_wf , [
408
+ ('outputnode.raw_ref_image' , 'inputnode.raw_ref_image' ),
409
+ ('outputnode.bold_file' , 'inputnode.bold_file' )]),
411
410
# EPI-T1 registration workflow
412
411
(inputnode , bold_reg_wf , [
413
412
('bold_file' , 'inputnode.name_source' ),
@@ -423,10 +422,6 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
423
422
('t1_2_fsnative_reverse_transform' , 'inputnode.t1_2_fsnative_reverse_transform' )]),
424
423
(bold_split , bold_reg_wf , [('out_files' , 'inputnode.bold_split' )]),
425
424
(bold_hmc_wf , bold_reg_wf , [('outputnode.xforms' , 'inputnode.hmc_xforms' )]),
426
- (bold_reg_wf , func_reports_wf , [
427
- ('outputnode.out_report' , 'inputnode.bold_reg_report' ),
428
- ('outputnode.fallback' , 'inputnode.bold_reg_fallback' ),
429
- ]),
430
425
(bold_reg_wf , outputnode , [('outputnode.bold_t1' , 'bold_t1' ),
431
426
('outputnode.bold_aseg_t1' , 'bold_aseg_t1' ),
432
427
('outputnode.bold_aparc_t1' , 'bold_aparc_t1' )]),
@@ -454,24 +449,21 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
454
449
('outputnode.movpar_file' , 'inputnode.movpar_file' )]),
455
450
(bold_reg_wf , bold_confounds_wf , [
456
451
('outputnode.itk_t1_to_bold' , 'inputnode.t1_bold_xform' )]),
457
- (bold_confounds_wf , func_reports_wf , [
458
- ('outputnode.rois_report' , 'inputnode.bold_rois_report' )]),
459
452
(bold_confounds_wf , outputnode , [
460
453
('outputnode.confounds_file' , 'confounds' ),
461
454
]),
462
455
# Connect bold_bold_trans_wf
463
456
(inputnode , bold_bold_trans_wf , [
464
457
('bold_file' , 'inputnode.name_source' )]),
465
458
(bold_split , bold_bold_trans_wf , [
466
- ('out_files' , 'inputnode.bold_split ' )]),
459
+ ('out_files' , 'inputnode.bold_file ' )]),
467
460
(bold_hmc_wf , bold_bold_trans_wf , [
468
461
('outputnode.xforms' , 'inputnode.hmc_xforms' )]),
469
462
(bold_bold_trans_wf , bold_confounds_wf , [
470
463
('outputnode.bold' , 'inputnode.bold' ),
471
464
('outputnode.bold_mask' , 'inputnode.bold_mask' )]),
472
465
# Summary
473
466
(outputnode , summary , [('confounds' , 'confounds_file' )]),
474
- (summary , func_reports_wf , [('out_report' , 'inputnode.summary_report' )]),
475
467
])
476
468
477
469
if fmaps :
@@ -506,94 +498,45 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
506
498
('outputnode.syn_bold_ref' , 'inputnode.in_post' )]),
507
499
])
508
500
509
- # Fill-in datasinks of reportlets seen so far
510
- for node in workflow .list_node_names ():
511
- if node .split ('.' )[- 1 ].startswith ('ds_report' ):
512
- workflow .get_node (node ).inputs .base_directory = reportlets_dir
513
- workflow .get_node (node ).inputs .source_file = bold_file
514
-
515
501
# if multiecho data, select first echo for hmc correction
516
502
if multiecho :
517
503
inputnode .iterables = ('bold_file' , bold_file )
518
504
519
- me_first_echo = pe .JoinNode (interface = FirstEcho (te_list = tes ),
520
- joinfield = ['in_files' , 'ref_imgs' ],
521
- joinsource = 'inputnode' ,
522
- name = 'me_first_echo' )
505
+ me_first_echo = pe .Node (FirstEcho (
506
+ te_list = tes , in_files = bold_file , ref_imgs = bold_file ),
507
+ name = 'me_first_echo' )
508
+ # Replace reference with the echo selected with FirstEcho
509
+ workflow .disconnect ([
510
+ (inputnode , bold_reference_wf , [
511
+ ('bold_file' , 'inputnode.bold_file' )]),
512
+ ])
523
513
workflow .connect ([
524
- (bold_reference_wf , me_first_echo , [
525
- ('outputnode.bold_file' , 'in_files' ),
526
- ('outputnode.raw_ref_image' , 'ref_imgs' )]),
527
- (me_first_echo , bold_hmc_wf , [
528
- ('first_image' , 'inputnode.bold_file' ),
529
- ('first_ref_image' , 'inputnode.raw_ref_image' )])
514
+ (me_first_echo , bold_reference_wf , [
515
+ ('first_image' , 'inputnode.bold_file' )])
530
516
])
531
517
532
518
if t2s_coreg :
533
- # use a joinNode to gather all preprocessed echos
534
- join_split_echos = pe .JoinNode (niu .IdentityInterface (fields = ['echo_files' ]),
535
- joinsource = 'inputnode' ,
536
- joinfield = 'echo_files' ,
537
- name = 'join_split_echos' )
538
-
539
519
# create a T2* map
540
- bold_t2s_wf = init_bold_t2s_wf (echo_times = tes ,
541
- name = 'bold_t2s_wf' ,
542
- mem_gb = mem_gb ['filesize' ],
543
- omp_nthreads = omp_nthreads )
544
-
545
- subset_reg_reports = pe .JoinNode (niu .Select (index = 0 ),
546
- name = 'subset_reg_reports' ,
547
- joinsource = inputnode ,
548
- joinfield = ['inlist' ])
549
-
550
- subset_reg_fallbacks = pe .JoinNode (niu .Select (index = 0 ),
551
- name = 'subset_reg_fallbacks' ,
552
- joinsource = inputnode ,
553
- joinfield = ['inlist' ])
554
-
555
- first_echo = pe .Node (niu .IdentityInterface (fields = ['first_echo' ]),
556
- name = 'first_echo' )
557
- first_echo .inputs .first_echo = ref_file
558
-
559
- # remove duplicate registration reports
520
+ bold_t2s_wf = init_bold_t2s_wf (bold_echos = bold_file ,
521
+ echo_times = tes ,
522
+ mem_gb = mem_gb ['resampled' ],
523
+ omp_nthreads = omp_nthreads ,
524
+ name = 'bold_t2s_wf' )
525
+ bold_t2s_wf .inputs .inputnode .name_source = ref_file
526
+
527
+ # Replace EPI-to-T1w registration inputs
560
528
workflow .disconnect ([
561
- (bold_reg_wf , func_reports_wf , [
562
- ('outputnode.out_report' , 'inputnode.bold_reg_report' ),
563
- ('outputnode.fallback' , 'inputnode.bold_reg_fallback' )]),
564
529
(bold_sdc_wf , bold_reg_wf , [
565
- ('outputnode.out_warp' , 'inputnode.fieldwarp' ),
566
530
('outputnode.bold_ref_brain' , 'inputnode.ref_bold_brain' ),
567
531
('outputnode.bold_mask' , 'inputnode.ref_bold_mask' )]),
568
532
])
569
-
570
533
workflow .connect ([
571
- (first_echo , func_reports_wf , [
572
- ('first_echo' , 'inputnode.first_echo' )]),
573
- (bold_split , join_split_echos , [
574
- ('out_files' , 'echo_files' )]),
575
- (join_split_echos , bold_t2s_wf , [
576
- ('echo_files' , 'inputnode.echo_split' )]),
577
534
(bold_hmc_wf , bold_t2s_wf , [
578
535
('outputnode.xforms' , 'inputnode.hmc_xforms' )]),
579
536
(bold_t2s_wf , bold_reg_wf , [
580
537
('outputnode.t2s_map' , 'inputnode.ref_bold_brain' ),
581
538
('outputnode.oc_mask' , 'inputnode.ref_bold_mask' )]),
582
- (bold_reg_wf , subset_reg_reports , [
583
- ('outputnode.out_report' , 'inlist' )]),
584
- (bold_reg_wf , subset_reg_fallbacks , [
585
- ('outputnode.fallback' , 'inlist' )]),
586
- (subset_reg_reports , func_reports_wf , [
587
- ('out' , 'inputnode.bold_reg_report' )]),
588
- (subset_reg_fallbacks , func_reports_wf , [
589
- ('out' , 'inputnode.bold_reg_fallback' )]),
590
539
])
591
- else :
592
- workflow .connect ([
593
- (bold_reference_wf , bold_hmc_wf , [
594
- ('outputnode.raw_ref_image' , 'inputnode.raw_ref_image' ),
595
- ('outputnode.bold_file' , 'inputnode.bold_file' )])
596
- ])
597
540
598
541
# Map final BOLD mask into T1w space (if required)
599
542
if 'T1w' in output_spaces :
@@ -684,8 +627,6 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
684
627
('outputnode.melodic_mix' , 'melodic_mix' ),
685
628
('outputnode.nonaggr_denoised_file' , 'nonaggr_denoised_file' )]),
686
629
(join , outputnode , [('out_file' , 'confounds' )]),
687
- (ica_aroma_wf , func_reports_wf , [
688
- ('outputnode.out_report' , 'inputnode.ica_aroma_report' )]),
689
630
])
690
631
691
632
# SURFACES ##################################################################################
@@ -706,89 +647,28 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
706
647
])
707
648
708
649
# REPORTING ############################################################
709
- bold_bold_report_wf = init_bold_preproc_report_wf (
710
- mem_gb = mem_gb ['resampled' ],
711
- reportlets_dir = reportlets_dir
712
- )
713
-
714
- workflow .connect ([
715
- (inputnode , bold_bold_report_wf , [
716
- ('bold_file' , 'inputnode.name_source' ),
717
- ('bold_file' , 'inputnode.in_pre' )]), # This should be after STC
718
- (bold_bold_trans_wf , bold_bold_report_wf , [
719
- ('outputnode.bold' , 'inputnode.in_post' )]),
720
- ])
721
-
722
- return workflow
723
-
724
-
725
- def init_func_reports_wf (reportlets_dir , freesurfer , use_aroma ,
726
- use_syn , t2s_coreg , name = 'func_reports_wf' ):
727
- """
728
- Set up a battery of datasinks to store reports in the right location
729
- """
730
- workflow = pe .Workflow (name = name )
731
-
732
- inputnode = pe .Node (
733
- niu .IdentityInterface (
734
- fields = ['source_file' , 'summary_report' , 'validation_report' ,
735
- 'bold_reg_report' , 'bold_reg_fallback' , 'bold_rois_report' ,
736
- 'syn_sdc_report' , 'ica_aroma_report' , 'first_echo' ]),
737
- name = 'inputnode' )
738
-
739
- ds_summary_report = pe .Node (
740
- DerivativesDataSink (base_directory = reportlets_dir ,
741
- suffix = 'summary' ),
742
- name = 'ds_summary_report' , run_without_submitting = True ,
650
+ ds_report_summary = pe .Node (
651
+ DerivativesDataSink (suffix = 'summary' ),
652
+ name = 'ds_report_summary' , run_without_submitting = True ,
743
653
mem_gb = DEFAULT_MEMORY_MIN_GB )
744
654
745
- ds_validation_report = pe .Node (
655
+ ds_report_validation = pe .Node (
746
656
DerivativesDataSink (base_directory = reportlets_dir ,
747
657
suffix = 'validation' ),
748
- name = 'ds_validation_report' , run_without_submitting = True ,
749
- mem_gb = DEFAULT_MEMORY_MIN_GB )
750
-
751
- ds_bold_rois_report = pe .Node (
752
- DerivativesDataSink (base_directory = reportlets_dir ,
753
- suffix = 'rois' ),
754
- name = 'ds_bold_rois_report' , run_without_submitting = True ,
755
- mem_gb = DEFAULT_MEMORY_MIN_GB )
756
-
757
- def _bold_reg_suffix (fallback , freesurfer ):
758
- if fallback :
759
- return 'coreg' if freesurfer else 'flirt'
760
- return 'bbr' if freesurfer else 'flt_bbr'
761
-
762
- ds_bold_reg_report = pe .Node (
763
- DerivativesDataSink (base_directory = reportlets_dir ),
764
- name = 'ds_bold_reg_report' , run_without_submitting = True ,
765
- mem_gb = DEFAULT_MEMORY_MIN_GB )
766
-
767
- ds_ica_aroma_report = pe .Node (
768
- DerivativesDataSink (base_directory = reportlets_dir ,
769
- suffix = 'ica_aroma' ),
770
- name = 'ds_ica_aroma_report' , run_without_submitting = True ,
658
+ name = 'ds_report_validation' , run_without_submitting = True ,
771
659
mem_gb = DEFAULT_MEMORY_MIN_GB )
772
660
773
661
workflow .connect ([
774
- (inputnode , ds_bold_reg_report , [
775
- ('first_echo' if t2s_coreg else 'source_file' , 'source_file' )]),
776
- (inputnode , ds_summary_report , [('source_file' , 'source_file' ),
777
- ('summary_report' , 'in_file' )]),
778
- (inputnode , ds_validation_report , [('source_file' , 'source_file' ),
779
- ('validation_report' , 'in_file' )]),
780
- (inputnode , ds_bold_rois_report , [('source_file' , 'source_file' ),
781
- ('bold_rois_report' , 'in_file' )]),
782
- (inputnode , ds_bold_reg_report , [
783
- ('bold_reg_report' , 'in_file' ),
784
- (('bold_reg_fallback' , _bold_reg_suffix , freesurfer ), 'suffix' )]),
662
+ (summary , ds_report_summary , [('out_report' , 'in_file' )]),
663
+ (bold_reference_wf , ds_report_validation , [
664
+ ('outputnode.validation_report' , 'in_file' )]),
785
665
])
786
666
787
- if use_aroma :
788
- workflow .connect ([
789
- ( inputnode , ds_ica_aroma_report , [( 'source_file' , 'source_file' ),
790
- ( 'ica_aroma_report' , 'in_file' )]),
791
- ])
667
+ # Fill-in datasinks of reportlets seen so far
668
+ for node in workflow .list_node_names ():
669
+ if node . split ( '.' )[ - 1 ]. startswith ( 'ds_report' ):
670
+ workflow . get_node ( node ). inputs . base_directory = reportlets_dir
671
+ workflow . get_node ( node ). inputs . source_file = ref_file
792
672
793
673
return workflow
794
674
0 commit comments