redback 1.0.3__py3-none-any.whl → 1.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.
Files changed (48) hide show
  1. redback/__init__.py +3 -2
  2. redback/analysis.py +321 -4
  3. redback/filters.py +57 -23
  4. redback/get_data/directory.py +18 -0
  5. redback/likelihoods.py +260 -0
  6. redback/model_library.py +12 -2
  7. redback/plotting.py +335 -4
  8. redback/priors/blackbody_spectrum_with_absorption_and_emission_lines.prior +9 -0
  9. redback/priors/csm_shock_and_arnett_two_rphots.prior +11 -0
  10. redback/priors/exp_rise_powerlaw_decline.prior +6 -0
  11. redback/priors/powerlaw_spectrum_with_absorption_and_emission_lines.prior +8 -0
  12. redback/priors/shockcooling_morag.prior +6 -0
  13. redback/priors/shockcooling_morag_and_arnett.prior +10 -0
  14. redback/priors/shockcooling_morag_and_arnett_bolometric.prior +9 -0
  15. redback/priors/shockcooling_morag_bolometric.prior +5 -0
  16. redback/priors/shockcooling_sapirandwaxman.prior +6 -0
  17. redback/priors/shockcooling_sapirandwaxman_bolometric.prior +5 -0
  18. redback/priors/shockcooling_sapirwaxman_and_arnett.prior +10 -0
  19. redback/priors/shockcooling_sapirwaxman_and_arnett_bolometric.prior +9 -0
  20. redback/priors/shocked_cocoon_and_arnett.prior +13 -0
  21. redback/priors/synchrotron_ism.prior +6 -0
  22. redback/priors/synchrotron_massloss.prior +6 -0
  23. redback/priors/synchrotron_pldensity.prior +7 -0
  24. redback/priors/thermal_synchrotron_v2_fluxdensity.prior +8 -0
  25. redback/priors/thermal_synchrotron_v2_lnu.prior +7 -0
  26. redback/priors.py +10 -3
  27. redback/result.py +9 -1
  28. redback/sampler.py +46 -4
  29. redback/sed.py +48 -1
  30. redback/simulate_transients.py +5 -1
  31. redback/tables/filters.csv +265 -254
  32. redback/transient/__init__.py +2 -3
  33. redback/transient/transient.py +648 -10
  34. redback/transient_models/__init__.py +3 -2
  35. redback/transient_models/extinction_models.py +3 -2
  36. redback/transient_models/gaussianprocess_models.py +45 -0
  37. redback/transient_models/general_synchrotron_models.py +296 -6
  38. redback/transient_models/phenomenological_models.py +154 -7
  39. redback/transient_models/shock_powered_models.py +503 -40
  40. redback/transient_models/spectral_models.py +82 -0
  41. redback/transient_models/supernova_models.py +333 -7
  42. redback/transient_models/tde_models.py +57 -41
  43. redback/utils.py +302 -51
  44. {redback-1.0.3.dist-info → redback-1.1.dist-info}/METADATA +8 -6
  45. {redback-1.0.3.dist-info → redback-1.1.dist-info}/RECORD +48 -29
  46. {redback-1.0.3.dist-info → redback-1.1.dist-info}/WHEEL +1 -1
  47. {redback-1.0.3.dist-info → redback-1.1.dist-info/licenses}/LICENCE.md +0 -0
  48. {redback-1.0.3.dist-info → redback-1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,82 @@
1
+ import numpy
2
+ from astropy.cosmology import Planck18 as cosmo
3
+ import redback.constants as cc
4
+ from redback.utils import lambda_to_nu, fnu_to_flambda
5
+ import redback.sed as sed
6
+ import redback.transient_models.phenomenological_models as pm
7
+
8
+ def _get_blackbody_spectrum(angstrom, temperature, r_photosphere, distance):
9
+ """
10
+ :param angstrom: wavelength array in angstroms
11
+ :param temperature: temperature in Kelvin
12
+ :param r_photosphere: photosphere radius in cm
13
+ :param distance: distance in cm
14
+ :return: flux in ergs/s/cm^2/angstrom
15
+ """
16
+ frequency = lambda_to_nu(angstrom)
17
+ flux_density = sed.blackbody_to_flux_density(frequency=frequency,
18
+ temperature=temperature,
19
+ r_photosphere=r_photosphere,
20
+ dl=distance)
21
+ flux_density = fnu_to_flambda(f_nu=flux_density, wavelength_A=angstrom)
22
+ return flux_density.value
23
+
24
+ def _get_powerlaw_spectrum(angstrom, alpha, aa):
25
+ """
26
+ :param angstrom: wavelength array in angstroms
27
+ :param alpha: power law index
28
+ :param aa: normalization
29
+ :return: flux in ergs/s/cm^2/angstrom
30
+ """
31
+ return aa*angstrom**alpha
32
+
33
+ def powerlaw_spectrum_with_absorption_and_emission_lines(angstroms, alpha, aa, lc1, ls1,
34
+ v1, lc2, ls2, v2, **kwargs):
35
+ """
36
+ A power law spectrum with one absorption line and one emission line.
37
+ One can add more lines if needed. Or turn the line strength to zero to remove the line.
38
+
39
+ :param angstroms: wavelength array in angstroms
40
+ :param alpha: power law index
41
+ :param aa: normalization
42
+ :param lc1: center of emission line
43
+ :param ls1: strength of emission line
44
+ :param v1: velocity of emission line
45
+ :param lc2: center of absorption line
46
+ :param ls2: strength of absorption line
47
+ :param v2: velocity of absorption line
48
+ :return: flux in ergs/s/cm^2/angstrom
49
+ """
50
+ flux = _get_powerlaw_spectrum(angstrom=angstroms, alpha=alpha, aa=aa)
51
+ fp1 = pm.line_spectrum_with_velocity_dispersion(angstroms, lc1, ls1, v1)
52
+ fp2 = pm.line_spectrum_with_velocity_dispersion(angstroms, lc2, ls2, v2)
53
+ return flux + fp1 - fp2
54
+
55
+
56
+ def blackbody_spectrum_with_absorption_and_emission_lines(angstroms, redshift,
57
+ rph, temp,
58
+ lc1, ls1, v1,
59
+ lc2, ls2, v2, **kwargs):
60
+ """
61
+ A blackbody spectrum with one absorption line and one emission line.
62
+ One can add more lines if needed. Or turn the line strength to zero to remove the line.
63
+
64
+ :param angstroms: wavelength array in angstroms
65
+ :param redshift: redshift
66
+ :param rph: photosphere radius in cm
67
+ :param temp: photosphere temperature in Kelvin
68
+ :param lc1: center of emission line
69
+ :param ls1: strength of emission line
70
+ :param v1: velocity of emission line
71
+ :param lc2: center of absorption line
72
+ :param ls2: strength of absorption line
73
+ :param v2: velocity of absorption line
74
+ :return: flux in ergs/s/cm^2/angstrom
75
+ """
76
+ cosmology = kwargs.get('cosmology', cosmo)
77
+ dl = cosmology.luminosity_distance(redshift).cgs.value
78
+ flux = _get_blackbody_spectrum(angstrom=angstroms, distance=dl,
79
+ r_photosphere=rph, temperature=temp)
80
+ fp1 = pm.line_spectrum_with_velocity_dispersion(angstroms, lc1, ls1, v1)
81
+ fp2 = pm.line_spectrum_with_velocity_dispersion(angstroms, lc2, ls2, v2)
82
+ return flux + fp1 - fp2
@@ -3,7 +3,7 @@ import pandas as pd
3
3
  from redback.transient_models.phenomenological_models import exponential_powerlaw, fallback_lbol
4
4
  from redback.transient_models.magnetar_models import magnetar_only, basic_magnetar
5
5
  from redback.transient_models.magnetar_driven_ejecta_models import _ejecta_dynamics_and_interaction
6
- from redback.transient_models.shock_powered_models import _shock_cooling
6
+ from redback.transient_models.shock_powered_models import _shock_cooling, _shocked_cocoon, _csm_shock_breakout
7
7
  import redback.interaction_processes as ip
8
8
  import redback.sed as sed
9
9
  import redback.photosphere as photosphere
@@ -363,7 +363,7 @@ def arnett(time, redshift, f_nickel, mej, **kwargs):
363
363
  spectra=spectra, lambda_array=lambda_observer_frame,
364
364
  **kwargs)
365
365
 
366
- @citation_wrapper('https://ui.adsabs.harvard.edu/abs/1982ApJ...253..785A/abstract')
366
+ @citation_wrapper('https://ui.adsabs.harvard.edu/abs/1982ApJ...253..785A/abstract, Piro+2021')
367
367
  def shock_cooling_and_arnett(time, redshift, log10_mass, log10_radius, log10_energy,
368
368
  f_nickel, mej, **kwargs):
369
369
  """
@@ -409,10 +409,11 @@ def shock_cooling_and_arnett(time, redshift, log10_mass, log10_radius, log10_ene
409
409
  lbol = lbol_1 + lbol_2
410
410
 
411
411
  if kwargs['interaction_process'] is not None:
412
- dense_resolution = kwargs.get("dense_resolution", 1000)
413
- dense_times = np.linspace(0, time[-1]+100, dense_resolution)
412
+ dense_resolution = kwargs.get("dense_resolution", 300)
413
+ dense_times = np.linspace(0.01, time[-1]+100, dense_resolution)
414
414
  dense_lbols = _nickelcobalt_engine(time=dense_times, f_nickel=f_nickel, mej=mej)
415
- dense_lbols += _shock_cooling(dense_times * day_to_s, mass=mass, radius=radius, energy=energy, **kwargs).lbol
415
+ shock_cooling = _shock_cooling(dense_times * day_to_s, mass=mass, radius=radius, energy=energy, **kwargs).lbol
416
+ dense_lbols += shock_cooling
416
417
  interaction_class = kwargs['interaction_process'](time=time, dense_times=dense_times, luminosity=dense_lbols,
417
418
  mej=mej, **kwargs)
418
419
  lbol = interaction_class.new_luminosity
@@ -447,6 +448,181 @@ def shock_cooling_and_arnett(time, redshift, log10_mass, log10_radius, log10_ene
447
448
  spectra=spectra, lambda_array=lambda_observer_frame,
448
449
  **kwargs)
449
450
 
451
+ @citation_wrapper('https://academic.oup.com/mnras/article/522/2/2764/7086123#443111844, https://ui.adsabs.harvard.edu/abs/1982ApJ...253..785A/abstract')
452
+ def shockcooling_morag_and_arnett_bolometric(time, v_shock, m_env, mej, f_rho, f_nickel, radius, kappa, **kwargs):
453
+ """
454
+ Assumes Shock cooling following Morag+ and arnett model for radioactive decay
455
+
456
+ :param time: time in source frame in days
457
+ :param v_shock: shock speed in km/s, also the ejecta velocity in the arnett calculation
458
+ :param m_env: envelope mass in solar masses
459
+ :param mej: ejecta mass in solar masses
460
+ :param f_rho: f_rho. Typically, of order unity
461
+ :param f_nickel: fraction of nickel mass
462
+ :param radius: star/envelope radius in units of 10^13 cm
463
+ :param kappa: opacity in cm^2/g
464
+ :param kwargs: Additional parameters required by model
465
+ :return: bolometric luminosity in erg/s
466
+ """
467
+ from redback.transient_models.shock_powered_models import shockcooling_morag_bolometric
468
+ f_rho_m = f_rho * mej
469
+ nickel_lbol = arnett_bolometric(time=time, f_nickel=f_nickel,
470
+ mej=mej, interaction_process=ip.Diffusion, kappa=kappa, vej=v_shock, **kwargs)
471
+ sbo_output = shockcooling_morag_bolometric(time=time, v_shock=v_shock, m_env=m_env, f_rho_m=f_rho_m,
472
+ radius=radius, kappa=kappa, **kwargs)
473
+ lbol = nickel_lbol + sbo_output
474
+ return lbol
475
+
476
+ @citation_wrapper('https://academic.oup.com/mnras/article/522/2/2764/7086123#443111844, https://ui.adsabs.harvard.edu/abs/1982ApJ...253..785A/abstract')
477
+ def shockcooling_morag_and_arnett(time, redshift, v_shock, m_env, mej, f_rho, f_nickel, radius, kappa, **kwargs):
478
+ """
479
+ Assumes Shock cooling following Morag+ and arnett model for radioactive decay
480
+
481
+ :param time: time in observer frame in days
482
+ :param redshift: source redshift
483
+ :param v_shock: shock speed in km/s, also the ejecta velocity in the arnett calculation
484
+ :param m_env: envelope mass in solar masses
485
+ :param mej: ejecta mass in solar masses
486
+ :param f_rho: f_rho. Typically, of order unity
487
+ :param f_nickel: fraction of nickel mass
488
+ :param radius: star/envelope radius in units of 10^13 cm
489
+ :param kappa: opacity in cm^2/g
490
+ :param kwargs: Additional parameters required by model
491
+ :param frequency: Required if output_format is 'flux_density'.
492
+ frequency to calculate - Must be same length as time array or a single number).
493
+ :param bands: Required if output_format is 'magnitude' or 'flux'.
494
+ :param output_format: 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
495
+ :param lambda_array: Optional argument to set your desired wavelength array (in Angstroms) to evaluate the SED on.
496
+ :param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
497
+ :return: set by output format - 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
498
+ """
499
+ cosmology = kwargs.get('cosmology', cosmo)
500
+ dl = cosmology.luminosity_distance(redshift).cgs.value
501
+
502
+ if kwargs['output_format'] == 'flux_density':
503
+ frequency = kwargs['frequency']
504
+ frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
505
+ lbol = shockcooling_morag_and_arnett_bolometric(time=time, v_shock=v_shock, m_env=m_env, mej=mej,
506
+ f_rho=f_rho, f_nickel=f_nickel, radius=radius, kappa=kappa, **kwargs)
507
+ photo = photosphere.TemperatureFloor(time=time, luminosity=lbol, vej=v_shock, **kwargs)
508
+ sed_1 = sed.Blackbody(temperature=photo.photosphere_temperature, r_photosphere=photo.r_photosphere,
509
+ frequency=frequency, luminosity_distance=dl)
510
+ flux_density = sed_1.flux_density
511
+ return flux_density.to(uu.mJy).value
512
+ else:
513
+ time_obs = time
514
+ lambda_observer_frame = kwargs.get('lambda_array', np.geomspace(100, 60000, 100))
515
+ time_temp = np.geomspace(0.1, 3000, 300) # in days
516
+ time_observer_frame = time_temp * (1. + redshift)
517
+ frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
518
+ redshift=redshift, time=time_observer_frame)
519
+ lbol = shockcooling_morag_and_arnett_bolometric(time=time, v_shock=v_shock, m_env=m_env, mej=mej,
520
+ f_rho=f_rho, f_nickel=f_nickel, radius=radius, kappa=kappa, **kwargs)
521
+ photo = photosphere.TemperatureFloor(time=time, luminosity=lbol, vej=v_shock, **kwargs)
522
+ sed_1 = sed.Blackbody(temperature=photo.photosphere_temperature, r_photosphere=photo.r_photosphere,
523
+ frequency=frequency[:, None], luminosity_distance=dl)
524
+ fmjy = sed_1.flux_density.T
525
+ spectra = fmjy.to(uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
526
+ equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
527
+ if kwargs['output_format'] == 'spectra':
528
+ return namedtuple('output', ['time', 'lambdas', 'spectra'])(time=time_observer_frame,
529
+ lambdas=lambda_observer_frame,
530
+ spectra=spectra)
531
+ else:
532
+ return sed.get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame,
533
+ spectra=spectra, lambda_array=lambda_observer_frame,
534
+ **kwargs)
535
+
536
+ @citation_wrapper('https://iopscience.iop.org/article/10.3847/1538-4357/aa64df, https://ui.adsabs.harvard.edu/abs/1982ApJ...253..785A/abstract')
537
+ def shockcooling_sapirwaxman_and_arnett_bolometric(time, v_shock, m_env, mej, f_rho, f_nickel, radius, kappa, **kwargs):
538
+ """
539
+ Assumes Shock cooling following Sapir and Waxman and arnett model for radioactive decay
540
+
541
+ :param time: time in source frame in days
542
+ :param v_shock: shock speed in km/s, also the ejecta velocity in the arnett calculation
543
+ :param m_env: envelope mass in solar masses
544
+ :param mej: ejecta mass in solar masses
545
+ :param f_rho: f_rho. Typically, of order unity
546
+ :param f_nickel: fraction of nickel mass
547
+ :param radius: star/envelope radius in units of 10^13 cm
548
+ :param kappa: opacity in cm^2/g
549
+ :param kwargs: Additional parameters required by model
550
+ :param n: index of progenitor density profile, 1.5 (default) or 3.0
551
+ :param RW: If True, use the simplified Rabinak & Waxman formulation (off by default)
552
+ :return: bolometric luminosity in erg/s
553
+ """
554
+ from redback.transient_models.shock_powered_models import shockcooling_sapirandwaxman_bolometric
555
+ f_rho_m = f_rho * mej
556
+ nickel_lbol = arnett_bolometric(time=time, f_nickel=f_nickel,
557
+ mej=mej, interaction_process=ip.Diffusion, kappa=kappa, vej=v_shock, **kwargs)
558
+ sbo_output = shockcooling_sapirandwaxman_bolometric(time=time, v_shock=v_shock, m_env=m_env, f_rho_m=f_rho_m,
559
+ radius=radius, kappa=kappa, **kwargs)
560
+ lbol = nickel_lbol + sbo_output
561
+ return lbol
562
+
563
+ @citation_wrapper('https://iopscience.iop.org/article/10.3847/1538-4357/aa64df, https://ui.adsabs.harvard.edu/abs/1982ApJ...253..785A/abstract')
564
+ def shockcooling_sapirwaxman_and_arnett(time, redshift, v_shock, m_env, mej, f_rho, f_nickel, radius, kappa, **kwargs):
565
+ """
566
+ Assumes Shock cooling following Sapir and Waxman and arnett model for radioactive decay
567
+
568
+ :param time: time in source frame in days
569
+ :param v_shock: shock speed in km/s, also the ejecta velocity in the arnett calculation
570
+ :param m_env: envelope mass in solar masses
571
+ :param mej: ejecta mass in solar masses
572
+ :param f_rho: f_rho. Typically, of order unity
573
+ :param f_nickel: fraction of nickel mass
574
+ :param radius: star/envelope radius in units of 10^13 cm
575
+ :param kappa: opacity in cm^2/g
576
+ :param kwargs: Additional parameters required by model
577
+ :param n: index of progenitor density profile, 1.5 (default) or 3.0
578
+ :param RW: If True, use the simplified Rabinak & Waxman formulation (off by default)
579
+ :param frequency: Required if output_format is 'flux_density'.
580
+ frequency to calculate - Must be same length as time array or a single number).
581
+ :param bands: Required if output_format is 'magnitude' or 'flux'.
582
+ :param output_format: 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
583
+ :param lambda_array: Optional argument to set your desired wavelength array (in Angstroms) to evaluate the SED on.
584
+ :param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
585
+ :return: set by output format - 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
586
+ """
587
+ cosmology = kwargs.get('cosmology', cosmo)
588
+ dl = cosmology.luminosity_distance(redshift).cgs.value
589
+
590
+ if kwargs['output_format'] == 'flux_density':
591
+ frequency = kwargs['frequency']
592
+ frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
593
+ lbol = shockcooling_morag_and_arnett_bolometric(time=time, v_shock=v_shock, m_env=m_env, mej=mej,
594
+ f_rho=f_rho, f_nickel=f_nickel, radius=radius, kappa=kappa,
595
+ **kwargs)
596
+ photo = photosphere.TemperatureFloor(time=time, luminosity=lbol, vej=v_shock, **kwargs)
597
+ sed_1 = sed.Blackbody(temperature=photo.photosphere_temperature, r_photosphere=photo.r_photosphere,
598
+ frequency=frequency, luminosity_distance=dl)
599
+ flux_density = sed_1.flux_density
600
+ return flux_density.to(uu.mJy).value
601
+ else:
602
+ time_obs = time
603
+ lambda_observer_frame = kwargs.get('lambda_array', np.geomspace(100, 60000, 100))
604
+ time_temp = np.geomspace(0.1, 3000, 300) # in days
605
+ time_observer_frame = time_temp * (1. + redshift)
606
+ frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
607
+ redshift=redshift, time=time_observer_frame)
608
+ lbol = shockcooling_morag_and_arnett_bolometric(time=time, v_shock=v_shock, m_env=m_env, mej=mej,
609
+ f_rho=f_rho, f_nickel=f_nickel, radius=radius, kappa=kappa,
610
+ **kwargs)
611
+ photo = photosphere.TemperatureFloor(time=time, luminosity=lbol, vej=v_shock, **kwargs)
612
+ sed_1 = sed.Blackbody(temperature=photo.photosphere_temperature, r_photosphere=photo.r_photosphere,
613
+ frequency=frequency[:, None], luminosity_distance=dl)
614
+ fmjy = sed_1.flux_density.T
615
+ spectra = fmjy.to(uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
616
+ equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
617
+ if kwargs['output_format'] == 'spectra':
618
+ return namedtuple('output', ['time', 'lambdas', 'spectra'])(time=time_observer_frame,
619
+ lambdas=lambda_observer_frame,
620
+ spectra=spectra)
621
+ else:
622
+ return sed.get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame,
623
+ spectra=spectra, lambda_array=lambda_observer_frame,
624
+ **kwargs)
625
+
450
626
  @citation_wrapper('redback')
451
627
  def basic_magnetar_powered_bolometric(time, p0, bp, mass_ns, theta_pb, **kwargs):
452
628
  """
@@ -707,7 +883,6 @@ def magnetar_nickel(time, redshift, f_nickel, mej, p0, bp, mass_ns, theta_pb, **
707
883
  **kwargs)
708
884
 
709
885
 
710
-
711
886
  @citation_wrapper('redback')
712
887
  def homologous_expansion_supernova_model_bolometric(time, mej, ek, **kwargs):
713
888
  """
@@ -1619,12 +1794,12 @@ def csm_shock_and_arnett_bolometric(time, mej, f_nickel, csm_mass, v_min, beta,
1619
1794
  lbol = nickel_lbol + sbo_output
1620
1795
  return lbol
1621
1796
 
1622
-
1623
1797
  @citation_wrapper('https://ui.adsabs.harvard.edu/abs/2022ApJ...933..238M/abstract, https://ui.adsabs.harvard.edu/abs/1982ApJ...253..785A/abstract')
1624
1798
  def csm_shock_and_arnett(time, redshift, mej, f_nickel, csm_mass, v_min, beta, shell_radius,
1625
1799
  shell_width_ratio, kappa, **kwargs):
1626
1800
  """
1627
1801
  Assumes CSM interaction for a shell-like CSM with a hard outer boundary and arnett model for radioactive decay
1802
+ Assumes one single photosphere from the sum of the bolometric luminosities
1628
1803
 
1629
1804
  :param time: time in days in observer frame
1630
1805
  :param redshift: source redshift
@@ -1674,6 +1849,157 @@ def csm_shock_and_arnett(time, redshift, mej, f_nickel, csm_mass, v_min, beta, s
1674
1849
  sed_1 = sed.Blackbody(temperature=photo.photosphere_temperature, r_photosphere=photo.r_photosphere,
1675
1850
  frequency=frequency[:, None], luminosity_distance=dl)
1676
1851
  fmjy = sed_1.flux_density.T
1852
+ spectra = fmjy.to(uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
1853
+ equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
1854
+ if kwargs['output_format'] == 'spectra':
1855
+ return namedtuple('output', ['time', 'lambdas', 'spectra'])(time=time_observer_frame,
1856
+ lambdas=lambda_observer_frame,
1857
+ spectra=spectra)
1858
+ else:
1859
+ return sed.get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame,
1860
+ spectra=spectra, lambda_array=lambda_observer_frame,
1861
+ **kwargs)
1862
+
1863
+ @citation_wrapper('https://ui.adsabs.harvard.edu/abs/2022ApJ...933..238M/abstract, https://ui.adsabs.harvard.edu/abs/1982ApJ...253..785A/abstract')
1864
+ def csm_shock_and_arnett_two_rphots(time, redshift, mej, f_nickel, csm_mass, v_min, beta, shell_radius,
1865
+ shell_width_ratio, kappa, **kwargs):
1866
+ """
1867
+ Assumes CSM interaction for a shell-like CSM with a hard outer boundary and arnett model for radioactive decay.
1868
+ Assumes the photospheres for the CSM-interaction and the Arnett model are different.
1869
+
1870
+ :param time: time in days in observer frame
1871
+ :param redshift: source redshift
1872
+ :param mej: ejecta mass in solar masses
1873
+ :param f_nickel: fraction of nickel mass
1874
+ :param csm_mass: csm mass in solar masses
1875
+ :param v_min: ejecta velocity in km/s
1876
+ :param beta: velocity ratio in c (beta < 1)
1877
+ :param shell_radius: radius of shell in 10^14 cm
1878
+ :param kappa: opacity
1879
+ :param shell_width_ratio: shell width ratio (deltaR/R0)
1880
+ :param kwargs: kappa_gamma, temperature_floor, and any kwarg to
1881
+ change any other input physics/parameters from default.
1882
+ :param frequency: Required if output_format is 'flux_density'.
1883
+ frequency to calculate - Must be same length as time array or a single number).
1884
+ :param bands: Required if output_format is 'magnitude' or 'flux'.
1885
+ :param output_format: 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
1886
+ :param lambda_array: Optional argument to set your desired wavelength array (in Angstroms) to evaluate the SED on.
1887
+ :param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
1888
+ :return: set by output format - 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
1889
+ """
1890
+ cosmology = kwargs.get('cosmology', cosmo)
1891
+ dl = cosmology.luminosity_distance(redshift).cgs.value
1892
+
1893
+ if kwargs['output_format'] == 'flux_density':
1894
+ frequency = kwargs['frequency']
1895
+ frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
1896
+
1897
+ output = _csm_shock_breakout(time=time, csm_mass=csm_mass*solar_mass, v_min=v_min, beta=beta, kappa=kappa,
1898
+ shell_radius=shell_radius, shell_width_ratio=shell_width_ratio, **kwargs)
1899
+ r_phot = output.r_photosphere
1900
+ temp = output.temperature
1901
+ flux_density = sed.blackbody_to_flux_density(temperature=temp, r_photosphere=r_phot, dl=dl, frequency=frequency)
1902
+ lbol = arnett_bolometric(time=time, f_nickel=f_nickel, mej=mej, vej=v_min, kappa=kappa,
1903
+ interaction_process=ip.Diffusion, **kwargs)
1904
+ photo = photosphere.TemperatureFloor(time=time, luminosity=lbol, vej=v_min, **kwargs)
1905
+ sed_1 = sed.Blackbody(temperature=photo.photosphere_temperature,
1906
+ r_photosphere=photo.r_photosphere, frequency=frequency, luminosity_distance=dl)
1907
+ flux_density += sed_1.flux_density
1908
+ return flux_density.to(uu.mJy).value
1909
+ else:
1910
+ time_obs = time
1911
+ lambda_observer_frame = kwargs.get('lambda_array', np.geomspace(100, 60000, 100))
1912
+ time_temp = np.geomspace(0.1, 300, 300) # in days
1913
+ time_observer_frame = time_temp * (1. + redshift)
1914
+ frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
1915
+ redshift=redshift, time=time_observer_frame)
1916
+ output = _csm_shock_breakout(time=time, csm_mass=csm_mass * solar_mass, v_min=v_min, beta=beta, kappa=kappa,
1917
+ shell_radius=shell_radius, shell_width_ratio=shell_width_ratio, **kwargs)
1918
+ fmjy = sed.blackbody_to_flux_density(temperature=output.temperature,
1919
+ r_photosphere=output.r_photosphere, frequency=frequency[:, None], dl=dl)
1920
+ lbol = arnett_bolometric(time=time, f_nickel=f_nickel, mej=mej, vej=v_min, kappa=kappa,
1921
+ interaction_process=ip.Diffusion, **kwargs)
1922
+ photo = photosphere.TemperatureFloor(time=time, luminosity=lbol, vej=v_min, **kwargs)
1923
+ sed_1 = sed.Blackbody(temperature=photo.photosphere_temperature,
1924
+ r_photosphere=photo.r_photosphere, frequency=frequency[:, None], luminosity_distance=dl)
1925
+ fmjy += sed_1.flux_density
1926
+ fmjy = fmjy.T
1927
+ spectra = fmjy.to(uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
1928
+ equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
1929
+ if kwargs['output_format'] == 'spectra':
1930
+ return namedtuple('output', ['time', 'lambdas', 'spectra'])(time=time_observer_frame,
1931
+ lambdas=lambda_observer_frame,
1932
+ spectra=spectra)
1933
+ else:
1934
+ return sed.get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame,
1935
+ spectra=spectra, lambda_array=lambda_observer_frame,
1936
+ **kwargs)
1937
+
1938
+ def shocked_cocoon_and_arnett(time, redshift, mej_c, vej_c, eta, tshock, shocked_fraction, cos_theta_cocoon, kappa,
1939
+ mej, f_nickel, vej, **kwargs):
1940
+ """
1941
+ Emission from a shocked cocoon and arnett model for radioactive decay.
1942
+ We assume two different photospheres here.
1943
+
1944
+ :param time: Time in days in observer frame
1945
+ :param redshift: redshift
1946
+ :param mej_c: cocoon mass (in solar masses)
1947
+ :param vej_c: cocoon material velocity (in c)
1948
+ :param eta: slope for the cocoon density profile
1949
+ :param tshock: shock breakout time (in seconds)
1950
+ :param shocked_fraction: fraction of the cocoon shocked
1951
+ :param cos_theta_cocoon: cosine of the cocoon opening angle
1952
+ :param kappa: opacity
1953
+ :param mej: supernova ejecta mass (in solar masses)
1954
+ :param f_nickel: fraction of nickel for ejecta mass
1955
+ :param vej: supernova ejecta velocity (in km/s)
1956
+ :param kwargs: Extra parameters used by model e.g., kappa_gamma, temperature_floor, and any kwarg to
1957
+ change any other input physics/parameters from default.
1958
+ :param frequency: Required if output_format is 'flux_density'.
1959
+ frequency to calculate - Must be same length as time array or a single number).
1960
+ :param bands: Required if output_format is 'magnitude' or 'flux'.
1961
+ :param output_format: 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
1962
+ :param lambda_array: Optional argument to set your desired wavelength array (in Angstroms) to evaluate the SED on.
1963
+ :param cosmology: Cosmology to use for luminosity distance calculation. Defaults to Planck18. Must be a astropy.cosmology object.
1964
+ :return: set by output format - 'flux_density', 'magnitude', 'spectra', 'flux', 'sncosmo_source'
1965
+ """
1966
+ cosmology = kwargs.get('cosmology', cosmo)
1967
+ dl = cosmology.luminosity_distance(redshift).cgs.value
1968
+ time_obs = time
1969
+
1970
+ if kwargs['output_format'] == 'flux_density':
1971
+ frequency = kwargs['frequency']
1972
+ frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
1973
+ output = _shocked_cocoon(time=time, mej=mej_c, vej=vej_c, eta=eta,
1974
+ tshock=tshock, shocked_fraction=shocked_fraction,
1975
+ cos_theta_cocoon=cos_theta_cocoon, kappa=kappa)
1976
+ flux_density = sed.blackbody_to_flux_density(temperature=output.temperature, r_photosphere=output.r_photosphere,
1977
+ dl=dl, frequency=frequency)
1978
+ lbol = arnett_bolometric(time=time, f_nickel=f_nickel, mej=mej, vej=vej,
1979
+ interaction_process=ip.Diffusion, kappa=kappa, **kwargs)
1980
+ photo = photosphere.TemperatureFloor(time=time, luminosity=lbol, vej=vej, **kwargs)
1981
+ sed_1 = sed.Blackbody(temperature=photo.photosphere_temperature,
1982
+ r_photosphere=photo.r_photosphere, frequency=frequency, luminosity_distance=dl)
1983
+ flux_density += sed_1.flux_density
1984
+ return flux_density.to(uu.mJy).value
1985
+ else:
1986
+ lambda_observer_frame = kwargs.get('frequency_array', np.geomspace(100, 60000, 200))
1987
+ time_temp = np.linspace(1e-2, 300, 300)
1988
+ time_observer_frame = time_temp
1989
+ frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
1990
+ redshift=redshift, time=time_observer_frame)
1991
+ output = _shocked_cocoon(time=time, mej=mej_c, vej=vej_c, eta=eta,
1992
+ tshock=tshock, shocked_fraction=shocked_fraction,
1993
+ cos_theta_cocoon=cos_theta_cocoon, kappa=kappa)
1994
+ fmjy = sed.blackbody_to_flux_density(temperature=output.temperature,
1995
+ r_photosphere=output.r_photosphere, frequency=frequency[:, None], dl=dl)
1996
+ lbol = arnett_bolometric(time=time, f_nickel=f_nickel, mej=mej, vej=vej,
1997
+ interaction_process=ip.Diffusion, kappa=kappa, **kwargs)
1998
+ photo = photosphere.TemperatureFloor(time=time, luminosity=lbol, vej=vej, **kwargs)
1999
+ sed_1 = sed.Blackbody(temperature=photo.photosphere_temperature,
2000
+ r_photosphere=photo.r_photosphere, frequency=frequency[:, None], luminosity_distance=dl)
2001
+ fmjy += sed_1.flux_density
2002
+ fmjy = fmjy.T
1677
2003
  spectra = fmjy.to(uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
1678
2004
  equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
1679
2005
  if kwargs['output_format'] == 'spectra':
@@ -1178,8 +1178,8 @@ def fitted_pl_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl,
1178
1178
  nulnus_decay = np.zeros(len(time))
1179
1179
 
1180
1180
  if len(freqs_un) == 1:
1181
- nulnus_plateau = m.model_UV(time, log_mh, a_bh, m_disc, r0, tvi, t_form, ang, frequency)
1182
- nulnus_decay = m.decay_model(time, log_L, tdecay, p, t_peak, log_T, v=freqs_un[0])
1181
+ nulnus_plateau = m.model_UV(time, log_mh, a_bh, m_disc, r0, tvi, t_form, ang, v=freqs_un[0])
1182
+ nulnus_decay = m.decay_model(time, log_L, t_decay, p, t_peak, log_T, v=freqs_un[0])
1183
1183
  nulnus_rise = m.rise_model(time, log_L, sigma, t_peak, log_T, v=freqs_un[0])
1184
1184
  else:
1185
1185
  for i in range(0,len(freqs_un)):
@@ -1199,9 +1199,11 @@ def fitted_pl_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl,
1199
1199
  frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
1200
1200
  redshift=redshift, time=time_observer_frame)
1201
1201
  nulnus_plateau = m.model_SEDs(time, log_mh, a_bh, m_disc, r0, tvi, t_form, ang, frequency)
1202
- nulnus_risedecay = np.zeros((100, 300))
1203
- for i in range(0,len(frequency)):
1204
- nulnus_risedecay[i,:] = m.decay_model(time, log_L, t_decay, p, t_peak, log_T, v=frequency[i]) + m.rise_model(time, log_L, sigma, t_peak, log_T, v=frequency[i])
1202
+
1203
+ 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, sigma, t_peak, log_T, freq_0))
1205
+ nulnus_risedecay = ((l_e_amp[:, None] * (frequency/freq_0)**4 *
1206
+ (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)
1205
1207
  flux_density = ((nulnus_risedecay + nulnus_plateau)/(4.0 * np.pi * dl**2 * frequency[:,np.newaxis] * 1.0e-26))
1206
1208
  fmjy = flux_density.T
1207
1209
  spectra = (fmjy * uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
@@ -1259,8 +1261,8 @@ def fitted_exp_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl
1259
1261
  nulnus_decay = np.zeros(len(time))
1260
1262
 
1261
1263
  if len(freqs_un) == 1:
1262
- nulnus_plateau = m.model_UV(time, log_mh, a_bh, m_disc, r0, tvi, t_form, ang, frequency)
1263
- nulnus_decay = m.decay_model(time, log_L, tdecay, t_peak, log_T, v=freqs_un[0])
1264
+ nulnus_plateau = m.model_UV(time, log_mh, a_bh, m_disc, r0, tvi, t_form, ang, v=freqs_un[0])
1265
+ nulnus_decay = m.decay_model(time, log_L, t_decay, t_peak, log_T, v=freqs_un[0])
1264
1266
  nulnus_rise = m.rise_model(time, log_L, sigma, t_peak, log_T, v=freqs_un[0])
1265
1267
  else:
1266
1268
  for i in range(0,len(freqs_un)):
@@ -1280,9 +1282,11 @@ def fitted_exp_decay(time, redshift, log_mh, a_bh, m_disc, r0, tvi, t_form, incl
1280
1282
  frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
1281
1283
  redshift=redshift, time=time_observer_frame)
1282
1284
  nulnus_plateau = m.model_SEDs(time, log_mh, a_bh, m_disc, r0, tvi, t_form, ang, frequency)
1283
- nulnus_risedecay = np.zeros((100, 300))
1284
- for i in range(0,len(frequency)):
1285
- nulnus_risedecay[i,:] = m.decay_model(time, log_L, t_decay, t_peak, log_T, v=frequency[i]) + m.rise_model(time, log_L, sigma, t_peak, log_T, v=frequency[i])
1285
+
1286
+ 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, sigma, t_peak, log_T, freq_0))
1288
+ nulnus_risedecay = ((l_e_amp[:, None] * (frequency/freq_0)**4 *
1289
+ (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)
1286
1290
  flux_density = ((nulnus_risedecay + nulnus_plateau)/(4.0 * np.pi * dl**2 * frequency[:,np.newaxis] * 1.0e-26))
1287
1291
  fmjy = flux_density.T
1288
1292
  spectra = (fmjy * uu.mJy).to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
@@ -1378,11 +1382,10 @@ def stream_stream_tde_bolometric(time, mbh_6, mstar, c1, f, h_r, inc_tcool, del_
1378
1382
  norm = output.bolometric_luminosity[0] / f1
1379
1383
 
1380
1384
  #evaluate giant array of bolometric luminosities
1381
- tt_pre_fb = np.linspace(0, output.time_temp[0], 100)
1385
+ tt_pre_fb = np.linspace(0, output.time_temp[0]-0.001, 100)
1382
1386
  tt_post_fb = output.time_temp
1383
1387
  full_time = np.concatenate([tt_pre_fb, tt_post_fb])
1384
- f1 = pm.gaussian_rise(time=tt_pre_fb, a_1=norm,
1385
- peak_time=peak_time * cc.day_to_s, sigma_t=sigma_t * cc.day_to_s)
1388
+ f1 = norm * np.exp(-(tt_pre_fb - (peak_time * cc.day_to_s))**2.0 / (2 * (sigma_t * cc.day_to_s) **2.0))
1386
1389
  f2 = output.bolometric_luminosity
1387
1390
  full_lbol = np.concatenate([f1, f2])
1388
1391
  lbol_func = interp1d(full_time, y=full_lbol, fill_value='extrapolate')
@@ -1420,7 +1423,7 @@ def stream_stream_tde(time, redshift, mbh_6, mstar, c1, f, h_r, inc_tcool, del_o
1420
1423
  #get bolometric and temperature info
1421
1424
  f1 = pm.gaussian_rise(time=output.time_temp[0] / cc.day_to_s, a_1=1, peak_time=peak_time, sigma_t=sigma_t)
1422
1425
  norm = output.bolometric_luminosity[0] / f1
1423
- tt_pre_fb = np.linspace(0, output.time_temp[0], 100)
1426
+ tt_pre_fb = np.linspace(0, output.time_temp[0]-0.001, 100)
1424
1427
  tt_post_fb = output.time_temp
1425
1428
  full_time = np.concatenate([tt_pre_fb, tt_post_fb])
1426
1429
  f1_src = pm.gaussian_rise(time=tt_pre_fb, a_1=norm,
@@ -1436,34 +1439,47 @@ def stream_stream_tde(time, redshift, mbh_6, mstar, c1, f, h_r, inc_tcool, del_o
1436
1439
  if kwargs['output_format'] == 'flux_density':
1437
1440
  frequency = kwargs['frequency']
1438
1441
  if isinstance(frequency, float):
1439
- frequency = np.ones(len(time)) * frequency
1440
-
1441
- else:
1442
- bands = kwargs['bands']
1443
- if isinstance(bands, str):
1444
- bands = [str(bands) for x in range(len(time))]
1445
- frequency=bands_to_frequency(bands)
1442
+ frequency = np.ones(len(time)) * frequency
1446
1443
 
1447
- # convert to source frame time and frequency
1448
- frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
1449
- unique_frequency = np.sort(np.unique(frequency))
1450
-
1451
- # build flux density function for each frequency
1452
- flux_den_interp_func = {}
1453
- total_time = full_time * (1 + redshift)
1454
- for freq in unique_frequency:
1455
- flux_den = sed.blackbody_to_flux_density(temperature=full_temp,
1444
+ # convert to source frame time and frequency
1445
+ frequency, time = calc_kcorrected_properties(frequency=frequency, redshift=redshift, time=time)
1446
+ unique_frequency = np.sort(np.unique(frequency))
1447
+
1448
+ # build flux density function for each frequency
1449
+ flux_den_interp_func = {}
1450
+ total_time = full_time * (1 + redshift)
1451
+ for freq in unique_frequency:
1452
+ flux_den = sed.blackbody_to_flux_density(temperature=full_temp,
1456
1453
  r_photosphere=r_eff,
1457
1454
  dl=dl, frequency=freq).to(uu.mJy)
1458
- flux_den_interp_func[freq] = interp1d(total_time, flux_den, fill_value='extrapolate')
1455
+ flux_den_interp_func[freq] = interp1d(total_time, flux_den, fill_value='extrapolate')
1459
1456
 
1460
- # interpolate onto actual observed frequency and time values
1461
- flux_density = []
1462
- for freq, tt in zip(frequency, time):
1463
- flux_density.append(flux_den_interp_func[freq](tt * cc.day_to_s))
1464
- flux_density = flux_density * uu.mJy
1465
-
1466
- if kwargs['output_format'] == 'flux_density':
1467
- return flux_density.to(uu.mJy).value
1468
- else:
1469
- return calc_ABmag_from_flux_density(flux_density.to(uu.mJy).value).value
1457
+ # interpolate onto actual observed frequency and time values
1458
+ flux_density = []
1459
+ for freq, tt in zip(frequency, time):
1460
+ flux_density.append(flux_den_interp_func[freq](tt * cc.day_to_s))
1461
+ flux_density = flux_density * uu.mJy
1462
+ return flux_density.to(uu.mJy).value
1463
+
1464
+ else:
1465
+ time_obs = time
1466
+ lambda_observer_frame = kwargs.get('lambda_array', np.geomspace(100, 60000, 100))
1467
+ time_observer_frame = full_time * (1. + redshift)
1468
+ frequency, time = calc_kcorrected_properties(frequency=lambda_to_nu(lambda_observer_frame),
1469
+ redshift=redshift, time=time_observer_frame)
1470
+ freq_0 = 6e14
1471
+ flux_den = sed.blackbody_to_flux_density(temperature=full_temp,
1472
+ r_photosphere=r_eff,
1473
+ dl=dl, frequency=freq_0).to(uu.mJy)
1474
+ fmjy = ((flux_den[:, None] * (frequency/freq_0)**4 *
1475
+ (np.exp(cc.planck * freq_0/(cc.boltzmann_constant * full_temp[:, None])) - 1) / (np.exp(cc.planck * frequency/(cc.boltzmann_constant * full_temp[:, None])) - 1)).T)
1476
+ spectra = fmjy.T.to(uu.erg / uu.cm ** 2 / uu.s / uu.Angstrom,
1477
+ equivalencies=uu.spectral_density(wav=lambda_observer_frame * uu.Angstrom))
1478
+ if kwargs['output_format'] == 'spectra':
1479
+ return namedtuple('output', ['time', 'lambdas', 'spectra'])(time=time_observer_frame,
1480
+ lambdas=lambda_observer_frame,
1481
+ spectra=spectra)
1482
+ else:
1483
+ return sed.get_correct_output_format_from_spectra(time=time_obs, time_eval=time_observer_frame/cc.day_to_s,
1484
+ spectra=spectra, lambda_array=lambda_observer_frame,
1485
+ **kwargs)