Source code for hats.pixel_math.healpix_shim

from __future__ import annotations

import math

import astropy.units as u
import cdshealpix
import numpy as np
from astropy.coordinates import Latitude, Longitude, SkyCoord

# pylint: disable=missing-function-docstring

## Arithmetic conversions


[docs] MAX_HEALPIX_ORDER = 29
[docs] def is_order_valid(order: int) -> bool: return np.all(0 <= order) and np.all(order <= MAX_HEALPIX_ORDER)
[docs] def npix2order(npix: int) -> int: if npix <= 0: raise ValueError("Invalid value for npix") order = int(math.log2(npix / 12)) >> 1 if not is_order_valid(order) or not 12 * (1 << (2 * order)) == npix: raise ValueError("Invalid value for npix") return order
[docs] def order2nside(order: int) -> int: if not is_order_valid(order): raise ValueError("Invalid value for order") return 1 << order
[docs] def order2npix(order: int) -> int: if not is_order_valid(order): raise ValueError("Invalid value for order") return 12 * (1 << (2 * order))
[docs] def order2resol(order: int, *, arcmin: bool = False, unit=u.rad) -> float: if arcmin: unit = u.arcmin unit = u.Unit(unit) return np.sqrt(order2pixarea(order, unit=unit * unit))
[docs] def order2pixarea(order: int, *, degrees: bool = False, unit=u.sr) -> float: if degrees: unit = "deg**2" unit = u.Unit(unit) npix = order2npix(order) pix_area_rad = 4 * np.pi / npix * u.steradian return pix_area_rad.to_value(unit)
[docs] def radec2pix(order: int, ra: float, dec: float) -> np.ndarray[np.int64]: if not is_order_valid(order): raise ValueError("Invalid value for order") ra = Longitude(np.asarray(ra, dtype=np.float64), unit="deg") dec = Latitude(np.asarray(dec, dtype=np.float64), unit="deg") return cdshealpix.lonlat_to_healpix(ra, dec, order).astype(np.int64)
## Coordinate conversion
[docs] def ang2vec(ra, dec, **kwargs) -> np.ndarray: """Converts ra and dec to cartesian coordinates on the unit sphere""" coords = SkyCoord(ra=ra * u.deg, dec=dec * u.deg, **kwargs).cartesian return np.array([coords.x.value, coords.y.value, coords.z.value]).T
## Custom functions
[docs] def avgsize2mindist(avg_size: np.ndarray) -> np.ndarray: """Get the minimum distance between pixels for a given average size We don't have the precise geometry of the healpix grid yet, so we are using average_size / mininimum_distance = 1.6 as a rough estimate. Parameters ---------- avg_size : np.ndarray of float The average size of a healpix pixel Returns ------- np.ndarray of float The minimum distance between pixels for the given average size """ return avg_size / 1.6
[docs] def mindist2avgsize(mindist: np.ndarray | float) -> np.ndarray | float: """Get the average size for a given minimum distance between pixels We don't have the precise geometry of the healpix grid yet, so we are using average_size / mininimum_distance = 1.6 as a rough estimate. Parameters ---------- mindist : np.ndarray of float | float The minimum distance between pixels Returns ------- np.ndarray of float | float The average size of a healpix pixel for the given minimum distance between pixels. """ return mindist * 1.6
[docs] def avgsize2order(avg_size_arcmin: np.ndarray | float) -> np.ndarray | int: """Get the largest order with average healpix size larger than avg_size_arcmin Parameters ---------- avg_size_arcmin : np.ndarray of float | float The average size of a healpix pixel in arcminutes Returns ------- np.ndarray of int | int The largest healpix order for which the average size is larger than avg_size_arcmin """ avg_size_arcmin = np.asarray(avg_size_arcmin) order_float = np.log2(np.sqrt(np.pi / 3) / np.radians(avg_size_arcmin / 60.0)) return np.clip(order_float.astype(np.int64), a_min=0, a_max=29)
[docs] def margin2order(margin_thr_arcmin: np.ndarray) -> np.ndarray: """Get the largest order for which distance between pixels is less than margin_thr_arcmin We don't have the precise geometry of the healpix grid yet, we are using average_size / mininimum_distance = 1.6 as a rough estimate. Parameters ---------- margin_thr_arcmin : np.ndarray of float The minimum distance between pixels in arcminutes Returns ------- np.ndarray of int The largest healpix order for which the distance between pixels is less than margin_thr_arcmin """ avg_size_arcmin = mindist2avgsize(margin_thr_arcmin) return avgsize2order(avg_size_arcmin)
[docs] def order2mindist(order: np.ndarray | int) -> np.ndarray | float: """Get the estimated minimum distance between pixels at a given order. We don't have the precise geometry of the healpix grid yet, we are using average_size / mininimum_distance = 1.6 as a rough estimate. Parameters ---------- order : np.ndarray of int | int The healpix order Returns ------- np.ndarray of float | float The minimum distance between pixels in arcminutes """ pixel_avgsize = order2resol(order, arcmin=True) return avgsize2mindist(pixel_avgsize)