Source code for roman_shear_sims.psf_makers

import numpy as np

import galsim
from galsim import roman

from .constant import IMCOM_PSF_FWHM

[docs] PSF_TYPES = ["gauss", "airy", "obs_airy", "roman", "imcom"]
[docs] _rad_to_arcsec = 180 * 3600 / np.pi
[docs] class PSFMaker: """ A class to create different types of PSFs. Parameters ---------- psf_type : str The type of PSF to create. Options are 'gauss', 'airy', 'obs_airy', 'roman', 'imcom'. fwhm : float, optional The full width at half maximum of the Gaussian PSF in arcseconds. chromatic : bool, optional Whether the PSF is chromatic. Default is True. wave : float, optional The wavelength in nanometers for the PSF. Required if `psf_type` is 'roman'. sca : int, optional The SCA number for the Roman PSF. Default is 1. pupil_bin : int, optional The binning factor for the pupil. Default is 8. n_waves : int, optional The number of wavelengths to use for the Roman PSF. Default is 10. """ def __init__( self, psf_type="gauss", fwhm=None, chromatic=True, wave=None, sca=1, pupil_bin=8, n_waves=10, ): if not isinstance(psf_type, str): raise TypeError("psf_type must be a string") psf_type = psf_type.lower() if psf_type not in PSF_TYPES: raise ValueError( f"psf_type must be one of {PSF_TYPES}, got {psf_type}" )
[docs] self.psf_type = psf_type
[docs] self.fwhm = fwhm
[docs] self.sca = sca
[docs] self.pupil_bin = pupil_bin
[docs] self.chromatic = chromatic
[docs] self.wave = wave
[docs] self.n_waves = n_waves
[docs] def init_psf(self, band="Y106"): """ Initialize the PSF parameters based on the bandpass. Parameters ---------- band : str The bandpass name for which to initialize the PSF parameters. """ if not isinstance(band, str): raise TypeError("band must be a string") self.band = band if self.psf_type != "imcom": if self.wave is None: bp = roman.getBandpasses()[self.band] self.wave = bp.effective_wavelength if self.fwhm is None: self.fwhm = self.wave / roman.pixel_scale * 1e-9 self.fwhm *= _rad_to_arcsec else: if self.fwhm is None: if self.band not in IMCOM_PSF_FWHM: raise ValueError( f"Band {self.band} not a valid IMCOM band." ) self.fwhm = IMCOM_PSF_FWHM[self.band]
[docs] def get_psf(self, sca=None, image_pos=None, wcs=None): """ Get the PSF object Parameters ---------- sca : int, optional The SCA number for the Roman PSF. Default is the initialized value. image_pos : galsim.CelestialCoord, optional The celestial coordinates of the image center. Required if `psf_type` is 'roman'. wcs : galsim.WCS, optional The WCS object for the image. Required if `psf_type` is 'roman'. Returns ------- galsim.GSObject The PSF object. """ if self.psf_type == "gauss" or self.psf_type == "imcom": psf = galsim.Gaussian(fwhm=self.fwhm) elif self.psf_type == "airy": psf = galsim.Airy(lam=self.wave, diam=roman.diameter) elif self.psf_type == "obs_airy": psf = galsim.Airy( lam=self.wave, diam=roman.diameter, obscuration=roman.obscuration, ) elif self.psf_type == "roman": wave = None if self.chromatic else self.wave psf = roman.getPSF( SCA=sca, bandpass=self.band, SCA_pos=image_pos, pupil_bin=self.pupil_bin, wcs=wcs, n_waves=self.n_waves, wavelength=wave, ) return psf