redback 1.1__py3-none-any.whl → 1.12.1__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 +1 -1
- redback/filters.py +57 -45
- redback/likelihoods.py +274 -6
- redback/model_library.py +2 -2
- redback/plotting.py +5 -3
- redback/priors/blackbody_spectrum_at_z.prior +3 -0
- redback/priors/bpl_cooling_envelope.prior +9 -0
- redback/priors/gaussianrise_cooling_envelope.prior +1 -5
- redback/priors/gaussianrise_cooling_envelope_bolometric.prior +1 -5
- redback/priors/powerlaw_plus_blackbody.prior +12 -0
- redback/priors/powerlaw_plus_blackbody_spectrum_at_z.prior +13 -0
- redback/priors/salt2.prior +6 -0
- redback/priors/shock_cooling_and_arnett_bolometric.prior +11 -0
- redback/priors/smooth_exponential_powerlaw_cooling_envelope_bolometric.prior +9 -0
- redback/priors/sn_nickel_fallback.prior +9 -0
- redback/priors/wr_bh_merger.prior +10 -0
- redback/priors/wr_bh_merger_bolometric.prior +8 -0
- redback/priors.py +14 -3
- redback/sed.py +185 -41
- redback/simulate_transients.py +13 -3
- redback/tables/filters.csv +260 -258
- redback/tables/qdot_rosswogkorobkin24.npz +0 -0
- redback/transient_models/afterglow_models.py +32 -16
- redback/transient_models/combined_models.py +16 -11
- redback/transient_models/extinction_models.py +310 -84
- redback/transient_models/gaussianprocess_models.py +1 -12
- redback/transient_models/kilonova_models.py +3 -3
- redback/transient_models/phase_models.py +97 -43
- redback/transient_models/phenomenological_models.py +172 -0
- redback/transient_models/spectral_models.py +101 -0
- redback/transient_models/stellar_interaction_models.py +254 -0
- redback/transient_models/supernova_models.py +349 -62
- redback/transient_models/tde_models.py +193 -54
- redback/utils.py +34 -7
- {redback-1.1.dist-info → redback-1.12.1.dist-info}/METADATA +7 -4
- {redback-1.1.dist-info → redback-1.12.1.dist-info}/RECORD +39 -28
- {redback-1.1.dist-info → redback-1.12.1.dist-info}/WHEEL +1 -1
- redback/tables/qdot_rosswogkorobkin24.pck +0 -0
- {redback-1.1.dist-info → redback-1.12.1.dist-info}/licenses/LICENCE.md +0 -0
- {redback-1.1.dist-info → redback-1.12.1.dist-info}/top_level.txt +0 -0
|
@@ -53,15 +53,20 @@ def t0_base_model(time, t0, **kwargs):
|
|
|
53
53
|
return output
|
|
54
54
|
|
|
55
55
|
|
|
56
|
-
def _t0_with_extinction(time, t0,
|
|
56
|
+
def _t0_with_extinction(time, t0, av_host, model_type='supernova', **kwargs):
|
|
57
57
|
"""
|
|
58
58
|
:param time: time in mjd
|
|
59
59
|
:param t0: start time in mjd
|
|
60
|
-
:param
|
|
61
|
-
:param
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
:param av_host: V-band extinction from host galaxy in magnitudes
|
|
61
|
+
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model'] plus:
|
|
62
|
+
- redshift: source redshift (required)
|
|
63
|
+
- av_mw: MW V-band extinction in magnitudes (default 0.0)
|
|
64
|
+
- rv_host: host R_V parameter (default 3.1)
|
|
65
|
+
- rv_mw: MW R_V parameter (default 3.1)
|
|
66
|
+
- host_law: host extinction law (default 'fitzpatrick99')
|
|
67
|
+
- mw_law: MW extinction law (default 'fitzpatrick99')
|
|
68
|
+
Available extinction laws: 'fitzpatrick99', 'fm07', 'calzetti00', 'odonnell94', 'ccm89'
|
|
69
|
+
:return: flux_density or magnitude depending on kwargs['output_format'] with extinction applied
|
|
65
70
|
"""
|
|
66
71
|
output = namedtuple('output', ['time', 'observable'])
|
|
67
72
|
function = extinction_model_functions[model_type]
|
|
@@ -70,7 +75,7 @@ def _t0_with_extinction(time, t0, av, model_type='supernova', **kwargs):
|
|
|
70
75
|
time = (time - t0).to(uu.day).value
|
|
71
76
|
transient_time = time[time >= 0.0]
|
|
72
77
|
bad_time = time[time < 0.0]
|
|
73
|
-
output_real = function(transient_time,
|
|
78
|
+
output_real = function(transient_time, av_host=av_host, **kwargs)
|
|
74
79
|
if kwargs['output_format'] == 'magnitude':
|
|
75
80
|
output_fake = np.zeros(len(bad_time)) + 5000
|
|
76
81
|
else:
|
|
@@ -80,83 +85,132 @@ def _t0_with_extinction(time, t0, av, model_type='supernova', **kwargs):
|
|
|
80
85
|
return output
|
|
81
86
|
|
|
82
87
|
@citation_wrapper('redback')
|
|
83
|
-
def t0_afterglow_extinction(time, t0,
|
|
88
|
+
def t0_afterglow_extinction(time, t0, av_host, **kwargs):
|
|
84
89
|
"""
|
|
90
|
+
Afterglow model with t0 parameter and host/MW extinction
|
|
91
|
+
|
|
85
92
|
:param time: time in mjd
|
|
86
93
|
:param t0: start time in mjd
|
|
87
|
-
:param
|
|
88
|
-
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model']
|
|
89
|
-
|
|
90
|
-
|
|
94
|
+
:param av_host: V-band extinction from host galaxy in magnitudes
|
|
95
|
+
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model'] plus:
|
|
96
|
+
- redshift: source redshift (required)
|
|
97
|
+
- av_mw: MW V-band extinction in magnitudes (default 0.0)
|
|
98
|
+
- rv_host: host R_V parameter (default 3.1)
|
|
99
|
+
- rv_mw: MW R_V parameter (default 3.1)
|
|
100
|
+
- host_law: host extinction law (default 'fitzpatrick99')
|
|
101
|
+
- mw_law: MW extinction law (default 'fitzpatrick99')
|
|
102
|
+
Available extinction laws: 'fitzpatrick99', 'fm07', 'calzetti00', 'odonnell94', 'ccm89'
|
|
103
|
+
:return: flux_density or magnitude depending on kwargs['output_format'] with extinction applied
|
|
91
104
|
"""
|
|
92
|
-
summary = _t0_with_extinction(time=time, t0=t0,
|
|
105
|
+
summary = _t0_with_extinction(time=time, t0=t0, av_host=av_host, model_type='afterglow', **kwargs)
|
|
93
106
|
return summary.observable
|
|
94
107
|
|
|
95
108
|
@citation_wrapper('redback')
|
|
96
|
-
def t0_supernova_extinction(time, t0,
|
|
109
|
+
def t0_supernova_extinction(time, t0, av_host, **kwargs):
|
|
97
110
|
"""
|
|
111
|
+
Supernova model with t0 parameter and host/MW extinction
|
|
112
|
+
|
|
98
113
|
:param time: time in mjd
|
|
99
114
|
:param t0: start time in mjd
|
|
100
|
-
:param
|
|
101
|
-
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model']
|
|
102
|
-
|
|
103
|
-
|
|
115
|
+
:param av_host: V-band extinction from host galaxy in magnitudes
|
|
116
|
+
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model'] plus:
|
|
117
|
+
- redshift: source redshift (required)
|
|
118
|
+
- av_mw: MW V-band extinction in magnitudes (default 0.0)
|
|
119
|
+
- rv_host: host R_V parameter (default 3.1)
|
|
120
|
+
- rv_mw: MW R_V parameter (default 3.1)
|
|
121
|
+
- host_law: host extinction law (default 'fitzpatrick99')
|
|
122
|
+
- mw_law: MW extinction law (default 'fitzpatrick99')
|
|
123
|
+
Available extinction laws: 'fitzpatrick99', 'fm07', 'calzetti00', 'odonnell94', 'ccm89'
|
|
124
|
+
:return: flux_density or magnitude depending on kwargs['output_format'] with extinction applied
|
|
104
125
|
"""
|
|
105
|
-
summary = _t0_with_extinction(time=time, t0=t0,
|
|
126
|
+
summary = _t0_with_extinction(time=time, t0=t0, av_host=av_host, model_type='supernova', **kwargs)
|
|
106
127
|
return summary.observable
|
|
107
128
|
|
|
108
129
|
@citation_wrapper('redback')
|
|
109
|
-
def t0_kilonova_extinction(time, t0,
|
|
130
|
+
def t0_kilonova_extinction(time, t0, av_host, **kwargs):
|
|
110
131
|
"""
|
|
132
|
+
Kilonova model with t0 parameter and host/MW extinction
|
|
133
|
+
|
|
111
134
|
:param time: time in mjd
|
|
112
135
|
:param t0: start time in mjd
|
|
113
|
-
:param
|
|
114
|
-
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model']
|
|
115
|
-
|
|
116
|
-
|
|
136
|
+
:param av_host: V-band extinction from host galaxy in magnitudes
|
|
137
|
+
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model'] plus:
|
|
138
|
+
- redshift: source redshift (required)
|
|
139
|
+
- av_mw: MW V-band extinction in magnitudes (default 0.0)
|
|
140
|
+
- rv_host: host R_V parameter (default 3.1)
|
|
141
|
+
- rv_mw: MW R_V parameter (default 3.1)
|
|
142
|
+
- host_law: host extinction law (default 'fitzpatrick99')
|
|
143
|
+
- mw_law: MW extinction law (default 'fitzpatrick99')
|
|
144
|
+
Available extinction laws: 'fitzpatrick99', 'fm07', 'calzetti00', 'odonnell94', 'ccm89'
|
|
145
|
+
:return: flux_density or magnitude depending on kwargs['output_format'] with extinction applied
|
|
117
146
|
"""
|
|
118
|
-
summary = _t0_with_extinction(time=time, t0=t0,
|
|
147
|
+
summary = _t0_with_extinction(time=time, t0=t0, av_host=av_host, model_type='kilonova', **kwargs)
|
|
119
148
|
return summary.observable
|
|
120
149
|
|
|
121
150
|
@citation_wrapper('redback')
|
|
122
|
-
def t0_tde_extinction(time, t0,
|
|
151
|
+
def t0_tde_extinction(time, t0, av_host, **kwargs):
|
|
123
152
|
"""
|
|
153
|
+
TDE model with t0 parameter and host/MW extinction
|
|
154
|
+
|
|
124
155
|
:param time: time in mjd
|
|
125
156
|
:param t0: start time in mjd
|
|
126
|
-
:param
|
|
127
|
-
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model']
|
|
128
|
-
|
|
129
|
-
|
|
157
|
+
:param av_host: V-band extinction from host galaxy in magnitudes
|
|
158
|
+
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model'] plus:
|
|
159
|
+
- redshift: source redshift (required)
|
|
160
|
+
- av_mw: MW V-band extinction in magnitudes (default 0.0)
|
|
161
|
+
- rv_host: host R_V parameter (default 3.1)
|
|
162
|
+
- rv_mw: MW R_V parameter (default 3.1)
|
|
163
|
+
- host_law: host extinction law (default 'fitzpatrick99')
|
|
164
|
+
- mw_law: MW extinction law (default 'fitzpatrick99')
|
|
165
|
+
- peak_time_mjd: peak time in mjd (if provided, will be converted to peak_time relative to t0)
|
|
166
|
+
Available extinction laws: 'fitzpatrick99', 'fm07', 'calzetti00', 'odonnell94', 'ccm89'
|
|
167
|
+
:return: flux_density or magnitude depending on kwargs['output_format'] with extinction applied
|
|
130
168
|
"""
|
|
131
169
|
if 'peak_time_mjd' in kwargs:
|
|
132
170
|
kwargs['peak_time'] = kwargs['peak_time_mjd'] - t0
|
|
133
|
-
summary = _t0_with_extinction(time=time, t0=t0,
|
|
171
|
+
summary = _t0_with_extinction(time=time, t0=t0, av_host=av_host, model_type='tde', **kwargs)
|
|
134
172
|
return summary.observable
|
|
135
173
|
|
|
136
174
|
@citation_wrapper('redback')
|
|
137
|
-
def t0_magnetar_driven_extinction(time, t0,
|
|
175
|
+
def t0_magnetar_driven_extinction(time, t0, av_host, **kwargs):
|
|
138
176
|
"""
|
|
177
|
+
Magnetar-driven model with t0 parameter and host/MW extinction
|
|
178
|
+
|
|
139
179
|
:param time: time in mjd
|
|
140
180
|
:param t0: start time in mjd
|
|
141
|
-
:param
|
|
142
|
-
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model']
|
|
143
|
-
|
|
144
|
-
|
|
181
|
+
:param av_host: V-band extinction from host galaxy in magnitudes
|
|
182
|
+
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model'] plus:
|
|
183
|
+
- redshift: source redshift (required)
|
|
184
|
+
- av_mw: MW V-band extinction in magnitudes (default 0.0)
|
|
185
|
+
- rv_host: host R_V parameter (default 3.1)
|
|
186
|
+
- rv_mw: MW R_V parameter (default 3.1)
|
|
187
|
+
- host_law: host extinction law (default 'fitzpatrick99')
|
|
188
|
+
- mw_law: MW extinction law (default 'fitzpatrick99')
|
|
189
|
+
Available extinction laws: 'fitzpatrick99', 'fm07', 'calzetti00', 'odonnell94', 'ccm89'
|
|
190
|
+
:return: flux_density or magnitude depending on kwargs['output_format'] with extinction applied
|
|
145
191
|
"""
|
|
146
|
-
summary = _t0_with_extinction(time=time, t0=t0,
|
|
192
|
+
summary = _t0_with_extinction(time=time, t0=t0, av_host=av_host, model_type='magnetar_driven', **kwargs)
|
|
147
193
|
return summary.observable
|
|
148
194
|
|
|
149
195
|
@citation_wrapper('redback')
|
|
150
|
-
def t0_shock_powered_extinction(time, t0,
|
|
196
|
+
def t0_shock_powered_extinction(time, t0, av_host, **kwargs):
|
|
151
197
|
"""
|
|
198
|
+
Shock-powered model with t0 parameter and host/MW extinction
|
|
199
|
+
|
|
152
200
|
:param time: time in mjd
|
|
153
201
|
:param t0: start time in mjd
|
|
154
|
-
:param
|
|
155
|
-
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model']
|
|
156
|
-
|
|
157
|
-
|
|
202
|
+
:param av_host: V-band extinction from host galaxy in magnitudes
|
|
203
|
+
:param kwargs: Must be all the parameters required by the base_model specified using kwargs['base_model'] plus:
|
|
204
|
+
- redshift: source redshift (required)
|
|
205
|
+
- av_mw: MW V-band extinction in magnitudes (default 0.0)
|
|
206
|
+
- rv_host: host R_V parameter (default 3.1)
|
|
207
|
+
- rv_mw: MW R_V parameter (default 3.1)
|
|
208
|
+
- host_law: host extinction law (default 'fitzpatrick99')
|
|
209
|
+
- mw_law: MW extinction law (default 'fitzpatrick99')
|
|
210
|
+
Available extinction laws: 'fitzpatrick99', 'fm07', 'calzetti00', 'odonnell94', 'ccm89'
|
|
211
|
+
:return: flux_density or magnitude depending on kwargs['output_format'] with extinction applied
|
|
158
212
|
"""
|
|
159
|
-
summary = _t0_with_extinction(time=time, t0=t0,
|
|
213
|
+
summary = _t0_with_extinction(time=time, t0=t0, av_host=av_host, model_type='shock_powered', **kwargs)
|
|
160
214
|
return summary.observable
|
|
161
215
|
|
|
162
216
|
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2021arXiv210601556S/abstract')
|
|
@@ -3,6 +3,33 @@ from redback.utils import citation_wrapper
|
|
|
3
3
|
from redback.constants import speed_of_light_si
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
def smooth_exponential_powerlaw(time, a_1, tpeak, alpha_1, alpha_2, smoothing_factor, **kwargs):
|
|
7
|
+
"""
|
|
8
|
+
Smoothed version of exponential power law
|
|
9
|
+
|
|
10
|
+
:param time: time array in seconds
|
|
11
|
+
:param a_1: exponential amplitude scale
|
|
12
|
+
:param alpha_1: first exponent
|
|
13
|
+
:param alpha_2: second exponent
|
|
14
|
+
:param tpeak: peak time in seconds
|
|
15
|
+
:param smoothing_factor: controls transition smoothness (higher = smoother)
|
|
16
|
+
:param kwargs: Additional parameters
|
|
17
|
+
:return: In whatever units set by a_1
|
|
18
|
+
"""
|
|
19
|
+
t_norm = time / tpeak
|
|
20
|
+
|
|
21
|
+
# Smooth transition function using tanh or similar
|
|
22
|
+
transition = 0.5 * (1 + np.tanh(smoothing_factor * np.log(t_norm)))
|
|
23
|
+
|
|
24
|
+
# Pre-peak behavior
|
|
25
|
+
pre_peak = a_1 * (t_norm ** alpha_1)
|
|
26
|
+
|
|
27
|
+
# Post-peak behavior
|
|
28
|
+
post_peak = a_1 * (t_norm ** alpha_2)
|
|
29
|
+
|
|
30
|
+
# Smooth combination
|
|
31
|
+
return pre_peak * (1 - transition) + post_peak * transition
|
|
32
|
+
|
|
6
33
|
def exp_rise_powerlaw_decline(t, t0, m_peak, tau_rise, alpha, t_peak, **kwargs):
|
|
7
34
|
"""
|
|
8
35
|
Compute a smooth light-curve model (in magnitudes) with an exponential rise
|
|
@@ -173,6 +200,151 @@ def villar_sne(time, aa, cc, t0, tau_rise, tau_fall, gamma, nu, **kwargs):
|
|
|
173
200
|
flux[mask2] = norm[mask2] * ((1 - nu) * np.exp(-((time[mask2] - t0 - gamma)/tau_fall)))
|
|
174
201
|
return np.concatenate((flux[mask1], flux[mask2]))
|
|
175
202
|
|
|
203
|
+
|
|
204
|
+
def powerlaw_plus_blackbody(time, redshift, pl_amplitude, pl_slope, pl_evolution_index, temperature_0, radius_0,
|
|
205
|
+
temp_rise_index, temp_decline_index, temp_peak_time,
|
|
206
|
+
radius_rise_index, radius_decline_index, radius_peak_time,
|
|
207
|
+
reference_time=1.0, **kwargs):
|
|
208
|
+
"""
|
|
209
|
+
Power law + blackbody spectrum with piecewise evolving temperature and radius
|
|
210
|
+
|
|
211
|
+
:param time: time in observer frame in days
|
|
212
|
+
:param redshift: source redshift
|
|
213
|
+
:param pl_amplitude: power law amplitude at reference wavelength at reference_time (erg/s/cm^2/Angstrom)
|
|
214
|
+
:param pl_slope: power law slope (F_lambda ∝ lambda^slope)
|
|
215
|
+
:param pl_evolution_index: power law time evolution F_pl(t) ∝ t^(-pl_evolution_index)
|
|
216
|
+
:param temperature_0: initial blackbody temperature in Kelvin at reference_time
|
|
217
|
+
:param radius_0: initial blackbody radius in cm at reference_time
|
|
218
|
+
:param temp_rise_index: temperature rise T(t) ∝ t^temp_rise_index for t < temp_peak_time
|
|
219
|
+
:param temp_decline_index: temperature decline T(t) ∝ t^(-temp_decline_index) for t > temp_peak_time
|
|
220
|
+
:param temp_peak_time: time in days when temperature peaks
|
|
221
|
+
:param radius_rise_index: radius rise R(t) ∝ t^radius_rise_index for t < radius_peak_time
|
|
222
|
+
:param radius_decline_index: radius decline R(t) ∝ t^(-radius_decline_index) for t > radius_peak_time
|
|
223
|
+
:param radius_peak_time: time in days when radius peaks
|
|
224
|
+
:param reference_time: reference time for temperature_0, radius_0, and pl_amplitude in days (defaults to 1.0)
|
|
225
|
+
:param kwargs: Additional parameters
|
|
226
|
+
:param reference_wavelength: wavelength for power law amplitude normalization in Angstroms (default 5000)
|
|
227
|
+
:param frequency: Required if output_format is 'flux_density'
|
|
228
|
+
:param bands: Required if output_format is 'magnitude' or 'flux'
|
|
229
|
+
:param output_format: 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
|
|
230
|
+
:param lambda_array: Optional wavelength array in Angstroms to evaluate SED
|
|
231
|
+
:param cosmology: Cosmology object for luminosity distance calculation
|
|
232
|
+
:return: set by output format - 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
|
|
233
|
+
"""
|
|
234
|
+
from astropy.cosmology import Planck18 as cosmo
|
|
235
|
+
from astropy import units as uu
|
|
236
|
+
from redback.utils import lambda_to_nu, calc_kcorrected_properties
|
|
237
|
+
import redback.sed as sed
|
|
238
|
+
from collections import namedtuple
|
|
239
|
+
|
|
240
|
+
cosmology = kwargs.get('cosmology', cosmo)
|
|
241
|
+
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
242
|
+
reference_wavelength = kwargs.get('reference_wavelength', 5000.0) # Angstroms
|
|
243
|
+
|
|
244
|
+
if kwargs['output_format'] == 'flux_density':
|
|
245
|
+
frequency = kwargs['frequency']
|
|
246
|
+
frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
|
|
247
|
+
|
|
248
|
+
# Calculate evolving temperature and radius
|
|
249
|
+
temperature, radius = _powerlaw_blackbody_evolution(time=time, temperature_0=temperature_0, radius_0=radius_0,
|
|
250
|
+
temp_rise_index=temp_rise_index,
|
|
251
|
+
temp_decline_index=temp_decline_index,
|
|
252
|
+
temp_peak_time=temp_peak_time,
|
|
253
|
+
radius_rise_index=radius_rise_index,
|
|
254
|
+
radius_decline_index=radius_decline_index,
|
|
255
|
+
radius_peak_time=radius_peak_time,
|
|
256
|
+
reference_time=reference_time)
|
|
257
|
+
|
|
258
|
+
# Create combined SED with time-evolving power law
|
|
259
|
+
sed_combined = sed.PowerlawPlusBlackbody(temperature=temperature, r_photosphere=radius,
|
|
260
|
+
pl_amplitude=pl_amplitude, pl_slope=pl_slope,
|
|
261
|
+
pl_evolution_index=pl_evolution_index, time=time,
|
|
262
|
+
reference_wavelength=reference_wavelength,
|
|
263
|
+
frequency=frequency, luminosity_distance=dl)
|
|
264
|
+
flux_density = sed_combined.flux_density
|
|
265
|
+
return flux_density.to(uu.mJy).value
|
|
266
|
+
else:
|
|
267
|
+
time_obs = time
|
|
268
|
+
lambda_observer_frame = kwargs.get('lambda_array', np.geomspace(100, 60000, 100))
|
|
269
|
+
time_temp = np.geomspace(0.1, 3000, 300) # in days
|
|
270
|
+
time_observer_frame = time_temp * (1. + redshift)
|
|
271
|
+
frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
|
|
272
|
+
redshift=redshift, time=time_observer_frame)
|
|
273
|
+
|
|
274
|
+
# Calculate evolving temperature and radius
|
|
275
|
+
temperature, radius = _powerlaw_blackbody_evolution(time=time, temperature_0=temperature_0, radius_0=radius_0,
|
|
276
|
+
temp_rise_index=temp_rise_index,
|
|
277
|
+
temp_decline_index=temp_decline_index,
|
|
278
|
+
temp_peak_time=temp_peak_time,
|
|
279
|
+
radius_rise_index=radius_rise_index,
|
|
280
|
+
radius_decline_index=radius_decline_index,
|
|
281
|
+
radius_peak_time=radius_peak_time,
|
|
282
|
+
reference_time=reference_time)
|
|
283
|
+
|
|
284
|
+
# Create combined SED with time-evolving power law
|
|
285
|
+
sed_combined = sed.PowerlawPlusBlackbody(temperature=temperature, r_photosphere=radius,
|
|
286
|
+
pl_amplitude=pl_amplitude, pl_slope=pl_slope,
|
|
287
|
+
pl_evolution_index=pl_evolution_index, time=time,
|
|
288
|
+
reference_wavelength=reference_wavelength,
|
|
289
|
+
frequency=frequency[:, None], luminosity_distance=dl)
|
|
290
|
+
fmjy = sed_combined.flux_density.T
|
|
291
|
+
spectra = fmjy.to(uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
|
|
292
|
+
equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
|
|
293
|
+
if kwargs['output_format'] == 'spectra':
|
|
294
|
+
return namedtuple('output', ['time', 'lambdas', 'spectra'])(time=time_observer_frame,
|
|
295
|
+
lambdas=lambda_observer_frame,
|
|
296
|
+
spectra=spectra)
|
|
297
|
+
else:
|
|
298
|
+
return sed.get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame,
|
|
299
|
+
spectra=spectra, lambda_array=lambda_observer_frame,
|
|
300
|
+
**kwargs)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def _powerlaw_blackbody_evolution(time, temperature_0, radius_0, temp_rise_index, temp_decline_index,
|
|
304
|
+
temp_peak_time, radius_rise_index, radius_decline_index, radius_peak_time,
|
|
305
|
+
reference_time=1.0, **kwargs):
|
|
306
|
+
"""
|
|
307
|
+
Calculate evolving temperature and radius with piecewise power-law evolution
|
|
308
|
+
|
|
309
|
+
:param time: time array in days
|
|
310
|
+
:param temperature_0: initial temperature at reference_time
|
|
311
|
+
:param radius_0: initial radius at reference_time
|
|
312
|
+
:param temp_rise_index: temperature rise index
|
|
313
|
+
:param temp_decline_index: temperature decline index
|
|
314
|
+
:param temp_peak_time: time when temperature peaks
|
|
315
|
+
:param radius_rise_index: radius rise index
|
|
316
|
+
:param radius_decline_index: radius decline index
|
|
317
|
+
:param radius_peak_time: time when radius peaks
|
|
318
|
+
:param reference_time: reference time for temperature_0 and radius_0 (defaults to 1.0 day)
|
|
319
|
+
:return: temperature and radius values (scalars if time is scalar)
|
|
320
|
+
"""
|
|
321
|
+
time = np.atleast_1d(time)
|
|
322
|
+
|
|
323
|
+
# Temperature evolution
|
|
324
|
+
temp_peak = temperature_0 * (temp_peak_time / reference_time) ** temp_rise_index
|
|
325
|
+
rise_mask_temp = time <= temp_peak_time
|
|
326
|
+
decline_mask_temp = ~rise_mask_temp
|
|
327
|
+
|
|
328
|
+
temperature = np.zeros_like(time)
|
|
329
|
+
temperature[rise_mask_temp] = temperature_0 * (time[rise_mask_temp] / reference_time) ** temp_rise_index
|
|
330
|
+
temperature[decline_mask_temp] = temp_peak * (time[decline_mask_temp] / temp_peak_time) ** (-temp_decline_index)
|
|
331
|
+
|
|
332
|
+
# Radius evolution
|
|
333
|
+
radius_peak = radius_0 * (radius_peak_time / reference_time) ** radius_rise_index
|
|
334
|
+
rise_mask_radius = time <= radius_peak_time
|
|
335
|
+
decline_mask_radius = ~rise_mask_radius
|
|
336
|
+
|
|
337
|
+
radius = np.zeros_like(time)
|
|
338
|
+
radius[rise_mask_radius] = radius_0 * (time[rise_mask_radius] / reference_time) ** radius_rise_index
|
|
339
|
+
radius[decline_mask_radius] = radius_peak * (time[decline_mask_radius] / radius_peak_time) ** (
|
|
340
|
+
-radius_decline_index)
|
|
341
|
+
|
|
342
|
+
# Return scalars if input was scalar
|
|
343
|
+
if len(time) == 1:
|
|
344
|
+
return temperature[0], radius[0]
|
|
345
|
+
else:
|
|
346
|
+
return temperature, radius
|
|
347
|
+
|
|
176
348
|
def fallback_lbol(time, logl1, tr, **kwargs):
|
|
177
349
|
"""
|
|
178
350
|
:param time: time in seconds
|
|
@@ -80,3 +80,104 @@ def blackbody_spectrum_with_absorption_and_emission_lines(angstroms, redshift,
|
|
|
80
80
|
fp1 = pm.line_spectrum_with_velocity_dispersion(angstroms, lc1, ls1, v1)
|
|
81
81
|
fp2 = pm.line_spectrum_with_velocity_dispersion(angstroms, lc2, ls2, v2)
|
|
82
82
|
return flux + fp1 - fp2
|
|
83
|
+
|
|
84
|
+
def blackbody_spectrum_at_z(angstroms, redshift, rph, temp, **kwargs):
|
|
85
|
+
"""
|
|
86
|
+
A blackbody spectrum at a given redshift, properly accounting for redshift effects.
|
|
87
|
+
|
|
88
|
+
:param angstroms: wavelength array in angstroms in obs frame
|
|
89
|
+
:param redshift: redshift
|
|
90
|
+
:param rph: photosphere radius in cm (rest frame)
|
|
91
|
+
:param temp: photosphere temperature in Kelvin (rest frame)
|
|
92
|
+
:return: flux in ergs/s/cm^2/angstrom in obs frame
|
|
93
|
+
"""
|
|
94
|
+
cosmology = kwargs.get('cosmology', cosmo)
|
|
95
|
+
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
96
|
+
|
|
97
|
+
# Convert observed wavelengths to rest frame
|
|
98
|
+
angstroms_rest = angstroms / (1 + redshift)
|
|
99
|
+
|
|
100
|
+
# Calculate blackbody in rest frame
|
|
101
|
+
flux_rest = _get_blackbody_spectrum(angstrom=angstroms_rest, distance=dl,
|
|
102
|
+
r_photosphere=rph, temperature=temp)
|
|
103
|
+
|
|
104
|
+
# Apply redshift corrections:
|
|
105
|
+
# - Surface brightness dimming: factor of (1+z)
|
|
106
|
+
# - Wavelength interval stretching: dλ_obs = dλ_rest × (1+z)
|
|
107
|
+
# Combined effect: divide by (1+z)
|
|
108
|
+
flux_obs = flux_rest / (1 + redshift)
|
|
109
|
+
|
|
110
|
+
return flux_obs
|
|
111
|
+
|
|
112
|
+
def powerlaw_plus_blackbody_spectrum_at_z(angstroms, redshift, pl_amplitude, pl_slope, pl_evolution_index,
|
|
113
|
+
temperature_0, radius_0, temp_rise_index, temp_decline_index,
|
|
114
|
+
temp_peak_time, radius_rise_index, radius_decline_index,
|
|
115
|
+
radius_peak_time, time, **kwargs):
|
|
116
|
+
"""
|
|
117
|
+
A powerlaw + blackbody spectrum at a given redshift and time, properly accounting for redshift effects.
|
|
118
|
+
|
|
119
|
+
:param angstroms: wavelength array in angstroms in obs frame
|
|
120
|
+
:param redshift: source redshift
|
|
121
|
+
:param pl_amplitude: power law amplitude at reference wavelength at t=1 day (erg/s/cm^2/Angstrom)
|
|
122
|
+
:param pl_slope: power law slope (F_lambda ∝ lambda^slope)
|
|
123
|
+
:param pl_evolution_index: power law time evolution F_pl(t) ∝ t^(-pl_evolution_index)
|
|
124
|
+
:param temperature_0: initial blackbody temperature in Kelvin at t=1 day (rest frame)
|
|
125
|
+
:param radius_0: initial blackbody radius in cm at t=1 day (rest frame)
|
|
126
|
+
:param temp_rise_index: temperature rise T(t) ∝ t^temp_rise_index for t < temp_peak_time
|
|
127
|
+
:param temp_decline_index: temperature decline T(t) ∝ t^(-temp_decline_index) for t > temp_peak_time
|
|
128
|
+
:param temp_peak_time: time in days when temperature peaks
|
|
129
|
+
:param radius_rise_index: radius rise R(t) ∝ t^radius_rise_index for t < radius_peak_time
|
|
130
|
+
:param radius_decline_index: radius decline R(t) ∝ t^(-radius_decline_index) for t > radius_peak_time
|
|
131
|
+
:param radius_peak_time: time in days when radius peaks
|
|
132
|
+
:param time: time in observer frame in days
|
|
133
|
+
:param kwargs: Additional parameters
|
|
134
|
+
:param reference_wavelength: wavelength for power law amplitude normalization in Angstroms (default 5000)
|
|
135
|
+
:param cosmology: Cosmology object for luminosity distance calculation
|
|
136
|
+
:return: flux in ergs/s/cm^2/angstrom in obs frame
|
|
137
|
+
"""
|
|
138
|
+
cosmology = kwargs.get('cosmology', cosmo)
|
|
139
|
+
dl = cosmology.luminosity_distance(redshift).cgs.value
|
|
140
|
+
reference_wavelength = kwargs.get('reference_wavelength', 5000.0) # Angstroms
|
|
141
|
+
|
|
142
|
+
# Convert observed wavelengths to rest frame
|
|
143
|
+
angstroms_rest = angstroms / (1 + redshift)
|
|
144
|
+
|
|
145
|
+
# Convert observed time to rest frame
|
|
146
|
+
time_rest = time / (1 + redshift)
|
|
147
|
+
|
|
148
|
+
# Convert wavelengths to frequencies for the SED calculation
|
|
149
|
+
frequency_rest = lambda_to_nu(wavelength=angstroms_rest)
|
|
150
|
+
|
|
151
|
+
# Calculate evolving temperature and radius at this time
|
|
152
|
+
temperature, radius = pm._powerlaw_blackbody_evolution(time=time_rest, temperature_0=temperature_0, radius_0=radius_0,
|
|
153
|
+
temp_rise_index=temp_rise_index,
|
|
154
|
+
temp_decline_index=temp_decline_index,
|
|
155
|
+
temp_peak_time=temp_peak_time,
|
|
156
|
+
radius_rise_index=radius_rise_index,
|
|
157
|
+
radius_decline_index=radius_decline_index,
|
|
158
|
+
radius_peak_time=radius_peak_time)
|
|
159
|
+
|
|
160
|
+
# Create combined SED in rest frame
|
|
161
|
+
sed_combined = sed.PowerlawPlusBlackbody(temperature=temperature, r_photosphere=radius,
|
|
162
|
+
pl_amplitude=pl_amplitude, pl_slope=pl_slope,
|
|
163
|
+
pl_evolution_index=pl_evolution_index, time=time_rest,
|
|
164
|
+
reference_wavelength=reference_wavelength,
|
|
165
|
+
frequency=frequency_rest, luminosity_distance=dl)
|
|
166
|
+
|
|
167
|
+
# Get flux density in rest frame (F_nu)
|
|
168
|
+
flux_density_rest = sed_combined.flux_density # erg/s/cm^2/Hz
|
|
169
|
+
|
|
170
|
+
# Convert from F_nu to F_lambda in rest frame
|
|
171
|
+
flux_lambda_rest = fnu_to_flambda(f_nu=flux_density_rest, wavelength_A=angstroms_rest)
|
|
172
|
+
|
|
173
|
+
# Apply redshift corrections to get observed frame flux:
|
|
174
|
+
# - Surface brightness dimming: factor of (1+z)
|
|
175
|
+
# - Wavelength interval stretching: dλ_obs = dλ_rest × (1+z)
|
|
176
|
+
# Combined effect: divide by (1+z)
|
|
177
|
+
flux_lambda_obs = flux_lambda_rest / (1 + redshift)
|
|
178
|
+
|
|
179
|
+
# Convert to plain values if needed
|
|
180
|
+
if hasattr(flux_lambda_obs, 'value'):
|
|
181
|
+
return flux_lambda_obs.value
|
|
182
|
+
else:
|
|
183
|
+
return flux_lambda_obs
|