Plotting functions
Cadabra can plot functions of one or two variables using thecdb.graphics.plot
packages. Plotting itself is handled by matplotlib (with a backend for plotly in preparation), but you do not have to know anything about that in order to use the plotting facilities.Functions of one variable
Functions of one variable can be plotted using theplot
function of the cdb.graphics.plot
package. Its
basic form takes a Cadabra expression which is a function of one variable, as well as a triplet containing
the independent variable and its start and end value.from cdb.graphics.plot import *
plot($\sin(x) (1-x**2)$, ($x$, 0, 20), grid=True);
Multiple functions can be plotted in the same figure by simply feeding a list of functions as the first argument
to
plot
, as in the example below. This also shows how to customise the plot by setting the title and axes.plot([$\sin(x) (1-x**2)$, $100 \cos(x)$], ($x$, 0, 20), title="Two functions", xlabel="time", ylabel="value");
You can also add curves to an existing figure. To do this, give every curve a label. If you want to overwrite
a curve, use the same label.
fig = plot($\sin(x)$, ($x$, 0, 10), label="curve1");
plot($\cos(x)$, ($x$, 0, 10), fig=fig, label="curve2", color="red");
plot($\sin(x)\exp(-x)$, ($x$, 0, 10), fig=fig, label="curve1");
Parametric plots in two dimensions
If you have a parametric representation of the curve you want to plot, there is a functionparametric_plot
, which
takes two arguments (or two lists of arguments). In the example below, we plot two parametric curves.
The first argument is a list of two functions (of the parameter $t$) for the
$x$-coordinates, while the second argument is a list of two functions for the $y$-coordinates. In order to make this
more readable, we have defined the functions as Cadabra expressions on separate lines.f1x := (1-(t/20)**2) \cos(t);
f1y := (1-(t/20)**2) \sin(t);
f2x := 1.2\cos(t);
f2y := 1.2\sin(t);
parametric_plot([f1x, f2x], [f1y, f2y], ($t$, 0, 20), aspect='equal');
\(\displaystyle{}\left(1 - \frac{1}{400}{t}^{2}\right) \cos{t}\)
(1 - 1/400 (t)**2) \cos(t)
\(\displaystyle{}\left(1 - \frac{1}{400}{t}^{2}\right) \sin{t}\)
(1 - 1/400 (t)**2) \sin(t)
\(\displaystyle{}1.2 \cos{t}\)
1.2 \cos(t)
\(\displaystyle{}1.2 \sin{t}\)
1.2 \sin(t)
Note the use of the
aspect
parameter to ensure that circles indeed come out as circles, not as ellipses.
You can use any of the matplotlib aspect options for this parameter.Animations
It is possible to make animations of functions by plotting each successive frame separately, and re-using the output cell into which the frames are displayed. In the example below,out
is the ID of the output cell (initially zero),
and the display
function is used to display each frame, overwriting the content of the output cell (this functionality
is currently unavailable when using Cadabra from Jupyter).out=0
import time
p = None
for a in np.concatenate( [np.linspace(0.5, 5.0, 100), np.linspace(5.0, 0.5, 100)] ):
p = plot($\sin( @(a) x) (1 - x**2)$, ($x$, 0, 10), yrange=[-50, 50], title=f"a = {a:.2f}", fig=p)
out = display(p, out)
time.sleep(0.01)
By re-using the figure, but using plots with different labels, different curves can be animated
independently. The following example has one figure, in which two plots are drawn: one called "sin" and another one called "cos".
We set the $y$-axis range manually to avoid the plot fitting tight around whatever is plotted on any given frame.
out=0
import time
f=None
for n in range(3):
for a in np.linspace(0, 9, 100):
f = plot($\sin(x)$, ($x$, 9-a-2, 9-a), xrange=[0, 6.28], yrange=[-1.2, 1.2],
fig=f, label="sin", title=f"sin(x) and cos(x)", color="green")
f = plot($\cos(x)$, ($x$, a-2, a), xrange=[0, 6.28], yrange=[-1.2, 1.2],
fig=f, label="cos", color="red")
out = display(f, out)
time.sleep(0.001)
time.sleep(1)
Below is an example which produces a fade-in effect by using colors with an alpha component which is animated.
out=0
f=None
for alpha in np.linspace(0, 1.0, 50):
f = plot($\sin(x)$, ($x$, 0, 6.28), xrange=[0, 6.28], yrange=[-1.2, 1.2],
fig=f, label="sin", title=f"sin(x)", color=(0, .5, 0, alpha))
out = display(f, out)
time.sleep(0.01)
for alpha in np.linspace(0, 1.0, 50):
f = plot($\cos(x)$, ($x$, 0, 6.28), xrange=[0, 6.28], yrange=[-1.2, 1.2],
fig=f, label="cos", title=f"sin(x) and cos(x)", color=(0.8, 0, 0, alpha))
out = display(f, out)
time.sleep(0.01)
You can do this with any of Cadabra's plot types, e.g. parametric plots, as in the example below.
out=0
import time
p = None
for a in np.linspace(0, 5*6.28, 100):
p = parametric_plot($\cos(t)$, $\sin(t)$, ($t$, a, a+0.5), fig=p,
xrange=[-1.5, 1.5], yrange=[-1.2, 1.2], aspect='equal')
out = display(p, out)
time.sleep(0.01)