Source code for fsleyes.controls.timeseriescontrolpanel

#
# timeseriescontrolpanel.py - The TimeSeriesControlPanel class.
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides the :class:`TimeSeriesControlPanel` a *FSLeyes
control* which allows the user to configure a :class:`.TimeSeriesPanel`.
"""


import fsleyes_props               as props
import fsl.data.image              as fslimage
import fsl.data.featimage          as fslfeatimage

import fsleyes.tooltips            as fsltooltips
import fsleyes.plotting.timeseries as timeseries
import fsleyes.strings             as strings
from . import plotcontrolpanel     as plotctrl


[docs]class TimeSeriesControlPanel(plotctrl.PlotControlPanel): """The ``TimeSeriesControlPanel`` is a :class:`.PlotContrlPanel` which allows the user to configure a :class:`.TimeSeriesPanel`. It contains controls which are linked to the properties of the ``TimeSeriesPanel``, (which include properties defined on the :class:`.PlotPanel` base class), and the :class:`.DataSeries` class. A ``TimeSeriesControlPanel`` looks something like this: .. image:: images/timeseriescontrolpanel.png :scale: 50% :align: center The settings shown on a ``TimeSeriesControlPanel`` are organised into three or four sections: - The *Time series plot settings* section has controls which are linked to properties of the :class:`.TimeSeriesPanel` class. - The *General plot settings* section has controls which are linked to properties of the :class:`.PlotPanel` base class. - The *Settings for the current time course* section has controls which are linked to properties of the :class:`.DataSeries` class. These properties define how the *current* time course is displayed (see the :class:`.TimeSeriesPanel` class documentation). - The *FEAT plot settings* is only shown if the currently selected overlay is a :class:`.FEATImage`. It has controls which are linked to properties of the :class:`.FEATTimeSeries` class. """
[docs] def __init__(self, *args, **kwargs): """Create a ``TimeSeriesControlPanel``. All arguments are passed through to the :meth:`.PlotControlPanel.__init__` method. """ plotctrl.PlotControlPanel.__init__(self, *args, **kwargs) tsPanel = self.getPlotPanel() tsPanel.addListener('plotMelodicICs', self.name, self.__plotMelodicICsChanged)
[docs] def destroy(self): """Must be called when this ``TimeSeriesControlPanel`` is no longer needed. Removes some property listeners, and calls :meth:`.PlotControlPanel.destroy`. """ psPanel = self.getPlotPanel() psPanel.removeListener('plotMelodicICs', self.name) plotctrl.PlotControlPanel.destroy(self)
[docs] @staticmethod def supportedViews(): """Overrides :meth:`.ControlMixin.supportedViews`. The ``TimeSeriesControlPanel`` is only intended to be added to :class:`.TimeSeriesPanel` views. """ from fsleyes.views.timeseriespanel import TimeSeriesPanel return [TimeSeriesPanel]
[docs] def generateCustomPlotPanelWidgets(self, groupName): """Overrides :meth:`.PlotControlPanel.generateCustomPlotPanelWidgets`. Adds some widgets for controlling some properties of the :class:`.TimeSeriesPanel`. """ widgetList = self.getWidgetList() allWidgets = [] tsPanel = self.getPlotPanel() tsProps = ['plotMode', 'usePixdim', 'plotMelodicICs'] for prop in tsProps: kwargs = {} if prop == 'plotMode': kwargs['labels'] = strings.choices[tsPanel, 'plotMode'] widget = props.makeWidget(widgetList, tsPanel, prop, **kwargs) allWidgets.append(widget) widgetList.AddWidget( widget, displayName=strings.properties[tsPanel, prop], tooltip=fsltooltips.properties[tsPanel, prop], groupName=groupName) return allWidgets
[docs] def generateCustomDataSeriesWidgets(self, ts, groupName): """Overrides :meth:`.PlotControlPanel.generateCustomDataSeriesWidgets`. Adds some widgets to the widget list for certain time series types. """ overlay = ts.overlay if (isinstance(overlay, fslfeatimage.FEATImage) and isinstance(ts, timeseries.FEATTimeSeries) and overlay.hasStats()): return self.__generateFeatWidgets(ts, groupName) elif isinstance(ts, timeseries.ComplexTimeSeries): return self.__generateComplexWidgets(ts, groupName) else: return []
def __generateFeatWidgets(self, ts, groupName): """Called by :meth:`generateCustomDataSeriesWidgets`. Generates widgets for :class:`.FEATTimeSeries` options, and adds them to the widget list. """ overlay = ts.overlay widgetList = self.getWidgetList() allWidgets = [] full = props.makeWidget( widgetList, ts, 'plotFullModelFit') res = props.makeWidget( widgetList, ts, 'plotResiduals') evs = props.makeListWidgets(widgetList, ts, 'plotEVs') pes = props.makeListWidgets(widgetList, ts, 'plotPEFits') copes = props.makeListWidgets(widgetList, ts, 'plotCOPEFits') partial = props.makeWidget( widgetList, ts, 'plotPartial') data = props.makeWidget( widgetList, ts, 'plotData') allWidgets.append(full) allWidgets.append(res) allWidgets.extend(evs) allWidgets.extend(pes) allWidgets.extend(copes) allWidgets.append(partial) allWidgets.append(data) widgetList.AddWidget( data, displayName=strings.properties[ts, 'plotData'], tooltip=fsltooltips.properties[ts, 'plotData'], groupName=groupName) widgetList.AddWidget( full, displayName=strings.properties[ts, 'plotFullModelFit'], tooltip=fsltooltips.properties[ts, 'plotFullModelFit'], groupName=groupName) widgetList.AddWidget( res, displayName=strings.properties[ts, 'plotResiduals'], tooltip=fsltooltips.properties[ts, 'plotResiduals'], groupName=groupName) widgetList.AddWidget( partial, displayName=strings.properties[ts, 'plotPartial'], tooltip=fsltooltips.properties[ts, 'plotPartial'], groupName=groupName) widgetList.AddSpace(groupName=groupName) for i, ev in enumerate(evs): evName = overlay.evNames()[i] widgetList.AddWidget( ev, displayName=strings.properties[ts, 'plotEVs'].format( i + 1, evName), tooltip=fsltooltips.properties[ts, 'plotEVs'], groupName=groupName) widgetList.AddSpace(groupName=groupName) for i, pe in enumerate(pes): evName = overlay.evNames()[i] widgetList.AddWidget( pe, displayName=strings.properties[ts, 'plotPEFits'].format( i + 1, evName), tooltip=fsltooltips.properties[ts, 'plotPEFits'], groupName=groupName) widgetList.AddSpace(groupName=groupName) copeNames = overlay.contrastNames() for i, (cope, name) in enumerate(zip(copes, copeNames)): widgetList.AddWidget( cope, displayName=strings.properties[ts, 'plotCOPEFits'].format( i + 1, name), tooltip=fsltooltips.properties[ts, 'plotCOPEFits'], groupName=groupName) return allWidgets def __generateComplexWidgets(self, ts, groupName): """Called by :meth:`generateCustomDataSeriesWidgets`. Generates widgets for :class:`.ComplexTimeSeries` options, and adds them to the widget list. """ widgetList = self.getWidgetList() allWidgets = [] if isinstance(ts, timeseries.ComplexTimeSeries): for propName in ['plotReal', 'plotImaginary', 'plotMagnitude', 'plotPhase']: widg = props.makeWidget(widgetList, ts, propName) widgetList.AddWidget( widg, displayName=strings.properties[ts, propName], tooltip=fsltooltips.properties[ts, propName], groupName=groupName) allWidgets.append(widg) return allWidgets def __plotMelodicICsChanged(self, *a): """Called when the :attr:`.TimeSeriesPanel.plotMelodicICs` property changes. If the current overlay is a :class:`.MelodicImage`, re-generates the widgets in the *current time course* section, as the :class:`.DataSeries` instance associated with the overlay may have been re-created. """ self.refreshDataSeriesWidgets()