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
|
@@ -2092,6 +2092,48 @@ def tophat(time, redshift, thv, loge0, thc, logn0, p, logepse, logepsb, ksin, g0
|
|
|
2092
2092
|
elif kwargs['output_format'] == 'magnitude':
|
|
2093
2093
|
return calc_ABmag_from_flux_density(flux_density).value
|
|
2094
2094
|
|
|
2095
|
+
|
|
2096
|
+
def tophat_from_emulator(time, redshift, thv, loge0, thc, logn0, p, logepse, logepsb, g0, **kwargs):
|
|
2097
|
+
"""
|
|
2098
|
+
Evaluate a tophat afterglow model using an mpl regressor. Note that this model predicts for a fixed redshift = 0.01 and fixed ksin = 1.
|
|
2099
|
+
This tophat model does not include all of the ususal kwargs
|
|
2100
|
+
|
|
2101
|
+
:param time: time in days in observer frame, should be in range 0.1 to 300
|
|
2102
|
+
:param redshift: source redshift
|
|
2103
|
+
:param thv: viewing angle in radians
|
|
2104
|
+
:param loge0: log10 on axis isotropic equivalent energy
|
|
2105
|
+
:param thc: half width of jet core/jet opening angle in radians
|
|
2106
|
+
:param logn0: log10 number density of ISM in cm^-3
|
|
2107
|
+
:param p: electron distribution power law index. Must be greater than 2.
|
|
2108
|
+
:param logepse: log10 fraction of thermal energy in electrons
|
|
2109
|
+
:param logepsb: log10 fraction of thermal energy in magnetic field
|
|
2110
|
+
:param g0: initial lorentz factor
|
|
2111
|
+
:param kwargs: Additional keyword arguments
|
|
2112
|
+
:param frequency: frequency of the band to view in- single number or same length as time array
|
|
2113
|
+
:param output_format: Whether to output flux density or AB mag, specified by 'flux_density' or 'magnitude'
|
|
2114
|
+
:return: flux density or AB mag predicted by emulator. Note this is going to give the monochromatic magnitude at the effective frequency for the band.
|
|
2115
|
+
For a proper calculation of the magntitude use the sed variant models
|
|
2116
|
+
"""
|
|
2117
|
+
|
|
2118
|
+
from redback_surrogates.afterglowmodels import tophat_emulator
|
|
2119
|
+
|
|
2120
|
+
z1=0.01
|
|
2121
|
+
z2= redshift
|
|
2122
|
+
frequency= np.log10(kwargs['frequency'])
|
|
2123
|
+
flux_density = tophat_emulator(new_time=time/(1+z2), thv=thv, loge0=loge0, thc=thc, logn0=logn0, p=p,
|
|
2124
|
+
logepse=logepse, logepsb=logepsb, g0=g0,frequency=frequency)
|
|
2125
|
+
|
|
2126
|
+
#scaling flux density with redshift
|
|
2127
|
+
dl1 = cosmo.luminosity_distance(z1)
|
|
2128
|
+
dl2 = cosmo.luminosity_distance(z2)
|
|
2129
|
+
scale_factor = ((dl1**2)*(1+z1)) / (dl2**2)
|
|
2130
|
+
flux_density=flux_density*scale_factor
|
|
2131
|
+
|
|
2132
|
+
if kwargs['output_format'] == 'flux_density':
|
|
2133
|
+
return flux_density
|
|
2134
|
+
elif kwargs['output_format'] == 'magnitude':
|
|
2135
|
+
return calc_ABmag_from_flux_density(flux_density).value
|
|
2136
|
+
|
|
2095
2137
|
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2020ApJ...896..166R/abstract')
|
|
2096
2138
|
def afterglow_models_with_energy_injection(time, **kwargs):
|
|
2097
2139
|
"""
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import redback.transient_models.extinction_models
|
|
2
|
-
|
|
1
|
+
import redback.transient_models.extinction_models as em
|
|
2
|
+
from redback.utils import citation_wrapper
|
|
3
|
+
|
|
4
|
+
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2020ApJ...896..166R/abstract, https://ui.adsabs.harvard.edu/abs/2020ApJ...891..152H/abstract')
|
|
5
|
+
def tophat_and_twolayerstratified(time, redshift, av, thv, loge0, thc, logn0, p, logepse,
|
|
6
|
+
logepsb, ksin, g0, mej, vej_1, vej_2, kappa, beta, **kwargs):
|
|
3
7
|
|
|
4
8
|
"""
|
|
5
9
|
function to combine the flux density signals of a tophat afterglow and a two layer stratified kilonova with extinction
|
|
@@ -36,18 +40,20 @@ def tophat_and_twolayerstratified(time, redshift, av, thv, loge0, thc, logn0, p,
|
|
|
36
40
|
"""
|
|
37
41
|
kwargs['output_format']='flux_density'
|
|
38
42
|
kwargs['base_model']='tophat'
|
|
39
|
-
afterglow =
|
|
43
|
+
afterglow = em.extinction_with_afterglow_base_model(time=time, redshift=redshift, av=av,
|
|
40
44
|
thv=thv, loge0=loge0 , thc= thc, logn0=logn0, p=p, logepse=logepse, logepsb=logepsb, ksin=ksin, g0=g0,
|
|
41
45
|
**kwargs)
|
|
42
46
|
kwargs['base_model']='two_layer_stratified_kilonova'
|
|
43
|
-
kilonova =
|
|
47
|
+
kilonova = em.extinction_with_kilonova_base_model(time=time, redshift=redshift, av=av,
|
|
44
48
|
mej=mej, vej_1=vej_1, vej_2=vej_2, kappa=kappa, beta=beta, **kwargs)
|
|
45
49
|
|
|
46
50
|
combined = afterglow+kilonova
|
|
47
51
|
return combined
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
def tophat_and_twocomponent(time, redshift, av, thv, loge0, thc, logn0,
|
|
53
|
+
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2020ApJ...896..166R/abstract, redback')
|
|
54
|
+
def tophat_and_twocomponent(time, redshift, av, thv, loge0, thc, logn0,
|
|
55
|
+
p, logepse, logepsb, ksin, g0, mej_1, vej_1,
|
|
56
|
+
temperature_floor_1, kappa_1, mej_2, vej_2, temperature_floor_2, kappa_2, **kwargs):
|
|
51
57
|
|
|
52
58
|
"""
|
|
53
59
|
function to combine the flux density signals of a tophat afterglow and a two component kilonova with extinction added
|
|
@@ -85,19 +91,21 @@ def tophat_and_twocomponent(time, redshift, av, thv, loge0, thc, logn0, p, logep
|
|
|
85
91
|
:return: flux density signal with extinction added
|
|
86
92
|
"""
|
|
87
93
|
|
|
88
|
-
kwargs['output_format']='flux_density'
|
|
89
|
-
kwargs['base_model']='tophat'
|
|
90
|
-
afterglow =
|
|
91
|
-
thv=thv, loge0=loge0
|
|
92
|
-
|
|
93
|
-
kwargs['base_model']='two_component_kilonova_model'
|
|
94
|
-
kilonova =
|
|
95
|
-
|
|
94
|
+
kwargs['output_format'] = 'flux_density'
|
|
95
|
+
kwargs['base_model'] = 'tophat'
|
|
96
|
+
afterglow = em.extinction_with_afterglow_base_model(time=time, redshift=redshift, av=av,
|
|
97
|
+
thv=thv, loge0=loge0, thc=thc, logn0=logn0, p=p, logepse=logepse, logepsb=logepsb, ksin=ksin, g0=g0,**kwargs)
|
|
98
|
+
|
|
99
|
+
kwargs['base_model'] = 'two_component_kilonova_model'
|
|
100
|
+
kilonova = em.extinction_with_kilonova_base_model(time=time, redshift=redshift, av=av,
|
|
101
|
+
mej_1=mej_1, vej_1=vej_1, temperature_floor_1=temperature_floor_1,
|
|
102
|
+
kappa_1=kappa_1, mej_2=mej_2, vej_2=vej_2,
|
|
103
|
+
temperature_floor_2=temperature_floor_2, kappa_2=kappa_2, **kwargs)
|
|
96
104
|
|
|
97
105
|
combined = afterglow + kilonova
|
|
98
106
|
return combined
|
|
99
107
|
|
|
100
|
-
|
|
108
|
+
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2020ApJ...896..166R/abstract, https://ui.adsabs.harvard.edu/abs/1982ApJ...253..785A/abstract')
|
|
101
109
|
def tophat_and_arnett(time, av, redshift, thv, loge0, thc, logn0, p, logepse, logepsb, ksin, g0, f_nickel, mej, **kwargs):
|
|
102
110
|
|
|
103
111
|
"""
|
|
@@ -137,19 +145,20 @@ def tophat_and_arnett(time, av, redshift, thv, loge0, thc, logn0, p, logepse, lo
|
|
|
137
145
|
:return: flux density with extinction added
|
|
138
146
|
"""
|
|
139
147
|
|
|
140
|
-
kwargs['output_format']='flux_density'
|
|
141
|
-
kwargs['base_model']='tophat'
|
|
142
|
-
afterglow =
|
|
143
|
-
thv=thv, loge0=loge0
|
|
148
|
+
kwargs['output_format'] = 'flux_density'
|
|
149
|
+
kwargs['base_model'] = 'tophat'
|
|
150
|
+
afterglow = em.extinction_with_afterglow_base_model(time=time, redshift=redshift, av=av,
|
|
151
|
+
thv=thv, loge0=loge0, thc=thc, logn0=logn0, p=p, logepse=logepse, logepsb=logepsb, ksin=ksin, g0=g0,
|
|
144
152
|
**kwargs)
|
|
145
|
-
kwargs['base_model']='arnett'
|
|
146
|
-
supernova =
|
|
153
|
+
kwargs['base_model'] = 'arnett'
|
|
154
|
+
supernova = em.extinction_with_supernova_base_model(time=time, redshift=redshift, av=av,
|
|
147
155
|
f_nickel=f_nickel, mej=mej, **kwargs)
|
|
148
156
|
|
|
149
157
|
combined = afterglow + supernova
|
|
150
158
|
return combined
|
|
151
159
|
|
|
152
|
-
|
|
160
|
+
@citation_wrapper('redback, and any citations for the specific model you use')
|
|
161
|
+
def afterglow_and_optical(time, redshift, av, **model_kwargs):
|
|
153
162
|
|
|
154
163
|
"""
|
|
155
164
|
function to combine the signals of any afterglow and any other optical transient with extinction added
|
|
@@ -157,26 +166,32 @@ def afterglow_and_optical(time, redshift, av, model_type, afterglow_kwargs, opti
|
|
|
157
166
|
:param time: time in days in observer frame
|
|
158
167
|
:param redshift: source redshift
|
|
159
168
|
:param av: absolute mag extinction
|
|
169
|
+
:param model_kwargs: kwargs shared by models e.g. output_format, frequency, bands, r_v (extinction paramater defaults to 3.1)
|
|
160
170
|
:param model_type: specify type of optical transient model- 'supernova', 'tde', 'kilonova', 'magnetar_driven', 'shock_powered'
|
|
161
171
|
:param afterglow_kwargs: dictionary of parameters required by the afterglow transient model specified by 'base_model'
|
|
162
172
|
and any additional keyword arguments. Refer to model documentation for details.
|
|
163
173
|
:param optical_kwargs: dictionary of parameters required by the optical transient model specifed by 'base_model'
|
|
164
174
|
and any additional keyword arguments. Note the base model must correspond to the given model type. Refer to model documentation
|
|
165
175
|
for details.
|
|
166
|
-
:param shared_kwargs: kwargs shared by models e.g. output_format, frequency, bands, r_v (extinction paramater defaults to 3.1)
|
|
167
176
|
:return: set by shared_kwargs output format - 'flux_density' or 'magnitude' with extinction added
|
|
168
177
|
note that only afterglow_models_sed allow for magnitude outputs
|
|
169
178
|
"""
|
|
179
|
+
|
|
180
|
+
optical_kwargs = model_kwargs['optical_kwargs']
|
|
181
|
+
afterglow_kwargs = model_kwargs['afterglow_kwargs']
|
|
182
|
+
|
|
183
|
+
_afterglow_kwargs = afterglow_kwargs.copy()
|
|
184
|
+
_afterglow_kwargs.update(model_kwargs)
|
|
185
|
+
_afterglow_kwargs.pop('model_type')
|
|
186
|
+
|
|
187
|
+
_optical_kwargs = optical_kwargs.copy()
|
|
188
|
+
_optical_kwargs.update(model_kwargs)
|
|
189
|
+
|
|
190
|
+
afterglow = em._evaluate_extinction_model(time=time, redshift=redshift, av=av,model_type='afterglow',
|
|
191
|
+
**_afterglow_kwargs)
|
|
170
192
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
afterglow = redback.transient_models.extinction_models._evaluate_extinction_model(time=time, redshift=redshift, av=av,
|
|
175
|
-
model_type='afterglow', **afterglow_kwargs)
|
|
176
|
-
|
|
177
|
-
optical= redback.transient_models.extinction_models._evaluate_extinction_model(time=time, redshift=redshift, av=av,
|
|
178
|
-
model_type=model_type, **optical_kwargs)
|
|
179
|
-
|
|
193
|
+
optical = em._evaluate_extinction_model(time=time, redshift=redshift, av=av, **_optical_kwargs)
|
|
194
|
+
|
|
180
195
|
combined= afterglow + optical
|
|
181
196
|
return combined
|
|
182
197
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from inspect import isfunction
|
|
2
2
|
import numpy as np
|
|
3
|
-
|
|
4
3
|
import redback.utils
|
|
5
4
|
from redback.transient_models.fireball_models import predeceleration
|
|
6
5
|
from redback.utils import logger, calc_ABmag_from_flux_density, citation_wrapper, lambda_to_nu
|
|
@@ -12,12 +11,14 @@ extinction_afterglow_base_models = ['tophat', 'cocoon', 'gaussian',
|
|
|
12
11
|
'kn_afterglow', 'cone_afterglow',
|
|
13
12
|
'gaussiancore', 'gaussian',
|
|
14
13
|
'smoothpowerlaw', 'powerlawcore',
|
|
14
|
+
'tophat','tophat_from_emulator',
|
|
15
15
|
'kilonova_afterglow_redback', 'kilonova_afterglow_nakarpiran',
|
|
16
16
|
'tophat_redback', 'gaussian_redback', 'twocomponent_redback',
|
|
17
17
|
'powerlaw_redback', 'alternativepowerlaw_redback', 'doublegaussian_redback',
|
|
18
18
|
'tophat_redback_refreshed', 'gaussian_redback_refreshed',
|
|
19
19
|
'twocomponent_redback_refreshed','powerlaw_redback_refreshed',
|
|
20
20
|
'alternativepowerlaw_redback_refreshed', 'doublegaussian_redback_refreshed']
|
|
21
|
+
|
|
21
22
|
extinction_integrated_flux_afterglow_models = extinction_afterglow_base_models
|
|
22
23
|
extinction_supernova_base_models = ['sn_exponential_powerlaw', 'arnett', 'shock_cooling_and_arnett',
|
|
23
24
|
'basic_magnetar_powered', 'slsn', 'magnetar_nickel',
|
|
@@ -25,17 +26,17 @@ extinction_supernova_base_models = ['sn_exponential_powerlaw', 'arnett', 'shock_
|
|
|
25
26
|
'general_magnetar_slsn','general_magnetar_driven_supernova']
|
|
26
27
|
extinction_kilonova_base_models = ['nicholl_bns', 'mosfit_rprocess', 'mosfit_kilonova',
|
|
27
28
|
'power_law_stratified_kilonova','bulla_bns_kilonova',
|
|
28
|
-
'bulla_nsbh_kilonova', '
|
|
29
|
+
'bulla_nsbh_kilonova', 'kasen_bns_kilonova','two_layer_stratified_kilonova',
|
|
29
30
|
'three_component_kilonova_model', 'two_component_kilonova_model',
|
|
30
31
|
'one_component_kilonova_model', 'one_component_ejecta_relation',
|
|
31
32
|
'one_component_ejecta_relation_projection', 'two_component_bns_ejecta_relation',
|
|
32
33
|
'polytrope_eos_two_component_bns', 'one_component_nsbh_ejecta_relation',
|
|
33
34
|
'two_component_nsbh_ejecta_relation','metzger_kilonova_model']
|
|
34
35
|
extinction_tde_base_models = ['tde_analytical', 'tde_semianalytical', 'gaussianrise_cooling_envelope',
|
|
35
|
-
'cooling_envelope']
|
|
36
|
+
'cooling_envelope', 'bpl_cooling_envelope']
|
|
36
37
|
extinction_magnetar_driven_base_models = ['basic_mergernova', 'general_mergernova', 'general_mergernova_thermalisation',
|
|
37
38
|
'general_mergernova_evolution', 'metzger_magnetar_driven_kilonova_model',
|
|
38
|
-
'general_metzger_magnetar_driven', '
|
|
39
|
+
'general_metzger_magnetar_driven', 'general_metzger_magnetar_driven_thermalisation',
|
|
39
40
|
'general_metzger_magnetar_driven_evolution']
|
|
40
41
|
extinction_shock_powered_base_models = ['shocked_cocoon', 'shock_cooling']
|
|
41
42
|
|
|
@@ -10,7 +10,7 @@ from redback.photosphere import TemperatureFloor, CocoonPhotosphere
|
|
|
10
10
|
from redback.interaction_processes import Diffusion, AsphericalDiffusion
|
|
11
11
|
|
|
12
12
|
from redback.utils import calc_kcorrected_properties, interpolated_barnes_and_kasen_thermalisation_efficiency, \
|
|
13
|
-
electron_fraction_from_kappa, citation_wrapper, lambda_to_nu
|
|
13
|
+
electron_fraction_from_kappa, citation_wrapper, lambda_to_nu, get_heating_terms, kappa_from_electron_fraction
|
|
14
14
|
from redback.eos import PiecewisePolytrope
|
|
15
15
|
from redback.sed import blackbody_to_flux_density, get_correct_output_format_from_spectra, Blackbody
|
|
16
16
|
from redback.constants import *
|
|
@@ -476,7 +476,7 @@ def mosfit_rprocess(time, redshift, mej, vej, kappa, kappa_gamma, temperature_fl
|
|
|
476
476
|
cosmology = kwargs.get('cosmology', cosmo)
|
|
477
477
|
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
478
478
|
dense_resolution = kwargs.get('dense_resolution', 300)
|
|
479
|
-
time_temp = np.geomspace(1e-2,
|
|
479
|
+
time_temp = np.geomspace(1e-2, 7e6, dense_resolution) # in source frame
|
|
480
480
|
time_obs = time
|
|
481
481
|
lbols = _mosfit_kilonova_one_component_lbol(time=time_temp,
|
|
482
482
|
mej=mej, vej=vej)
|
|
@@ -555,7 +555,7 @@ def mosfit_kilonova(time, redshift, mej_1, vej_1, temperature_floor_1, kappa_1,
|
|
|
555
555
|
cosmology = kwargs.get('cosmology', cosmo)
|
|
556
556
|
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
557
557
|
dense_resolution = kwargs.get('dense_resolution', 300)
|
|
558
|
-
time_temp = np.geomspace(1e-2,
|
|
558
|
+
time_temp = np.geomspace(1e-2, 7e6, dense_resolution) # in source frame
|
|
559
559
|
time_obs = time
|
|
560
560
|
mej = [mej_1, mej_2, mej_3]
|
|
561
561
|
vej = [vej_1, vej_2, vej_3]
|
|
@@ -817,7 +817,7 @@ def kasen_bns_kilonova(time, redshift, mej, vej, chi, **kwargs):
|
|
|
817
817
|
fmjy = spectra.to(uu.mJy, equivalencies=uu.spectral_density(wav=output.lambdas * uu.Angstrom)).value
|
|
818
818
|
nu_array = lambda_to_nu(output.lambdas)
|
|
819
819
|
fmjy_func = RegularGridInterpolator((np.unique(time), nu_array), fmjy, bounds_error=False)
|
|
820
|
-
if type(frequency) == float:
|
|
820
|
+
if type(frequency) == float or type(frequency) == np.float64:
|
|
821
821
|
frequency = np.ones(len(time)) * frequency
|
|
822
822
|
points = np.array([time, frequency]).T
|
|
823
823
|
return fmjy_func(points)
|
|
@@ -890,6 +890,11 @@ def _kilonova_hr(time, redshift, mej, velocity_array, kappa_array, beta, **kwarg
|
|
|
890
890
|
time = time * day_to_s
|
|
891
891
|
# convert to source frame time and frequency
|
|
892
892
|
frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
|
|
893
|
+
if (isinstance(frequency, (float, int)) == False):
|
|
894
|
+
radio_mask = frequency < 10e10
|
|
895
|
+
frequency[radio_mask]=10e50
|
|
896
|
+
elif frequency < 10e10:
|
|
897
|
+
frequency =10e50
|
|
893
898
|
|
|
894
899
|
_, temperature, r_photosphere = _kilonova_hr_sourceframe(time, mej, velocity_array, kappa_array, beta)
|
|
895
900
|
|
|
@@ -974,7 +979,7 @@ def three_component_kilonova_model(time, redshift, mej_1, vej_1, temperature_flo
|
|
|
974
979
|
"""
|
|
975
980
|
cosmology = kwargs.get('cosmology', cosmo)
|
|
976
981
|
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
977
|
-
time_temp = np.geomspace(1e-2,
|
|
982
|
+
time_temp = np.geomspace(1e-2, 7e6, 300) # in source frame
|
|
978
983
|
time_obs = time
|
|
979
984
|
|
|
980
985
|
mej = [mej_1, mej_2, mej_3]
|
|
@@ -1063,7 +1068,7 @@ def two_component_kilonova_model(time, redshift, mej_1, vej_1, temperature_floor
|
|
|
1063
1068
|
"""
|
|
1064
1069
|
cosmology = kwargs.get('cosmology', cosmo)
|
|
1065
1070
|
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
1066
|
-
time_temp = np.geomspace(1e-2,
|
|
1071
|
+
time_temp = np.geomspace(1e-2, 7e6, 300) # in source frame
|
|
1067
1072
|
time_obs = time
|
|
1068
1073
|
|
|
1069
1074
|
mej = [mej_1, mej_2]
|
|
@@ -1376,7 +1381,7 @@ def one_component_kilonova_model(time, redshift, mej, vej, kappa, **kwargs):
|
|
|
1376
1381
|
"""
|
|
1377
1382
|
cosmology = kwargs.get('cosmology', cosmo)
|
|
1378
1383
|
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
1379
|
-
time_temp = np.geomspace(1e-3,
|
|
1384
|
+
time_temp = np.geomspace(1e-3, 7e6, 300) # in source frame
|
|
1380
1385
|
time_obs = time
|
|
1381
1386
|
_, temperature, r_photosphere = _one_component_kilonova_model(time_temp, mej, vej, kappa, **kwargs)
|
|
1382
1387
|
|
|
@@ -1416,6 +1421,234 @@ def one_component_kilonova_model(time, redshift, mej, vej, kappa, **kwargs):
|
|
|
1416
1421
|
spectra=spectra, lambda_array=lambda_observer_frame,
|
|
1417
1422
|
**kwargs)
|
|
1418
1423
|
|
|
1424
|
+
|
|
1425
|
+
def _calc_new_heating_rate(time, mej, electron_fraction, ejecta_velocity, **kwargs):
|
|
1426
|
+
"""
|
|
1427
|
+
Heating rate prescription following Rosswog and Korobkin 2022
|
|
1428
|
+
|
|
1429
|
+
:param time: time in seconds
|
|
1430
|
+
:param mej: ejecta mass in solar masses
|
|
1431
|
+
:param electron_fraction: electron fraction
|
|
1432
|
+
:param ejecta_velocity: ejecta velocity in c
|
|
1433
|
+
:param kwargs: Additional keyword arguments
|
|
1434
|
+
:param heating_rate_perturbation: A fudge factor for heating rate to account for uncertainties in the heating rate. Default is 1.0 i.e., no perturbation.
|
|
1435
|
+
:param heating_rate_fudge: A fudge factor for each of the terms in the heating rate. Default to 1. i.e., no uncertainty
|
|
1436
|
+
Default is 1.0 i.e., no perturbation.
|
|
1437
|
+
:return: heating rate in erg/s
|
|
1438
|
+
"""
|
|
1439
|
+
heating_terms = get_heating_terms(electron_fraction, ejecta_velocity, **kwargs)
|
|
1440
|
+
heating_rate_perturbation = kwargs.get('heating_rate_perturbation', 1.0)
|
|
1441
|
+
# rescale
|
|
1442
|
+
m0 = mej * solar_mass
|
|
1443
|
+
c1 = np.exp(heating_terms.c1)
|
|
1444
|
+
c2 = np.exp(heating_terms.c2)
|
|
1445
|
+
c3 = np.exp(heating_terms.c3)
|
|
1446
|
+
tau1 = 1e3*heating_terms.tau1
|
|
1447
|
+
tau2 = 1e5*heating_terms.tau2
|
|
1448
|
+
tau3 = 1e5*heating_terms.tau3
|
|
1449
|
+
term1 = 10.**(heating_terms.e0+18) * (0.5 - np.arctan((time - heating_terms.t0) / heating_terms.sig) / np.pi)**heating_terms.alp
|
|
1450
|
+
term2 = (0.5 + np.arctan((time - heating_terms.t1)/heating_terms.sig1) / np.pi )**heating_terms.alp1
|
|
1451
|
+
term3 = c1 * np.exp(-time/tau1)
|
|
1452
|
+
term4 = c2 * np.exp(-time/tau2)
|
|
1453
|
+
term5 = c3 * np.exp(-time/tau3)
|
|
1454
|
+
lum_in = term1*term2 + term3 + term4 + term5
|
|
1455
|
+
return lum_in*m0 * heating_rate_perturbation
|
|
1456
|
+
|
|
1457
|
+
def _one_component_kilonova_rosswog_heatingrate(time, mej, vej, electron_fraction, **kwargs):
|
|
1458
|
+
tdays = time/day_to_s
|
|
1459
|
+
# set up kilonova physics
|
|
1460
|
+
av, bv, dv = interpolated_barnes_and_kasen_thermalisation_efficiency(mej, vej)
|
|
1461
|
+
# thermalisation from Barnes+16
|
|
1462
|
+
e_th = 0.36 * (np.exp(-av * tdays) + np.log1p(2.0 * bv * tdays ** dv) / (2.0 * bv * tdays ** dv))
|
|
1463
|
+
temperature_floor = kwargs.get('temperature_floor', 4000) # kelvin
|
|
1464
|
+
beta = 13.7
|
|
1465
|
+
|
|
1466
|
+
v0 = vej * speed_of_light
|
|
1467
|
+
m0 = mej * solar_mass
|
|
1468
|
+
kappa = kappa_from_electron_fraction(electron_fraction)
|
|
1469
|
+
tdiff = np.sqrt(2.0 * kappa * (m0) / (beta * v0 * speed_of_light))
|
|
1470
|
+
|
|
1471
|
+
lum_in = _calc_new_heating_rate(time, mej, electron_fraction, vej, **kwargs)
|
|
1472
|
+
integrand = lum_in * e_th * (time / tdiff) * np.exp(time ** 2 / tdiff ** 2)
|
|
1473
|
+
|
|
1474
|
+
bolometric_luminosity = np.zeros(len(time))
|
|
1475
|
+
bolometric_luminosity[1:] = cumtrapz(integrand, time)
|
|
1476
|
+
bolometric_luminosity[0] = bolometric_luminosity[1]
|
|
1477
|
+
bolometric_luminosity = bolometric_luminosity * np.exp(-time ** 2 / tdiff ** 2) / tdiff
|
|
1478
|
+
|
|
1479
|
+
temperature = (bolometric_luminosity / (4.0 * np.pi * sigma_sb * v0 ** 2 * time ** 2)) ** 0.25
|
|
1480
|
+
r_photosphere = (bolometric_luminosity / (4.0 * np.pi * sigma_sb * temperature_floor ** 4)) ** 0.5
|
|
1481
|
+
|
|
1482
|
+
# check temperature floor conditions
|
|
1483
|
+
mask = temperature <= temperature_floor
|
|
1484
|
+
temperature[mask] = temperature_floor
|
|
1485
|
+
mask = np.logical_not(mask)
|
|
1486
|
+
r_photosphere[mask] = v0 * time[mask]
|
|
1487
|
+
return bolometric_luminosity, temperature, r_photosphere
|
|
1488
|
+
|
|
1489
|
+
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2024arXiv240407271S/abstract, https://ui.adsabs.harvard.edu/abs/2024AnP...53600306R/abstract')
|
|
1490
|
+
def one_comp_kne_rosswog_heatingrate(time, redshift, mej, vej, ye, **kwargs):
|
|
1491
|
+
"""
|
|
1492
|
+
:param time: observer frame time in days
|
|
1493
|
+
:param redshift: redshift
|
|
1494
|
+
:param mej: ejecta mass in solar masses
|
|
1495
|
+
:param vej: minimum initial velocity
|
|
1496
|
+
:param kappa: gray opacity
|
|
1497
|
+
:param kwargs: Additional keyword arguments
|
|
1498
|
+
:param temperature_floor: Temperature floor in K (default 4000)
|
|
1499
|
+
:param heating_rate_perturbation: A fudge factor for heating rate to account for uncertainties in the heating rate.
|
|
1500
|
+
Default is 1.0 i.e., no perturbation.
|
|
1501
|
+
:param heating_rate_fudge: A fudge factor for each of the terms in the heating rate. Default to 1. i.e., no uncertainty
|
|
1502
|
+
:param frequency: Required if output_format is 'flux_density'.
|
|
1503
|
+
frequency to calculate - Must be same length as time array or a single number).
|
|
1504
|
+
:param bands: Required if output_format is 'magnitude' or 'flux'.
|
|
1505
|
+
:param output_format: 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
|
|
1506
|
+
:param lambda_array: Optional argument to set your desired wavelength array (in Angstroms) to evaluate the SED on.
|
|
1507
|
+
:param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
|
|
1508
|
+
:return: set by output format - 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
|
|
1509
|
+
"""
|
|
1510
|
+
cosmology = kwargs.get('cosmology', cosmo)
|
|
1511
|
+
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
1512
|
+
time_temp = np.geomspace(1e-3, 7e6, 300) # in source frame
|
|
1513
|
+
time_obs = time
|
|
1514
|
+
_, temperature, r_photosphere = _one_component_kilonova_rosswog_heatingrate(time_temp, mej, vej, ye, **kwargs)
|
|
1515
|
+
|
|
1516
|
+
if kwargs['output_format'] == 'flux_density':
|
|
1517
|
+
time = time_obs * day_to_s
|
|
1518
|
+
frequency = kwargs['frequency']
|
|
1519
|
+
# interpolate properties onto observation times
|
|
1520
|
+
temp_func = interp1d(time_temp, y=temperature)
|
|
1521
|
+
rad_func = interp1d(time_temp, y=r_photosphere)
|
|
1522
|
+
# convert to source frame time and frequency
|
|
1523
|
+
frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
|
|
1524
|
+
|
|
1525
|
+
temp = temp_func(time)
|
|
1526
|
+
photosphere = rad_func(time)
|
|
1527
|
+
|
|
1528
|
+
flux_density = blackbody_to_flux_density(temperature=temp, r_photosphere=photosphere,
|
|
1529
|
+
dl=dl, frequency=frequency)
|
|
1530
|
+
|
|
1531
|
+
return flux_density.to(uu.mJy).value
|
|
1532
|
+
|
|
1533
|
+
else:
|
|
1534
|
+
lambda_observer_frame = kwargs.get('lambda_array', np.geomspace(100, 60000, 200))
|
|
1535
|
+
time_observer_frame = time_temp * (1. + redshift)
|
|
1536
|
+
frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
|
|
1537
|
+
redshift=redshift, time=time_observer_frame)
|
|
1538
|
+
fmjy = blackbody_to_flux_density(temperature=temperature,
|
|
1539
|
+
r_photosphere=r_photosphere, frequency=frequency[:, None], dl=dl)
|
|
1540
|
+
fmjy = fmjy.T
|
|
1541
|
+
spectra = fmjy.to(uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
|
|
1542
|
+
equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
|
|
1543
|
+
if kwargs['output_format'] == 'spectra':
|
|
1544
|
+
return namedtuple('output', ['time', 'lambdas', 'spectra'])(time=time_observer_frame,
|
|
1545
|
+
lambdas=lambda_observer_frame,
|
|
1546
|
+
spectra=spectra)
|
|
1547
|
+
else:
|
|
1548
|
+
return get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame/day_to_s,
|
|
1549
|
+
spectra=spectra, lambda_array=lambda_observer_frame,
|
|
1550
|
+
**kwargs)
|
|
1551
|
+
|
|
1552
|
+
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2024arXiv240407271S/abstract, https://ui.adsabs.harvard.edu/abs/2024AnP...53600306R/abstract')
|
|
1553
|
+
def two_comp_kne_rosswog_heatingrate(time, redshift, mej_1, vej_1, temperature_floor_1, ye_1,
|
|
1554
|
+
mej_2, vej_2, temperature_floor_2, ye_2, **kwargs):
|
|
1555
|
+
"""
|
|
1556
|
+
:param time: observer frame time in days
|
|
1557
|
+
:param redshift: redshift
|
|
1558
|
+
:param mej_1: ejecta mass in solar masses of first component
|
|
1559
|
+
:param vej_1: minimum initial velocity of first component
|
|
1560
|
+
:param kappa_1: gray opacity of first component
|
|
1561
|
+
:param temperature_floor_1: floor temperature of first component
|
|
1562
|
+
:param mej_2: ejecta mass in solar masses of second component
|
|
1563
|
+
:param vej_2: minimum initial velocity of second component
|
|
1564
|
+
:param temperature_floor_2: floor temperature of second component
|
|
1565
|
+
:param kappa_2: gray opacity of second component
|
|
1566
|
+
:param kwargs: Additional keyword arguments
|
|
1567
|
+
:param heating_rate_perturbation: A fudge factor for heating rate to account for uncertainties in the heating rate.
|
|
1568
|
+
Default is 1.0 i.e., no perturbation.
|
|
1569
|
+
:param heating_rate_fudge: A fudge factor for each of the terms in the heating rate. Default to 1. i.e., no uncertainty
|
|
1570
|
+
:param frequency: Required if output_format is 'flux_density'.
|
|
1571
|
+
frequency to calculate - Must be same length as time array or a single number).
|
|
1572
|
+
:param bands: Required if output_format is 'magnitude' or 'flux'.
|
|
1573
|
+
:param output_format: 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
|
|
1574
|
+
:param lambda_array: Optional argument to set your desired wavelength array (in Angstroms) to evaluate the SED on.
|
|
1575
|
+
:param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
|
|
1576
|
+
:return: set by output format - 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
|
|
1577
|
+
"""
|
|
1578
|
+
cosmology = kwargs.get('cosmology', cosmo)
|
|
1579
|
+
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
1580
|
+
time_temp = np.geomspace(1e-2, 7e6, 300) # in source frame
|
|
1581
|
+
time_obs = time
|
|
1582
|
+
|
|
1583
|
+
mej = [mej_1, mej_2]
|
|
1584
|
+
vej = [vej_1, vej_2]
|
|
1585
|
+
temperature_floor = [temperature_floor_1, temperature_floor_2]
|
|
1586
|
+
ye = [ye_1, ye_2]
|
|
1587
|
+
|
|
1588
|
+
if kwargs['output_format'] == 'flux_density':
|
|
1589
|
+
time = time * day_to_s
|
|
1590
|
+
frequency = kwargs['frequency']
|
|
1591
|
+
|
|
1592
|
+
# convert to source frame time and frequency
|
|
1593
|
+
frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
|
|
1594
|
+
|
|
1595
|
+
ff = np.zeros(len(time))
|
|
1596
|
+
for x in range(2):
|
|
1597
|
+
temp_kwargs = {}
|
|
1598
|
+
if 'heating_rate_fudge' in kwargs:
|
|
1599
|
+
temp_kwargs['heating_rate_fudge'] = kwargs['heating_rate_fudge']
|
|
1600
|
+
if 'heating_rate_perturbation' in kwargs:
|
|
1601
|
+
temp_kwargs['heating_rate_perturbation'] = kwargs['heating_rate_perturbation']
|
|
1602
|
+
temp_kwargs['temperature_floor'] = temperature_floor[x]
|
|
1603
|
+
_, temperature, r_photosphere = _one_component_kilonova_rosswog_heatingrate(time_temp, mej[x], vej[x], ye[x],
|
|
1604
|
+
**temp_kwargs)
|
|
1605
|
+
# interpolate properties onto observation times
|
|
1606
|
+
temp_func = interp1d(time_temp, y=temperature)
|
|
1607
|
+
rad_func = interp1d(time_temp, y=r_photosphere)
|
|
1608
|
+
temp = temp_func(time)
|
|
1609
|
+
photosphere = rad_func(time)
|
|
1610
|
+
flux_density = blackbody_to_flux_density(temperature=temp, r_photosphere=photosphere,
|
|
1611
|
+
dl=dl, frequency=frequency)
|
|
1612
|
+
units = flux_density.unit
|
|
1613
|
+
ff += flux_density.value
|
|
1614
|
+
|
|
1615
|
+
ff = ff * units
|
|
1616
|
+
return ff.to(uu.mJy).value
|
|
1617
|
+
|
|
1618
|
+
else:
|
|
1619
|
+
lambda_observer_frame = kwargs.get('lambda_array', np.geomspace(100, 60000, 200))
|
|
1620
|
+
time_observer_frame = time_temp * (1. + redshift)
|
|
1621
|
+
frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
|
|
1622
|
+
redshift=redshift, time=time_observer_frame)
|
|
1623
|
+
full_spec = np.zeros((len(time), len(frequency)))
|
|
1624
|
+
|
|
1625
|
+
for x in range(2):
|
|
1626
|
+
temp_kwargs = {}
|
|
1627
|
+
if 'heating_rate_fudge' in kwargs:
|
|
1628
|
+
temp_kwargs['heating_rate_fudge'] = kwargs['heating_rate_fudge']
|
|
1629
|
+
if 'heating_rate_perturbation' in kwargs:
|
|
1630
|
+
temp_kwargs['heating_rate_perturbation'] = kwargs['heating_rate_perturbation']
|
|
1631
|
+
temp_kwargs['temperature_floor'] = temperature_floor[x]
|
|
1632
|
+
_, temperature, r_photosphere = _one_component_kilonova_rosswog_heatingrate(time_temp, mej[x], vej[x], ye[x],
|
|
1633
|
+
**temp_kwargs)
|
|
1634
|
+
fmjy = blackbody_to_flux_density(temperature=temperature,
|
|
1635
|
+
r_photosphere=r_photosphere, frequency=frequency[:, None], dl=dl)
|
|
1636
|
+
fmjy = fmjy.T
|
|
1637
|
+
spectra = fmjy.to(uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
|
|
1638
|
+
equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
|
|
1639
|
+
units = spectra.unit
|
|
1640
|
+
full_spec += spectra.value
|
|
1641
|
+
|
|
1642
|
+
full_spec = full_spec * units
|
|
1643
|
+
if kwargs['output_format'] == 'spectra':
|
|
1644
|
+
return namedtuple('output', ['time', 'lambdas', 'spectra'])(time=time_observer_frame,
|
|
1645
|
+
lambdas=lambda_observer_frame,
|
|
1646
|
+
spectra=full_spec)
|
|
1647
|
+
else:
|
|
1648
|
+
return get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame/day_to_s,
|
|
1649
|
+
spectra=full_spec, lambda_array=lambda_observer_frame,
|
|
1650
|
+
**kwargs)
|
|
1651
|
+
|
|
1419
1652
|
def _one_component_kilonova_model(time, mej, vej, kappa, **kwargs):
|
|
1420
1653
|
"""
|
|
1421
1654
|
:param time: source frame time in seconds
|
|
@@ -1479,7 +1712,7 @@ def metzger_kilonova_model(time, redshift, mej, vej, beta, kappa, **kwargs):
|
|
|
1479
1712
|
"""
|
|
1480
1713
|
cosmology = kwargs.get('cosmology', cosmo)
|
|
1481
1714
|
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
1482
|
-
time_temp = np.geomspace(1e-4,
|
|
1715
|
+
time_temp = np.geomspace(1e-4, 7e6, 300) # in source frame
|
|
1483
1716
|
time_obs = time
|
|
1484
1717
|
bolometric_luminosity, temperature, r_photosphere = _metzger_kilonova_model(time_temp, mej, vej, beta,
|
|
1485
1718
|
kappa, **kwargs)
|
|
@@ -58,8 +58,8 @@ def _ejecta_dynamics_and_interaction(time, mej, beta, ejecta_radius, kappa, n_is
|
|
|
58
58
|
|
|
59
59
|
ni56_lum = 6.45e43
|
|
60
60
|
co56_lum = 1.45e43
|
|
61
|
-
ni56_life = 8.8 # days
|
|
62
|
-
co56_life = 111.3 # days
|
|
61
|
+
ni56_life = 8.8*86400 # days
|
|
62
|
+
co56_life = 111.3*86400 # days
|
|
63
63
|
|
|
64
64
|
for i in range(len(time)):
|
|
65
65
|
beta = np.sqrt(1 - 1 / gamma ** 2)
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
|
|
3
|
+
def line_spectrum(wavelength, line_amp, cont_amp, x0):
|
|
4
|
+
"""
|
|
5
|
+
A gaussian to add or subtract from a continuum spectrum to mimic absorption or emission lines
|
|
6
|
+
|
|
7
|
+
:param wavelength: wavelength array in whatever units
|
|
8
|
+
:param line_amp: line amplitude scale
|
|
9
|
+
:param cont_amp: Continuum amplitude scale
|
|
10
|
+
:param x0: Position of emission line
|
|
11
|
+
:return: spectrum in whatever units set by line_amp
|
|
12
|
+
"""
|
|
13
|
+
spectrum = line_amp / cont_amp * np.exp(-(wavelength - x0) ** 2. / (2 * cont_amp ** 2) )
|
|
14
|
+
return spectrum
|
|
15
|
+
|
|
3
16
|
def gaussian_rise(time, a_1, peak_time, sigma_t):
|
|
4
17
|
"""
|
|
5
18
|
:param time: time array in whatver time units
|