Visualizing the spherical harmonics#

The real spherical harmonics \(Y_l^m(\theta, \varphi)\) form an orthonormal basis on the sphere. This notebook constructs and plots them by applying the inverse SHT to unit basis vectors in spectral space.

Setup#

import torch
import matplotlib.pyplot as plt

from torch_harmonics import RealSHT, InverseRealSHT
from torch_harmonics.plotting import plot_sphere

Forming the Vandermonde matrix#

The Vandermonde matrix maps spectral coefficients to grid values. Each column corresponds to a single spherical harmonic \(Y_l^m\). We construct it by applying the ISHT to each canonical basis vector \(e_{l,m}\) in the coefficient space.

For negative orders \(m < 0\), the real spherical harmonics are recovered by placing the basis vector in the imaginary part of the \(|m|\) coefficient.

nlat = 60
nlon = 2*nlat
lmax = mmax = nlat

sht = RealSHT(nlat, nlon, lmax=lmax, mmax=mmax)
isht = InverseRealSHT(nlat, nlon, lmax=lmax, mmax=mmax)
# forming the Vandermonde matrix

nmodes = int(lmax * lmax)
e = torch.zeros(nmodes, lmax, mmax, dtype=torch.complex64)

midx = lambda l,m : l*(l+1) + m

for l in range(lmax):
    for m in range(-l, l+1):
        e[midx(l,m), l, abs(m)] = 1.0 if m >= 0 else 1.0j

vdm = isht(e)

Plotting the spherical harmonics#

We plot the first few spherical harmonics on a grid indexed by degree \(l\) (rows) and order \(m\) (columns). Each subplot shows an orthographic projection of the sphere:

import os
os.makedirs("plots", exist_ok=True)

plt_lmax = 3

fig = plt.figure(layout='constrained', figsize=(12, 8))
subfigs = fig.subfigures(plt_lmax, 2*plt_lmax-1)

for l in range(plt_lmax):
    for m in range(-l, l+1):
        plot_sphere(vdm[midx(l,m)], fig=subfigs[l, m+plt_lmax-1], projection="orthographic", title=f"l={l}, m={m}", central_latitude=20, central_longitude=30, cmap="plasma")

plt.savefig("./plots/spherical_harmonics.png")
../_images/01918413393bd3380b85c8f5de9bc0d657288bcde0141be9567be8849b054005.png

Animated version (optional)#

The following cells generate a rotating animation of the spherical harmonics. Uncomment to run:

# import matplotlib.animation as animation

# fig = plt.figure(layout='constrained', figsize=(12, 8), dpi=72)
# subfigs = fig.subfigures(plt_lmax, plt_lmax)

# moviewriter = animation.writers['pillow'](fps=30)
# moviewriter.setup(fig, './plots/spherical_harmonics.gif', dpi=72)
# for frame in range(120):
#     # compute the rotation of the sphere
#     lon = -120 - 3 * frame

#     if frame % 10 == 0:
#         print(f"frame={frame}")

#     for l in range(plt_lmax):
#         for m in range(l+1):
#             plot_sphere(vdm[midx(l,m)], fig=subfigs[l, m], projection="orthographic", title=f"l={l}, m={m}", central_longitude=lon)

#     plt.draw()
#     moviewriter.grab_frame()

# moviewriter.finish()