Source code for fsleyes.actions.reloadoverlay

#
# reloadoverlay.py - The ReloadOverlayAction class.
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides the :class:`ReloadOverlayAction`, a global action
which reloads the currently selected overlay from disk.
"""


import logging
import os.path as op



import fsl.data.image               as fslimage
import fsleyes_widgets.utils.status as status
import fsleyes_props                as props
from . import                          base
from . import                          removeoverlay


log = logging.getLogger(__name__)


[docs]class ReloadOverlayAction(base.Action): """The ``ReloadOverlayAction`` reloads the currently selected overlay from disk. Currently only :class:`.Image` overlays are supported. """
[docs] def __init__(self, overlayList, displayCtx, frame): """Create a ``ReloadOverlayAction``. :arg overlayList: The :class:`.OverlayList`. :arg displayCtx: The :class:`.DisplayContext`. :arg frame: The :class:`.FSLeyesFrame`. """ base.Action.__init__( self, overlayList, displayCtx, self.__reloadOverlay) self.__frame = frame self.__name = '{}_{}'.format(type(self).__name__, id(self)) overlayList.addListener('overlays', self.__name, self.__selectedOverlayChanged) displayCtx .addListener('selectedOverlay', self.__name, self.__selectedOverlayChanged) self.__selectedOverlayChanged()
[docs] def destroy(self): """Must be called when this ``ReloadOverlayAction`` is no longer required. Removes some property listeners, and calls :meth:`.Action.destroy`. """ self.overlayList.removeListener('overlays', self.__name) self.displayCtx .removeListener('selectedOverlay', self.__name) base.Action.destroy(self)
def __selectedOverlayChanged(self, *a): """Called when the currently selected overlay changes. Enables/disables this ``Action`` depending on the type of the newly selected overlay. """ ovl = self.displayCtx.getSelectedOverlay() self.enabled = (ovl is not None) and \ (ovl.dataSource is not None) and \ type(ovl) == fslimage.Image and \ op.exists(ovl.dataSource) def __reloadOverlay(self): """Reloads the currently selected overlay from disk. """ ovl = self.displayCtx.getSelectedOverlay() if ovl is None or type(ovl) != fslimage.Image: raise RuntimeError('Only Image overlays can be reloaded') index = self.overlayList.index(ovl) order = self.displayCtx.overlayOrder[:] dataSource = ovl.dataSource status.update('Reloading {}...'.format(dataSource)) # Get refs to all DisplayContexts - # the master one, and the one for # every view panel. displayCtxs = [self.displayCtx] viewPanels = self.__frame.viewPanels displayCtxs += [vp.displayCtx for vp in viewPanels] # Now get refs to all Display and # DisplayOpts instances for this # overlay. displays = [] opts = [] for dctx in displayCtxs: displays.append(self.displayCtx.getDisplay(ovl)) opts .append(self.displayCtx.getOpts( ovl)) # Turn those references into # {prop : value} dictionaries for i in range(len(displays)): d = displays[i] o = opts[ i] displayProps = d.getAllProperties()[0] optProps = o.getAllProperties()[0] displays[i] = {p : getattr(d, p) for p in displayProps} opts[ i] = {p : getattr(o, p) for p in optProps} # Now that we've got all the settings # for this overlay, we'll remove it # from the list. If removeOverlay # returns False, it probably means # the user cancelled the action. if not removeoverlay.removeOverlay(self.overlayList, self.displayCtx, ovl, 'reloadoverlay.unsaved'): return # Now we re-load the overlay, and add it # back in to the list at the same location ovl = fslimage.Image(dataSource) self.overlayList.insert(index, ovl) # Make sure the overlay is selected, # and the display order is preserved self.displayCtx.selectOverlay(ovl) self.displayCtx.overlayOrder = order # The last step is to re-apply all of the # Display/DisplayOpts settings to the # newly created Display/DisplayOpts # instances. for i, dctx in enumerate(displayCtxs): displayProps = displays[i] optProps = opts[ i] d = dctx.getDisplay(ovl) for prop, val in displayProps.items(): if not d.propertyIsEnabled(prop): continue try: setattr(d, prop, val) except props.DisabledError: continue # Get a ref to the DisplayOpts instance # after we have configured the Display, # as its overlay type may have changed # (and hence the DisplayOpts instance # may have been re-created). o = dctx.getOpts(ovl) for prop, val in optProps.items(): if not o.propertyIsEnabled(prop): continue setattr(o, prop, val) status.update('{} reloaded.'.format(dataSource))