Source code for slsim.Sources.SourceCatalogues.SupernovaeCatalog.supernovae_sample

from astropy.table import Table, hstack
from slsim.Sources.Supernovae import random_supernovae
from slsim.Sources.Supernovae.supernovae_lightcone import SNeLightcone
from slsim.Sources.SourceCatalogues.skypy_galaxy_catalog import GalaxyCatalog
from slsim.Sources.Supernovae.supernovae_host_match import SupernovaeHostMatch
import numpy as np
from astropy import units
from scipy import stats
from slsim.Sources.SourcePopulation.galaxies import galaxy_projected_eccentricity
from slsim.Util.param_util import ellipticity_slsim_to_lenstronomy
from slsim.Util.param_util import elliptical_distortion_product_average


[docs] def supernovae_host_galaxy_offset(host_galaxy_catalog): """This function generates random supernovae offsets from their host galaxy center based on observed data. (Wang et al. 2013) :param host_galaxy_catalog: catalog of host galaxies matched with supernovae (must have 'angular_size' and 'ellipticity' columns) :type host_galaxy_catalog: astropy Table :return: offsets x and y [arcsec] selected for each supernovae based on observed distribution; e1 and e2 projected eccentricities calculated for each host galaxy :return type: list; float """ # Select offset ratios based on observed offset distribution (Wang et al. 2013) offset_ratios = list( # Parameters (s, loc, and scale) obtained from fitting the observed data (Wang et al. 2013) # to lognorm distribution with distfit stats.lognorm.rvs( 0.764609, loc=-0.0284546, scale=0.450885, size=len(host_galaxy_catalog) ) ) offsets = [] position_angle_galaxy = [] position_angle_supernovae = [] original_x_off = [] original_y_off = [] e1 = [] e2 = [] transformed_x_off = [] transformed_y_off = [] for i in range(len(host_galaxy_catalog)): # Set a limit on maximum SN Ia offset ratio from host galaxy center while offset_ratios[i] > 3: offset_ratios[i] = stats.lognorm.rvs( 0.764609, loc=-0.0284546, scale=0.450885, size=1 )[0] # Calculate offsets [rad] offset = offset_ratios[i] * list(host_galaxy_catalog["angular_size"])[i] offsets.append(offset) galaxy_angle = np.random.uniform(0, np.pi) supernova_angle = np.random.uniform(0, 2 * np.pi) position_angle_galaxy.append(galaxy_angle) position_angle_supernovae.append(supernova_angle) # Calculate the x and y coordinates of the offset [arcsec] x_off = ((np.cos(supernova_angle * units.rad)) * (offset * units.rad)).to( units.arcsec ) y_off = ((np.sin(supernova_angle * units.rad)) * (offset * units.rad)).to( units.arcsec ) original_x_off.append(x_off) original_y_off.append(y_off) # Calculate projected eccentricities slsim_e1, slsim_e2 = galaxy_projected_eccentricity( host_galaxy_catalog["ellipticity"][i], galaxy_angle * units.rad ) e1.append(slsim_e1) e2.append(slsim_e2) # Transform the offset coordinates with eccentricities e1, e2 into elliptical coordinate # system lens_e1, lens_e2 = ellipticity_slsim_to_lenstronomy(slsim_e1, slsim_e2) transform_x_off, transform_y_off = elliptical_distortion_product_average( x_off.value, y_off.value, lens_e1, lens_e2, 0, 0 ) transformed_x_off.append(transform_x_off) transformed_y_off.append(transform_y_off) return transformed_x_off, transformed_y_off, e1, e2
[docs] class SupernovaeCatalog(object): """Class to generate a supernovae catalog.""" def __init__( self, sn_type, band_list, lightcurve_time, absolute_mag_band, mag_zpsys, cosmo, skypy_config, sky_area, absolute_mag, sn_modeldir=None, host_galaxy_candidate=None, redshift_max=5, ): """ :param sn_type: Supernova type (Ia, Ib, Ic, IIP, etc.) :type sn_type: str :param band_list: observation band. It sould be a list of bands. Eg: ["i"], ["i","r"] :type band_list: str. eg: 'i', 'g', 'r', or any other supported band :param lightcurve_time: observation time array for lightcurve in unit of days. :type lightcurve_time: array or None :param absolute_mag_band: Band used to normalize to absolute magnitude :type absolute_mag_band: str or `~sncosmo.Bandpass` :param mag_zpsys: Optional, AB or Vega (AB default) :type mag_zpsys: str :param cosmo: astropy.cosmology instance :param skypy_config: path to SkyPy configuration yaml file :type skypy_config: string or None :param sky_area: Sky area over which galaxies are sampled. Must be in units of solid angle. :type sky_area: `~astropy.units.Quantity` :param sn_modeldir: sn_modeldir is the path to the directory containing files needed to initialize the sncosmo.model class. For example, sn_modeldir = 'C:/Users/username/Documents/SALT3.NIR_WAVEEXT'. These data can be downloaded from https://github.com/LSST-strong-lensing/data_public . For more detail, please look at the documentation of RandomizedSupernovae class. :type sn_modeldir: str :param host_galaxy_candidate: Galaxy catalog in an Astropy table. This catalog is used to match with the supernova population. If None, the galaxy catalog is generated within this class. :param redshift_max: Maximum redshift for supernovae sample. Default is 5. """ self.sn_type = sn_type self.band_list = band_list self.lightcurve_time = lightcurve_time self.absolute_mag = absolute_mag self.absolute_mag_band = absolute_mag_band self.mag_zpsys = mag_zpsys self.cosmo = cosmo self.skypy_config = skypy_config self.sky_area = sky_area self.sn_modeldir = sn_modeldir self.host_galaxy_candidate = host_galaxy_candidate self.redshift_max = redshift_max
[docs] def supernovae_catalog(self, host_galaxy=True, lightcurve=True): """Generates supernovae catalog for given redshifts. :param host_galaxy: kwargs to decide whether catalog should include host galaxies or not. True or False. :param lightcurve: kwargs for the lightcurve, if lightcurve is True, it returns extracts lightcurve for each supernovae redshift. :return: Astropy Table of supernovae catalog containg redshift, lightcurves, ra_off, dec_off, and host galaxy properties. If host_galaxy is set to False, it returns catalog without host galaxy properties. Light curves are generated using RandomizedSupernova class. Light curves are saved as an array of observation time and array of corresponding magnitudes in specified bands in different columns of the Table. """ sne_lightcone = SNeLightcone( self.cosmo, redshifts=np.linspace(0, self.redshift_max, 500), sky_area=self.sky_area, noise=True, time_interval=1 * units.year, ) supernovae_redshift = sne_lightcone.supernovae_sample() if host_galaxy is True: if self.host_galaxy_candidate is None: galaxy_catalog = GalaxyCatalog( cosmo=self.cosmo, skypy_config=self.skypy_config, sky_area=self.sky_area, ) host_galaxy_catalog = galaxy_catalog.galaxy_catalog() else: host_galaxy_catalog = self.host_galaxy_candidate matching_catalogs = SupernovaeHostMatch( supernovae_catalog=supernovae_redshift, galaxy_catalog=host_galaxy_catalog, ) matched_table = matching_catalogs.match() time = [] # Initialize a list attribute for each band in self.band_list for band in self.band_list: setattr(self, f"magnitude_{band}", []) # Generate lightcurve for each supernovae. if lightcurve is True: for z in supernovae_redshift: lightcurve_class = random_supernovae.RandomizedSupernova( self.sn_type, z, self.absolute_mag, self.absolute_mag_band, self.mag_zpsys, self.cosmo, self.sn_modeldir, ) time.append(self.lightcurve_time) for band in self.band_list: mag = lightcurve_class.get_apparent_magnitude( self.lightcurve_time, "lsst" + band, zpsys=self.mag_zpsys ) getattr(self, f"magnitude_{band}").append(mag) lightcurve_data = {"MJD": time} for band in self.band_list: lightcurve_data["ps_mag_" + band] = getattr(self, f"magnitude_{band}") else: lightcurve_data = {} # Get ra_off and dec_off if host galaxy is true. if host_galaxy is True: x_off, y_off, e1, e2 = supernovae_host_galaxy_offset(matched_table) matched_table["x_off"] = x_off matched_table["y_off"] = y_off matched_table["e1"] = e1 matched_table["e2"] = e2 lightcurve_table = Table(lightcurve_data) supernovae_table = hstack([lightcurve_table, matched_table]) # Only saves supernovae redshift and corresponding lightcurves else: lightcurve_data["z"] = supernovae_redshift supernovae_table = Table(lightcurve_data) return supernovae_table