Source code for astrowisp.psf_base

"""Defines a base class for all PSF models: PSFBase."""

from abc import ABC, abstractmethod

import numpy

[docs] class PSFBase(ABC): """The base class for all supported PSFs."""
[docs] @abstractmethod #(x, y) is a reasonable way to specify the components of an offset vector. #pylint: disable=invalid-name def __call__(self, x, y): """ Return the value of the PSF at the given point. Args: x: The horizontal offset from center of the point at which to return the PSF value. y: The vertical offset from center of the point at which to return the PSF value. Returns: The value of the PSF at (x, y) relative to the source center. """
#pylint: enable=invalid-name
[docs] @abstractmethod def get_left_range(self): """Return how far the PSF extends to the left of center."""
[docs] @abstractmethod def get_right_range(self): """Return how far the PSF extends to the right of center."""
[docs] @abstractmethod def get_down_range(self): """Return how far the PSF extends downward of center."""
[docs] @abstractmethod def get_up_range(self): """Return how far the PSF extends upward of center."""
[docs] @abstractmethod def integrate(self, *, center_x, center_y, width, height, circle_radius=None): """ Return integrals of the PSF over circle-rectangle overlaps. Args: center_x(float or array): The x coordinate(s) of the center(s) of the rectangle(s) to integrate over. center_y(float or array): The y coordinate(s) of the center(s) of the rectangle(s) to integrate over. width(float or array): The width(s) of the rectangle(s). height(float or array): The height(s) of the rectangle(s). circle_radius(float or array): The rad(ii/us) of the circle(s). For zero entries or None, the integral is over the full rectangle(s). Returns: float or array: The integral of the PSF over the specified area(s). """
[docs] def predict_pixel(self, center_x, center_y, subpix_map=numpy.array([[1.0]])): """ Predict the value(s) of pixel(s) assuming a pixel sensitivity map. Args: center_x(float or array): The offset(s) of the center(s) of the pixels from the source position in the x direction. center_y(float or array): The offset(s) of the center(s) of the pixels from the source position in the y direction. subpix_map(2-D array): The pixel sensitivity map to assume. Returns: float or array: The integral(s) of product of the PSF and the sub-pixel sensitivity map over pixel(s) located as specified relative to the source center. """ if isinstance(center_x, numpy.ndarray): if not isinstance(center_y, numpy.ndarray): center_y = numpy.full(center_x.shape, center_y) else: if isinstance(center_y, numpy.ndarray): center_x = numpy.full(center_y.shape, center_x) else: center_x = numpy.array([float(center_x)]) center_y = numpy.array([float(center_y)]) width = 1.0 / subpix_map.shape[1] height = 1.0 / subpix_map.shape[0] subpix_center_x, subpix_center_y = numpy.meshgrid( numpy.arange(-0.5, 0.5, width) + width / 2.0, numpy.arange(-0.5, 0.5, height) + height / 2.0 ) subpix_center_x = center_x.ravel()[:, None] + subpix_center_x.ravel() subpix_center_y = center_y.ravel()[:, None] + subpix_center_y.ravel() return self.integrate( center_x=subpix_center_x, center_y=subpix_center_y, width=numpy.full(subpix_center_x.shape, width), height=numpy.full(subpix_center_x.shape, height) ).dot( subpix_map.ravel() )