Cadabra
a field-theory motivated approach to computer algebra

Plotting functions

Cadabra can plot functions of one or two variables using the cdb.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 the plot 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 function parametric_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)
Copyright © 2001-2024 Kasper Peeters
Questions? info@cadabra.science