symplot

Create interactive plots for sympy expressions.

The procedure to create interactive plots with for sympy expressions with mpl-interactions has been extracted to this module.

The module is only available here, under the documentation. If this feature turns out to be popular, it can be published as an independent package.

class SliderKwargs(sliders: Mapping[str, Union[ipywidgets.widgets.widget_float.FloatSlider, ipywidgets.widgets.widget_int.IntSlider]], arg_to_symbol: Mapping[str, str])[source]

Bases: collections.abc.Mapping

Wrapper around a dict of sliders that can serve as keyword arguments.

Sliders can be defined in mpl_interactions.interactive_plot through kwargs. This wrapper class can be used for that.

__getitem__(key: Union[str, sympy.core.symbol.Symbol])Union[ipywidgets.widgets.widget_float.FloatSlider, ipywidgets.widgets.widget_int.IntSlider][source]

Get slider by symbol, symbol name, or argument name.

set_ranges(*args: Dict[str, Union[Tuple[float, float], Tuple[float, float, int]]], **kwargs: Union[Tuple[float, float], Tuple[float, float, int]])None[source]

Set min, max and (optionally) the number of steps for each slider.

set_values(*args: Dict[str, float], **kwargs: float)None[source]

Set initial values for the sliders.

Either use a dict as input, or use kwargs with slider names as the keywords (see SliderKwargs.__getitem__). This façade method exists in particular for parameter_defaults.

create_slider(symbol: sympy.core.symbol.Symbol)Union[ipywidgets.widgets.widget_float.FloatSlider, ipywidgets.widgets.widget_int.IntSlider][source]

Create an int or float slider, depending on Symbol assumptions.

The description for the slider is rendered as LaTeX from the Symbol name.

>>> import sympy as sp
>>> from symplot import create_slider
>>> create_slider(sp.Symbol("y"))
FloatSlider(value=0.0, description='$y$')
>>> create_slider(sp.Symbol("n", integer=True))
IntSlider(value=0, description='$n$')
prepare_sliders(expression: sympy.core.expr.Expr, plot_symbol: sympy.core.symbol.Symbol)Tuple[Callable, symplot.SliderKwargs][source]

Lambdify a sympy expression and create sliders for its arguments.

>>> import sympy as sp
>>> from symplot import prepare_sliders
>>> n = sp.Symbol("n", integer=True)
>>> x = sp.Symbol("x")
>>> expression, sliders = prepare_sliders(x ** n, plot_symbol=x)
>>> expression
<function _lambdifygenerated at ...>
>>> sliders
SliderKwargs(...)

Examples

The following examples show how to work with prepare_sliders() and the resulting SliderKwargs. For more explanation about what happens behind the scenes, see Inspect model interactively.

Exponential wave

Construct a mathematical expression with sympy:

import sympy as sp

n = sp.Symbol("n", integer=True)
x, a = sp.symbols("x, a")
expression = sp.sin(n * x) * sp.exp(-a * x)
expression
\[\displaystyle e^{- a x} \sin{\left(n x \right)}\]

Create sliders with prepare_sliders(), set their ranges and (optionally) provide some initial values:

from symplot import prepare_sliders

np_expression, sliders = prepare_sliders(expression, plot_symbol=x)
sliders.set_ranges(
    n=(0, 10),
    a=(-1, 1, 200),
)
sliders.set_values(n=6, a=0.3)

Now use mpl-interactions to plot the lambdified expression. Note how the SliderKwargs are unpacked as keyword arguments:

%matplotlib widget
import matplotlib.pyplot as plt
import mpl_interactions.ipyplot as iplt
import numpy as np

plot_domain = np.linspace(0, 10, 1_000)
fig, ax = plt.subplots(figsize=(7, 4))
controls = iplt.plot(
    plot_domain,
    lambda x, **kwargs: np_expression(x, **kwargs),
    **sliders,
    ylim="auto",
)
ax.set_xlabel("$x$")
ax.set_ylabel(f"${sp.latex(expression)}$");
../_images/symplot_14_1.png

Range slider

See Using RangeSliders.

np_expression, sliders = prepare_sliders(expression, plot_symbol=x)
sliders.set_values(n=6, a=0.3)
sliders.set_ranges(
    n=(0, 10),
    a=(-1, 1, 200),
)


def x_domain(x_range, **kwargs):
    min_, max_ = x_range
    return np.linspace(min_, max_, 1_000)


def f(x, **kwargs):
    del kwargs["x_range"]
    return np_expression(x, **kwargs)


fig, ax = plt.subplots()
controls = iplt.plot(
    x_domain,
    f,
    x_range=("r", 0, 10),
    **sliders,
    xlim="auto",
    ylim="auto",
)