⇤ ← Revision 1 as of 2022-08-12 10:03:00
Size: 3973
Comment: Example of matplotlib plots
|
Size: 4020
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
Toggle line numbers
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)
Toggle line numbers
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()