2D general plotting
NOTE:
For technical reasons, all interactive-widgets plots in this documentation
are created using Holoviz’s Panel. Often, they will ran just fine with
ipywidgets too. However, if a specific example uses the param
library,
or widgets from the panel
module, then users will have to modify the
params
dictionary in order to make it work with ipywidgets.
Refer to Interactive module for more information.
- spb.graphics.functions_2d.line(expr, range=None, label=None, rendering_kw=None, **kwargs)[source]
Plot a function of one variable over a 2D space.
- Parameters:
- exprExpr or callable
It can either be a symbolic expression representing the function of one variable to be plotted, or a numerical function of one variable, supporting vectorization. In the latter case the following keyword arguments are not supported:
params
,sum_bound
.- range(symbol, min, max)
A 3-tuple denoting the range of the x variable. Default values: min=-10 and max=10.
- labelstr, optional
The label to be shown in the legend. If not provided, the string representation of
expr
will be used.- rendering_kwdict, optional
A dictionary of keywords/values which is passed to the backend’s function to customize the appearance of lines. Refer to the plotting library (backend) manual for more informations.
- adaptivebool, optional
Setting
adaptive=True
activates the adaptive algorithm implemented in [python-adaptive] to create smooth plots. Useadaptive_goal
andloss_fn
to further customize the output.The default value is
False
, which uses an uniform sampling strategy, where the number of discretization points is specified by then
keyword argument.- adaptive_goalcallable, int, float or None
Controls the “smoothness” of the evaluation. Possible values:
None
(default): it will use the following goal:lambda l: l.loss() < 0.01
number (int or float). The lower the number, the more evaluation points. This number will be used in the following goal:
lambda l: l.loss() < number
callable: a function requiring one input element, the learner. It must return a float number. Refer to [python-adaptive] for more information.
- color_funccallable or Expr, optional
Define the line color mapping. It can either be:
A numerical function of 2 variables, x, y (the points computed by the internal algorithm) supporting vectorization.
A symbolic expression having at most as many free symbols as
expr
.None: the default value (no color mapping).
- detect_polesboolean or str, optional
Chose whether to detect and correctly plot poles. There are two algorithms at work:
based on the gradient of the numerical data, it introduces NaN values at locations where the steepness is greater than some threshold. This splits the line into multiple segments. To improve detection, increase the number of discretization points
n
and/or change the value ofeps
.a symbolic approach based on the
continuous_domain
function from thesympy.calculus.util
module, which computes the locations of discontinuities. If any is found, vertical lines will be shown.
Possible options:
True
: activate poles detection computed with the numerical gradient.False
: no poles detection."symbolic"
: use both numerical and symbolic algorithms.
Default to
False
.- epsfloat, optional
An arbitrary small value used by the
detect_poles
algorithm. Default value to 0.1. Before changing this value, it is recommended to increase the number of discretization points.- excludelist, optional
A list of numerical values in the horizontal coordinate which are going to be excluded from the plot. In practice, it introduces discontinuities in the resulting line.
- force_real_evalboolean, optional
Default to False, with which the numerical evaluation is attempted over a complex domain, which is slower but produces correct results. Set this to True if performance is of paramount importance, but be aware that it might produce wrong results. It only works with
adaptive=False
.- scatterboolean, optional
Default to False, which will render a line connecting all the points. If True, a scatter plot will be generated.
- fillboolean, optional
Default to True, which will render empty circular markers. It only works if
scatter=True
. If False, filled circular markers will be rendered.- loss_fncallable or None
The loss function to be used by the
adaptive
learner. Possible values:None
(default): it will use thedefault_loss
from the adaptive module.callable : Refer to [python-adaptive] for more information. Specifically, look at
adaptive.learner.learner1D
to find more loss functions.
- nint, optional
Used when the
adaptive=False
: the function is uniformly sampled atn
number of points. Default value to 1000. If theadaptive=True
, this parameter will be ignored.- only_integersboolean, optional
Default to
False
. IfTrue
, discretize the domain with integer numbers. It only works whenadaptive=False
. Whenonly_integers=True
, the number of discretization points is choosen by the algorithm.- paramsdict
A dictionary mapping symbols to parameters. This keyword argument enables the interactive-widgets plot, which doesn’t support the adaptive algorithm (meaning it will use
adaptive=False
). Learn more by reading the documentation of the interactive sub-module.- steps{‘pre’, ‘post’, ‘mid’, False}, default: False, optional
If set, it connects consecutive points with steps rather than straight segments.
- sum_boundint, optional
When plotting sums, the expression will be pre-processed in order to replace lower/upper bounds set to +/- infinity with this +/- numerical value. Default value to 1000. Note: the higher this number, the slower the evaluation.
- tx, tycallable, optional
Apply a numerical function to the discretized x-direction or to the output of the numerical evaluation, the y-direction.
- xscale‘linear’ or ‘log’, optional
Sets the scaling of the discretized range. Default to
'linear'
.
- Returns:
- serieslist
A list containing one instance of
LineOver1DRangeSeries
.
See also
Examples
>>> from sympy import symbols, sin, pi, tan, exp, cos, log, floor >>> from spb import * >>> x, y = symbols('x, y')
Single Plot
>>> graphics(line(x**2, (x, -5, 5))) Plot object containing: [0]: cartesian line: x**2 for x over (-5.0, 5.0)
(
Source code
,png
)Multiple functions over the same range with custom rendering options:
>>> graphics( ... line(x, (x, -3, 3)), ... line(log(x), (x, -3, 3), rendering_kw={"linestyle": "--"}), ... line(exp(x), (x, -3, 3), rendering_kw={"linestyle": ":"}), ... aspect="equal", ylim=(-3, 3) ... ) Plot object containing: [0]: cartesian line: x for x over (-3.0, 3.0) [1]: cartesian line: log(x) for x over (-3.0, 3.0) [2]: cartesian line: exp(x) for x over (-3.0, 3.0)
(
Source code
,png
)Plotting a summation in which the free symbol of the expression is not used in the lower/upper bounds:
>>> from sympy import Sum, oo, latex >>> expr = Sum(1 / x ** y, (x, 1, oo)) >>> graphics( ... line(expr, (y, 2, 10), sum_bound=1e03), ... title="$%s$" % latex(expr) ... ) Plot object containing: [0]: cartesian line: Sum(x**(-y), (x, 1, 1000)) for y over (2.0, 10.0)
(
Source code
,png
)Plotting a summation in which the free symbol of the expression is used in the lower/upper bounds. Here, the discretization variable must assume integer values:
>>> expr = Sum(1 / x, (x, 1, y)) >>> graphics( ... line(expr, (y, 2, 10), scatter=True), ... title="$%s$" % latex(expr) ... ) Plot object containing: [0]: cartesian line: Sum(1/x, (x, 1, y)) for y over (2.0, 10.0)
(
Source code
,png
)Using an adaptive algorithm, detect and plot vertical lines at singularities. Also, apply a transformation function to the discretized domain in order to convert radians to degrees:
>>> import numpy as np >>> graphics( ... line( ... tan(x), (x, -1.5*pi, 1.5*pi), ... adaptive=True, adaptive_goal=0.001, ... detect_poles="symbolic", tx=np.rad2deg ... ), ... ylim=(-7, 7), xlabel="x [deg]", grid=False ... ) Plot object containing: [0]: cartesian line: tan(x) for x over (-4.71238898038469, 4.71238898038469)
(
Source code
,png
)Introducing discontinuities by excluding specified points:
>>> graphics( ... line(floor(x) / x, (x, -3.25, 3.25), exclude=list(range(-4, 5))), ... ylim=(-1, 5) ... ) Plot object containing: [0]: cartesian line: floor(x)/x for x over (-3.25, 3.25)
(
Source code
,png
)Creating a step plot:
>>> graphics( ... line(x-2, (x, 0, 10), only_integers=True, steps="pre", label="pre"), ... line(x, (x, 0, 10), only_integers=True, steps="mid", label="mid"), ... line(x+2, (x, 0, 10), only_integers=True, steps="post", label="post"), ... ) Plot object containing: [0]: cartesian line: x - 2 for x over (0.0, 10.0) [1]: cartesian line: x for x over (0.0, 10.0) [2]: cartesian line: x + 2 for x over (0.0, 10.0)
(
Source code
,png
)Advanced example showing:
detect singularities by setting
adaptive=False
(better performance), increasing the number of discretization points (in order to have ‘vertical’ segments on the lines) and reducing the threshold for the singularity-detection algorithm.application of color function.
combining together multiple lines.
>>> import numpy as np >>> expr = 1 / cos(10 * x) + 5 * sin(x) >>> def cf(x, y): ... # map a colormap to the distance from the origin ... d = np.sqrt(x**2 + y**2) ... # visibility of the plot is limited: ylim=(-10, 10). However, ... # some of the y-values computed by the function are much higher ... # (or lower). Filter them out in order to have the entire ... # colormap spectrum visible in the plot. ... offset = 12 # 12 > 10 (safety margin) ... d[(y > offset) | (y < -offset)] = 0 ... return d >>> graphics( ... line( ... expr, (x, -5, 5), "distance from (0, 0)", ... rendering_kw={"cmap": "plasma"}, ... adaptive=False, detect_poles=True, n=3e04, ... eps=1e-04, color_func=cf), ... line(5 * sin(x), (x, -5, 5), rendering_kw={"linestyle": "--"}), ... ylim=(-10, 10), title="$%s$" % latex(expr) ... ) Plot object containing: [0]: cartesian line: 5*sin(x) + 1/cos(10*x) for x over (-5.0, 5.0) [1]: cartesian line: 5*sin(x) for x over (-5.0, 5.0)
(
Source code
,png
)Interactive-widget plot of an oscillator. Refer to the interactive sub-module documentation to learn more about the
params
dictionary. This plot illustrates:plotting multiple expressions, each one with its own label and rendering options.
the use of
prange
(parametric plotting range).the use of the
params
dictionary to specify sliders in their basic form: (default, min, max).the use of
panel.widgets.slider.RangeSlider
, which is a 2-values widget. In this case it is used to enforce the condition f1 < f2.the use of a parametric title, specified with a tuple of the form:
(title_str, param_symbol1, ...)
, where:title_str
must be a formatted string, for example:"test = {:.2f}"
.param_symbol1, ...
must be a symbol or a symbolic expression whose free symbols are contained in theparams
dictionary.
from sympy import * from spb import * import panel as pn x, y, f1, f2, d, n = symbols("x, y, f_1, f_2, d, n") params = { (f1, f2): pn.widgets.RangeSlider( value=(1, 2), start=0, end=10, step=0.1), # frequencies d: (0.25, 0, 1), # damping n: (2, 0, 4) # multiple of pi } graphics( line(cos(f1 * x) * exp(-d * x), prange(x, 0, n * pi), label="oscillator 1", params=params), line(cos(f2 * x) * exp(-d * x), prange(x, 0, n * pi), label="oscillator 2", params=params), line(exp(-d * x), prange(x, 0, n * pi), label="upper limit", rendering_kw={"linestyle": ":"}, params=params), line(-exp(-d * x), prange(x, 0, n * pi), label="lower limit", rendering_kw={"linestyle": ":"}, params=params), ylim=(-1.25, 1.25), title=("$f_1$ = {:.2f} Hz", f1) )
- spb.graphics.functions_2d.line_parametric_2d(expr1, expr2, range=None, label=None, rendering_kw=None, colorbar=True, use_cm=True, **kwargs)[source]
Plots a 2D parametric curve.
- Parameters:
- expr1, expr2Expr or callable
The expression representing the horizontal and vertical components of the parametric function. It can either be a symbolic expression representing the function of one variable to be plotted, or a numerical function of one variable, supporting vectorization. In the latter case the following keyword arguments are not supported:
params
,sum_bound
.- range(symbol, min, max)
A 3-tuple denoting the parameter symbol, start value and stop value. For example,
(u, 0, 5)
. If the range is not specified, then a default range of (-10, 10) is used.- labelstr, optional
The label to be shown in the legend. If not provided, the string representation of
expr1
andexpr1
will be used.- rendering_kwdict, optional
A dictionary of keywords/values which is passed to the backend’s function to customize the appearance of lines. Refer to the plotting library (backend) manual for more informations.
- adaptivebool, optional
Setting
adaptive=True
activates the adaptive algorithm implemented in [python-adaptive] to create smooth plots. Useadaptive_goal
andloss_fn
to further customize the output.The default value is
False
, which uses an uniform sampling strategy, where the number of discretization points is specified by then
keyword argument.- adaptive_goalcallable, int, float or None
Controls the “smoothness” of the evaluation. Possible values:
None
(default): it will use the following goal:lambda l: l.loss() < 0.01
number (int or float). The lower the number, the more evaluation points. This number will be used in the following goal:
lambda l: l.loss() < number
callable: a function requiring one input element, the learner. It must return a float number. Refer to [python-adaptive] for more information.
- colorbarboolean, optional
Show/hide the colorbar. Default to True (colorbar is visible). Only works when
use_cm=True
.- color_funccallable, optional
Define the line color mapping when
use_cm=True
. It can either be:A numerical function supporting vectorization. The arity can be:
1 argument:
f(t)
, wheret
is the parameter.2 arguments:
f(x, y)
wherex, y
are the coordinates of the points.3 arguments:
f(x, y, t)
.
A symbolic expression having at most as many free symbols as
expr1
orexpr2
.None: the default value (color mapping applied to the parameter).
- excludelist, optional
A list of numerical values along the parameter which are going to be excluded from the plot. In practice, it introduces discontinuities in the resulting line.
- force_real_evalboolean, optional
Default to False, with which the numerical evaluation is attempted over a complex domain, which is slower but produces correct results. Set this to True if performance is of paramount importance, but be aware that it might produce wrong results. It only works with
adaptive=False
.- loss_fncallable or None
The loss function to be used by the adaptive learner. Possible values:
None
(default): it will use thedefault_loss
from the adaptive module.callable : Refer to [python-adaptive] for more information. Specifically, look at
adaptive.learner.learner1D
to find more loss functions.
- nint, optional
Used when the
adaptive=False
. The function is uniformly sampled atn
number of points. Default value to 1000. If theadaptive=True
, this parameter will be ignored.- paramsdict
A dictionary mapping symbols to parameters. This keyword argument enables the interactive-widgets plot, which doesn’t support the adaptive algorithm (meaning it will use
adaptive=False
). Learn more by reading the documentation of the interactive sub-module.- tx, ty, tpcallable, optional
Apply a numerical function to the x-direction, y-direction and parameter, respectively.
- use_cmboolean, optional
If True, apply a color map to the parametric lines. If False, solid colors will be used instead. Default to True.
- xscale‘linear’ or ‘log’, optional
Sets the scaling of the parameter.
- Returns:
- serieslist
A list containing one instance of
Parametric2DLineSeries
.
Examples
>>> from sympy import symbols, cos, sin, pi, floor, log >>> from spb import * >>> t, u, v = symbols('t, u, v')
A parametric plot of a single expression (a Hypotrochoid using an equal aspect ratio):
>>> graphics( ... line_parametric_2d( ... 2 * cos(u) + 5 * cos(2 * u / 3), ... 2 * sin(u) - 5 * sin(2 * u / 3), ... (u, 0, 6 * pi) ... ), ... aspect="equal" ... ) Plot object containing: [0]: parametric cartesian line: (5*cos(2*u/3) + 2*cos(u), -5*sin(2*u/3) + 2*sin(u)) for u over (0.0, 18.84955592153876)
(
Source code
,png
)A parametric plot with multiple expressions with the same range with solid line colors:
>>> graphics( ... line_parametric_2d(2 * cos(t), sin(t), (t, 0, 2*pi), use_cm=False), ... line_parametric_2d(cos(t), 2 * sin(t), (t, 0, 2*pi), use_cm=False), ... ) Plot object containing: [0]: parametric cartesian line: (2*cos(t), sin(t)) for t over (0.0, 6.283185307179586) [1]: parametric cartesian line: (cos(t), 2*sin(t)) for t over (0.0, 6.283185307179586)
(
Source code
,png
)A parametric plot with multiple expressions with different ranges, custom labels, custom rendering options and a transformation function applied to the discretized parameter to convert radians to degrees:
>>> import numpy as np >>> graphics( ... line_parametric_2d( ... 3 * cos(u), 3 * sin(u), (u, 0, 2 * pi), "u [deg]", ... rendering_kw={"lw": 3}, tp=np.rad2deg), ... line_parametric_2d( ... 3 * cos(2 * v), 5 * sin(4 * v), (v, 0, pi), "v [deg]", ... tp=np.rad2deg ... ), ... aspect="equal" ... ) Plot object containing: [0]: parametric cartesian line: (3*cos(u), 3*sin(u)) for u over (0.0, 6.283185307179586) [1]: parametric cartesian line: (3*cos(2*v), 5*sin(4*v)) for v over (0.0, 3.141592653589793)
(
Source code
,png
)Introducing discontinuities by excluding specified points:
>>> e1 = log(floor(t))*cos(t) >>> e2 = log(floor(t))*sin(t) >>> graphics( ... line_parametric_2d( ... e1, e2, (t, 1, 4*pi), exclude=list(range(1, 13))), ... grid=False ... ) Plot object containing: [0]: parametric cartesian line: (log(floor(t))*cos(t), log(floor(t))*sin(t)) for t over (1.0, 12.566370614359172)
(
Source code
,png
)Plotting a numerical function instead of a symbolic expression:
>>> import numpy as np >>> fx = lambda t: np.sin(t) * (np.exp(np.cos(t)) - 2 * np.cos(4 * t) - np.sin(t / 12)**5) >>> fy = lambda t: np.cos(t) * (np.exp(np.cos(t)) - 2 * np.cos(4 * t) - np.sin(t / 12)**5) >>> graphics( ... line_parametric_2d(fx, fy, ("t", 0, 12 * pi), ... use_cm=False, n=2000), ... title="Butterfly Curve", ... )
(
Source code
,png
)Interactive-widget plot. Refer to the interactive sub-module documentation to learn more about the
params
dictionary. This plot illustrates:the use of
prange
(parametric plotting range).the use of the
params
dictionary to specify sliders in their basic form: (default, min, max).
from sympy import * from spb import * x, a, s, e = symbols("x a s, e") graphics( line_parametric_2d( cos(a * x), sin(x), prange(x, s*pi, e*pi), params={ a: (0.5, 0, 2), s: (0, 0, 2), e: (2, 0, 2), }), aspect="equal", xlim=(-1.25, 1.25), ylim=(-1.25, 1.25) )
- spb.graphics.functions_2d.line_polar(expr, range=None, label=None, rendering_kw=None, **kwargs)[source]
Creates a 2D polar plot of a function of one variable.
This function executes
line_parametric_2d
. Refer to its documentation for a full list of keyword arguments.See also
Examples
>>> from sympy import symbols, sin, cos, exp, pi >>> from spb import * >>> theta = symbols('theta')
Plot with cartesian axis:
>>> graphics( ... line_polar(3 * sin(2 * theta), (theta, 0, 2*pi)), ... aspect="equal" ... ) Plot object containing: [0]: parametric cartesian line: (3*sin(2*theta)*cos(theta), 3*sin(theta)*sin(2*theta)) for theta over (0.0, 6.283185307179586)
(
Source code
,png
)Plot with polar axis:
>>> graphics( ... line_polar(exp(sin(theta)) - 2 * cos(4 * theta), (theta, 0, 2 * pi)), ... polar_axis=True, aspect="equal" ... ) Plot object containing: [0]: parametric cartesian line: ((exp(sin(theta)) - 2*cos(4*theta))*cos(theta), (exp(sin(theta)) - 2*cos(4*theta))*sin(theta)) for theta over (0.0, 6.283185307179586)
(
Source code
,png
)Interactive-widget plot of Guilloché Pattern. Refer to the interactive sub-module documentation to learn more about the
params
dictionary. This plot illustrates:the use of
prange
(parametric plotting range).the use of the
params
dictionary to specify the widgets to be created by Holoviz’s Panel.
from sympy import * from spb import * import panel as pn a, b, c, d, e, f, theta, tp = symbols("a:f theta tp") def func(n): t1 = (c + sin(a * theta + d)) t2 = ((b + sin(b * theta + e)) - (c + sin(a * theta + d))) t3 = (f + sin(a * theta + n / pi)) return t1 + t2 * t3 / 2 params = { a: pn.widgets.IntInput(value=6, name="a"), b: pn.widgets.IntInput(value=12, name="b"), c: pn.widgets.IntInput(value=18, name="c"), d: (4.7, 0, 2*pi), e: (1.8, 0, 2*pi), f: (3, 0, 5), tp: (2, 0, 2) } series = [] for n in range(20): series += line_polar( func(n), prange(theta, 0, tp*pi), params=params, rendering_kw={"line_color": "black", "line_width": 0.5}) graphics( *series, aspect="equal", layout = "sbl", ncols = 1, title="Guilloché Pattern Explorer", backend=BB, legend=False, servable=True, imodule="panel" )
- spb.graphics.functions_2d.contour(expr, range1=None, range2=None, label=None, rendering_kw=None, colorbar=True, clabels=True, fill=True, **kwargs)[source]
Plots contour lines or filled contours of a function of two variables.
- Parameters:
- clabelsbool, optional
Visualize labels of contour lines. Only works when
fill=False
. Default to True. Note that some backend might not implement this feature.- colorbarboolean, optional
Show/hide the colorbar. Default to True (colorbar is visible). Only works when
use_cm=True
.- fillbool, optional
Choose between filled contours or line contours. Default to True (filled contours).
- **kwargs
Keyword arguments are the same as
surface()
. Refer to its documentation for a for a full list of keyword arguments.
- Returns:
- serieslist
A list containing one instance of
ContourSeries
.
See also
Examples
>>> from sympy import symbols, cos, exp, sin, pi, Eq, Add >>> from spb import * >>> x, y = symbols('x, y')
Filled contours of a function of two variables.
>>> graphics( ... contour( ... cos((x**2 + y**2)) * exp(-(x**2 + y**2) / 10), ... (x, -5, 5), (y, -5, 5) ... ), ... grid=False ... ) Plot object containing: [0]: contour: exp(-x**2/10 - y**2/10)*cos(x**2 + y**2) for x over (-5.0, 5.0) and y over (-5.0, 5.0)
(
Source code
,png
)Line contours of a function of two variables.
>>> expr = 5 * (cos(x) - 0.2 * sin(y))**2 + 5 * (-0.2 * cos(x) + sin(y))**2 >>> graphics( ... contour(expr, (x, 0, 2 * pi), (y, 0, 2 * pi), fill=False) ... ) Plot object containing: [0]: contour: 5*(-0.2*sin(y) + cos(x))**2 + 5*(sin(y) - 0.2*cos(x))**2 for x over (0.0, 6.283185307179586) and y over (0.0, 6.283185307179586)
(
Source code
,png
)Combining together filled and line contours. Use a custom label on the colorbar of the filled contour.
>>> expr = 5 * (cos(x) - 0.2 * sin(y))**2 + 5 * (-0.2 * cos(x) + sin(y))**2 >>> graphics( ... contour(expr, (x, 0, 2 * pi), (y, 0, 2 * pi), "z", ... rendering_kw={"cmap": "coolwarm"}), ... contour(expr, (x, 0, 2 * pi), (y, 0, 2 * pi), ... rendering_kw={"colors": "k", "cmap": None, "linewidths": 0.75}, ... fill=False), ... grid=False ... ) Plot object containing: [0]: contour: 5*(-0.2*sin(y) + cos(x))**2 + 5*(sin(y) - 0.2*cos(x))**2 for x over (0.0, 6.283185307179586) and y over (0.0, 6.283185307179586) [1]: contour: 5*(-0.2*sin(y) + cos(x))**2 + 5*(sin(y) - 0.2*cos(x))**2 for x over (0.0, 6.283185307179586) and y over (0.0, 6.283185307179586)
(
Source code
,png
)Visually inspect the solutions of a system of 2 non-linear equations. The intersections between the contour lines represent the solutions.
>>> eq1 = Eq((cos(x) - sin(y) / 2)**2 + 3 * (-sin(x) + cos(y) / 2)**2, 2) >>> eq2 = Eq((cos(x) - 2 * sin(y))**2 - (sin(x) + 2 * cos(y))**2, 3) >>> graphics( ... contour( ... eq1.rewrite(Add), (x, 0, 2 * pi), (y, 0, 2 * pi), ... rendering_kw={"levels": [0]}, ... fill=False, clabels=False), ... contour( ... eq2.rewrite(Add), (x, 0, 2 * pi), (y, 0, 2 * pi), ... rendering_kw={"levels": [0]}, ... fill=False, clabels=False), ... ) Plot object containing: [0]: contour: 3*(-sin(x) + cos(y)/2)**2 + (-sin(y)/2 + cos(x))**2 - 2 for x over (0.0, 6.283185307179586) and y over (0.0, 6.283185307179586) [1]: contour: -(sin(x) + 2*cos(y))**2 + (-2*sin(y) + cos(x))**2 - 3 for x over (0.0, 6.283185307179586) and y over (0.0, 6.283185307179586)
(
Source code
,png
)Contour plot with polar axis:
>>> r, theta = symbols("r, theta") >>> graphics( ... contour( ... sin(2 * r) * cos(theta), (theta, 0, 2*pi), (r, 0, 7), ... rendering_kw={"levels": 100} ... ), ... polar_axis=True, aspect="equal" ... ) Plot object containing: [0]: contour: sin(2*r)*cos(theta) for theta over (0.0, 6.283185307179586) and r over (0.0, 7.0)
(
Source code
,png
)Interactive-widget plot. Refer to the interactive sub-module documentation to learn more about the
params
dictionary. This plot illustrates:the use of
prange
(parametric plotting range).the use of the
params
dictionary to specify sliders in their basic form: (default, min, max).the use of
panel.widgets.slider.RangeSlider
, which is a 2-values widget.
from sympy import * from spb import * import panel as pn x, y, a, b = symbols("x y a b") x_min, x_max, y_min, y_max = symbols("x_min x_max y_min y_max") expr = (cos(x) + a * sin(x) * sin(y) - b * sin(x) * cos(y))**2 graphics( contour( expr, prange(x, x_min*pi, x_max*pi), prange(y, y_min*pi, y_max*pi), params={ a: (1, 0, 2), b: (1, 0, 2), (x_min, x_max): pn.widgets.RangeSlider( value=(-1, 1), start=-3, end=3, step=0.1), (y_min, y_max): pn.widgets.RangeSlider( value=(-1, 1), start=-3, end=3, step=0.1), }), grid=False )
- spb.graphics.functions_2d.implicit_2d(expr, range1=None, range2=None, label=None, rendering_kw=None, color=None, border_color=None, border_kw=None, **kwargs)[source]
Plot implicit equations / inequalities.
implicit_2d
, by default, generates a contour using a mesh grid of fixednumber of points. The greater the number of points, the better the results, but also the greater the memory used. By settingadaptive=True
, interval arithmetic will be used to plot functions. If the expression cannot be plotted using interval arithmetic, it defaults to generating a contour using a mesh grid. With interval arithmetic, the line width can become very small; in those cases, it is better to use the mesh grid approach.- Parameters:
- exprExpr, Relational, BooleanFunction
The equation / inequality that is to be plotted.
- range1, range2tuples or Symbol
Tuple denoting the discretization domain, for example:
(x, -10, 10)
.- labelstr, optional
The label to be shown when multiple expressions are plotted. If not provided, the string representation of the expression will be used.
- rendering_kwdict, optional
A dictionary of keywords/values which is passed to the backend’s function to customize the appearance of contours. Refer to the plotting library (backend) manual for more informations.
- colorstr, optional
Specify the color of lines/regions. Default to None (automatic coloring by the backend).
- border_colorstr or bool, optional
If given, a limiting border will be added when plotting inequalities (<, <=, >, >=). Use
border_kw
if more customization options are required.- border_kwdict, optional
If given, a limiting border will be added when plotting inequalities (<, <=, >, >=). This is a dictionary of keywords/values which is passed to the backend’s function to customize the appearance of the limiting border. Refer to the plotting library (backend) manual for more informations.
- adaptivebool, optional
The default value is set to
False
, meaning that the internal algorithm uses a mesh grid approach. In such case, Boolean combinations of expressions cannot be plotted. If set toTrue
, the internal algorithm uses interval arithmetic. If the expression cannot be plotted with interval arithmetic, it switches to the meshgrid approach.- depthinteger
The depth of recursion for adaptive grid. Default value is 0. Takes value in the range (0, 4). Think of the resulting plot as a picture composed by pixels. By increasing
depth
we are increasing the number of pixels, thus obtaining a more accurate plot.- n, n1, n2int
Number of discretization points in the horizontal and vertical directions when
adaptive=False
. Default to 100.n
is a shortcut to set the same number of discretization points on both directions.- paramsdict
A dictionary mapping symbols to parameters. This keyword argument enables the interactive-widgets plot. Learn more by reading the documentation of the interactive sub-module.
- show_in_legendbool
If True, add a legend entry for the expression being plotted. This option is useful to hide a particular expression when combining together multiple plots. Default to True.
- Returns:
- serieslist
A list containing at most two instances of
Implicit2DSeries
.
See also
Examples
Plot expressions:
>>> from sympy import symbols, Ne, Eq, And, sin, cos, pi, log, latex >>> from spb import * >>> x, y = symbols('x y')
Plot a line representing an equality:
>>> graphics(implicit_2d(x - 1, (x, -5, 5), (y, -5, 5))) Plot object containing: [0]: Implicit expression: Eq(x - 1, 0) for x over (-5.0, 5.0) and y over (-5.0, 5.0)
(
Source code
,png
)Plot a region:
>>> graphics( ... implicit_2d(y > x**2, (x, -5, 5), (y, -10, 10), n=150), ... grid=False) Plot object containing: [0]: Implicit expression: y > x**2 for x over (-5.0, 5.0) and y over (-10.0, 10.0)
(
Source code
,png
)Plot a region using a custom color, highlights the limiting border and customize its appearance.
>>> expr = 4 * (cos(x) - sin(y) / 5)**2 + 4 * (-cos(x) / 5 + sin(y))**2 >>> graphics( ... implicit_2d( ... expr <= pi, (x, -pi, pi), (y, -pi, pi), ... color="gold", border_color="k", ... border_kw={"linestyles": "-.", "linewidths": 1} ... ), ... grid=False ... ) Plot object containing: [0]: Implicit expression: 4*(-sin(y)/5 + cos(x))**2 + 4*(sin(y) - cos(x)/5)**2 <= pi for x over (-3.141592653589793, 3.141592653589793) and y over (-3.141592653589793, 3.141592653589793) [1]: Implicit expression: Eq(-4*(-sin(y)/5 + cos(x))**2 - 4*(sin(y) - cos(x)/5)**2 + pi, 0) for x over (-3.141592653589793, 3.141592653589793) and y over (-3.141592653589793, 3.141592653589793)
(
Source code
,png
)Boolean expressions will be plotted with the adaptive algorithm. Note the thin width of lines:
>>> graphics( ... implicit_2d( ... Eq(y, sin(x)) & (y > 0), (x, -2 * pi, 2 * pi), (y, -4, 4)), ... implicit_2d( ... Eq(y, sin(x)) & (y < 0), (x, -2 * pi, 2 * pi), (y, -4, 4)), ... ylim=(-2, 2) ... ) Plot object containing: [0]: Implicit expression: (y > 0) & Eq(y, sin(x)) for x over (-6.283185307179586, 6.283185307179586) and y over (-4.0, 4.0) [1]: Implicit expression: (y < 0) & Eq(y, sin(x)) for x over (-6.283185307179586, 6.283185307179586) and y over (-4.0, 4.0)
(
Source code
,png
)Plotting multiple implicit expressions and setting labels:
>>> V, t, b, L = symbols("V, t, b, L") >>> L_array = [5, 10, 15, 20, 25] >>> b_val = 0.0032 >>> expr = b * V * 0.277 * t - b * L - log(1 + b * V * 0.277 * t) >>> series = [] >>> for L_val in L_array: ... series += implicit_2d( ... expr.subs({b: b_val, L: L_val}), (t, 0, 3), (V, 0, 1000), ... label="L = %s" % L_val) >>> graphics(*series) Plot object containing: [0]: Implicit expression: Eq(0.0008864*V*t - log(0.0008864*V*t + 1) - 0.016, 0) for t over (0.0, 3.0) and V over (0.0, 1000.0) [1]: Implicit expression: Eq(0.0008864*V*t - log(0.0008864*V*t + 1) - 0.032, 0) for t over (0.0, 3.0) and V over (0.0, 1000.0) [2]: Implicit expression: Eq(0.0008864*V*t - log(0.0008864*V*t + 1) - 0.048, 0) for t over (0.0, 3.0) and V over (0.0, 1000.0) [3]: Implicit expression: Eq(0.0008864*V*t - log(0.0008864*V*t + 1) - 0.064, 0) for t over (0.0, 3.0) and V over (0.0, 1000.0) [4]: Implicit expression: Eq(0.0008864*V*t - log(0.0008864*V*t + 1) - 0.08, 0) for t over (0.0, 3.0) and V over (0.0, 1000.0)
(
Source code
,png
)Comparison of similar expressions plotted with different algorithms. Note:
Adaptive algorithm (
adaptive=True
) can be used with any expression, but it usually creates lines with variable thickness. Thedepth
keyword argument can be used to improve the accuracy, but reduces line thickness even further.Mesh grid algorithm (
adaptive=False
) creates lines with constant thickness.
>>> expr1 = Eq(x * y - 20, 15 * y) >>> expr2 = Eq((x - 3) * y - 20, 15 * y) >>> expr3 = Eq((x - 6) * y - 20, 15 * y) >>> ranges = (x, 15, 30), (y, 0, 50) >>> graphics( ... implicit_2d( ... expr1, *ranges, adaptive=True, depth=0, ... label="adaptive=True, depth=0"), ... implicit_2d( ... expr2, *ranges, adaptive=True, depth=1, ... label="adaptive=True, depth=1"), ... implicit_2d( ... expr3, *ranges, adaptive=False, label="adaptive=False"), ... grid=False ... ) Plot object containing: [0]: Implicit expression: Eq(x*y - 20, 15*y) for x over (15.0, 30.0) and y over (0.0, 50.0) [1]: Implicit expression: Eq(y*(x - 3) - 20, 15*y) for x over (15.0, 30.0) and y over (0.0, 50.0) [2]: Implicit expression: Eq(y*(x - 6) - 20, 15*y) for x over (15.0, 30.0) and y over (0.0, 50.0)
(
Source code
,png
)If the expression is plotted with the adaptive algorithm and it produces “low-quality” results, maybe it’s possible to rewrite it in order to use the mesh grid approach (contours). For example:
>>> from spb import plotgrid >>> expr = Ne(x*y, 1) >>> p1 = graphics( ... implicit_2d(expr, (x, -10, 10), (y, -10, 10)), ... grid=False, title="$%s$ : First approach" % latex(expr), ... aspect="equal", show=False) >>> p2 = graphics( ... implicit_2d(x < 20, (x, -10, 10), (y, -10, 10)), ... implicit_2d(Eq(*expr.args), (x, -10, 10), (y, -10, 10), ... color="w", show_in_legend=False), ... grid=False, title="$%s$ : Second approach" % latex(expr), ... aspect="equal", show=False) >>> plotgrid(p1, p2, nc=2)
(
Source code
,png
)Interactive-widget implicit plot. Refer to the interactive sub-module documentation to learn more about the
params
dictionary. This plot illustrates:the use of
prange
(parametric plotting range).the use of the
params
dictionary to specify sliders in their basic form: (default, min, max).the use of
panel.widgets.slider.RangeSlider
, which is a 2-values widget.
from sympy import * from spb import * import panel as pn x, y, a, b, c, d = symbols("x, y, a, b, c, d") y_min, y_max = symbols("y_min, y_max") expr = Eq(a * x**2 - b * x + c, d * y + y**2) graphics( implicit_2d(expr, (x, -2, 2), prange(y, y_min, y_max), params={ a: (10, -15, 15), b: (7, -15, 15), c: (3, -15, 15), d: (2, -15, 15), (y_min, y_max): pn.widgets.RangeSlider( value=(-10, 10), start=-15, end=15, step=0.1) }, n=150), ylim=(-10, 10))
- spb.graphics.functions_2d.list_2d(coord_x, coord_y, label=None, rendering_kw=None, **kwargs)[source]
Plots lists of coordinates.
- Parameters:
- coord_x, coord_ylist or tuple
List of coordinates.
- labelstr, optional
The label to be shown in the legend.
- rendering_kwdict, optional
A dictionary of keywords/values which is passed to the backend’s function to customize the appearance of lines. Refer to the
- scatterboolean, optional
Default to False, which will render a line connecting all the points. If True, a scatter plot will be generated.
- fillboolean, optional
Default to False, which will render empty circular markers. It only works if
scatter=True
. If True, filled circular markers will be rendered.- paramsdict
A dictionary mapping symbols to parameters. This keyword argument enables the interactive-widgets plot. Learn more by reading the documentation of the interactive sub-module.
- Returns:
- serieslist
A list containing one instance of
List2DSeries
.
See also
Examples
>>> from sympy import symbols, sin, cos >>> from spb import * >>> x = symbols('x')
Plot the coordinates of a single function:
>>> xx = [t / 100 * 6 - 3 for t in list(range(101))] >>> yy = [cos(x).evalf(subs={x: t}) for t in xx] >>> graphics(list_2d(xx, yy)) Plot object containing: [0]: 2D list plot
(
Source code
,png
)Plot individual points with custom labels. Each point will be converted to a list by the algorithm:
>>> graphics( ... list_2d(0, 0, "A", scatter=True), ... list_2d(1, 1, "B", scatter=True), ... list_2d(2, 0, "C", scatter=True), ... ) Plot object containing: [0]: 2D list plot [1]: 2D list plot [2]: 2D list plot
(
Source code
,png
)Scatter plot of the coordinates of multiple functions, with custom rendering keywords:
>>> xx = [t / 70 * 6 - 3 for t in list(range(71))] >>> yy1 = [cos(x).evalf(subs={x: t}) for t in xx] >>> yy2 = [sin(x).evalf(subs={x: t}) for t in xx] >>> graphics( ... list_2d(xx, yy1, "cos", scatter=True), ... list_2d(xx, yy2, "sin", {"marker": "*", "markerfacecolor": None}, ... scatter=True), ... ) Plot object containing: [0]: 2D list plot [1]: 2D list plot
(
Source code
,png
)Interactive-widget plot. Refer to the interactive sub-module documentation to learn more about the
params
dictionary.from sympy import * from spb import * x, t = symbols("x, t") params = {t: (0, 0, 2*pi)} graphics( line_parametric_2d( cos(x), sin(x), (x, 0, 2*pi), rendering_kw={"linestyle": ":"}, use_cm=False), line_parametric_2d( cos(2 * x) / 2, sin(2 * x) / 2, (x, 0, pi), rendering_kw={"linestyle": ":"}, use_cm=False), list_2d( cos(t), sin(t), "A", rendering_kw={"marker": "s", "markerfacecolor": None}, params=params, scatter=True), list_2d( cos(2 * t) / 2, sin(2 * t) / 2, "B", rendering_kw={"marker": "s", "markerfacecolor": None}, params=params, scatter=True), aspect="equal" )
- spb.graphics.functions_2d.geometry(geom, label=None, rendering_kw=None, fill=True, **kwargs)[source]
Plot entities from the sympy.geometry module.
- Parameters:
- geomGeometryEntity
Represent the geometric entity to be plotted.
- labelstr, optional
The name of the geometry entity to be eventually shown on the legend. If not provided, the string representation of
geom
will be used.- rendering_kwdict, optional
A dictionary of keywords/values which is passed to the backend’s function to customize the appearance of lines or fills. Refer to the plotting library (backend) manual for more informations.
- fillboolean
Default to True. Fill the polygon/circle/ellipse.
- A dictionary mapping symbols to parameters. This keyword argument
enables the interactive-widgets plot. Learn more by reading the documentation of the interactive sub-module.
- Returns:
- serieslist
A list containing one instance of
GeometrySeries
.
See also
Examples
>>> from sympy import (symbols, Circle, Ellipse, Polygon, ... Curve, Segment, Point2D, Point3D, Line3D, Plane, ... Rational, pi, Point, cos, sin) >>> from spb import * >>> x, y, z = symbols('x, y, z')
Plot a single geometry, customizing its color:
>>> graphics( ... geometry( ... Ellipse(Point(-3, 2), hradius=3, eccentricity=Rational(4, 5)), ... rendering_kw={"color": "tab:orange"}), ... grid=False, aspect="equal" ... ) Plot object containing: [0]: geometry entity: Ellipse(Point2D(-3, 2), 3, 9/5)
(
Source code
,png
)Plot several numeric geometric entitiesy. By default, circles, ellipses and polygons are going to be filled. Plotting Curve objects is the same as plot_parametric.
>>> graphics( ... geometry(Circle(Point(0, 0), 5)), ... geometry(Ellipse(Point(-3, 2), hradius=3, eccentricity=Rational(4, 5))), ... geometry(Polygon((4, 0), 4, n=5)), ... geometry(Curve((cos(x), sin(x)), (x, 0, 2 * pi))), ... geometry(Segment((-4, -6), (6, 6))), ... geometry(Point2D(0, 0)), ... aspect="equal", grid=False ... ) Plot object containing: [0]: geometry entity: Circle(Point2D(0, 0), 5) [1]: geometry entity: Ellipse(Point2D(-3, 2), 3, 9/5) [2]: geometry entity: RegularPolygon(Point2D(4, 0), 4, 5, 0) [3]: parametric cartesian line: (cos(x), sin(x)) for x over (0.0, 6.283185307179586) [4]: geometry entity: Segment2D(Point2D(-4, -6), Point2D(6, 6)) [5]: geometry entity: Point2D(0, 0)
(
Source code
,png
)Plot several numeric geometric entities defined by numbers only, turn off fill. Every entity is represented as a line.
>>> graphics( ... geometry(Circle(Point(0, 0), 5), fill=False), ... geometry( ... Ellipse(Point(-3, 2), hradius=3, eccentricity=Rational(4, 5)), ... fill=False), ... geometry(Polygon((4, 0), 4, n=5), fill=False), ... geometry(Curve((cos(x), sin(x)), (x, 0, 2 * pi)), fill=False), ... geometry(Segment((-4, -6), (6, 6)), fill=False), ... geometry(Point2D(0, 0), fill=False), ... aspect="equal", grid=False ... ) Plot object containing: [0]: geometry entity: Circle(Point2D(0, 0), 5) [1]: geometry entity: Ellipse(Point2D(-3, 2), 3, 9/5) [2]: geometry entity: RegularPolygon(Point2D(4, 0), 4, 5, 0) [3]: parametric cartesian line: (cos(x), sin(x)) for x over (0.0, 6.283185307179586) [4]: geometry entity: Segment2D(Point2D(-4, -6), Point2D(6, 6)) [5]: geometry entity: Point2D(0, 0)
(
Source code
,png
)Plot 3D geometric entities. Instances of
Plane
must be plotted withimplicit_3d
or withplane
(with the necessary ranges).from sympy import * from spb import * x, y, z = symbols("x, y, z") graphics( geometry( Point3D(0, 0, 0), label="center", rendering_kw={"point_size": 1}), geometry(Line3D(Point3D(-2, -3, -4), Point3D(2, 3, 4)), "line"), plane( Plane((0, 0, 0), (1, 1, 1)), (x, -5, 5), (y, -4, 4), (z, -10, 10)), backend=KB )
Interactive-widget plot. Refer to the interactive sub-module documentation to learn more about the
params
dictionary.from sympy import * from spb import * import panel as pn a, b, c, d = symbols("a, b, c, d") params = { a: (0, -1, 1), b: (1, -1, 1), c: (2, 1, 2), d: pn.widgets.IntInput(value=6, start=3, end=8, name="n") } graphics( geometry(Polygon((a, b), c, n=d), "a", params=params), geometry( Polygon((a + 2, b + 3), c, n=d + 1), "b", params=params, fill=False), aspect="equal", xlim=(-2.5, 5.5), ylim=(-3, 6.5), imodule="panel")