Commit 7d6d1346 authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

Merge branch 'rel/3.6.3' into 'v3.6'

Version 3.6.3

See merge request fsl/fslpy!303
parents 694694f1 cab56e08
Pipeline #9830 passed with stages
in 1 minute and 30 seconds
......@@ -3,6 +3,19 @@ order.
3.6.3 (Wednesday 28th July 2021)
--------------------------------
Changed
^^^^^^^
* When creating an ``Image`` object with ``loadData=False``, the ``calcRange``
argument is ignored, as it would otherwise cause the data to be loaded
(!301).
3.6.2 (Wednesday 23rd June 2021)
--------------------------------
......
......@@ -1042,7 +1042,8 @@ class Image(Nifti):
calculated immediately (vi a call to
:meth:`calcRange`). Otherwise, the image range is
incrementally updated as more data is read from memory
or disk.
or disk. If ``loadData=False``, ``calcRange`` is also
set to ``False``.
:arg threaded: If ``True``, the :class:`.ImageWrapper` will use a
separate thread for data range calculation. Defaults
......@@ -1065,8 +1066,11 @@ class Image(Nifti):
nibImage = None
saved = False
if loadData:
threaded = False
# disable threaded access if loadData is True
threaded = threaded and (not loadData)
# don't calcRange if not loading data
calcRange = calcRange and loadData
# Take a copy of the header if one has
# been provided
......
......@@ -388,6 +388,14 @@ class ImageWrapper(notifier.Notifier):
self.__data = np.asanyarray(self.__image.dataobj)
@property
def dataIsLoaded(self):
"""Return true if the image data has been loaded into memory, ``False``
otherwise.
"""
return self.__data is not None
def __getData(self, sliceobj, isTuple=False):
"""Retrieves the image data at the location specified by ``sliceobj``.
......
......@@ -133,10 +133,18 @@ def getDataFile(meldir):
if topDir is None:
return None
dataFile = op.join(topDir, 'filtered_func_data')
# People often rename filtered_func_data.nii.gz
# to something like filtered_func_data_clean.nii.gz,
# because that is the recommended approach when
# performing ICA-based denoising). So we try both.
candidates = ['filtered_func_data', 'filtered_func_data_clean']
try: return fslimage.addExt(dataFile)
except fslimage.PathError: return None
for candidate in candidates:
dataFile = op.join(topDir, candidate)
try: return fslimage.addExt(dataFile)
except fslimage.PathError: continue
return None
def getMeanFile(meldir):
......
......@@ -47,7 +47,7 @@ import re
import string
__version__ = '3.6.2'
__version__ = '3.6.3'
"""Current version number, as a string. """
......
......@@ -321,3 +321,26 @@ def _test_image_calcRange(threaded):
if threaded:
img.getImageWrapper().getTaskThread().waitUntilIdle()
assert img.dataRange == (0, 1)
# sanity check - make sure data is not loaded
# when loadData is False (fsl/fslpy#374)
def test_Image_loadData():
with tests.testdir() as testdir:
filename = 'image.nii.gz'
# Data range grows with volume
data = np.zeros((50, 50, 50, 50))
for vol in range(data.shape[-1]):
data[..., vol] = vol
fslimage.Image(data).save(filename)
img = fslimage.Image(filename, loadData=False)
assert not img.getImageWrapper().dataIsLoaded
img = fslimage.Image(filename, loadData=False, calcRange=False)
assert not img.getImageWrapper().dataIsLoaded
img = fslimage.Image(filename, loadData=False, calcRange=True)
assert not img.getImageWrapper().dataIsLoaded
......@@ -129,6 +129,12 @@ def test_getDataFile():
'analysis.feat/filtered_func_data.nii.gz'],
'analysis.feat/filtfunc.ica',
'analysis.feat/filtered_func_data.nii.gz'),
(['analysis.feat/filtfunc.ica/melodic_IC.nii.gz',
'analysis.feat/filtfunc.ica/melodic_mix',
'analysis.feat/filtfunc.ica/melodic_FTmix',
'analysis.feat/filtered_func_data_clean.nii.gz'],
'analysis.feat/filtfunc.ica',
'analysis.feat/filtered_func_data_clean.nii.gz'),
(['no/analysis/dirs/here/melodic_IC.nii.gz'],
'no/analysis/dirs/here/',
None),
......@@ -137,7 +143,6 @@ def test_getDataFile():
'analysis.feat/analysis.ica/melodic_FTmix'],
'analysis.feat/analysis.ica',
None),
]
for paths, meldir, expected in testcases:
......
Markdown is supported
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