19
19
AFNICommandOutputSpec , AFNIPythonCommandInputSpec ,
20
20
AFNIPythonCommand , Info , no_afni )
21
21
22
+ from ...import logging
23
+ iflogger = logging .getLogger ('interface' )
24
+
22
25
23
26
class CentralityInputSpec (AFNICommandInputSpec ):
24
27
"""Common input spec class for all centrality-related commands
@@ -2560,9 +2563,10 @@ class TProject(AFNICommand):
2560
2563
input_spec = TProjectInputSpec
2561
2564
output_spec = AFNICommandOutputSpec
2562
2565
2566
+
2563
2567
class TShiftInputSpec (AFNICommandInputSpec ):
2564
2568
in_file = File (
2565
- desc = 'input file to 3dTShift ' ,
2569
+ desc = 'input file to 3dTshift ' ,
2566
2570
argstr = '%s' ,
2567
2571
position = - 1 ,
2568
2572
mandatory = True ,
@@ -2589,12 +2593,26 @@ class TShiftInputSpec(AFNICommandInputSpec):
2589
2593
desc = 'ignore the first set of points specified' , argstr = '-ignore %s' )
2590
2594
interp = traits .Enum (
2591
2595
('Fourier' , 'linear' , 'cubic' , 'quintic' , 'heptic' ),
2592
- desc = 'different interpolation methods (see 3dTShift for details) '
2596
+ desc = 'different interpolation methods (see 3dTshift for details) '
2593
2597
'default = Fourier' ,
2594
2598
argstr = '-%s' )
2595
- tpattern = Str (
2599
+ tpattern = traits .Enum (
2600
+ 'alt+z' , 'altplus' , # Synonyms
2601
+ 'alt+z2' ,
2602
+ 'alt-z' , 'altminus' , # Synonyms
2603
+ 'alt-z2' ,
2604
+ 'seq+z' , 'seqplus' , # Synonyms
2605
+ 'seq-z' , 'seqminus' , # Synonyms
2606
+ Str , # For backwards compatibility
2596
2607
desc = 'use specified slice time pattern rather than one in header' ,
2597
- argstr = '-tpattern %s' )
2608
+ argstr = '-tpattern %s' ,
2609
+ xor = ['slice_timing' ])
2610
+ slice_timing = traits .Either (
2611
+ File (exists = True ),
2612
+ traits .List (traits .Float ),
2613
+ desc = 'time offsets from the volume acquisition onset for each slice' ,
2614
+ argstr = '-tpattern @%s' ,
2615
+ xor = ['tpattern' ])
2598
2616
rlt = traits .Bool (
2599
2617
desc = 'Before shifting, remove the mean and linear trend' ,
2600
2618
argstr = '-rlt' )
@@ -2623,11 +2641,41 @@ class TShift(AFNICommand):
2623
2641
'3dTshift -prefix functional_tshift -tpattern alt+z -tzero 0.0 functional.nii'
2624
2642
>>> res = tshift.run() # doctest: +SKIP
2625
2643
2644
+ Slice timings may be explicitly specified:
2645
+
2646
+ >>> TR = 2.5
2647
+ >>> tshift = afni.TShift()
2648
+ >>> tshift.inputs.in_file = 'functional.nii'
2649
+ >>> tshift.inputs.tzero = 0.0
2650
+ >>> tshift.inputs.tr = '%.1fs' % TR
2651
+ >>> tshift.inputs.slice_timing = list(np.arange(40) / TR)
2652
+ >>> tshift.cmdline
2653
+ '3dTshift -prefix functional_tshift -tpattern @slice_timing.1D -TR 2.5s -tzero 0.0 functional.nii'
2654
+
2655
+ This will create the ``slice_timing.1D`` file in the working directory.
2656
+ You may wish to remove this after running:
2657
+
2658
+ >>> os.unlink('slice_timing.1D')
2659
+
2626
2660
"""
2627
2661
_cmd = '3dTshift'
2628
2662
input_spec = TShiftInputSpec
2629
2663
output_spec = AFNICommandOutputSpec
2630
2664
2665
+ def _format_arg (self , name , trait_spec , value ):
2666
+ if name == 'tpattern' and value .startswith ('@' ):
2667
+ iflogger .warning ('Passing a file prefixed by "@" will be deprecated'
2668
+ '; please use the `slice_timing` input' )
2669
+ elif name == 'slice_timing' and isinstance (value , list ):
2670
+ value = self ._write_slice_timing ()
2671
+ return super (TShift , self )._format_arg (name , trait_spec , value )
2672
+
2673
+ def _write_slice_timing (self ):
2674
+ fname = 'slice_timing.1D'
2675
+ with open (fname , 'w' ) as fobj :
2676
+ fobj .write ('\t ' .join (map (str , self .inputs .slice_timing )))
2677
+ return fname
2678
+
2631
2679
2632
2680
class VolregInputSpec (AFNICommandInputSpec ):
2633
2681
in_file = File (
0 commit comments