furax.math
Modules:
-
bspline– -
quaternion–Functions for quaternion operations using JAX.
-
sht–Operators for spherical harmonic transforms backed by jax-healpy.
furax.math.bspline
Functions:
-
cubic_bspline–Cubic cardinal B-spline, support [0,4).
-
spline_basis–Dense cubic B-spline basis on
K = n_knots + 2uniform knots. -
spline_window–Banded form of
spline_basis: the 4 nonzero knots under each sample.
cubic_bspline(u)
Cubic cardinal B-spline, support [0,4).
Source code in src/furax/math/bspline.py
spline_basis(times, n_knots)
Dense cubic B-spline basis on K = n_knots + 2 uniform knots.
Returns:
-
B(Float[Array, 'k samp']) –(K, N) basis matrix,
B[j] = cubic_bspline(position - j + 1).
Source code in src/furax/math/bspline.py
spline_window(times, n_knots)
Banded form of spline_basis: the 4 nonzero knots under each sample.
A cubic B-spline reaches only 4 consecutive knots, so each sample's column of
spline_basis has just 4 nonzero entries. This returns those directly, avoiding the
mostly-zero `(K, N) matrix (seefurax.mapmaking.templates.WindowedBasis`).
Returns:
-
offset(Int[Array, ' samp']) –(N,) index of the first of the 4 knots, clamped to
[0, K - 4]. -
weights(Float[Array, 'samp 4']) –(N, 4) the B-spline values at knots
offset + 0..3; weights of knots whose support misses the sample (at the time-range edges) are exactly zero.
Source code in src/furax/math/bspline.py
furax.math.quaternion
Functions for quaternion operations using JAX.
This module provides vectorized functions for multiplying quaternions, and rotating 3D vectors by quaternions.
We use scalar-vector storage, i.e. (1,i,j,k) with the scalar part first.
Functions:
-
euler–The quaternion representing an Euler rotation.
-
qmul–Compute quaternion multiplication.
-
qrot–Rotate vector by quaternion.
-
qrot_zaxis–Rotate the Z axis [0,0,1] by a given quaternion.
-
qrot_xaxis–Rotate the X axis [1,0,0] by a given quaternion.
-
to_polarization_angle_cos_sin–Compute cos and sin of the polarization angle from the rotation quaternion.
-
to_polarization_angle–Compute the polarization angle from the rotation quaternion using the COSMO convention.
euler(axis, angle)
The quaternion representing an Euler rotation.
For example, if axis=2 the computed quaternion(s) will have components:
Parameters:
-
axis(int) –The index of the cartesian axis of the rotation (x, y, z). Must be 0, 1, or 2.
-
angle(Float[Array, ...]) –Angle of rotation, in radians.
Returns:
-
Quat–Quaternion array of shape (..., 4).
Source code in src/furax/math/quaternion.py
qmul(q1, q2)
Compute quaternion multiplication.
Source code in src/furax/math/quaternion.py
qrot(q, vec)
qrot_zaxis(q)
Rotate the Z axis [0,0,1] by a given quaternion.
Source code in src/furax/math/quaternion.py
qrot_xaxis(q)
Rotate the X axis [1,0,0] by a given quaternion.
Source code in src/furax/math/quaternion.py
to_polarization_angle_cos_sin(q)
Compute cos and sin of the polarization angle from the rotation quaternion.
Equivalent to (cos(pa), sin(pa)) where pa = to_polarization_angle(q),
but avoids transcendental functions by using quaternion algebra directly.
See to_polarization_angle for the definition and convention.
Source code in src/furax/math/quaternion.py
to_polarization_angle(q)
Compute the polarization angle from the rotation quaternion using the COSMO convention.
The polarization angle is measured from the South through the East.
The rotation quaternion q transforms detector coordinates to celestial (equatorial) coordinates.
In detector coordinates:
- The detector points in the z direction.
- The detector is sensitive to electric fields in the x direction.
After applying the rotation:
- The vector v identifies the point on the equatorial sphere where the detector is pointing.
- The vector u defines the polarization-sensitive direction, tangent to the unit sphere at v.
The unit vector toward the South in the tangent plane is:
- w = -z - (-z · v) v
The polarization angle pa between w and u is computed as:
- cos(pa) = w · u = -u_z (since u · v = 0)
- sin(pa) = (w × u) · v = (u × v) · w = (v × u) · z = v_x u_y - v_y u_x
- Therefore, pa = atan2(v_x u_y - v_y u_x, -u_z)
Parameters:
-
q(Quat) –Rotation quaternion array of shape (*dims, 4).
Returns:
-
Ang–Polarization angle array of shape (*dims).
Source code in src/furax/math/quaternion.py
furax.math.sht
Operators for spherical harmonic transforms backed by jax-healpy.
The two core operators are:
Map2Alm: analysis transform (pixel map → spherical harmonic coefficients).Alm2Map: synthesis transform (spherical harmonic coefficients → pixel map).
Both operators accept PyTree inputs whose leaves are 2-D arrays of shape
(nfreq, npix) or (nfreq, lmax+1, 2*lmax+1). A 1-D leaf is promoted to 2-D via
jnp.atleast_2d before processing so that single-frequency inputs work
without special-casing.
SHTRule registers an algebraic simplification so that the composition
Map2Alm @ Alm2Map (synthesis followed by analysis) is reduced to an
IdentityOperator at operator-construction time.
Classes:
-
Map2Alm–Analysis spherical harmonic transform: pixel map → alm coefficients.
-
Alm2Map–Synthesis spherical harmonic transform: alm coefficients → pixel map.
-
SHTRule–Algebraic rule reducing
Map2Alm @ Alm2Mapto an identity.
Map2Alm
dataclass
Bases: AbstractLinearOperator
Analysis spherical harmonic transform: pixel map → alm coefficients.
Each leaf of the input PyTree must be a 2-D array of shape
(nfreq, npix). A 1-D leaf is silently promoted to (1, npix) via
jnp.atleast_2d. The transform are applied to all frequency rows,
via jhp.map2alm producing an output leaf of shape
(nfreq, lmax+1, 2*lmax+1).
Construction is guarded by a hasattr check against jax_healpy:
if jhp.map2alm is missing (e.g. on an older jax-healpy release),
instantiation raises ImportError.
Attributes:
-
lmax(int) –Maximum spherical harmonic degree.
-
nside(int) – -
iter(int) –Number of iterations for the map2alm solver; more iterations, which are more expensive, yield more accurate alm coefficients. (default is 3)
-
pol(bool) –Reserved for the polarization-aware SHT. Routed to
jhp.map2almbut onlyFalseis supported today; passingTrueraisesNotImplementedErrorat construction.
Examples:
>>> import jax.numpy as jnp
>>> from furax.math.sht import Map2Alm
>>> from furax.obs.stokes import StokesIQU
>>> nside, lmax, nfreq = 32, 63, 3
>>> npix = 12 * nside ** 2
>>> structure = StokesIQU.structure_for((nfreq, npix), jnp.float64)
>>> op = Map2Alm(lmax=lmax, nside=nside, in_structure=structure)
Methods:
-
__post_init__– -
mv–Apply the analysis SHT to every leaf of x.
-
inverse–Return the pseudo-inverse operator
Alm2Map.
Source code in src/furax/math/sht.py
lmax = field(metadata={'static': True})
class-attribute
instance-attribute
nside = field(metadata={'static': True})
class-attribute
instance-attribute
iter = field(default=3, metadata={'static': True})
class-attribute
instance-attribute
pol = field(default=False, metadata={'static': True})
class-attribute
instance-attribute
__post_init__()
Source code in src/furax/math/sht.py
mv(x)
Apply the analysis SHT to every leaf of x.
Parameters:
-
x(PyTree[Inexact[Array, ' _a']]) –Input PyTree whose leaves have shape
(nfreq, npix)or(npix,)for a single frequency.
Returns:
-
PyTree[Inexact[Array, ' _b']]–PyTree with the same structure as x; each leaf has shape
-
PyTree[Inexact[Array, ' _b']]–(nfreq, lmax+1, 2*lmax+1)and complex dtype.
Source code in src/furax/math/sht.py
inverse()
Return the pseudo-inverse operator Alm2Map.
Returns:
-
Alm2Map–An
Alm2Mapwhosein_structurematches the output -
Alm2Map–structure of this operator (i.e. alm space).
Source code in src/furax/math/sht.py
Alm2Map
dataclass
Bases: AbstractLinearOperator
Synthesis spherical harmonic transform: alm coefficients → pixel map.
Each leaf of the input PyTree must be a 2-D array of shape
(nfreq, lmax+1, 2*lmax+1). A 2-D leaf (lmax+1, 2*lmax+1) is
silently reshaped to (1, lmax+1, 2*lmax+1) via reshape(-1, ...),
handling the single-frequency case without branching. The transform are applied
to all frequency rows, via jhp.alm2map producing an output leaf of shape
(nfreq, npix) where npix = 12 * nside ** 2.
Construction is guarded by a hasattr check against jax_healpy:
if jhp.alm2map is missing (e.g. on an older jax-healpy release),
instantiation raises ImportError.
Attributes:
-
lmax(int) –Maximum spherical harmonic degree.
-
nside(int) –HEALPix resolution parameter used by the synthesis step.
-
iter(int) –Number of iterations for the map2alm solver used by the inverse. (Default is 3)
-
pol(bool) –Reserved for the polarization-aware SHT. Routed to
jhp.alm2mapbut onlyFalseis supported today; passingTrueraisesNotImplementedErrorat construction.
Examples:
>>> import jax.numpy as jnp
>>> from furax.math.sht import Alm2Map
>>> from furax.obs.stokes import StokesIQU
>>> nside, lmax, nfreq = 32, 63, 3
>>> structure = StokesIQU.structure_for((nfreq, lmax+1, 2*lmax+1), jnp.complex128)
>>> op = Alm2Map(lmax=lmax, nside=nside, in_structure=structure)
Methods:
-
__post_init__– -
mv–Apply the synthesis SHT to every leaf of x.
-
inverse–Return the pseudo-inverse operator
Map2Alm.
Source code in src/furax/math/sht.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | |
lmax = field(metadata={'static': True})
class-attribute
instance-attribute
nside = field(metadata={'static': True})
class-attribute
instance-attribute
iter = field(default=3, metadata={'static': True})
class-attribute
instance-attribute
pol = field(default=False, metadata={'static': True})
class-attribute
instance-attribute
__post_init__()
Source code in src/furax/math/sht.py
mv(x)
Apply the synthesis SHT to every leaf of x.
Parameters:
-
x(PyTree[Inexact[Array, ' _a']]) –Input PyTree whose leaves have shape
(nfreq, lmax+1, 2*lmax+1)or(lmax+1, 2*lmax+1,)for a single frequency.
Returns:
-
PyTree[Inexact[Array, ' _b']]–PyTree with the same structure as x; each leaf has shape
-
PyTree[Inexact[Array, ' _b']]–(nfreq, npix)and real dtype.
Source code in src/furax/math/sht.py
inverse()
Return the pseudo-inverse operator Map2Alm.
Returns:
-
Map2Alm–A
Map2Almwhosein_structurematches the output -
Map2Alm–structure of this operator (i.e. map space).
Source code in src/furax/math/sht.py
SHTRule
Bases: AbstractCompositionRule
Algebraic rule reducing Map2Alm @ Alm2Map to an identity.
The composition analysis after synthesis (Map2Alm @ Alm2Map) is
exact when the band-limit lmax is consistent with the HEALPix
resolution nside, so the rule collapses it to an
IdentityOperator on the alm input space.
The reverse composition Alm2Map @ Map2Alm is a band-limited
projection, not an identity, and is therefore not reduced.
Methods:
-
apply–Reduce
left @ rightto an identity when the pair is Map2Alm/Alm2Map.
Attributes:
Source code in src/furax/math/sht.py
left_operator_class = Map2Alm
class-attribute
instance-attribute
right_operator_class = Alm2Map
class-attribute
instance-attribute
apply(left, right)
Reduce left @ right to an identity when the pair is Map2Alm/Alm2Map.
Parameters:
-
left(AbstractLinearOperator) –Left operator in the composition (must be
Map2Alm). -
right(AbstractLinearOperator) –Right operator in the composition (must be
Alm2Map).
Returns:
-
list[AbstractLinearOperator]–A single-element list containing an
-
list[AbstractLinearOperator]–IdentityOperatoron the alm input space.
Raises:
-
NoReduction–If the operator pair does not match the expected types or if the transforms use different
lmaxvalues.