Source code for fsleyes.actions.addroihistogram

#
# addroihistogram.py - The AddROIHistogramAction class.
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides the :class:`AddROIHistogramAction` class, an
action used by the :class:`.HistogramPanel`.
"""


import          wx
import numpy as np

import fsl.data.image                   as fslimage

import fsleyes.strings                  as strings
import fsleyes.plotting.dataseries      as dataseries
import fsleyes.plotting.histogramseries as histogramseries

from . import                         base
from . import                         addmaskdataseries


[docs]class AddROIHistogramAction(base.Action): """The ``AddROIHistogramAction`` class is used by the :class:`.HistogramPanel`. It performs a very similar task to the :class:`.AddMaskDataSeriesAction` - the user selects a binary mask, the data within the base image is extracted for that mask, and the histogram of that data is added to the plot. """
[docs] def __init__(self, overlayList, displayCtx, plotPanel): """Create an ``AddROIHistogramAction``. :arg overlayList: The :class:`.OverlayList`. :arg displayCtx: The :class:`.DisplayContext`. :arg plotPanel: The :class:`.HistogramPanel`. """ base.Action.__init__( self, overlayList, displayCtx, self.__addROIHistogram) self.__plotPanel = plotPanel self.__name = '{}_{}'.format(type(self).__name__, id(self)) self.__roiOptions = [] overlayList.addListener('overlays', self.__name, self.__overlayListChanged) displayCtx .addListener('selectedOverlay', self.__name, self.__overlayListChanged) self.__overlayListChanged()
[docs] def destroy(self): """Must be called when this ``AddROIHistogramAction`` is no longer in use. """ self.overlayList.removeListener('overlays', self.__name) self.displayCtx .removeListener('selectedOverlay', self.__name) self.__plotPanel = None self.__roiOptions = None base.Action.destroy(self)
def __overlayListChanged(self, *a): """Called when the :class:`.OverlayList` or the :attr:`.DisplayContext.selectedOverlay` changes. Updates a list of valid mask images for the currently selected overlay. """ overlay = self.displayCtx.getSelectedOverlay() if (len(self.overlayList) == 0 or (not isinstance(overlay, fslimage.Image))): self.enabled = False return self.__roiOptions = [o for o in self.overlayList if isinstance(o, fslimage.Image) and o is not overlay and o.sameSpace(overlay)] self.enabled = len(self.__roiOptions) > 0 def __addROIHistogram(self): """Prompts the user to select an ROI mask, calculates the histogram of that mask on the currently selected overlay, and adds the result to the ``HistogramPanel``. """ overlay = self.displayCtx.getSelectedOverlay() opts = self.displayCtx.getOpts(overlay) roiOptions = self.__roiOptions frame = wx.GetApp().GetTopWindow() msg = strings.messages[self, 'selectMask'].format(overlay.name) title = strings.titles[ self, 'selectMask'].format(overlay.name) dlg = addmaskdataseries.MaskDialog( frame, [o.name for o in roiOptions], title=title, message=msg, checkbox=False) if dlg.ShowModal() != wx.ID_OK: return maskimg = roiOptions[dlg.GetChoice()] mask = maskimg[:] > 0 if overlay.ndim > 3: data = overlay[opts.index()][mask] else: data = overlay[mask] count = self.__plotPanel.histType == 'count' drange = (np.nanmin(data), np.nanmax(data)) nbins = histogramseries.autoBin(data, drange) xdata, ydata, _ = histogramseries.histogram(data, nbins, drange, drange, includeOutliers=False, count=count) ds = dataseries.DataSeries(overlay, self.overlayList, self.displayCtx, self.__plotPanel) ds.colour = self.__plotPanel.getOverlayPlotColour(overlay) ds.lineStyle = self.__plotPanel.getOverlayPlotStyle(overlay) ds.lineWidth = 2 ds.alpha = 1 ds.label = '{} [mask: {}]'.format(overlay.name, maskimg.name) # We have to run the data through # prepareDataSeries to preprocess # (e.g. smooth) it ds.setData(xdata, ydata) ds.setData(*self.__plotPanel.prepareDataSeries(ds)) self.__plotPanel.dataSeries.append(ds)