Plotting¶

Introduction¶

The plotting module allows you to make 2-dimensional and 3-dimensional plots. Presently the plots are rendered using matplotlib as a backend.

The plotting module has the following functions:

• plot: Plots 2D line plots.
• plot_parametric: Plots 2D parametric plots.
• plot_implicit: Plots 2D implicit and region plots.
• plot3d: Plots 3D plots of functions in two variables.
• plot3d_parametric_line: Plots 3D line plots, defined by a parameter.
• plot3d_parametric_surface: Plots 3D parametric surface plots.

The above functions are only for convenience and ease of use. It is possible to plot any plot by passing the corresponding Series class to Plot as argument.

Plot Class¶

class diofant.plotting.plot.Plot(*args, **kwargs)[source]

The central class of the plotting module.

For interactive work the function plot is better suited.

This class permits the plotting of diofant expressions using numerous backends (matplotlib, Google charts api, etc).

The figure can contain an arbitrary number of plots of diofant expressions, lists of coordinates of points, etc. Plot has a private attribute _series that contains all data series to be plotted (expressions for lines or surfaces, lists of points, etc (all subclasses of BaseSeries)). Those data series are instances of classes not imported by from diofant import *.

The customization of the figure is on two levels. Global options that concern the figure as a whole (eg title, xlabel, scale, etc) and per-data series options (eg name) and aesthetics (eg. color, point shape, line type, etc.).

The difference between options and aesthetics is that an aesthetic can be a function of the coordinates (or parameters in a parametric plot). The supported values for an aesthetic are: - None (the backend uses default values) - a constant - a function of one variable (the first coordinate or parameter) - a function of two variables (the first and second coordinate or parameters) - a function of three variables (only in nonparametric 3D plots) Their implementation depends on the backend so they may not work in some backends.

If the plot is parametric and the arity of the aesthetic function permits it the aesthetic is calculated over parameters and not over coordinates. If the arity does not permit calculation over parameters the calculation is done over coordinates.

Only cartesian coordinates are supported for the moment, but you can use the parametric plots to plot in polar, spherical and cylindrical coordinates.

The arguments for the constructor Plot must be subclasses of BaseSeries.

Any global option can be specified as a keyword argument.

The global options for a figure are:

• title : str
• xlabel : str
• ylabel : str
• legend : bool
• xscale : {‘linear’, ‘log’}
• yscale : {‘linear’, ‘log’}
• axis : bool
• axis_center : tuple of two floats or {‘center’, ‘auto’}
• xlim : tuple of two floats
• ylim : tuple of two floats
• aspect_ratio : tuple of two floats or {‘auto’}
• autoscale : bool
• margin : float in [0, 1]

The per data series options and aesthetics are: There are none in the base series. See below for options for subclasses.

Some data series support additional aesthetics or options:

ListSeries, LineOver1DRangeSeries, Parametric2DLineSeries, Parametric3DLineSeries support the following:

Aesthetics:

• line_color : function which returns a float.

options:

• label : str
• steps : bool
• integers_only : bool

SurfaceOver2DRangeSeries, ParametricSurfaceSeries support the following:

aesthetics:

• surface_color : function which returns a float.
append(arg)[source]

Adds an element from a plot’s series to an existing plot.

Examples

Consider two Plot objects, p1 and p2. To add the second plot’s first series object to the first, use the append method, like so:

>>> p1 = plot(x*x)
>>> p2 = plot(x)
>>> p1.append(p2[0])
>>> print(str(p1))
Plot object containing:
[0]: cartesian line: x**2 for x over (-10.0, 10.0)
[1]: cartesian line: x for x over (-10.0, 10.0)

extend(arg)[source]

Adds all series from another plot.

Examples

Consider two Plot objects, p1 and p2. To add the second plot to the first, use the extend method, like so:

>>> p1 = plot(x*x)
>>> p2 = plot(x)
>>> p1.extend(p2)
>>> print(str(p1))
Plot object containing:
[0]: cartesian line: x**2 for x over (-10.0, 10.0)
[1]: cartesian line: x for x over (-10.0, 10.0)


Plotting Function Reference¶

diofant.plotting.plot.plot(*args, **kwargs)[source]

Plots a function of a single variable and returns an instance of the Plot class (also, see the description of the show keyword argument below).

The plotting uses an adaptive algorithm which samples recursively to accurately plot the plot. The adaptive algorithm uses a random point near the midpoint of two points that has to be further sampled. Hence the same plots can appear slightly different.

Single Plot.

plot(expr, range, **kwargs)

If the range is not specified, then a default range of (-10, 10) is used.

Multiple plots with same range.

plot(expr1, expr2, ..., range, **kwargs)

If the range is not specified, then a default range of (-10, 10) is used.

Multiple plots with different ranges.

plot((expr1, range), (expr2, range), ..., **kwargs)

Range has to be specified for every expression.

Default range may change in the future if a more advanced default range detection algorithm is implemented.

Parameters: expr : Expr Expression representing the function of single variable range: tuple (x, 0, 5), A 3-tuple denoting the range of the free variable. show: Boolean, optional The default value is set to True. Set show to False and the function will not display the plot. The returned instance of the Plot class can then be used to save or display the plot by calling the save() and show() methods respectively. Arguments for LineOver1DRangeSeries class: adaptive: Boolean, optional The default value is set to True. Set adaptive to False and specify nb_of_points if uniform sampling is required. depth: int, optional Recursion depth of the adaptive algorithm. A depth of value n samples a maximum of $$2^{n}$$ points. nb_of_points: int, optional Used when the adaptive is set to False. The function is uniformly sampled at nb_of_points number of points. Aesthetics options: line_color: float, optional Specifies the color for the plot. See Plot to see how to set color for the plots. If there are multiple plots, then the same series series are applied to all the plots. If you want to set these options separately, you can index the Plot object returned and set it. Arguments for Plot class: title : str, optional Title of the plot. It is set to the latex representation of the expression, if the plot has only one expression. xlabel : str, optional Label for the x-axis. ylabel : str, optional Label for the y-axis. xscale: {‘linear’, ‘log’}, optional Sets the scaling of the x-axis. yscale: {‘linear’, ‘log’}, optional Sets the scaling if the y-axis. axis_center: tuple of two floats denoting the coordinates of the center or {‘center’, ‘auto’} xlim : tuple of two floats denoting the x-axis limits. ylim : tuple of two floats denoting the y-axis limits.

Examples

Single Plot

>>> print(str(plot(x**2, (x, -5, 5))))
Plot object containing:
[0]: cartesian line: x**2 for x over (-5.0, 5.0)


Multiple plots with single range.

>>> print(str(plot(x, x**2, x**3, (x, -5, 5))))
Plot object containing:
[0]: cartesian line: x for x over (-5.0, 5.0)
[1]: cartesian line: x**2 for x over (-5.0, 5.0)
[2]: cartesian line: x**3 for x over (-5.0, 5.0)


Multiple plots with different ranges.

>>> print(str(plot((x**2, (x, -6, 6)), (x, (x, -5, 5)))))
Plot object containing:
[0]: cartesian line: x**2 for x over (-6.0, 6.0)
[1]: cartesian line: x for x over (-5.0, 5.0)


>>> print(str(plot(x**2, adaptive=False, nb_of_points=400)))
Plot object containing:
[0]: cartesian line: x**2 for x over (-10.0, 10.0)

diofant.plotting.plot.plot_parametric(*args, **kwargs)[source]

Plots a 2D parametric plot.

The plotting uses an adaptive algorithm which samples recursively to accurately plot the plot. The adaptive algorithm uses a random point near the midpoint of two points that has to be further sampled. Hence the same plots can appear slightly different.

Single plot.

plot_parametric(expr_x, expr_y, range, **kwargs)

If the range is not specified, then a default range of (-10, 10) is used.

Multiple plots with same range.

plot_parametric((expr1_x, expr1_y), (expr2_x, expr2_y), range, **kwargs)

If the range is not specified, then a default range of (-10, 10) is used.

Multiple plots with different ranges.

plot_parametric((expr_x, expr_y, range), ..., **kwargs)

Range has to be specified for every expression.

Default range may change in the future if a more advanced default range detection algorithm is implemented.

Parameters: expr_x : Expr Expression representing the function along x. expr_y : Expr Expression representing the function along y. range: tuple (u, 0, 5), A 3-tuple denoting the range of the parameter variable. Arguments for Parametric2DLineSeries class: adaptive: Boolean, optional The default value is set to True. Set adaptive to False and specify nb_of_points if uniform sampling is required. depth: int, optional Recursion depth of the adaptive algorithm. A depth of value n samples a maximum of $$2^{n}$$ points. nb_of_points: int, optional Used when the adaptive is set to False. The function is uniformly sampled at nb_of_points number of points. Aesthetics: line_color: function which returns a float Specifies the color for the plot. See diofant.plotting.Plot for more details. If there are multiple plots, then the same Series arguments are applied to all the plots. If you want to set these options separately, you can index the returned Plot object and set it. Arguments for Plot class: xlabel : str Label for the x-axis. ylabel : str Label for the y-axis. xscale: {‘linear’, ‘log’} Sets the scaling of the x-axis. yscale: {‘linear’, ‘log’} Sets the scaling if the y-axis. axis_center: tuple of two floats denoting the coordinates of the center or {‘center’, ‘auto’} xlim : tuple of two floats denoting the x-axis limits. ylim : tuple of two floats denoting the y-axis limits.

Examples

>>> u = symbols('u')


Single Parametric plot

>>> print(str(plot_parametric(cos(u), sin(u), (u, -5, 5))))
Plot object containing:
[0]: parametric cartesian line: (cos(u), sin(u)) for u over (-5.0, 5.0)


Multiple parametric plot with single range.

>>> print(str(plot_parametric((cos(u), sin(u)), (u, cos(u)))))
Plot object containing:
[0]: parametric cartesian line: (cos(u), sin(u)) for u over (-10.0, 10.0)
[1]: parametric cartesian line: (u, cos(u)) for u over (-10.0, 10.0)


Multiple parametric plots.

>>> print(str(plot_parametric((cos(u), sin(u), (u, -5, 5)),
...     (cos(u), u, (u, -5, 5)))))
Plot object containing:
[0]: parametric cartesian line: (cos(u), sin(u)) for u over (-5.0, 5.0)
[1]: parametric cartesian line: (cos(u), u) for u over (-5.0, 5.0)

diofant.plotting.plot.plot3d(*args, **kwargs)[source]

Plots a 3D surface plot.

Single plot.

plot3d(expr, range_x, range_y, **kwargs)

If the ranges are not specified, then a default range of (-10, 10) is used.

Multiple plot with the same range.

plot3d(expr1, expr2, range_x, range_y, **kwargs)

If the ranges are not specified, then a default range of (-10, 10) is used.

Multiple plots with different ranges.

plot3d((expr1, range_x, range_y), (expr2, range_x, range_y), ..., **kwargs)

Ranges have to be specified for every expression.

Default range may change in the future if a more advanced default range detection algorithm is implemented.

Parameters: expr : Expr Expression representing the function along x. range_x: tuple (x, 0, 5), A 3-tuple denoting the range of the x variable. range_y: tuple (y, 0, 5), A 3-tuple denoting the range of the y variable. Arguments for SurfaceOver2DRangeSeries class: nb_of_points_x: int The x range is sampled uniformly at nb_of_points_x of points. nb_of_points_y: int The y range is sampled uniformly at nb_of_points_y of points. Aesthetics: surface_color: Function which returns a float Specifies the color for the surface of the plot. See diofant.plotting.Plot for more details. If there are multiple plots, then the same series arguments are applied to all the plots. If you want to set these options separately, you can index the returned Plot object and set it. Arguments for Plot class: title : str Title of the plot.

Examples

Single plot

>>> print(str(plot3d(x*y, (x, -5, 5), (y, -5, 5))))
Plot object containing:
[0]: cartesian surface: x*y for x over (-5.0, 5.0) and y over (-5.0, 5.0)


Multiple plots with same range

>>> print(str(plot3d(x*y, -x*y, (x, -5, 5), (y, -5, 5))))
Plot object containing:
[0]: cartesian surface: x*y for x over (-5.0, 5.0) and y over (-5.0, 5.0)
[1]: cartesian surface: -x*y for x over (-5.0, 5.0) and y over (-5.0, 5.0)


Multiple plots with different ranges.

>>> print(str(plot3d((x**2 + y**2, (x, -5, 5), (y, -5, 5)),
...     (x*y, (x, -3, 3), (y, -3, 3)))))
Plot object containing:
[0]: cartesian surface: x**2 + y**2 for x over (-5.0, 5.0) and y over (-5.0, 5.0)
[1]: cartesian surface: x*y for x over (-3.0, 3.0) and y over (-3.0, 3.0)

diofant.plotting.plot.plot3d_parametric_line(*args, **kwargs)[source]

Plots a 3D parametric line plot.

Single plot.

plot3d_parametric_line(expr_x, expr_y, expr_z, range, **kwargs)

If the range is not specified, then a default range of (-10, 10) is used.

Multiple plots.

plot3d_parametric_line((expr_x, expr_y, expr_z, range), ..., **kwargs)

Ranges have to be specified for every expression.

Default range may change in the future if a more advanced default range detection algorithm is implemented.

Parameters: expr_x : Expr Expression representing the function along x. expr_y : Expr Expression representing the function along y. expr_z : Expr Expression representing the function along z. range: tuple (u, 0, 5), A 3-tuple denoting the range of the parameter variable. Arguments for Parametric3DLineSeries class. nb_of_points: int The range is uniformly sampled at nb_of_points number of points. Aesthetics: line_color: function which returns a float. Specifies the color for the plot. See diofant.plotting.Plot for more details. If there are multiple plots, then the same series arguments are applied to all the plots. If you want to set these options separately, you can index the returned Plot object and set it. Arguments for Plot class. title : str Title of the plot.

Examples

>>> u = symbols('u')


Single plot.

>>> print(str(plot3d_parametric_line(cos(u), sin(u), u, (u, -5, 5))))
Plot object containing:
[0]: 3D parametric cartesian line: (cos(u), sin(u), u) for u over (-5.0, 5.0)


Multiple plots.

>>> print(str(plot3d_parametric_line((cos(u), sin(u), u, (u, -5, 5)),
...     (sin(u), u**2, u, (u, -5, 5)))))
Plot object containing:
[0]: 3D parametric cartesian line: (cos(u), sin(u), u) for u over (-5.0, 5.0)
[1]: 3D parametric cartesian line: (sin(u), u**2, u) for u over (-5.0, 5.0)

diofant.plotting.plot.plot3d_parametric_surface(*args, **kwargs)[source]

Plots a 3D parametric surface plot.

Single plot.

plot3d_parametric_surface(expr_x, expr_y, expr_z, range_u, range_v, **kwargs)

If the ranges is not specified, then a default range of (-10, 10) is used.

Multiple plots.

plot3d_parametric_surface((expr_x, expr_y, expr_z, range_u, range_v), ..., **kwargs)

Ranges have to be specified for every expression.

Default range may change in the future if a more advanced default range detection algorithm is implemented.

Parameters: expr_x: Expr Expression representing the function along x. expr_y: Expr Expression representing the function along y. expr_z: Expr Expression representing the function along z. range_u: tuple (u, 0, 5), A 3-tuple denoting the range of the u variable. range_v: tuple (v, 0, 5), A 3-tuple denoting the range of the v variable. Arguments for ParametricSurfaceSeries class: nb_of_points_u: int The u range is sampled uniformly at nb_of_points_v of points nb_of_points_y: int The v range is sampled uniformly at nb_of_points_y of points Aesthetics: surface_color: Function which returns a float Specifies the color for the surface of the plot. See diofant.plotting.Plot for more details. If there are multiple plots, then the same series arguments are applied for all the plots. If you want to set these options separately, you can index the returned Plot object and set it. Arguments for Plot class: title : str Title of the plot.

Examples

>>> u, v = symbols('u v')


Single plot.

>>> print(str(plot3d_parametric_surface(cos(u + v), sin(u - v), u - v,
...     (u, -5, 5), (v, -5, 5))))
Plot object containing:
[0]: parametric cartesian surface: (cos(u + v), sin(u - v), u - v) for u over (-5.0, 5.0) and v over (-5.0, 5.0)

diofant.plotting.plot_implicit.plot_implicit(expr, x_var=None, y_var=None, **kwargs)[source]

A plot function to plot implicit equations / inequalities.

Parameters: expr : Expr The equation / inequality that is to be plotted. x_var : symbol or tuple, optional symbol to plot on x-axis or tuple giving symbol and range as (symbol, xmin, xmax) y_var : symbol or tuple, optional symbol to plot on y-axis or tuple giving symbol and range as (symbol, ymin, ymax) If neither x_var nor y_var are given then the free symbols in the expression will be assigned in the order they are sorted. The following keyword arguments can also be used: adaptive : Boolean, optional The default value is set to True. It has to be set to False if you want to use a mesh grid. depth : integer The depth of recursion for adaptive mesh grid. Default value is 0. Takes value in the range (0, 4). points : integer The number of points if adaptive mesh grid is not used. Default value is 200. title : str The title for the plot. xlabel : str The label for the x-axis ylabel : string The label for the y-axis Aesthetics options: line_color : float or str Specifies the color for the plot. See Plot to see how to set color for the plots. plot_implicit, by default, uses interval arithmetic to plot functions. If the expression cannot be plotted using interval arithmetic, it defaults to a generating a contour using a mesh grid of fixed number of points. By setting adaptive to False, you can force plot_implicit to use the mesh grid. The mesh grid method can be effective when adaptive plotting using interval arithmetic, fails to plot with small line width.

Examples

Plot expressions:

Without any ranges for the symbols in the expression

>>> p1 = plot_implicit(Eq(x**2 + y**2, 5))


With the range for the symbols

>>> p2 = plot_implicit(Eq(x**2 + y**2, 3),
...         (x, -3, 3), (y, -3, 3))


With depth of recursion as argument.

>>> p3 = plot_implicit(Eq(x**2 + y**2, 5),
...         (x, -4, 4), (y, -4, 4), depth = 2)


Using mesh grid and not using adaptive meshing.

>>> p4 = plot_implicit(Eq(x**2 + y**2, 5),
...         (x, -5, 5), (y, -2, 2), adaptive=False)


Using mesh grid with number of points as input.

>>> p5 = plot_implicit(Eq(x**2 + y**2, 5),
...         (x, -5, 5), (y, -2, 2),


Plotting regions.

>>> p6 = plot_implicit(y > x**2)


Plotting Using boolean conjunctions.

>>> p7 = plot_implicit(And(y > x, y > -x))


When plotting an expression with a single variable (y - 1, for example), specify the x or the y variable explicitly:

>>> p8 = plot_implicit(y - 1, y_var=y)
>>> p9 = plot_implicit(x - 1, x_var=x)


Series Classes¶

class diofant.plotting.plot.BaseSeries[source]

Base class for the data objects containing stuff to be plotted.

The backend should check if it supports the data series that it’s given. (eg TextBackend supports only LineOver1DRange). It’s the backend responsibility to know how to use the class of data series that it’s given.

Some data series classes are grouped (using a class attribute like is_2Dline) according to the api they present (based only on convention). The backend is not obliged to use that api (eg. The LineOver1DRange belongs to the is_2Dline group and presents the get_points method, but the TextBackend does not use the get_points method).

class diofant.plotting.plot.Line2DBaseSeries[source]

A base class for 2D lines.

• adding the label, steps and only_integers options
• making is_2Dline true
• defining get_segments and get_color_array
class diofant.plotting.plot.LineOver1DRangeSeries(expr, var_start_end, **kwargs)[source]

Representation for a line consisting of a Diofant expression over a range.

get_segments()[source]

The adaptive sampling is done by recursively checking if three points are almost collinear. If they are not collinear, then more points are added between those points.

References

[1] Adaptive polygonal approximation of parametric curves,
Luiz Henrique de Figueiredo.
class diofant.plotting.plot.Parametric2DLineSeries(expr_x, expr_y, var_start_end, **kwargs)[source]

Representation for a line consisting of two parametric diofant expressions over a range.

get_segments()[source]

The adaptive sampling is done by recursively checking if three points are almost collinear. If they are not collinear, then more points are added between those points.

References

[1] Adaptive polygonal approximation of parametric curves,
Luiz Henrique de Figueiredo.
class diofant.plotting.plot.Line3DBaseSeries[source]

A base class for 3D lines.

Most of the stuff is derived from Line2DBaseSeries.

class diofant.plotting.plot.Parametric3DLineSeries(expr_x, expr_y, expr_z, var_start_end, **kwargs)[source]

Representation for a 3D line consisting of two parametric diofant expressions and a range.

class diofant.plotting.plot.SurfaceBaseSeries[source]

A base class for 3D surfaces.

class diofant.plotting.plot.SurfaceOver2DRangeSeries(expr, var_start_end_x, var_start_end_y, **kwargs)[source]

Representation for a 3D surface consisting of a diofant expression and 2D range.

class diofant.plotting.plot.ParametricSurfaceSeries(expr_x, expr_y, expr_z, var_start_end_u, var_start_end_v, **kwargs)[source]

Representation for a 3D surface consisting of three parametric diofant expressions and a range.

class diofant.plotting.plot_implicit.ImplicitSeries(expr, var_start_end_x, var_start_end_y, has_equality, use_interval_math, depth, nb_of_points, line_color)[source]

Representation for Implicit plot