Source code for nanslice.layer

#!/usr/bin/env python
"""layer.py

Contains the :py:class:`~nanslice.layer.Layer` class and the :py:func:`~nanslice.layer.blend_layers`
function.
"""
from numpy import nanpercentile, ma
from nibabel import load
from . import slice_func
from .box import Box
from .util import ensure_image, check_path

[docs]class Layer: """ The Layer class Each layer consists of a base MR image, with optional mask and alpha (transparency) images and their associated parameters (colormap, limits, scales etc.) Constructor parameters: - image -- The image contained in this layer. Can be either a string/path to an image file or an nibabel image - scale -- A scaling factor to multiply all voxels in the image by - volume -- If reading a 4D file, specify which volume to use - interp_order -- Interpolation order. 1 is linear interpolation - cmap -- The colormap to apply to the Layer. Any valid matplotlib colormap - clim -- The limits (min, max) values to use for the colormap - label -- The label for this layer (used for colorbars) - mask -- A mask image to use with this layer - mask_threshold -- Apply a threshold (lower) to the mask - alpha -- An alpha (transparency) image to use with this layer - alpha_lim -- Specify the limits/window for the alpha image - alpha_scale -- Scaling factor for the alpha image - alpha_label -- Label for the alpha axis on alphabars """ def __init__(self, image, scale=1.0, volume=0, interp_order=1, cmap=None, clim=None, label='', mask=None, mask_threshold=0, alpha=None, alpha_lim=None, alpha_scale=1.0, alpha_label=''): self.image = ensure_image(image) self.scale = scale self.interp_order = interp_order self.volume = volume self.label = label self.mask_image = ensure_image(mask) self.mask_threshold = mask_threshold if self.mask_image: self.bbox = Box.fromMask(self.mask_image) else: self.bbox = Box.fromImage(self.image) if cmap: self.cmap = cmap else: self.cmap = 'gist_gray' if clim: self.clim = clim else: if len(self.image.shape) == 4: imdata = self.image.dataobj[:,:,:,self.volume].squeeze() else: imdata = self.image.dataobj if self.mask_image: imdata = ma.masked_where(self.mask_image.get_data() > 0, imdata).compressed() self.clim = nanpercentile(imdata, (2, 98)) if check_path(alpha): self.alpha_image = load(str(alpha)) if alpha_lim: self.alpha_lim = alpha_lim else: self.alpha_lim = nanpercentile(self.alpha_image.get_data(), (2, 98)) elif alpha: self.alpha_image = np.ones_like(self.image) * alpha else: self.alpha_image = None self.alpha_label = alpha_label self.alpha_scale = alpha_scale
[docs] def get_slice(self, slicer): """ Returns a slice through the base image Parameters: - slicer -- The :py:class:`~nanslice.slicer.Slicer` object to slice this layer with """ return slicer.sample(self.image, self.interp_order, self.scale, self.volume)
[docs] def get_color(self, slicer): """ Returns a colorized slice through the base image contained in the Layer Parameters: - slicer -- The :py:class:`~nanslice.slicer.Slicer` object to slice this layer with """ return slice_func.colorize(self.get_slice(slicer), self.cmap, self.clim)
[docs] def get_mask(self, slicer): if self.mask_image: mask_slc = slicer.sample(self.mask_image, 0) > self.mask_threshold elif self.mask_threshold: mask_slc = slicer.sample(self.image, self.interp_order, self.scale, self.volume) > self.mask_threshold else: return None return mask_slc
[docs] def get_alpha(self, slicer): """ Returns the alpha (transparency) slice for this Layer Parameters: - slicer -- The :py:class:`~nanslice.slicer.Slicer` object to slice this layer with """ if self.alpha_image: alpha_slice = slicer.sample(self.alpha_image, self.interp_order, self.alpha_scale) alpha_slice = slice_func.scale_clip(alpha_slice, self.alpha_lim) return alpha_slice else: return None
[docs] def plot(self, slicer, axes): """ Plot a Layer into a Matplotlib axes using the provided Slicer Parameters: - slicer -- The :py:class:`~nanslice.slicer.Slicer` object to slice this layer with - axes -- A matplotlib axes object """ slc = self.get_color(slicer) cax = axes.imshow(slc, origin='lower', extent=slicer.extent, interpolation='nearest') axes.axis('off') return cax
[docs]def blend_layers(layers, slicer): """ Blends together a set of overlays using their alpha information Parameters: - layers -- An iterable (e.g. list/tuple) of :py:class:`Layer` objects - slicer -- The :py:class:`~nanslice.slicer.Slicer` object to slice the layers with """ slc = slice_func.mask(layers[0].get_color(slicer), layers[0].get_mask(slicer)) for next_layer in layers[1:]: next_slc = next_layer.get_color(slicer) if next_layer.alpha_image: next_alpha = next_layer.get_alpha(slicer) slc = slice_func.blend(slc, next_slc, next_alpha) else: slc = slice_func.mask(next_slc, next_layer.get_mask(slicer), slc) return slc