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
|
@@ -28,39 +28,77 @@ def _analytic_fallback(time, l0, t_0):
|
|
|
28
28
|
def _semianalytical_fallback():
|
|
29
29
|
pass
|
|
30
30
|
|
|
31
|
+
|
|
31
32
|
def _cooling_envelope(mbh_6, stellar_mass, eta, alpha, beta, **kwargs):
|
|
32
33
|
"""
|
|
34
|
+
Sarin and Metzger 24 cooling envelope model.
|
|
35
|
+
Also includes partial disruptions by assuming only fraction of stellar mass is disrupted.
|
|
36
|
+
|
|
33
37
|
:param mbh_6: mass of supermassive black hole in units of 10^6 solar mass
|
|
34
38
|
:param stellar_mass: stellar mass in units of solar masses
|
|
35
39
|
:param eta: SMBH feedback efficiency (typical range: etamin - 0.1)
|
|
36
40
|
:param alpha: disk viscosity
|
|
37
|
-
:param beta: TDE penetration factor (typical range: 1 - beta_max)
|
|
38
|
-
:param kwargs:
|
|
41
|
+
:param beta: TDE penetration factor (typical range: 0.1 - beta_max).
|
|
42
|
+
:param kwargs: Binding energy constant, zeta, hoverR, t_0_init, f_debris (optional, defaults to 1 unless
|
|
43
|
+
calculate_f_debris=True), calculate_f_debris (optional, defaults to False).
|
|
39
44
|
:return: named tuple with bolometric luminosity, photosphere radius, temperature, and other parameters
|
|
40
45
|
"""
|
|
41
46
|
t_0_init = kwargs.get('t_0_init', 1.0)
|
|
42
47
|
binding_energy_const = kwargs.get('binding_energy_const', 0.8)
|
|
43
|
-
zeta = kwargs.get('zeta',2.0)
|
|
48
|
+
zeta = kwargs.get('zeta', 2.0)
|
|
44
49
|
hoverR = kwargs.get('hoverR', 0.3)
|
|
50
|
+
calculate_f_debris = kwargs.get('calculate_f_debris', False)
|
|
51
|
+
|
|
52
|
+
# Determine debris fraction
|
|
53
|
+
if 'f_debris' in kwargs:
|
|
54
|
+
# User explicitly provided f_debris - use that value
|
|
55
|
+
f_debris = kwargs['f_debris']
|
|
56
|
+
f_mbh = None
|
|
57
|
+
g_mstar = None
|
|
58
|
+
scaling_factor = None
|
|
59
|
+
elif calculate_f_debris:
|
|
60
|
+
# Calculate debris fraction from beta using Ryu et al. scaling
|
|
61
|
+
# R_t = r_t * f(m_bh) * g(m_star)
|
|
62
|
+
# f(m_bh) = 0.80 + 0.26 * (mbh/10^6)^0.5
|
|
63
|
+
f_mbh = 0.80 + 0.26 * (mbh_6) ** 0.5
|
|
64
|
+
|
|
65
|
+
# g(m_star) = (1.47 + exp[(M_star - 0.669)/0.137]) / (1 + 2.34 * exp[(M_star - 0.669)/0.137])
|
|
66
|
+
exp_term = np.exp((stellar_mass - 0.669) / 0.137)
|
|
67
|
+
g_mstar = (1.47 + exp_term) / (1 + 2.34 * exp_term)
|
|
68
|
+
|
|
69
|
+
# Combined scaling factor
|
|
70
|
+
scaling_factor = f_mbh * g_mstar
|
|
71
|
+
|
|
72
|
+
# f_debris = (beta * scaling_factor)^3
|
|
73
|
+
f_debris = (beta * scaling_factor) ** 3
|
|
74
|
+
f_debris = np.clip(f_debris, 0.0, 1.0) # Ensure physical bounds
|
|
75
|
+
else:
|
|
76
|
+
# Default behavior: assume complete disruption
|
|
77
|
+
f_debris = 1.0
|
|
78
|
+
f_mbh = None
|
|
79
|
+
g_mstar = None
|
|
80
|
+
scaling_factor = None
|
|
45
81
|
|
|
46
82
|
# gravitational radius
|
|
47
83
|
Rg = cc.graviational_constant * mbh_6 * 1.0e6 * (cc.solar_mass / cc.speed_of_light ** (2.0))
|
|
48
84
|
# stellar mass in cgs
|
|
49
85
|
Mstar = stellar_mass * cc.solar_mass
|
|
86
|
+
# effective disrupted mass
|
|
87
|
+
Mdisrupt = f_debris * Mstar
|
|
50
88
|
# stellar radius in cgs
|
|
51
89
|
Rstar = stellar_mass ** (0.8) * cc.solar_radius
|
|
52
90
|
# tidal radius
|
|
53
|
-
Rt = Rstar * (mbh_6*1.0e6 /stellar_mass) ** (1
|
|
91
|
+
Rt = Rstar * (mbh_6 * 1.0e6 / stellar_mass) ** (1. / 3.)
|
|
54
92
|
# circularization radius
|
|
55
|
-
Rcirc = 2.0*Rt/beta
|
|
56
|
-
# fall-back time of most tightly bound debris
|
|
57
|
-
tfb = calc_tfb(binding_energy_const, mbh_6, stellar_mass)
|
|
93
|
+
Rcirc = 2.0 * Rt / beta
|
|
94
|
+
# fall-back time of most tightly bound debris (uses effective disrupted mass)
|
|
95
|
+
tfb = calc_tfb(binding_energy_const, mbh_6, stellar_mass * f_debris)
|
|
58
96
|
# Eddington luminosity of SMBH in units of 1e40 erg/s
|
|
59
97
|
Ledd40 = 1.4e4 * mbh_6
|
|
60
|
-
time_temp = np.logspace(np.log10(1.0*tfb), np.log10(5000*tfb), 5000)
|
|
61
|
-
tdays = time_temp/cc.day_to_s
|
|
98
|
+
time_temp = np.logspace(np.log10(1.0 * tfb), np.log10(5000 * tfb), 5000)
|
|
99
|
+
tdays = time_temp / cc.day_to_s
|
|
62
100
|
|
|
63
|
-
#set up grids
|
|
101
|
+
# set up grids
|
|
64
102
|
# mass of envelope in Msun
|
|
65
103
|
Me = np.empty_like(tdays)
|
|
66
104
|
# thermal energy of envelope in units of 1e40 ergs
|
|
@@ -90,28 +128,30 @@ def _cooling_envelope(mbh_6, stellar_mass, eta, alpha, beta, **kwargs):
|
|
|
90
128
|
# proxy x-ray luminosity (not used directly in optical light curve calculation)
|
|
91
129
|
LX40 = np.empty_like(tdays)
|
|
92
130
|
|
|
93
|
-
|
|
131
|
+
# Modified fallback rate using disrupted mass
|
|
132
|
+
Mdotfb = (0.8 * Mdisrupt / (3.0 * tfb)) * (time_temp / tfb) ** (-5. / 3.)
|
|
94
133
|
|
|
95
134
|
# ** initialize grid quantities at t = t_0_init [grid point 0] **
|
|
96
|
-
# initial envelope mass at t_0_init
|
|
97
|
-
Me[0] = 0.1 * Mstar + (0.4 * Mstar) * (1.0 - t_0_init**(-2. / 3.))
|
|
135
|
+
# initial envelope mass at t_0_init (scaled by disruption fraction)
|
|
136
|
+
Me[0] = f_debris * (0.1 * Mstar + (0.4 * Mstar) * (1.0 - t_0_init ** (-2. / 3.)))
|
|
98
137
|
# initial envelope radius determined by energy of TDE process
|
|
99
|
-
Rv[0] = (2. * Rt**(2.0)/(5.0 * binding_energy_const * Rstar)) * (Me[0]/Mstar)
|
|
138
|
+
Rv[0] = (2. * Rt ** (2.0) / (5.0 * binding_energy_const * Rstar)) * (Me[0] / (f_debris * Mstar))
|
|
100
139
|
# initial thermal energy of envelope
|
|
101
140
|
Ee40[0] = ((2.0 * cc.graviational_constant * mbh_6 * 1.0e6 * Me[0]) / (5.0 * Rv[0])) * 2.0e-7
|
|
102
141
|
# initial characteristic optical depth
|
|
103
|
-
Lamb[0] = 0.38 * Me[0] / (10.0 *np.pi * Rv[0] ** (2.0))
|
|
142
|
+
Lamb[0] = 0.38 * Me[0] / (10.0 * np.pi * Rv[0] ** (2.0))
|
|
104
143
|
# initial photosphere radius
|
|
105
144
|
Rph[0] = Rv[0] * (1.0 + np.log(Lamb[0]))
|
|
106
145
|
# initial fallback stream accretion radius
|
|
107
146
|
Racc[0] = zeta * Rv[0]
|
|
108
147
|
# initial fallback accretion heating rate in 1e40 erg/s
|
|
109
|
-
Edotfb40[0] = (cc.graviational_constant * mbh_6 * 1.0e6 * Mdotfb[0]/Racc[0]) * (2.0e-7)
|
|
148
|
+
Edotfb40[0] = (cc.graviational_constant * mbh_6 * 1.0e6 * Mdotfb[0] / Racc[0]) * (2.0e-7)
|
|
110
149
|
# initial luminosity of envelope
|
|
111
150
|
Lrad[0] = Ledd40 + Edotfb40[0]
|
|
112
151
|
# initial SMBH accretion timescale in s
|
|
113
|
-
tacc[0] = 2.2e-17 * (10. / (3. * alpha)) * (Rv[0] ** (2.0)) / (
|
|
114
|
-
|
|
152
|
+
tacc[0] = 2.2e-17 * (10. / (3. * alpha)) * (Rv[0] ** (2.0)) / (
|
|
153
|
+
cc.graviational_constant * mbh_6 * 1.0e6 * Rcirc) ** (0.5) * (hoverR) ** (
|
|
154
|
+
-2.0)
|
|
115
155
|
# initial SMBH accretion rate in g/s
|
|
116
156
|
MdotBH[0] = (Me[0] / tacc[0])
|
|
117
157
|
# initial SMBH feedback heating rate in 1e40 erg/s
|
|
@@ -127,7 +167,7 @@ def _cooling_envelope(mbh_6, stellar_mass, eta, alpha, beta, **kwargs):
|
|
|
127
167
|
# update envelope radius based on its new energy
|
|
128
168
|
Rv[ii] = ((2.0 * cc.graviational_constant * mbh_6 * 1.0e6 * Me[ii]) / (5.0 * Ee40[ii])) * (2.0e-7)
|
|
129
169
|
# update envelope optical depth
|
|
130
|
-
Lamb[ii] = 0.38 * Me[ii] / (10.0 *np.pi * Rv[ii] ** (2.0))
|
|
170
|
+
Lamb[ii] = 0.38 * Me[ii] / (10.0 * np.pi * Rv[ii] ** (2.0))
|
|
131
171
|
# update envelope photosphere radius
|
|
132
172
|
Rph[ii] = Rv[ii] * (1.0 + np.log(Lamb[ii]))
|
|
133
173
|
# update accretion radius
|
|
@@ -137,10 +177,11 @@ def _cooling_envelope(mbh_6, stellar_mass, eta, alpha, beta, **kwargs):
|
|
|
137
177
|
# update total radiated luminosity
|
|
138
178
|
Lrad[ii] = Ledd40 + Edotfb40[ii]
|
|
139
179
|
# update photosphere temperature in K
|
|
140
|
-
Teff[ii] = 1.0e10 * ((Ledd40 + Edotfb40[ii]) / (4.0 *np.pi * cc.sigma_sb * Rph[ii] ** (2.0))) ** (0.25)
|
|
180
|
+
Teff[ii] = 1.0e10 * ((Ledd40 + Edotfb40[ii]) / (4.0 * np.pi * cc.sigma_sb * Rph[ii] ** (2.0))) ** (0.25)
|
|
141
181
|
# update SMBH accretion timescale in seconds
|
|
142
|
-
tacc[ii] = 2.2e-17 * (10. / (3.0 * alpha)) * (Rv[ii] ** (2.0)) / (
|
|
143
|
-
|
|
182
|
+
tacc[ii] = 2.2e-17 * (10. / (3.0 * alpha)) * (Rv[ii] ** (2.0)) / (
|
|
183
|
+
cc.graviational_constant * mbh_6 * 1.0e6 * Rcirc) ** (0.5) * (
|
|
184
|
+
hoverR) ** (-2.0)
|
|
144
185
|
# update SMBH accretion rate in g/s
|
|
145
186
|
MdotBH[ii] = (Me[ii] / tacc[ii])
|
|
146
187
|
# update proxy X-ray luminosity
|
|
@@ -151,19 +192,24 @@ def _cooling_envelope(mbh_6, stellar_mass, eta, alpha, beta, **kwargs):
|
|
|
151
192
|
output = namedtuple('output', ['bolometric_luminosity', 'photosphere_temperature',
|
|
152
193
|
'photosphere_radius', 'lum_xray', 'accretion_radius',
|
|
153
194
|
'SMBH_accretion_rate', 'time_temp', 'nulnu',
|
|
154
|
-
'time_since_fb','tfb', 'lnu', 'envelope_radius', 'envelope_mass',
|
|
155
|
-
'rtidal', 'rcirc', 'termination_time', 'termination_time_id'
|
|
195
|
+
'time_since_fb', 'tfb', 'lnu', 'envelope_radius', 'envelope_mass',
|
|
196
|
+
'rtidal', 'rcirc', 'termination_time', 'termination_time_id', 'f_debris',
|
|
197
|
+
'f_mbh', 'g_mstar', 'scaling_factor'])
|
|
156
198
|
try:
|
|
157
|
-
constraint_1 = np.min(np.where(Rv < Rcirc/2.))
|
|
199
|
+
constraint_1 = np.min(np.where(Rv < Rcirc / 2.))
|
|
200
|
+
if constraint_1 == 0.:
|
|
201
|
+
# ignore constraining on Rv < Rcirc/2. if it is at the first time step
|
|
202
|
+
constraint_1 = 5000
|
|
158
203
|
constraint_2 = np.min(np.where(Me < 0.0))
|
|
159
204
|
except ValueError:
|
|
160
205
|
constraint_1 = len(time_temp)
|
|
161
206
|
constraint_2 = len(time_temp)
|
|
162
207
|
constraint = np.min([constraint_1, constraint_2])
|
|
163
208
|
termination_time_id = np.min([constraint_1, constraint_2])
|
|
209
|
+
|
|
164
210
|
nu = 6.0e14
|
|
165
211
|
expon = 1. / (np.exp(cc.planck * nu / (cc.boltzmann_constant * Teff)) - 1.0)
|
|
166
|
-
nuLnu40 = (8.0*np.pi ** (2.0) * Rph ** (2.0) / cc.speed_of_light ** (2.0))
|
|
212
|
+
nuLnu40 = (8.0 * np.pi ** (2.0) * Rph ** (2.0) / cc.speed_of_light ** (2.0))
|
|
167
213
|
nuLnu40 = nuLnu40 * ((cc.planck * nu) * (nu ** (2.0))) / 1.0e30
|
|
168
214
|
nuLnu40 = nuLnu40 * expon
|
|
169
215
|
nuLnu40 = nuLnu40 * (nu / 1.0e10)
|
|
@@ -187,6 +233,10 @@ def _cooling_envelope(mbh_6, stellar_mass, eta, alpha, beta, **kwargs):
|
|
|
187
233
|
output.termination_time_id = termination_time_id
|
|
188
234
|
output.tfb = tfb
|
|
189
235
|
output.nulnu = nuLnu40[:constraint] * 1e40
|
|
236
|
+
output.f_debris = f_debris
|
|
237
|
+
output.f_mbh = f_mbh
|
|
238
|
+
output.g_mstar = g_mstar
|
|
239
|
+
output.scaling_factor = scaling_factor
|
|
190
240
|
return output
|
|
191
241
|
|
|
192
242
|
@citation_wrapper('https://arxiv.org/abs/2307.15121,https://ui.adsabs.harvard.edu/abs/2022arXiv220707136M/abstract')
|
|
@@ -201,7 +251,7 @@ def cooling_envelope(time, redshift, mbh_6, stellar_mass, eta, alpha, beta, **kw
|
|
|
201
251
|
:param eta: SMBH feedback efficiency (typical range: etamin - 0.1)
|
|
202
252
|
:param alpha: disk viscosity
|
|
203
253
|
:param beta: TDE penetration factor (typical range: 1 - beta_max)
|
|
204
|
-
:param kwargs: Additional parameters
|
|
254
|
+
:param kwargs: Additional parameters, check _cooling_envelope for more information
|
|
205
255
|
:param frequency: Required if output_format is 'flux_density'.
|
|
206
256
|
frequency to calculate - Must be same length as time array or a single number).
|
|
207
257
|
:param bands: Required if output_format is 'magnitude' or 'flux'.
|
|
@@ -256,9 +306,10 @@ def cooling_envelope(time, redshift, mbh_6, stellar_mass, eta, alpha, beta, **kw
|
|
|
256
306
|
**kwargs)
|
|
257
307
|
|
|
258
308
|
@citation_wrapper('https://arxiv.org/abs/2307.15121,https://ui.adsabs.harvard.edu/abs/2022arXiv220707136M/abstract')
|
|
259
|
-
def gaussianrise_cooling_envelope_bolometric(time, peak_time, sigma_t, mbh_6, stellar_mass, eta, alpha, beta,
|
|
309
|
+
def gaussianrise_cooling_envelope_bolometric(time, peak_time, sigma_t, mbh_6, stellar_mass, eta, alpha, beta,
|
|
310
|
+
**kwargs):
|
|
260
311
|
"""
|
|
261
|
-
Full lightcurve, with gaussian rise till fallback time and then the metzger tde model,
|
|
312
|
+
Full lightcurve, with gaussian rise till xi * fallback time and then the metzger tde model,
|
|
262
313
|
bolometric version for fitting the bolometric lightcurve
|
|
263
314
|
|
|
264
315
|
:param time: time in source frame in days
|
|
@@ -269,28 +320,116 @@ def gaussianrise_cooling_envelope_bolometric(time, peak_time, sigma_t, mbh_6, st
|
|
|
269
320
|
:param eta: SMBH feedback efficiency (typical range: etamin - 0.1)
|
|
270
321
|
:param alpha: disk viscosity
|
|
271
322
|
:param beta: TDE penetration factor (typical range: 1 - beta_max)
|
|
272
|
-
:param kwargs: Additional parameters
|
|
323
|
+
:param kwargs: Additional parameters, check _cooling_envelope for more information
|
|
324
|
+
:param xi: Optional, default is 1. transition factor - Gaussian transitions to cooling envelope at xi * tfb
|
|
273
325
|
:return luminosity in ergs/s
|
|
274
326
|
"""
|
|
275
327
|
output = _cooling_envelope(mbh_6, stellar_mass, eta, alpha, beta, **kwargs)
|
|
276
328
|
kwargs['binding_energy_const'] = kwargs.get('binding_energy_const', 0.8)
|
|
277
329
|
tfb_sf = calc_tfb(kwargs['binding_energy_const'], mbh_6, stellar_mass) # source frame
|
|
278
|
-
|
|
330
|
+
|
|
331
|
+
# Transition time
|
|
332
|
+
xi = kwargs.get('xi', 1.)
|
|
333
|
+
transition_time = xi * tfb_sf
|
|
334
|
+
|
|
335
|
+
# Find the luminosity value at the transition time by interpolating the cooling envelope model
|
|
336
|
+
# Create interpolation function for the cooling envelope model
|
|
337
|
+
cooling_envelope_func = interp1d(output.time_temp, output.bolometric_luminosity,
|
|
338
|
+
bounds_error=False, fill_value='extrapolate')
|
|
339
|
+
|
|
340
|
+
# Get luminosity at transition time
|
|
341
|
+
f1 = pm.gaussian_rise(time=transition_time, a_1=1,
|
|
342
|
+
peak_time=peak_time * cc.day_to_s,
|
|
343
|
+
sigma_t=sigma_t * cc.day_to_s)
|
|
279
344
|
|
|
280
345
|
# get normalisation
|
|
281
|
-
f2 =
|
|
282
|
-
norm = f2/f1
|
|
346
|
+
f2 = cooling_envelope_func(transition_time)
|
|
347
|
+
norm = f2 / f1
|
|
283
348
|
|
|
284
|
-
#evaluate giant array of bolometric luminosities
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
349
|
+
# evaluate giant array of bolometric luminosities
|
|
350
|
+
tt_pre_transition = np.linspace(0, transition_time, 100)
|
|
351
|
+
# Only use cooling envelope times after the transition
|
|
352
|
+
tt_post_transition = output.time_temp[output.time_temp >= transition_time]
|
|
353
|
+
|
|
354
|
+
full_time = np.concatenate([tt_pre_transition, tt_post_transition])
|
|
355
|
+
|
|
356
|
+
# Gaussian part before transition
|
|
357
|
+
f1_array = pm.gaussian_rise(time=tt_pre_transition, a_1=norm,
|
|
358
|
+
peak_time=peak_time * cc.day_to_s,
|
|
359
|
+
sigma_t=sigma_t * cc.day_to_s)
|
|
360
|
+
|
|
361
|
+
# Cooling envelope part after transition
|
|
362
|
+
f2_array = output.bolometric_luminosity[output.time_temp >= transition_time]
|
|
363
|
+
|
|
364
|
+
full_lbol = np.concatenate([f1_array, f2_array])
|
|
292
365
|
lbol_func = interp1d(full_time, y=full_lbol, fill_value='extrapolate')
|
|
293
|
-
|
|
366
|
+
|
|
367
|
+
return lbol_func(time * cc.day_to_s)
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
@citation_wrapper('https://arxiv.org/abs/2307.15121,https://ui.adsabs.harvard.edu/abs/2022arXiv220707136M/abstract')
|
|
371
|
+
def smooth_exponential_powerlaw_cooling_envelope_bolometric(time, peak_time, alpha_1, alpha_2, smoothing_factor,
|
|
372
|
+
mbh_6, stellar_mass, eta, alpha, beta, **kwargs):
|
|
373
|
+
"""
|
|
374
|
+
Full lightcurve, with smoothed exponential power law rise till xi * fallback time and then the metzger tde model,
|
|
375
|
+
bolometric version for fitting the bolometric lightcurve
|
|
376
|
+
|
|
377
|
+
:param time: time in source frame in days
|
|
378
|
+
:param peak_time: peak time in days
|
|
379
|
+
:param alpha_1: power law index before peak
|
|
380
|
+
:param alpha_2: power law index after peak
|
|
381
|
+
:param smoothing_factor: controls transition smoothness at peak (higher = smoother)
|
|
382
|
+
:param mbh_6: mass of supermassive black hole in units of 10^6 solar mass
|
|
383
|
+
:param stellar_mass: stellar mass in units of solar masses
|
|
384
|
+
:param eta: SMBH feedback efficiency (typical range: etamin - 0.1)
|
|
385
|
+
:param alpha: disk viscosity
|
|
386
|
+
:param beta: TDE penetration factor (typical range: 1 - beta_max)
|
|
387
|
+
:param xi: Optional transition factor - smooth exponential power law transitions to cooling envelope at xi * tfb
|
|
388
|
+
:param kwargs: Additional parameters, check _cooling_envelope for more information
|
|
389
|
+
:return luminosity in ergs/s
|
|
390
|
+
"""
|
|
391
|
+
# Get cooling envelope output
|
|
392
|
+
output = _cooling_envelope(mbh_6, stellar_mass, eta, alpha, beta, **kwargs)
|
|
393
|
+
kwargs['binding_energy_const'] = kwargs.get('binding_energy_const', 0.8)
|
|
394
|
+
tfb_sf = calc_tfb(kwargs['binding_energy_const'], mbh_6, stellar_mass) # source frame
|
|
395
|
+
|
|
396
|
+
# Transition time
|
|
397
|
+
xi = kwargs.get('xi', 1.)
|
|
398
|
+
transition_time = xi * tfb_sf
|
|
399
|
+
|
|
400
|
+
# Find the luminosity value at the transition time by interpolating the cooling envelope model
|
|
401
|
+
# Create interpolation function for the cooling envelope model
|
|
402
|
+
cooling_envelope_func = interp1d(output.time_temp, output.bolometric_luminosity,
|
|
403
|
+
bounds_error=False, fill_value='extrapolate')
|
|
404
|
+
|
|
405
|
+
# Get luminosity at transition time using smooth exponential power law
|
|
406
|
+
f1 = pm.smooth_exponential_powerlaw(np.array([transition_time]), 1.0,
|
|
407
|
+
peak_time * cc.day_to_s,
|
|
408
|
+
alpha_1, alpha_2, smoothing_factor)[0]
|
|
409
|
+
|
|
410
|
+
# get normalisation
|
|
411
|
+
f2 = cooling_envelope_func(transition_time)
|
|
412
|
+
norm = f2 / f1
|
|
413
|
+
|
|
414
|
+
# evaluate giant array of bolometric luminosities
|
|
415
|
+
tt_pre_transition = np.linspace(0, transition_time, 100)
|
|
416
|
+
# Only use cooling envelope times after the transition
|
|
417
|
+
tt_post_transition = output.time_temp[output.time_temp >= transition_time]
|
|
418
|
+
|
|
419
|
+
full_time = np.concatenate([tt_pre_transition, tt_post_transition])
|
|
420
|
+
|
|
421
|
+
# Smooth exponential power law part before transition
|
|
422
|
+
f1_array = pm.smooth_exponential_powerlaw(tt_pre_transition, norm,
|
|
423
|
+
peak_time * cc.day_to_s,
|
|
424
|
+
alpha_1, alpha_2, smoothing_factor)
|
|
425
|
+
|
|
426
|
+
# Cooling envelope part after transition
|
|
427
|
+
f2_array = output.bolometric_luminosity[output.time_temp >= transition_time]
|
|
428
|
+
|
|
429
|
+
full_lbol = np.concatenate([f1_array, f2_array])
|
|
430
|
+
lbol_func = interp1d(full_time, y=full_lbol, fill_value='extrapolate')
|
|
431
|
+
|
|
432
|
+
return lbol_func(time * cc.day_to_s)
|
|
294
433
|
|
|
295
434
|
|
|
296
435
|
@citation_wrapper('https://arxiv.org/abs/2307.15121,https://ui.adsabs.harvard.edu/abs/2022arXiv220707136M/abstract')
|
|
@@ -308,7 +447,7 @@ def gaussianrise_cooling_envelope(time, redshift, peak_time, sigma_t, mbh_6, ste
|
|
|
308
447
|
:param eta: SMBH feedback efficiency (typical range: etamin - 0.1)
|
|
309
448
|
:param alpha: disk viscosity
|
|
310
449
|
:param beta: TDE penetration factor (typical range: 1 - beta_max)
|
|
311
|
-
:param kwargs: Additional parameters
|
|
450
|
+
:param kwargs: Additional parameters, check _cooling_envelope for more information
|
|
312
451
|
:param xi: Optional argument (default set to one) to change the point where lightcurve switches from Gaussian rise to cooling envelope.
|
|
313
452
|
stitching_point = xi * tfb (where tfb is fallback time). So a xi=1 means the stitching point is at fallback time.
|
|
314
453
|
:param frequency: Required if output_format is 'flux_density'.
|
|
@@ -428,7 +567,7 @@ def bpl_cooling_envelope(time, redshift, peak_time, alpha_1, alpha_2, mbh_6, ste
|
|
|
428
567
|
:param eta: SMBH feedback efficiency (typical range: etamin - 0.1)
|
|
429
568
|
:param alpha: disk viscosity
|
|
430
569
|
:param beta: TDE penetration factor (typical range: 1 - beta_max)
|
|
431
|
-
:param kwargs: Additional parameters
|
|
570
|
+
:param kwargs: Additional parameters, check _cooling_envelope for more information
|
|
432
571
|
:param xi: Optional argument (default set to one) to change the point where lightcurve switches from Gaussian rise to cooling envelope.
|
|
433
572
|
stitching_point = xi * tfb (where tfb is fallback time). So a xi=1 means the stitching point is at fallback time.
|
|
434
573
|
:param frequency: Required if output_format is 'flux_density'.
|
|
@@ -1134,7 +1273,7 @@ def fitted(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl, **kwargs
|
|
|
1134
1273
|
**kwargs)
|
|
1135
1274
|
|
|
1136
1275
|
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2024arXiv240815048M/abstract')
|
|
1137
|
-
def fitted_pl_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl, log_L, t_decay, p, log_T,
|
|
1276
|
+
def fitted_pl_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl, log_L, t_decay, p, log_T, sigma_t, t_peak, **kwargs):
|
|
1138
1277
|
"""
|
|
1139
1278
|
An import of FitTeD to model the plateau phase, with a gaussian rise and power-law decay
|
|
1140
1279
|
|
|
@@ -1151,7 +1290,7 @@ def fitted_pl_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl,
|
|
|
1151
1290
|
:param t_decay: fallback timescale (days)
|
|
1152
1291
|
:param p: power-law decay index
|
|
1153
1292
|
:param log_T: single temperature blackbody temperature for decay model (log_10 Kelvin)
|
|
1154
|
-
:param
|
|
1293
|
+
:param sigma_t: gaussian rise timescale (days)
|
|
1155
1294
|
:param t_peak: time of light curve peak (days)
|
|
1156
1295
|
:param kwargs: Must be all the kwargs required by the specific output_format
|
|
1157
1296
|
:param output_format: 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
|
|
@@ -1180,13 +1319,13 @@ def fitted_pl_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl,
|
|
|
1180
1319
|
if len(freqs_un) == 1:
|
|
1181
1320
|
nulnus_plateau = m.model_UV(time, log_mh, a_bh, m_disc, r0, tvi, t_form, ang, v=freqs_un[0])
|
|
1182
1321
|
nulnus_decay = m.decay_model(time, log_L, t_decay, p, t_peak, log_T, v=freqs_un[0])
|
|
1183
|
-
nulnus_rise = m.rise_model(time, log_L,
|
|
1322
|
+
nulnus_rise = m.rise_model(time, log_L, sigma_t, t_peak, log_T, v=freqs_un[0])
|
|
1184
1323
|
else:
|
|
1185
1324
|
for i in range(0,len(freqs_un)):
|
|
1186
1325
|
inds = np.where(frequency == freqs_un[i])[0]
|
|
1187
1326
|
nulnus[inds] = m.model_UV([time[j] for j in inds], log_mh, a_bh, m_disc, r0, tvi, t_form, ang, freqs_un[i])
|
|
1188
1327
|
nulnus_decay[inds] = m.decay_model([time[j] for j in inds], log_L, t_decay, p, t_peak, log_T, v=freqs_un[i])
|
|
1189
|
-
nulnus_rise[inds] = m.rise_model([time[j] for j in inds], log_L,
|
|
1328
|
+
nulnus_rise[inds] = m.rise_model([time[j] for j in inds], log_L, sigma_t, t_peak, log_T, v=freqs_un[i])
|
|
1190
1329
|
nulnus = nulnus_plateau + nulnus_rise + nulnus_decay
|
|
1191
1330
|
flux_density = nulnus/(4.0 * np.pi * dl**2 * frequency)
|
|
1192
1331
|
return flux_density/1.0e-26
|
|
@@ -1201,7 +1340,7 @@ def fitted_pl_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl,
|
|
|
1201
1340
|
nulnus_plateau = m.model_SEDs(time, log_mh, a_bh, m_disc, r0, tvi, t_form, ang, frequency)
|
|
1202
1341
|
|
|
1203
1342
|
freq_0 = 6e14
|
|
1204
|
-
l_e_amp = (model.decay_model(time, log_L, t_decay, t_peak, log_T, freq_0) + model.rise_model(time, log_L,
|
|
1343
|
+
l_e_amp = (model.decay_model(time, log_L, t_decay, t_peak, log_T, freq_0) + model.rise_model(time, log_L, sigma_t, t_peak, log_T, freq_0))
|
|
1205
1344
|
nulnus_risedecay = ((l_e_amp[:, None] * (frequency/freq_0)**4 *
|
|
1206
1345
|
(np.exp(cc.planck * freq_0/(cc.boltzmann_constant * 10**log_T)) - 1)/(np.exp(cc.planck * frequency/(cc.boltzmann_constant * 10**log_T)) - 1)).T)
|
|
1207
1346
|
flux_density = ((nulnus_risedecay + nulnus_plateau)/(4.0 * np.pi * dl**2 * frequency[:,np.newaxis] * 1.0e-26))
|
|
@@ -1218,7 +1357,7 @@ def fitted_pl_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl,
|
|
|
1218
1357
|
**kwargs)
|
|
1219
1358
|
|
|
1220
1359
|
@citation_wrapper('https://ui.adsabs.harvard.edu/abs/2024arXiv240815048M/abstract')
|
|
1221
|
-
def fitted_exp_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl, log_L, t_decay, log_T,
|
|
1360
|
+
def fitted_exp_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl, log_L, t_decay, log_T, sigma_t, t_peak, **kwargs):
|
|
1222
1361
|
"""
|
|
1223
1362
|
An import of FitTeD to model the plateau phase, with a gaussian rise and exponential decay
|
|
1224
1363
|
|
|
@@ -1234,7 +1373,7 @@ def fitted_exp_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl
|
|
|
1234
1373
|
:param log_L: single temperature blackbody amplitude for decay model (log_10 erg/s)
|
|
1235
1374
|
:param t_decay: fallback timescale (days)
|
|
1236
1375
|
:param log_T: single temperature blackbody temperature for decay model (log_10 Kelvin)
|
|
1237
|
-
:param
|
|
1376
|
+
:param sigma_t: gaussian rise timescale (days)
|
|
1238
1377
|
:param t_peak: time of light curve peak (days)
|
|
1239
1378
|
:param kwargs: Must be all the kwargs required by the specific output_format
|
|
1240
1379
|
:param output_format: 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
|
|
@@ -1263,13 +1402,13 @@ def fitted_exp_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl
|
|
|
1263
1402
|
if len(freqs_un) == 1:
|
|
1264
1403
|
nulnus_plateau = m.model_UV(time, log_mh, a_bh, m_disc, r0, tvi, t_form, ang, v=freqs_un[0])
|
|
1265
1404
|
nulnus_decay = m.decay_model(time, log_L, t_decay, t_peak, log_T, v=freqs_un[0])
|
|
1266
|
-
nulnus_rise = m.rise_model(time, log_L,
|
|
1405
|
+
nulnus_rise = m.rise_model(time, log_L, sigma_t, t_peak, log_T, v=freqs_un[0])
|
|
1267
1406
|
else:
|
|
1268
1407
|
for i in range(0,len(freqs_un)):
|
|
1269
1408
|
inds = np.where(frequency == freqs_un[i])[0]
|
|
1270
1409
|
nulnus[inds] = m.model_UV([time[j] for j in inds], log_mh, a_bh, m_disc, r0, tvi, t_form, ang, freqs_un[i])
|
|
1271
1410
|
nulnus_decay[inds] = m.decay_model([time[j] for j in inds], log_L, t_decay, t_peak, log_T, v=freqs_un[i])
|
|
1272
|
-
nulnus_rise[inds] = m.rise_model([time[j] for j in inds], log_L,
|
|
1411
|
+
nulnus_rise[inds] = m.rise_model([time[j] for j in inds], log_L, sigma_t, t_peak, log_T, v=freqs_un[i])
|
|
1273
1412
|
nulnus = nulnus_plateau + nulnus_rise + nulnus_decay
|
|
1274
1413
|
flux_density = nulnus/(4.0 * np.pi * dl**2 * frequency)
|
|
1275
1414
|
return flux_density/1.0e-26
|
|
@@ -1284,7 +1423,7 @@ def fitted_exp_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl
|
|
|
1284
1423
|
nulnus_plateau = m.model_SEDs(time, log_mh, a_bh, m_disc, r0, tvi, t_form, ang, frequency)
|
|
1285
1424
|
|
|
1286
1425
|
freq_0 = 6e14
|
|
1287
|
-
l_e_amp = (m.decay_model(time, log_L, t_decay, t_peak, log_T, freq_0) + m.rise_model(time, log_L,
|
|
1426
|
+
l_e_amp = (m.decay_model(time, log_L, t_decay, t_peak, log_T, freq_0) + m.rise_model(time, log_L, sigma_t, t_peak, log_T, freq_0))
|
|
1288
1427
|
nulnus_risedecay = ((l_e_amp[:, None] * (frequency/freq_0)**4 *
|
|
1289
1428
|
(np.exp(cc.planck * freq_0/(cc.boltzmann_constant * 10**log_T)) - 1)/(np.exp(cc.planck * frequency/(cc.boltzmann_constant * 10**log_T)) - 1)).T)
|
|
1290
1429
|
flux_density = ((nulnus_risedecay + nulnus_plateau)/(4.0 * np.pi * dl**2 * frequency[:,np.newaxis] * 1.0e-26))
|
redback/utils.py
CHANGED
|
@@ -125,12 +125,24 @@ def citation_wrapper(r):
|
|
|
125
125
|
|
|
126
126
|
return wrapper
|
|
127
127
|
|
|
128
|
+
def calc_effective_width_hz_from_angstrom(effective_width, effective_wavelength):
|
|
129
|
+
"""
|
|
130
|
+
Calculate the effective width in Hz from the effective wavelength in Angstrom
|
|
131
|
+
|
|
132
|
+
:param effective_width: effective_width in Angstrom
|
|
133
|
+
:param effective_wavelength: effective wavelength in Angstrom
|
|
134
|
+
:return: effective width in Hz
|
|
135
|
+
"""
|
|
136
|
+
wavelength_m = effective_wavelength * 1.0e-10
|
|
137
|
+
effective_width_m = effective_width * 1.0e-10
|
|
138
|
+
effective_width = (3.0e8 / (wavelength_m**2)) * effective_width_m
|
|
139
|
+
return effective_width
|
|
128
140
|
|
|
129
141
|
def calc_tfb(binding_energy_const, mbh_6, stellar_mass):
|
|
130
142
|
"""
|
|
131
143
|
Calculate the fall back timescale for a SMBH disrupting a stellar mass object
|
|
132
144
|
:param binding_energy_const:
|
|
133
|
-
:param mbh_6: SMBH mass in solar masses
|
|
145
|
+
:param mbh_6: SMBH mass in 10^6 solar masses
|
|
134
146
|
:param stellar_mass: stellar mass in solar masses
|
|
135
147
|
:return: fall back time in seconds
|
|
136
148
|
"""
|
|
@@ -1260,20 +1272,35 @@ def get_heating_terms(ye, vel, **kwargs):
|
|
|
1260
1272
|
return heating_terms
|
|
1261
1273
|
|
|
1262
1274
|
|
|
1275
|
+
# Global cache to avoid recreating interpolator every time
|
|
1276
|
+
_qdot_interpolator_cache = None
|
|
1277
|
+
|
|
1263
1278
|
def _calculate_rosswogkorobkin24_qdot(time_array, ejecta_velocity, electron_fraction):
|
|
1264
|
-
import
|
|
1279
|
+
import numpy as np
|
|
1280
|
+
from scipy.interpolate import RegularGridInterpolator
|
|
1265
1281
|
import os
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1282
|
+
|
|
1283
|
+
global _qdot_interpolator_cache
|
|
1284
|
+
|
|
1285
|
+
if _qdot_interpolator_cache is None:
|
|
1286
|
+
dirname = os.path.dirname(__file__)
|
|
1287
|
+
|
|
1288
|
+
with np.load(f"{dirname}/tables/qdot_rosswogkorobkin24.npz") as data:
|
|
1289
|
+
qedt = data['qedt']
|
|
1290
|
+
v_grid = data['v_grid']
|
|
1291
|
+
ye_grid = data['ye_grid']
|
|
1292
|
+
time_grid = data['time_array']
|
|
1293
|
+
|
|
1294
|
+
_qdot_interpolator_cache = RegularGridInterpolator((v_grid, ye_grid, time_grid), qedt,
|
|
1295
|
+
bounds_error=False, fill_value=None)
|
|
1296
|
+
|
|
1269
1297
|
steps = len(time_array)
|
|
1270
1298
|
_ej_velocity = np.repeat(ejecta_velocity, steps)
|
|
1271
1299
|
_ye = np.repeat(electron_fraction, steps)
|
|
1272
1300
|
full_array = np.array([_ej_velocity, _ye, time_array]).T
|
|
1273
|
-
lum_in =
|
|
1301
|
+
lum_in = _qdot_interpolator_cache(full_array)
|
|
1274
1302
|
return lum_in
|
|
1275
1303
|
|
|
1276
|
-
|
|
1277
1304
|
def electron_fraction_from_kappa(kappa):
|
|
1278
1305
|
"""
|
|
1279
1306
|
Uses interpolation from Tanaka+19 to calculate
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: redback
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.12.1
|
|
4
4
|
Summary: A Bayesian inference and modelling pipeline for electromagnetic transients
|
|
5
5
|
Home-page: https://github.com/nikhil-sarin/redback
|
|
6
6
|
Author: Nikhil Sarin, Moritz Huebner
|
|
@@ -12,10 +12,10 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENCE.md
|
|
15
|
-
Requires-Dist: numpy
|
|
15
|
+
Requires-Dist: numpy
|
|
16
16
|
Requires-Dist: setuptools
|
|
17
17
|
Requires-Dist: pandas
|
|
18
|
-
Requires-Dist: scipy
|
|
18
|
+
Requires-Dist: scipy
|
|
19
19
|
Requires-Dist: selenium
|
|
20
20
|
Requires-Dist: matplotlib
|
|
21
21
|
Requires-Dist: astropy
|
|
@@ -37,8 +37,11 @@ Requires-Dist: PyQt5; extra == "all"
|
|
|
37
37
|
Requires-Dist: lalsuite; extra == "all"
|
|
38
38
|
Requires-Dist: kilonova-heating-rate; extra == "all"
|
|
39
39
|
Requires-Dist: redback-surrogates; extra == "all"
|
|
40
|
+
Requires-Dist: tensorflow; extra == "all"
|
|
41
|
+
Requires-Dist: keras; extra == "all"
|
|
40
42
|
Requires-Dist: kilonovanet; extra == "all"
|
|
41
43
|
Requires-Dist: astroquery; extra == "all"
|
|
44
|
+
Requires-Dist: pyphot==1.6.0; extra == "all"
|
|
42
45
|
Dynamic: author
|
|
43
46
|
Dynamic: author-email
|
|
44
47
|
Dynamic: classifier
|
|
@@ -85,7 +88,7 @@ Simulate single transients or populations or simulate a full survey including no
|
|
|
85
88
|
### Contributing
|
|
86
89
|
If you are interested in contributing please join the redback
|
|
87
90
|
[slack](https://join.slack.com/t/redback-group/shared_invite/zt-2503mmkaq-EMEAgz7i3mY0pg1o~VUdqw)
|
|
88
|
-
and email [Nikhil Sarin](mailto:
|
|
91
|
+
and email [Nikhil Sarin](mailto:nsarin.astro@gmail.com?subject=Contributing%20to%20redback).
|
|
89
92
|
|
|
90
93
|
To make changes to redback, we require users to use a merge request system.
|
|
91
94
|
|