Skip to content
Snippets Groups Projects
Commit 3033db8b authored by Paul McCarthy's avatar Paul McCarthy :mountain_bicyclist:
Browse files

Merge branch 'rf/melodic-datafile' into 'master'

RF: Ignore calcRange if loadData=False (fsl/fslpy#374)

Closes #374

See merge request fsl/fslpy!301
parents c17195b5 fce7f058
No related branches found
No related tags found
No related merge requests found
Pipeline #9819 canceled
...@@ -1042,7 +1042,8 @@ class Image(Nifti): ...@@ -1042,7 +1042,8 @@ class Image(Nifti):
calculated immediately (vi a call to calculated immediately (vi a call to
:meth:`calcRange`). Otherwise, the image range is :meth:`calcRange`). Otherwise, the image range is
incrementally updated as more data is read from memory 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 :arg threaded: If ``True``, the :class:`.ImageWrapper` will use a
separate thread for data range calculation. Defaults separate thread for data range calculation. Defaults
...@@ -1065,8 +1066,11 @@ class Image(Nifti): ...@@ -1065,8 +1066,11 @@ class Image(Nifti):
nibImage = None nibImage = None
saved = False saved = False
if loadData: # disable threaded access if loadData is True
threaded = False 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 # Take a copy of the header if one has
# been provided # been provided
......
...@@ -388,6 +388,14 @@ class ImageWrapper(notifier.Notifier): ...@@ -388,6 +388,14 @@ class ImageWrapper(notifier.Notifier):
self.__data = np.asanyarray(self.__image.dataobj) 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): def __getData(self, sliceobj, isTuple=False):
"""Retrieves the image data at the location specified by ``sliceobj``. """Retrieves the image data at the location specified by ``sliceobj``.
......
...@@ -133,10 +133,18 @@ def getDataFile(meldir): ...@@ -133,10 +133,18 @@ def getDataFile(meldir):
if topDir is None: if topDir is None:
return 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) for candidate in candidates:
except fslimage.PathError: return None dataFile = op.join(topDir, candidate)
try: return fslimage.addExt(dataFile)
except fslimage.PathError: continue
return None
def getMeanFile(meldir): def getMeanFile(meldir):
......
...@@ -321,3 +321,26 @@ def _test_image_calcRange(threaded): ...@@ -321,3 +321,26 @@ def _test_image_calcRange(threaded):
if threaded: if threaded:
img.getImageWrapper().getTaskThread().waitUntilIdle() img.getImageWrapper().getTaskThread().waitUntilIdle()
assert img.dataRange == (0, 1) 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(): ...@@ -129,6 +129,12 @@ def test_getDataFile():
'analysis.feat/filtered_func_data.nii.gz'], 'analysis.feat/filtered_func_data.nii.gz'],
'analysis.feat/filtfunc.ica', 'analysis.feat/filtfunc.ica',
'analysis.feat/filtered_func_data.nii.gz'), '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/melodic_IC.nii.gz'],
'no/analysis/dirs/here/', 'no/analysis/dirs/here/',
None), None),
...@@ -137,7 +143,6 @@ def test_getDataFile(): ...@@ -137,7 +143,6 @@ def test_getDataFile():
'analysis.feat/analysis.ica/melodic_FTmix'], 'analysis.feat/analysis.ica/melodic_FTmix'],
'analysis.feat/analysis.ica', 'analysis.feat/analysis.ica',
None), None),
] ]
for paths, meldir, expected in testcases: for paths, meldir, expected in testcases:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment