redback 1.0.1__py3-none-any.whl → 1.0.3__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.
Files changed (66) hide show
  1. redback/__init__.py +4 -0
  2. redback/constraints.py +46 -25
  3. redback/eos.py +1 -0
  4. redback/get_data/fink.py +1 -1
  5. redback/get_data/lasair.py +3 -4
  6. redback/get_data/swift.py +7 -7
  7. redback/interaction_processes.py +1 -4
  8. redback/likelihoods.py +207 -21
  9. redback/model_library.py +2 -2
  10. redback/plotting.py +10 -10
  11. redback/priors/bazin_sne.prior +5 -0
  12. redback/priors/csm_interaction.prior +6 -7
  13. redback/priors/csm_nickel.prior +3 -3
  14. redback/priors/csm_shock_and_arnett.prior +11 -0
  15. redback/priors/csm_shock_and_arnett_bolometric.prior +10 -0
  16. redback/priors/csm_shock_breakout.prior +7 -0
  17. redback/priors/nicholl_bns.prior +2 -1
  18. redback/priors/one_comp_kne_rosswog_heatingrate.prior +5 -0
  19. redback/priors/pwn.prior +7 -0
  20. redback/priors/shocked_cocoon.prior +6 -6
  21. redback/priors/sn_fallback.prior +8 -0
  22. redback/priors/stream_stream_tde.prior +10 -0
  23. redback/priors/stream_stream_tde_bolometric.prior +9 -0
  24. redback/priors/tde_analytical.prior +5 -5
  25. redback/priors/tde_analytical_bolometric.prior +6 -4
  26. redback/priors/tde_fallback.prior +9 -0
  27. redback/priors/tde_fallback_bolometric.prior +6 -0
  28. redback/priors/tde_synchrotron.prior +6 -0
  29. redback/priors/tophat_from_emulator.prior +9 -0
  30. redback/priors/two_comp_kne_rosswog_heatingrate.prior +9 -0
  31. redback/priors/two_layer_stratified_kilonova.prior +1 -1
  32. redback/priors/villar_sne.prior +7 -0
  33. redback/priors.py +12 -1
  34. redback/sed.py +194 -2
  35. redback/simulate_transients.py +71 -35
  36. redback/tables/GRBs_w_redshift.txt +430 -413
  37. redback/tables/LGRB_table.txt +70 -6
  38. redback/tables/SGRB_table.txt +139 -135
  39. redback/tables/filters.csv +14 -0
  40. redback/tables/qdot_rosswogkorobkin24.pck +0 -0
  41. redback/tables/ztf.tar.gz +0 -0
  42. redback/transient/afterglow.py +17 -7
  43. redback/transient/kilonova.py +6 -3
  44. redback/transient/prompt.py +14 -4
  45. redback/transient/supernova.py +7 -3
  46. redback/transient/tde.py +6 -3
  47. redback/transient/transient.py +29 -12
  48. redback/transient_models/afterglow_models.py +152 -146
  49. redback/transient_models/combined_models.py +69 -48
  50. redback/transient_models/extinction_models.py +6 -6
  51. redback/transient_models/general_synchrotron_models.py +518 -0
  52. redback/transient_models/integrated_flux_afterglow_models.py +2 -2
  53. redback/transient_models/kilonova_models.py +310 -61
  54. redback/transient_models/magnetar_driven_ejecta_models.py +2 -2
  55. redback/transient_models/magnetar_models.py +1 -1
  56. redback/transient_models/phenomenological_models.py +69 -1
  57. redback/transient_models/shock_powered_models.py +159 -110
  58. redback/transient_models/supernova_models.py +211 -43
  59. redback/transient_models/tde_models.py +975 -5
  60. redback/utils.py +309 -16
  61. {redback-1.0.1.dist-info → redback-1.0.3.dist-info}/METADATA +46 -6
  62. {redback-1.0.1.dist-info → redback-1.0.3.dist-info}/RECORD +65 -49
  63. {redback-1.0.1.dist-info → redback-1.0.3.dist-info}/WHEEL +1 -1
  64. redback/tables/ztf_obslog.csv +0 -106649
  65. {redback-1.0.1.dist-info → redback-1.0.3.dist-info}/LICENCE.md +0 -0
  66. {redback-1.0.1.dist-info → redback-1.0.3.dist-info}/top_level.txt +0 -0
@@ -4,13 +4,14 @@ import pandas as pd
4
4
  from astropy.table import Table, Column
5
5
  from scipy.interpolate import interp1d, RegularGridInterpolator
6
6
  from astropy.cosmology import Planck18 as cosmo # noqa
7
- from scipy.integrate import cumtrapz
7
+ from scipy.integrate import cumulative_trapezoid
8
8
  from collections import namedtuple
9
9
  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, _calculate_rosswogkorobkin24_qdot, \
14
+ kappa_from_electron_fraction
14
15
  from redback.eos import PiecewisePolytrope
15
16
  from redback.sed import blackbody_to_flux_density, get_correct_output_format_from_spectra, Blackbody
16
17
  from redback.constants import *
@@ -18,7 +19,7 @@ import redback.ejecta_relations as ejr
18
19
 
19
20
  @citation_wrapper('https://ui.adsabs.harvard.edu/abs/2021MNRAS.505.3016N/abstract')
20
21
  def _nicholl_bns_get_quantities(mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
21
- mtov, epsilon, alpha, cos_theta_cocoon, cos_theta, **kwargs):
22
+ mtov, epsilon, alpha, cos_theta_open, cos_theta, **kwargs):
22
23
  """
23
24
  Calculates quantities for the Nicholl et al. 2021 BNS model
24
25
 
@@ -31,7 +32,7 @@ def _nicholl_bns_get_quantities(mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
31
32
  :param epsilon: fraction of disk that gets unbound/ejected
32
33
  :param alpha: Enhancement of blue ejecta by NS surface winds if mtotal < prompt collapse,
33
34
  can turn off by setting alpha=1
34
- :param cos_theta_cocoon: Opening angle of shocked cocoon
35
+ :param cos_theta_open: Lanthanide opening angle
35
36
  :param cos_theta: Viewing angle of observer
36
37
  :param kwargs: Additional keyword arguments
37
38
  :param dynamical_ejecta_error: Error in dynamical ejecta mass, default is 1 i.e., no error in fitting formula
@@ -50,7 +51,7 @@ def _nicholl_bns_get_quantities(mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
50
51
  n_ave = 0.743
51
52
  dynamical_ejecta_error = kwargs.get('dynamical_ejecta_error', 1.0)
52
53
  disk_ejecta_error = kwargs.get('disk_ejecta_error', 1.0)
53
- theta_open = np.arccos(cos_theta_cocoon)
54
+ theta_open = np.arccos(cos_theta_open)
54
55
 
55
56
  fq = (1 - (mass_2 / mass_1) ** (10. / (3 - n_ave))) / (1 + (mass_2 / mass_1) ** (10. / (3 - n_ave)))
56
57
 
@@ -210,14 +211,14 @@ def _nicholl_bns_get_quantities(mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
210
211
  kappa_blue * mejecta_blue) / (mejecta_purple + mejecta_red + mejecta_blue)
211
212
 
212
213
  # Viewing angle and lanthanide-poor opening angle correction from Darbha and Kasen 2020
213
- ct = (1 - cos_theta_cocoon ** 2) ** 0.5
214
+ ct = (1 - cos_theta_open ** 2) ** 0.5
214
215
 
215
- if cos_theta_cocoon > ct:
216
+ if cos_theta > ct:
216
217
  area_projected_top = np.pi * ct * cos_theta
217
218
  else:
218
- theta_p = np.arccos(cos_theta_cocoon /
219
+ theta_p = np.arccos(cos_theta_open /
219
220
  (1 - cos_theta ** 2) ** 0.5)
220
- theta_d = np.arctan(np.sin(theta_p) / cos_theta_cocoon *
221
+ theta_d = np.arctan(np.sin(theta_p) / cos_theta_open *
221
222
  (1 - cos_theta ** 2) ** 0.5 / np.abs(cos_theta))
222
223
  area_projected_top = (theta_p - np.sin(theta_p) * np.cos(theta_p)) - (ct *
223
224
  cos_theta * (theta_d - np.sin(theta_d) * np.cos(
@@ -228,9 +229,9 @@ def _nicholl_bns_get_quantities(mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
228
229
  if minus_cos_theta < -1 * ct:
229
230
  area_projected_bottom = 0
230
231
  else:
231
- theta_p2 = np.arccos(cos_theta_cocoon /
232
+ theta_p2 = np.arccos(cos_theta_open /
232
233
  (1 - minus_cos_theta ** 2) ** 0.5)
233
- theta_d2 = np.arctan(np.sin(theta_p2) / cos_theta_cocoon *
234
+ theta_d2 = np.arctan(np.sin(theta_p2) / cos_theta_open *
234
235
  (1 - minus_cos_theta ** 2) ** 0.5 / np.abs(minus_cos_theta))
235
236
 
236
237
  Aproj_bot1 = (theta_p2 - np.sin(theta_p2) * np.cos(theta_p2)) + (ct *
@@ -247,9 +248,9 @@ def _nicholl_bns_get_quantities(mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
247
248
  if cos_theta_ref > ct:
248
249
  area_ref_top = np.pi * ct * cos_theta_ref
249
250
  else:
250
- theta_p_ref = np.arccos(cos_theta_cocoon /
251
+ theta_p_ref = np.arccos(cos_theta_open /
251
252
  (1 - cos_theta_ref ** 2) ** 0.5)
252
- theta_d_ref = np.arctan(np.sin(theta_p_ref) / cos_theta_cocoon *
253
+ theta_d_ref = np.arctan(np.sin(theta_p_ref) / cos_theta_open *
253
254
  (1 - cos_theta_ref ** 2) ** 0.5 / np.abs(cos_theta_ref))
254
255
  area_ref_top = (theta_p_ref - np.sin(theta_p_ref) *
255
256
  np.cos(theta_p_ref)) - (ct * cos_theta_ref *
@@ -261,10 +262,10 @@ def _nicholl_bns_get_quantities(mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
261
262
  if minus_cos_theta_ref < -1 * ct:
262
263
  area_ref_bottom = 0
263
264
  else:
264
- theta_p2_ref = np.arccos(cos_theta_cocoon /
265
+ theta_p2_ref = np.arccos(cos_theta_open /
265
266
  (1 - minus_cos_theta_ref ** 2) ** 0.5)
266
267
  theta_d2_ref = np.arctan(np.sin(theta_p2_ref) /
267
- cos_theta_cocoon * (1 - minus_cos_theta_ref ** 2) ** 0.5 /
268
+ cos_theta_open * (1 - minus_cos_theta_ref ** 2) ** 0.5 /
268
269
  np.abs(minus_cos_theta_ref))
269
270
 
270
271
  area_ref_bottom = (theta_p2_ref - np.sin(theta_p2_ref) *
@@ -309,7 +310,7 @@ def _nicholl_bns_get_quantities(mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
309
310
 
310
311
  @citation_wrapper('https://ui.adsabs.harvard.edu/abs/2021MNRAS.505.3016N/abstract')
311
312
  def nicholl_bns(time, redshift, mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
312
- mtov, epsilon, alpha, cos_theta, cos_theta_cocoon, temperature_floor_1,
313
+ mtov, epsilon, alpha, cos_theta, cos_theta_open, cos_theta_cocoon, temperature_floor_1,
313
314
  temperature_floor_2, temperature_floor_3, **kwargs):
314
315
  """
315
316
  Kilonova model from Nicholl et al. 2021, inclides three kilonova components
@@ -327,6 +328,7 @@ def nicholl_bns(time, redshift, mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
327
328
  :param alpha: Enhancement of blue ejecta by NS surface winds if mtotal < prompt collapse,
328
329
  can turn off by setting alpha=1
329
330
  :param cos_theta: Viewing angle of observer
331
+ :param cos_theta_open: Lanthanide opening angle
330
332
  :param cos_theta_cocoon: Opening angle of shocked cocoon
331
333
  :param temperature_floor_1: Temperature floor of first (blue) component
332
334
  :param temperature_floor_2: Temperature floor of second (purple) component
@@ -351,11 +353,12 @@ def nicholl_bns(time, redshift, mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
351
353
  cosmology = kwargs.get('cosmology', cosmo)
352
354
  dl = cosmology.luminosity_distance(redshift).cgs.value
353
355
  dense_resolution = kwargs.get('dense_resolution', 100)
354
- time_temp = np.geomspace(0.1, 30, dense_resolution) # in source frame and days
356
+ time_temp = np.geomspace(0.01, 30, dense_resolution) # in source frame and days
355
357
  kappa_gamma = kwargs.get('kappa_gamma', 10)
358
+ ckm = 3e10/1e5
356
359
 
357
360
  if np.max(time) > 20: # in source frame and days
358
- time_temp = np.geomspace(0.1, np.max(time) + 5, dense_resolution)
361
+ time_temp = np.geomspace(0.01, np.max(time) + 5, dense_resolution)
359
362
 
360
363
  time_obs = time
361
364
  shocked_fraction = kwargs.get('shocked_fraction', 0.2)
@@ -364,14 +367,14 @@ def nicholl_bns(time, redshift, mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
364
367
 
365
368
  output = _nicholl_bns_get_quantities(mass_1=mass_1, mass_2=mass_2, lambda_s=lambda_s,
366
369
  kappa_red=kappa_red, kappa_blue=kappa_blue, mtov=mtov,
367
- epsilon=epsilon, alpha=alpha, cos_theta_cocoon=cos_theta_cocoon,
370
+ epsilon=epsilon, alpha=alpha, cos_theta_open=cos_theta_open,
368
371
  cos_theta=cos_theta, **kwargs)
369
372
  cocoon_output = _shocked_cocoon_nicholl(time=time_temp, kappa=kappa_blue, mejecta=output.mejecta_blue,
370
373
  vejecta=output.vejecta_blue, cos_theta_cocoon=cos_theta_cocoon,
371
374
  shocked_fraction=shocked_fraction, nn=nn, tshock=tshock)
372
375
  cocoon_photo = CocoonPhotosphere(time=time_temp, luminosity=cocoon_output.lbol,
373
376
  tau_diff=cocoon_output.taudiff, t_thin=cocoon_output.tthin,
374
- vej=output.vejecta_blue, nn=nn)
377
+ vej=output.vejecta_blue*ckm, nn=nn)
375
378
  mejs = [output.mejecta_blue, output.mejecta_purple, output.mejecta_red]
376
379
  vejs = [output.vejecta_blue, output.vejecta_purple, output.vejecta_red]
377
380
  area_projs = [output.area_blue, output.area_blue, output.area_red]
@@ -386,26 +389,29 @@ def nicholl_bns(time, redshift, mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
386
389
  rad_func = interp1d(time_temp, y=cocoon_photo.r_photosphere)
387
390
  # convert to source frame time and frequency
388
391
  frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
389
- temp = temp_func(time_obs)
390
- photosphere = rad_func(time_obs)
392
+ temp = temp_func(time)
393
+ photosphere = rad_func(time)
391
394
  flux_density = blackbody_to_flux_density(temperature=temp, r_photosphere=photosphere,
392
395
  dl=dl, frequency=frequency)
393
396
  ff = flux_density.value
397
+ ff = np.nan_to_num(ff)
394
398
  for x in range(3):
395
399
  lbols = _mosfit_kilonova_one_component_lbol(time=time_temp*day_to_s, mej=mejs[x], vej=vejs[x])
396
- interaction_class = AsphericalDiffusion(time=time_temp*day_to_s, dense_times=time_temp*day_to_s,
400
+ interaction_class = AsphericalDiffusion(time=time_temp, dense_times=time_temp,
397
401
  luminosity=lbols, kappa=kappas[x], kappa_gamma=kappa_gamma,
398
- mej=mejs[x], vej=vejs[x], area_projection=area_projs[x],
402
+ mej=mejs[x], vej=vejs[x]*ckm, area_projection=area_projs[x],
399
403
  area_reference=area_refs[x])
400
404
  lbols = interaction_class.new_luminosity
401
- photo = TemperatureFloor(time=time_temp*day_to_s, luminosity=lbols,
402
- temperature_floor=temperature_floors[x], vej=vejs[x])
405
+ lbols = np.nan_to_num(lbols)
406
+ photo = TemperatureFloor(time=time_temp, luminosity=lbols,
407
+ temperature_floor=temperature_floors[x], vej=vejs[x]*ckm)
403
408
  temp_func = interp1d(time_temp, y=photo.photosphere_temperature)
404
409
  rad_func = interp1d(time_temp, y=photo.r_photosphere)
405
410
  temp = temp_func(time)
406
411
  photosphere = rad_func(time)
407
412
  flux_density = blackbody_to_flux_density(temperature=temp, r_photosphere=photosphere,
408
413
  dl=dl, frequency=frequency)
414
+ flux_density = np.nan_to_num(flux_density)
409
415
  units = flux_density.unit
410
416
  ff += flux_density.value
411
417
  ff = ff * units
@@ -420,22 +426,24 @@ def nicholl_bns(time, redshift, mass_1, mass_2, lambda_s, kappa_red, kappa_blue,
420
426
  frequency=frequency[:,None]).T
421
427
  cocoon_spectra = fmjy.to(uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
422
428
  equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
429
+ cocoon_spectra = np.nan_to_num(cocoon_spectra)
423
430
  full_spec = cocoon_spectra.value
424
431
  for x in range(3):
425
432
  lbols = _mosfit_kilonova_one_component_lbol(time=time_temp*day_to_s, mej=mejs[x], vej=vejs[x])
426
- interaction_class = AsphericalDiffusion(time=time_temp*day_to_s, dense_times=time_temp*day_to_s,
433
+ interaction_class = AsphericalDiffusion(time=time_temp, dense_times=time_temp,
427
434
  luminosity=lbols, kappa=kappas[x], kappa_gamma=kappa_gamma,
428
- mej=mejs[x], vej=vejs[x], area_projection=area_projs[x],
435
+ mej=mejs[x], vej=vejs[x]*ckm, area_projection=area_projs[x],
429
436
  area_reference=area_refs[x])
430
437
  lbols = interaction_class.new_luminosity
431
- photo = TemperatureFloor(time=time_temp*day_to_s, luminosity=lbols,
432
- temperature_floor=temperature_floors[x], vej=vejs[x])
438
+ photo = TemperatureFloor(time=time_temp, luminosity=lbols,
439
+ temperature_floor=temperature_floors[x], vej=vejs[x]*ckm)
433
440
  fmjy = blackbody_to_flux_density(temperature=photo.photosphere_temperature,
434
441
  r_photosphere=photo.r_photosphere, dl=dl,
435
442
  frequency=frequency[:, None])
436
443
  fmjy = fmjy.T
437
444
  spectra = fmjy.to(uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
438
445
  equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
446
+ spectra = np.nan_to_num(spectra)
439
447
  units = spectra.unit
440
448
  full_spec += spectra.value
441
449
 
@@ -459,7 +467,7 @@ def mosfit_rprocess(time, redshift, mej, vej, kappa, kappa_gamma, temperature_fl
459
467
  :param time: observer frame time in days
460
468
  :param redshift: redshift
461
469
  :param mej: ejecta mass in solar masses of first component
462
- :param vej: minimum initial velocity of first component
470
+ :param vej: minimum initial velocity of first component in units of c
463
471
  :param kappa: gray opacity of first component
464
472
  :param temperature_floor: floor temperature of first component
465
473
  :param kappa_gamma: gamma-ray opacity
@@ -473,25 +481,26 @@ def mosfit_rprocess(time, redshift, mej, vej, kappa, kappa_gamma, temperature_fl
473
481
  :param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
474
482
  :return: set by output format - 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
475
483
  """
484
+ ckm = 3e10/1e5
476
485
  cosmology = kwargs.get('cosmology', cosmo)
477
486
  dl = cosmology.luminosity_distance(redshift).cgs.value
478
487
  dense_resolution = kwargs.get('dense_resolution', 300)
479
- time_temp = np.geomspace(1e-2, 5e6, dense_resolution) # in source frame
488
+ time_temp = np.geomspace(1e-2, 7e6, dense_resolution) # in source frame in seconds
480
489
  time_obs = time
481
490
  lbols = _mosfit_kilonova_one_component_lbol(time=time_temp,
482
491
  mej=mej, vej=vej)
483
- interaction_class = Diffusion(time=time_temp, dense_times=time_temp, luminosity=lbols,
484
- kappa=kappa, kappa_gamma=kappa_gamma, mej=mej, vej=vej)
492
+ interaction_class = Diffusion(time=time_temp / day_to_s, dense_times=time_temp / day_to_s, luminosity=lbols,
493
+ kappa=kappa, kappa_gamma=kappa_gamma, mej=mej, vej=vej*ckm)
485
494
  lbols = interaction_class.new_luminosity
486
- photo = TemperatureFloor(time=time_temp, luminosity=lbols, vej=vej,
495
+ photo = TemperatureFloor(time=time_temp / day_to_s, luminosity=lbols, vej=vej*ckm,
487
496
  temperature_floor=temperature_floor)
488
497
 
489
498
  if kwargs['output_format'] == 'flux_density':
490
- time = time_obs * day_to_s
499
+ #time = time_obs * day_to_s
491
500
  frequency = kwargs['frequency']
492
501
  # interpolate properties onto observation times
493
- temp_func = interp1d(time_temp, y=photo.photosphere_temperature)
494
- rad_func = interp1d(time_temp, y=photo.r_photosphere)
502
+ temp_func = interp1d(time_temp / day_to_s, y=photo.photosphere_temperature)
503
+ rad_func = interp1d(time_temp / day_to_s, y=photo.r_photosphere)
495
504
  # convert to source frame time and frequency
496
505
  frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
497
506
  temp = temp_func(time)
@@ -501,7 +510,7 @@ def mosfit_rprocess(time, redshift, mej, vej, kappa, kappa_gamma, temperature_fl
501
510
  return flux_density.to(uu.mJy).value
502
511
  else:
503
512
  lambda_observer_frame = kwargs.get('lambda_array', np.geomspace(100, 60000, 200))
504
- time_observer_frame = time_temp * (1. + redshift)
513
+ time_observer_frame = time_temp / day_to_s * (1. + redshift) # in days
505
514
  frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
506
515
  redshift=redshift, time=time_observer_frame)
507
516
  fmjy = blackbody_to_flux_density(temperature=photo.photosphere_temperature,
@@ -514,7 +523,7 @@ def mosfit_rprocess(time, redshift, mej, vej, kappa, kappa_gamma, temperature_fl
514
523
  lambdas=lambda_observer_frame,
515
524
  spectra=spectra)
516
525
  else:
517
- return get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame / day_to_s,
526
+ return get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame,
518
527
  spectra=spectra, lambda_array=lambda_observer_frame,
519
528
  **kwargs)
520
529
 
@@ -530,15 +539,15 @@ def mosfit_kilonova(time, redshift, mej_1, vej_1, temperature_floor_1, kappa_1,
530
539
  :param time: observer frame time in days
531
540
  :param redshift: redshift
532
541
  :param mej_1: ejecta mass in solar masses of first component
533
- :param vej_1: minimum initial velocity of first component
542
+ :param vej_1: minimum initial velocity of first component in units of c
534
543
  :param kappa_1: gray opacity of first component
535
544
  :param temperature_floor_1: floor temperature of first component
536
545
  :param mej_2: ejecta mass in solar masses of second component
537
- :param vej_2: minimum initial velocity of second component
546
+ :param vej_2: minimum initial velocity of second component in units of c
538
547
  :param temperature_floor_2: floor temperature of second component
539
548
  :param kappa_2: gray opacity of second component
540
549
  :param mej_3: ejecta mass in solar masses of third component
541
- :param vej_3: minimum initial velocity of third component
550
+ :param vej_3: minimum initial velocity of third component in units of c
542
551
  :param temperature_floor_3: floor temperature of third component
543
552
  :param kappa_3: gray opacity of third component
544
553
  :param kappa_gamma: gamma-ray opacity
@@ -552,17 +561,18 @@ def mosfit_kilonova(time, redshift, mej_1, vej_1, temperature_floor_1, kappa_1,
552
561
  :param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
553
562
  :return: set by output format - 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
554
563
  """
564
+ ckm = 3e10/1e5
555
565
  cosmology = kwargs.get('cosmology', cosmo)
556
566
  dl = cosmology.luminosity_distance(redshift).cgs.value
557
567
  dense_resolution = kwargs.get('dense_resolution', 300)
558
- time_temp = np.geomspace(1e-2, 5e6, dense_resolution) # in source frame
568
+ time_temp = np.geomspace(1e-2, 7e6, dense_resolution) # in source frame in s
559
569
  time_obs = time
560
570
  mej = [mej_1, mej_2, mej_3]
561
571
  vej = [vej_1, vej_2, vej_3]
562
572
  temperature_floor = [temperature_floor_1, temperature_floor_2, temperature_floor_3]
563
573
  kappa = [kappa_1, kappa_2, kappa_3]
564
574
  if kwargs['output_format'] == 'flux_density':
565
- time = time_obs * day_to_s
575
+ #time = time_obs * day_to_s
566
576
  frequency = kwargs['frequency']
567
577
  frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
568
578
 
@@ -570,13 +580,13 @@ def mosfit_kilonova(time, redshift, mej_1, vej_1, temperature_floor_1, kappa_1,
570
580
  for x in range(3):
571
581
  lbols = _mosfit_kilonova_one_component_lbol(time=time_temp,
572
582
  mej=mej[x], vej=vej[x])
573
- interaction_class = Diffusion(time=time_temp, dense_times=time_temp, luminosity=lbols,
574
- kappa=kappa[x], kappa_gamma=kappa_gamma, mej=mej[x], vej=vej[x])
583
+ interaction_class = Diffusion(time=time_temp / day_to_s, dense_times=time_temp / day_to_s, luminosity=lbols,
584
+ kappa=kappa[x], kappa_gamma=kappa_gamma, mej=mej[x], vej=vej[x]*ckm)
575
585
  lbols = interaction_class.new_luminosity
576
- photo = TemperatureFloor(time=time_temp, luminosity=lbols, vej=vej[x],
586
+ photo = TemperatureFloor(time=time_temp / day_to_s, luminosity=lbols, vej=vej[x]*ckm,
577
587
  temperature_floor=temperature_floor[x])
578
- temp_func = interp1d(time_temp, y=photo.photosphere_temperature)
579
- rad_func = interp1d(time_temp, y=photo.r_photosphere)
588
+ temp_func = interp1d(time_temp / day_to_s, y=photo.photosphere_temperature)
589
+ rad_func = interp1d(time_temp / day_to_s, y=photo.r_photosphere)
580
590
  # convert to source frame time and frequency
581
591
  temp = temp_func(time)
582
592
  photosphere = rad_func(time)
@@ -588,17 +598,17 @@ def mosfit_kilonova(time, redshift, mej_1, vej_1, temperature_floor_1, kappa_1,
588
598
  return ff.to(uu.mJy).value
589
599
  else:
590
600
  lambda_observer_frame = kwargs.get('lambda_array', np.geomspace(100, 60000, 200))
591
- time_observer_frame = time_temp * (1. + redshift)
601
+ time_observer_frame = time_temp / day_to_s * (1. + redshift) # in days
592
602
  frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
593
603
  redshift=redshift, time=time_observer_frame)
594
604
  full_spec = np.zeros((len(time), len(frequency)))
595
605
  for x in range(3):
596
606
  lbols = _mosfit_kilonova_one_component_lbol(time=time_temp,
597
607
  mej=mej[x], vej=vej[x])
598
- interaction_class = Diffusion(time=time_temp, dense_times=time_temp, luminosity=lbols,
599
- kappa=kappa[x], kappa_gamma=kappa_gamma, mej=mej[x], vej=vej[x])
608
+ interaction_class = Diffusion(time=time_temp / day_to_s, dense_times=time_temp / day_to_s, luminosity=lbols,
609
+ kappa=kappa[x], kappa_gamma=kappa_gamma, mej=mej[x], vej=vej[x]*ckm)
600
610
  lbols = interaction_class.new_luminosity
601
- photo = TemperatureFloor(time=time_temp, luminosity=lbols, vej=vej[x],
611
+ photo = TemperatureFloor(time=time_temp / day_to_s, luminosity=lbols, vej=vej[x]*ckm,
602
612
  temperature_floor=temperature_floor[x])
603
613
  fmjy = blackbody_to_flux_density(temperature=photo.photosphere_temperature,
604
614
  r_photosphere=photo.r_photosphere, frequency=frequency[:, None], dl=dl).T
@@ -613,7 +623,7 @@ def mosfit_kilonova(time, redshift, mej_1, vej_1, temperature_floor_1, kappa_1,
613
623
  lambdas=lambda_observer_frame,
614
624
  spectra=full_spec)
615
625
  else:
616
- return get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame / day_to_s,
626
+ return get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame,
617
627
  spectra=full_spec, lambda_array=lambda_observer_frame,
618
628
  **kwargs)
619
629
 
@@ -817,7 +827,7 @@ def kasen_bns_kilonova(time, redshift, mej, vej, chi, **kwargs):
817
827
  fmjy = spectra.to(uu.mJy, equivalencies=uu.spectral_density(wav=output.lambdas * uu.Angstrom)).value
818
828
  nu_array = lambda_to_nu(output.lambdas)
819
829
  fmjy_func = RegularGridInterpolator((np.unique(time), nu_array), fmjy, bounds_error=False)
820
- if type(frequency) == float:
830
+ if type(frequency) == float or type(frequency) == np.float64:
821
831
  frequency = np.ones(len(time)) * frequency
822
832
  points = np.array([time, frequency]).T
823
833
  return fmjy_func(points)
@@ -890,6 +900,11 @@ def _kilonova_hr(time, redshift, mej, velocity_array, kappa_array, beta, **kwarg
890
900
  time = time * day_to_s
891
901
  # convert to source frame time and frequency
892
902
  frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
903
+ if (isinstance(frequency, (float, int)) == False):
904
+ radio_mask = frequency < 10e10
905
+ frequency[radio_mask]=10e50
906
+ elif frequency < 10e10:
907
+ frequency =10e50
893
908
 
894
909
  _, temperature, r_photosphere = _kilonova_hr_sourceframe(time, mej, velocity_array, kappa_array, beta)
895
910
 
@@ -974,7 +989,7 @@ def three_component_kilonova_model(time, redshift, mej_1, vej_1, temperature_flo
974
989
  """
975
990
  cosmology = kwargs.get('cosmology', cosmo)
976
991
  dl = cosmology.luminosity_distance(redshift).cgs.value
977
- time_temp = np.geomspace(1e-2, 5e6, 300) # in source frame
992
+ time_temp = np.geomspace(1e-2, 7e6, 300) # in source frame
978
993
  time_obs = time
979
994
 
980
995
  mej = [mej_1, mej_2, mej_3]
@@ -1063,7 +1078,7 @@ def two_component_kilonova_model(time, redshift, mej_1, vej_1, temperature_floor
1063
1078
  """
1064
1079
  cosmology = kwargs.get('cosmology', cosmo)
1065
1080
  dl = cosmology.luminosity_distance(redshift).cgs.value
1066
- time_temp = np.geomspace(1e-2, 5e6, 300) # in source frame
1081
+ time_temp = np.geomspace(1e-2, 7e6, 300) # in source frame
1067
1082
  time_obs = time
1068
1083
 
1069
1084
  mej = [mej_1, mej_2]
@@ -1376,7 +1391,7 @@ def one_component_kilonova_model(time, redshift, mej, vej, kappa, **kwargs):
1376
1391
  """
1377
1392
  cosmology = kwargs.get('cosmology', cosmo)
1378
1393
  dl = cosmology.luminosity_distance(redshift).cgs.value
1379
- time_temp = np.geomspace(1e-3, 5e6, 300) # in source frame
1394
+ time_temp = np.geomspace(1e-3, 7e6, 300) # in source frame
1380
1395
  time_obs = time
1381
1396
  _, temperature, r_photosphere = _one_component_kilonova_model(time_temp, mej, vej, kappa, **kwargs)
1382
1397
 
@@ -1416,6 +1431,240 @@ def one_component_kilonova_model(time, redshift, mej, vej, kappa, **kwargs):
1416
1431
  spectra=spectra, lambda_array=lambda_observer_frame,
1417
1432
  **kwargs)
1418
1433
 
1434
+
1435
+ def _calc_new_heating_rate(time, mej, electron_fraction, ejecta_velocity, **kwargs):
1436
+ """
1437
+ Heating rate prescription following Rosswog and Korobkin 2024
1438
+
1439
+ :param time: time in seconds
1440
+ :param mej: ejecta mass in solar masses
1441
+ :param electron_fraction: electron fraction
1442
+ :param ejecta_velocity: ejecta velocity in c
1443
+ :param kwargs: Additional keyword arguments
1444
+ :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.
1445
+ :param heating_rate_fudge: A fudge factor for each of the terms in the heating rate. Default to 1. i.e., no uncertainty
1446
+ Default is 1.0 i.e., no perturbation.
1447
+ :return: heating rate in erg/s
1448
+ """
1449
+ heating_rate_perturbation = kwargs.get('heating_rate_perturbation', 1.0)
1450
+ # rescale
1451
+ m0 = mej * solar_mass
1452
+ qdot_in = _calculate_rosswogkorobkin24_qdot(time, ejecta_velocity, electron_fraction)
1453
+ lum_in = qdot_in * m0
1454
+ return lum_in * heating_rate_perturbation
1455
+
1456
+ def _calculate_rosswogkorobkin24_qdot_formula(time_array, e0, alp, t0, sig, alp1,
1457
+ t1, sig1, c1, tau1, c2, tau2, c3, tau3):
1458
+ time = time_array
1459
+ c1 = np.exp(c1)
1460
+ c2 = np.exp(c2)
1461
+ c3 = np.exp(c3)
1462
+ tau1 = 1e3 * tau1
1463
+ tau2 = 1e5 * tau2
1464
+ tau3 = 1e5 * tau3
1465
+ term1 = 10. ** (e0 + 18) * (0.5 - np.arctan((time - t0) / sig) / np.pi) ** alp
1466
+ term2 = (0.5 + np.arctan((time - t1) / sig1) / np.pi) ** alp1
1467
+ term3 = c1 * np.exp(-time / tau1)
1468
+ term4 = c2 * np.exp(-time / tau2)
1469
+ term5 = c3 * np.exp(-time / tau3)
1470
+ lum_in = term1 * term2 + term3 + term4 + term5
1471
+ return lum_in
1472
+
1473
+ def _one_component_kilonova_rosswog_heatingrate(time, mej, vej, electron_fraction, **kwargs):
1474
+ tdays = time/day_to_s
1475
+ # set up kilonova physics
1476
+ av, bv, dv = interpolated_barnes_and_kasen_thermalisation_efficiency(mej, vej)
1477
+ # thermalisation from Barnes+16
1478
+ e_th = 0.36 * (np.exp(-av * tdays) + np.log1p(2.0 * bv * tdays ** dv) / (2.0 * bv * tdays ** dv))
1479
+ temperature_floor = kwargs.get('temperature_floor', 4000) # kelvin
1480
+ beta = 13.7
1481
+
1482
+ v0 = vej * speed_of_light
1483
+ m0 = mej * solar_mass
1484
+ kappa = kappa_from_electron_fraction(electron_fraction)
1485
+ tdiff = np.sqrt(2.0 * kappa * (m0) / (beta * v0 * speed_of_light))
1486
+
1487
+ lum_in = _calc_new_heating_rate(time, mej, electron_fraction, vej, **kwargs)
1488
+ integrand = lum_in * e_th * (time / tdiff) * np.exp(time ** 2 / tdiff ** 2)
1489
+
1490
+ bolometric_luminosity = np.zeros(len(time))
1491
+ bolometric_luminosity[1:] = cumulative_trapezoid(integrand, time)
1492
+ bolometric_luminosity[0] = bolometric_luminosity[1]
1493
+ bolometric_luminosity = bolometric_luminosity * np.exp(-time ** 2 / tdiff ** 2) / tdiff
1494
+
1495
+ temperature = (bolometric_luminosity / (4.0 * np.pi * sigma_sb * v0 ** 2 * time ** 2)) ** 0.25
1496
+ r_photosphere = (bolometric_luminosity / (4.0 * np.pi * sigma_sb * temperature_floor ** 4)) ** 0.5
1497
+
1498
+ # check temperature floor conditions
1499
+ mask = temperature <= temperature_floor
1500
+ temperature[mask] = temperature_floor
1501
+ mask = np.logical_not(mask)
1502
+ r_photosphere[mask] = v0 * time[mask]
1503
+ return bolometric_luminosity, temperature, r_photosphere
1504
+
1505
+ @citation_wrapper('https://ui.adsabs.harvard.edu/abs/2024arXiv240407271S/abstract, https://ui.adsabs.harvard.edu/abs/2024AnP...53600306R/abstract')
1506
+ def one_comp_kne_rosswog_heatingrate(time, redshift, mej, vej, ye, **kwargs):
1507
+ """
1508
+ :param time: observer frame time in days
1509
+ :param redshift: redshift
1510
+ :param mej: ejecta mass in solar masses
1511
+ :param vej: minimum initial velocity
1512
+ :param kappa: gray opacity
1513
+ :param kwargs: Additional keyword arguments
1514
+ :param temperature_floor: Temperature floor in K (default 4000)
1515
+ :param heating_rate_perturbation: A fudge factor for heating rate to account for uncertainties in the heating rate.
1516
+ Default is 1.0 i.e., no perturbation.
1517
+ :param heating_rate_fudge: A fudge factor for each of the terms in the heating rate. Default to 1. i.e., no uncertainty
1518
+ :param frequency: Required if output_format is 'flux_density'.
1519
+ frequency to calculate - Must be same length as time array or a single number).
1520
+ :param bands: Required if output_format is 'magnitude' or 'flux'.
1521
+ :param output_format: 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
1522
+ :param lambda_array: Optional argument to set your desired wavelength array (in Angstroms) to evaluate the SED on.
1523
+ :param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
1524
+ :return: set by output format - 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
1525
+ """
1526
+ cosmology = kwargs.get('cosmology', cosmo)
1527
+ dl = cosmology.luminosity_distance(redshift).cgs.value
1528
+ time_temp = np.geomspace(1e-3, 7e6, 300) # in source frame
1529
+ time_obs = time
1530
+ _, temperature, r_photosphere = _one_component_kilonova_rosswog_heatingrate(time_temp, mej, vej, ye, **kwargs)
1531
+
1532
+ if kwargs['output_format'] == 'flux_density':
1533
+ time = time_obs * day_to_s
1534
+ frequency = kwargs['frequency']
1535
+ # interpolate properties onto observation times
1536
+ temp_func = interp1d(time_temp, y=temperature)
1537
+ rad_func = interp1d(time_temp, y=r_photosphere)
1538
+ # convert to source frame time and frequency
1539
+ frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
1540
+
1541
+ temp = temp_func(time)
1542
+ photosphere = rad_func(time)
1543
+
1544
+ flux_density = blackbody_to_flux_density(temperature=temp, r_photosphere=photosphere,
1545
+ dl=dl, frequency=frequency)
1546
+
1547
+ return flux_density.to(uu.mJy).value
1548
+
1549
+ else:
1550
+ lambda_observer_frame = kwargs.get('lambda_array', np.geomspace(100, 60000, 200))
1551
+ time_observer_frame = time_temp * (1. + redshift)
1552
+ frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
1553
+ redshift=redshift, time=time_observer_frame)
1554
+ fmjy = blackbody_to_flux_density(temperature=temperature,
1555
+ r_photosphere=r_photosphere, frequency=frequency[:, None], dl=dl)
1556
+ fmjy = fmjy.T
1557
+ spectra = fmjy.to(uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
1558
+ equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
1559
+ if kwargs['output_format'] == 'spectra':
1560
+ return namedtuple('output', ['time', 'lambdas', 'spectra'])(time=time_observer_frame,
1561
+ lambdas=lambda_observer_frame,
1562
+ spectra=spectra)
1563
+ else:
1564
+ return get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame/day_to_s,
1565
+ spectra=spectra, lambda_array=lambda_observer_frame,
1566
+ **kwargs)
1567
+
1568
+ @citation_wrapper('https://ui.adsabs.harvard.edu/abs/2024arXiv240407271S/abstract, https://ui.adsabs.harvard.edu/abs/2024AnP...53600306R/abstract')
1569
+ def two_comp_kne_rosswog_heatingrate(time, redshift, mej_1, vej_1, temperature_floor_1, ye_1,
1570
+ mej_2, vej_2, temperature_floor_2, ye_2, **kwargs):
1571
+ """
1572
+ :param time: observer frame time in days
1573
+ :param redshift: redshift
1574
+ :param mej_1: ejecta mass in solar masses of first component
1575
+ :param vej_1: minimum initial velocity of first component
1576
+ :param kappa_1: gray opacity of first component
1577
+ :param temperature_floor_1: floor temperature of first component
1578
+ :param mej_2: ejecta mass in solar masses of second component
1579
+ :param vej_2: minimum initial velocity of second component
1580
+ :param temperature_floor_2: floor temperature of second component
1581
+ :param kappa_2: gray opacity of second component
1582
+ :param kwargs: Additional keyword arguments
1583
+ :param heating_rate_perturbation: A fudge factor for heating rate to account for uncertainties in the heating rate.
1584
+ Default is 1.0 i.e., no perturbation.
1585
+ :param heating_rate_fudge: A fudge factor for each of the terms in the heating rate. Default to 1. i.e., no uncertainty
1586
+ :param frequency: Required if output_format is 'flux_density'.
1587
+ frequency to calculate - Must be same length as time array or a single number).
1588
+ :param bands: Required if output_format is 'magnitude' or 'flux'.
1589
+ :param output_format: 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
1590
+ :param lambda_array: Optional argument to set your desired wavelength array (in Angstroms) to evaluate the SED on.
1591
+ :param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
1592
+ :return: set by output format - 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
1593
+ """
1594
+ cosmology = kwargs.get('cosmology', cosmo)
1595
+ dl = cosmology.luminosity_distance(redshift).cgs.value
1596
+ time_temp = np.geomspace(1e-2, 7e6, 300) # in source frame
1597
+ time_obs = time
1598
+
1599
+ mej = [mej_1, mej_2]
1600
+ vej = [vej_1, vej_2]
1601
+ temperature_floor = [temperature_floor_1, temperature_floor_2]
1602
+ ye = [ye_1, ye_2]
1603
+
1604
+ if kwargs['output_format'] == 'flux_density':
1605
+ time = time * day_to_s
1606
+ frequency = kwargs['frequency']
1607
+
1608
+ # convert to source frame time and frequency
1609
+ frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
1610
+
1611
+ ff = np.zeros(len(time))
1612
+ for x in range(2):
1613
+ temp_kwargs = {}
1614
+ if 'heating_rate_fudge' in kwargs:
1615
+ temp_kwargs['heating_rate_fudge'] = kwargs['heating_rate_fudge']
1616
+ if 'heating_rate_perturbation' in kwargs:
1617
+ temp_kwargs['heating_rate_perturbation'] = kwargs['heating_rate_perturbation']
1618
+ temp_kwargs['temperature_floor'] = temperature_floor[x]
1619
+ _, temperature, r_photosphere = _one_component_kilonova_rosswog_heatingrate(time_temp, mej[x], vej[x], ye[x],
1620
+ **temp_kwargs)
1621
+ # interpolate properties onto observation times
1622
+ temp_func = interp1d(time_temp, y=temperature)
1623
+ rad_func = interp1d(time_temp, y=r_photosphere)
1624
+ temp = temp_func(time)
1625
+ photosphere = rad_func(time)
1626
+ flux_density = blackbody_to_flux_density(temperature=temp, r_photosphere=photosphere,
1627
+ dl=dl, frequency=frequency)
1628
+ units = flux_density.unit
1629
+ ff += flux_density.value
1630
+
1631
+ ff = ff * units
1632
+ return ff.to(uu.mJy).value
1633
+
1634
+ else:
1635
+ lambda_observer_frame = kwargs.get('lambda_array', np.geomspace(100, 60000, 200))
1636
+ time_observer_frame = time_temp * (1. + redshift)
1637
+ frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
1638
+ redshift=redshift, time=time_observer_frame)
1639
+ full_spec = np.zeros((len(time), len(frequency)))
1640
+
1641
+ for x in range(2):
1642
+ temp_kwargs = {}
1643
+ if 'heating_rate_fudge' in kwargs:
1644
+ temp_kwargs['heating_rate_fudge'] = kwargs['heating_rate_fudge']
1645
+ if 'heating_rate_perturbation' in kwargs:
1646
+ temp_kwargs['heating_rate_perturbation'] = kwargs['heating_rate_perturbation']
1647
+ temp_kwargs['temperature_floor'] = temperature_floor[x]
1648
+ _, temperature, r_photosphere = _one_component_kilonova_rosswog_heatingrate(time_temp, mej[x], vej[x], ye[x],
1649
+ **temp_kwargs)
1650
+ fmjy = blackbody_to_flux_density(temperature=temperature,
1651
+ r_photosphere=r_photosphere, frequency=frequency[:, None], dl=dl)
1652
+ fmjy = fmjy.T
1653
+ spectra = fmjy.to(uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
1654
+ equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
1655
+ units = spectra.unit
1656
+ full_spec += spectra.value
1657
+
1658
+ full_spec = full_spec * units
1659
+ if kwargs['output_format'] == 'spectra':
1660
+ return namedtuple('output', ['time', 'lambdas', 'spectra'])(time=time_observer_frame,
1661
+ lambdas=lambda_observer_frame,
1662
+ spectra=full_spec)
1663
+ else:
1664
+ return get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame/day_to_s,
1665
+ spectra=full_spec, lambda_array=lambda_observer_frame,
1666
+ **kwargs)
1667
+
1419
1668
  def _one_component_kilonova_model(time, mej, vej, kappa, **kwargs):
1420
1669
  """
1421
1670
  :param time: source frame time in seconds
@@ -1444,7 +1693,7 @@ def _one_component_kilonova_model(time, mej, vej, kappa, **kwargs):
1444
1693
  lum_in = 4.0e18 * (m0) * (0.5 - np.arctan((time - t0) / sig) / np.pi)**1.3
1445
1694
  integrand = lum_in * e_th * (time/tdiff) * np.exp(time**2/tdiff**2)
1446
1695
  bolometric_luminosity = np.zeros(len(time))
1447
- bolometric_luminosity[1:] = cumtrapz(integrand, time)
1696
+ bolometric_luminosity[1:] = cumulative_trapezoid(integrand, time)
1448
1697
  bolometric_luminosity[0] = bolometric_luminosity[1]
1449
1698
  bolometric_luminosity = bolometric_luminosity * np.exp(-time**2/tdiff**2) / tdiff
1450
1699
 
@@ -1479,7 +1728,7 @@ def metzger_kilonova_model(time, redshift, mej, vej, beta, kappa, **kwargs):
1479
1728
  """
1480
1729
  cosmology = kwargs.get('cosmology', cosmo)
1481
1730
  dl = cosmology.luminosity_distance(redshift).cgs.value
1482
- time_temp = np.geomspace(1e-4, 1e7, 300) # in source frame
1731
+ time_temp = np.geomspace(1e-4, 7e6, 300) # in source frame
1483
1732
  time_obs = time
1484
1733
  bolometric_luminosity, temperature, r_photosphere = _metzger_kilonova_model(time_temp, mej, vej, beta,
1485
1734
  kappa, **kwargs)