Source code for skysurvey.source.angular

"""
This module defines `AngularTimeSeriesSource`, a `sncosmo` source class for spectral time series models.
"""

import numpy as np
from scipy.interpolate import RectBivariateSpline as Spline2d
import sncosmo


[docs] class AngularTimeSeriesSource(sncosmo.Source): r""" A single-component spectral time series model. The spectral flux density of this model is given by .. math:: F(t, \lambda) = A \times M(t, \lambda, \cos\theta) where :math:`M` is the flux defined on a grid in phase and wavelength and :math:`A` (amplitude) is the single free parameter of the model. The amplitude :math:`A` is a simple unitless scaling factor applied to whatever flux values are used to initialize the ``TimeSeriesSource``. Therefore, the :math:`A` parameter has no intrinsic meaning. It can only be interpreted in conjunction with the model values. Thus, it is meaningless to compare the :math:`A` parameter between two different ``TimeSeriesSource`` instances with different model data. Parameters ---------- phase : `numpy.ndarray` Phases in days. wave : `numpy.ndarray` Wavelengths in Angstroms. flux : `numpy.ndarray` Model spectral flux density in arbitrary units. Must have shape `(num_phases)`. zero_before : bool, optional If True, flux at phases before minimum phase will be zeroed. The default is False, in which case the flux at such phases will be equal to the flux at the minimum phase (``flux[0, :]`` in the input array). zero_after : bool, optional If True, flux at phases after minimum phase will be zeroed. The default is False, in which case the flux at such phases will be equal to the flux at the maximum phase (``flux[-1, :]`` in the input array). cos_theta : `numpy.ndarray` cosine of viewing angle name : str, optional Name of the model. Default is None. version : str, optional Version of the model. Default is None. """ _param_names = ['amplitude', 'theta'] param_names_latex = ['A', r'\theta'] def __init__(self, phase, wave, cos_theta, flux, zero_before=False, zero_after=False, name=None, version=None): """ Initialize the AngularTimeSeriesSource class.""" self.name = name self.version = version self._phase = phase self._wave = wave self._cos_theta = cos_theta self._flux_array = flux self._parameters = np.array([1., 0.]) self._current_theta = 0. self._zero_before = zero_before self._zero_after = zero_after self._set_theta() def _set_theta(self): """ Update the internal 2D interpolation grid based on the current theta parameter. """ logflux_ = np.zeros(self._flux_array.shape[:2]) for k in range(len(self._phase)): adding = 1e-10 # Here we add 1e-10 to avoid problems with null values f_tmp = Spline2d(self._wave, self._cos_theta, np.log(self._flux_array[k]+adding), kx=1, ky=1) logflux_[k] = f_tmp(self._wave, np.cos(self._parameters[1]*np.pi/180)).T self._model_flux = Spline2d(self._phase, self._wave, logflux_, kx=1, ky=1) self._current_theta = self._parameters[1] def _flux(self, phase, wave): """ Compute the spectral flux density at given phase and wavelength. Parameters ---------- phase : `numpy.ndarray` Array of phases. wave : `numpy.ndarray` Array of wavelengths. Returns ------- flux : `numpy.ndarray` The interpolated flux density, scaled by amplitude. """ if self._current_theta != self._parameters[1]: self._set_theta() f = self._parameters[0] * (np.exp(self._model_flux(phase, wave))) if self._zero_before: mask = np.atleast_1d(phase) < self.minphase() f[mask, :] = 0. if self._zero_after: mask = np.atleast_1d(phase) > self.maxphase() f[mask, :] = 0. return f