Differences between revisions 1 and 2
Revision 1 as of 2022-08-12 10:03:00
Size: 3973
Editor: saraedum
Comment: Example of matplotlib plots
Revision 2 as of 2022-08-12 10:04:12
Size: 4020
Editor: saraedum
Comment: Fix layout
Deletions are marked like this. Additions are marked like this.
Line 5: Line 5:
* [[interact|@interact]] creates configurable widgets.
* [[https://github.com/flatsurf/ipymuvue/|ipyμvue]] can be used to write Jupyter widgets in Python that work with SageMath.
* matplotlib plots can be made interactive.
 * [[interact|@interact]] creates configurable widgets.
 * [[https://github.com/flatsurf/ipymuvue/tree/master/examples|ipyμvue]] can be used to write Jupyter widgets in Python that work with SageMath.
 * matplotlib plots can be made interactive.
Line 11: Line 11:
{{{ {{{#!python
Line 88: Line 88:
{{{ {{{#!python
Line 100: Line 100:
{{{ {{{#!python

Interactive Widgets

Currently, visualization in SageMath is mostly not interactive. However, there are approaches to build interactive widgets for the Jupyter notebook:

  • @interact creates configurable widgets.

  • ipyμvue can be used to write Jupyter widgets in Python that work with SageMath.

  • matplotlib plots can be made interactive.

Example: Interactive matplotlib Plots

   1 # Enable interactive matplotlib output in Jupyter.
   2 %matplotlib notebook
   3 
   4 class DynamicPlot(sage.plot.primitive.GraphicPrimitive):
   5     r"""
   6     A dynamic 2D plot that redraws when it is dragged around.
   7     
   8     INPUT:
   9     
  10     - ``create_plot`` -- a callable that creates a plot for given ``xmin``, ``ymin``, ``xmax``, ``ymax`` bounds.
  11     
  12     - ``xmin``, ``ymin``, ``xmax``, ``ymax`` -- initial bounds of the 2D plot.
  13 
  14     """
  15     def __init__(self, create_plot, xmin=-1, xmax=1, ymin=-1, ymax=1, options={}):
  16         self._create_plot = create_plot
  17         
  18         self._xmin = xmin
  19         self._xmax = xmax
  20         self._ymin = ymin
  21         self._ymax = ymax
  22         
  23         super().__init__(options)
  24         
  25     def _render_on_subplot(self, subplot):
  26         def redraw(_=None):
  27             try:
  28                 # Clear the subplot before redrawing. Otherwise, we would pile up lots
  29                 # of identical plots that take more and more time to draw.
  30                 # Note that this will also clear other primitives from this subplot.
  31                 subplot._children = []
  32 
  33                 xlim = subplot.axes.get_xlim()
  34                 ylim = subplot.axes.get_ylim()
  35 
  36                 import sage.misc.verbose
  37                 verbose = sage.misc.verbose.get_verbose()
  38                 # Silence warnings about undefined values in the plotted function.
  39                 sage.misc.verbose.set_verbose(-1)
  40                 try:
  41                     # Plot all the objects produced by create_plot().
  42                     for object in self._create_plot(xmin=xlim[0], xmax=xlim[1], ymin=ylim[0], ymax=ylim[1])._objects:
  43                         object._render_on_subplot(subplot)
  44                 finally:
  45                     sage.misc.verbose.set_verbose(verbose)
  46             except Exception:
  47                 # Unfortunately, there is no easy way to display an error message in a matplotlib callback.
  48                 # Errors are shown in the terminal where Jupyter was started.
  49                 subplot.clear()
  50                 raise
  51 
  52         # Redraw when the plot is dragged around.
  53         subplot.axes.callbaacks.connect("ylim_changed", redraw)
  54         subplot.axes.callbacks.connect("xlim_changed", redraw)
  55         
  56         # Draw the plot in the initial bounds.
  57         redraw()
  58      
  59     def get_minmax_data(self):
  60         r"""
  61         Return the initial bounds of this plot to focus the camera here.
  62         """
  63         return dict(xmin=self._xmin, ymin=self._ymin, xmax=self._xmax, ymax=self._ymax)
  64 
  65     def show(self):
  66         r"""
  67         Create a matplotlib figure and show this plot.
  68         """
  69         g = Graphics()
  70         g.add_primitive(self)
  71 
  72         import matplotlib.pyplot as plt
  73         figure = plt.figure()
  74         g.matplotlib(figure=figure)

   1 # We plot an infinite ray from the origin.
   2 def create_plot(*, xmin, ymin, xmax, ymax):
   3     def ray(x):
   4         if x > 0:
   5             return x + sin(x)
   6 
   7     return plot(ray, alpha=.5, xmin=xmin, ymin=ymin, xmax=xmax, ymax=ymax)
   8 
   9 DynamicPlot(create_plot).show()

   1 # We plot a parabola
   2 def create_plot(*, xmin, ymin, xmax, ymax):
   3     return plot(x^2, alpha=.5, xmin=xmin, ymin=ymin, xmax=xmax, ymax=ymax,
   4                # Adaptive recursion slows down the plotting when we zoom out a lot, so we disable
   5                # it for this simple function.
   6                adaptive_recursion=0)
   7 
   8 DynamicPlot(create_plot).show()

interactive (last edited 2022-08-23 18:33:47 by saraedum)