diff --git a/fsl/data/strings.py b/fsl/data/strings.py index df5cb2f08463ccdba986ae787d588b2809d79753..a825943f010892ef3922b4e114f75d1caa3126c5 100644 --- a/fsl/data/strings.py +++ b/fsl/data/strings.py @@ -195,11 +195,12 @@ titles = TypeDict({ actions = TypeDict({ - 'OpenFileAction' : 'Add overlay file', - 'OpenStandardAction' : 'Add standard', - 'CopyOverlayAction' : 'Copy overlay', - 'SaveOverlayAction' : 'Save overlay', - 'LoadColourMapAction' : 'Load custom colour map', + 'OpenFileAction' : 'Add overlay file', + 'OpenStandardAction' : 'Add standard', + 'CopyOverlayAction' : 'Copy overlay', + 'SaveOverlayAction' : 'Save overlay', + 'LoadColourMapAction' : 'Load custom colour map', + 'SavePerspectiveAction' : 'Save current perspective', 'FSLEyesFrame.closeViewPanel' : 'Close', @@ -779,3 +780,8 @@ melodic = TypeDict({ 'tr' : 'TR time', 'report' : 'Link to report', }) + +perspectives = { + 'melview' : 'Melodic mode', + 'feat' : 'FEAT mode', +} diff --git a/fsl/fsleyes/__init__.py b/fsl/fsleyes/__init__.py index 0e47190c4b52aaf72c6ddc7436b5c84555b34ba9..cd64937778004a092c32bc6119598324e0e8d855 100644 --- a/fsl/fsleyes/__init__.py +++ b/fsl/fsleyes/__init__.py @@ -26,8 +26,10 @@ Amongst other things, *FSLeyes* provides the following features: - Lightbox view (:mod:`.lightboxpanel`) - Time series plotting (:mod:`.timeseriespanel`) - Histogram plotting (:mod:`.histogrampanel`) + - Power spectrum plotting (:mod:`.powerspectrumpanel`) - FSL atlas explorer (:mod:`.atlaspanel`) - FEAT cluster results explorer (:mod:`.clusterpanel`) + - Melodic component classification (:mod:`.melodicclassificationpanel`) - NIFTI1 image editing (:mod:`.editor`) - A comprehensive command line interface (:mod:`.fsleyes_parseargs`) @@ -180,12 +182,13 @@ The rest of *FSLeyes* is organised into the following sub-packages: Some other miscellaneous modules are contained in the ``fsleyes`` package: .. autosummary:: + ~fsl.fsleyes.frame + ~fsl.fsleyes.panel + ~fsl.fsleyes.toolbar ~fsl.fsleyes.tooltips + ~fsl.fsleyes.perspectives ~fsl.fsleyes.icons ~fsl.fsleyes.colourmaps + ~fsl.fsleyes.plotting ~fsl.fsleyes.splash - ~fsl.fsleyes.frame - ~fsl.fsleyes.panel - ~fsl.fsleyes.toolbar - """ diff --git a/fsl/fsleyes/actions/copyoverlay.py b/fsl/fsleyes/actions/copyoverlay.py index 6adc966d9283f2ca6a6a3e0a488a5a4ab5dcfea0..7c78fb11dfc7667d181ff480db57d737b981ba5b 100644 --- a/fsl/fsleyes/actions/copyoverlay.py +++ b/fsl/fsleyes/actions/copyoverlay.py @@ -8,7 +8,6 @@ which creates a copy of the currently selected overlay. """ -import logging import numpy as np @@ -16,9 +15,6 @@ import fsl.fsleyes.actions as actions import fsl.data.image as fslimage -log = logging.getLogger(__name__) - - class CopyOverlayAction(actions.Action): """The ``CopyOverlayAction`` does as its name suggests - it creates a copy of the currently selected overlay. diff --git a/fsl/fsleyes/actions/loadperspective.py b/fsl/fsleyes/actions/loadperspective.py new file mode 100644 index 0000000000000000000000000000000000000000..ee7e37fcfc8ab68f8ea71d68883c29a188eb8647 --- /dev/null +++ b/fsl/fsleyes/actions/loadperspective.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# +# loadperspective.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# +""" +""" + + +import fsl.fsleyes.actions as actions +import fsl.fsleyes.perspectives as perspectives + + +class LoadPerspectiveAction(actions.Action): + """ + """ + + def __init__(self, frame, perspective): + """ + """ + + self.__frame = frame + self.__perspective = perspective + + actions.Action.__init__(self, self.__loadPerspective) + + + def __loadPerspective(self): + """ + """ + perspectives.loadPerspective(self.__frame, self.__perspective) diff --git a/fsl/fsleyes/actions/openfile.py b/fsl/fsleyes/actions/openfile.py index d051475dd3cf382f46ba9eb7567ce865a79ba2ae..7e0e127c57b08a17c3e3ed10990560c15edddbe3 100644 --- a/fsl/fsleyes/actions/openfile.py +++ b/fsl/fsleyes/actions/openfile.py @@ -9,14 +9,9 @@ load overlay files into the :class:`.OverlayList`. """ -import logging - import fsl.fsleyes.actions as actions -log = logging.getLogger(__name__) - - class OpenFileAction(actions.Action): """The ``OpenFileAction`` allows the user to add files to the :class:`.OverlayList`. This functionality is provided by the diff --git a/fsl/fsleyes/actions/openstandard.py b/fsl/fsleyes/actions/openstandard.py index 0c059665a31a5eabe76ff9a720aa5aa2304a07c8..3603264c273628c884f028d110045e44ddcf9440 100644 --- a/fsl/fsleyes/actions/openstandard.py +++ b/fsl/fsleyes/actions/openstandard.py @@ -13,14 +13,9 @@ to load in standard space images from the ``$FSLDIR/data/standard/`` directory. import os import os.path as op -import logging - import fsl.fsleyes.actions as actions -log = logging.getLogger(__name__) - - class OpenStandardAction(actions.Action): """The ``OpenStandardAction`` prompts the user to open one or more overlays, using ``$FSLDIR/data/standard/`` as the default directory. diff --git a/fsl/fsleyes/actions/saveoverlay.py b/fsl/fsleyes/actions/saveoverlay.py index 2538c007c66650fad4b01735bfb51e1d7b7062be..639fb2f0fe85c106485936d5b5edb4edfc5c0cac 100644 --- a/fsl/fsleyes/actions/saveoverlay.py +++ b/fsl/fsleyes/actions/saveoverlay.py @@ -9,15 +9,10 @@ to save the currently selected overlay. """ -import logging - import fsl.data.image as fslimage import fsl.fsleyes.actions as actions -log = logging.getLogger(__name__) - - class SaveOverlayAction(actions.Action): """The ``SaveOverlayAction`` allows the user to save the currently selected overlay, if it has been edited, or only exists in memory. diff --git a/fsl/fsleyes/actions/saveperspective.py b/fsl/fsleyes/actions/saveperspective.py new file mode 100644 index 0000000000000000000000000000000000000000..5c3b8de19a527c5fbb25378e613190fbddae51d1 --- /dev/null +++ b/fsl/fsleyes/actions/saveperspective.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# +# saveperspective.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# +""" +""" + + +import fsl.fsleyes.actions as actions +import fsl.fsleyes.perspectives as perspectives + + +class SavePerspectiveAction(actions.Action): + """ + """ + + def __init__(self, frame): + """ + """ + + self.__frame = frame + + actions.Action.__init__(self, self.__savePerspective) + + + def __savePerspective(self): + """ + """ + + # TODO prompt for name + name = 'blah' + + perspectives.savePerspective(self.__frame, name) diff --git a/fsl/fsleyes/frame.py b/fsl/fsleyes/frame.py index c6f55f9027317f45bba7c6ac8c7f9171eca96f29..6f3c2b146eb35f76557b1b97f9baa78c0f8a67f2 100644 --- a/fsl/fsleyes/frame.py +++ b/fsl/fsleyes/frame.py @@ -20,10 +20,14 @@ import fsl.utils.settings as fslsettings import views import actions -import actions.copyoverlay as copyoverlay -import actions.openfile as openfile -import actions.openstandard as openstandard -import actions.saveoverlay as saveoverlay +import actions.copyoverlay as copyoverlay +import actions.openfile as openfile +import actions.openstandard as openstandard +import actions.saveoverlay as saveoverlay +import actions.loadperspective as loadperspective +import actions.saveperspective as saveperspective +import perspectives + import displaycontext @@ -551,10 +555,11 @@ class FSLEyesFrame(wx.Frame): menuBar = wx.MenuBar() self.SetMenuBar(menuBar) - fileMenu = wx.Menu() - viewMenu = wx.Menu() - settingsMenu = wx.Menu() - + fileMenu = wx.Menu() + viewMenu = wx.Menu() + perspectiveMenu = wx.Menu() + settingsMenu = wx.Menu() + menuBar.Append(fileMenu, 'File') menuBar.Append(viewMenu, 'View') menuBar.Append(settingsMenu, 'Settings') @@ -563,21 +568,43 @@ class FSLEyesFrame(wx.Frame): self.__viewMenu = viewMenu self.__settingsMenu = settingsMenu - viewPanels = views .listViewPanels() - actionz = [openfile .OpenFileAction, - openstandard.OpenStandardAction, - copyoverlay .CopyOverlayAction, - saveoverlay .SaveOverlayAction] - + # Global actions + actionz = [openfile .OpenFileAction, + openstandard.OpenStandardAction, + copyoverlay .CopyOverlayAction, + saveoverlay .SaveOverlayAction] + for action in actionz: - menuItem = fileMenu.Append(wx.ID_ANY, strings.actions[action]) - + menuItem = fileMenu.Append(wx.ID_ANY, strings.actions[action]) actionObj = action(self.__overlayList, self.__displayCtx) actionObj.bindToWidget(self, wx.EVT_MENU, menuItem) + # Shortcuts to open a new view panel + viewPanels = [views.OrthoPanel, + views.LightBoxPanel, + views.TimeSeriesPanel, + views.PowerSpectrumPanel, + views.HistogramPanel] + for viewPanel in viewPanels: viewAction = viewMenu.Append(wx.ID_ANY, strings.titles[viewPanel]) self.Bind(wx.EVT_MENU, lambda ev, vp=viewPanel: self.addViewPanel(vp), viewAction) + + # Perspectives + viewMenu.AppendSubMenu(perspectiveMenu, 'Perspectives') + for persp in perspectives.getAllPerspectives(): + + menuItem = perspectiveMenu.Append(wx.ID_ANY, + strings.perspectives[persp]) + actionObj = loadperspective.LoadPerspectiveAction(self, persp) + actionObj.bindToWidget(self, wx.EVT_MENU, menuItem) + + # Save perspective + savePerspAction = saveperspective.SavePerspectiveAction(self) + savePerspMenuItem = perspectiveMenu.Append( + wx.ID_ANY, strings.actions[savePerspAction]) + + savePerspAction.bindToWidget(self, wx.EVT_MENU, savePerspMenuItem) diff --git a/fsl/fsleyes/perspectives.py b/fsl/fsleyes/perspectives.py new file mode 100644 index 0000000000000000000000000000000000000000..577eb314e8a44c4c3070570c66667f9cfa5d4da5 --- /dev/null +++ b/fsl/fsleyes/perspectives.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# perspectives.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +import logging + + +log = logging.getLogger(__name__) + + +def getAllPerspectives(): + return ['melview', 'feat'] + + +def loadPerspective(frame, name): + log.debug('Loading perspective {}'.format(name)) + + +def savePerspective(frame, name): + log.debug('Saving current perspective with name {}'.format(name)) + + + +def serialisePerspective(frame): + log.debug('Serialising current perspective') + + +class Perspective(object): + + # Views + # + # View layout + # + # For each view: + # - Controls + # - Control layout + pass diff --git a/fsl/fsleyes/platform.py b/fsl/fsleyes/platform.py new file mode 100644 index 0000000000000000000000000000000000000000..9575f46e2c79d9783d2fadce441caee1e64751b7 --- /dev/null +++ b/fsl/fsleyes/platform.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# +# platform.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +haveGui = False +wxFlavour = None +wxPlatform = None + + +WX_PYTHON = 1 +WX_PHOENIX = 2 + +WX_MAC = 1 +WX_GTK = 2 + + +try: + import wx + haveGui = True + +except ImportError: + haveGui = False + + +if 'phoenix' in wx.PlatformInformation: wxFlavour = WX_PHOENIX +else: wxFlavour = WX_PYTHON + + +if 'MAC' in wx.Platform: wxPlatform = WX_MAC +elif 'GTK' in wx.Platform: wxPlatform = WX_GTK diff --git a/fsl/fsleyes/views/__init__.py b/fsl/fsleyes/views/__init__.py index 3d472c5d30d8e56590f1c7ab20763dfd6ad14d3e..0b457ffb612284d2fd007229e24ce6ef538f515f 100644 --- a/fsl/fsleyes/views/__init__.py +++ b/fsl/fsleyes/views/__init__.py @@ -12,9 +12,7 @@ the :mod:`~fsl.fsleyes` package documentation. It contains a collection of views. -A package-level convenience function, :func:`listViewPanels`, is provided to -allow dynamic lookup of all :class:`.ViewPanel` sub-classes. The following -:class:`.ViewPanel` sub-classes currently exist: +The following :class:`.ViewPanel` sub-classes currently exist: .. autosummary:: :nosignatures: @@ -51,24 +49,3 @@ LightBoxPanel = lightboxpanel .LightBoxPanel TimeSeriesPanel = timeseriespanel .TimeSeriesPanel PowerSpectrumPanel = powerspectrumpanel.PowerSpectrumPanel HistogramPanel = histogrampanel .HistogramPanel - - -def listViewPanels(): - """Convenience function which returns a list containing all - :class:`.ViewPanel` sub-classes in the ``views`` package. - """ - - atts = globals() - - viewPanels = [] - - for name, val in atts.items(): - - if not isinstance(val, type): continue - if val == FSLEyesPanel: continue - - if issubclass(val, FSLEyesPanel) and \ - val not in (CanvasPanel, ViewPanel, PlotPanel): - viewPanels.append(val) - - return viewPanels