Skip to content

Commit 3a1e457

Browse files
committed
ENH: Allow BIDS-style slice timings to be passed directly to TShift
1 parent 205ea17 commit 3a1e457

File tree

1 file changed

+52
-4
lines changed

1 file changed

+52
-4
lines changed

nipype/interfaces/afni/preprocess.py

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
AFNICommandOutputSpec, AFNIPythonCommandInputSpec,
2020
AFNIPythonCommand, Info, no_afni)
2121

22+
from ...import logging
23+
iflogger = logging.getLogger('interface')
24+
2225

2326
class CentralityInputSpec(AFNICommandInputSpec):
2427
"""Common input spec class for all centrality-related commands
@@ -2560,9 +2563,10 @@ class TProject(AFNICommand):
25602563
input_spec = TProjectInputSpec
25612564
output_spec = AFNICommandOutputSpec
25622565

2566+
25632567
class TShiftInputSpec(AFNICommandInputSpec):
25642568
in_file = File(
2565-
desc='input file to 3dTShift',
2569+
desc='input file to 3dTshift',
25662570
argstr='%s',
25672571
position=-1,
25682572
mandatory=True,
@@ -2589,12 +2593,26 @@ class TShiftInputSpec(AFNICommandInputSpec):
25892593
desc='ignore the first set of points specified', argstr='-ignore %s')
25902594
interp = traits.Enum(
25912595
('Fourier', 'linear', 'cubic', 'quintic', 'heptic'),
2592-
desc='different interpolation methods (see 3dTShift for details) '
2596+
desc='different interpolation methods (see 3dTshift for details) '
25932597
'default = Fourier',
25942598
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
25962607
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'])
25982616
rlt = traits.Bool(
25992617
desc='Before shifting, remove the mean and linear trend',
26002618
argstr='-rlt')
@@ -2623,11 +2641,41 @@ class TShift(AFNICommand):
26232641
'3dTshift -prefix functional_tshift -tpattern alt+z -tzero 0.0 functional.nii'
26242642
>>> res = tshift.run() # doctest: +SKIP
26252643
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+
26262660
"""
26272661
_cmd = '3dTshift'
26282662
input_spec = TShiftInputSpec
26292663
output_spec = AFNICommandOutputSpec
26302664

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+
26312679

26322680
class VolregInputSpec(AFNICommandInputSpec):
26332681
in_file = File(

0 commit comments

Comments
 (0)