Source code for brutus.dust.extinction

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Extinction and coordinate utilities for dust mapping.

This module provides utilities for coordinate transformations and
extinction calculations used in 3D dust mapping.
"""

import healpy as hp  # type: ignore
import numpy as np

__all__ = ["lb2pix"]


[docs] def lb2pix(nside, l, b, nest=True): # noqa: E741 """ Convert Galactic (l, b) coordinates to HEALPix pixel indices. Parameters ---------- nside : int The HEALPix nside parameter. Must be a power of 2. l : float or array_like Galactic longitude in degrees. b : float or array_like Galactic latitude in degrees. nest : bool, optional Whether to use nested pixel ordering instead of ring ordering. Default is True. Returns ------- pix_ids : int or ndarray HEALPix pixel indices corresponding to the input (l, b) coordinates. Invalid coordinates (absolute b > 90°) return -1. Examples -------- >>> # Single coordinate >>> pix = lb2pix(nside=64, l=0.0, b=0.0) >>> isinstance(pix, int) True >>> # Multiple coordinates >>> l_arr = np.array([0.0, 90.0, 180.0]) >>> b_arr = np.array([0.0, 30.0, -30.0]) >>> pix_arr = lb2pix(nside=64, l=l_arr, b=b_arr) >>> len(pix_arr) == 3 True >>> # Invalid coordinate >>> invalid_pix = lb2pix(nside=64, l=0.0, b=95.0) >>> invalid_pix == -1 True """ # Rename to avoid E741 (ambiguous variable 'l') gal_l = l # Convert angles to spherical coordinates theta = np.radians(90.0 - b) phi = np.radians(gal_l) # Handle scalar inputs if not hasattr(gal_l, "__len__"): # Check for valid coordinate if (b < -90.0) or (b > 90.0): return -1 # Query HEALPix pixel pix_idx = hp.pixelfunc.ang2pix(nside, theta, phi, nest=nest) return int(pix_idx) # Handle array inputs - use broadcasting l_arr = np.asarray(gal_l) b_arr = np.asarray(b) # Use numpy broadcasting to handle different shapes try: l_broadcast, b_broadcast = np.broadcast_arrays(l_arr, b_arr) theta_broadcast, phi_broadcast = np.broadcast_arrays(theta, phi) except ValueError as e: raise ValueError( f"Coordinate arrays have incompatible shapes: l.shape={l_arr.shape}, b.shape={b_arr.shape}" ) from e # Initialize output array with broadcast shape pix_idx = np.empty(l_broadcast.shape, dtype="i8") # Mask for valid coordinates valid_idx = (b_broadcast >= -90.0) & (b_broadcast <= 90.0) # Compute pixels for valid coordinates pix_idx[valid_idx] = hp.pixelfunc.ang2pix( nside, theta_broadcast[valid_idx], phi_broadcast[valid_idx], nest=nest ) # Set invalid coordinates to -1 pix_idx[~valid_idx] = -1 return pix_idx