From e0d897b54dc04abfdaf36b30188e83fd89becd16 Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Sun, 12 Mar 2017 18:31:55 +0000 Subject: [PATCH] ImageWrapper "adjustment" (sort of but not really a bugfix). When an image is written to, the old coverages are not discarded - rather, the new data range is calculated on the union of the old coverage and the write slice, across all volumes. --- fsl/data/image.py | 10 ++++----- fsl/data/imagewrapper.py | 48 +++++++++++++++++++++++++++------------- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/fsl/data/image.py b/fsl/data/image.py index c1cf28cc9..ea537f80c 100644 --- a/fsl/data/image.py +++ b/fsl/data/image.py @@ -486,11 +486,11 @@ class Nifti(notifier.Notifier): @memoize.Instanceify(memoize.memoize) def isNeurological(self): - """Returns ``True`` if it looks like this ``Nifti`` object is in - neurological orientation, ``False`` otherwise. This test is purely - based on the determinant of the voxel-to-mm transformation matrix - - if it has a positive determinant, the image is assumed to be in - neurological orientation, otherwise it is assumed to be in + """Returns ``True`` if it looks like this ``Nifti`` object has a + neurological voxel orientation, ``False`` otherwise. This test is + purely based on the determinant of the voxel-to-mm transformation + matrix - if it has a positive determinant, the image is assumed to + be in neurological orientation, otherwise it is assumed to be in radiological orientation. See http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FLIRT/FAQ#What_is_the\ diff --git a/fsl/data/imagewrapper.py b/fsl/data/imagewrapper.py index 921dd6e36..458865eaf 100644 --- a/fsl/data/imagewrapper.py +++ b/fsl/data/imagewrapper.py @@ -421,13 +421,15 @@ class ImageWrapper(notifier.Notifier): log.debug('Updating image {} data range [slice: {}] ' '(current range: [{}, {}]; ' 'number of expansions: {}; ' - 'current coverage: {})'.format( + 'current coverage: {}; ' + 'volume ranges: {})'.format( self.__name, slices, self.__range[0], self.__range[1], len(expansions), - self.__coverage)) + self.__coverage, + self.__volRanges)) # As we access the data for each expansions, # we want it to have the same dimensionality @@ -530,30 +532,46 @@ class ImageWrapper(notifier.Notifier): # area and the current coverage, then it's # easy - we just expand the coverage to # include the newly written area. + # + # But if there is overlap between the written + # area and the current coverage, things are + # more complicated, because the portion of + # the image that has been written over may + # have contained the currently known data + # minimum/maximum. We have no way of knowing + # this, so we have to reset the coverage (on + # the affected volumes), and recalculate the + # data range. if overlap in (OVERLAP_SOME, OVERLAP_ALL): - # If there is overlap between the written - # area and the current coverage, things are - # more complicated, because the portion of - # the image that has been written over may - # have contained the currently known data - # minimum/maximum. We have no way of knowing - # this, so we have to reset the coverage (on - # the affected volumes), and recalculate the - # data range. - # TODO Could you store the location of the # data minimum/maximum (in each volume), # so you know whether resetting the # coverage is necessary? lowVol, highVol = slices[self.__numRealDims - 1] + # We create a single slice which + # encompasses the given slice, and + # all existing coverages for each + # volume in the given slice. The + # data range for this slice will + # be recalculated. + slices = adjustCoverage(self.__coverage[:, :, lowVol], slices) + for vol in range(lowVol + 1, highVol): + slices = adjustCoverage(slices, self.__coverage[:, :, vol].T) + + slices = np.array(slices.T, dtype=np.uint32) + slices = tuple(it.chain(map(tuple, slices), [(lowVol, highVol)])) + log.debug('Image {} data written - clearing known data ' - 'range on volumes {} - {} (write slice: {})'.format( + 'range on volumes {} - {} (write slice: {}; ' + 'coverage: {}; volRanges: {})'.format( self.__name, lowVol, highVol, - slices)) + slices, + self.__coverage[:, :, lowVol:highVol], + self.__volRanges[lowVol:highVol, :])) for vol in range(lowVol, highVol): self.__coverage[:, :, vol] = np.nan @@ -909,7 +927,7 @@ def adjustCoverage(oldCoverage, slices): :return: A ``numpy`` array containing the adjusted/expanded coverage. """ - newCoverage = np.zeros(oldCoverage.shape, dtype=np.uint32) + newCoverage = np.zeros(oldCoverage.shape, dtype=oldCoverage.dtype) for dim in range(oldCoverage.shape[1]): -- GitLab