Commit b389e7ee authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

Merge branch 'rel/3.9.5' into 'v3.9'

Rel/3.9.5

See merge request fsl/fslpy!345
parents 51f0828d e86a5d3d
Pipeline #14578 passed with stages
in 1 minute and 58 seconds
......@@ -2,6 +2,27 @@ This document contains the ``fslpy`` release history in reverse chronological
order.
3.9.5 (Thursday 2nd June 2022)
------------------------------
Changed
^^^^^^^
* Updated the :func:`.ensureIsImage` function to support ``pathlib.Path``
objects (!343).
Fixed
^^^^^
* Some fixes in the :mod:`.wrappers` module (specifically in the
:class:`.FileOrThing` class) to better support ``pathlib.Path`` objects
(!343).
3.9.4 (Friday 27th May 2022)
----------------------------
......@@ -13,7 +34,6 @@ Changed
* Changed the behaviour of :meth:`.Image.__getitem__` so that, if image
data is accessed with a boolean mask array (e.g. ``image[mask > 0]``),
the image data is loaded into memory (!341).
* Fixed an issue in the :func:`.func_to_cmd` function (!339).
3.9.3 (Friday 27th May 2022)
......
......@@ -13,6 +13,7 @@ that some condition is met.
ensureIsImage
"""
import pathlib
import nibabel as nib
......@@ -22,7 +23,7 @@ import fsl.data.image as fslimage
def ensureIsImage(img):
"""Ensures that the given ``img`` is an in-memory ``nibabel`` object.
"""
if isinstance(img, str):
if isinstance(img, (str, pathlib.Path)):
img = fslimage.addExt(img)
img = nib.load(img)
return img
......@@ -47,7 +47,7 @@ import re
import string
__version__ = '3.9.4'
__version__ = '3.9.5'
"""Current version number, as a string. """
......
......@@ -76,6 +76,21 @@ Similarly, we can run a ``fslmaths`` command on in-memory images::
output = fslmaths(image).mas(mask).bin().run()
It is possible to run a Python script in Windows, and call FSL commands which
are installed in a WSL environment. When specifying inputs/outputs as
file/directory paths, the safest option is to use ``pathlib.Path`` objects
to ensure that they are correctly translated bewteen Windows and Linux-style
paths, e.g.::
from pathlib import Path
from fsl.wrappers import bet
bet(Path('T1\\T1.nii.gz`), Path('T1_brain'))
If you use strings to specify inputs/outputs, they must be absolute paths, as
they may otherwise not be translated correctly.
If you are *writing* wrapper functions, take a look at the
:mod:`.wrapperutils` module - it contains several useful functions and
decorators.
......
......@@ -709,6 +709,7 @@ class FileOrThing:
- The argument value that was passed in
"""
self.__func = func
self.__prepIn = prepIn
self.__prepOut = prepOut
......@@ -873,6 +874,8 @@ class FileOrThing:
# accept an output prefix which contains
# a directory path.
if prefix is not None:
if isinstance(prefix, pathlib.Path):
prefix = op.abspath(prefix)
# If prefix is set to LOAD,
# all generated output files
......@@ -965,6 +968,15 @@ class FileOrThing:
if realPrefix is not None and len(prefixedFiles) == 0:
allargs[self.__outprefix] = realPrefix
# Turn any Path objects into absolute path
# strings. Don't use Path.resolve(), as it
# returns a relative path for non-existent
# files/dirs on Windows/certain Python
# versions.
for k, v in allargs.items():
if isinstance(v, pathlib.Path):
allargs[k] = op.abspath(v)
args = [allargs.pop(k) for k in argnames]
kwargs = allargs
......
......@@ -5,6 +5,7 @@
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
import pathlib
import numpy as np
import nibabel as nib
......@@ -22,8 +23,10 @@ def test_ensureIsImage():
assert ensure.ensureIsImage(img) is img
loaded = [ensure.ensureIsImage('image.nii'),
ensure.ensureIsImage('image')]
loaded = [ensure.ensureIsImage( 'image.nii'),
ensure.ensureIsImage( 'image'),
ensure.ensureIsImage(pathlib.Path('image')),
ensure.ensureIsImage(pathlib.Path('image.nii'))]
for l in loaded:
assert isinstance(l, nib.nifti1.Nifti1Image)
......
......@@ -475,6 +475,44 @@ def test_fileOrThing_outprefix():
cleardir(td, 'myout*')
def test_fileOrThing_pathlib():
@wutils.fileOrImage('img', 'out')
def basefunc(img, out):
img = np.asanyarray(nib.load(img).dataobj)
outimg = nib.nifti1.Nifti1Image(img * 5, np.eye(4))
nib.save(outimg, out)
with tempdir.tempdir() as td:
img = nib.nifti1.Nifti1Image(np.array([[1, 2], [3, 4]]), np.eye(4))
exp = np.asanyarray(img.dataobj) * 5
nib.save(img, 'img.nii')
basefunc(pathlib.Path('img.nii'), pathlib.Path('output.nii'))
assert np.all(np.asanyarray(nib.load('output.nii') .dataobj) == exp)
def test_fileOrThing_outprefix_pathlib():
@wutils.fileOrImage('img', outprefix='output_base')
def basefunc(img, output_base):
img = np.asanyarray(nib.load(img).dataobj)
out1 = nib.nifti1.Nifti1Image(img * 5, np.eye(4))
out2 = nib.nifti1.Nifti1Image(img * 10, np.eye(4))
nib.save(out1, '{}_times5.nii.gz' .format(output_base))
nib.save(out2, '{}_times10.nii.gz'.format(output_base))
with tempdir.tempdir() as td:
img = nib.nifti1.Nifti1Image(np.array([[1, 2], [3, 4]]), np.eye(4))
exp1 = np.asanyarray(img.dataobj) * 5
exp2 = np.asanyarray(img.dataobj) * 10
nib.save(img, 'img.nii')
basefunc(pathlib.Path('img.nii'), pathlib.Path('myout'))
assert np.all(np.asanyarray(nib.load('myout_times5.nii.gz') .dataobj) == exp1)
assert np.all(np.asanyarray(nib.load('myout_times10.nii.gz').dataobj) == exp2)
def test_fileOrThing_outprefix_differentTypes():
@wutils.fileOrImage('img', outprefix='outpref')
......
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