Field visualisation using pyvista#

Note: If you experience any problems in plotting with pyvista, please make sure you run the Jupyter notebook in Google Chrome.

There are several ways how a field can be visualised, using:

  • matplotlib -pyvista

  • holoviews

  • vtk-based libraries, e.g. pyvista

pyvista provides three-dimensional interactive plots of fields inside Jupyter notebook.

Let us say we have a sample, which is an ellipsoid

\[\frac{x^2}{a^2} + \frac{y^2}{b^2} + \frac{z^2}{c^2} <= 1\]

with \(a=5\,\text{nm}\), \(b=3\,\text{nm}\), and \(c=2\,\text{nm}\). The space is discretised into cells with dimensions \((0.5\,\text{nm}, 0.5\,\text{nm}, 0.5\,\text{nm})\). The value of the field at \((x, y, z)\) point is \((-cy, cx, cz)\), with \(c=10^{9}\). The norm of the field inside the cylinder is \(10^{6}\).

Let us first build that field.

[1]:
import discretisedfield as df

a, b, c = 5e-9, 3e-9, 2e-9
cell = (0.5e-9, 0.5e-9, 0.5e-9)

mesh = df.Mesh(p1=(-a, -b, -c), p2=(a, b, c), cell=cell)


def norm_fun(pos):
    x, y, z = pos
    if (x / a) ** 2 + (y / b) ** 2 + (z / c) ** 2 <= 1:
        return 1e6
    else:
        return 0


def value_fun(pos):
    x, y, z = pos
    c = 1e9
    return (-c * y, c * x, c * z)


field = df.Field(mesh, nvdim=3, value=value_fun, norm=norm_fun, valid="norm")

The most basic plot we can show is the plot of all the cells where the value is valid.

[2]:
field.pyvista.valid()

The plot is interactive, so it can be manipulated using a mouse. To change the color of voxels, we can pass the new color via color argument.

[3]:
field.pyvista.valid(color="red")

Next, we can plot a scalar field. For plotting a scalar field, we are using discretisedfield.Field.pyvista.scalar() method. This produces an interactive slice of the field.

[4]:
field.pyvista.scalar()

By default, this plots the last vdims. However, we can plot any vdims by using the scalars argument.

[5]:
field.pyvista.scalar(scalars="x")

Alternatively, we can also create a scalar field using discreitsedfield syntax and plot that.

[6]:
field.pyvista.scalar()

To further modify the plot, keyword arguments for pyvista.plotter.add_mesh function are accepted. Please refer to its documentation

Next, we can plot the vector field itself.

[7]:
field.pyvista.vector()

By cascading, we can plot its slice at \(x=0\).

[8]:
field.orientation.sel(x=(0, 0)).pyvista.vector()

To improve the understanding of the plot, we can colour the vectors plotted. For that, we need to tell it according to which the vectors will be coloured.

[9]:
field.pyvista.vector(scalars="x")

We can also colour by any field by using the color_field argument

[10]:
field.pyvista.vector(color_field=field.x**2)

Plotting a scalar can also be done using volume. The density and color within the volume represent the scalar value at each point.

[11]:
field.pyvista.volume()

Isosurfaces of a scalar field can also be plotted using contour

[12]:
field.pyvista.contour()

contour_scalars can be used to select the dimension for which the isosurfaces are plotted. If isosurfaces controls the number of isosurfaces plotted.

[13]:
field.pyvista.contour(isosurfaces=4, contour_scalars="x")

If isosurfaces is an iterable, then an isosurface will be plotted at each specific value.

[14]:
field.pyvista.contour(isosurfaces=[-6e5, 0.0, 2e5], contour_scalars="x")

Streamlines can also be plotted. However, it is common for the default values not to produce desired plots as the optimal values of the arguments can very unique to the specific field being plotted.

[15]:
field.pyvista.streamlines()

Multiple visualisation on the same plot#

Sometimes, it is necessary to show, for example, multiple planes of the sample on the same plot. This can be done by exposing the pyvista.Plotter and passing it to different plotting methods. For instance.

[16]:
import pyvista

plotter = pyvista.Plotter()
field.pyvista.vector(plotter=plotter, scalars="y", cmap="hsv")
field.pyvista.contour(plotter=plotter, isosurfaces=4, contour_scalars="x")
plotter.show()