Skip to content
Snippets Groups Projects
Commit 82e3b29c authored by Paul McCarthy's avatar Paul McCarthy
Browse files

fslimage.Image header can now be set via constructor, for images created

from numpy arrays. AtlasPanel now allows showing/hiding of probabilistic
overlays, as well as binary label overlays.
parent a1698720
No related branches found
No related tags found
No related merge requests found
......@@ -90,7 +90,12 @@ class Image(props.HasProperties):
"""
def __init__(self, image, xform=None, name=None, loadData=True):
def __init__(self,
image,
xform=None,
name=None,
header=None,
loadData=True):
"""Initialise an Image object with the given image data or file name.
:arg image: A string containing the name of an image file to load,
......@@ -102,6 +107,11 @@ class Image(props.HasProperties):
:arg name: A name for the image.
:arg header: If not ``None``, assumed to be a
:class:`nibabel.nifti1.Nifti1Header` to be used as the
image header. Not applied to images loaded from file,
or existing :mod:`nibabel` images.
:arg loadData: Defaults to ``True``. If ``False``, the image data is
not loaded - this is useful if you're only interested
in the header data, as the file will be loaded much
......@@ -113,6 +123,9 @@ class Image(props.HasProperties):
self.imageFile = None
self.tempFile = None
if header is not None:
header = header.copy()
# The image parameter may be the name of an image file
if isinstance(image, basestring):
......@@ -136,10 +149,14 @@ class Image(props.HasProperties):
# to 1mm^3 in real world space)
elif isinstance(image, np.ndarray):
if xform is None: xform = np.identity(4)
if xform is None:
if header is None: xform = np.identity(4)
else: xform = header.get_best_affine()
if name is None: name = 'Numpy array'
self.nibImage = nib.nifti1.Nifti1Image(image, xform)
self.nibImage = nib.nifti1.Nifti1Image(image,
xform,
header=header)
self.name = name
# otherwise, we assume that it is a nibabel image
......
......@@ -40,10 +40,10 @@ class CopyImageAction(actions.Action):
if image is None:
return
data = np.copy(image.data)
xform = image.voxToWorldMat
name = '{}_copy'.format(image.name)
copy = fslimage.Image(data, xform, name)
data = np.copy(image.data)
header = image.nibImage.get_header()
name = '{}_copy'.format(image.name)
copy = fslimage.Image(data, name=name, header=header)
# TODO copy display properties
......
......@@ -119,10 +119,10 @@ class AtlasPanel(fslpanel.FSLViewPanel):
log.debug('{}/{} clicked'.format(atlasID, label.name))
if isinstance(atlas, atlases.ProbabilisticAtlas):
pass
self.toggleOverlay(atlasID, labelIndex, False)
elif isinstance(atlas, atlases.LabelAtlas):
self.toggleLabelOverlay(atlasID, labelIndex)
self.toggleOverlay(atlasID, labelIndex, True)
......@@ -146,11 +146,10 @@ class AtlasPanel(fslpanel.FSLViewPanel):
pass
def toggleProbabilisticOverlay(self, atlasID, labelIndex):
pass
def toggleLabelOverlay(self, atlasID, labelIndex):
def toggleOverlay(self, atlasID, labelIndex, label):
"""
"""
desc = self.atlasDescs[atlasID]
overlayName = '{}/{}'.format(atlasID, desc.labels[labelIndex].name)
......@@ -166,26 +165,35 @@ class AtlasPanel(fslpanel.FSLViewPanel):
if atlas is None:
atlas = atlases.loadAtlas(self.atlasDescs[atlasID], True)
if desc.atlasType == 'probabilistic': labelVal = labelIndex + 1
elif desc.atlasType == 'label': labelVal = labelIndex
if label:
if desc.atlasType == 'probabilistic':
labelVal = labelIndex + 1
elif desc.atlasType == 'label':
labelVal = labelIndex
mask = np.zeros(atlas.shape, dtype=np.uint8)
mask[atlas.data == labelIndex] = labelVal
mask = np.zeros(atlas.shape, dtype=np.uint8)
mask[atlas.data == labelIndex] = labelVal
else:
mask = atlas.data[..., labelIndex]
overlay = fslimage.Image(
mask,
atlas.voxToWorldMat,
header=atlas.nibImage.get_header(),
name=overlayName)
overlay.imageType = 'mask'
if label:
overlay.imageType = 'mask'
log.debug('Adding overlay {}'.format(overlayName))
self._imageList.append(overlay)
display = self._displayCtx.getDisplayProperties(overlay)
display.getDisplayOpts().colour = np.random.random(3)
if label:
display.getDisplayOpts().colour = np.random.random(3)
else:
display.getDisplayOpts().cmap = 'hot'
......
......@@ -52,7 +52,7 @@ class VolumeOpts(fsldisplay.DisplayOpts):
"""Image values which map to the minimum and maximum colour map colours."""
clipLow = props.Boolean(default=False)
clipLow = props.Boolean(default=True)
"""If ``True``, don't display voxel values which are lower than
the :attr:`displayRange`.
"""
......
......@@ -260,10 +260,10 @@ class Editor(props.HasProperties):
image = self._imageList[imageIdx]
mask = np.array(self._selection.selection, dtype=np.uint8)
xform = image.voxToWorldMat
name = '{}_mask'.format(image.name)
header = image.nibImage.get_header()
name = '{}_mask'.format(image.name)
roiImage = fslimage.Image(mask, xform, name)
roiImage = fslimage.Image(mask, name=name, header=header)
self._imageList.insert(imageIdx + 1, roiImage)
......@@ -276,8 +276,8 @@ class Editor(props.HasProperties):
roi[self._selection.selection] = image.data[self._selection.selection]
xform = image.voxToWorldMat
name = '{}_roi'.format(image.name)
header = image.nibImage.get_header()
name = '{}_roi'.format(image.name)
roiImage = fslimage.Image(roi, xform, name)
roiImage = fslimage.Image(roi, name=name, header=header)
self._imageList.insert(imageIdx + 1, roiImage)
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