redback 1.0.0__py3-none-any.whl → 1.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. redback/__init__.py +4 -0
  2. redback/constraints.py +31 -25
  3. redback/ejecta_relations.py +8 -8
  4. redback/get_data/lasair.py +3 -4
  5. redback/get_data/swift.py +7 -7
  6. redback/interaction_processes.py +1 -4
  7. redback/likelihoods.py +207 -21
  8. redback/plotting.py +11 -11
  9. redback/priors/csm_interaction.prior +6 -7
  10. redback/priors/csm_nickel.prior +3 -3
  11. redback/priors/one_comp_kne_rosswog_heatingrate.prior +5 -0
  12. redback/priors/one_component_nsbh_ejecta_relation.prior +1 -1
  13. redback/priors/tde_analytical.prior +5 -5
  14. redback/priors/tde_analytical_bolometric.prior +6 -4
  15. redback/priors/tophat_from_emulator.prior +9 -0
  16. redback/priors/two_comp_kne_rosswog_heatingrate.prior +9 -0
  17. redback/priors/two_component_nsbh_ejecta_relation.prior +1 -1
  18. redback/priors/two_layer_stratified_kilonova.prior +1 -1
  19. redback/priors.py +11 -0
  20. redback/sed.py +194 -2
  21. redback/simulate_transients.py +61 -32
  22. redback/tables/filters.csv +15 -1
  23. redback/tables/ztf.tar.gz +0 -0
  24. redback/transient/afterglow.py +3 -2
  25. redback/transient/kilonova.py +1 -1
  26. redback/transient/supernova.py +1 -1
  27. redback/transient/tde.py +1 -1
  28. redback/transient/transient.py +2 -2
  29. redback/transient_models/afterglow_models.py +42 -0
  30. redback/transient_models/combined_models.py +47 -32
  31. redback/transient_models/extinction_models.py +12 -5
  32. redback/transient_models/kilonova_models.py +247 -14
  33. redback/transient_models/magnetar_driven_ejecta_models.py +2 -2
  34. redback/transient_models/phenomenological_models.py +13 -0
  35. redback/transient_models/supernova_models.py +50 -36
  36. redback/transient_models/tde_models.py +126 -1
  37. redback/utils.py +283 -6
  38. {redback-1.0.0.dist-info → redback-1.0.2.dist-info}/METADATA +7 -4
  39. {redback-1.0.0.dist-info → redback-1.0.2.dist-info}/RECORD +42 -40
  40. {redback-1.0.0.dist-info → redback-1.0.2.dist-info}/WHEEL +1 -1
  41. redback/tables/ztf_obslog.csv +0 -106649
  42. {redback-1.0.0.dist-info → redback-1.0.2.dist-info}/LICENCE.md +0 -0
  43. {redback-1.0.0.dist-info → redback-1.0.2.dist-info}/top_level.txt +0 -0
redback/sed.py CHANGED
@@ -6,6 +6,193 @@ from sncosmo import TimeSeriesSource
6
6
  from redback.constants import *
7
7
  from redback.utils import nu_to_lambda, bandpass_magnitude_to_flux
8
8
 
9
+ def _bandflux_single_redback(model, band, time_or_phase):
10
+ """
11
+
12
+ Synthetic photometry of a model through a single bandpass
13
+
14
+ :param model: Source object
15
+ :param band: Bandpass
16
+ :param time_or_phase: Time or phase numpy array
17
+ :return: bandflux through the bandpass
18
+ """
19
+ from sncosmo.utils import integration_grid
20
+ HC_ERG_AA = 1.9864458571489284e-08 # planck * speed_of_light in AA/s
21
+ MODEL_BANDFLUX_SPACING = 5.0 # Angstroms
22
+
23
+ if (band.minwave() < model.minwave() or band.maxwave() > model.maxwave()):
24
+ raise ValueError('bandpass {0!r:s} [{1:.6g}, .., {2:.6g}] '
25
+ 'outside spectral range [{3:.6g}, .., {4:.6g}]'
26
+ .format(band.name, band.minwave(), band.maxwave(),
27
+ model.minwave(), model.maxwave()))
28
+
29
+ # Set up wavelength grid. Spacing (dwave) evenly divides the bandpass,
30
+ # closest to 5 angstroms without going over.
31
+ wave, dwave = integration_grid(band.minwave(), band.maxwave(),
32
+ MODEL_BANDFLUX_SPACING)
33
+ trans = band(wave)
34
+ f = model._flux(time_or_phase, wave)
35
+ f = np.abs(f)
36
+ return np.sum(wave * trans * f, axis=1) * dwave / HC_ERG_AA
37
+
38
+
39
+ def _bandflux_redback(model, band, time_or_phase, zp, zpsys):
40
+ """
41
+ Support function for bandflux in Source and Model. Follows SNCOSMO
42
+
43
+ This is necessary to have outside because ``phase`` is used in Source
44
+ and ``time`` is used in Model, and we want the method signatures to
45
+ have the right variable name.
46
+ """
47
+ from sncosmo.magsystems import get_magsystem
48
+ from sncosmo.bandpasses import get_bandpass
49
+
50
+ if zp is not None and zpsys is None:
51
+ raise ValueError('zpsys must be given if zp is not None')
52
+
53
+ # broadcast arrays
54
+ if zp is None:
55
+ time_or_phase, band = np.broadcast_arrays(time_or_phase, band)
56
+ else:
57
+ time_or_phase, band, zp, zpsys = \
58
+ np.broadcast_arrays(time_or_phase, band, zp, zpsys)
59
+
60
+ # Convert all to 1-d arrays.
61
+ ndim = time_or_phase.ndim # Save input ndim for return val.
62
+ time_or_phase = np.atleast_1d(time_or_phase)
63
+ band = np.atleast_1d(band)
64
+ if zp is not None:
65
+ zp = np.atleast_1d(zp)
66
+ zpsys = np.atleast_1d(zpsys)
67
+
68
+ # initialize output arrays
69
+ bandflux = np.zeros(time_or_phase.shape, dtype=float)
70
+
71
+ # Loop over unique bands.
72
+ for b in set(band):
73
+ mask = band == b
74
+ b = get_bandpass(b)
75
+
76
+ fsum = _bandflux_single_redback(model, b, time_or_phase[mask])
77
+
78
+ if zp is not None:
79
+ zpnorm = 10. ** (0.4 * zp[mask])
80
+ bandzpsys = zpsys[mask]
81
+ for ms in set(bandzpsys):
82
+ mask2 = bandzpsys == ms
83
+ ms = get_magsystem(ms)
84
+ zpnorm[mask2] = zpnorm[mask2] / ms.zpbandflux(b)
85
+ fsum *= zpnorm
86
+
87
+ bandflux[mask] = fsum
88
+
89
+ if ndim == 0:
90
+ return bandflux[0]
91
+ return bandflux
92
+
93
+ def _bandmag_redback(model, band, magsys, time_or_phase):
94
+ """
95
+ Support function for bandflux in Source and Model.
96
+ This is necessary to have outside the models because ``phase`` is used in
97
+ Source and ``time`` is used in Model.
98
+ """
99
+ from sncosmo.magsystems import get_magsystem
100
+
101
+ bandflux = _bandflux_redback(model, band, time_or_phase, None, None)
102
+ band, magsys, bandflux = np.broadcast_arrays(band, magsys, bandflux)
103
+ return_scalar = (band.ndim == 0)
104
+ band = band.ravel()
105
+ magsys = magsys.ravel()
106
+ bandflux = bandflux.ravel()
107
+
108
+ result = np.empty(bandflux.shape, dtype=float)
109
+ for i, (b, ms, f) in enumerate(zip(band, magsys, bandflux)):
110
+ ms = get_magsystem(ms)
111
+ zpf = ms.zpbandflux(b)
112
+ result[i] = -2.5 * np.log10(f / zpf)
113
+
114
+ if return_scalar:
115
+ return result[0]
116
+ return result
117
+
118
+ class RedbackTimeSeriesSource(TimeSeriesSource):
119
+ def __init__(self, phase, wave, flux, **kwargs):
120
+ """
121
+ RedbackTimeSeriesSource is a subclass of sncosmo.TimeSeriesSource that adds the ability to return the
122
+ flux density at a given time and wavelength, and changes
123
+ the behaviour of the _flux method to better handle models with very low flux values.
124
+
125
+ :param phase: phase/time array
126
+ :param wave: wavelength array in Angstrom
127
+ :param spectra: spectra in erg/cm^2/s/A evaluated at all times and frequencies; shape (len(times), len(frequency_array))
128
+ :param kwargs: additional arguments
129
+ """
130
+ super(RedbackTimeSeriesSource, self).__init__(phase=phase, wave=wave, flux=flux, **kwargs)
131
+
132
+ def get_flux_density(self, time, wavelength):
133
+ """
134
+ Get the flux density at a given time and wavelength.
135
+
136
+ :param time: time in days
137
+ :param wavelength: wavelength in Angstrom
138
+ :return: flux density in erg/cm^2/s/A
139
+ """
140
+ return self._flux(time, wavelength)
141
+
142
+ def bandflux(self, band, phase, zp=None, zpsys=None):
143
+ """
144
+ Flux through the given bandpass(es) at the given phase(s).
145
+
146
+ Default return value is flux in photons / s / cm^2. If zp and zpsys
147
+ are given, flux(es) are scaled to the requested zeropoints.
148
+
149
+ Parameters
150
+ ----------
151
+ band : str or list_like
152
+ Name(s) of bandpass(es) in registry.
153
+ phase : float or list_like, optional
154
+ Phase(s) in days. Default is `None`, which corresponds to the full
155
+ native phase sampling of the model.
156
+ zp : float or list_like, optional
157
+ If given, zeropoint to scale flux to (must also supply ``zpsys``).
158
+ If not given, flux is not scaled.
159
+ zpsys : str or list_like, optional
160
+ Name of a magnitude system in the registry, specifying the system
161
+ that ``zp`` is in.
162
+
163
+ Returns
164
+ -------
165
+ bandflux : float or `~numpy.ndarray`
166
+ Flux in photons / s /cm^2, unless `zp` and `zpsys` are
167
+ given, in which case flux is scaled so that it corresponds
168
+ to the requested zeropoint. Return value is `float` if all
169
+ input parameters are scalars, `~numpy.ndarray` otherwise.
170
+ """
171
+ return _bandflux_redback(self, band, phase, zp, zpsys)
172
+
173
+ def bandmag(self, band, magsys, phase):
174
+ """Magnitude at the given phase(s) through the given
175
+ bandpass(es), and for the given magnitude system(s).
176
+
177
+ Parameters
178
+ ----------
179
+ band : str or list_like
180
+ Name(s) of bandpass in registry.
181
+ magsys : str or list_like
182
+ Name(s) of `~sncosmo.MagSystem` in registry.
183
+ phase : float or list_like
184
+ Phase(s) in days.
185
+
186
+ Returns
187
+ -------
188
+ mag : float or `~numpy.ndarray`
189
+ Magnitude for each item in band, magsys, phase.
190
+ The return value is a float if all parameters are not iterables.
191
+ The return value is an `~numpy.ndarray` if any are iterable.
192
+ """
193
+ return _bandmag_redback(self, band, magsys, phase)
194
+
195
+
9
196
 
10
197
  def blackbody_to_flux_density(temperature, r_photosphere, dl, frequency):
11
198
  """
@@ -298,13 +485,18 @@ def get_correct_output_format_from_spectra(time, time_eval, spectra, lambda_arra
298
485
  :param time: times in observer frame in days to evaluate the model on
299
486
  :param time_eval: times in observer frame where spectra are evaluated. A densely sampled array for accuracy
300
487
  :param bands: band array - must be same length as time array or a single band
301
- :param spectra: spectra in mJy evaluated at all times and frequencies; shape (len(times), len(frequency_array))
488
+ :param spectra: spectra in erg/cm^2/s/A evaluated at all times and frequencies; shape (len(times), len(frequency_array))
302
489
  :param lambda_array: wavelenth array in Angstrom in observer frame
303
490
  :param kwargs: Additional parameters
304
491
  :param output_format: 'flux', 'magnitude', 'sncosmo_source', 'flux_density'
305
492
  :return: flux, magnitude or SNcosmo TimeSeries Source depending on output format kwarg
306
493
  """
307
- source = TimeSeriesSource(phase=time_eval, wave=lambda_array, flux=spectra)
494
+ # clean up spectrum to remove nonsensical values before creating sncosmo source
495
+ spectra = np.nan_to_num(spectra)
496
+ spectra[spectra.value == np.nan_to_num(np.inf)] = 1e-30 * np.mean(spectra[5])
497
+ spectra[spectra.value == 0.] = 1e-30 * np.mean(spectra[5])
498
+
499
+ source = RedbackTimeSeriesSource(phase=time_eval, wave=lambda_array, flux=spectra)
308
500
  if kwargs['output_format'] == 'flux':
309
501
  bands = kwargs['bands']
310
502
  magnitude = source.bandmag(phase=time, band=bands, magsys='ab')
@@ -14,7 +14,7 @@ datadir = os.path.join(os.path.dirname(redback.__file__), 'tables')
14
14
 
15
15
  class SimulateGenericTransient(object):
16
16
  def __init__(self, model, parameters, times, model_kwargs, data_points,
17
- seed=1234, multiwavelength_transient=False, noise_term=0.2):
17
+ seed=1234, multiwavelength_transient=False, noise_term=0.2, noise_type='gaussianmodel', extra_scatter=0.0):
18
18
  """
19
19
  A generic interface to simulating transients
20
20
 
@@ -31,7 +31,12 @@ class SimulateGenericTransient(object):
31
31
  and the data points are sampled in bands/frequency as well,
32
32
  rather than just corresponding to one wavelength/filter.
33
33
  This also allows the same time value to be sampled multiple times.
34
- :param noise_term: Float. Factor which is multiplied by the model flux/magnitude to give the sigma.
34
+ :param noise_type: String. Type of noise to add to the model.
35
+ Default is 'gaussianmodel' where sigma is noise_term * model.
36
+ Another option is 'gaussian' i.e., a simple Gaussian noise with sigma = noise_term.
37
+ :param noise_term: Float. Factor which is multiplied by the model flux/magnitude to give the sigma
38
+ or is sigma itself for 'gaussian' noise.
39
+ :param extra_scatter: Float. Sigma of normal added to output for additional scatter.
35
40
  """
36
41
  self.model = redback.model_library.all_models_dict[model]
37
42
  self.parameters = parameters
@@ -44,20 +49,25 @@ class SimulateGenericTransient(object):
44
49
  self.noise_term = noise_term
45
50
  random.seed(self.seed)
46
51
 
47
- if multiwavelength_transient:
48
- self.all_bands = self.model_kwargs.get('bands', None)
49
- self.all_frequency = self.model_kwargs.get('frequency', None)
50
- if self.all_bands is None and self.all_frequency is None:
51
- raise ValueError('Must supply either bands or frequency to sample data points for an optical transient')
52
- if self.all_bands is not None and self.all_frequency is None:
53
- self.subset_bands = np.array(random.choices(self.all_bands, k=self.data_points))
54
- if self.all_bands is None and self.all_frequency is not None:
55
- self.subset_frequency = np.array(random.choices(self.all_frequency, k=self.data_points))
56
- self.replacement = True
57
- # allow times to be chosen repeatedly
52
+ self.all_bands = self.model_kwargs.get('bands', None)
53
+ self.all_frequency = self.model_kwargs.get('frequency', None)
54
+ if self.all_bands is None and self.all_frequency is None:
55
+ raise ValueError('Must supply either bands or frequency to sample data points for an optical transient')
58
56
  else:
59
- # allow times to be chosen only once.
60
- self.replacement = False
57
+ if multiwavelength_transient:
58
+ if self.all_bands is not None and self.all_frequency is None:
59
+ self.subset_bands = np.array(random.choices(self.all_bands, k=self.data_points))
60
+ if self.all_bands is None and self.all_frequency is not None:
61
+ self.subset_frequency = np.array(random.choices(self.all_frequency, k=self.data_points))
62
+ self.replacement = True
63
+ # allow times to be chosen repeatedly
64
+ else:
65
+ if self.all_bands is not None and self.all_frequency is None:
66
+ self.subset_bands = self.data_points * [self.all_bands]
67
+ if self.all_bands is None and self.all_frequency is not None:
68
+ self.subset_frequency = np.ones(self.data_points) * self.all_frequency
69
+ # allow times to be chosen only once.
70
+ self.replacement = False
61
71
  self.subset_times = np.sort(np.random.choice(self.all_times, size=self.data_points, replace=self.replacement))
62
72
 
63
73
  injection_kwargs = self.parameters.copy()
@@ -76,24 +86,43 @@ class SimulateGenericTransient(object):
76
86
  if 'frequency' in model_kwargs.keys():
77
87
  data['frequency'] = self.subset_frequency
78
88
  data['true_output'] = true_output
79
- data['output'] = np.random.normal(true_output, self.noise_term * true_output)
80
- data['output_error'] = self.noise_term * true_output
89
+
90
+ if noise_type == 'gaussianmodel':
91
+ noise = np.random.normal(0, self.noise_term * true_output, len(true_output))
92
+ output = true_output + noise
93
+ output_error = self.noise_term * true_output
94
+ elif noise_type == 'gaussian':
95
+ noise = np.random.normal(0, self.noise_term, len(true_output))
96
+ output = true_output + noise
97
+ output_error = self.noise_term
98
+ else:
99
+ logger.warning(f"noise_type {noise_type} not implemented.")
100
+ raise ValueError('noise_type must be either gaussianmodel or gaussian')
101
+
102
+ if extra_scatter > 0:
103
+ extra_noise = np.random.normal(0, extra_scatter, len(true_output))
104
+ output = output + extra_noise
105
+ output_error = np.sqrt(output_error**2 + extra_noise**2)
106
+
107
+ data['output'] = output
108
+ data['output_error'] = output_error
81
109
  self.data = data
82
110
 
83
- def save_transient(self, name):
84
- """
85
- Save the transient observations to a csv file.
86
- This will save the full observational dataframe including non-detections etc.
87
- This will save the data to a folder called 'simulated'
88
- with the name of the transient and a csv file of the injection parameters
89
-
90
- :param name: name to save transient.
91
- """
92
- bilby.utils.check_directory_exists_and_if_not_mkdir('simulated')
93
- path = 'simulated/' + name + '.csv'
94
- injection_path = 'simulated/' + name + '_injection_parameters.csv'
95
- self.observations.to_csv(path, index=False)
96
- self.parameters.to_csv(injection_path, index=False)
111
+ def save_transient(self, name):
112
+ """
113
+ Save the transient observations to a csv file.
114
+ This will save the full observational dataframe including non-detections etc.
115
+ This will save the data to a folder called 'simulated'
116
+ with the name of the transient and a csv file of the injection parameters
117
+
118
+ :param name: name to save transient.
119
+ """
120
+ bilby.utils.check_directory_exists_and_if_not_mkdir('simulated')
121
+ path = 'simulated/' + name + '.csv'
122
+ injection_path = 'simulated/' + name + '_injection_parameters.csv'
123
+ self.data.to_csv(path, index=False)
124
+ self.parameters=pd.DataFrame.from_dict([self.parameters])
125
+ self.parameters.to_csv(injection_path, index=False)
97
126
 
98
127
  class SimulateOpticalTransient(object):
99
128
  def __init__(self, model, parameters, pointings_database=None,
@@ -415,7 +444,7 @@ class SimulateOpticalTransient(object):
415
444
  Convert the circular field of view to a radius in radians.
416
445
  :return: survey_radius in radians
417
446
  """
418
- survey_fov_sqrad = self.survey_fov_sqdeg*(np.pi/180.0)
447
+ survey_fov_sqrad = self.survey_fov_sqdeg*(np.pi/180.0)**2
419
448
  survey_radius = np.sqrt(survey_fov_sqrad/np.pi)
420
449
  # survey_radius = np.sqrt(self.survey_fov_sqdeg*((np.pi/180.0)**2.0)/np.pi)
421
450
  return survey_radius
@@ -212,7 +212,7 @@ f2100w,1.443e+13,207950.05,black,1.122e-07,f2100w,MIRI/F2100W
212
212
  f2300c,1.325e+13,226446.44,black,9.225e-08,f2300c,MIRI/F2300C
213
213
  f2550w,1.183e+13,253640.02,black,6.601e-08,f2550w,MIRI/F2550W
214
214
  G,4.799e+14,6251.50,black,1.321e-05,gaia::G,Gaia/G
215
- gaia::G,4.799e+14,6251.50,black,1.321e-05,gaia::G,Gaia/G
215
+ gaia::g,4.799e+14,6251.50,black,1.321e-05,gaia::g,Gaia/G
216
216
  y',3.116e+14,9627.79,black,7.517e-07,ps1::y,PS1/y
217
217
  y,3.116e+14,9627.79,black,7.517e-07,ps1::y,PS1/y
218
218
  Y,3.116e+14,9627.79,black,7.517e-07,ps1::y,PS1/y
@@ -238,3 +238,17 @@ euclid::VIS,4.223e+14,7103.37,black,7.577e-06,euclid::VIS,EUCLID/VIS
238
238
  efosc2::g,5.866e+14,5114.66,black,3.302e-06,efosc2::g,EFOSC2/g
239
239
  efosc2::r,4.493e+14,6677.40,black,2.342e-06,efosc2::r,EFOSC2/r
240
240
  efosc2::i,3.758e+14,7983.20,black,2.435e-06,efosc2::i,EFOSC2/i
241
+ desg,6.2390e+14,4808.49,black,4.781e-06,desg,DES/g
242
+ desr,4.6746e+14,6417.65,black,3.409e-06,desr,DES/r
243
+ desi,3.8390e+14,7814.58,black,2.300e-06,desi,DES/i
244
+ desz,3.2719e+14,9168.85,black,1.679e-06,desz,DES/z
245
+ desy,3.0315e+14,9896.11,black,7.511e-07,desy,DES/y
246
+ tess,3.8973e+14,7697.6,black,7.658e-06,tess,TESS
247
+ gaia::gbp,5.8712e+14,5109.71,black,9.421e-06,gaia::gbp,GAIA/Gbp
248
+ gaia::g,4.799e+14,6217.59,black,1.278e-05,gaia::g,GAIA/G
249
+ gaia::grp,3.8615e+14,7769.02,black,5.472e-06,gaia::grp,GAIA/Grp
250
+ gaia::grvs,3.4970e+14,8578.76,black,3.481e-07,gaia::grvs,GAIA/Grvs
251
+ gotob,6.4895e+14,4622.88,black,3.771e-06,gotob,GOTO/B
252
+ gotog,5.5819e+14,5374.54,black,3.255e-06,gotog,GOTO/G
253
+ gotol,5.4311e+14,5523.78,black,8.027e-06,gotol,GOTO/L
254
+ gotor,4.6679e+14,6426.84,black,2.510e-06,gotor,GOTO/R
redback/tables/ztf.tar.gz CHANGED
Binary file
@@ -57,7 +57,7 @@ class Afterglow(Transient):
57
57
  :type flux: np.ndarray, optional
58
58
  :type flux_err: np.ndarray, optional
59
59
  :param flux_err: Flux error values.
60
- :param flux_density:Flux density values.
60
+ :param flux_density: Flux density values.
61
61
  :type flux_density: np.ndarray, optional
62
62
  :param flux_density_err: Flux density error values.
63
63
  :type flux_density_err: np.ndarray, optional
@@ -244,7 +244,8 @@ class Afterglow(Transient):
244
244
  'BAT Photon Index (15-150 keV) (PL = simple power-law, CPL = cutoff power-law)'].fillna(0)
245
245
  self.meta_data = meta_data
246
246
  except FileNotFoundError:
247
- logger.warning("Meta data does not exist for this event.")
247
+ logger.info("Metadata does not exist for this event.")
248
+ logger.info("Setting metadata to None. This is not an error, but a warning that no metadata could be found online.")
248
249
  self.meta_data = None
249
250
 
250
251
  def _set_photon_index(self) -> None:
@@ -50,7 +50,7 @@ class Kilonova(OpticalTransient):
50
50
  :type flux: np.ndarray, optional
51
51
  :type flux_err: np.ndarray, optional
52
52
  :param flux_err: Flux error values.
53
- :param flux_density:Flux density values.
53
+ :param flux_density: Flux density values.
54
54
  :type flux_density: np.ndarray, optional
55
55
  :param flux_density_err: Flux density error values.
56
56
  :type flux_density_err: np.ndarray, optional
@@ -45,7 +45,7 @@ class Supernova(OpticalTransient):
45
45
  :type flux: np.ndarray, optional
46
46
  :type flux_err: np.ndarray, optional
47
47
  :param flux_err: Flux error values.
48
- :param flux_density:Flux density values.
48
+ :param flux_density: Flux density values.
49
49
  :type flux_density: np.ndarray, optional
50
50
  :param flux_density_err: Flux density error values.
51
51
  :type flux_density_err: np.ndarray, optional
redback/transient/tde.py CHANGED
@@ -42,7 +42,7 @@ class TDE(OpticalTransient):
42
42
  :type flux: np.ndarray, optional
43
43
  :type flux_err: np.ndarray, optional
44
44
  :param flux_err: Flux error values.
45
- :param flux_density:Flux density values.
45
+ :param flux_density: Flux density values.
46
46
  :type flux_density: np.ndarray, optional
47
47
  :param flux_density_err: Flux density error values.
48
48
  :type flux_density_err: np.ndarray, optional
@@ -137,7 +137,7 @@ class Transient(object):
137
137
  self.system = system
138
138
  self.data_mode = data_mode
139
139
  self.active_bands = active_bands
140
- self.sncosmo_bands = redback.utils.sncosmo_bandname_from_band(self.bands, warning_style='soft')
140
+ self.sncosmo_bands = redback.utils.sncosmo_bandname_from_band(self.bands)
141
141
  self.redshift = redshift
142
142
  self.name = name
143
143
  self.use_phase_model = use_phase_model
@@ -906,7 +906,7 @@ class OpticalTransient(Transient):
906
906
  meta_data = pd.read_csv(self.event_table, on_bad_lines='skip', delimiter=',', dtype='str')
907
907
  except FileNotFoundError as e:
908
908
  redback.utils.logger.warning(e)
909
- redback.utils.logger.warning("Setting metadata to None")
909
+ redback.utils.logger.warning("Setting metadata to None. This is not an error, but a warning that no metadata could be found online.")
910
910
  meta_data = None
911
911
  self.meta_data = meta_data
912
912
 
@@ -2092,6 +2092,48 @@ def tophat(time, redshift, thv, loge0, thc, logn0, p, logepse, logepsb, ksin, g0
2092
2092
  elif kwargs['output_format'] == 'magnitude':
2093
2093
  return calc_ABmag_from_flux_density(flux_density).value
2094
2094
 
2095
+
2096
+ def tophat_from_emulator(time, redshift, thv, loge0, thc, logn0, p, logepse, logepsb, g0, **kwargs):
2097
+ """
2098
+ Evaluate a tophat afterglow model using an mpl regressor. Note that this model predicts for a fixed redshift = 0.01 and fixed ksin = 1.
2099
+ This tophat model does not include all of the ususal kwargs
2100
+
2101
+ :param time: time in days in observer frame, should be in range 0.1 to 300
2102
+ :param redshift: source redshift
2103
+ :param thv: viewing angle in radians
2104
+ :param loge0: log10 on axis isotropic equivalent energy
2105
+ :param thc: half width of jet core/jet opening angle in radians
2106
+ :param logn0: log10 number density of ISM in cm^-3
2107
+ :param p: electron distribution power law index. Must be greater than 2.
2108
+ :param logepse: log10 fraction of thermal energy in electrons
2109
+ :param logepsb: log10 fraction of thermal energy in magnetic field
2110
+ :param g0: initial lorentz factor
2111
+ :param kwargs: Additional keyword arguments
2112
+ :param frequency: frequency of the band to view in- single number or same length as time array
2113
+ :param output_format: Whether to output flux density or AB mag, specified by 'flux_density' or 'magnitude'
2114
+ :return: flux density or AB mag predicted by emulator. Note this is going to give the monochromatic magnitude at the effective frequency for the band.
2115
+ For a proper calculation of the magntitude use the sed variant models
2116
+ """
2117
+
2118
+ from redback_surrogates.afterglowmodels import tophat_emulator
2119
+
2120
+ z1=0.01
2121
+ z2= redshift
2122
+ frequency= np.log10(kwargs['frequency'])
2123
+ flux_density = tophat_emulator(new_time=time/(1+z2), thv=thv, loge0=loge0, thc=thc, logn0=logn0, p=p,
2124
+ logepse=logepse, logepsb=logepsb, g0=g0,frequency=frequency)
2125
+
2126
+ #scaling flux density with redshift
2127
+ dl1 = cosmo.luminosity_distance(z1)
2128
+ dl2 = cosmo.luminosity_distance(z2)
2129
+ scale_factor = ((dl1**2)*(1+z1)) / (dl2**2)
2130
+ flux_density=flux_density*scale_factor
2131
+
2132
+ if kwargs['output_format'] == 'flux_density':
2133
+ return flux_density
2134
+ elif kwargs['output_format'] == 'magnitude':
2135
+ return calc_ABmag_from_flux_density(flux_density).value
2136
+
2095
2137
  @citation_wrapper('https://ui.adsabs.harvard.edu/abs/2020ApJ...896..166R/abstract')
2096
2138
  def afterglow_models_with_energy_injection(time, **kwargs):
2097
2139
  """
@@ -1,5 +1,9 @@
1
- import redback.transient_models.extinction_models
2
- def tophat_and_twolayerstratified(time, redshift, av, thv, loge0, thc, logn0, p, logepse, logepsb, ksin, g0, mej, vej_1, vej_2, kappa, beta, **kwargs):
1
+ import redback.transient_models.extinction_models as em
2
+ from redback.utils import citation_wrapper
3
+
4
+ @citation_wrapper('https://ui.adsabs.harvard.edu/abs/2020ApJ...896..166R/abstract, https://ui.adsabs.harvard.edu/abs/2020ApJ...891..152H/abstract')
5
+ def tophat_and_twolayerstratified(time, redshift, av, thv, loge0, thc, logn0, p, logepse,
6
+ logepsb, ksin, g0, mej, vej_1, vej_2, kappa, beta, **kwargs):
3
7
 
4
8
  """
5
9
  function to combine the flux density signals of a tophat afterglow and a two layer stratified kilonova with extinction
@@ -36,18 +40,20 @@ def tophat_and_twolayerstratified(time, redshift, av, thv, loge0, thc, logn0, p,
36
40
  """
37
41
  kwargs['output_format']='flux_density'
38
42
  kwargs['base_model']='tophat'
39
- afterglow = redback.transient_models.extinction_models.extinction_with_afterglow_base_model(time=time, redshift=redshift, av=av,
43
+ afterglow = em.extinction_with_afterglow_base_model(time=time, redshift=redshift, av=av,
40
44
  thv=thv, loge0=loge0 , thc= thc, logn0=logn0, p=p, logepse=logepse, logepsb=logepsb, ksin=ksin, g0=g0,
41
45
  **kwargs)
42
46
  kwargs['base_model']='two_layer_stratified_kilonova'
43
- kilonova = redback.transient_models.extinction_models.extinction_with_kilonova_base_model(time=time, redshift=redshift, av=av,
47
+ kilonova = em.extinction_with_kilonova_base_model(time=time, redshift=redshift, av=av,
44
48
  mej=mej, vej_1=vej_1, vej_2=vej_2, kappa=kappa, beta=beta, **kwargs)
45
49
 
46
50
  combined = afterglow+kilonova
47
51
  return combined
48
52
 
49
-
50
- def tophat_and_twocomponent(time, redshift, av, thv, loge0, thc, logn0, p, logepse, logepsb, ksin, g0, mej_1, vej_1, temperature_floor_1, kappa_1, mej_2, vej_2, temperature_floor_2, kappa_2, **kwargs):
53
+ @citation_wrapper('https://ui.adsabs.harvard.edu/abs/2020ApJ...896..166R/abstract, redback')
54
+ def tophat_and_twocomponent(time, redshift, av, thv, loge0, thc, logn0,
55
+ p, logepse, logepsb, ksin, g0, mej_1, vej_1,
56
+ temperature_floor_1, kappa_1, mej_2, vej_2, temperature_floor_2, kappa_2, **kwargs):
51
57
 
52
58
  """
53
59
  function to combine the flux density signals of a tophat afterglow and a two component kilonova with extinction added
@@ -85,19 +91,21 @@ def tophat_and_twocomponent(time, redshift, av, thv, loge0, thc, logn0, p, logep
85
91
  :return: flux density signal with extinction added
86
92
  """
87
93
 
88
- kwargs['output_format']='flux_density'
89
- kwargs['base_model']='tophat'
90
- afterglow = redback.transient_models.extinction_models.extinction_with_afterglow_base_model(time=time, redshift=redshift, av=av,
91
- thv=thv, loge0=loge0 , thc= thc, logn0=logn0, p=p, logepse=logepse, logepsb=logepsb, ksin=ksin, g0=g0,
92
- **kwargs)
93
- kwargs['base_model']='two_component_kilonova_model'
94
- kilonova = redback.transient_models.extinction_models.extinction_with_kilonova_base_model(time=time, redshift=redshift, av=av,
95
- mej_1=mej_1, vej_1=vej_2, temperature_floor_1=temperature_floor_1, kappa_1=kappa_1, mej_2=mej_2, vej_2=vej_2, temperature_floor_2=temperature_floor_2, kappa_2=kappa_2, **kwargs)
94
+ kwargs['output_format'] = 'flux_density'
95
+ kwargs['base_model'] = 'tophat'
96
+ afterglow = em.extinction_with_afterglow_base_model(time=time, redshift=redshift, av=av,
97
+ thv=thv, loge0=loge0, thc=thc, logn0=logn0, p=p, logepse=logepse, logepsb=logepsb, ksin=ksin, g0=g0,**kwargs)
98
+
99
+ kwargs['base_model'] = 'two_component_kilonova_model'
100
+ kilonova = em.extinction_with_kilonova_base_model(time=time, redshift=redshift, av=av,
101
+ mej_1=mej_1, vej_1=vej_1, temperature_floor_1=temperature_floor_1,
102
+ kappa_1=kappa_1, mej_2=mej_2, vej_2=vej_2,
103
+ temperature_floor_2=temperature_floor_2, kappa_2=kappa_2, **kwargs)
96
104
 
97
105
  combined = afterglow + kilonova
98
106
  return combined
99
107
 
100
-
108
+ @citation_wrapper('https://ui.adsabs.harvard.edu/abs/2020ApJ...896..166R/abstract, https://ui.adsabs.harvard.edu/abs/1982ApJ...253..785A/abstract')
101
109
  def tophat_and_arnett(time, av, redshift, thv, loge0, thc, logn0, p, logepse, logepsb, ksin, g0, f_nickel, mej, **kwargs):
102
110
 
103
111
  """
@@ -137,19 +145,20 @@ def tophat_and_arnett(time, av, redshift, thv, loge0, thc, logn0, p, logepse, lo
137
145
  :return: flux density with extinction added
138
146
  """
139
147
 
140
- kwargs['output_format']='flux_density'
141
- kwargs['base_model']='tophat'
142
- afterglow = redback.transient_models.extinction_models.extinction_with_afterglow_base_model(time=time, redshift=redshift, av=av,
143
- thv=thv, loge0=loge0 , thc= thc, logn0=logn0, p=p, logepse=logepse, logepsb=logepsb, ksin=ksin, g0=g0,
148
+ kwargs['output_format'] = 'flux_density'
149
+ kwargs['base_model'] = 'tophat'
150
+ afterglow = em.extinction_with_afterglow_base_model(time=time, redshift=redshift, av=av,
151
+ thv=thv, loge0=loge0, thc=thc, logn0=logn0, p=p, logepse=logepse, logepsb=logepsb, ksin=ksin, g0=g0,
144
152
  **kwargs)
145
- kwargs['base_model']='arnett'
146
- supernova = redback.transient_models.extinction_models.extinction_with_supernova_base_model(time=time, redshift=redshift, av=av,
153
+ kwargs['base_model'] = 'arnett'
154
+ supernova = em.extinction_with_supernova_base_model(time=time, redshift=redshift, av=av,
147
155
  f_nickel=f_nickel, mej=mej, **kwargs)
148
156
 
149
157
  combined = afterglow + supernova
150
158
  return combined
151
159
 
152
- def afterglow_and_optical(time, redshift, av, model_type, afterglow_kwargs, optical_kwargs, **shared_kwargs):
160
+ @citation_wrapper('redback, and any citations for the specific model you use')
161
+ def afterglow_and_optical(time, redshift, av, **model_kwargs):
153
162
 
154
163
  """
155
164
  function to combine the signals of any afterglow and any other optical transient with extinction added
@@ -157,26 +166,32 @@ def afterglow_and_optical(time, redshift, av, model_type, afterglow_kwargs, opti
157
166
  :param time: time in days in observer frame
158
167
  :param redshift: source redshift
159
168
  :param av: absolute mag extinction
169
+ :param model_kwargs: kwargs shared by models e.g. output_format, frequency, bands, r_v (extinction paramater defaults to 3.1)
160
170
  :param model_type: specify type of optical transient model- 'supernova', 'tde', 'kilonova', 'magnetar_driven', 'shock_powered'
161
171
  :param afterglow_kwargs: dictionary of parameters required by the afterglow transient model specified by 'base_model'
162
172
  and any additional keyword arguments. Refer to model documentation for details.
163
173
  :param optical_kwargs: dictionary of parameters required by the optical transient model specifed by 'base_model'
164
174
  and any additional keyword arguments. Note the base model must correspond to the given model type. Refer to model documentation
165
175
  for details.
166
- :param shared_kwargs: kwargs shared by models e.g. output_format, frequency, bands, r_v (extinction paramater defaults to 3.1)
167
176
  :return: set by shared_kwargs output format - 'flux_density' or 'magnitude' with extinction added
168
177
  note that only afterglow_models_sed allow for magnitude outputs
169
178
  """
179
+
180
+ optical_kwargs = model_kwargs['optical_kwargs']
181
+ afterglow_kwargs = model_kwargs['afterglow_kwargs']
182
+
183
+ _afterglow_kwargs = afterglow_kwargs.copy()
184
+ _afterglow_kwargs.update(model_kwargs)
185
+ _afterglow_kwargs.pop('model_type')
186
+
187
+ _optical_kwargs = optical_kwargs.copy()
188
+ _optical_kwargs.update(model_kwargs)
189
+
190
+ afterglow = em._evaluate_extinction_model(time=time, redshift=redshift, av=av,model_type='afterglow',
191
+ **_afterglow_kwargs)
170
192
 
171
- afterglow_kwargs.update(shared_kwargs)
172
- optical_kwargs.update(shared_kwargs)
173
-
174
- afterglow = redback.transient_models.extinction_models._evaluate_extinction_model(time=time, redshift=redshift, av=av,
175
- model_type='afterglow', **afterglow_kwargs)
176
-
177
- optical= redback.transient_models.extinction_models._evaluate_extinction_model(time=time, redshift=redshift, av=av,
178
- model_type=model_type, **optical_kwargs)
179
-
193
+ optical = em._evaluate_extinction_model(time=time, redshift=redshift, av=av, **_optical_kwargs)
194
+
180
195
  combined= afterglow + optical
181
196
  return combined
182
197