@mddoc
-def interactive(figure: Union[Figure, SubFigure, Axes]) -> Html:
- """Render a matplotlib figure using an interactive viewer.
-
- The interactive viewer allows you to pan, zoom, and see plot coordinates
- on mouse hover.
-
- Example:
- ```python
- plt.plot([1, 2])
- # plt.gcf() gets the current figure
- mo.mpl.interactive(plt.gcf())
- ```
-
- Args:
- figure (matplotlib Figure or Axes): A matplotlib `Figure` or `Axes` object.
-
- Returns:
- Html: An interactive matplotlib figure as an `Html` object.
- """
- # No top-level imports of matplotlib, since it isn't a required
- # dependency
- from matplotlib.axes import Axes
-
- if isinstance(figure, Axes):
- maybe_figure = figure.get_figure()
- assert maybe_figure is not None, "Axes object does not have a Figure"
- figure = maybe_figure
-
- # We can't support interactive plots in Pyodide
- # since they require a WebSocket connection
- if is_pyodide():
- LOGGER.warning(
- "Interactive plots are not supported in Pyodide/WebAssembly"
- )
- return NonInteractiveMplHtml(figure)
-
- ctx = get_context()
- if not isinstance(ctx, KernelRuntimeContext):
- return NonInteractiveMplHtml(figure)
-
- # When virtual files are not supported (e.g., during HTML export),
- # fall back to static PNG instead of interactive plot
- if not ctx.virtual_files_supported:
- return NonInteractiveMplHtml(figure)
-
- # Figure Manager, Any type because matplotlib doesn't have typings
- figure_manager = new_figure_manager_given_figure(id(figure), figure)
-
- # TODO(akshayka): Proxy this server through the marimo server to help with
- # deployment.
- app = get_or_create_application()
- port = app.state.port
-
- class CleanupHandle(CellLifecycleItem):
- def create(self, context: RuntimeContext) -> None:
- del context
-
- def dispose(self, context: RuntimeContext, deletion: bool) -> bool:
- del context
- del deletion
- figure_managers.remove(figure_manager)
- return True
-
- figure_managers.add(figure_manager)
- assert ctx.execution_context is not None
- ctx.cell_lifecycle_registry.add(CleanupHandle())
- ctx.stream.cell_id = ctx.execution_context.cell_id
-
- content = _template(str(figure_manager.num), port)
-
- return InteractiveMplHtml(
- h.iframe(
- srcdoc=html.escape(content),
- width="100%",
- height="550px",
- onload="__resizeIframe(this)",
- ),
- figure,
- )
-