Query Disc Functions#
This module provides functions for querying pixels within circular regions on the sphere, essential for astronomical applications involving point sources, aperture photometry, and local analysis.
Query disc implementation for HEALPix spherical disc queries.
- jax_healpy._query_disc.query_disc(nside, vec, radius, inclusive=False, fact=4, nest=False, max_length=None)[source]#
Find pixels within a disc on the sphere.
This function supports both single and batched queries. It is fully JIT-compatible and differentiable with respect to vec and radius parameters.
- Parameters:
nside (int) – The resolution parameter of the HEALPix map
vec (array-like) – Either a single three-component unit vector (3,) defining the center of the disc, or a batch of vectors (B, 3) defining B disc centers
radius (float) – The radius of the disc in radians
inclusive (bool, optional) – If False (default), return pixels whose centers lie within the disc. Results are guaranteed to match healpy exactly for inclusive=False. If True, return all pixels that overlap with the disc. Note: inclusive=True may produce slightly different results compared to healpy due to algorithm differences in determining pixel overlap.
fact (int, optional) – For inclusive queries, the pixelization factor (default: 4)
nest (bool, optional) – If True, assume NESTED pixel ordering, otherwise RING ordering (default: False)
max_length (int, optional) – Maximum number of pixels to return per disc. If None, defaults to npix. For batched inputs, this limits memory usage by returning (max_length, B) instead of (npix, B).
- Returns:
ipix – For single vector input (3,): returns (max_length,) or (npix,) if max_length is None For batch vector input (B, 3): returns (max_length, B) Pixels outside the disc are marked as npix (sentinel value). This allows direct indexing like: map.at[disc].set(value)
- Return type:
array
- Raises:
NotImplementedError – If nest=True (nested ordering not yet supported)
Notes
This function currently only supports RING ordering. The function is JIT-compatible and differentiable when compiled with static_argnums=(0,) for the nside parameter. The returned array has fixed size for JIT compatibility - pixels outside the disc have value npix.
When indexing a JAX array, pixels outside the disc should be ignored. If indexing a numpy array, this will raise an out-of-bounds error.
Examples
Single disc query:
>>> import jax_healpy as hp >>> import jax.numpy as jnp >>> import jax >>> nside = 16 >>> vec = jnp.array([1.0, 0.0, 0.0]) # Point on equator >>> radius = 0.1 # ~5.7 degrees >>> disc = hp.query_disc(nside, vec, radius) >>> # Use directly for indexing >>> map = jnp.zeros(hp.nside2npix(nside)) >>> map = map.at[disc].set(1.0)
Batch disc query:
>>> vecs = jnp.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) # (2, 3) - two centers >>> discs = hp.query_disc(nside, vecs, radius, max_length=1000) # (1000, 2) >>> # Each column contains pixels for one disc >>> map1 = map.at[discs[:, 0]].set(1.0) # First disc >>> map2 = map.at[discs[:, 1]].set(2.0) # Second disc
For JIT compilation:
>>> jit_query_disc = jax.jit( ... lambda n, v, r: hp.query_disc(n, v, r) ... ) >>> disc_jit = jit_query_disc(nside, vec, radius)
- jax_healpy._query_disc.estimate_disc_pixel_count(nside, radius)[source]#
Estimate number of pixels in a disc of given radius.
Uses the analytical approximation: n_approx = 6 * nside^2 * (1 - cos(radius))
This approximation is exact at radius = π (full sphere) and loses precision for smaller radii. It provides a good estimate for setting the max_length parameter in query_disc functions.
- Parameters:
- Returns:
pixel_count – Estimated number of pixels in the disc
- Return type:
Notes
The approximation assumes uniform pixel density across the sphere, which is accurate for large discs but less precise for small discs where pixel shape variations matter more.
Examples
>>> import jax_healpy as hp >>> nside = 64 >>> radius = 0.1 # ~5.7 degrees >>> estimated_count = hp.estimate_disc_pixel_count(nside, radius) >>> # Use as max_length for query_disc >>> actual_disc = hp.query_disc(nside, [1, 0, 0], radius, max_length=estimated_count)
- jax_healpy._query_disc.estimate_disc_radius(nside, pixel_count)[source]#
Estimate radius needed for a disc containing given pixel count.
Inverse of estimate_disc_pixel_count. Uses the analytical relationship: radius = arccos(1 - pixel_count / (6 * nside^2))
- Parameters:
- Returns:
radius – Estimated disc radius in radians
- Return type:
Notes
This is the inverse of estimate_disc_pixel_count and has the same accuracy characteristics: exact at full sphere, less precise for small discs.
Examples
>>> import jax_healpy as hp >>> nside = 64 >>> target_pixels = 1000 >>> estimated_radius = hp.estimate_disc_radius(nside, target_pixels) >>> # Verify the relationship >>> back_pixels = hp.estimate_disc_pixel_count(nside, estimated_radius) >>> abs(back_pixels - target_pixels) < 10 # Should be close True
Disc Query Functions#
- jax_healpy.query_disc(nside, vec, radius, inclusive=False, fact=4, nest=False, max_length=None)[source]#
Find pixels within a disc on the sphere.
This function supports both single and batched queries. It is fully JIT-compatible and differentiable with respect to vec and radius parameters.
- Parameters:
nside (int) – The resolution parameter of the HEALPix map
vec (array-like) – Either a single three-component unit vector (3,) defining the center of the disc, or a batch of vectors (B, 3) defining B disc centers
radius (float) – The radius of the disc in radians
inclusive (bool, optional) – If False (default), return pixels whose centers lie within the disc. Results are guaranteed to match healpy exactly for inclusive=False. If True, return all pixels that overlap with the disc. Note: inclusive=True may produce slightly different results compared to healpy due to algorithm differences in determining pixel overlap.
fact (int, optional) – For inclusive queries, the pixelization factor (default: 4)
nest (bool, optional) – If True, assume NESTED pixel ordering, otherwise RING ordering (default: False)
max_length (int, optional) – Maximum number of pixels to return per disc. If None, defaults to npix. For batched inputs, this limits memory usage by returning (max_length, B) instead of (npix, B).
- Returns:
ipix – For single vector input (3,): returns (max_length,) or (npix,) if max_length is None For batch vector input (B, 3): returns (max_length, B) Pixels outside the disc are marked as npix (sentinel value). This allows direct indexing like: map.at[disc].set(value)
- Return type:
array
- Raises:
NotImplementedError – If nest=True (nested ordering not yet supported)
Notes
This function currently only supports RING ordering. The function is JIT-compatible and differentiable when compiled with static_argnums=(0,) for the nside parameter. The returned array has fixed size for JIT compatibility - pixels outside the disc have value npix.
When indexing a JAX array, pixels outside the disc should be ignored. If indexing a numpy array, this will raise an out-of-bounds error.
Examples
Single disc query:
>>> import jax_healpy as hp >>> import jax.numpy as jnp >>> import jax >>> nside = 16 >>> vec = jnp.array([1.0, 0.0, 0.0]) # Point on equator >>> radius = 0.1 # ~5.7 degrees >>> disc = hp.query_disc(nside, vec, radius) >>> # Use directly for indexing >>> map = jnp.zeros(hp.nside2npix(nside)) >>> map = map.at[disc].set(1.0)
Batch disc query:
>>> vecs = jnp.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) # (2, 3) - two centers >>> discs = hp.query_disc(nside, vecs, radius, max_length=1000) # (1000, 2) >>> # Each column contains pixels for one disc >>> map1 = map.at[discs[:, 0]].set(1.0) # First disc >>> map2 = map.at[discs[:, 1]].set(2.0) # Second disc
For JIT compilation:
>>> jit_query_disc = jax.jit( ... lambda n, v, r: hp.query_disc(n, v, r) ... ) >>> disc_jit = jit_query_disc(nside, vec, radius)
Disc Estimation Functions#
- jax_healpy.estimate_disc_pixel_count(nside, radius)[source]#
Estimate number of pixels in a disc of given radius.
Uses the analytical approximation: n_approx = 6 * nside^2 * (1 - cos(radius))
This approximation is exact at radius = π (full sphere) and loses precision for smaller radii. It provides a good estimate for setting the max_length parameter in query_disc functions.
- Parameters:
- Returns:
pixel_count – Estimated number of pixels in the disc
- Return type:
Notes
The approximation assumes uniform pixel density across the sphere, which is accurate for large discs but less precise for small discs where pixel shape variations matter more.
Examples
>>> import jax_healpy as hp >>> nside = 64 >>> radius = 0.1 # ~5.7 degrees >>> estimated_count = hp.estimate_disc_pixel_count(nside, radius) >>> # Use as max_length for query_disc >>> actual_disc = hp.query_disc(nside, [1, 0, 0], radius, max_length=estimated_count)
Estimate the number of pixels within a circular disc on the sphere.
- jax_healpy.estimate_disc_radius(nside, pixel_count)[source]#
Estimate radius needed for a disc containing given pixel count.
Inverse of estimate_disc_pixel_count. Uses the analytical relationship: radius = arccos(1 - pixel_count / (6 * nside^2))
- Parameters:
- Returns:
radius – Estimated disc radius in radians
- Return type:
Notes
This is the inverse of estimate_disc_pixel_count and has the same accuracy characteristics: exact at full sphere, less precise for small discs.
Examples
>>> import jax_healpy as hp >>> nside = 64 >>> target_pixels = 1000 >>> estimated_radius = hp.estimate_disc_radius(nside, target_pixels) >>> # Verify the relationship >>> back_pixels = hp.estimate_disc_pixel_count(nside, estimated_radius) >>> abs(back_pixels - target_pixels) < 10 # Should be close True
Estimate the angular radius needed to contain a given number of pixels.
Find all pixels within a circular region on the sphere.
This function identifies all HEALPix pixels whose centers lie within a circular region defined by a center direction and angular radius.
Parameters#
- nsideint
HEALPix resolution parameter
- vecarray_like
Unit vector pointing to the disc center, shape (3,)
- radiusfloat
Angular radius of the disc in radians
- inclusivebool, optional
If True, include pixels that are partially within the disc. If False, only include pixels whose centers are within the disc. Default: False
- factint, optional
Factor for subdividing pixels when inclusive=True. Higher values give more accurate results but are slower. Default: 4
- nestbool, optional
If True, return pixel indices in NESTED ordering. If False, return in RING ordering. Default: False
Returns#
- pixelsarray_like
Array of pixel indices within the specified disc
Examples#
Basic disc query:
import jax.numpy as jnp import jax_healpy as hp # Define disc center (North pole) center_vec = jnp.array([0.0, 0.0, 1.0]) # Query pixels within 10 degree radius radius = jnp.radians(10.0) # Convert to radians nside = 64 pixels = hp.query_disc(nside, center_vec, radius) print(f"Found {len(pixels)} pixels in disc")
Using angular coordinates:
# Convert from theta, phi to unit vector theta, phi = jnp.radians(45.0), jnp.radians(30.0) # 45° from pole, 30° azimuth center_vec = hp.ang2vec(theta, phi) # Query with inclusive boundary pixels = hp.query_disc(nside, center_vec, radius, inclusive=True)
Batch processing multiple discs:
# Define multiple disc centers centers = jnp.array([ [0.0, 0.0, 1.0], # North pole [1.0, 0.0, 0.0], # X-axis [0.0, 1.0, 0.0] # Y-axis ]) # Query each disc all_pixels = [] for center in centers: pixels = hp.query_disc(nside, center, radius) all_pixels.append(pixels)
Mathematical Background#
The query_disc function finds pixels whose centers satisfy:
where \(\vec{v}_{\text{center}}\) is the disc center unit vector and \(\vec{v}_{\text{pixel}}\) is the pixel center unit vector.
For inclusive queries, the function also considers pixels that are partially within the disc boundary by subdividing pixel boundaries and checking if any subdivision points fall within the disc.
Applications#
Common use cases for disc queries include:
Point Source Analysis
# Find pixels around a known source position
source_ra, source_dec = 83.6331, 22.0145 # Crab Nebula (degrees)
# Convert to HEALPix coordinates
theta = jnp.radians(90.0 - source_dec) # Convert Dec to colatitude
phi = jnp.radians(source_ra)
source_vec = hp.ang2vec(theta, phi)
# Query 1-degree radius around source
aperture_radius = jnp.radians(1.0)
source_pixels = hp.query_disc(nside, source_vec, aperture_radius)
Aperture Photometry
# Extract flux within aperture
sky_map = jnp.random.normal(0, 1, hp.nside2npix(nside))
aperture_pixels = hp.query_disc(nside, source_vec, aperture_radius)
aperture_flux = jnp.sum(sky_map[aperture_pixels])
print(f"Total flux in aperture: {aperture_flux}")
Local Statistics
# Compute local statistics around multiple positions
positions = jnp.array([
hp.ang2vec(jnp.radians(30), jnp.radians(0)),
hp.ang2vec(jnp.radians(60), jnp.radians(90)),
hp.ang2vec(jnp.radians(90), jnp.radians(180))
])
local_stats = []
for pos in positions:
pixels = hp.query_disc(nside, pos, aperture_radius)
local_mean = jnp.mean(sky_map[pixels])
local_std = jnp.std(sky_map[pixels])
local_stats.append((local_mean, local_std))
Masking and Exclusion
# Create exclusion mask around bright sources
bright_sources = [
hp.ang2vec(jnp.radians(45), jnp.radians(0)),
hp.ang2vec(jnp.radians(135), jnp.radians(90))
]
exclusion_mask = jnp.ones(hp.nside2npix(nside))
exclusion_radius = jnp.radians(5.0) # 5-degree exclusion
for source in bright_sources:
excluded_pixels = hp.query_disc(nside, source, exclusion_radius)
exclusion_mask = exclusion_mask.at[excluded_pixels].set(0)
Performance Considerations#
Query disc is optimized for GPU execution when JAX is configured with CUDA/ROCm
Performance scales with disc size and resolution (nside)
For many small discs, consider batching operations:
@jax.jit
def batch_query_disc(nside, centers, radius):
# Vectorized implementation for multiple discs
return jax.vmap(lambda c: hp.query_disc(nside, c, radius))(centers)
The inclusive parameter significantly affects computation time
For very large discs (> 60°), consider alternative approaches
Accuracy Notes#
Standard queries (inclusive=False) are exact for pixel centers
Inclusive queries provide better boundary accuracy at computational cost
Higher fact values in inclusive mode improve accuracy but slow computation
For critical applications, validate results against known geometric cases
See Also#
jax_healpy.ang2vec(): Convert angular coordinates to unit vectorsjax_healpy.pix2vec(): Get unit vectors for pixel centersjax_healpy.get_interp_weights(): For interpolation within regions