foscat.HealBili#

HealBili: Bilinear weights from a curvilinear (theta, phi) source grid to arbitrary HEALPix targets.

This module provides a class HealBili that, given a curvilinear source grid of angular coordinates (theta[y,x], phi[y,x]) on the sphere (e.g., a tangent-plane grid built on an ellipsoid), computes bilinear interpolation weights to map values from that grid onto arbitrary target directions specified by HEALPix angles (heal_theta[n], heal_phi[n]).

Key idea#

Because the source grid is not rectilinear in index-space, we cannot assume a simple affine mapping from (i,j) to angles. Instead, for each target direction (theta_h, phi_h), we:

  1. locate a nearby source cell (seed) by nearest neighbor search on the unit sphere;

  2. consider up to 4 candidate quads around the seed: [(i0,j0),(i0+1,j0),(i0,j0+1),(i0+1,j0+1)];

  3. project the 4 corner unit vectors and the target onto a local tangent plane built at the quad barycenter;

  4. invert the bilinear mapping f(s,t) from the quad corners to the plane point using Newton, retrieving (s,t) in [0,1]^2;

  5. build the 4 bilinear weights [(1-s)(1-t), s(1-t), (1-s)t, st] and the 4 linear indices into the source image (row-major, j*W + i).

If no candidate quad cleanly contains the point, we choose the one with the smallest residual in the plane and clamp (s,t) to [0,1].

The code is NumPy-only by default, but can optionally use scipy.spatial.cKDTree for a faster nearest neighbor seed search by setting prefer_kdtree=True (falls back automatically if SciPy is absent).

Usage#

>>> hb = HealBili(src_theta, src_phi, prefer_kdtree=True)
>>> I, W = hb.compute_weights(heal_theta, heal_phi)
>>> # Apply to a source image `img` of shape (H,W):
>>> vals = hb.apply_weights(img, I, W)  # shape (N,)

All angles must be in radians. theta is colatitude (0 at north pole), phi is longitude in [0, 2*pi).

Classes#

HealBili

Compute bilinear interpolation weights from a curvilinear (theta, phi) grid to HEALPix targets.

Module Contents#

class foscat.HealBili.HealBili(src_theta: numpy.ndarray, src_phi: numpy.ndarray, *, prefer_kdtree: bool = False)[source]#

Compute bilinear interpolation weights from a curvilinear (theta, phi) grid to HEALPix targets.

Parameters:
  • src_theta (np.ndarray, shape (H, W)) – Source colatitude (radians) at each grid node.

  • src_phi (np.ndarray, shape (H, W)) – Source longitude (radians) at each grid node.

  • prefer_kdtree (bool, default False) – If True and SciPy is available, use cKDTree on unit vectors for a faster nearest-neighbor seed. Falls back to blocked brute-force dot-product search otherwise.

src_theta#
src_phi#
prefer_kdtree = False#
compute_weights(level, cell_ids: numpy.ndarray) Tuple[numpy.ndarray, numpy.ndarray][source]#

Compute bilinear weights/indices for target HEALPix angles.

Parameters:

cell_ids (np.ndarray, shape (N,)) – Target cell_ids .

Returns:

  • I (np.ndarray, shape (4, N), dtype=int64) – Linear indices of the 4 source corners per target (row-major: j*W + i). Invalid corners are -1.

  • W (np.ndarray, shape (4, N), dtype=float64) – Bilinear weights aligned with I. Weights are set to 0.0 for invalid corners and normalized to sum to 1 when at least one corner is valid.

apply_weights(img: numpy.ndarray, I: numpy.ndarray, W: numpy.ndarray) numpy.ndarray[source]#

Apply precomputed (I, W) to a source image to obtain values at the HEALPix targets.

Parameters:
  • img (np.ndarray, shape (H, W)) – Source image values defined on the same grid as (src_theta, src_phi).

  • I (np.ndarray, shape (4, N), dtype=int64) – Linear indices (row-major) of corner samples; -1 for invalid corners.

  • W (np.ndarray, shape (4, N), dtype=float64) – Bilinear weights aligned with I.

Returns:

vals (np.ndarray, shape (N,)) – Interpolated values at the target directions.