20
20
AFNICommandOutputSpec , AFNIPythonCommandInputSpec ,
21
21
AFNIPythonCommand , Info , no_afni )
22
22
23
+ from ...import logging
24
+ iflogger = logging .getLogger ('nipype.interface' )
25
+
23
26
24
27
class CentralityInputSpec (AFNICommandInputSpec ):
25
28
"""Common input spec class for all centrality-related commands
@@ -2565,9 +2568,10 @@ class TProject(AFNICommand):
2565
2568
output_spec = AFNICommandOutputSpec
2566
2569
2567
2570
2571
+
2568
2572
class TShiftInputSpec (AFNICommandInputSpec ):
2569
2573
in_file = File (
2570
- desc = 'input file to 3dTShift ' ,
2574
+ desc = 'input file to 3dTshift ' ,
2571
2575
argstr = '%s' ,
2572
2576
position = - 1 ,
2573
2577
mandatory = True ,
@@ -2594,12 +2598,26 @@ class TShiftInputSpec(AFNICommandInputSpec):
2594
2598
desc = 'ignore the first set of points specified' , argstr = '-ignore %s' )
2595
2599
interp = traits .Enum (
2596
2600
('Fourier' , 'linear' , 'cubic' , 'quintic' , 'heptic' ),
2597
- desc = 'different interpolation methods (see 3dTShift for details) '
2601
+ desc = 'different interpolation methods (see 3dTshift for details) '
2598
2602
'default = Fourier' ,
2599
2603
argstr = '-%s' )
2600
- tpattern = Str (
2604
+ tpattern = traits .Either (
2605
+ traits .Enum ('alt+z' , 'altplus' , # Synonyms
2606
+ 'alt+z2' ,
2607
+ 'alt-z' , 'altminus' , # Synonyms
2608
+ 'alt-z2' ,
2609
+ 'seq+z' , 'seqplus' , # Synonyms
2610
+ 'seq-z' , 'seqminus' ), # Synonyms
2611
+ Str , # For backwards compatibility
2601
2612
desc = 'use specified slice time pattern rather than one in header' ,
2602
- argstr = '-tpattern %s' )
2613
+ argstr = '-tpattern %s' ,
2614
+ xor = ['slice_timing' ])
2615
+ slice_timing = traits .Either (
2616
+ File (exists = True ),
2617
+ traits .List (traits .Float ),
2618
+ desc = 'time offsets from the volume acquisition onset for each slice' ,
2619
+ argstr = '-tpattern @%s' ,
2620
+ xor = ['tpattern' ])
2603
2621
rlt = traits .Bool (
2604
2622
desc = 'Before shifting, remove the mean and linear trend' ,
2605
2623
argstr = '-rlt' )
@@ -2609,6 +2627,10 @@ class TShiftInputSpec(AFNICommandInputSpec):
2609
2627
argstr = '-rlt+' )
2610
2628
2611
2629
2630
+ class TShiftOutputSpec (AFNICommandOutputSpec ):
2631
+ timing_file = File (desc = "AFNI formatted timing file, if ``slice_timing`` is a list" )
2632
+
2633
+
2612
2634
class TShift (AFNICommand ):
2613
2635
"""Shifts voxel time series from input so that seperate slices are aligned
2614
2636
to the same temporal origin.
@@ -2619,19 +2641,101 @@ class TShift(AFNICommand):
2619
2641
Examples
2620
2642
========
2621
2643
2644
+ Slice timing details may be specified explicitly via the ``slice_timing``
2645
+ input:
2646
+
2622
2647
>>> from nipype.interfaces import afni
2648
+ >>> TR = 2.5
2649
+ >>> tshift = afni.TShift()
2650
+ >>> tshift.inputs.in_file = 'functional.nii'
2651
+ >>> tshift.inputs.tzero = 0.0
2652
+ >>> tshift.inputs.tr = '%.1fs' % TR
2653
+ >>> tshift.inputs.slice_timing = list(np.arange(40) / TR)
2654
+ >>> tshift.cmdline
2655
+ '3dTshift -prefix functional_tshift -tpattern @slice_timing.1D -TR 2.5s -tzero 0.0 functional.nii'
2656
+
2657
+ When the ``slice_timing`` input is used, the ``timing_file`` output is populated,
2658
+ in this case with the generated file.
2659
+
2660
+ >>> tshift._list_outputs()['timing_file'] # doctest: +ELLIPSIS
2661
+ '.../slice_timing.1D'
2662
+
2663
+ This method creates a ``slice_timing.1D`` file to be passed to ``3dTshift``.
2664
+ A pre-existing slice-timing file may be used in the same way:
2665
+
2666
+ >>> tshift = afni.TShift()
2667
+ >>> tshift.inputs.in_file = 'functional.nii'
2668
+ >>> tshift.inputs.tzero = 0.0
2669
+ >>> tshift.inputs.tr = '%.1fs' % TR
2670
+ >>> tshift.inputs.slice_timing = 'slice_timing.1D'
2671
+ >>> tshift.cmdline
2672
+ '3dTshift -prefix functional_tshift -tpattern @slice_timing.1D -TR 2.5s -tzero 0.0 functional.nii'
2673
+
2674
+ When a pre-existing file is provided, ``timing_file`` is simply passed through.
2675
+
2676
+ >>> tshift._list_outputs()['timing_file'] # doctest: +ELLIPSIS
2677
+ '.../slice_timing.1D'
2678
+
2679
+ Alternatively, pre-specified slice timing patterns may be specified with the
2680
+ ``tpattern`` input.
2681
+ For example, to specify an alternating, ascending slice timing pattern:
2682
+
2623
2683
>>> tshift = afni.TShift()
2624
2684
>>> tshift.inputs.in_file = 'functional.nii'
2685
+ >>> tshift.inputs.tzero = 0.0
2686
+ >>> tshift.inputs.tr = '%.1fs' % TR
2625
2687
>>> tshift.inputs.tpattern = 'alt+z'
2688
+ >>> tshift.cmdline
2689
+ '3dTshift -prefix functional_tshift -tpattern alt+z -TR 2.5s -tzero 0.0 functional.nii'
2690
+
2691
+ For backwards compatibility, ``tpattern`` may also take filenames prefixed
2692
+ with ``@``.
2693
+ However, in this case, filenames are not validated, so this usage will be
2694
+ deprecated in future versions of Nipype.
2695
+
2696
+ >>> tshift = afni.TShift()
2697
+ >>> tshift.inputs.in_file = 'functional.nii'
2626
2698
>>> tshift.inputs.tzero = 0.0
2699
+ >>> tshift.inputs.tr = '%.1fs' % TR
2700
+ >>> tshift.inputs.tpattern = '@slice_timing.1D'
2627
2701
>>> tshift.cmdline
2628
- '3dTshift -prefix functional_tshift -tpattern alt+z -tzero 0.0 functional.nii'
2629
- >>> res = tshift.run() # doctest: +SKIP
2702
+ '3dTshift -prefix functional_tshift -tpattern @slice_timing.1D -TR 2.5s -tzero 0.0 functional.nii'
2703
+
2704
+ In these cases, ``timing_file`` is undefined.
2630
2705
2706
+ >>> tshift._list_outputs()['timing_file'] # doctest: +ELLIPSIS
2707
+ <undefined>
2708
+
2709
+ In any configuration, the interface may be run as usual:
2710
+
2711
+ >>> res = tshift.run() # doctest: +SKIP
2631
2712
"""
2632
2713
_cmd = '3dTshift'
2633
2714
input_spec = TShiftInputSpec
2634
- output_spec = AFNICommandOutputSpec
2715
+ output_spec = TShiftOutputSpec
2716
+
2717
+ def _format_arg (self , name , trait_spec , value ):
2718
+ if name == 'tpattern' and value .startswith ('@' ):
2719
+ iflogger .warning ('Passing a file prefixed by "@" will be deprecated'
2720
+ '; please use the `slice_timing` input' )
2721
+ elif name == 'slice_timing' and isinstance (value , list ):
2722
+ value = self ._write_slice_timing ()
2723
+ return super (TShift , self )._format_arg (name , trait_spec , value )
2724
+
2725
+ def _write_slice_timing (self ):
2726
+ fname = 'slice_timing.1D'
2727
+ with open (fname , 'w' ) as fobj :
2728
+ fobj .write ('\t ' .join (map (str , self .inputs .slice_timing )))
2729
+ return fname
2730
+
2731
+ def _list_outputs (self ):
2732
+ outputs = super (TShift , self )._list_outputs ()
2733
+ if isdefined (self .inputs .slice_timing ):
2734
+ if isinstance (self .inputs .slice_timing , list ):
2735
+ outputs ['timing_file' ] = os .path .abspath ('slice_timing.1D' )
2736
+ else :
2737
+ outputs ['timing_file' ] = os .path .abspath (self .inputs .slice_timing )
2738
+ return outputs
2635
2739
2636
2740
2637
2741
class VolregInputSpec (AFNICommandInputSpec ):
0 commit comments