Commit 9b4203c7 authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

Merge branch 'enh_parse_data' into 'master'

Added support for neuroimaging files in argparse

See merge request fsl/fslpy!46
parents 75a2eea6 a9cfc8e0
Pipeline #1890 canceled with stages
#!/usr/bin/env python
#
# Support for neuroimage data in argparse
#
# Author: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk
#
"""This module contains support for neuroimaging data in argparse
Argparse is the built-in python library for resolving command line arguments.
The functions in this module can be passed on to the ``type`` argument in the ``ArgumentParser.add_command`` method
to interpret command line arguments as neuroimageing objects (.e.g, NIFTI image files)
.. autosummary::
:nosignatures:
Image
ImageOut
Mesh
Atlas
"""
from fsl.data import image, gifti, vtk, atlases
from fsl.utils import path
import argparse
def Image(filename):
"""
Reads in an image from a NIFTI or Analyze file.
:arg filename: filename provided by the user
:return: fsl.data.image.Image object
"""
try:
full_filename = image.addExt(filename)
except path.PathError as e:
raise argparse.ArgumentTypeError(*e.args)
return image.Image(full_filename)
def ImageOut(basename):
"""
Uses the FSL convention to create a complete image output filename
:param basename: filename provided by the user
:return: filename with extension
"""
return image.addExt(basename, mustExist=False)
def Mesh(filename):
"""
Reads in a mesh from either a GIFTI (.surf.gii) or a VTK (.vtk) file
:param filename: filename provided by the user
:return: GIFTI or VTK sub-class of fsl.data.mesh.Mesh
"""
try:
full_filename = path.addExt(filename, ['.surf.gii', '.vtk'])
except path.PathError as e:
raise argparse.ArgumentTypeError(*e.args)
if path.hasExt(full_filename, '.surf.gii'):
return gifti.GiftiMesh(full_filename)
else:
return vtk.VTKMesh(full_filename)
def Atlas(name):
"""
Reads in the atlas from the FSL standard atlases
:param name: name of the atlas
:return: fsl.data.atlases.Atlas representation of an FSL atlas
"""
atlases.rescanAtlases()
if not atlases.hasAtlas(name):
atlas_names = tuple(desc.atlasID for desc in atlases.listAtlases())
raise argparse.ArgumentTypeError('Requested atlas %r not one of: %r' % (name, atlas_names))
return atlases.loadAtlas(name)
......@@ -305,7 +305,7 @@ def applyArgStyle(style, valsep=None, argmap=None, valmap=None, **kwargs):
def namedPositionals(func, args):
"""Given a function, and a sequence of positional arguments destined
for that function, identiifes the name for each positional argument.
for that function, identifies the name for each positional argument.
Variable positional arguments are given an automatic name.
:arg func: Function which will accept ``args`` as positionals.
......
#!/usr/bin/env python
#
# test_parse_data.py -
#
# Author: Michiel Cottaar <Michiel.Cottaar@ndcn.ox.ac.uk>
#
import argparse
from fsl.utils import parse_data, tempdir, path
import os.path as op
from fsl.data.vtk import VTKMesh
from fsl.data.gifti import GiftiMesh
from fsl.data.image import Image
from fsl.data.atlases import Atlas
from pytest import raises
from .test_image import make_image
import os
datadir = op.join(op.dirname(__file__), 'testdata')
def test_mesh():
mesh_parser = argparse.ArgumentParser("Reads a VTK file")
mesh_parser.add_argument("mesh", type=parse_data.Mesh)
real_filename = op.join(datadir, 'test_mesh.vtk')
args = mesh_parser.parse_args([real_filename])
assert isinstance(args.mesh, VTKMesh)
real_filename = op.join(datadir, 'test_mesh')
args = mesh_parser.parse_args([real_filename])
assert isinstance(args.mesh, VTKMesh)
real_filename = op.join(datadir, 'example.surf.gii')
args = mesh_parser.parse_args([real_filename])
assert isinstance(args.mesh, GiftiMesh)
real_filename = op.join(datadir, 'example')
args = mesh_parser.parse_args([real_filename])
assert isinstance(args.mesh, GiftiMesh)
fake_filename = op.join(datadir, 'test_mesh_fake.vtk')
with raises(SystemExit):
mesh_parser.parse_args([fake_filename])
fake_filename = op.join(datadir, 'example.shape.gii')
with raises(SystemExit):
mesh_parser.parse_args([fake_filename])
def test_image():
with tempdir.tempdir() as testdir:
image_parser = argparse.ArgumentParser("Reads an image")
image_parser.add_argument("image", type=parse_data.Image)
for filetype in range(3):
filename = op.join(testdir, 'image%r' % filetype)
make_image(filename, filetype)
args = image_parser.parse_args([filename])
assert isinstance(args.image, Image)
if filetype == 0:
args = image_parser.parse_args([filename + '.hdr'])
assert isinstance(args.image, Image)
args = image_parser.parse_args([filename + '.img'])
assert isinstance(args.image, Image)
with raises(SystemExit):
image_parser.parse_args([filename + '.nii'])
with raises(SystemExit):
image_parser.parse_args([filename + '.nii.gz'])
else:
args = image_parser.parse_args([filename + '.nii'])
assert isinstance(args.image, Image)
with raises(SystemExit):
image_parser.parse_args([filename + '.img'])
with raises(SystemExit):
image_parser.parse_args([filename + '.hdr'])
with raises(SystemExit):
image_parser.parse_args([filename + '.nii.gz'])
double_filename = op.join(testdir, 'image1')
make_image(double_filename, 0)
with raises(SystemExit):
image_parser.parse_args([double_filename])
def test_image_out():
image_parser = argparse.ArgumentParser("Reads an image")
image_parser.add_argument("image_out", type=parse_data.ImageOut)
for fsl_output_type, extension in (
('NIFTI', '.nii'),
('NIFTI_PAIR', '.img'),
('NIFTI_GZ', '.nii.gz')
):
os.environ['FSLOUTPUTTYPE'] = fsl_output_type
args = image_parser.parse_args(['test'])
assert path.hasExt(args.image_out, extension)
assert args.image_out == 'test' + extension
args = image_parser.parse_args(['test.nii'])
assert path.hasExt(args.image_out, '.nii')
assert args.image_out == 'test.nii'
args = image_parser.parse_args(['test.nii.gz'])
assert path.hasExt(args.image_out, '.nii.gz')
assert args.image_out == 'test.nii.gz'
args = image_parser.parse_args(['test.img'])
assert path.hasExt(args.image_out, '.img')
assert args.image_out == 'test.img'
args = image_parser.parse_args(['test.surf.gii'])
assert path.hasExt(args.image_out, extension)
assert args.image_out == 'test.surf.gii' + extension
def test_atlas():
atlas_parser = argparse.ArgumentParser('reads an atlas')
atlas_parser.add_argument('atlas', type=parse_data.Atlas)
args = atlas_parser.parse_args(['cerebellum_mniflirt'])
assert isinstance(args.atlas, Atlas)
with raises(SystemExit):
atlas_parser.parse_args(['fake'])
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment