Visualizing data with matplotlib¶
Visualizations are a subjective matter: different people have different
tastes, and it is impossible to have one-size-fits-all solutions.
visualize_matplotlib comes with convenient functions to quickly
visualize data, but the module has default values that are opinionated. Where
possible, customization has been exposed for your convenience. However, some
settings and choices cannot be changed.
Time and frequency series in
kuibit can be plotted with
native functions. For example,
# Assuming rho_b is a TimeSeries import matplotlib.pyplot as plt plt.plot(rho_b)
The main way to visualize grid data is with the functions
plot_contourf. The first plots directly the values of the given
data, the second plots contours (filled). The functions support a large variety
NumPy arrays, with coordintes specified by the
UniformGridData: it will be plotted over the entire domain, unless the keywords
shapeare provided. These specify the extent of the grid to be plotted.
shapeis essentially the resolution of the plot. See documentation on grid data for details.
HierarchicalGridData: it will be plotted over the entire domain, with resolution provided by
shape. The keywords
x1can change the grid extent.
A table at the end of this document sums up these options.
x1 are all 2D lists or tuples.
The functions take additional arguments (for example, the labels for the axes). Details can be found in the reference material (Reference on kuibit.visualize_matplotlib).
Mask information will be lost upon resampling. If you want masks, you need to
UniformGridData you want to plot.
Plots can be enanched by adding a colorbar with
plot_contour() plots the contours without filling. It
requires the number of levels, or an array that specify where the levels are.
plot_components_boundaries(), you can plot the grid structure.
The function takes a
HierarchicalGridData as argument as plots its
grid structure. By defaults, ghost zones are not included, but they can be
remove_ghosts=False. The function plots the boundaries of the single
components, but when multiple components can be merged into a single refinement
level, then only the outer boundary is plotted (a notable case in which this is
currently not possible is when there are multiple refinement centers).
Apparent horizons can be plotted with
function takes the 2D shape of an horizon as returned by
There are two wrappers around this function to simplify plotting horizons on the
plot_horizon_on_plane_at_time(). These take an
OneHorizon object, the iteration/time that has to be plotted, and
the plane over which you are plotting. All these functions take also the color
of the horizon, the color of its boundary, and the opacity (
When you take a cross section (an outline) of an horizon,
points that are within a threshold to the plane that cuts the surface.
However, the way points are distributed on apparent horizons is highly
non-uniform. So, if you are cutting the horizon along an axis that is not one
of the coordinate ones (for the horizon), it is likely that too few points
will be close enough to the intersecting plane, resulting in a malformed or
absent outline. In some distant future,
kuibit will perform
interpolations to solve this problem.
The default settings in
matplotlib are not great (e.g., the text is
typically too small). The function
setup_matplotlib() sets some
better defaults. Since “better” is relative, the function takes an optional
params. This has to be dictionary with keys the parameters in
matplotlib and values their new values. This can be used to override some of
the defaults in
setup_matplotlib() simply updates the settings in
matplotlib. It does not have any other effect.
add_text_to_corner() annotates a figure adding a label.
The location of the label can be specified with the
node argument. This is
identified with cardinal point (N,S,W, or E) or a combination of two of them.
For example, the default behavior is to place the text in the bottom right
corner (corresponding to South-East–SE). The distance from the border can also
be customized by passing the
save() function saves the figure to file. The function takes the
path of the output and saves the current figure. If the file has extension
tikzplotlib instead of
matplotlib is used to save the
figure. This results in a PGFPlots/TikZ ASCII file ready to be compiled with
preprocess_plot and preprocess_plot_grid¶
from kuibit.visualize_matplotlib import preprocess_plot @preprocess_plot def my_plot(data, figure=None, axis=None): # My plotting, for example ax.plot(data)
preprocess_plot() is the following: if the user provides
axis, then those are used. If the user does not provide
those arguments, then the current one are used. This is roughly equivalent to
figure is None and if it is, then set
figure = plt.gcf().
The second decorator is
preprocess_plot_grid(). With this, you can
forget about all the classes defined in
kuibit and simply plot NumPy arrays.
In more details: when you work with
kuibit, you will typically work with
UniformGridData. These are
complex structures that cannot be plotted immediately. The decorator
preprocess_plot_grid() takes care of all the boilerplate needed to
work with those two classes so that the user can provide a
HierarchicalGridData, or a NumPy array. Let us see how it works:
from kuibit.visualize_matplotlib import preprocess_plot_grid @preprocess_plot_grid def my_plot(data, coordinates=None, figure=None, axis=None): # My plotting, for example ax.imshow(data) # bob here is a H5OneGridFunction # Some of the arguments are optional my_plot(bob, shape=[500, 500], iteration=0, x0=[0, 0], x1=[1,1]) # rho_b here is a HierarchicalGridData # Some of the arguments are optional my_plot(rho_b, shape=[500, 500], x0=[0, 0], x1=[1,1]) # press here is a UniformGridData # Some of the arguments are optional my_plot(press, x0=[0,0]) # eps here is a NumPy array my_plot(eps)
Depending on the type of object passed, additional arguments might be needed. See table below for details.
2D NumPy array