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

Quick rework of TimeSeriesPanel to handle non-volumetric overlays. Will

be refactoring TimeSeriesPanel soon ...
parent 56fa8d1e
No related branches found
No related tags found
No related merge requests found
......@@ -56,6 +56,11 @@ messages = TypeDict({
'this command: \n{}',
'HistogramPanel.noData' : 'Selected overlay has no data',
'TimeSeriesPanel.noData' : 'Selected overlay has no data',
'TimeSeriesPanel.not4D' : 'Selected overlay is '
'not four dimensional',
'TimeSeriesPanel.outOfBounds' : 'Selected overlay has no data '
'at the current coordinates',
})
......
......@@ -160,7 +160,7 @@ class HistogramPanel(plotpanel.PlotPanel):
overlay = self._displayCtx.getSelectedOverlay()
if not isinstance(overlay, fslimage.Image):
self._displayMessage(strings.messages[self, 'noData'])
self.message(strings.messages[self, 'noData'])
return
minval = float(overlay.data.min())
......@@ -212,18 +212,6 @@ class HistogramPanel(plotpanel.PlotPanel):
self.dataRange.x = newRange
def _displayMessage(self, msg):
axis = self.getAxis()
axis.clear()
axis.set_xlim((0.0, 1.0))
axis.set_ylim((0.0, 1.0))
axis.text(0.5, 0.5, msg, ha='center', va='center')
self.getCanvas().draw()
self.Refresh()
def _drawPlot(self, *a):
overlay = self._displayCtx.getSelectedOverlay()
......
......@@ -93,9 +93,6 @@ class LightBoxPanel(canvaspanel.CanvasPanel):
self._displayCtx .addListener('selectedOverlay',
self._name,
self._selectedOverlayChanged)
self._displayCtx .addListener('overlayOrder',
self._name,
self._selectedOverlayChanged)
self._overlayList.addListener('overlays',
self._name,
self._selectedOverlayChanged)
......
......@@ -68,3 +68,15 @@ class PlotPanel(viewpanel.ViewPanel):
def screenshot(self, *a):
pass
def message(self, msg):
axis = self.getAxis()
axis.clear()
axis.set_xlim((0.0, 1.0))
axis.set_ylim((0.0, 1.0))
axis.text(0.5, 0.5, msg, ha='center', va='center')
self.getCanvas().draw()
self.Refresh()
......@@ -13,13 +13,19 @@ of overlay objects stored in an :class:`.OverlayList`.
"""
import logging
import numpy as np
import plotpanel
import fsl.data.image as fslimage
import fsl.data.strings as strings
import fsl.fslview.displaycontext as fsldisplay
import fsl.utils.transform as transform
log = logging.getLogger(__name__)
import numpy as np
import plotpanel
import fsl.data.image as fslimage
import fsl.utils.transform as transform
# TODO
# - Whack a scrollbar in there, to allow
......@@ -58,98 +64,99 @@ class TimeSeriesPanel(plotpanel.PlotPanel):
self._overlayList.addListener(
'overlays',
self._name,
self._locationChanged)
self._selectedOverlayChanged)
self._displayCtx.addListener(
'location',
'selectedOverlay',
self._name,
self._locationChanged)
self._selectedOverlayChanged)
self._displayCtx.addListener(
'volume',
'location',
self._name,
self._locationChanged)
self._locationChanged)
self.Layout()
self._selectedOverlayChanged()
def destroy(self):
plotpanel.PlotPanel.destroy(self)
self._overlayList.removeListener('overlays', self._name)
self._displayCtx .removeListener('location', self._name)
self._displayCtx .removeListener('volume', self._name)
def _locationChanged(self, *a):
self.getAxis().clear()
if len(self._overlayList) == 0:
return
self._overlayList.removeListener('overlays', self._name)
self._displayCtx .removeListener('selectedOverlay', self._name)
self._displayCtx .removeListener('location', self._name)
self._drawPlot()
for ovl in self._overlayList:
opts = self._displayCtx.getOpts(ovl)
if isinstance(opts, fsldisplay.ImageOpts):
opts.removeListener('volume', self._name)
def _drawPlot(self):
axis = self.getAxis()
canvas = self.getCanvas()
x, y, z = self._displayCtx.location.xyz
vol = self._displayCtx.volume
def _selectedOverlayChanged(self, *a):
mins = []
maxs = []
vols = []
overlay = self._displayCtx.getSelectedOverlay()
for overlay in self._overlayList:
for ovl in self._overlayList:
if not isinstance(overlay, fslimage.Image):
log.warn('{}: Non-volumetric overlay types '
'not supported yet'.format(overlay))
if not isinstance(ovl, fslimage.Image):
continue
display = self._displayCtx.getDisplay(overlay)
xform = display.getTransform('display', 'voxel')
ix, iy, iz = transform.transform([[x, y, z]], xform)[0]
opts = self._displayCtx.getOpts(ovl)
ix = round(ix)
iy = round(iy)
iz = round(iz)
if ovl is overlay:
opts.addListener('volume',
self._name,
self._locationChanged,
overwrite=True)
else:
opts.removeListener('volume', self._name)
minmaxvol = self._drawPlotOneOverlay(overlay, ix, iy, iz)
if minmaxvol is not None:
mins.append(minmaxvol[0])
maxs.append(minmaxvol[1])
vols.append(minmaxvol[2])
self._locationChanged()
def _locationChanged(self, *a):
self.getAxis().clear()
if len(self._overlayList) == 0:
self.getCanvas().draw()
self.Refresh()
else:
self._drawPlot()
axis.axvline(vol, c='#000080', lw=2, alpha=0.4)
if len(mins) > 0:
def _drawPlot(self):
xmin = 0
xmax = max(vols) - 1
ymin = min(mins)
ymax = max(maxs)
axis = self.getAxis()
canvas = self.getCanvas()
x, y, z = self._displayCtx.location.xyz
overlay = self._displayCtx.getSelectedOverlay()
xlen = xmax - xmin
ylen = ymax - ymin
if not isinstance(overlay, fslimage.Image):
self.message(strings.messages[self, 'noData'])
axis.grid(True)
axis.set_xlim((xmin - xlen * 0.05, xmax + xlen * 0.05))
axis.set_ylim((ymin - ylen * 0.05, ymax + ylen * 0.05))
elif not overlay.is4DImage():
self.message(strings.messages[self, 'not4D'])
if ymin != ymax: yticks = np.linspace(ymin, ymax, 5)
else: yticks = [ymin]
else:
opts = self._displayCtx.getOpts(overlay)
xform = opts.getTransform('display', 'voxel')
axis.set_yticks(yticks)
vox = transform.transform([[x, y, z]], xform)[0]
vox = np.floor(vox + 0.5)
for tick in axis.yaxis.get_major_ticks():
tick.set_pad(-15)
tick.label1.set_horizontalalignment('left')
if vox[0] < 0 or \
vox[1] < 0 or \
vox[2] < 0 or \
vox[0] >= overlay.shape[0] or \
vox[1] >= overlay.shape[1] or \
vox[2] >= overlay.shape[2]:
for tick in axis.xaxis.get_major_ticks():
tick.set_pad(-20)
self.message(strings.messages[self, 'outOfBounds'])
else:
self._drawPlotOneOverlay(overlay, *vox)
axis.axvline(opts.volume, c='#000080', lw=2, alpha=0.4)
canvas.draw()
self.Refresh()
......@@ -174,8 +181,15 @@ class TimeSeriesPanel(plotpanel.PlotPanel):
def _onPlotMouseDown(self, ev):
if ev.inaxes != self.getAxis(): return
overlay = self._displayCtx.getSelectedOverlay()
if not isinstance(overlay, fslimage.Image) or not overlay.is4DImage():
return
self._mouseDown = True
self._displayCtx.volume = np.floor(ev.xdata)
opts = self._displayCtx.getOpts(overlay)
opts.volume = np.floor(ev.xdata)
def _onPlotMouseUp(self, ev):
......@@ -185,4 +199,12 @@ class TimeSeriesPanel(plotpanel.PlotPanel):
def _onPlotMouseMove(self, ev):
if not self._mouseDown: return
if ev.inaxes != self.getAxis(): return
self._displayCtx.volume = np.floor(ev.xdata)
overlay = self._displayCtx.getSelectedOverlay()
if not isinstance(overlay, fslimage.Image) or not overlay.is4DImage():
return
opts = self._displayCtx.getOpts(overlay)
opts.volume = np.floor(ev.xdata)
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