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.
The package also provides other helpful functions, like
substitute_indexed_symbols()
, that are useful when visualizing sympy
expressions.
- Slider#
Allowed ipywidgets slider types.
alias of
Union
[FloatSlider
,IntSlider
]
- RangeDefinition#
Types of range definitions used in
set_ranges()
.alias of
Union
[Tuple
[float
,float
],Tuple
[float
,float
,Union
[float
,int
]]]
- class SliderKwargs(sliders: Mapping[str, FloatSlider | IntSlider], arg_to_symbol: Mapping[str, str])[source]#
Bases:
Mapping
Wrapper around a
dict
of sliders that can serve as keyword arguments.Sliders can be defined in
interactive_plot()
through kwargs. This wrapper class can be used for that.- __getitem__(key: str | Symbol) FloatSlider | IntSlider [source]#
Get slider by symbol, symbol name, or argument name.
- property arg_to_symbol: dict[str, str][source]#
Copy of the internal translation
dict
for argument names.
- prepare_sliders(expression: Expr, plot_symbol: Symbol | tuple[Symbol, ...]) tuple[Callable, SliderKwargs] [source]#
Lambdify a
sympy
expression and create sliders for its arguments.>>> 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(...)
- create_slider(symbol: Symbol) FloatSlider | IntSlider [source]#
Create an
int
orfloat
slider, depending on Symbol assumptions.The description for the slider is rendered as LaTeX from the
Symbol
name.>>> create_slider(sp.Symbol("a")) FloatSlider(value=0.0, description='\\(a\\)') >>> create_slider(sp.Symbol("n0", integer=True)) IntSlider(value=0, description='\\(n_{0}\\)')
- partial_doit(expression: Expr, doit_classes: type[Basic] | tuple[type[Basic], ...]) Expr [source]#
Perform
doit()
up to a certain level.
- rename_symbols(expression: Expr, renames: Callable[[str], str] | dict[str, str]) Expr [source]#
Rename symbols in an expression.
>>> a, b, x = sp.symbols(R"a \beta x") >>> expr = a + b * x >>> rename_symbols(expr, renames={"a": "A", R"\beta": "B"}) A + B*x >>> rename_symbols(expr, renames=lambda s: s.replace("\\", "")) a + beta*x >>> rename_symbols(expr, renames={"non-existent": "c"}) Traceback (most recent call last): ... KeyError: "No symbol with name 'non-existent' in expression"
- substitute_indexed_symbols(expression: Expr) Expr [source]#
Substitute
IndexedBase
with symbols.See Indexed free symbols for more info.
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
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
%config InlineBackend.figure_formats = ['svg']
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,
np_expression,
**sliders,
ylim="auto",
)
ax.set_xlabel("$x$")
ax.set_ylabel(f"${sp.latex(expression)}$");
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",
)