Skip to content

Commit 833a9e3

Browse files
committed
First version of img2imgcoord and img2stdcoord
1 parent af406fe commit 833a9e3

File tree

6 files changed

+324
-2
lines changed

6 files changed

+324
-2
lines changed

nipype/interfaces/fsl/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
ImageStats, FilterRegressor, Overlay, Slicer,
1717
PlotTimeSeries, PlotMotionParams, ConvertXFM,
1818
SwapDimensions, PowerSpectrum, Reorient2Std,
19-
Complex, InvWarp, WarpUtils, ConvertWarp)
19+
Complex, InvWarp, WarpUtils, ConvertWarp, WarpPoints, WarpPointsToStd)
2020

2121
from .epi import (PrepareFieldmap, TOPUP, ApplyTOPUP, Eddy, EPIDeWarp,
2222
SigLoss, EddyCorrect)

nipype/interfaces/fsl/tests/test_auto_ConvertWarp.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ def test_ConvertWarp_inputs():
2020
),
2121
jacobian_min=dict(argstr='--jmin=%f',
2222
),
23+
midmat=dict(argstr='--midmat=%s',
24+
),
2325
out_abswarp=dict(argstr='--absout',
2426
xor=['out_relwarp'],
2527
),
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from nipype.testing import assert_equal
3+
from nipype.interfaces.fsl.utils import WarpPoints
4+
5+
def test_WarpPoints_inputs():
6+
input_map = dict(args=dict(argstr='%s',
7+
),
8+
coord_mm=dict(argstr='-mm',
9+
xor=['coord_vox'],
10+
),
11+
coord_vox=dict(argstr='-vox',
12+
xor=['coord_mm'],
13+
),
14+
dest_file=dict(argstr='-dest %s',
15+
mandatory=True,
16+
),
17+
environ=dict(nohash=True,
18+
usedefault=True,
19+
),
20+
ignore_exception=dict(nohash=True,
21+
usedefault=True,
22+
),
23+
in_coords=dict(argstr='%s',
24+
mandatory=True,
25+
position=-1,
26+
),
27+
out_file=dict(name_source='in_coords',
28+
name_template='%s_warped',
29+
output_name='out_file',
30+
),
31+
src_file=dict(argstr='-src %s',
32+
mandatory=True,
33+
),
34+
terminal_output=dict(mandatory=True,
35+
nohash=True,
36+
),
37+
warp_file=dict(argstr='-warp %s',
38+
xor=['xfm_file'],
39+
),
40+
xfm_file=dict(argstr='-xfm %s',
41+
xor=['warp_file'],
42+
),
43+
)
44+
inputs = WarpPoints.input_spec()
45+
46+
for key, metadata in input_map.items():
47+
for metakey, value in metadata.items():
48+
yield assert_equal, getattr(inputs.traits()[key], metakey), value
49+
50+
def test_WarpPoints_outputs():
51+
output_map = dict(out_file=dict(),
52+
)
53+
outputs = WarpPoints.output_spec()
54+
55+
for key, metadata in output_map.items():
56+
for metakey, value in metadata.items():
57+
yield assert_equal, getattr(outputs.traits()[key], metakey), value
58+
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from nipype.testing import assert_equal
3+
from nipype.interfaces.fsl.utils import WarpPointsToStd
4+
5+
def test_WarpPointsToStd_inputs():
6+
input_map = dict(args=dict(argstr='%s',
7+
),
8+
coord_mm=dict(argstr='-mm',
9+
xor=['coord_vox'],
10+
),
11+
coord_vox=dict(argstr='-vox',
12+
xor=['coord_mm'],
13+
),
14+
environ=dict(nohash=True,
15+
usedefault=True,
16+
),
17+
ignore_exception=dict(nohash=True,
18+
usedefault=True,
19+
),
20+
img_file=dict(argstr='-img %s',
21+
mandatory=True,
22+
),
23+
in_coords=dict(argstr='%s',
24+
mandatory=True,
25+
position=-1,
26+
),
27+
out_file=dict(name_source='in_coords',
28+
name_template='%s_warped',
29+
output_name='out_file',
30+
),
31+
premat_file=dict(argstr='-premat %s',
32+
),
33+
std_file=dict(argstr='-std %s',
34+
mandatory=True,
35+
),
36+
terminal_output=dict(mandatory=True,
37+
nohash=True,
38+
),
39+
warp_file=dict(argstr='-warp %s',
40+
xor=['xfm_file'],
41+
),
42+
xfm_file=dict(argstr='-xfm %s',
43+
xor=['warp_file'],
44+
),
45+
)
46+
inputs = WarpPointsToStd.input_spec()
47+
48+
for key, metadata in input_map.items():
49+
for metakey, value in metadata.items():
50+
yield assert_equal, getattr(inputs.traits()[key], metakey), value
51+
52+
def test_WarpPointsToStd_outputs():
53+
output_map = dict(out_file=dict(),
54+
)
55+
outputs = WarpPointsToStd.output_spec()
56+
57+
for key, metadata in output_map.items():
58+
for metakey, value in metadata.items():
59+
yield assert_equal, getattr(outputs.traits()[key], metakey), value
60+

nipype/interfaces/fsl/utils.py

Lines changed: 203 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@
1818
import os
1919
from glob import glob
2020
import warnings
21+
import tempfile
2122

2223
import numpy as np
2324

2425
from .base import FSLCommand, FSLCommandInputSpec, Info
2526
from ..base import (traits, TraitedSpec, OutputMultiPath, File,
26-
isdefined)
27+
CommandLine, CommandLineInputSpec, isdefined)
2728
from ...utils.filemanip import (load_json, save_json, split_filename,
2829
fname_presuffix)
2930

@@ -1663,3 +1664,204 @@ class ConvertWarp(FSLCommand):
16631664
input_spec = ConvertWarpInputSpec
16641665
output_spec = ConvertWarpOutputSpec
16651666
_cmd = 'convertwarp'
1667+
1668+
1669+
class WarpPointsBaseInputSpec(CommandLineInputSpec):
1670+
in_coords = File(exists=True, position=-1, argstr='%s', mandatory=True,
1671+
desc=('filename of file containing coordinates'))
1672+
xfm_file = File(exists=True, argstr='-xfm %s', xor=['warp_file'],
1673+
desc=('filename of affine transform (e.g. source2dest.mat)'))
1674+
warp_file = File(exists=True, argstr='-warp %s', xor=['xfm_file'],
1675+
desc=('filename of warpfield (e.g. '
1676+
'intermediate2dest_warp.nii.gz)'))
1677+
coord_vox = traits.Bool(True, argstr='-vox', xor=['coord_mm'],
1678+
desc=('all coordinates in voxels - default'))
1679+
coord_mm = traits.Bool(False, argstr='-mm', xor=['coord_vox'],
1680+
desc=('all coordinates in mm'))
1681+
out_file = File(name_source='in_coords',
1682+
name_template='%s_warped', output_name='out_file',
1683+
desc='output file name')
1684+
1685+
class WarpPointsInputSpec(WarpPointsBaseInputSpec):
1686+
src_file = File(exists=True, argstr='-src %s', mandatory=True,
1687+
desc=('filename of source image'))
1688+
dest_file = File(exists=True, argstr='-dest %s', mandatory=True,
1689+
desc=('filename of destination image'))
1690+
1691+
1692+
class WarpPointsOutputSpec(TraitedSpec):
1693+
out_file = File(exists=True,
1694+
desc=('Name of output file, containing the warp as field or coefficients.'))
1695+
1696+
1697+
class WarpPoints(CommandLine):
1698+
"""Use FSL `img2imgcoord <http://fsl.fmrib.ox.ac.uk/fsl/fsl-4.1.9/flirt/overview.html>`_
1699+
to transform point sets. Accepts plain text files and vtk files.
1700+
1701+
.. Note:: transformation of TrackVis trk files is not yet implemented
1702+
1703+
1704+
Examples::
1705+
1706+
>>> from nipype.interfaces.fsl import WarpPoints
1707+
>>> warppoints = WarpPoints()
1708+
>>> warppoints.inputs.in_coords = 'surf.txt'
1709+
>>> warppoints.inputs.src_file = 'epi.nii'
1710+
>>> warppoints.inputs.dest_file = 'T1.nii'
1711+
>>> warppoints.inputs.warp_file = 'warpfield.nii'
1712+
>>> warppoints.inputs.coord_mm = True
1713+
>>> warppoints.cmdline # doctest: +ELLIPSIS
1714+
'img2imgcoord -mm -dest T1.nii -scr epi.nii -warp warpfield.nii surf.txt'
1715+
>>> res = invwarp.run() # doctest: +SKIP
1716+
"""
1717+
1718+
input_spec = WarpPointsInputSpec
1719+
output_spec = WarpPointsOutputSpec
1720+
_cmd = 'img2imgcoord'
1721+
_terminal_output = 'stream'
1722+
1723+
def __init__(self, command=None, **inputs):
1724+
self._tmpfile = None
1725+
super(WarpPoints, self).__init__(command=command, **inputs)
1726+
1727+
def _format_arg(self, name, trait_spec, value):
1728+
if name == 'out_file':
1729+
return ''
1730+
else:
1731+
return super(WarpPoints, self)._format_arg(name, trait_spec, value)
1732+
1733+
def _parse_inputs(self, skip=None):
1734+
import os.path as op
1735+
fname, ext = op.splitext(self.inputs.in_coords)
1736+
setattr(self, '_in_file', fname)
1737+
setattr(self, '_outformat', ext[1:])
1738+
first_args = super(WarpPoints, self)._parse_inputs(skip=['in_coords', 'out_file'])
1739+
1740+
second_args = fname + '.txt'
1741+
1742+
if ext in ['.vtk', '.trk']:
1743+
if self._tmpfile is None:
1744+
self._tmpfile = tempfile.NamedTemporaryFile(suffix='.txt', dir=os.getcwd()).name
1745+
second_args = self._tmpfile
1746+
1747+
return first_args + [ second_args ]
1748+
1749+
def _vtk_to_coords(self, in_file, out_file=None):
1750+
import os.path as op
1751+
try:
1752+
from tvtk.api import tvtk
1753+
except ImportError:
1754+
raise ImportError('This interface requires tvtk to run.')
1755+
1756+
reader = tvtk.PolyDataReader(file_name=in_file+'.vtk')
1757+
reader.update()
1758+
points = reader.output.points
1759+
1760+
if out_file is None:
1761+
out_file, _ = op.splitext(in_file) + '.txt'
1762+
1763+
np.savetxt(out_file, points)
1764+
return out_file
1765+
1766+
def _coords_to_vtk(self, points, out_file):
1767+
import os.path as op
1768+
try:
1769+
from tvtk.api import tvtk
1770+
except ImportError:
1771+
raise ImportError('This interface requires tvtk to run.')
1772+
1773+
reader = tvtk.PolyDataReader(file_name=self.inputs.in_file)
1774+
reader.update()
1775+
mesh = reader.output
1776+
mesh.points = points
1777+
1778+
writer = tvtk.PolyDataWriter(file_name=out_file, input=mesh)
1779+
writer.write()
1780+
1781+
def _trk_to_coords(self, in_file, out_file=None):
1782+
raise NotImplementedError('trk files are not yet supported')
1783+
try:
1784+
from nibabel.trackvis import TrackvisFile
1785+
except ImportError:
1786+
raise ImportError('This interface requires nibabel to run')
1787+
1788+
trkfile = TrackvisFile.from_file(in_file)
1789+
streamlines = trkfile.streamlines
1790+
1791+
if out_file is None:
1792+
out_file, _ = op.splitext(in_file)
1793+
1794+
np.savetxt(points, out_file + '.txt')
1795+
return out_file + '.txt'
1796+
1797+
def _coords_to_trk(self, points, out_file):
1798+
raise NotImplementedError('trk files are not yet supported')
1799+
1800+
def _overload_extension(self, value, name):
1801+
if name == 'out_file':
1802+
return '%s.%s' % (value, getattr(self, '_outformat'))
1803+
1804+
def _run_interface(self, runtime):
1805+
fname = getattr(self, '_in_file')
1806+
outformat = getattr(self, '_outformat')
1807+
tmpfile = None
1808+
1809+
if outformat == 'vtk':
1810+
tmpfile = self._tmpfile
1811+
self._vtk_to_coords(fname, out_file=tmpfile)
1812+
elif outformat == 'trk':
1813+
tmpfile = self._tmpfile
1814+
self._trk_to_coords(fname, out_file=tmpfile)
1815+
1816+
runtime = super(WarpPoints, self)._run_interface(runtime)
1817+
newpoints = np.fromstring('\n'.join(runtime.stdout.split('\n')[1:]), sep=' ')
1818+
1819+
if not tmpfile is None:
1820+
os.unlink(tmpfile.name)
1821+
1822+
out_file = self._filename_from_source('out_file')
1823+
1824+
if outformat == 'vtk':
1825+
self._coords_to_vtk(newpoints, out_file)
1826+
elif outformat == 'trk':
1827+
self._coords_to_trk(newpoints, out_file)
1828+
else:
1829+
np.savetxt(out_file, newpoints.reshape(-1,3))
1830+
return runtime
1831+
1832+
1833+
class WarpPointsToStdInputSpec(WarpPointsBaseInputSpec):
1834+
img_file = File(exists=True, argstr='-img %s', mandatory=True,
1835+
desc=('filename of input image'))
1836+
std_file = File(exists=True, argstr='-std %s', mandatory=True,
1837+
desc=('filename of destination image'))
1838+
premat_file = File(exists=True, argstr='-premat %s',
1839+
desc=('filename of pre-warp affine transform '
1840+
'(e.g. example_func2highres.mat)'))
1841+
1842+
1843+
class WarpPointsToStd(WarpPoints):
1844+
"""
1845+
Use FSL `img2stdcoord <http://fsl.fmrib.ox.ac.uk/fsl/fsl-4.1.9/flirt/overview.html>`_
1846+
to transform point sets to standard space coordinates. Accepts plain text files and
1847+
vtk files.
1848+
1849+
.. Note:: transformation of TrackVis trk files is not yet implemented
1850+
1851+
Examples::
1852+
1853+
>>> from nipype.interfaces.fsl import WarpPointsToStd
1854+
>>> warppoints = WarpPointsToStd()
1855+
>>> warppoints.inputs.in_coords = 'surf.txt'
1856+
>>> warppoints.inputs.img_file = 'T1.nii'
1857+
>>> warppoints.inputs.std_file = 'mni.nii'
1858+
>>> warppoints.inputs.warp_file = 'warpfield.nii'
1859+
>>> warppoints.inputs.coord_mm = True
1860+
>>> warppoints.cmdline # doctest: +ELLIPSIS
1861+
'img2stdcoord -mm -img T1.nii -std mni.nii -warp warpfield.nii surf.txt'
1862+
>>> res = invwarp.run() # doctest: +SKIP
1863+
"""
1864+
1865+
input_spec = WarpPointsToStdInputSpec
1866+
output_spec = WarpPointsOutputSpec
1867+
_cmd = 'img2stdcoord'

nipype/testing/data/surf.txt

Whitespace-only changes.

0 commit comments

Comments
 (0)