Visualizing Grid Topology#
Authors: Philip Chmielowiec
Overview#
This usage example showcases how to use UXarray’s plotting API to visualize the topology of an unstructured grid (i.e., the elements that make up a grid). The majority of this notebook uses the Primal Mesh of an MPAS Ocean Grid, with the final example using an MPAS Atmosphere Grid.
Note
UXarray’s Plotting API is build around the Holoviews package. For details about customization and accepted parameters, pleases refer to their documentation.
import uxarray as ux
from holoviews import opts
base_path = "../../test/meshfiles/mpas/QU/"
grid_path = base_path + "oQU480.231010.nc"
uxds = ux.open_dataset(grid_path, grid_path)
grid = uxds.uxgrid
Using the Grid.plot()
Accessor#
Each Grid
object is initialized with a plotting accessor, which enables plotting routines to be called directly on the object. By default, calling .plot()
on a Grid
instance plots all the edges of a grid.
grid.plot(title="Default Grid Plot Method", height=350, width=700)
Since all of our plotting methods are built around the Holoviews package, you can select between Matplotlib and Bokeh backends if desired (Bokeh is the default and is suggested).
grid.plot(backend="matplotlib", title="Default Grid Plot Method with Matplotlib Backend", fig_size=200)
Since each UxDataArray
and UxDataset
is paired with a Grid
objected through the .uxgrid
attribute, the same function calls can be executed
uxds.uxgrid.plot(title="Default Plot Method through uxgrid Accessor", height=350, width=700)
Visualizing Grid Elements#
As described in previous sections, a Grid
is composed of nodes and edges that connect to create our unstructured grid. These elements can be visualized directly through a Grid
instance.
grid.plot.nodes(title="Node Plot", size=1, height=350, width=700)
grid.plot.edges(title="Edge Plot", height=350, width=700)
Since the edge plot above outlines the geometry of our mesh, another way to call it is through the plot.mesh()
call. Both plot.mesh()
and plot.edges()
takes in an optional argument called exclude_antimeridian
, which generates the visualuzation with or without correcting polygons that cross at the antimeridian (+- 180 longitude)
grid.plot.mesh(exclude_antimeridian=True, height=350, width=700)
Zooming in and overlaying both the edge and node plots together shows us the relationship between how the nodes are connected to form edges and faces.
(grid.plot.edges(color="Black") * \
grid.plot.nodes(color="Red", size=5)).opts(xlim = (-150,-90), ylim = (20, 50), height=350, width=700, title="Nodes and Edges")
Visualization Grid Coordinates (Nodes, Edge Centers, & Face Centers)#
We saw above that Nodes are plotted as points using latitude and longitude coordinates. In addition to nodes, one may want to visualize other coordinates, such as face centers or edge centers. Since these elements are also represented in terms of the latitude and longitude, we can also plot them as points like we did with the Nodes.
(uxds.uxgrid.plot.mesh(color="Black", line_dash='dashed', line_width=2, exclude_antimeridian=False) * \
uxds.uxgrid.plot.nodes(color = "Red", size=4) * \
uxds.uxgrid.plot.face_centers(color = "Blue", size=4) * \
uxds.uxgrid.plot.edge_centers(color = "Green", size=4)).opts(title="Node, Edge, & Face Coordinates", xlim=(-150,-90), ylim=(20, 50), width=700, height=350)
You can also plot each of these elements using the plot.node_coords()
, plot.face_coords()
, and plot.edge_coords()
methods, which are equivalent to the ones shown above.
( uxds.uxgrid.plot.mesh(color="Black", line_dash='dashed', line_width=2, exclude_antimeridian=False) * \
uxds.uxgrid.plot.node_coords(color = "Red", size=4) * \
uxds.uxgrid.plot.face_coords(color = "Blue", size=4) * \
uxds.uxgrid.plot.edge_coords(color = "Green", size=4)).opts(title="Node, Edge, & Face Coordinates", xlim=(-150,-90), ylim=(20, 50), width=700, height=350)
MPAS Voronoi Mesh#
The dataset used in the examples above is an MPAS Ocean Mesh, which as of the most recent release can only be loaded correctly using the Primal Mesh in UXarray. The following mesh is taken from the atmospheric component of MPAS, which covers the whole surface of the earth, and can be properly loaded in with UXarray in both the Primal and Dual formats.
base_path = "../../test/meshfiles/mpas/QU/"
grid_path = base_path + "mesh.QU.1920km.151026.nc"
primal_grid = ux.open_grid(grid_path, use_dual=False)
dual_grid = ux.open_grid(grid_path, use_dual=True)
We can plot the Nodes and Edges of both the Primal and Dual meshes together to form a Voronoi Mesh, which can be read about here.
(primal_grid.plot.edges(color="Blue", line_width=2) * \
primal_grid.plot.nodes(color="Blue", size=10) * \
dual_grid.plot.edges(color="Red", line_width = 2) * \
dual_grid.plot.nodes(color="Red", size=10)).opts(title="MPAS Primal & Dual Mesh", xlim=(-50, 50), ylim=(-25, 25), width=700, height=350)