Skip to content

Commit eed080e

Browse files
ShotgunosineDylan
authored andcommitted
[ENH] add align_epi_anat.py interface
1 parent ff97f6a commit eed080e

File tree

2 files changed

+164
-2
lines changed

2 files changed

+164
-2
lines changed

nipype/interfaces/afni/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
"""
99

1010
from .base import Info
11-
from .preprocess import (Allineate, Automask, AutoTcorrelate,
12-
AutoTLRC,
11+
from .preprocess import (AlignEpiAnatPy,Allineate, Automask,
12+
AutoTcorrelate,AutoTLRC,
1313
Bandpass, BlurInMask, BlurToFWHM,
1414
ClipLevel, DegreeCentrality, Despike,
1515
Detrend, ECM, Fim, Fourier, Hist, LFCD,

nipype/interfaces/afni/preprocess.py

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import os
1616
import os.path as op
17+
from distutils import spawn
1718

1819
from ...utils.filemanip import (load_json, save_json, split_filename)
1920
from ..base import (
@@ -46,6 +47,167 @@ class CentralityInputSpec(AFNICommandInputSpec):
4647
desc='Mask the dataset to target brain-only voxels',
4748
argstr='-automask')
4849

50+
class AlignEpiAnatPyInputSpec(CommandLineInputSpec):
51+
outputtype = traits.Enum('AFNI', list(Info.ftypes.keys()),
52+
desc='AFNI output filetype')
53+
py27_path = File(
54+
desc='Path to Python 2.7 executable for running afni python scripts',
55+
argstr='%s '+spawn.find_executable('align_epi_anat.py'),
56+
exists=True,
57+
#default='/opt/miniconda/envs/py27/bin/python',
58+
mandatory=True,
59+
position=0
60+
)
61+
in_file = File(
62+
desc='EPI dataset to align',
63+
argstr='-epi %s',
64+
mandatory=True,
65+
exists=True,
66+
copyfile=False)
67+
anat = File(
68+
desc='name of structural dataset',
69+
argstr='-anat %s',
70+
mandatory=True,
71+
exists=True,
72+
copyfile=False)
73+
epi_base = traits.Str(
74+
desc='the epi base used in alignment'
75+
'should be one of (0/mean/median/max/subbrick#)',
76+
mandatory=True,
77+
argstr='-epi_base %s')
78+
anat2epi = traits.Bool(
79+
default = True,
80+
desc='align anatomical to EPI dataset (default)',
81+
argstr='-anat2epi')
82+
epi2anat = traits.Bool(
83+
desc='align EPI to anatomical dataset',
84+
argstr='-epi2anat')
85+
save_skullstrip = traits.Bool(
86+
desc='save skull-stripped (not aligned)',
87+
argstr='-save_skullstrip')
88+
suffix = traits.Str(
89+
desc='append suffix to the original anat/epi dataset to use'
90+
'in the resulting dataset names (default is "_al")',
91+
argstr='-suffix %s')
92+
epi_strip = traits.Enum(('3dSkullStrip','3dAutomask','None'),
93+
desc='method to mask brain in EPI data'
94+
'should be one of[3dSkullStrip]/3dAutomask/None)',
95+
argstr='-epi_strip %s')
96+
volreg = traits.Enum(('on','off'),
97+
desc='do volume registration on EPI dataset before alignment'
98+
'should be \'on\' or \'off\', defaults to \'on\'',
99+
default='on',
100+
argstr='-volreg %s')
101+
tshift = traits.Enum(('on','off'),
102+
desc='do time shifting of EPI dataset before alignment'
103+
'should be \'on\' or \'off\', defaults to \'on\'',
104+
default='on',
105+
argstr='-tshift %s')
106+
107+
class AlignEpiAnatPyOutputSpec(TraitedSpec):
108+
anat_al_orig = File(
109+
desc="A version of the anatomy that is aligned to the EPI")
110+
epi_al_orig = File(
111+
desc="A version of the EPI dataset aligned to the anatomy")
112+
epi_tlrc_al = File(
113+
desc="A version of the EPI dataset aligned to a standard template")
114+
anat_al_mat = File(
115+
desc="matrix to align anatomy to the EPI")
116+
epi_al_mat = File(
117+
desc="matrix to align EPI to anatomy")
118+
epi_vr_al_mat = File(
119+
desc="matrix to volume register EPI")
120+
epi_reg_al_mat = File(
121+
desc="matrix to volume register and align epi to anatomy")
122+
epi_al_tlrc_mat = File(
123+
desc="matrix to volume register and align epi"
124+
"to anatomy and put into standard space")
125+
epi_vr_motion = File(
126+
desc="motion parameters from EPI time-series"
127+
"registration (tsh included in name if slice"
128+
"timing correction is also included).")
129+
skullstrip = File(
130+
desc="skull-stripped (not aligned) volume")
131+
132+
class AlignEpiAnatPy(AFNICommand):
133+
"""align EPI to anatomical datasets or vice versa
134+
This Python script computes the alignment between two datasets, typically
135+
an EPI and an anatomical structural dataset, and applies the resulting
136+
transformation to one or the other to bring them into alignment.
137+
138+
This script computes the transforms needed to align EPI and
139+
anatomical datasets using a cost function designed for this purpose. The
140+
script combines multiple transformations, thereby minimizing the amount of
141+
interpolation applied to the data.
142+
143+
Basic Usage:
144+
align_epi_anat.py -anat anat+orig -epi epi+orig -epi_base 5
145+
146+
The user must provide EPI and anatomical datasets and specify the EPI
147+
sub-brick to use as a base in the alignment.
148+
149+
Internally, the script always aligns the anatomical to the EPI dataset,
150+
and the resulting transformation is saved to a 1D file.
151+
As a user option, the inverse of this transformation may be applied to the
152+
EPI dataset in order to align it to the anatomical data instead.
153+
154+
This program generates several kinds of output in the form of datasets
155+
and transformation matrices which can be applied to other datasets if
156+
needed. Time-series volume registration, oblique data transformations and
157+
Talairach (standard template) transformations will be combined as needed
158+
and requested (with options to turn on and off each of the steps) in
159+
order to create the aligned datasets.
160+
161+
For complete details, see the `align_epi_anat.py' Documentation.
162+
<https://afni.nimh.nih.gov/pub/dist/doc/program_help/align_epi_anat.py.html>`_
163+
164+
Examples
165+
========
166+
>>> from nipype.interfaces import afni
167+
>>> al_ea = afni.AlignEpiAnatPy()
168+
>>> al_ea.inputs.py27_path = "/opt/miniconda/envs/py27/bin/python"
169+
>>> al_ea.inputs.anat = "structural.nii"
170+
>>> al_ea.inputs.in_file = "functional.nii"
171+
>>> al_ea.inputs.epi_base = '0'
172+
>>> al_ea.inputs.epi_strip = '3dAutomask'
173+
>>> al_ea.inputs.volreg = 'off'
174+
>>> al_ea.inputs.tshift = 'off'
175+
>>> al_ea.inputs.save_skullstrip = True
176+
>>> al_ea.cmdline # doctest: +ALLOW_UNICODE
177+
'echo "" && /opt/miniconda/envs/py27/bin/python /root/abin/align_epi_anat.py -anat structural.nii -epi_base 0 -epi_strip 3dAutomask -epi functional.nii -save_skullstrip -tshift off -volreg off'
178+
>>> res = allineate.run() # doctest: +SKIP
179+
"""
180+
_cmd = 'echo "" && '
181+
input_spec = AlignEpiAnatPyInputSpec
182+
output_spec = AlignEpiAnatPyOutputSpec
183+
184+
def _list_outputs(self):
185+
outputs = self.output_spec().get()
186+
anat_prefix = ''.join(self._gen_fname(self.inputs.anat).split('+')[:-1])
187+
epi_prefix = ''.join(self._gen_fname(self.inputs.in_file).split('+')[:-1])
188+
ext = '.HEAD'
189+
matext='.1D'
190+
if not isdefined(self.inputs.suffix):
191+
suffix = '_al'
192+
else:
193+
suffix = '_'+self.inputs.suffix
194+
if self.inputs.anat2epi:
195+
outputs['anat_al_orig'] = os.path.abspath(self._gen_fname(anat_prefix, suffix=suffix+'+orig')+ext)
196+
outputs['anat_al_mat'] = os.path.abspath(self._gen_fname(anat_prefix, suffix=suffix+'_mat.aff12')+matext)
197+
if self.inputs.epi2anat:
198+
outputs['epi_al_orig'] = os.path.abspath(self._gen_fname(epi_prefix, suffix=suffix+'+orig')+ext)
199+
outputs['epi_al_mat'] = os.path.abspath(self._gen_fname(epi_prefix, suffix=suffix+'_mat.aff12')+matext)
200+
if self.inputs.volreg == 'on':
201+
outputs['epi_vr_al_mat'] = os.path.abspath(self._gen_fname(epi_prefix, suffix='_vr'+suffix+'_mat.aff12')+matext)
202+
if self.inputs.tshift == 'on':
203+
outputs['epi_vr_motion'] = os.path.abspath(self._gen_fname(epi_prefix, suffix='tsh_vr_motion')+matext)
204+
elif self.inputs.tshift == 'off':
205+
outputs['epi_vr_motion'] = os.path.abspath(self._gen_fname(epi_prefix, suffix='vr_motion')+matext)
206+
if self.inputs.volreg == 'on' and self.inputs.epi2anat:
207+
outputs['epi_reg_al_mat']= os.path.abspath(self._gen_fname(epi_prefix, suffix='_reg'+suffix+'_mat.aff12')+matext)
208+
if self.inputs.save_skullstrip:
209+
outputs.skullstrip = os.path.abspath(self._gen_fname(anat_prefix, suffix='_ns'+'+orig')+ext)
210+
return outputs
49211

50212
class AllineateInputSpec(AFNICommandInputSpec):
51213
in_file = File(

0 commit comments

Comments
 (0)