Skip to main content

jht — JAX Harmonic Transforms

JAX-native spherical harmonic transforms (map ↔ aₗₘ): GPU-capable, fully differentiable, and minimal-dependency — pure JAX + NumPy at runtime, no compiled C++ extension and no third-party SHT library, so it installs with pip and needs no build toolchain. Scoped to spin-0 and spin-2 fields on the HEALPix RING pixelization, validated to nside ≤ 4096 / ℓ_max ≲ 6000 (the recursion is numerically exact far beyond; nside ≤ 2048 is the routine-gated regime, nside = 8192 the compile ceiling), with both on-grid (pixel) and off-grid (arbitrary-pointing) transforms.

Reach for jht when you need spherical harmonic transforms that run on a GPU, differentiate end-to-end, and whose numerics you can read and own. The rationale and the accuracy boundary versus a C++ production transform are in docs/design.md.

What it does

Validated by a gated suite (float64) against healpy and ducc0:

  • On-grid transforms — spin-0 & spin-2 synthesis (aₗₘ→map), its exact adjoint Sᵀ, and a weighted + Jacobi-iterated inverse (analysis, aka map2alm), to machine precision versus healpy and ducc0.
  • Off-grid (NUFFT) — evaluate a band-limited field at arbitrary pointings (spin 0–3), differentiable in both the aₗₘ and the pointings.
  • Differentiable — native JAX autodiff throughout (jacfwd ≡ jacrev, tight adjoint identity), plus a convention-clean real-DOF layer (synthesis_real / analysis_real on-grid, synthesis_general_real off-grid) with no complex-conjugate subtlety.
  • GPU — pure JAX, so every transform runs on CUDA with no code change; measured GPU==CPU parity ~1e-13 (fp64) through nside=2048.
  • Partial-sky — masked pseudo-aₗₘ, a cut-sky CG deconvolution, and a masked Wiener filter / constrained realization, with an optional preconditioner and convergence diagnostics (SolveInfo).
  • Accuracy — jht's own ring quadrature weights + iteration reach ~1e-13 on band-limited maps (matching healpy.map2alm(use_weights=True)).

Install

Released on PyPI as jaxht (the import name stays jht):

pip install jaxht        # then:  import jht

Runtime dependencies are just jax + numpy. To track the repo directly:

pip install "jaxht @ git+https://github.com/jrcheshire/jht.git"

Development uses pixi:

pixi install          # CPU env (osx-arm64 / linux-64)
pixi run test         # the gated suite (parity vs healpy + ducc0)
pixi run -e gpu python scripts/gpu_check.py   # GPU parity check on an NVIDIA box

Quick start

float64 is opt-in per entry point — enable it before creating any array (library code never touches the global config):

import jax
jax.config.update("jax_enable_x64", True)
import jax.numpy as jnp
import jht

nside, lmax = 256, 512
m = jnp.asarray(my_map)                       # your (12*nside**2,) HEALPix RING map (spin 0)

alm = jht.analysis(m, nside, lmax, niter=3)   # map -> aₗₘ  (healpy-packed; weighted + iterated)
cl  = jht.bandpower(alm, lmax)                # angular auto-power C_ℓ
m2  = jht.synthesis(alm, nside, lmax)         # aₗₘ -> map  (round-trips m)

# off-grid: evaluate the same aₗₘ at arbitrary pointings (theta, phi)
loc = jnp.stack([theta, phi], axis=-1)        # (npts, 2)
f   = jht.synthesis_general(alm, loc, lmax=lmax)

spin=2 takes/returns (E, B) aₗₘ of shape (2, …) and (Q, U) maps of shape (2, npix). jht.adjoint_synthesis is the exact unweighted transpose Sᵀ (the operator seam / VJP), distinct from analysis (the approximate inverse). For gradient-based work use the real-DOF layer jht.synthesis_real / jht.analysis_real (plain ℝⁿ→ℝᵐ — no complex-conjugate convention to track).

Conventions

healpy m-major triangular aₗₘ packing, orthonormal Yₗₘ with the Condon–Shortley phase, HEALPix-internal (COSMO) polarization — verified against healpy 1.19.0 and ducc0 0.41.0. Pinned in docs/design.md.

Accuracy

HEALPix has no sampling theorem, so any HEALPix SHT is approximate. jht targets the tier where the ~1e-3 sampling floor is acceptable; its ring quadrature weights + Jacobi iteration close that to ~1e-13 on band-limited inputs. It is not a drop-in for a purity-critical (~1e-4) production pipeline. Tolerances are a-priori and gate-driven, never relaxed without sign-off; residual mismatches are logged in DISCREPANCIES.md. Full contract and the weight-solve algorithm: docs/accuracy.md.

Performance

Pure JAX runs unchanged on CUDA. Measured on A100 (incl. a 20 GB MIG) / V100, fp64:

  • GPU==CPU parity ~1e-13 through nside=2048 (synthesis and analysis).
  • Forward synthesis 14–60× the 8-core CPU; fp64/fp32 ≈ 2.2×.
  • Off-grid forward ~0.5–0.9 s at ℓ_max=1000 — independent of the number of points (recursion-bound) — with the pointing gradient ~1× a forward.
  • nside=2048 compiles and runs on a ~20 GB GPU slice (synthesis + analysis); the one-time compile is multi-minute (jit-cached).

The recurring GPU lesson: fp64/complex scatters are catastrophic on GPU, so jht packs and assembles via gathers. CPU perf model + memory: docs/performance.md; GPU detail: docs/gpu.md.

Using jht as a dependency

jht is standalone and consumer-agnostic; runtime deps are just jax + numpy. The operator / gradient seam a downstream needs — and the accuracy boundary — are documented in docs/consumers.md. Any backend-selection wiring lives in the consumer, not here.

Docs

Metadata

Release files for jaxht 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jaxht 0.4.0
File Size Uploaded Provenance Actions
jaxht-0.4.0.tar.gz 213.2 kB With provenance Details for jaxht-0.4.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for jaxht 0.4.0
File Interpreter ABI Platform Actions
jaxht-0.4.0-py3-none-any.whl Python 3 none any Details for jaxht-0.4.0-py3-none-any.whl

Total release size: 267.9 kB

Release files / jaxht-0.4.0.tar.gz

Download URL jaxht-0.4.0.tar.gz
Size 213.2 kB
Tags Source
SHA-256 checksum
How to use checksums
e059ae204faaa92adee23f20bdd225fc296a578ec77810f0795681e4f771cffd
BLAKE2b-256 checksum
How to use checksums
861f629ccc122300bee63621b5b0ee681dd41684c944afeea45f9aec74d6def1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / jaxht-0.4.0-py3-none-any.whl

Download URL jaxht-0.4.0-py3-none-any.whl
Size 54.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
81c6825231a46a18ee03b5ac09fdd18759a76207aaff9e8ed9ea23b2ae884529
BLAKE2b-256 checksum
How to use checksums
cd3cb194fb1ba79789e25573d1af65b91a74b0c61d1adfb318d4f6ca7c7655f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Security for jaxht 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for jaxht-0.4.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page