Commit 0ee48df0 authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

Merge branch 'enh/wrappers_support_fsl_image' into 'master'

Support fsl data image in wrappers

See merge request fsl/fslpy!53
parents 523b1f6e 14b4211d
Pipeline #2025 passed with stages
in 16 minutes and 5 seconds
......@@ -2,6 +2,18 @@ This document contains the ``fslpy`` release history in reverse chronological
order.
1.8.1 (Friday May 11th 2018)
----------------------------
Changed
^^^^^^^
* The :func:`.fileOrImage` decorator function now accepts :class:`.Image`
objects as well as ``nibabel`` image objects.
1.8.0 (Thursday May 3rd 2018)
-----------------------------
......
......@@ -48,12 +48,10 @@ Some extra dependencies are listed in `requirements.txt
on the mesh.
If you are using Linux, need to install wxPython first, as binaries are not
available on PyPI. Change the URL for your specific platform::
To install these additional dependencies, you first need to install wxPython,
which is still in pre-relaes.
- **macOS**: ``pip install --pre wxPython``
- **Linux** (change the URL for your specific platform): ``pip install --only-binary wxpython -f https://extras.wxpython.org/wxPython4/extras/linux/gtk2/ubuntu-16.04/ wxpython``
pip install -f https://extras.wxpython.org/wxPython4/extras/linux/gtk2/ubuntu-16.04/ wxpython
The ``rtree`` library also assumes that ``libspatialindex`` is installed on
......
......@@ -42,6 +42,7 @@ the following labels (this convention has been inherited from `nibabel
* *DOC*: for all kinds of documentation related commits
* *TEST*: for adding or changing tests
* *MAINT*: for administrative/maintenance changes
* *CI*: for continuous-integration changes
Version number
......
......@@ -635,13 +635,25 @@ class _FileOrThing(object):
def fileOrImage(*imgargs):
"""Decorator which can be used to ensure that any NIfTI images are saved
to file, and output images can be loaded and returned as ``nibabel``
image objects.
image objects or :class:`.Image` objects.
"""
# keep track of the input argument
# types on each call, so we know
# whether to return a fsl.Image or
# a nibabel image
intypes = []
def prepIn(workdir, name, val):
infile = None
if isinstance(val, (fslimage.Image, nib.nifti1.Nifti1Image)):
intypes.append(type(val))
if isinstance(val, fslimage.Image):
val = val.nibImage
if isinstance(val, nib.nifti1.Nifti1Image):
infile = val.get_filename()
......@@ -661,13 +673,28 @@ def fileOrImage(*imgargs):
# create an independent in-memory
# copy of the image file
img = nib.load(path)
return nib.nifti1.Nifti1Image(img.get_data(), None, img.header)
# if any arguments were fsl images,
# that takes precedence.
if fslimage.Image in intypes:
return fslimage.Image(img.get_data(), header=img.header)
# but if all inputs were file names,
# nibabel takes precedence
elif nib.nifti1.Nifti1Image in intypes or len(intypes) == 0:
return nib.nifti1.Nifti1Image(img.get_data(), None, img.header)
# this function should not be called
# under any other circumstances
else:
raise RuntimeError('Cannot handle type: {}'.format(intypes))
def decorator(func):
fot = _FileOrThing(func, prepIn, prepOut, load, *imgargs)
def wrapper(*args, **kwargs):
return fot(*args, **kwargs)
result = fot(*args, **kwargs)
intypes[:] = []
return result
return _update_wrapper(wrapper, func)
......
......@@ -15,6 +15,7 @@ from fsl.data.atlases import Atlas
from pytest import raises
from .test_image import make_image
import os
import pytest
datadir = op.join(op.dirname(__file__), 'testdata')
......@@ -115,6 +116,7 @@ def test_image_out():
assert args.image_out == 'test.surf.gii' + extension
@pytest.mark.fsltest
def test_atlas():
atlas_parser = argparse.ArgumentParser('reads an atlas')
atlas_parser.add_argument('atlas', type=parse_data.Atlas)
......@@ -123,4 +125,4 @@ def test_atlas():
assert isinstance(args.atlas, Atlas)
with raises(SystemExit):
atlas_parser.parse_args(['fake'])
\ No newline at end of file
atlas_parser.parse_args(['fake'])
......@@ -21,6 +21,7 @@ import nibabel as nib
import fsl.utils.tempdir as tempdir
import fsl.utils.run as run
import fsl.utils.fslsub as fslsub
import fsl.data.image as fslimage
import fsl.wrappers.wrapperutils as wutils
......@@ -284,6 +285,28 @@ def test_fileOrImage():
assert np.all(nib.load('output.nii').get_data() == expected)
os.remove('output.nii')
# fslimage, file, load
result = func(fslimage.Image(img1), img2='img2.nii',
output=wutils.LOAD)['output']
assert isinstance(result, fslimage.Image)
assert np.all(result[:].squeeze() == expected)
# fslimage, fslimage, load
result = func(fslimage.Image(img1), img2=fslimage.Image(img2),
output=wutils.LOAD)['output']
assert isinstance(result, fslimage.Image)
assert np.all(result[:].squeeze() == expected)
# fslimage, nib.image, load
result = func(fslimage.Image(img1), img2=img2,
output=wutils.LOAD)['output']
assert isinstance(result, fslimage.Image)
assert np.all(result[:].squeeze() == expected)
# nib.image, nib.image, load
result = func(img1, img2=img2, output=wutils.LOAD)['output']
assert isinstance(result, nib.nifti1.Nifti1Image)
assert np.all(result.get_data()[:] == expected)
def test_chained_fileOrImageAndArray():
......
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