differt.plotting package#
Module contents#
Plotting utilities for DiffeRT objects.
Warning
Unlike in other modules, plotting utilities work
with NumPy arrays (np.ndarray
)
instead of JAX arrays. Therefore, it is important to first
convert any JAX array into its NumPy equivalent with
np.asarray
before using it as an
argument to any of the functions defined here.
Note
Backend names are case-sensitive.
Backend-specific notes#
Each backend comes with its own configuration options and outputs that the user should be aware of.
VisPy#
VisPy uses SceneCanvas
objects
to display contents, on which a view is attached. The view
(ViewBox
)
is what contains
the data to be plotted.
To reuse an existing canvas
object, just pass it as a keyword
argument to any of the draw_*
functions in this module, i.e.,
with draw_*(..., canvas=canvas)
.
In turn, each of those functions returns a figure on which you
can later add data.
It is also possible to pass an existing view
on which data will be plotted: draw_*(..., view=view)
.
If the jupyter_rfb
module is installed, VisPy’s canvas integrate
nicely within Jupyter notebooks.
Matplotlib#
Matplotlib uses Figure
objects
to display contents, on which multiple axes can be attached. In turn, each
axis can contain data to be plotted.
To reuse an existing figure
object, just pass it as a keyword
argument to any of the draw_*
functions in this module, i.e.,
with draw_*(..., figure=figure)
.
In turn, each of those functions returns a figure on which you
can later add data.
It is also possible to pass an existing axis
(Axes
)
on which data will be plotted: draw_*(..., ax=ax)
.
Warning
By default, Matplotlib instantiates 2D axes, but this module extensively uses 3D plot methods. If an axis is provided, it is your responsibility to ensure that it can plot 3D data when needed.
By default, Matpotlib displays static images in Jupyter notebooks.
To make them interactive, install ipympl
and load the corresponding
extension with %matplotlib widget
.
Plotly#
Plotly is a dictionary-oriented library that produces HTML-based outputs. Hence, Plotly is a very good choice for publishing nice interactive plots on webpages.
Plots are fully contained inside
Figure
objects, and can be nicely
displayed within Jupyter notebooks without further configuration.
To reuse an existing figure
object, you can do the same as with
the Matplotlib backend.
- dispatch(fun)[source]#
Transform a function into a backend dispatcher for plot functions.
- Parameters:
fun (
Callable
[[ParamSpec
(P
)],TypeVar
(T
,SceneCanvas
,Figure
,Figure
)]) – The callable that will register future dispatch functions for each backend implementation.- Return type:
Dispatcher
[ParamSpec
(P
),TypeVar
(T
,SceneCanvas
,Figure
,Figure
)]- Returns:
The same callable, wrapped in a
Dispatcher
class instance.
Examples
The following example shows how one can implement plotting utilities on different backends for a given plot.
>>> import differt.plotting as dplt >>> >>> @dplt.dispatch ... def plot_line(vertices, color): ... pass >>> >>> @plot_line.register("matplotlib") ... def _(vertices, color): ... print("Using matplotlib backend") >>> >>> @plot_line.register("plotly") ... def _(vertices, color): ... print("Using plotly backend") >>> >>> plot_line( ... _, ... _, ... backend="matplotlib", ... ) Using matplotlib backend >>> >>> plot_line( ... _, ... _, ... backend="plotly", ... ) Using plotly backend >>> >>> plot_line( ... _, ... _, ... backend="vispy", ... ) Traceback (most recent call last): NotImplementedError: No backend implementation for 'vispy' >>> >>> # The default backend is VisPy so unimplemented too. >>> plot_line(_, _) Traceback (most recent call last): NotImplementedError: No backend implementation for 'vispy' >>> >>> @plot_line.register("numpy") ... def _(vertices, color): ... pass Traceback (most recent call last): ValueError: Unsupported backend 'numpy', allowed values are: ...
- draw_image(data, x=None, y=None, z0=0.0, **kwargs)[source]#
Plot a 2D image on a 3D canvas, at using a fixed z-coordinate.
- Parameters:
data (
Num[ndarray, 'm n']
|Num[ndarray, 'm n 3']
|Num[ndarray, 'm n 4']
) – The image data array. Can be grayscale, RGB or RGBA. For more details on how the data is interpreted, please refer to the documentation of the function corresponding to the specified backend (see below).x (
Float[ndarray, '*m']
|None
) – The x-coordinates corresponding to first dimension of the image. Those coordinates will be used to scale and translate the image.y (
Float[ndarray, '*n']
|None
) – The y-coordinates corresponding to second dimension of the image. Those coordinates will be used to scale and translate the image.z0 (
float
) – The z-coordinate at which the image is placed.kwargs (
Any
) – Keyword arguments passed toMesh
,plot_trisurf
, orMesh3d
, depending on the backend.
- Return type:
SceneCanvas
|Figure
|Figure
- Returns:
The resulting plot output.
Warning
Matplotlib backend requires
data
to be either RGB or RGBA array.Examples
The following example shows how plot a 2-D image, without and with axis scaling.
>>> from differt.plotting import draw_image >>> >>> x = np.linspace(-1.0, +1.0, 100) >>> y = np.linspace(-4.0, +4.0, 200) >>> X, Y = np.meshgrid(x, y) >>> Z = np.sin(X) * np.cos(Y) >>> fig1 = draw_image(Z, backend="plotly") >>> fig1 >>> >>> fig2 = draw_image(Z, x=x, y=y, backend="plotly") >>> fig2
- draw_markers(markers, labels=None, text_kwargs=None, **kwargs)[source]#
Plot markers and, optionally, their label.
- Parameters:
markers (
Float[ndarray, 'num_markers 3']
) – The array of marker vertices.text_kwargs (
Mapping
[str
,Any
] |None
) –A mapping of keyword arguments passed to
Text
if VisPy backend is used.By default,
font_sise=1000
is used.kwargs (
Any
) – Keyword arguments passed toMarkers
, orScatter3d
, depending on the backend.
- Return type:
SceneCanvas
|Figure
|Figure
- Returns:
The resulting plot output.
Warning
Unsupported backend(s): Matplotlib.
Examples
The following example shows how to plot several annotated markers.
>>> from differt.plotting import draw_markers >>> >>> markers = np.array( ... [ ... [0.0, 0.0, 0.0], ... [1.0, 0.0, 0.0], ... [1.0, 1.0, 0.0], ... [0.0, 1.0, 0.0], ... ] ... ) >>> labels = ["A", "B", "C", "D"] >>> fig = draw_markers(markers, labels, backend="plotly") >>> fig
- draw_mesh(vertices, triangles, **kwargs)[source]#
Plot a 3D mesh made of triangles.
- Parameters:
vertices (
Float[ndarray, 'num_vertices 3']
) – The array of triangle vertices.triangles (
UInt[ndarray, 'num_triangles 3']
) – The array of triangle indices.kwargs (
Any
) – Keyword arguments passed toMesh
,plot_trisurf
, orMesh3d
, depending on the backend.
- Return type:
SceneCanvas
|Figure
|Figure
- Returns:
The resulting plot output.
Examples
The following example shows how to plot a pyramid mesh.
>>> from differt.plotting import draw_mesh >>> >>> vertices = np.array( ... [ ... [0.0, 0.0, 0.0], ... [1.0, 0.0, 0.0], ... [1.0, 1.0, 0.0], ... [0.0, 1.0, 0.0], ... [0.5, 0.5, 1.0], ... ] ... ) >>> triangles = np.array( ... [[0, 1, 2], [0, 2, 3], [0, 1, 4], [1, 2, 4], [2, 3, 4], [3, 0, 4]] ... ) >>> fig = draw_mesh(vertices, triangles, backend="plotly", opacity=0.5) >>> fig
- draw_paths(paths, **kwargs)[source]#
Plot a batch of paths of the same length.
- Parameters:
- Return type:
SceneCanvas
|Figure
|Figure
- Returns:
The resulting plot output.
Examples
The following example shows how to plot ten line strings.
>>> from differt.plotting import draw_paths >>> >>> def rotation(angle: float) -> np.ndarray: ... c = np.cos(angle) ... s = np.sin(angle) ... return np.array( ... [ ... [+c, -s, 0.0], ... [+s, +c, 0.0], ... [0.0, 0.0, 1.0], ... ] ... ) >>> >>> path = np.array( ... [ ... [0.0, 0.0, 0.0], ... [1.0, 0.0, 0.0], ... [1.0, 1.0, 0.0], ... [0.1, 0.1, 0.0], ... ], ... ) >>> paths = np.stack( ... [ ... path @ rotation(angle) + np.array([0.0, 0.0, 0.1 * dz]) ... for dz, angle in enumerate(np.linspace(0, 2 * np.pi, 10)) ... ] ... ) >>> fig = draw_paths( ... paths, ... backend="plotly", ... marker=dict(size=0, color="red"), ... line=dict(color="black", width=3), ... ) >>> fig
- process_matplotlib_kwargs(kwargs)[source]#
Process keyword arguments passed to some Matplotlib plotting utility.
- Parameters:
kwargs (
MutableMapping
[str
,Any
]) –A mutable mapping of keyword arguments passed to Matplotlib plotting.
Warning
The keys specified below will be removed from the mapping.
- Keyword Arguments:
Warning
When supplying both
figure
andax
, user must ensure thatax in figure.axes
evaluates toTrue
.
- process_plotly_kwargs(kwargs)[source]#
Process keyword arguments passed to some Plotly plotting utility.
- Parameters:
kwargs (
MutableMapping
[str
,Any
]) –A mutable mapping of keyword arguments passed to Plotly plotting.
Warning
The keys specified below will be removed from the mapping.
- Keyword Arguments:
figure (
Figure
) – The figure that draws contents of the scene.- Return type:
Figure
- Returns:
The figure used to display contents.
- process_vispy_kwargs(kwargs)[source]#
Process keyword arguments passed to some VisPy plotting utility.
- Parameters:
kwargs (
MutableMapping
[str
,Any
]) –A mutable mapping of keyword arguments passed to VisPy plotting.
Warning
The keys specified below will be removed from the mapping.
- Keyword Arguments:
convas (
SceneCanvas
) – The canvas that draws contents of the scene. If not provided, will try to access canvas fromview
(if supplied).view (
Viewbox
) – The view on which contents are displayed. If not provided, will try to get a view fromcanvas
(if supplied and has at least one view in its children).
Warning
When supplying both
canvas
andview
, user must ensure thatview in canvas.central_widget.children
evaluates toTrue
.- Return type:
- Returns:
The canvas and view used to display contents.
- reuse(**kwargs)[source]#
Create a context manager that will automatically reuse the current canvas / figure.
- Parameters:
args – Positional arguments passed to
set_defaults
.kwargs (
Any
) – Keywords arguments passed toset_defaults
.
- Return type:
Iterator
[SceneCanvas
|Figure
|Figure
]- Returns:
The canvas or figure that is reused for this context.
- set_defaults(backend=None, **kwargs)[source]#
Set default keyword arguments for future plotting utilities.
- Parameters:
- Return type:
- Returns:
The name of the (new) default backend.
- Raises:
ValueError – If the backend is not supported.
ImportError – If the backend is not installed.
Examples
The following example shows how to set the default plotting backend.
>>> import differt.plotting as dplt >>> >>> @dplt.dispatch ... def my_plot(): ... pass >>> >>> @my_plot.register("vispy") ... def _(): ... print("Using vispy backend") >>> >>> @my_plot.register("matplotlib") ... def _(): ... print("Using matplotlib backend") >>> >>> my_plot() # When not specified, use default backend Using vispy backend >>> >>> my_plot(backend="matplotlib") # We can force the backend Using matplotlib backend >>> >>> dplt.set_defaults("matplotlib") # Or change the default backend... 'matplotlib' >>> my_plot() # So that now it defaults to 'matplotlib' Using matplotlib backend >>> >>> my_plot(backend="vispy") # Of course, the 'vispy' backend is still available Using vispy backend
- use(*args, **kwargs)[source]#
Create a context manager that sets plotting defaults and returns the current default backend.
When exiting the context, the previous default backend and default keyword arguments are set back.
- Parameters:
args (
Any
) – Positional arguments passed toset_defaults
.kwargs (
Any
) – Keywords arguments passed toset_defaults
.
- Return type:
- Returns:
The name of the default backend used in this context.
- view_from_canvas(canvas)[source]#
Return the view from the specified canvas.
If the canvas does not have any view, create one and return it.
This utility is used by
process_vispy_kwargs
.- Parameters:
canvas (
SceneCanvas
) – The canvas that draws the contents of the scene.- Return type:
- Returns:
The view on which contents are displayed.