Source code for scwidgets.cue._widget_cue_figure

# postpones evaluation of annotations
# see https://stackoverflow.com/a/33533514
from __future__ import annotations

from typing import List, Optional, Union

import matplotlib
import matplotlib.pyplot as plt
from IPython.display import display
from ipywidgets import Widget
from matplotlib.figure import Figure
from traitlets.utils.sentinel import Sentinel

from ._widget_cue_output import CueOutput


[docs] class CueFigure(CueOutput): """ A cued displayable ipywidget.Output for a matplotlib figure. Provides utilities to clear and draw the updated figure. For the matplotlib inline backend it closes the active figure to prevent any display outside of the container, that happens on the creation of the figure because pyplot does magic behind the curtain that is hard to suppress. For the matplot interactive widget backend, named "nbagg", it wraps te figure within. :param figure: The matplotlib figure :param widgets_to_observe: The widget to observe if the :param traits_to_observe: has changed. :param traits_to_observe: The trait from the :param widgets_to_observe: to observe if changed. Specify `traitlets.All` to observe all traits. :param cued: Specifies if it is cued on initialization :param show_toolbars: Hide toolbars and headers when using in widget mode. :param css_syle: - **base**: the css style of the box during initialization - **cue**: the css style that is added when :param traits_to_observe: in widget :param widgets_to_observe: changes. It is supposed to change the style of the box such that the user has a visual cue that :param widget_to_cue: has changed. """ def __init__( self, figure: Figure, widgets_to_observe: Union[None, List[Widget], Widget] = None, traits_to_observe: Union[ None, str, Sentinel, List[Union[str, Sentinel, List[str]]] ] = None, cued: bool = True, show_toolbars: bool = False, css_style: Optional[dict] = None, **kwargs, ): CueOutput.__init__( self, widgets_to_observe, traits_to_observe, cued, css_style, **kwargs, ) self.figure = figure if matplotlib.backends.backend in [ "module://matplotlib_inline.backend_inline", "macosx", "agg", ]: # we close the figure so the figure is only contained in this widget # and not shown using plt.show() plt.close(self.figure) elif ( matplotlib.backends.backend == "module://ipympl.backend_nbagg" or matplotlib.backends.backend == "widget" ): # jupyter lab 3 uses "module://ipympl.backend_nbagg" # jupyter lab 4 uses "widget" with self: self.figure.canvas.show() else: raise NotImplementedError( f"matplotlib backend {matplotlib.backends.backend!r} not supported. " "Please change backend to 'widget' by running `%matplotlib widget` " "that should be supported on all systems." ) if show_toolbars: # hides unnecessary elements shown with %matplotlib widget self.figure.canvas.header_visible = False self.figure.canvas.footer_visible = False self.figure.canvas.toolbar_visible = False self.figure.canvas.resizable = False self.draw_display()
[docs] def clear_display(self, wait=False): """ :param wait: same meaning as for the `wait` parameter in the ipywidgets.clear_output function """ if matplotlib.backends.backend in [ "module://matplotlib_inline.backend_inline", "macosx", "agg", ]: self.clear_figure() self.clear_output(wait=wait) elif ( matplotlib.backends.backend == "module://ipympl.backend_nbagg" or matplotlib.backends.backend == "widget" ): # jupyter lab 3 uses "module://ipympl.backend_nbagg" # jupyter lab 4 uses "widget" self.clear_figure() if not (wait): self.figure.canvas.draw_idle() self.figure.canvas.flush_events() else: raise NotImplementedError( f"matplotlib backend {matplotlib.backends.backend!r} not supported. " "Please change backend to 'widget' by running `%matplotlib widget` " "that should be supported on all systems." )
[docs] def draw_display(self): """ Enforces redrawing the figure """ if matplotlib.backends.backend in [ "module://matplotlib_inline.backend_inline", "macosx", "agg", ]: with self: display(self.figure) elif ( matplotlib.backends.backend == "module://ipympl.backend_nbagg" or matplotlib.backends.backend == "widget" ): # jupyter lab 3 uses "module://ipympl.backend_nbagg" # jupyter lab 4 uses "widget" self.figure.canvas.draw_idle() self.figure.canvas.flush_events() else: raise NotImplementedError( f"matplotlib backend {matplotlib.backends.backend!r} not supported. " "Please change backend to 'widget' by running `%matplotlib widget` " "that should be supported on all systems." )
[docs] def clear_figure(self): """ Clears the figure while retainin axes. figure.clear() removes the axes sometimes. """ for ax in self.figure.get_axes(): if ax.has_data() or len(ax.artists) > 0: ax.clear()