Convolution of bare arrays

Convolution of bare arrays#

As a basic building block, the API for bare arrays exists.

Before getting into how this works, we first needs to import a few things:

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import numpy as np
from xdggs.healpix import HealpixInfo

import healpix_convolution as hc
from healpix_convolution.plotting import plot_healpix

rng = np.random.default_rng(seed=0)

Global convolution#

We first define the grid and the data to convolve:

grid_info = HealpixInfo(level=3, indexing_scheme="nested")

cell_ids = np.arange(12 * 4**grid_info.level)
data = rng.normal(size=cell_ids.shape)

We also need a kernel:

_, kernel = hc.kernels.gaussian_kernel(
    cell_ids,
    grid_info=grid_info,
    sigma=0.5,
    kernel_size=5,
    weights_threshold=1e-8,
)
kernel
Formatcoo
Data Typefloat64
Shape(768, 768)
nnz18984
Density0.032185872395833336
Read-onlyTrue
Size444.9K
Storage ratio0.10

With all that, convolution is simply:

convolved = hc.convolve(data, kernel)
convolved.shape
(768,)

On a map:

fig, axes = plt.subplots(
    ncols=2, figsize=(16, 12), subplot_kw={"projection": ccrs.Robinson()}
)

plot_healpix(
    data, cell_ids, ax=axes[0], grid_info=grid_info, features=["coastlines"]
)
plot_healpix(
    convolved,
    cell_ids,
    ax=axes[1],
    grid_info=grid_info,
    features=["coastlines"],
)
<cartopy.mpl.geocollection.GeoQuadMesh at 0x7e54195213a0>
/home/docs/checkouts/readthedocs.org/user_builds/healpix-convolution/conda/stable/lib/python3.12/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/110m_physical/ne_110m_coastline.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
../_images/array_4_2.png

Regional convolution#

Similarly to above, we also first have to define the data:

grid_info = HealpixInfo(level=4, indexing_scheme="nested")

cell_ids = 4 * 4**grid_info.level + np.arange(4**grid_info.level)
data = rng.normal(size=cell_ids.shape)

and we can immediately define the kernel:

kernel_size = 5
_, kernel = hc.kernels.gaussian_kernel(
    cell_ids,
    grid_info=grid_info,
    sigma=0.5,
    kernel_size=kernel_size,
    weights_threshold=1e-10,
)
kernel
Formatcoo
Data Typefloat64
Shape(256, 392)
nnz6382
Density0.06359614158163265
Read-onlyTrue
Size149.6K
Storage ratio0.19

However, since we now have boundaries we have to pad the data before convolving:

padded_data = hc.pad(
    cell_ids,
    grid_info=grid_info,
    ring=kernel_size // 2,
    mode="constant",
    constant_value=0,
).apply(data)
padded_data.shape
(392,)

After that, convolving works as before (but on the padded data):

convolved = hc.convolve(padded_data, kernel)

Again, we can look at the result:

fig, axes = plt.subplots(
    ncols=2, figsize=(16, 12), subplot_kw={"projection": ccrs.Robinson()}
)

plot_healpix(
    data,
    cell_ids,
    ax=axes[0],
    grid_info=grid_info,
    features=["coastlines"],
    xsize=3000,
)
plot_healpix(
    convolved,
    cell_ids,
    ax=axes[1],
    grid_info=grid_info,
    features=["coastlines"],
    xsize=3000,
)
<cartopy.mpl.geocollection.GeoQuadMesh at 0x7e541a5004a0>
../_images/array_9_1.png