redback 1.0.1__py3-none-any.whl → 1.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- redback/__init__.py +4 -0
- redback/constraints.py +31 -25
- redback/get_data/lasair.py +3 -4
- redback/get_data/swift.py +7 -7
- redback/interaction_processes.py +1 -4
- redback/likelihoods.py +207 -21
- redback/plotting.py +10 -10
- redback/priors/csm_interaction.prior +6 -7
- redback/priors/csm_nickel.prior +3 -3
- redback/priors/one_comp_kne_rosswog_heatingrate.prior +5 -0
- redback/priors/tde_analytical.prior +5 -5
- redback/priors/tde_analytical_bolometric.prior +6 -4
- redback/priors/tophat_from_emulator.prior +9 -0
- redback/priors/two_comp_kne_rosswog_heatingrate.prior +9 -0
- redback/priors/two_layer_stratified_kilonova.prior +1 -1
- redback/priors.py +11 -0
- redback/sed.py +194 -2
- redback/simulate_transients.py +61 -32
- redback/tables/filters.csv +14 -0
- redback/tables/ztf.tar.gz +0 -0
- redback/transient/afterglow.py +3 -2
- redback/transient/kilonova.py +1 -1
- redback/transient/supernova.py +1 -1
- redback/transient/tde.py +1 -1
- redback/transient/transient.py +2 -2
- redback/transient_models/afterglow_models.py +42 -0
- redback/transient_models/combined_models.py +47 -32
- redback/transient_models/extinction_models.py +5 -4
- redback/transient_models/kilonova_models.py +241 -8
- redback/transient_models/magnetar_driven_ejecta_models.py +2 -2
- redback/transient_models/phenomenological_models.py +13 -0
- redback/transient_models/supernova_models.py +50 -36
- redback/transient_models/tde_models.py +126 -1
- redback/utils.py +283 -6
- {redback-1.0.1.dist-info → redback-1.0.2.dist-info}/METADATA +6 -3
- {redback-1.0.1.dist-info → redback-1.0.2.dist-info}/RECORD +39 -37
- {redback-1.0.1.dist-info → redback-1.0.2.dist-info}/WHEEL +1 -1
- redback/tables/ztf_obslog.csv +0 -106649
- {redback-1.0.1.dist-info → redback-1.0.2.dist-info}/LICENCE.md +0 -0
- {redback-1.0.1.dist-info → redback-1.0.2.dist-info}/top_level.txt +0 -0
redback/plotting.py
CHANGED
|
@@ -346,7 +346,7 @@ class IntegratedFluxPlotter(Plotter):
|
|
|
346
346
|
axes.plot(times, ys, color=self.random_sample_color, alpha=self.random_sample_alpha, lw=self.linewidth,
|
|
347
347
|
zorder=self.zorder)
|
|
348
348
|
elif self.uncertainty_mode == "credible_intervals":
|
|
349
|
-
lower_bound, upper_bound, _ = redback.utils.calc_credible_intervals(samples=random_ys_list)
|
|
349
|
+
lower_bound, upper_bound, _ = redback.utils.calc_credible_intervals(samples=random_ys_list, interval=self.credible_interval_level)
|
|
350
350
|
axes.fill_between(
|
|
351
351
|
times, lower_bound, upper_bound, alpha=self.uncertainty_band_alpha, color=self.max_likelihood_color)
|
|
352
352
|
|
|
@@ -391,11 +391,11 @@ class LuminosityPlotter(IntegratedFluxPlotter):
|
|
|
391
391
|
|
|
392
392
|
class MagnitudePlotter(Plotter):
|
|
393
393
|
|
|
394
|
-
xlim_low_phase_model_multiplier = 0.9
|
|
395
|
-
xlim_high_phase_model_multiplier = 1.1
|
|
396
|
-
xlim_high_multiplier = 1.2
|
|
397
|
-
ylim_low_magnitude_multiplier = 0.8
|
|
398
|
-
ylim_high_magnitude_multiplier = 1.2
|
|
394
|
+
xlim_low_phase_model_multiplier = KwargsAccessorWithDefault("xlim_low_multiplier", 0.9)
|
|
395
|
+
xlim_high_phase_model_multiplier = KwargsAccessorWithDefault("xlim_high_multiplier", 1.1)
|
|
396
|
+
xlim_high_multiplier = KwargsAccessorWithDefault("xlim_high_multiplier", 1.2)
|
|
397
|
+
ylim_low_magnitude_multiplier = KwargsAccessorWithDefault("ylim_low_multiplier", 0.8)
|
|
398
|
+
ylim_high_magnitude_multiplier = KwargsAccessorWithDefault("ylim_high_multiplier", 1.2)
|
|
399
399
|
ncols = KwargsAccessorWithDefault("ncols", 2)
|
|
400
400
|
|
|
401
401
|
@property
|
|
@@ -635,11 +635,11 @@ class MagnitudePlotter(Plotter):
|
|
|
635
635
|
elif self.uncertainty_mode == "credible_intervals":
|
|
636
636
|
if band in self.band_scaling:
|
|
637
637
|
if self.band_scaling.get("type") == 'x':
|
|
638
|
-
lower_bound, upper_bound, _ = redback.utils.calc_credible_intervals(samples=np.array(random_ys_list) * self.band_scaling.get(band))
|
|
638
|
+
lower_bound, upper_bound, _ = redback.utils.calc_credible_intervals(samples=np.array(random_ys_list) * self.band_scaling.get(band), interval=self.credible_interval_level)
|
|
639
639
|
elif self.band_scaling.get("type") == '+':
|
|
640
|
-
lower_bound, upper_bound, _ = redback.utils.calc_credible_intervals(samples=np.array(random_ys_list) + self.band_scaling.get(band))
|
|
640
|
+
lower_bound, upper_bound, _ = redback.utils.calc_credible_intervals(samples=np.array(random_ys_list) + self.band_scaling.get(band), interval=self.credible_interval_level)
|
|
641
641
|
else:
|
|
642
|
-
lower_bound, upper_bound, _ = redback.utils.calc_credible_intervals(samples=np.array(random_ys_list))
|
|
642
|
+
lower_bound, upper_bound, _ = redback.utils.calc_credible_intervals(samples=np.array(random_ys_list), interval=self.credible_interval_level)
|
|
643
643
|
axes.fill_between(
|
|
644
644
|
times - self._reference_mjd_date, lower_bound, upper_bound,
|
|
645
645
|
alpha=self.uncertainty_band_alpha, color=color_sample)
|
|
@@ -789,7 +789,7 @@ class MagnitudePlotter(Plotter):
|
|
|
789
789
|
axes[ii].plot(times - self._reference_mjd_date, random_ys, color=color_sample,
|
|
790
790
|
alpha=self.random_sample_alpha, lw=self.linewidth, zorder=self.zorder)
|
|
791
791
|
elif self.uncertainty_mode == "credible_intervals":
|
|
792
|
-
lower_bound, upper_bound, _ = redback.utils.calc_credible_intervals(samples=random_ys_list)
|
|
792
|
+
lower_bound, upper_bound, _ = redback.utils.calc_credible_intervals(samples=random_ys_list, interval=self.credible_interval_level)
|
|
793
793
|
axes[ii].fill_between(
|
|
794
794
|
times - self._reference_mjd_date, lower_bound, upper_bound,
|
|
795
795
|
alpha=self.uncertainty_band_alpha, color=color_sample)
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
redshift = Uniform(1e-3,3,name='redshift', latex_label = r'$z$')
|
|
2
|
-
mej = LogUniform(
|
|
3
|
-
csm_mass = LogUniform(
|
|
2
|
+
mej = LogUniform(1, 100, 'mej', latex_label = r'$M_{\mathrm{ej} }~(M_\odot)$')
|
|
3
|
+
csm_mass = LogUniform(1, 100, 'csm_mass', latex_label = r'$M_{\mathrm{csm}}~(M_\odot)$')
|
|
4
4
|
vej = LogUniform(1e3, 1e5, 'vej', latex_label = r'$v_{\mathrm{ej}}~(\mathrm{km}/\mathrm{s})$')
|
|
5
|
-
eta = Uniform(0,
|
|
6
|
-
rho =
|
|
7
|
-
r0 = Uniform(
|
|
5
|
+
eta = Uniform(0, 2, '\\eta', latex_label = r'$\\eta$')
|
|
6
|
+
rho = LogUniform(1e-14, 1e-12, 'rho', latex_label = r'$\\rho$')
|
|
7
|
+
r0 = Uniform(50, 700, 'r0', latex_label=r'$r_0~({\mathrm{AU}})$')
|
|
8
8
|
kappa = Uniform(0.05, 2, 'kappa', latex_label = r'$\\kappa~(\mathrm{cm}^{2}/\mathrm{g})$')
|
|
9
|
-
|
|
10
|
-
temperature_floor = LogUniform(1e3,1e5,name = 'temperature_floor', latex_label = r'$T_{\mathrm{floor}}~(\mathrm{K})$')
|
|
9
|
+
temperature_floor = LogUniform(100,1e4,name = 'temperature_floor', latex_label = r'$T_{\mathrm{floor}}~(\mathrm{K})$')
|
redback/priors/csm_nickel.prior
CHANGED
|
@@ -3,9 +3,9 @@ mej = LogUniform(1e-4, 100, 'mej', latex_label = r'$M_{\mathrm{ej} }~(M_\odot)$'
|
|
|
3
3
|
f_nickel = LogUniform(1e-3,1,name='f_nickel', latex_label = r'$f_{\mathrm{Ni}}$')
|
|
4
4
|
csm_mass = LogUniform(1e-4, 100, 'csm_mass', latex_label = r'$M_{\mathrm{csm}}~(M_\odot)$')
|
|
5
5
|
ek = LogUniform(1e48, 1e52, 'ek', latex_label = r'$E_{\mathrm{kin}}~(\mathrm{ erg})$')
|
|
6
|
-
eta = Uniform(0,
|
|
7
|
-
rho =
|
|
6
|
+
eta = Uniform(0, 2, '\\eta', latex_label = r'$\\eta$')
|
|
7
|
+
rho = LogUniform(1e-15, 1e-12, 'rho', latex_label = r'$\\rho$')
|
|
8
8
|
r0 = Uniform(4, 8, 'r0', latex_label=r'$r_0~({\mathrm{AU}})$')
|
|
9
9
|
kappa = Uniform(0.05, 2, 'kappa', latex_label = r'$\\kappa~(\mathrm{cm}^{2}/\mathrm{g})$')
|
|
10
10
|
kappa_gamma = LogUniform(1e-4, 1e4, 'kappa_gamma', latex_label = r'$\\kappa_{\\gamma}~(\mathrm{cm}^{2}/\mathrm{g})$')
|
|
11
|
-
temperature_floor = LogUniform(
|
|
11
|
+
temperature_floor = LogUniform(100,1e4,name = 'temperature_floor', latex_label = r'$T_{\mathrm{floor}}~(\mathrm{K})$')
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
redshift = Uniform(1e-6, 0.1, 'redshift', latex_label = r'$z$')
|
|
2
|
+
mej = Uniform(1e-2, 0.05, 'mej', latex_label = r'$M_{\mathrm{ej} }~(M_\odot)$')
|
|
3
|
+
vej = Uniform(0.05, 0.3, 'vej', latex_label = r'$v_{\mathrm{ej}}~(c)$')
|
|
4
|
+
ye = Uniform(0.05, 0.4, 'ye', latex_label = r'$Y_{e}$')
|
|
5
|
+
temperature_floor = LogUniform(100, 6000, 'temperature_floor', latex_label = r'$T_{\mathrm{floor}}~(\mathrm{K})$')
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
redshift = Uniform(0.01, 3, 'redshift', latex_label=r'$z$')
|
|
2
|
-
mej = LogUniform(
|
|
2
|
+
mej = LogUniform(0.1, 100, 'mej', latex_label = r'$M_{\mathrm{ej} }~(M_\odot)$')
|
|
3
3
|
vej = LogUniform(1e3, 1e5, 'vej', latex_label = r'$v_{\mathrm{ej}}~(\mathrm{km}/\mathrm{s})$')
|
|
4
|
-
kappa = Uniform(0.05,
|
|
4
|
+
kappa = Uniform(0.05, 1e2, 'kappa', latex_label = r'$\\kappa~(\mathrm{cm}^{2}/\mathrm{g})$')
|
|
5
5
|
kappa_gamma = LogUniform(1e-4, 1e4, 'kappa_gamma', latex_label = r'$\\kappa_{\\gamma}~(\mathrm{cm}^{2}/\mathrm{g})$')
|
|
6
|
-
temperature_floor = LogUniform(1e3,
|
|
7
|
-
l0 = LogUniform(1e51,
|
|
8
|
-
t_0_turn = LogUniform(1e-4,
|
|
6
|
+
temperature_floor = LogUniform(1e3,1e4,name = 'temperature_floor', latex_label = r'$T_{\mathrm{floor}}~(\mathrm{K})$')
|
|
7
|
+
l0 = LogUniform(1e51, 1e60, "l0", latex_label="$l_0$")
|
|
8
|
+
t_0_turn = LogUniform(1e-4, 5e2, "t_0_turn", latex_label="$t_{0 t}$")
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
redshift = Uniform(0.01, 3, 'redshift', latex_label=r'$z$')
|
|
2
|
+
mej = LogUniform(0.1, 100, 'mej', latex_label = r'$M_{\mathrm{ej} }~(M_\odot)$')
|
|
2
3
|
vej = LogUniform(1e3, 1e5, 'vej', latex_label = r'$v_{\mathrm{ej}}~(\mathrm{km}/\mathrm{s})$')
|
|
3
|
-
kappa = Uniform(0.05,
|
|
4
|
+
kappa = Uniform(0.05, 1e2, 'kappa', latex_label = r'$\\kappa~(\mathrm{cm}^{2}/\mathrm{g})$')
|
|
4
5
|
kappa_gamma = LogUniform(1e-4, 1e4, 'kappa_gamma', latex_label = r'$\\kappa_{\\gamma}~(\mathrm{cm}^{2}/\mathrm{g})$')
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
temperature_floor = LogUniform(1e3,1e4,name = 'temperature_floor', latex_label = r'$T_{\mathrm{floor}}~(\mathrm{K})$')
|
|
7
|
+
l0 = LogUniform(1e51, 1e60, "l0", latex_label="$l_0$")
|
|
8
|
+
t_0_turn = LogUniform(1e-4, 5e2, "t_0_turn", latex_label="$t_{0 t}$")
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
redshift = Uniform(0.01, 3, 'redshift', latex_label=r'$z$')
|
|
2
|
+
thv = Sine(name='thv', maximum=np.pi/2, latex_label=r'$\\theta_{\mathrm{observer}}~(\mathrm{rad})$')
|
|
3
|
+
loge0 = Uniform(44, 54, 'loge0', latex_label=r'$\log_{10}~E_{0} / {\mathrm{erg}}$')
|
|
4
|
+
thc = Uniform(0.01, 0.1, 'thc', latex_label=r'$\\theta_{\mathrm{core}}~({\mathrm{rad}})$')
|
|
5
|
+
logn0 = Uniform(-5, 2, 'logn0', latex_label=r'$\log_{10}~n_{\mathrm{ism}} / {\mathrm{cm}}^{-3}$')
|
|
6
|
+
p = Uniform(2, 3, 'p', latex_label=r'$p$')
|
|
7
|
+
logepse = Uniform(-5, 0, 'logepse', latex_label=r'$\log_{10}~\\epsilon_{e}$')
|
|
8
|
+
logepsb = Uniform(-5, 0, 'logepsb', latex_label=r'$\log_{10}~\\epsilon_{B}$')
|
|
9
|
+
g0 = Uniform(100,2000, 'g0', latex_label=r'$\\Gamma_{0}$')
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
redshift = Uniform(1e-6, 0.1, 'redshift', latex_label = r'$z$')
|
|
2
|
+
mej_1 = Uniform(1e-2, 0.05, 'mej', latex_label = r'$M_{\mathrm{ej}~1}~(M_\odot)$')
|
|
3
|
+
vej_1 = Uniform(0.05, 0.3, 'vej', latex_label = r'$v_{\mathrm{ej}~1}~(c)$')
|
|
4
|
+
ye_1 = Uniform(0.05, 0.4, 'ye', latex_label = r'$Y_{e}~1$')
|
|
5
|
+
temperature_floor_1 = LogUniform(100, 6000, 'temperature_floor', latex_label = r'$T_{\mathrm{floor}~1}~(\mathrm{K})$')
|
|
6
|
+
mej_2 = Uniform(1e-2, 0.05, 'mej', latex_label = r'$M_{\mathrm{ej}~2}~(M_\odot)$')
|
|
7
|
+
vej_2 = Uniform(0.05, 0.3, 'vej', latex_label = r'$v_{\mathrm{ej}~2}~(c)$')
|
|
8
|
+
ye_2 = Uniform(0.05, 0.4, 'ye', latex_label = r'$Y_{e}~2$')
|
|
9
|
+
temperature_floor_2 = LogUniform(100, 6000, 'temperature_floor', latex_label = r'$T_{\mathrm{floor}~2}~(\mathrm{K})$')
|
|
@@ -3,4 +3,4 @@ mej = Uniform(1e-2, 0.05, 'mej', latex_label = r'$M_{\mathrm{ej}}~(M_\odot)$')
|
|
|
3
3
|
vej_1 = Uniform(0.05, 0.2, 'vej_1', latex_label = r'$v_{\mathrm{ej}~1}~(c)$')
|
|
4
4
|
vej_2 = Uniform(0.3, 0.5, 'vej_2', latex_label = r'$v_{\mathrm{ej}~2}~(c)$')
|
|
5
5
|
kappa = Uniform(1, 30, 'kappa', latex_label = r'$\\kappa~(\mathrm{cm}^{2}/\mathrm{g})$')
|
|
6
|
-
beta = Uniform(1
|
|
6
|
+
beta = Uniform(3.1, 8, 'beta', latex_label = r'$\\beta$')
|
redback/priors.py
CHANGED
|
@@ -9,6 +9,17 @@ from redback.utils import logger
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def get_priors(model, times=None, y=None, yerr=None, dt=None, **kwargs):
|
|
12
|
+
"""
|
|
13
|
+
Get the prior for the given model. If the model is a prompt model, the times, y, and yerr must be provided.
|
|
14
|
+
|
|
15
|
+
:param model: String referring to a name of a model implemented in Redback.
|
|
16
|
+
:param times: Time array
|
|
17
|
+
:param y: Y values, arbitrary units
|
|
18
|
+
:param yerr: Error on y values, arbitrary units
|
|
19
|
+
:param dt: time interval
|
|
20
|
+
:param kwargs: Extra arguments to be passed to the prior function
|
|
21
|
+
:return: priors: PriorDict object
|
|
22
|
+
"""
|
|
12
23
|
prompt_prior_functions = dict(gaussian=get_gaussian_priors, skew_gaussian=get_skew_gaussian_priors,
|
|
13
24
|
skew_exponential=get_skew_exponential_priors, fred=get_fred_priors,
|
|
14
25
|
fred_extended=get_fred_extended_priors)
|
redback/sed.py
CHANGED
|
@@ -6,6 +6,193 @@ from sncosmo import TimeSeriesSource
|
|
|
6
6
|
from redback.constants import *
|
|
7
7
|
from redback.utils import nu_to_lambda, bandpass_magnitude_to_flux
|
|
8
8
|
|
|
9
|
+
def _bandflux_single_redback(model, band, time_or_phase):
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
Synthetic photometry of a model through a single bandpass
|
|
13
|
+
|
|
14
|
+
:param model: Source object
|
|
15
|
+
:param band: Bandpass
|
|
16
|
+
:param time_or_phase: Time or phase numpy array
|
|
17
|
+
:return: bandflux through the bandpass
|
|
18
|
+
"""
|
|
19
|
+
from sncosmo.utils import integration_grid
|
|
20
|
+
HC_ERG_AA = 1.9864458571489284e-08 # planck * speed_of_light in AA/s
|
|
21
|
+
MODEL_BANDFLUX_SPACING = 5.0 # Angstroms
|
|
22
|
+
|
|
23
|
+
if (band.minwave() < model.minwave() or band.maxwave() > model.maxwave()):
|
|
24
|
+
raise ValueError('bandpass {0!r:s} [{1:.6g}, .., {2:.6g}] '
|
|
25
|
+
'outside spectral range [{3:.6g}, .., {4:.6g}]'
|
|
26
|
+
.format(band.name, band.minwave(), band.maxwave(),
|
|
27
|
+
model.minwave(), model.maxwave()))
|
|
28
|
+
|
|
29
|
+
# Set up wavelength grid. Spacing (dwave) evenly divides the bandpass,
|
|
30
|
+
# closest to 5 angstroms without going over.
|
|
31
|
+
wave, dwave = integration_grid(band.minwave(), band.maxwave(),
|
|
32
|
+
MODEL_BANDFLUX_SPACING)
|
|
33
|
+
trans = band(wave)
|
|
34
|
+
f = model._flux(time_or_phase, wave)
|
|
35
|
+
f = np.abs(f)
|
|
36
|
+
return np.sum(wave * trans * f, axis=1) * dwave / HC_ERG_AA
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _bandflux_redback(model, band, time_or_phase, zp, zpsys):
|
|
40
|
+
"""
|
|
41
|
+
Support function for bandflux in Source and Model. Follows SNCOSMO
|
|
42
|
+
|
|
43
|
+
This is necessary to have outside because ``phase`` is used in Source
|
|
44
|
+
and ``time`` is used in Model, and we want the method signatures to
|
|
45
|
+
have the right variable name.
|
|
46
|
+
"""
|
|
47
|
+
from sncosmo.magsystems import get_magsystem
|
|
48
|
+
from sncosmo.bandpasses import get_bandpass
|
|
49
|
+
|
|
50
|
+
if zp is not None and zpsys is None:
|
|
51
|
+
raise ValueError('zpsys must be given if zp is not None')
|
|
52
|
+
|
|
53
|
+
# broadcast arrays
|
|
54
|
+
if zp is None:
|
|
55
|
+
time_or_phase, band = np.broadcast_arrays(time_or_phase, band)
|
|
56
|
+
else:
|
|
57
|
+
time_or_phase, band, zp, zpsys = \
|
|
58
|
+
np.broadcast_arrays(time_or_phase, band, zp, zpsys)
|
|
59
|
+
|
|
60
|
+
# Convert all to 1-d arrays.
|
|
61
|
+
ndim = time_or_phase.ndim # Save input ndim for return val.
|
|
62
|
+
time_or_phase = np.atleast_1d(time_or_phase)
|
|
63
|
+
band = np.atleast_1d(band)
|
|
64
|
+
if zp is not None:
|
|
65
|
+
zp = np.atleast_1d(zp)
|
|
66
|
+
zpsys = np.atleast_1d(zpsys)
|
|
67
|
+
|
|
68
|
+
# initialize output arrays
|
|
69
|
+
bandflux = np.zeros(time_or_phase.shape, dtype=float)
|
|
70
|
+
|
|
71
|
+
# Loop over unique bands.
|
|
72
|
+
for b in set(band):
|
|
73
|
+
mask = band == b
|
|
74
|
+
b = get_bandpass(b)
|
|
75
|
+
|
|
76
|
+
fsum = _bandflux_single_redback(model, b, time_or_phase[mask])
|
|
77
|
+
|
|
78
|
+
if zp is not None:
|
|
79
|
+
zpnorm = 10. ** (0.4 * zp[mask])
|
|
80
|
+
bandzpsys = zpsys[mask]
|
|
81
|
+
for ms in set(bandzpsys):
|
|
82
|
+
mask2 = bandzpsys == ms
|
|
83
|
+
ms = get_magsystem(ms)
|
|
84
|
+
zpnorm[mask2] = zpnorm[mask2] / ms.zpbandflux(b)
|
|
85
|
+
fsum *= zpnorm
|
|
86
|
+
|
|
87
|
+
bandflux[mask] = fsum
|
|
88
|
+
|
|
89
|
+
if ndim == 0:
|
|
90
|
+
return bandflux[0]
|
|
91
|
+
return bandflux
|
|
92
|
+
|
|
93
|
+
def _bandmag_redback(model, band, magsys, time_or_phase):
|
|
94
|
+
"""
|
|
95
|
+
Support function for bandflux in Source and Model.
|
|
96
|
+
This is necessary to have outside the models because ``phase`` is used in
|
|
97
|
+
Source and ``time`` is used in Model.
|
|
98
|
+
"""
|
|
99
|
+
from sncosmo.magsystems import get_magsystem
|
|
100
|
+
|
|
101
|
+
bandflux = _bandflux_redback(model, band, time_or_phase, None, None)
|
|
102
|
+
band, magsys, bandflux = np.broadcast_arrays(band, magsys, bandflux)
|
|
103
|
+
return_scalar = (band.ndim == 0)
|
|
104
|
+
band = band.ravel()
|
|
105
|
+
magsys = magsys.ravel()
|
|
106
|
+
bandflux = bandflux.ravel()
|
|
107
|
+
|
|
108
|
+
result = np.empty(bandflux.shape, dtype=float)
|
|
109
|
+
for i, (b, ms, f) in enumerate(zip(band, magsys, bandflux)):
|
|
110
|
+
ms = get_magsystem(ms)
|
|
111
|
+
zpf = ms.zpbandflux(b)
|
|
112
|
+
result[i] = -2.5 * np.log10(f / zpf)
|
|
113
|
+
|
|
114
|
+
if return_scalar:
|
|
115
|
+
return result[0]
|
|
116
|
+
return result
|
|
117
|
+
|
|
118
|
+
class RedbackTimeSeriesSource(TimeSeriesSource):
|
|
119
|
+
def __init__(self, phase, wave, flux, **kwargs):
|
|
120
|
+
"""
|
|
121
|
+
RedbackTimeSeriesSource is a subclass of sncosmo.TimeSeriesSource that adds the ability to return the
|
|
122
|
+
flux density at a given time and wavelength, and changes
|
|
123
|
+
the behaviour of the _flux method to better handle models with very low flux values.
|
|
124
|
+
|
|
125
|
+
:param phase: phase/time array
|
|
126
|
+
:param wave: wavelength array in Angstrom
|
|
127
|
+
:param spectra: spectra in erg/cm^2/s/A evaluated at all times and frequencies; shape (len(times), len(frequency_array))
|
|
128
|
+
:param kwargs: additional arguments
|
|
129
|
+
"""
|
|
130
|
+
super(RedbackTimeSeriesSource, self).__init__(phase=phase, wave=wave, flux=flux, **kwargs)
|
|
131
|
+
|
|
132
|
+
def get_flux_density(self, time, wavelength):
|
|
133
|
+
"""
|
|
134
|
+
Get the flux density at a given time and wavelength.
|
|
135
|
+
|
|
136
|
+
:param time: time in days
|
|
137
|
+
:param wavelength: wavelength in Angstrom
|
|
138
|
+
:return: flux density in erg/cm^2/s/A
|
|
139
|
+
"""
|
|
140
|
+
return self._flux(time, wavelength)
|
|
141
|
+
|
|
142
|
+
def bandflux(self, band, phase, zp=None, zpsys=None):
|
|
143
|
+
"""
|
|
144
|
+
Flux through the given bandpass(es) at the given phase(s).
|
|
145
|
+
|
|
146
|
+
Default return value is flux in photons / s / cm^2. If zp and zpsys
|
|
147
|
+
are given, flux(es) are scaled to the requested zeropoints.
|
|
148
|
+
|
|
149
|
+
Parameters
|
|
150
|
+
----------
|
|
151
|
+
band : str or list_like
|
|
152
|
+
Name(s) of bandpass(es) in registry.
|
|
153
|
+
phase : float or list_like, optional
|
|
154
|
+
Phase(s) in days. Default is `None`, which corresponds to the full
|
|
155
|
+
native phase sampling of the model.
|
|
156
|
+
zp : float or list_like, optional
|
|
157
|
+
If given, zeropoint to scale flux to (must also supply ``zpsys``).
|
|
158
|
+
If not given, flux is not scaled.
|
|
159
|
+
zpsys : str or list_like, optional
|
|
160
|
+
Name of a magnitude system in the registry, specifying the system
|
|
161
|
+
that ``zp`` is in.
|
|
162
|
+
|
|
163
|
+
Returns
|
|
164
|
+
-------
|
|
165
|
+
bandflux : float or `~numpy.ndarray`
|
|
166
|
+
Flux in photons / s /cm^2, unless `zp` and `zpsys` are
|
|
167
|
+
given, in which case flux is scaled so that it corresponds
|
|
168
|
+
to the requested zeropoint. Return value is `float` if all
|
|
169
|
+
input parameters are scalars, `~numpy.ndarray` otherwise.
|
|
170
|
+
"""
|
|
171
|
+
return _bandflux_redback(self, band, phase, zp, zpsys)
|
|
172
|
+
|
|
173
|
+
def bandmag(self, band, magsys, phase):
|
|
174
|
+
"""Magnitude at the given phase(s) through the given
|
|
175
|
+
bandpass(es), and for the given magnitude system(s).
|
|
176
|
+
|
|
177
|
+
Parameters
|
|
178
|
+
----------
|
|
179
|
+
band : str or list_like
|
|
180
|
+
Name(s) of bandpass in registry.
|
|
181
|
+
magsys : str or list_like
|
|
182
|
+
Name(s) of `~sncosmo.MagSystem` in registry.
|
|
183
|
+
phase : float or list_like
|
|
184
|
+
Phase(s) in days.
|
|
185
|
+
|
|
186
|
+
Returns
|
|
187
|
+
-------
|
|
188
|
+
mag : float or `~numpy.ndarray`
|
|
189
|
+
Magnitude for each item in band, magsys, phase.
|
|
190
|
+
The return value is a float if all parameters are not iterables.
|
|
191
|
+
The return value is an `~numpy.ndarray` if any are iterable.
|
|
192
|
+
"""
|
|
193
|
+
return _bandmag_redback(self, band, magsys, phase)
|
|
194
|
+
|
|
195
|
+
|
|
9
196
|
|
|
10
197
|
def blackbody_to_flux_density(temperature, r_photosphere, dl, frequency):
|
|
11
198
|
"""
|
|
@@ -298,13 +485,18 @@ def get_correct_output_format_from_spectra(time, time_eval, spectra, lambda_arra
|
|
|
298
485
|
:param time: times in observer frame in days to evaluate the model on
|
|
299
486
|
:param time_eval: times in observer frame where spectra are evaluated. A densely sampled array for accuracy
|
|
300
487
|
:param bands: band array - must be same length as time array or a single band
|
|
301
|
-
:param spectra: spectra in
|
|
488
|
+
:param spectra: spectra in erg/cm^2/s/A evaluated at all times and frequencies; shape (len(times), len(frequency_array))
|
|
302
489
|
:param lambda_array: wavelenth array in Angstrom in observer frame
|
|
303
490
|
:param kwargs: Additional parameters
|
|
304
491
|
:param output_format: 'flux', 'magnitude', 'sncosmo_source', 'flux_density'
|
|
305
492
|
:return: flux, magnitude or SNcosmo TimeSeries Source depending on output format kwarg
|
|
306
493
|
"""
|
|
307
|
-
|
|
494
|
+
# clean up spectrum to remove nonsensical values before creating sncosmo source
|
|
495
|
+
spectra = np.nan_to_num(spectra)
|
|
496
|
+
spectra[spectra.value == np.nan_to_num(np.inf)] = 1e-30 * np.mean(spectra[5])
|
|
497
|
+
spectra[spectra.value == 0.] = 1e-30 * np.mean(spectra[5])
|
|
498
|
+
|
|
499
|
+
source = RedbackTimeSeriesSource(phase=time_eval, wave=lambda_array, flux=spectra)
|
|
308
500
|
if kwargs['output_format'] == 'flux':
|
|
309
501
|
bands = kwargs['bands']
|
|
310
502
|
magnitude = source.bandmag(phase=time, band=bands, magsys='ab')
|
redback/simulate_transients.py
CHANGED
|
@@ -14,7 +14,7 @@ datadir = os.path.join(os.path.dirname(redback.__file__), 'tables')
|
|
|
14
14
|
|
|
15
15
|
class SimulateGenericTransient(object):
|
|
16
16
|
def __init__(self, model, parameters, times, model_kwargs, data_points,
|
|
17
|
-
seed=1234, multiwavelength_transient=False, noise_term=0.2):
|
|
17
|
+
seed=1234, multiwavelength_transient=False, noise_term=0.2, noise_type='gaussianmodel', extra_scatter=0.0):
|
|
18
18
|
"""
|
|
19
19
|
A generic interface to simulating transients
|
|
20
20
|
|
|
@@ -31,7 +31,12 @@ class SimulateGenericTransient(object):
|
|
|
31
31
|
and the data points are sampled in bands/frequency as well,
|
|
32
32
|
rather than just corresponding to one wavelength/filter.
|
|
33
33
|
This also allows the same time value to be sampled multiple times.
|
|
34
|
-
:param
|
|
34
|
+
:param noise_type: String. Type of noise to add to the model.
|
|
35
|
+
Default is 'gaussianmodel' where sigma is noise_term * model.
|
|
36
|
+
Another option is 'gaussian' i.e., a simple Gaussian noise with sigma = noise_term.
|
|
37
|
+
:param noise_term: Float. Factor which is multiplied by the model flux/magnitude to give the sigma
|
|
38
|
+
or is sigma itself for 'gaussian' noise.
|
|
39
|
+
:param extra_scatter: Float. Sigma of normal added to output for additional scatter.
|
|
35
40
|
"""
|
|
36
41
|
self.model = redback.model_library.all_models_dict[model]
|
|
37
42
|
self.parameters = parameters
|
|
@@ -44,20 +49,25 @@ class SimulateGenericTransient(object):
|
|
|
44
49
|
self.noise_term = noise_term
|
|
45
50
|
random.seed(self.seed)
|
|
46
51
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
raise ValueError('Must supply either bands or frequency to sample data points for an optical transient')
|
|
52
|
-
if self.all_bands is not None and self.all_frequency is None:
|
|
53
|
-
self.subset_bands = np.array(random.choices(self.all_bands, k=self.data_points))
|
|
54
|
-
if self.all_bands is None and self.all_frequency is not None:
|
|
55
|
-
self.subset_frequency = np.array(random.choices(self.all_frequency, k=self.data_points))
|
|
56
|
-
self.replacement = True
|
|
57
|
-
# allow times to be chosen repeatedly
|
|
52
|
+
self.all_bands = self.model_kwargs.get('bands', None)
|
|
53
|
+
self.all_frequency = self.model_kwargs.get('frequency', None)
|
|
54
|
+
if self.all_bands is None and self.all_frequency is None:
|
|
55
|
+
raise ValueError('Must supply either bands or frequency to sample data points for an optical transient')
|
|
58
56
|
else:
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
if multiwavelength_transient:
|
|
58
|
+
if self.all_bands is not None and self.all_frequency is None:
|
|
59
|
+
self.subset_bands = np.array(random.choices(self.all_bands, k=self.data_points))
|
|
60
|
+
if self.all_bands is None and self.all_frequency is not None:
|
|
61
|
+
self.subset_frequency = np.array(random.choices(self.all_frequency, k=self.data_points))
|
|
62
|
+
self.replacement = True
|
|
63
|
+
# allow times to be chosen repeatedly
|
|
64
|
+
else:
|
|
65
|
+
if self.all_bands is not None and self.all_frequency is None:
|
|
66
|
+
self.subset_bands = self.data_points * [self.all_bands]
|
|
67
|
+
if self.all_bands is None and self.all_frequency is not None:
|
|
68
|
+
self.subset_frequency = np.ones(self.data_points) * self.all_frequency
|
|
69
|
+
# allow times to be chosen only once.
|
|
70
|
+
self.replacement = False
|
|
61
71
|
self.subset_times = np.sort(np.random.choice(self.all_times, size=self.data_points, replace=self.replacement))
|
|
62
72
|
|
|
63
73
|
injection_kwargs = self.parameters.copy()
|
|
@@ -76,24 +86,43 @@ class SimulateGenericTransient(object):
|
|
|
76
86
|
if 'frequency' in model_kwargs.keys():
|
|
77
87
|
data['frequency'] = self.subset_frequency
|
|
78
88
|
data['true_output'] = true_output
|
|
79
|
-
|
|
80
|
-
|
|
89
|
+
|
|
90
|
+
if noise_type == 'gaussianmodel':
|
|
91
|
+
noise = np.random.normal(0, self.noise_term * true_output, len(true_output))
|
|
92
|
+
output = true_output + noise
|
|
93
|
+
output_error = self.noise_term * true_output
|
|
94
|
+
elif noise_type == 'gaussian':
|
|
95
|
+
noise = np.random.normal(0, self.noise_term, len(true_output))
|
|
96
|
+
output = true_output + noise
|
|
97
|
+
output_error = self.noise_term
|
|
98
|
+
else:
|
|
99
|
+
logger.warning(f"noise_type {noise_type} not implemented.")
|
|
100
|
+
raise ValueError('noise_type must be either gaussianmodel or gaussian')
|
|
101
|
+
|
|
102
|
+
if extra_scatter > 0:
|
|
103
|
+
extra_noise = np.random.normal(0, extra_scatter, len(true_output))
|
|
104
|
+
output = output + extra_noise
|
|
105
|
+
output_error = np.sqrt(output_error**2 + extra_noise**2)
|
|
106
|
+
|
|
107
|
+
data['output'] = output
|
|
108
|
+
data['output_error'] = output_error
|
|
81
109
|
self.data = data
|
|
82
110
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
111
|
+
def save_transient(self, name):
|
|
112
|
+
"""
|
|
113
|
+
Save the transient observations to a csv file.
|
|
114
|
+
This will save the full observational dataframe including non-detections etc.
|
|
115
|
+
This will save the data to a folder called 'simulated'
|
|
116
|
+
with the name of the transient and a csv file of the injection parameters
|
|
117
|
+
|
|
118
|
+
:param name: name to save transient.
|
|
119
|
+
"""
|
|
120
|
+
bilby.utils.check_directory_exists_and_if_not_mkdir('simulated')
|
|
121
|
+
path = 'simulated/' + name + '.csv'
|
|
122
|
+
injection_path = 'simulated/' + name + '_injection_parameters.csv'
|
|
123
|
+
self.data.to_csv(path, index=False)
|
|
124
|
+
self.parameters=pd.DataFrame.from_dict([self.parameters])
|
|
125
|
+
self.parameters.to_csv(injection_path, index=False)
|
|
97
126
|
|
|
98
127
|
class SimulateOpticalTransient(object):
|
|
99
128
|
def __init__(self, model, parameters, pointings_database=None,
|
|
@@ -415,7 +444,7 @@ class SimulateOpticalTransient(object):
|
|
|
415
444
|
Convert the circular field of view to a radius in radians.
|
|
416
445
|
:return: survey_radius in radians
|
|
417
446
|
"""
|
|
418
|
-
survey_fov_sqrad = self.survey_fov_sqdeg*(np.pi/180.0)
|
|
447
|
+
survey_fov_sqrad = self.survey_fov_sqdeg*(np.pi/180.0)**2
|
|
419
448
|
survey_radius = np.sqrt(survey_fov_sqrad/np.pi)
|
|
420
449
|
# survey_radius = np.sqrt(self.survey_fov_sqdeg*((np.pi/180.0)**2.0)/np.pi)
|
|
421
450
|
return survey_radius
|
redback/tables/filters.csv
CHANGED
|
@@ -238,3 +238,17 @@ euclid::VIS,4.223e+14,7103.37,black,7.577e-06,euclid::VIS,EUCLID/VIS
|
|
|
238
238
|
efosc2::g,5.866e+14,5114.66,black,3.302e-06,efosc2::g,EFOSC2/g
|
|
239
239
|
efosc2::r,4.493e+14,6677.40,black,2.342e-06,efosc2::r,EFOSC2/r
|
|
240
240
|
efosc2::i,3.758e+14,7983.20,black,2.435e-06,efosc2::i,EFOSC2/i
|
|
241
|
+
desg,6.2390e+14,4808.49,black,4.781e-06,desg,DES/g
|
|
242
|
+
desr,4.6746e+14,6417.65,black,3.409e-06,desr,DES/r
|
|
243
|
+
desi,3.8390e+14,7814.58,black,2.300e-06,desi,DES/i
|
|
244
|
+
desz,3.2719e+14,9168.85,black,1.679e-06,desz,DES/z
|
|
245
|
+
desy,3.0315e+14,9896.11,black,7.511e-07,desy,DES/y
|
|
246
|
+
tess,3.8973e+14,7697.6,black,7.658e-06,tess,TESS
|
|
247
|
+
gaia::gbp,5.8712e+14,5109.71,black,9.421e-06,gaia::gbp,GAIA/Gbp
|
|
248
|
+
gaia::g,4.799e+14,6217.59,black,1.278e-05,gaia::g,GAIA/G
|
|
249
|
+
gaia::grp,3.8615e+14,7769.02,black,5.472e-06,gaia::grp,GAIA/Grp
|
|
250
|
+
gaia::grvs,3.4970e+14,8578.76,black,3.481e-07,gaia::grvs,GAIA/Grvs
|
|
251
|
+
gotob,6.4895e+14,4622.88,black,3.771e-06,gotob,GOTO/B
|
|
252
|
+
gotog,5.5819e+14,5374.54,black,3.255e-06,gotog,GOTO/G
|
|
253
|
+
gotol,5.4311e+14,5523.78,black,8.027e-06,gotol,GOTO/L
|
|
254
|
+
gotor,4.6679e+14,6426.84,black,2.510e-06,gotor,GOTO/R
|
redback/tables/ztf.tar.gz
CHANGED
|
Binary file
|
redback/transient/afterglow.py
CHANGED
|
@@ -57,7 +57,7 @@ class Afterglow(Transient):
|
|
|
57
57
|
:type flux: np.ndarray, optional
|
|
58
58
|
:type flux_err: np.ndarray, optional
|
|
59
59
|
:param flux_err: Flux error values.
|
|
60
|
-
:param flux_density:Flux density values.
|
|
60
|
+
:param flux_density: Flux density values.
|
|
61
61
|
:type flux_density: np.ndarray, optional
|
|
62
62
|
:param flux_density_err: Flux density error values.
|
|
63
63
|
:type flux_density_err: np.ndarray, optional
|
|
@@ -244,7 +244,8 @@ class Afterglow(Transient):
|
|
|
244
244
|
'BAT Photon Index (15-150 keV) (PL = simple power-law, CPL = cutoff power-law)'].fillna(0)
|
|
245
245
|
self.meta_data = meta_data
|
|
246
246
|
except FileNotFoundError:
|
|
247
|
-
logger.
|
|
247
|
+
logger.info("Metadata does not exist for this event.")
|
|
248
|
+
logger.info("Setting metadata to None. This is not an error, but a warning that no metadata could be found online.")
|
|
248
249
|
self.meta_data = None
|
|
249
250
|
|
|
250
251
|
def _set_photon_index(self) -> None:
|
redback/transient/kilonova.py
CHANGED
|
@@ -50,7 +50,7 @@ class Kilonova(OpticalTransient):
|
|
|
50
50
|
:type flux: np.ndarray, optional
|
|
51
51
|
:type flux_err: np.ndarray, optional
|
|
52
52
|
:param flux_err: Flux error values.
|
|
53
|
-
:param flux_density:Flux density values.
|
|
53
|
+
:param flux_density: Flux density values.
|
|
54
54
|
:type flux_density: np.ndarray, optional
|
|
55
55
|
:param flux_density_err: Flux density error values.
|
|
56
56
|
:type flux_density_err: np.ndarray, optional
|
redback/transient/supernova.py
CHANGED
|
@@ -45,7 +45,7 @@ class Supernova(OpticalTransient):
|
|
|
45
45
|
:type flux: np.ndarray, optional
|
|
46
46
|
:type flux_err: np.ndarray, optional
|
|
47
47
|
:param flux_err: Flux error values.
|
|
48
|
-
:param flux_density:Flux density values.
|
|
48
|
+
:param flux_density: Flux density values.
|
|
49
49
|
:type flux_density: np.ndarray, optional
|
|
50
50
|
:param flux_density_err: Flux density error values.
|
|
51
51
|
:type flux_density_err: np.ndarray, optional
|
redback/transient/tde.py
CHANGED
|
@@ -42,7 +42,7 @@ class TDE(OpticalTransient):
|
|
|
42
42
|
:type flux: np.ndarray, optional
|
|
43
43
|
:type flux_err: np.ndarray, optional
|
|
44
44
|
:param flux_err: Flux error values.
|
|
45
|
-
:param flux_density:Flux density values.
|
|
45
|
+
:param flux_density: Flux density values.
|
|
46
46
|
:type flux_density: np.ndarray, optional
|
|
47
47
|
:param flux_density_err: Flux density error values.
|
|
48
48
|
:type flux_density_err: np.ndarray, optional
|
redback/transient/transient.py
CHANGED
|
@@ -137,7 +137,7 @@ class Transient(object):
|
|
|
137
137
|
self.system = system
|
|
138
138
|
self.data_mode = data_mode
|
|
139
139
|
self.active_bands = active_bands
|
|
140
|
-
self.sncosmo_bands = redback.utils.sncosmo_bandname_from_band(self.bands
|
|
140
|
+
self.sncosmo_bands = redback.utils.sncosmo_bandname_from_band(self.bands)
|
|
141
141
|
self.redshift = redshift
|
|
142
142
|
self.name = name
|
|
143
143
|
self.use_phase_model = use_phase_model
|
|
@@ -906,7 +906,7 @@ class OpticalTransient(Transient):
|
|
|
906
906
|
meta_data = pd.read_csv(self.event_table, on_bad_lines='skip', delimiter=',', dtype='str')
|
|
907
907
|
except FileNotFoundError as e:
|
|
908
908
|
redback.utils.logger.warning(e)
|
|
909
|
-
redback.utils.logger.warning("Setting metadata to None")
|
|
909
|
+
redback.utils.logger.warning("Setting metadata to None. This is not an error, but a warning that no metadata could be found online.")
|
|
910
910
|
meta_data = None
|
|
911
911
|
self.meta_data = meta_data
|
|
912
912
|
|