Zonal Averaging#

This section demonstrates how to perform Zonal Averaging using UXarray.

import numpy as np

import uxarray as ux

uxds = ux.open_dataset(
    "../../test/meshfiles/ugrid/outCSne30/outCSne30.ug",
    "../../test/meshfiles/ugrid/outCSne30/outCSne30_vortex.nc",
)
uxds["psi"].plot(cmap="inferno", periodic_elements="split")

What is a Zonal Average/Mean?#

A zonal average (or zonal mean) is a statistical measure that represents the average of a variable along one or more lines of constant latitude. In other words, it’s the mean value calculated around the sphere at constant latitudes.

UXarray currently implements a non-conservative Zonal Mean, which weights candidate faces by the length of intersection of a line of constant latitude.

zonal_mean_psi = uxds["psi"].zonal_mean()
zonal_mean_psi
<xarray.UxDataArray 'psi_zonal_mean' (latitudes: 19)> Size: 152B
array([1.08546247, 1.09219987, 1.10863654, 1.10011333, 1.04989243,
       1.03074397, 1.01980815, 1.01312147, 0.9973705 , 1.00000001,
       1.00262952, 0.98687854, 0.98019186, 0.96925608, 0.95010754,
       0.89988665, 0.89136345, 0.90780013, 0.91453753])
Coordinates:
  * latitudes  (latitudes) int64 152B -90 -80 -70 -60 -50 -40 ... 50 60 70 80 90
Attributes:
    zonal_mean:  True

The default latitude range is between -90 and 90 degrees with a step size of 10 degrees.

(zonal_mean_psi.plot.line() * zonal_mean_psi.plot.scatter(color="red")).opts(
    title="Zonal Average Plot (Default)", xticks=np.arange(-90, 100, 20), xlim=(-95, 95)
)

The range of latitudes can be modified by using the lat parameter. It accepts:

  • Single scalar: e.g., lat=45

  • List/array: e.g., lat=[10, 20] or lat=np.array([10, 20])

  • Tuple: e.g., (min_lat, max_lat, step)

zonal_mean_psi_large = uxds["psi"].zonal_mean(lat=(-90, 90, 1))
(
    zonal_mean_psi_large.plot.line()
    * zonal_mean_psi_large.plot.scatter(color="red", s=1)
).opts(
    title="Zonal Average Plot (Larger Sample)",
    xticks=np.arange(-90, 100, 20),
    xlim=(-95, 95),
)

Combined Plots#

It is often desired to plot the zonal average along side other plots, such as color or contour plots.

(
    uxds["psi"].plot(
        cmap="inferno",
        periodic_elements="split",
        height=250,
        width=500,
        colorbar=False,
        ylim=(-90, 90),
    )
    + zonal_mean_psi.plot.line(
        x="psi_zonal_mean",
        y="latitudes",
        height=250,
        width=150,
        ylabel="",
        ylim=(-90, 90),
        xlim=(0.8, 1.2),
        xticks=[0.8, 0.9, 1.0, 1.1, 1.2],
        yticks=[-90, -45, 0, 45, 90],
        grid=True,
    )
).opts(title="Combined Zonal Average & Raster Plot")