healpix_analyse.up ================== .. py:module:: healpix_analyse.up .. autoapi-nested-parse:: up.py ===== HEALPix resolution-increase operator for the ``healpix_analyse`` package. Increases the HEALPix resolution by a factor of 2: nside_out = nside_in * 2 N_out = N_in * 4 The operation is defined as the *adjoint* (transpose) of the smooth downsampling matrix from :mod:`healpix_analyse.down`, with an optional diagonal normalisation that improves round-trip consistency. Works on the full sphere or on a partial-sky subset. Resolution is exposed through the Grid4Earth ``level`` convention, with ``nside = 2**level``. Accepts numpy arrays or torch tensors of shape ``[N]`` or ``[B, N]`` and returns an output of the same type and number of dimensions. Dependencies: numpy, torch, healpy. Attributes ---------- .. autoapisummary:: healpix_analyse.up.ArrayLike Classes ------- .. autoapisummary:: healpix_analyse.up.HealPixUp Module Contents --------------- .. py:data:: ArrayLike .. py:class:: HealPixUp(level: int, radius_deg: Optional[float] = None, sigma_deg: Optional[float] = None, weight_norm: str = 'l1', up_norm: str = 'col_l1', eps: float = 1e-12, ellipsoid: str = 'WGS84', cell_ids: Optional[ArrayLike] = None, device: Optional[Union[str, torch.device]] = None, dtype: torch.dtype = torch.float32, paired_down: Optional[healpix_analyse.down.HealPixDown] = None) Bases: :py:obj:`torch.nn.Module` HEALPix upsampling: increase resolution by a factor of 2. Implements the *adjoint* of the smooth downsampling operator from :class:`healpix_analyse.down.HealPixDown`: x_up = M^T @ x where ``M`` is the (N_coarse × N_fine) downsampling matrix. Optional diagonal normalisation modes improve amplitude preservation for constant fields or local energy: - ``"adjoint"`` -- raw transpose (M^T x). - ``"col_l1"`` -- divide by column sums of M: preserves constant fields when ``HealPixDown`` used ``weight_norm="l1"``. - ``"diag_l2"`` -- divide by diagonal of M^T M: least-squares diagonal preconditioner (local amplitude correction). :Parameters: * **level** (:py:class:`int`) -- Coarse input Grid4Earth/HEALPix level (integer ≥ 0). Internally, ``nside_in = 2**level`` and the output level is ``level + 1``. * **radius_deg** (:py:class:`float` or :py:obj:`None`) -- Angular radius passed to :class:`~healpix_analyse.down.HealPixDown` for building the transpose matrix. ``None`` → default. * **sigma_deg** (:py:class:`float` or :py:obj:`None`) -- Gaussian sigma (degrees). ``None`` → default. * **weight_norm** (``{"l1", "l2", "none"}``, *default* ``"l1"``) -- Weight normalisation used when building the downsampling matrix. Must match the norm used by the paired :class:`HealPixDown`. * **up_norm** (``{"adjoint", "col_l1", "diag_l2"}``, *default* ``"col_l1"``) -- Diagonal normalisation applied after the transpose: *adjoint* -- no normalisation. *col_l1* -- preserve constant fields. *diag_l2* -- preserve local energy. * **eps** (:py:class:`float`, *default* ``1e-12``) -- Small value added to the denominator to avoid division by zero. * **cell_ids** (:py:class:`array-like` of :py:class:`int` or :py:obj:`None`) -- Coarse pixel indices (NESTED) for partial-sky operation. If ``None``, the operator covers the full sphere. * **device** (:py:class:`torch.device` or :py:class:`str` or :py:obj:`None`) -- Device for computation. Defaults to CUDA if available, else CPU. * **dtype** (:py:class:`torch.dtype`, *default* :py:class:`torch.float32`) -- Floating-point dtype for the sparse matrix values. * **paired_down** (:py:class:`HealPixDown` or :py:obj:`None`) -- Reuse the exact sparse matrix and fine-cell domain of an existing smooth downsampler. This is the strictest way to construct a matched Up operator for a partial patch. ``cell_ids`` must then be omitted; the ellipsoid and weight normalisation are inherited. .. admonition:: Examples Full sphere: >>> import numpy as np >>> from healpix_analyse.up import HealPixUp >>> level = 5 >>> nside = 2**level >>> x = np.random.randn(12 * nside**2) # [N_coarse] >>> up = HealPixUp(level=level) >>> y, cell_ids_out = up(x) >>> y.shape (49152,) # 12 * 64**2 Partial sky: >>> import healpy as hp >>> cell_ids_coarse = hp.query_disc(nside, hp.ang2vec(np.pi/2, 0), 0.3, nest=True) >>> up = HealPixUp(level=level, cell_ids=cell_ids_coarse) >>> y, fine_ids = up(x[cell_ids_coarse]) .. py:attribute:: device .. py:attribute:: dtype :value: Ellipsis .. py:attribute:: ellipsoid .. py:attribute:: weight_norm .. py:attribute:: level_in .. py:attribute:: level_out .. py:attribute:: level .. py:attribute:: nside_in .. py:attribute:: nside_out .. py:attribute:: N_in_full .. py:attribute:: N_out_full .. py:attribute:: up_norm :value: '' .. py:attribute:: eps .. py:property:: cell_ids_out :type: numpy.ndarray Output cell ids (fine-resolution NESTED indices). .. py:method:: forward(x: ArrayLike) -> Tuple[ArrayLike, numpy.ndarray] Apply the upsampling operator. :Parameters: **x** (:py:class:`numpy.ndarray` or :py:class:`torch.Tensor`, :py:class:`shape [N]` or :py:class:`[B`, :py:class:`N]`) -- Input map(s) at coarse resolution ``nside_in``. When ``cell_ids`` was given at construction, ``N`` must equal ``len(cell_ids)``. Otherwise ``N = 12 * nside_in**2``. :returns: * **y** (:py:class:`same type as x`, :py:class:`shape [N_out]` or :py:class:`[B`, :py:class:`N_out]`) -- Upsampled map(s) at fine resolution ``nside_out = nside_in * 2``. * **cell_ids_out** (:py:class:`np.ndarray`) -- NESTED pixel indices of the output pixels at ``nside_out``.