Plotting#
This section introduces UXarray’s plotting API, showcasing how to visualize both data variables and grid topology.
import uxarray as ux
Data#
For most of the examples in this notebook, we will be using a simple mesh consisting of 4 hexagons, with sample data mapped to the faces, edges, and nodes.
grid_path = "../../test/meshfiles/ugrid/quad-hexagon/grid.nc"
data_paths = [
"../../test/meshfiles/ugrid/quad-hexagon/random-node-data.nc",
"../../test/meshfiles/ugrid/quad-hexagon/random-edge-data.nc",
"../../test/meshfiles/ugrid/quad-hexagon/random-face-data.nc",
]
uxds = ux.open_mfdataset(grid_path, data_paths)
uxgrid = uxds.uxgrid
uxds
<xarray.UxDataset> Size: 312B Dimensions: (n_node: 16, n_edge: 19, n_face: 4) Dimensions without coordinates: n_node, n_edge, n_face Data variables: random_data_node (n_node) float64 128B dask.array<chunksize=(16,), meta=np.ndarray> random_data_edge (n_edge) float64 152B dask.array<chunksize=(19,), meta=np.ndarray> random_data_face (n_face) float64 32B dask.array<chunksize=(4,), meta=np.ndarray>
Grid Topology Visualization#
The topology (i.e. edges and coordinates) of an unstructured grid can be plotted using the Grid.plot()
accessor. By default, Grid.plot()
will plot the edges of the unstructured grid.
uxgrid.plot(title="Grid Plot Accessor")
Edge Plots#
The default plotting routine above calls the Grid.edges()
method, which visualizes the edges of each face in the unstructured grid.
uxgrid.plot.edges(color="black", title="Grid Edge Plot")
Point Plots#
There are three coordinates that are typically associated with unstructured grids:
Corner Nodes:
node_lon
&node_lat
Edge Centers:
edge_lon
&edge_lat
Face Centers:
face_lon
&face_lat
These coordinates can be plotted using the following plotting methods:
Corner Nodes:
Grid.plot.nodes()
Edge Centers:
Grid.plot.edge_centers()
Face Centers:
Grid.plot.face_centers()
(
uxgrid.plot.edges(color="black")
* uxgrid.plot.nodes(marker="o", size=150).relabel("Corner Nodes")
* uxgrid.plot.face_centers(marker="s", size=150).relabel("Face Centers")
* uxgrid.plot.edge_centers(marker="^", size=150).relabel("Edge Centers")
).opts(title="Grid Coordinates", legend_position="top_right")
Data Visualization#
Visualizing Data#
The section above visualized the topology an unstructured grid. If you are working with data residing on an unstructured grid, plotting is handled through the UxDataArray.plot()
accessor.
uxds["random_data_face"].plot(
cmap=ux.cmaps.diverging, title="UxDataArray Plot Accessor"
)
Polygons#
Face centered data can be visualized as polygons using the UxDataArray.polygons()
method. The geometry of each face is represented as a polygon, shaded with the data variable mapped to it.
(
uxds["random_data_face"].plot.polygons(
rasterize=False,
cmap=ux.cmaps.diverging,
title="Vector Polygons (rasterize=False)",
colorbar=False,
)
+ uxds["random_data_face"].plot.polygons(
rasterize=True,
cmap=ux.cmaps.diverging,
title="Raster Polygons (rasterize=True)",
colorbar=False,
)
).cols(1)
Points#
Since data can be mapped to either the nodes, edges, or faces of an unstructured grid, the coordinates at these locations can be shaded to represent the data. Data can be plotted as points using the UxDataArray.plot.points()
method.
(
uxds.uxgrid.plot(line_color="black")
* uxds["random_data_node"]
.plot.points(
cmap="inferno", size=150, marker="circle", clabel=None, tools=["hover"]
)
.relabel("Node Data")
* uxds["random_data_edge"]
.plot.points(
cmap="inferno", size=150, marker="square", clabel=None, tools=["hover"]
)
.relabel("Edge Data")
* uxds["random_data_face"]
.plot.points(
cmap="inferno", size=150, marker="triangle", clabel=None, tools=["hover"]
)
.relabel("Face Data")
).opts(title="Plotting Data as Points", legend_position="top_right")
Working with Periodic Data#
The grid used in the previous example is extremely simple, only consisting of 4 hexagons. When working with a periodic global grid, such as those from global climate model simulations, additional attention must be given to handling periodic elements (i.e. those that cross the antimeridian.
The periodic_elements
parameter can be used to select how to handle these elements.
periodic_elements='exclude'
: Periodic polygons are excluded from the final plotperiodic_elements='split'
: Periodic polygons are split along the antimeridianperiodic_elements='ignore'
: Periodic polygons are left uncorrected.
Warning
It is suggested to keep periodic_elements='exclude'
(default value) when working with moderatly large datasets, as there is a significant overhead needed correct the antimeridian faces.
base_path = "../../test/meshfiles/mpas/QU/"
grid_path = base_path + "oQU480.231010.nc"
uxds_mpas = ux.open_dataset(grid_path, grid_path)
(
uxds_mpas["bottomDepth"]
.plot(cmap=ux.cmaps.sequential_blue)
.opts(width=700, height=350, title="Default Plot (Excluding Periodic Elements)")
+ uxds_mpas["bottomDepth"]
.plot(
periodic_elements="split", cmap=ux.cmaps.sequential_blue, width=700, height=350
)
.opts(title="Include Periodic Elements (Split)")
).cols(1)