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

TimeSeriesPanel now has option to display time series for all overlays.

parent fc20e863
No related branches found
No related tags found
No related merge requests found
......@@ -6,6 +6,8 @@ https://internal.fmrib.ox.ac.uk/i-wiki/Analysis/Todos/FSLView regularly, too.
* Required feature list before next internal release
** Ability to display time series for all overlays in TimeSeriesPanel
** Open new view panel (time series) resets location?
** Iconify/clean up interface
** Tooltips
** Rename to FSLEyes
......@@ -74,7 +76,7 @@ All spinctrls now refresh on focus-lose, or when enter is hit.
* Things to do once the feature list is complete
** Profile actions/settings in canvas settings panel
** Action categories, so they can be grouped in menus
** Combine SliceCanvas offscreen+prerender modes
** Combine SliceCanvas offscreen+prerender modes - apply both simultaneously
** A better way of managing colour maps/luts
** Text annotations for models and labels
** A pre-processor for GL14 shader programs
......@@ -179,6 +181,7 @@ perhaps into a standalone module...
** DONE Graceful handling of bad input filenames
** DONE Aspect ratio on slicecanvas zoom, and panning is broken.
* Little things
** Ability to import/export time series data
** A 'FeatModel' control widget, allowing user to look at design matrix, stats, whatever ..
** A 'MELODICTimeSeries' thingo, just like the FEATTimeSeries - plot component time courses alongside a voxel's time course.
** GLModel - annotate view with model name
......@@ -193,10 +196,6 @@ the vertex data is returned unmodified.
** Make ortho aspect ratio/zoom thing better
** RunWindow should print to stdout
** Startup - ability to set $FSLDIR
** Time Series - option to 'hold' voxel time course
You could have a list panel which lists the image and voxel coordinates of the
time courses that are currently plotted. Allow voxels to be held, and images
to be held.
** Histogram - mouse drag should zoom into plot but not change data range.
** A proper GLMask class - deriving from GLVolume is inefficient
** A top-level class, from which all things inherit, which has a destroy method that must be called when the object is destroy4ed
......@@ -222,7 +221,6 @@ Actually, why not just a nifti header editor? Another idea - interactive
editing of the affine transform - click, drag, scale, rotate, etc. I think
I've had this idea before
** 'Outline' image type
** Make display range limit-edit-widget less crappy.
** Improve colour bar
*** ColourBarCanvas - make it smarter
Display either the cbar for the current image, or cbars for all images.
......@@ -235,8 +233,13 @@ Display either the cbar for the current image, or cbars for all images.
** IN PROGRESS 'Actions'? - Make 'Add File' and 'Add Std' menu items actions.
Need to be able to specify the order that actions appear in the menu - perhaps
just hard code in fsl/fslview/actions/__init__.py
** WONTFIX Make display range limit-edit-widget less crappy.
** WONTFIX Allow display resolution greater than image resolution?
Now that I'm smoothing over voxels (when interpolation is on), I don't think this is necessary
** DONE Time Series - option to 'hold' voxel time course
You could have a list panel which lists the image and voxel coordinates of the
time courses that are currently plotted. Allow voxels to be held, and images
to be held.
** DONE Colour command line (e.g. renderpy background) should be floating point in the range [0, 1]
** DONE Absolute clipping (e.g. clip [-3, 3])
** DONE Add 'load colour map' button to VolumeOpts settings panel. If you do this, you could probably remove the option from the file menu.
......
......@@ -355,6 +355,7 @@ properties = TypeDict({
'TimeSeriesPanel.plotMode' : 'Plotting mode',
'TimeSeriesPanel.usePixdim' : 'Use pixdims',
'TimeSeriesPanel.showCurrent' : 'Plot time series for current voxel',
'TimeSeriesPanel.showAllCurrent' : 'Plot time series for all overlays',
'TimeSeriesPanel.currentColour' : 'Colour for current time course',
'TimeSeriesPanel.currentAlpha' : 'Transparency for current '
'time course',
......
......@@ -29,7 +29,8 @@ class TimeSeriesControlPanel(fslpanel.FSLViewPanel):
tsProps = ['plotMode',
'usePixdim',
'showCurrent']
'showCurrent',
'showAllCurrent']
plotProps = ['xLogScale',
'yLogScale',
'smooth',
......
......@@ -403,9 +403,10 @@ class TimeSeriesPanel(plotpanel.PlotPanel):
"""
usePixdim = props.Boolean(default=False)
showCurrent = props.Boolean(default=True)
plotMode = props.Choice(
usePixdim = props.Boolean(default=False)
showCurrent = props.Boolean(default=True)
showAllCurrent = props.Boolean(default=False)
plotMode = props.Choice(
('normal', 'demean', 'normalise', 'percentChange'),
labels=[strings.choices['TimeSeriesPanel.plotMode.normal'],
strings.choices['TimeSeriesPanel.plotMode.demean'],
......@@ -454,6 +455,7 @@ class TimeSeriesPanel(plotpanel.PlotPanel):
self.addListener('showCurrent', self._name, self.draw)
csc = self.__currentSettingsChanged
self.addListener('showAllCurrent', self._name, csc)
self.addListener('currentColour', self._name, csc)
self.addListener('currentAlpha', self._name, csc)
self.addListener('currentLineWidth', self._name, csc)
......@@ -520,29 +522,17 @@ class TimeSeriesPanel(plotpanel.PlotPanel):
if bind: self.__currentTs.addGlobalListener( self._name, self.draw)
else: self.__currentTs.removeGlobalListener(self._name)
def __calcCurrent(self):
prevTs = self.__currentTs
prevOverlay = self.__currentOverlay
if prevTs is not None:
self.__bindCurrentProps(prevTs, False)
self.__currentTs = None
self.__currentOverlay = None
if len(self._overlayList) == 0:
return
def __getTimeSeriesLocation(self, overlay):
x, y, z = self._displayCtx.location.xyz
overlay = self._displayCtx.getSelectedOverlay()
opts = self._displayCtx.getOpts(overlay)
if not isinstance(overlay, fslimage.Image) or \
not isinstance(opts, fsldisplay.VolumeOpts) or \
not overlay.is4DImage():
return
return None
xform = opts.getTransform('display', 'voxel')
vox = transform.transform([[x, y, z]], xform)[0]
......@@ -554,6 +544,44 @@ class TimeSeriesPanel(plotpanel.PlotPanel):
vox[0] >= overlay.shape[0] or \
vox[1] >= overlay.shape[1] or \
vox[2] >= overlay.shape[2]:
return None
return vox
def __genTimeSeries(self, overlay, vox):
if isinstance(overlay, fslfeatimage.FEATImage):
ts = FEATTimeSeries(self, overlay, vox)
else:
ts = TimeSeries(self, overlay, vox)
ts.colour = self.currentColour
ts.alpha = self.currentAlpha
ts.lineWidth = self.currentLineWidth
ts.lineStyle = self.currentLineStyle
ts.label = None
return ts
def __calcCurrent(self):
prevTs = self.__currentTs
prevOverlay = self.__currentOverlay
if prevTs is not None:
self.__bindCurrentProps(prevTs, False)
self.__currentTs = None
self.__currentOverlay = None
if len(self._overlayList) == 0:
return
overlay = self._displayCtx.getSelectedOverlay()
vox = self.__getTimeSeriesLocation(overlay)
if vox is None:
return
if overlay is prevOverlay:
......@@ -562,17 +590,7 @@ class TimeSeriesPanel(plotpanel.PlotPanel):
prevTs.update(vox)
else:
if isinstance(overlay, fslfeatimage.FEATImage):
ts = FEATTimeSeries(self, overlay, vox)
else:
ts = TimeSeries(self, overlay, vox)
ts.colour = self.currentColour
ts.alpha = self.currentAlpha
ts.lineWidth = self.currentLineWidth
ts.lineStyle = self.currentLineStyle
ts.label = None
ts = self.__genTimeSeries(overlay, vox)
self.__currentTs = ts
self.__currentOverlay = overlay
......@@ -588,13 +606,40 @@ class TimeSeriesPanel(plotpanel.PlotPanel):
self.__calcCurrent()
current = self.__currentTs
if self.showCurrent and \
current is not None:
if isinstance(current, FEATTimeSeries):
extras = current.getModelTimeSeries()
else:
extras = [current]
if self.showCurrent:
extras = []
currOverlay = None
if current is not None:
if isinstance(current, FEATTimeSeries):
extras = current.getModelTimeSeries()
else:
extras = [current]
currOverlay = current.overlay
if self.showAllCurrent:
overlays = [o for o in self._overlayList
if o is not currOverlay]
locs = map(self.__getTimeSeriesLocation, overlays)
locovl = filter(lambda (l, o): l is not None,
zip(locs, overlays))
if len(locovl) > 0:
locs, overlays = zip(*locovl)
tss = map(self.__genTimeSeries, overlays, locs)
extras.extend([ts for ts in tss if ts is not None])
for ts in tss:
ts.alpha = 0.5
ts.lineWidth = 0.5
if isinstance(ts, FEATTimeSeries):
extras.extend(ts.getModelTimeSeries())
self.drawDataSeries(extras)
else:
......
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