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

Merge branch 'rf/dtype' into 'master'

Rf/dtype

See merge request fsl/fslpy!231
parents 0c8a3325 50b9989a
......@@ -10,12 +10,26 @@ Added
^^^^^
* New :func:`.cifti` module, providing classes and functions for working with
`CIFTI <https://www.nitrc.org/projects/cifti/>`_ data.
* New :func:`.winpath` and :func:`wslpath` functions for working with paths
when using FSL in a Windows Subsystem for Linux (WSL) environment.
* New :func:`.wslcmd` function for generating a path to a FSL command installed
in a WSL environment.
* New :meth:`.Platform.fslwsl` attribute for detecting whether FSL is installed
in a WSL environment.
* New :meth:`.Image.niftiDataType` property.
* The :class:`.FileTree` class has been updated to allow creation of
deep copies via the new :meth:`.FileTree.copy` method.
Changed
^^^^^^^
* :func:`.Image` objects created from ``numpy`` arrays will be NIFTI1 or
NIFTI2, depending on the value of the ``$FSLOUTPUTTYPE`` environment
variable.
Fixed
......
......@@ -98,6 +98,36 @@ NIFTI_UNITS_PPM = 40
NIFTI_UNITS_RADS = 48
# NIFTI datatype codes
NIFTI_DT_NONE = 0
NIFTI_DT_UNKNOWN = 0
NIFTI_DT_BINARY = 1
NIFTI_DT_UNSIGNED_CHAR = 2
NIFTI_DT_SIGNED_SHORT = 4
NIFTI_DT_SIGNED_INT = 8
NIFTI_DT_FLOAT = 16
NIFTI_DT_COMPLEX = 32
NIFTI_DT_DOUBLE = 64
NIFTI_DT_RGB = 128
NIFTI_DT_ALL = 255
NIFTI_DT_UINT8 = 2
NIFTI_DT_INT16 = 4
NIFTI_DT_INT32 = 8
NIFTI_DT_FLOAT32 = 16
NIFTI_DT_COMPLEX64 = 32
NIFTI_DT_FLOAT64 = 64
NIFTI_DT_RGB24 = 128
NIFTI_DT_INT8 = 256
NIFTI_DT_UINT16 = 512
NIFTI_DT_UINT32 = 768
NIFTI_DT_INT64 = 1024
NIFTI_DT_UINT64 = 1280
NIFTI_DT_FLOAT128 = 1536
NIFTI_DT_COMPLEX128 = 1792
NIFTI_DT_COMPLEX256 = 2048
NIFTI_DT_RGBA32 = 2304
# NIFTI file intent codes
NIFTI_INTENT_NONE = 0
NIFTI_INTENT_CORREL = 2
......
......@@ -39,7 +39,6 @@ import json
import string
import logging
import tempfile
import warnings
import six
import numpy as np
......@@ -560,6 +559,11 @@ class Nifti(notifier.Notifier, meta.Meta):
"""Returns the NIFTI intent code of this image. """
return self.header.get('intent_code', constants.NIFTI_INTENT_NONE)
@property
def niftiDataType(self):
"""Returns the NIFTI data type code of this image. """
return self.header.get('datatype', constants.NIFTI_DT_UNKNOWN)
@intent.setter
def intent(self, val):
......@@ -1094,11 +1098,12 @@ class Image(Nifti):
if header is not None: xform = header.get_best_affine()
else: xform = np.identity(4)
# We default to NIFTI1 and not
# NIFTI2, because the rest of
# FSL is not yet NIFTI2 compatible.
# default to NIFTI1 if FSLOUTPUTTYPE
# is not set, just to be safe.
if header is None:
ctr = nib.nifti1.Nifti1Image
outputType = os.environ.get('FSLOUTPUTTYPE', 'NIFTI_GZ')
if 'NIFTI2' in outputType: ctr = nib.Nifti2Image
else: ctr = nib.Nifti1Image
# make sure that the data type is correct,
# in case this header was passed in from
......@@ -1643,9 +1648,14 @@ def defaultExt():
# TODO: Add analyze support.
options = {
'NIFTI' : '.nii',
'NIFTI_PAIR' : '.img',
'NIFTI_GZ' : '.nii.gz',
'NIFTI' : '.nii',
'NIFTI2' : '.nii',
'NIFTI_GZ' : '.nii.gz',
'NIFTI2_GZ' : '.nii.gz',
'NIFTI_PAIR' : '.img',
'NIFTI2_PAIR' : '.img',
'NIFTI_PAIR_GZ' : '.img.gz',
'NIFTI2_PAIR_GZ' : '.img.gz',
}
outputType = os.environ.get('FSLOUTPUTTYPE', 'NIFTI_GZ')
......
......@@ -246,6 +246,11 @@ def _test_Image_atts(imgtype):
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]
......@@ -307,14 +312,15 @@ def _test_Image_atts(imgtype):
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.name == op.basename(path)
assert i.dataSource == fslpath.addExt(path,
allowedExts=allowedExts,
mustExist=True,
fileGroups=fileGroups)
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
......@@ -493,8 +499,9 @@ def test_splitExt():
def test_defaultExt():
fslOutputTypes = ['NIFTI', 'NIFTI_PAIR', 'NIFTI_GZ']
exts = ['.nii', '.img', '.nii.gz']
fslOutputTypes = ['NIFTI', 'NIFTI_PAIR', 'NIFTI_GZ', 'NIFTI_PAIR_GZ',
'NIFTI2', 'NIFTI2_PAIR', 'NIFTI2_GZ', 'NIFTI2_PAIR_GZ']
exts = ['.nii', '.img', '.nii.gz', '.img.gz'] * 2
os.environ.pop('FSLOUTPUTTYPE', None)
assert fslimage.defaultExt() == '.nii.gz'
......@@ -506,6 +513,35 @@ def test_defaultExt():
assert fslimage.defaultExt() == e
def test_defaultImageType():
fslOutputTypes = [None,
'NIFTI', 'NIFTI_PAIR', 'NIFTI_GZ', 'NIFTI_PAIR_GZ',
'NIFTI2', 'NIFTI2_PAIR', 'NIFTI2_GZ', 'NIFTI2_PAIR_GZ']
exts = ['.nii.gz'] + \
['.nii', '.img', '.nii.gz', '.img.gz'] * 2
with tempdir():
for o, e in zip(fslOutputTypes, exts):
if o is None:
os.environ.pop('FSLOUTPUTTYPE', None)
else:
os.environ['FSLOUTPUTTYPE'] = o
if o is None or 'NIFTI2' not in o:
exptype = nib.Nifti1Image
else:
exptype = nib.Nifti2Image
img = fslimage.Image(np.random.randint(1, 10, (30, 30, 30)))
assert type(img.nibImage) == exptype
img.save('image')
assert op.exists('image' + e)
def test_fixExt():
with tempdir():
......
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