Source code for epsf.epsf
import numpy as np
from scipy.interpolate import RectBivariateSpline
[docs]
class EPSF:
"""Effective point spread function
Python object to store an empirical PSF function.
Once created, the Python object can be called to generate a PSF with the desired offset in pixels.
:param epsf: Array with the (oversampled) epsf pixel values
:param true_size: Size (in pixels) of the output images from the epsf.
:param oversampling: Oversampling factor between the epsf pixel and the detector pixels.
"""
def __init__(self, epsf: np.ndarray, true_size: int = 11, oversampling: int = 4):
self.ny, self.nx = epsf.shape
x = np.arange(self.nx) # axis that goes to the right with origin=lower
y = np.arange(self.ny) # axis that goes up with origin=lower
self.array = epsf
self.spl = RectBivariateSpline(x, y, epsf)
self.true_size = true_size
self.oversampling = oversampling
def __repr__(self):
return f"EPSF(true_size={self.true_size}, oversampling={self.oversampling})"
def __call__(self, x: float, y: float) -> np.ndarray:
"""Generate a PSF at the ``(x, y)`` detector coordinates
:param x: x coordinate on the detector
:param y: y coordinate on the detector
"""
# Hardcoded for a 11x11 cutout
start = - (self.true_size // 2)
end = self.true_size // 2 + self.true_size % 2
dx_grid = np.arange(start, end) - x
dy_grid = np.arange(start, end) - y
# These assume the 4x oversampled 101x101 grid from Jay Anderson's jwst1pass
x_grid = self.nx // 2 + self.oversampling * dx_grid
y_grid = self.ny // 2 + self.oversampling * dy_grid
psf = self.spl(x_grid, y_grid)
return psf / np.sum(psf)