|
18 | 18 | import os
|
19 | 19 | from glob import glob
|
20 | 20 | import warnings
|
| 21 | +import tempfile |
21 | 22 |
|
22 | 23 | import numpy as np
|
23 | 24 |
|
24 | 25 | from .base import FSLCommand, FSLCommandInputSpec, Info
|
25 | 26 | from ..base import (traits, TraitedSpec, OutputMultiPath, File,
|
26 |
| - isdefined) |
| 27 | + CommandLine, CommandLineInputSpec, isdefined) |
27 | 28 | from ...utils.filemanip import (load_json, save_json, split_filename,
|
28 | 29 | fname_presuffix)
|
29 | 30 |
|
@@ -1663,3 +1664,204 @@ class ConvertWarp(FSLCommand):
|
1663 | 1664 | input_spec = ConvertWarpInputSpec
|
1664 | 1665 | output_spec = ConvertWarpOutputSpec
|
1665 | 1666 | _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' |
0 commit comments