20
20
AFNICommandOutputSpec , AFNIPythonCommandInputSpec ,
21
21
AFNIPythonCommand , Info , no_afni )
22
22
23
+ from ...import logging
24
+ iflogger = logging .getLogger ('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 .Enum (
2605
+ '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' )
@@ -2628,11 +2646,41 @@ class TShift(AFNICommand):
2628
2646
'3dTshift -prefix functional_tshift -tpattern alt+z -tzero 0.0 functional.nii'
2629
2647
>>> res = tshift.run() # doctest: +SKIP
2630
2648
2649
+ Slice timings may be explicitly specified:
2650
+
2651
+ >>> TR = 2.5
2652
+ >>> tshift = afni.TShift()
2653
+ >>> tshift.inputs.in_file = 'functional.nii'
2654
+ >>> tshift.inputs.tzero = 0.0
2655
+ >>> tshift.inputs.tr = '%.1fs' % TR
2656
+ >>> tshift.inputs.slice_timing = list(np.arange(40) / TR)
2657
+ >>> tshift.cmdline
2658
+ '3dTshift -prefix functional_tshift -tpattern @slice_timing.1D -TR 2.5s -tzero 0.0 functional.nii'
2659
+
2660
+ This will create the ``slice_timing.1D`` file in the working directory.
2661
+ You may wish to remove this after running:
2662
+
2663
+ >>> os.unlink('slice_timing.1D')
2664
+
2631
2665
"""
2632
2666
_cmd = '3dTshift'
2633
2667
input_spec = TShiftInputSpec
2634
2668
output_spec = AFNICommandOutputSpec
2635
2669
2670
+ def _format_arg (self , name , trait_spec , value ):
2671
+ if name == 'tpattern' and value .startswith ('@' ):
2672
+ iflogger .warning ('Passing a file prefixed by "@" will be deprecated'
2673
+ '; please use the `slice_timing` input' )
2674
+ elif name == 'slice_timing' and isinstance (value , list ):
2675
+ value = self ._write_slice_timing ()
2676
+ return super (TShift , self )._format_arg (name , trait_spec , value )
2677
+
2678
+ def _write_slice_timing (self ):
2679
+ fname = 'slice_timing.1D'
2680
+ with open (fname , 'w' ) as fobj :
2681
+ fobj .write ('\t ' .join (map (str , self .inputs .slice_timing )))
2682
+ return fname
2683
+
2636
2684
2637
2685
class VolregInputSpec (AFNICommandInputSpec ):
2638
2686
in_file = File (
0 commit comments