def test_canonicalShape(): # (input, expected) tests = [ ((10, ), (10, 1, 1)), ((10, 1), (10, 1, 1)), ((10, 1, 1), (10, 1, 1)), ((10, 1, 1, 1), (10, 1, 1)), ((10, 1, 1, 1, 1), (10, 1, 1)), ((10, 10), (10, 10, 1)), ((10, 10, 1), (10, 10, 1)), ((10, 10, 1, 1), (10, 10, 1)), ((10, 10, 1, 1, 1), (10, 10, 1)), ((10, 10, 10), (10, 10, 10)), ((10, 10, 10, 1), (10, 10, 10)), ((10, 10, 10, 1, 1), (10, 10, 10)), ((10, 10, 10, 10), (10, 10, 10, 10)), ((10, 10, 10, 10, 1), (10, 10, 10, 10)), ((10, 10, 10, 10, 1, 1), (10, 10, 10, 10)), ((10, 10, 10, 10, 10), (10, 10, 10, 10, 10)), ((10, 10, 10, 10, 10, 1), (10, 10, 10, 10, 10)), ] for input, expected in tests: assert tuple(fslimage.canonicalShape(input)) == expected
def _test_Image_atts(imgtype): """Test that basic Nifti/Image attributes are correct. """ allowedExts = fslimage.ALLOWED_EXTENSIONS fileGroups = fslimage.FILE_GROUPS typeMap = { np.uint8: constants.NIFTI_DT_UINT8, np.int16: constants.NIFTI_DT_INT16, np.int32: constants.NIFTI_DT_INT32, np.float32: constants.NIFTI_DT_FLOAT32, np.float64: constants.NIFTI_DT_FLOAT64 } # (file, dims, pixdims, dtype) dtypes = [np.uint8, np.int16, np.int32, np.float32, np.double] dims = [(1, 1, 1), (10, 1, 1), (1, 10, 1), (1, 1, 10), (10, 10, 1), (10, 1, 10), (1, 10, 10), (10, 10, 10), (1, 1, 1, 1), (10, 1, 1, 1), (1, 10, 1, 1), (1, 1, 10, 1), (10, 10, 1, 1), (10, 10, 1, 5), (10, 1, 10, 5), (1, 10, 10, 5), (10, 10, 10, 5)] pixdims = [(0.5, 0.5, 0.5, 2), (1.0, 1.0, 1.0, 2), (2.0, 2.0, 2.0, 2), (1.0, 5.0, 1.0, 3)] tests = it.product(dims, pixdims, dtypes) tests = list(tests) paths = ['test{:03d}'.format(i) for i in range(len(tests))] with tempdir() as testdir: for path, atts in zip(paths, tests): dims, pixdims, dtype = atts ndims = len(dims) pixdims = pixdims[:ndims] path = op.abspath(op.join(testdir, path)) make_image(path, imgtype, dims, pixdims, dtype) for path, atts in zip(paths, tests): dims, pixdims, dtype = atts expdims = fslimage.canonicalShape(dims) expndims = len(expdims) ndims = len(dims) pixdims = pixdims[:ndims] exppixdims = pixdims[:expndims] path = op.abspath(op.join(testdir, path)) i = fslimage.Image(path) assert not i.iscomplex assert tuple(i.shape) == tuple(expdims) assert tuple(i.data.shape) == tuple(expdims) assert tuple(i.pixdim) == tuple(exppixdims) assert tuple(i.nibImage.shape) == tuple(dims) assert tuple(i.nibImage.header.get_zooms()) == tuple(pixdims) assert i.nvals == 1 assert i.ndim == expndims assert i.dtype == dtype assert i.niftiDataType == typeMap[dtype] assert i.name == op.basename(path) assert i.dataSource == fslpath.addExt(path, allowedExts=allowedExts, mustExist=True, fileGroups=fileGroups) i = None
def __init__(self, image, name=None, loadData=False, dataRange=None, threaded=False): """Create an ``ImageWrapper``. :arg image: A ``nibabel.Nifti1Image`` or ``nibabel.Nifti2Image``. :arg name: A name for this ``ImageWrapper``, solely used for debug log messages. :arg loadData: If ``True``, the image data is loaded into memory. Otherwise it is kept on disk (and data access is performed through the ``nibabel.Nifti1Image.dataobj`` array proxy). :arg dataRange: A tuple containing the initial ``(min, max)`` data range to use. See the :meth:`reset` method for important information about this parameter. :arg threaded: If ``True``, the data range is updated on a :class:`.TaskThread`. Otherwise (the default), the data range is updated directly on reads/writes. """ import fsl.data.image as fslimage self.__image = image self.__name = name self.__taskThread = None # Save the number of 'real' dimensions, # that is the number of dimensions minus # any trailing dimensions of length 1 self.__numRealDims = len(image.shape) for d in reversed(image.shape): if d == 1: self.__numRealDims -= 1 else: break # Degenerate case - less # than three real dimensions if self.__numRealDims < 3: self.__numRealDims = min(3, len(image.shape)) # And save the number of # 'padding' dimensions too. self.__numPadDims = len(image.shape) - self.__numRealDims # Too many shapes! Figure out # what shape we should present # the data as (e.g. at least 3 # dimensions). This is used in # __getitem__ to force the # result to have the correct # dimensionality. self.__canonicalShape = fslimage.canonicalShape(image.shape) # The internal state is stored # in these attributes - they're # initialised in the reset method. self.__range = None self.__coverage = None self.__volRanges = None self.__covered = False self.reset(dataRange) # We keep an internal ref to # the data numpy array if/when # it is loaded in memory self.__data = None if loadData or image.in_memory: self.loadData() if threaded: self.__taskThread = idle.TaskThread() self.__taskThread.daemon = True self.__taskThread.start()