Source code for yippy.stellar_intens

"""Module for handling stellar intensity data from stellar_intens files."""

from pathlib import Path

import astropy.io.fits as pyfits
import numpy as np
from astropy.units import Quantity
from lod_unit import lod
from scipy.interpolate import CubicSpline

from .util import convert_to_lod


[docs] class StellarIntens: """Class to handle and interpolate stellar intensity data. This class loads stellar intensity data and corresponding stellar diameters, providing an interpolation interface to get the stellar intensity map for a given stellar diameter. Attributes: ln_interp (CubicSpline): A spline interpolator that operates on the natural logarithm of the stellar intensities to ensure that interpolated values are non-negative. Args: yip_dir (Path): Path to the directory containing the yield input package (YIP). stellar_intens_file (str): Filename of the FITS file containing the stellar intensity data. stellar_diam_file (str): Filename of the FITS file containing the stellar diameters. """ def __init__( self, yip_dir: Path, stellar_intens_file: str, stellar_diam_file: str, ) -> None: """Initializes StellarIntens class by loading data and creating the interpolant. Stellar intensity data and stellar diameters are loaded from FITS files, and a natural logarithm-based cubic spline interpolator is set up to facilitate interpolation. Args: yip_dir (Path): The directory where the stellar intensity and diameter FITS files are located. stellar_intens_file (str): The filename of the FITS file containing unitless arrays of stellar intensities. stellar_diam_file (str): The filename of the FITS file containing arrays of stellar diameters in lambda/D units. """ # Load on-axis stellar intensity PSF data psfs = pyfits.getdata(Path(yip_dir, stellar_intens_file), 0) # Get header information header = pyfits.getheader(Path(yip_dir, stellar_intens_file), 0) # Get center coordinates from header or use image center if "XCENTER" in header: self.center_x = header["XCENTER"] else: self.center_x = psfs[0].shape[1] / 2 if "YCENTER" in header: self.center_y = header["YCENTER"] else: self.center_y = psfs[0].shape[0] / 2 # Load the stellar angular diameters in units of lambda/D self.diams = pyfits.getdata(Path(yip_dir, stellar_diam_file), 0).flatten() * lod # For interpolation purpose, replace 0s with smallest positive value self.diams[self.diams == 0] = np.finfo(np.float32).eps * lod # Store a copy of the original PSFs self.psfs = psfs.copy() # Interpolate stellar data in logarithmic space to ensure non-negative # interpolated values self.psfs[self.psfs == 0] = np.finfo(np.float32).eps self.ln_interp = CubicSpline(self.diams, np.log(self.psfs))
[docs] def __call__(self, stellar_diam: Quantity, lam=None, D=None): """Returns the stellar intensity map at a specified stellar diameter. Stellar intensity is interpolated based on a specified diameter using the previously configured cubic spline interpolator. The interpolation considers the logarithm of the intensity to ensure that all computed values are positive. Args: stellar_diam (Quantity): The desired stellar diameter for which to retrieve the intensity map, in units of lambda/D. lam (Quantity, optional): Wavelength of observation, required if stellar_diam is in angular units. D (Quantity, optional): Diameter of the telescope, required if stellar_diam is in angular units. Returns: NDArray: An interpolated 2D map of the stellar intensity at the given stellar diameter. """ # Set up conversion from angular units to lambda/D if stellar_diam.unit != lod: stellar_diam = convert_to_lod(stellar_diam, lam=lam, D=D) # Return the exponentiated result of the interpolation to get the # actual intensity map return np.exp(self.ln_interp(stellar_diam))