ler 0.4.1__py3-none-any.whl → 0.4.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.

Potentially problematic release.


This version of ler might be problematic. Click here for more details.

Files changed (35) hide show
  1. ler/__init__.py +26 -26
  2. ler/gw_source_population/__init__.py +1 -0
  3. ler/gw_source_population/cbc_source_parameter_distribution.py +1076 -818
  4. ler/gw_source_population/cbc_source_redshift_distribution.py +619 -295
  5. ler/gw_source_population/jit_functions.py +484 -9
  6. ler/gw_source_population/sfr_with_time_delay.py +107 -0
  7. ler/image_properties/image_properties.py +44 -13
  8. ler/image_properties/multiprocessing_routine.py +5 -209
  9. ler/lens_galaxy_population/__init__.py +2 -0
  10. ler/lens_galaxy_population/epl_shear_cross_section.py +0 -0
  11. ler/lens_galaxy_population/jit_functions.py +101 -9
  12. ler/lens_galaxy_population/lens_galaxy_parameter_distribution.py +817 -885
  13. ler/lens_galaxy_population/lens_param_data/density_profile_slope_sl.txt +5000 -0
  14. ler/lens_galaxy_population/lens_param_data/external_shear_sl.txt +2 -0
  15. ler/lens_galaxy_population/lens_param_data/number_density_zl_zs.txt +48 -0
  16. ler/lens_galaxy_population/lens_param_data/optical_depth_epl_shear_vd_ewoud.txt +48 -0
  17. ler/lens_galaxy_population/mp copy.py +554 -0
  18. ler/lens_galaxy_population/mp.py +736 -138
  19. ler/lens_galaxy_population/optical_depth.py +2248 -616
  20. ler/rates/__init__.py +1 -2
  21. ler/rates/gwrates.py +129 -75
  22. ler/rates/ler.py +257 -116
  23. ler/utils/__init__.py +2 -0
  24. ler/utils/function_interpolation.py +322 -0
  25. ler/utils/gwsnr_training_data_generator.py +233 -0
  26. ler/utils/plots.py +1 -1
  27. ler/utils/test.py +1078 -0
  28. ler/utils/utils.py +553 -125
  29. {ler-0.4.1.dist-info → ler-0.4.3.dist-info}/METADATA +22 -9
  30. ler-0.4.3.dist-info/RECORD +34 -0
  31. {ler-0.4.1.dist-info → ler-0.4.3.dist-info}/WHEEL +1 -1
  32. ler/rates/ler copy.py +0 -2097
  33. ler-0.4.1.dist-info/RECORD +0 -25
  34. {ler-0.4.1.dist-info → ler-0.4.3.dist-info/licenses}/LICENSE +0 -0
  35. {ler-0.4.1.dist-info → ler-0.4.3.dist-info}/top_level.txt +0 -0
@@ -11,21 +11,21 @@ import warnings
11
11
  warnings.filterwarnings("ignore")
12
12
 
13
13
  import numpy as np
14
- from numba import njit
15
-
16
- # from gwcosmo import priors as p
17
- from scipy.integrate import quad
14
+ from multiprocessing import Pool
15
+ from tqdm import tqdm
16
+ from scipy.interpolate import CubicSpline
18
17
 
19
18
  # for redshift to luminosity distance conversion
20
19
  from astropy.cosmology import LambdaCDM
21
20
 
22
- from ..utils import interpolator_from_pickle, cubic_spline_interpolator, inverse_transform_sampler
23
- from .jit_functions import merger_rate_density_bbh_popI_II_oguri2018, star_formation_rate_madau_dickinson2014, merger_rate_density_bbh_popIII_ken2022, merger_rate_density_bbh_primordial_ken2022
21
+ from ..utils import FunctionConditioning, interpolator_pickle_path
22
+ from .jit_functions import merger_rate_density_bbh_popI_II_oguri2018, sfr_madau_dickinson2014, merger_rate_density_bbh_popIII_ken2022, merger_rate_density_bbh_primordial_ken2022
23
+ from .sfr_with_time_delay import sfr_with_time_delay
24
24
 
25
25
 
26
26
  class CBCSourceRedshiftDistribution(object):
27
27
  """Class to generate a population of source galaxies.
28
- This class is inherited by :class:`~ler.ler.CompactBinaryPopulation` and :class:`~ler.ler.LensGalaxyParameterDistribution` class.
28
+ This class is inherited by :class:`~ler.ler.CBCSourceParameterDistribution` and :class:`~ler.ler.LensGalaxyParameterDistribution` class.
29
29
 
30
30
  Parameters
31
31
  ----------
@@ -47,7 +47,7 @@ class CBCSourceRedshiftDistribution(object):
47
47
  for others see instance method in :class:`~ler.ler.merger_rate_density_model_list`
48
48
  merger_rate_density_param : `dict`
49
49
  Dictionary of merger rate density function parameters
50
- default: None/dict(R0=25 * 1e-9, b2=1.6, b3=2.0, b4=30)
50
+ default: None/dict(R0=25 * 1e-9, b2=1.6, b3=2.1, b4=30)
51
51
  directory : `str`
52
52
  Directory to store the interpolator pickle files
53
53
  default: './interpolator_pickle'
@@ -71,6 +71,8 @@ class CBCSourceRedshiftDistribution(object):
71
71
  +-------------------------------------+----------------------------------+
72
72
  |:attr:`~z_max` | `float` |
73
73
  +-------------------------------------+----------------------------------+
74
+ |:attr:`~directory` | `str` |
75
+ +-------------------------------------+----------------------------------+
74
76
  |:attr:`~event_type` | `str` |
75
77
  +-------------------------------------+----------------------------------+
76
78
  |:attr:`~cosmo` | `astropy.cosmology` |
@@ -85,26 +87,23 @@ class CBCSourceRedshiftDistribution(object):
85
87
  | | merger rate density functions |
86
88
  | | and its parameters |
87
89
  +-------------------------------------+----------------------------------+
88
- |:attr:`~sample_source_redshift` | Function to sample source |
89
- | | redshifts |
90
+ |:attr:`~merger_rate_density` | `class object` |
91
+ +-------------------------------------+----------------------------------+
92
+ |:attr:`~source_redshift` | `class object` |
93
+ +-------------------------------------+----------------------------------+
94
+ |:attr:`~luminosity_distance` | `class object` |
95
+ +-------------------------------------+----------------------------------+
96
+ |:attr:`~differential_comoving_volume`| `class object` |
90
97
  +-------------------------------------+----------------------------------+
91
98
 
99
+
92
100
  Instance Methods
93
101
  ----------
94
102
  SourceGalaxyPopulationModel has the following instance methods:\n
95
103
  +-------------------------------------+----------------------------------+
96
104
  | Methods | Type |
97
105
  +=====================================+==================================+
98
- |:attr:`~merger_rate_density` | `function` |
99
- +-------------------------------------+----------------------------------+
100
- |:attr:`~z_to_luminosity_distance` | `function` |
101
- +-------------------------------------+----------------------------------+
102
- |:attr:`~differential_comoving_volume`| `function` |
103
- +-------------------------------------+----------------------------------+
104
- |:meth:`~pdf_z` | Function to compute the pdf |
105
- | | p(z) |
106
- +-------------------------------------+----------------------------------+
107
- |:meth:`~merger_rate_density_detector_frame` |
106
+ |:meth:`~merger_rate_density_detector_frame` |
108
107
  +-------------------------------------+----------------------------------+
109
108
  | | Function to compute the merger |
110
109
  | | rate density (detector frame) |
@@ -120,7 +119,7 @@ class CBCSourceRedshiftDistribution(object):
120
119
  | | rate density (PopI/PopII) |
121
120
  | | from Oguri et al. (2018) |
122
121
  +-------------------------------------+----------------------------------+
123
- |:meth:`~star_formation_rate_madau_dickinson2014` |
122
+ |:meth:`~sfr_madau_dickinson2014` |
124
123
  +-------------------------------------+----------------------------------+
125
124
  | | Function to compute star |
126
125
  | | formation rate as given in |
@@ -167,9 +166,9 @@ class CBCSourceRedshiftDistribution(object):
167
166
  Dictionary of merger rate density function input parameters
168
167
  """
169
168
 
170
- c_n_i = None
169
+ create_new_interpolator = None
171
170
  """``dict`` \n
172
- c_n_i stands for 'create new interpolator'. Dictionary of interpolator creation parameters. \n
171
+ Dictionary of interpolator creation parameters. \n
173
172
  e.g. dict(redshift_distribution=dict(create_new=False, resolution=1000), z_to_luminosity_distance=dict(create_new=False, resolution=1000), differential_comoving_volume=dict(create_new=False, resolution=1000))
174
173
  """
175
174
 
@@ -178,130 +177,167 @@ class CBCSourceRedshiftDistribution(object):
178
177
  Normalization constant of the pdf p(z)
179
178
  """
180
179
 
181
- z_to_luminosity_distance = None
182
- """``scipy.interpolate.interpolate`` \n
183
- Function to convert redshift to luminosity distance
184
- """
185
-
186
- differential_comoving_volume = None
187
- """``scipy.interpolate.interpolate`` \n
188
- Function to calculate the differential comoving volume
189
- """
190
-
191
180
  def __init__(
192
181
  self,
182
+ npool=4,
193
183
  z_min=0.001,
194
184
  z_max=10.0,
195
185
  event_type="BBH",
196
- merger_rate_density="merger_rate_density_bbh_popI_II_oguri2018",
186
+ merger_rate_density=None,
197
187
  merger_rate_density_param=None,
198
188
  cosmology=None,
199
189
  directory="./interpolator_pickle",
200
190
  create_new_interpolator=False,
201
191
  ):
192
+ print("\nInitializing CBCSourceRedshiftDistribution...\n")
202
193
  # set attributes
194
+ self.npool = npool
203
195
  self.z_min = z_min
204
196
  self.z_max = z_max
197
+ self.directory = directory
205
198
  self.event_type = event_type
206
199
  # if None is passed, use the default cosmology
207
200
  self.cosmo = cosmology if cosmology else LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
201
+
208
202
  # setting up the interpolator creation parameters
209
- self.c_n_i = dict(
210
- redshift_distribution=dict(create_new=False, resolution=1000), z_to_luminosity_distance=dict(create_new=False, resolution=1000), differential_comoving_volume=dict(create_new=False, resolution=1000))
211
- if create_new_interpolator:
212
- self.c_n_i.update(create_new_interpolator)
203
+ self.create_new_interpolator = self.setup_decision_dictionary(create_new_interpolator, merger_rate_density)
204
+
213
205
  # creating of interpolators for redshift dependent quantities
214
- self.create_lookup_table(z_min, z_max, directory)
215
-
216
- # Define the merger-rate density function/method instances
217
- # self.merger_rate_density takes function or function name as input
218
- self.merger_rate_density = merger_rate_density # function initialization
219
- # if None is passed, use the default merger_rate_density_param
220
- if merger_rate_density_param is None and merger_rate_density== "merger_rate_density_bbh_popI_II_oguri2018":
221
- if self.event_type == "BBH":
222
- R0 = 23.9 * 1e-9
223
- elif self.event_type == "BNS":
224
- R0 = 105.5 * 1e-9
225
- elif self.event_type == "NSBH":
226
- R0 = 45.0 * 1e-9
227
- else:
228
- raise ValueError("event_type must be one of 'BBH', 'BNS', 'NSBH'")
229
- merger_rate_density_param = dict(R0=R0, b2=1.6, b3=2.0, b4=30)
230
- self.merger_rate_density_param = merger_rate_density_param
231
-
232
-
233
- # To find the normalization constant of the pdf p(z)
234
- # merger_rate_density_detector_frame is njit function and takes array as input but quad integrand function takes only float as input
235
- merger_rate_density_detector_frame = lambda z: self.merger_rate_density_detector_frame(zs=np.array([z]), param=merger_rate_density_param)[0]
236
- # this normalization is important to find the correct pdf p(z)
237
- self.normalization_pdf_z = quad(
238
- merger_rate_density_detector_frame,
239
- z_min,
240
- z_max
241
- )[0]
242
-
243
- # generate inverse cdf for inverse transform sampling
244
- # create sampler using the pdf p(z)
245
- resolution = self.c_n_i["redshift_distribution"]["resolution"]
246
- create_new = self.c_n_i["redshift_distribution"]["create_new"]
247
-
248
- # if callable(merger_rate_density):
249
- # merger_rate_density_name = merger_rate_density.__name__
250
- # else:
251
- # merger_rate_density_name = merger_rate_density
252
-
253
- zs_inv_cdf = interpolator_from_pickle(
254
- param_dict_given= dict(z_min=z_min,
255
- z_max=z_max,
256
- cosmology=self.cosmo,
257
- event_type=event_type,
258
- merger_rate_density=str(merger_rate_density),
259
- merger_rate_density_param=str(merger_rate_density_param),
260
- resolution=resolution,
261
- ),
262
- directory=directory,
263
- sub_directory="merger_rate_density",
264
- name="merger_rate_density",
265
- x = np.linspace(z_min, z_max, resolution),
266
- pdf_func= lambda z_: self.pdf_z(zs=z_, param=merger_rate_density_param),
267
- conditioned_y=None,
268
- dimension=1,
269
- category="inv_cdf",
270
- create_new=create_new,
271
- )
272
-
273
- # redshift sampler using inverse transform sampling
274
- self.sample_source_redshift = njit( lambda size, param=None: inverse_transform_sampler(size, zs_inv_cdf[0], zs_inv_cdf[1]) )
275
-
276
- def pdf_z(self, zs, param=None):
206
+ self.create_lookup_table()
207
+
208
+ # function initialization
209
+ merger_rate_density, self.merger_rate_density_param = self.merger_rate_density_priors_categorization(event_type, merger_rate_density, merger_rate_density_param)
210
+ self.merger_rate_density = merger_rate_density # this is an initialization, not a variable assignment
211
+
212
+ # source redshift distribution initialization
213
+ self.merger_rate_density_detector_frame = self.merger_rate_density_detector_frame(zs=None, get_attribute=True)
214
+ self.source_redshift = self.merger_rate_density_detector_frame.rvs
215
+ self.normalization_pdf_z = self.merger_rate_density_detector_frame.pdf_norm_const
216
+
217
+
218
+ def setup_decision_dictionary(self, create_new_interpolator, merger_rate_density):
277
219
  """
278
- Function to compute the pdf p(z). The output is in detector frame and is normalized.
220
+ Method to set up a decision dictionary for interpolator creation.
279
221
 
280
222
  Parameters
281
223
  ----------
282
- zs : `float` or `numpy.ndarray` (1D array of floats)
283
- Source redshifts
284
- param : `dict`
285
- Allows to pass in above parameters as dict.
286
- e.g. if the merger_rate_density is merger_rate_density_bbh_popI_II_oguri2018
287
- param = dict(R0=23.9*1e-9, b2=1.6, b3=2.0, b4=30)
224
+ create_new_interpolator : `dict`, `bool`
225
+ If `dict`, dictionary of boolean values and resolution to create new interpolator.
226
+ If `bool`, boolean value to create new interpolator for all quantities.
288
227
 
289
228
  Returns
290
- ----------
291
- pdf : `numpy.ndarray`
292
- 1D array of floats
293
- pdf p(z)
229
+ -------
230
+ create_new_interpolator_ : `dict`
231
+ Dictionary of boolean values and resolution to create new interpolator.
232
+ e.g. dict(redshift_distribution=dict(create_new=False, resolution=1000), luminosity_distance=dict(create_new=False, resolution=1000), differential_comoving_volume=dict(create_new=False, resolution=1000))
233
+ """
234
+ create_new_interpolator_ = dict(
235
+ merger_rate_density=dict(create_new=False, resolution=500),
236
+ redshift_distribution=dict(create_new=False, resolution=500),
237
+ luminosity_distance=dict(create_new=False, resolution=500),
238
+ differential_comoving_volume=dict(create_new=False, resolution=500),
239
+ )
240
+
241
+ if isinstance(create_new_interpolator, dict):
242
+ create_new_interpolator_.update(create_new_interpolator)
243
+ elif create_new_interpolator is True:
244
+ for key in create_new_interpolator_:
245
+ create_new_interpolator_[key]["create_new"] = True
294
246
 
295
- Examples
247
+ if isinstance(merger_rate_density, str):
248
+ if merger_rate_density=="sfr_with_td":
249
+ create_new_interpolator_["merger_rate_density"]["resolution"] = 48
250
+
251
+ return create_new_interpolator_
252
+
253
+ def merger_rate_density_priors_categorization(self, event_type, merger_rate_density, merger_rate_density_param):
254
+ """
255
+ Function to categorize the merger rate density and its parameters.
256
+
257
+ Parameters
296
258
  ----------
297
- >>> from ler.gw_source_population import SourceGalaxyPopulationModel
298
- >>> cbc = SourceGalaxyPopulationModel()
299
- >>> pdf = cbc.pdf_z(zs=0.1)
259
+ event_type : `str`
260
+ Type of event to generate.
261
+ e.g. 'BBH', 'BNS', 'BBH_popIII', 'BBH_primordial', 'NSBH'
262
+ merger_rate_density : `str` or `callable`
263
+ Merger rate density function name or function itself.
264
+ If `str`, it must be one of the available merger rate density functions.
265
+ If `callable`, it must accept a single argument, the redshift.
266
+ merger_rate_density_param : `dict`
267
+ Dictionary of merger rate density function parameters.
268
+ If `None`, use the default parameters for the chosen merger rate density function.
269
+ If not `None`, must contain the following parameters:
270
+ R0 : `float`
271
+ Normalization constant of the merger rate density.
272
+ b2 : `float`
273
+ Power law exponent of the merger rate density.
274
+ b3 : `float`
275
+ Power law exponent of the merger rate density.
276
+ b4 : `float`
277
+ Power law exponent of the merger rate density.
278
+
279
+ Returns
280
+ -------
281
+ merger_rate_density_ : `str` or `callable`
282
+ Merger rate density function name or function itself.
283
+ merger_rate_density_param_ : `dict`
284
+ Dictionary of merger rate density function parameters.
285
+
286
+ Notes
287
+ -----
288
+ If `merger_rate_density` is a string, it must be one of the available merger rate density functions.
289
+ If `merger_rate_density` is a callable, it must accept a single argument, the redshift.
290
+ If `merger_rate_density_param` is `None`, use the default parameters for the chosen merger rate density function.
291
+ If `merger_rate_density_param` is not `None`, it must contain the following parameters: R0, b2, b3, b4.
300
292
  """
301
293
 
302
- return self.merger_rate_density_detector_frame(zs=zs,param=param)/self.normalization_pdf_z
294
+ # update the merger rate density and its parameters with user provided values
295
+ if isinstance(merger_rate_density, str):
296
+ if merger_rate_density in self.merger_rate_density_model_list:
297
+ merger_rate_density_ = merger_rate_density
298
+ # you can't provide merger_rate_density_param and not merger_rate_density
299
+ merger_rate_density_param_ = self.merger_rate_density_model_list[merger_rate_density]
300
+ else:
301
+ raise ValueError(f"'merger rate density' sampler '{merger_rate_density}' not available.\n Available 'merger rate density' samplers and its parameters are: {self.merger_rate_density_model_list}")
302
+ elif callable(merger_rate_density):
303
+ print("using user provided custom merger rate density function")
304
+ merger_rate_density_ = merger_rate_density
305
+ else:
306
+ merger_rate_density_ = "merger_rate_density_bbh_popI_II_oguri2018"
307
+
308
+ # Oguri et al. (2018) merger rate density
309
+ if merger_rate_density_ == "merger_rate_density_bbh_popI_II_oguri2018":
310
+ if event_type == "BBH":
311
+ merger_rate_density_param_ = dict(R0=23.9 * 1e-9, b2=1.6, b3=2.1, b4=30)
312
+ elif event_type == "BNS":
313
+ merger_rate_density_param_ = dict(R0=105.5 * 1e-9, b2=1.6, b3=2.1, b4=30)
314
+ elif event_type == "NSBH":
315
+ merger_rate_density_param_ = dict(R0=45.0 * 1e-9, b2=1.6, b3=2.1, b4=30)
316
+ else:
317
+ raise ValueError("event_type must be 'BBH', 'BNS' or 'NSBH'")
318
+
319
+ # merger rate with time delay; Borhanian & Sathyaprakash (2024)
320
+ list_ = ['sfr_with_td',
321
+ #'sfr_madau_fragos2017_with_bbh_dt',
322
+ # 'sfr_madau_dickinson2014_with_bbh_dt',
323
+ # 'sfr_madau_fragos2017_with_bns_dt',
324
+ # 'sfr_madau_dickinson2014_with_bns_dt'
325
+ ]
326
+ if merger_rate_density_ in list_:
327
+ if event_type == "BBH":
328
+ merger_rate_density_param_ = dict(R0=23.9 * 1e-9, a=0.01, b=2.6, c=3.2, d=6.2, td_min=10e-3, td_max=10.0)
329
+ elif event_type == "BNS":
330
+ merger_rate_density_param_ = dict(R0=105.5 * 1e-9, a=0.01, b=2.6, c=3.2, d=6.2, td_min=20e-3, td_max=10.0)
331
+ else:
332
+ raise ValueError("event_type must be 'BBH', 'BNS'")
333
+
334
+ # if callable(merger_rate_density), below code will not matter
335
+ if isinstance(merger_rate_density_param, dict): # merger_rate_density_param is user provided
336
+ merger_rate_density_param_.update(merger_rate_density_param)
337
+
338
+ return merger_rate_density_, merger_rate_density_param_
303
339
 
304
- def merger_rate_density_detector_frame(self, zs, param=None):
340
+ def merger_rate_density_detector_frame(self, zs, get_attribute=False, **kwargs):
305
341
  """
306
342
  Function to compute the merger rate density (detector frame). The output is in detector frame and is unnormalized.
307
343
 
@@ -312,7 +348,7 @@ class CBCSourceRedshiftDistribution(object):
312
348
  param : `dict`
313
349
  Allows to pass in above parameters as dict.
314
350
  e.g. if the merger_rate_density is merger_rate_density_bbh_popI_II_oguri2018
315
- param = dict(R0=23.9*1e-9, b2=1.6, b3=2.0, b4=30)
351
+ param = dict(R0=23.9*1e-9, b2=1.6, b3=2.1, b4=30)
316
352
 
317
353
  Returns
318
354
  ----------
@@ -327,19 +363,38 @@ class CBCSourceRedshiftDistribution(object):
327
363
  >>> rate_density = cbc.merger_rate_density_detector_frame(zs=0.1)
328
364
  """
329
365
 
330
- zs = np.array([zs]).reshape(-1)
331
- # Define the merger-rate density function
332
- rate_density = (
333
- self.merger_rate_density(zs, param=param)
334
- / (1 + zs)
335
- * (self.differential_comoving_volume(zs))
366
+ identifier_dict = self.merger_rate_density_param.copy()
367
+ identifier_dict['z_min'] = self.z_min
368
+ identifier_dict['z_max'] = self.z_max
369
+ identifier_dict['cosmology'] = self.cosmo
370
+ identifier_dict['event_type'] = self.event_type
371
+ identifier_dict['name'] = "merger_rate_density_detector_frame"
372
+ identifier_dict['resolution'] = self.create_new_interpolator["merger_rate_density"]["resolution"]
373
+
374
+ zs = np.linspace(identifier_dict['z_min'], identifier_dict['z_max'], identifier_dict['resolution'])
375
+ Pzs = lambda z: self.merger_rate_density(z)/(1+z) * self.differential_comoving_volume(z)
376
+
377
+ Pzs_object = FunctionConditioning(
378
+ function=Pzs,
379
+ x_array=zs,
380
+ param_dict_given=identifier_dict,
381
+ directory=self.directory,
382
+ sub_directory="merger_rate_density",
383
+ name=identifier_dict['name'],
384
+ create_new=self.create_new_interpolator["merger_rate_density"]["create_new"],
385
+ create_function_inverse=False,
386
+ create_function=True,
387
+ create_pdf=True,
388
+ create_rvs=True,
389
+ callback='function',
336
390
  )
337
391
 
338
- return rate_density
392
+ if get_attribute:
393
+ return Pzs_object
394
+ else:
395
+ return Pzs_object(zs)
339
396
 
340
- def merger_rate_density_bbh_popI_II_oguri2018(self,
341
- zs, R0=23.9 * 1e-9, b2=1.6, b3=2.0, b4=30, param=None
342
- ):
397
+ def merger_rate_density_bbh_popI_II_oguri2018(self, zs, get_attribute=False, **kwargs):
343
398
  """
344
399
  Function to compute the merger rate density (PopI/PopII). Reference: Oguri et al. (2018). The output is in source frame and is unnormalized.
345
400
 
@@ -347,27 +402,18 @@ class CBCSourceRedshiftDistribution(object):
347
402
  ----------
348
403
  zs : `float` or `numpy.ndarray` (nD array of floats)
349
404
  Source redshifts
350
- R0 : `float`
351
- local merger rate density at low redshift
352
- default: 23.9*1e-9 Mpc^-3 yr^-1
353
- b2 : `float`
354
- Fitting paramters
355
- default: 1.6
356
- b3 : `float`
357
- Fitting paramters
358
- default: 2.0
359
- b4 : `float`
360
- Fitting paramters
361
- default: 30
362
- param : `dict`
363
- Allows to pass in above parameters as dict.
364
- e.g. param = dict(R0=23.9*1e-9, b2=1.6, b3=2.0, b4=30)
365
- default: None
405
+ get_attribute : `bool`
406
+ If True, returns the merger rate density function instead of the value
407
+ default: False
408
+ kwargs : `dict`
409
+ Dictionary of merger rate density function fitting parameters.
410
+ default: R0=23.9*1e-9, b2=1.6, b3=2.1, b4=30
411
+ R0 is the local merger rate density at low redshift in Mpc^-3 yr^-1
366
412
 
367
413
  Returns
368
414
  ----------
369
415
  rate_density : `float` or `numpy.ndarray` (nD array of floats)
370
- merger rate density
416
+ merger rate density in source frame (Mpc^-3 yr^-1)
371
417
 
372
418
  Examples
373
419
  ----------
@@ -376,89 +422,239 @@ class CBCSourceRedshiftDistribution(object):
376
422
  >>> rate_density = pop.merger_rate_density(zs=0.1)
377
423
  """
378
424
 
379
- if param:
380
- R0 = param["R0"]
381
- b2 = param["b2"]
382
- b3 = param["b3"]
383
- b4 = param["b4"]
425
+ identifier_dict = {}
426
+ identifier_dict['z_min'] = self.z_min
427
+ identifier_dict['z_max'] = self.z_max
428
+ identifier_dict['cosmology'] = self.cosmo
429
+ identifier_dict['event_type'] = self.event_type
430
+ identifier_dict['name'] = "merger_rate_density_bbh_popI_II_oguri2018"
431
+ identifier_dict['resolution'] = self.create_new_interpolator["merger_rate_density"]["resolution"]
432
+ param_dict = self.merger_rate_density_model_list["merger_rate_density_bbh_popI_II_oguri2018"]
433
+ param_dict.update(kwargs)
434
+ identifier_dict.update(param_dict)
435
+
436
+ zs_array = np.linspace(identifier_dict['z_min'], identifier_dict['z_max'], identifier_dict['resolution'])
437
+ Rzs = lambda zs: merger_rate_density_bbh_popI_II_oguri2018(
438
+ zs=zs,
439
+ R0=identifier_dict['R0'],
440
+ b2=identifier_dict['b2'],
441
+ b3=identifier_dict['b3'],
442
+ b4=identifier_dict['b4']
443
+ )
444
+
445
+ Rzs_object = FunctionConditioning(
446
+ function=Rzs,
447
+ x_array=zs_array,
448
+ param_dict_given=identifier_dict,
449
+ directory=self.directory,
450
+ sub_directory="merger_rate_density",
451
+ name=identifier_dict['name'],
452
+ create_new=self.create_new_interpolator["merger_rate_density"]["create_new"],
453
+ create_function_inverse=False,
454
+ create_function=True,
455
+ create_pdf=True,
456
+ create_rvs=True,
457
+ callback='function',
458
+ )
384
459
 
385
- #print(f"\nR0: {R0}\n")
386
- return merger_rate_density_bbh_popI_II_oguri2018(zs=zs, R0=R0, b2=b2, b3=b3, b4=b4)
460
+ return Rzs_object if get_attribute else Rzs_object(zs)
387
461
 
388
- def star_formation_rate_madau_dickinson2014(self,
389
- zs, af=2.7, bf=5.6, cf=2.9, param=None
390
- ):
462
+ def sfr_with_td(self, zs, get_attribute=False, **kwargs):
463
+ """
391
464
  """
392
- Function to compute star formation rate as given in Eqn. 15 Madau & Dickinson (2014). The output is in detector frame and is unnormalized.
465
+
466
+ identifier_dict = {}
467
+ identifier_dict['z_min'] = self.z_min
468
+ identifier_dict['z_max'] = self.z_max
469
+ identifier_dict['cosmology'] = self.cosmo
470
+ identifier_dict['event_type'] = self.event_type
471
+ identifier_dict['name'] = "sfr_with_td"
472
+ identifier_dict['resolution'] = self.create_new_interpolator["merger_rate_density"]["resolution"]
473
+ param_dict = self.merger_rate_density_model_list["sfr_with_td"]
474
+ param_dict.update(kwargs)
475
+ identifier_dict.update(param_dict)
476
+ print(identifier_dict)
477
+
478
+ print("Numerically solving the merger_rate_density with time delay")
479
+ zs_resolution = identifier_dict['resolution']
480
+ zs_array = np.geomspace(self.z_min+0.001, self.z_max, zs_resolution) if self.z_min==0 else np.geomspace(self.z_min, self.z_max, zs_resolution)
481
+
482
+ _, it_exist = interpolator_pickle_path(
483
+ param_dict_given=identifier_dict,
484
+ directory=self.directory,
485
+ sub_directory="merger_rate_density",
486
+ interpolator_name=identifier_dict['name'],
487
+ )
488
+
489
+ create_new = self.create_new_interpolator["merger_rate_density"]["create_new"]
490
+ if not it_exist or create_new:
491
+ rate_density = self._helper_rate_density_multiprocessing(zs_array, identifier_dict)
492
+ else:
493
+ rate_density=None
494
+
495
+ rate_density_object = FunctionConditioning(
496
+ function=rate_density,
497
+ x_array=zs_array,
498
+ param_dict_given=identifier_dict,
499
+ directory=self.directory,
500
+ sub_directory="merger_rate_density",
501
+ name=identifier_dict['name'],
502
+ create_new=create_new,
503
+ create_function_inverse=False,
504
+ create_function=True,
505
+ create_pdf=True,
506
+ create_rvs=True,
507
+ callback='function',
508
+ )
509
+
510
+ return rate_density_object if get_attribute else rate_density_object(zs)
511
+
512
+ def _helper_rate_density_multiprocessing(self, zs_array, identifier_dict):
513
+ """
514
+ Computes the merger rate density distribution with a time delay applied to the star formation rate (SFR),
515
+ utilizing multiprocessing for improved performance.
393
516
 
394
517
  Parameters
395
518
  ----------
396
- zs : `float` or `numpy.ndarray` (nD array of floats)
519
+ zs_array : `numpy.ndarray`
520
+ 1D array of source redshifts for which the merger rate density is calculated.
521
+ identifier_dict : `dict`
522
+ Dictionary containing parameters for the computation, including cosmological parameters
523
+ (H0, Omega_M, Omega_Lambda), time delay bounds (td_min, td_max), and SFR parameters (a, b, c, d).
524
+
525
+ Returns
526
+ -------
527
+ rate_density_array : `numpy.ndarray`
528
+ 1D array representing the computed merger rate density distribution normalized to the local
529
+ merger rate density at low redshift (R0).
530
+ """
531
+
532
+ size = len(zs_array)
533
+ input_args = np.array([
534
+ zs_array, # source redshifts
535
+ np.arange(size), # index
536
+ identifier_dict['td_min']*np.ones(size), # time delay minimum
537
+ identifier_dict['td_max']*np.ones(size), # time delay maximum
538
+ identifier_dict['cosmology'].H0.value*np.ones(size), # H0
539
+ identifier_dict['cosmology'].Om0*np.ones(size), # Omega_M
540
+ identifier_dict['cosmology'].Ode0*np.ones(size), # Omega_Lambda
541
+ # SFR params
542
+ identifier_dict['a']*np.ones(size),
543
+ identifier_dict['b']*np.ones(size),
544
+ identifier_dict['c']*np.ones(size),
545
+ identifier_dict['d']*np.ones(size),
546
+ ]).T
547
+
548
+ print("Computing merger rate density distribution (with time delay to SFR) using multiprocessing...")
549
+ # with tqdm
550
+ rate_density_array = np.zeros(size)
551
+ with Pool(processes=self.npool) as pool:
552
+ for result in tqdm(
553
+ pool.imap_unordered(sfr_with_time_delay, input_args),
554
+ total=size,
555
+ ncols=100,
556
+ disable=False,
557
+ ):
558
+ # print(result)
559
+ (
560
+ iter_i,
561
+ density_,
562
+ ) = result
563
+
564
+ rate_density_array[iter_i] = density_
565
+
566
+ rm_spline = CubicSpline(zs_array, rate_density_array, extrapolate=True)
567
+ # divide
568
+ rate_density_array = rate_density_array/rm_spline(0.) * identifier_dict['R0']
569
+
570
+ return rate_density_array
571
+
572
+ def sfr_madau_dickinson2014(self, zs, get_attribute=False, **kwargs):
573
+ """
574
+ Formation rate as given in Eqn. 15 Madau & Dickinson (2014). The output is in detector frame and is unnormalized.
575
+
576
+ Parameters
577
+ ----------
578
+ zs : `float` or `numpy.ndarray` (nd.array of floats)
397
579
  Source redshifts
398
- af : `float`
399
- Fitting paramters
400
- default: 2.7
401
- bf : `float`
402
- Fitting paramters
403
- default: 5.6
404
- cf : `float`
405
- Fitting paramters
406
- default: 2.9
407
- param : `dict`
408
- Allows to pass in above parameters as dict.
409
- e.g. param = dict(af=2.7, bf=5.6, cf=2.9)
410
- default: None
580
+ get_attribute : `bool`
581
+ If True, returns the merger rate density function instead of the value
582
+ default: False
583
+ kwargs : `dict`
584
+ Dictionary of star formation rate function fitting parameters.
585
+ default: af=2.7, bf=5.6, cf=2.9
411
586
 
412
587
  Returns
413
588
  ----------
414
589
  rate_density : `float` or `numpy.ndarray` (nD array of floats)
415
- merger rate density
590
+ merger rate density in detector frame (Mpc^-3 yr^-1)
416
591
 
417
592
  Examples
418
593
  ----------
419
594
  >>> from ler.gw_source_population import SourceGalaxyPopulationModel
420
- >>> pop = SourceGalaxyPopulationModel(z_min=5., z_max=40., event_type = "BBH", merger_rate_density="star_formation_rate_madau_dickinson2014")
595
+ >>> pop = SourceGalaxyPopulationModel(z_min=5., z_max=40., event_type = "BBH", merger_rate_density="sfr_madau_dickinson2014")
421
596
  >>> rate_density = pop.merger_rate_density(zs=10)
422
597
  """
423
598
 
424
- if param:
425
- af = param["af"]
426
- bf = param["bf"]
427
- cf = param["cf"]
599
+ identifier_dict = {}
600
+ identifier_dict['z_min'] = self.z_min
601
+ identifier_dict['z_max'] = self.z_max
602
+ identifier_dict['cosmology'] = self.cosmo
603
+ identifier_dict['event_type'] = self.event_type
604
+ identifier_dict['name'] = "sfr_madau_dickinson2014"
605
+ identifier_dict['resolution'] = self.create_new_interpolator["merger_rate_density"]["resolution"]
606
+ param_dict = self.merger_rate_density_model_list["sfr_madau_dickinson2014"]
607
+ param_dict.update(kwargs)
608
+ identifier_dict.update(param_dict)
609
+
610
+ zs_array = np.linspace(identifier_dict['z_min'], identifier_dict['z_max'], identifier_dict['resolution'])
611
+ Rzs = lambda zs: sfr_madau_dickinson2014(
612
+ zs=zs,
613
+ a=identifier_dict['a'],
614
+ b=identifier_dict['b'],
615
+ c=identifier_dict['c'],
616
+ )
617
+
618
+ Rzs_object = FunctionConditioning(
619
+ function=Rzs,
620
+ x_array=zs_array,
621
+ param_dict_given=identifier_dict,
622
+ directory=self.directory,
623
+ sub_directory="merger_rate_density",
624
+ name=identifier_dict['name'],
625
+ create_new=self.create_new_interpolator["merger_rate_density"]["create_new"],
626
+ create_function_inverse=False,
627
+ create_function=True,
628
+ create_pdf=True,
629
+ create_rvs=True,
630
+ callback='function',
631
+ )
428
632
 
429
- return star_formation_rate_madau_dickinson2014(zs=zs, af=af, bf=bf, cf=cf)
633
+ if get_attribute:
634
+ return Rzs_object
635
+ else:
636
+ return Rzs_object(zs)
430
637
 
431
- def merger_rate_density_bbh_popIII_ken2022(self,
432
- zs, n0=19.2 * 1e-9, aIII=0.66, bIII=0.3, zIII=11.6, param=None
433
- ):
638
+ def merger_rate_density_bbh_popIII_ken2022(self, zs, get_attribute=False, **kwargs):
434
639
  """
435
- Function to compute the unnormalized merger rate density (PopIII). Reference: Ng et al. 2022. The output is in detector frame and is unnormalized.
640
+ Merger rate density (PopIII). Reference: Ng et al. 2022. The output is in detector frame and is unnormalized.
436
641
 
437
642
  Parameters
438
643
  ----------
439
- zs : `float` or `numpy.ndarray` (nD array of floats)
644
+ zs : `float` or `numpy.ndarray`
440
645
  Source redshifts
441
- n0 : `float`
442
- normalization constant
443
- default: 19.2*1e-9
444
- aIII : `float`
445
- Fitting paramters
446
- default: 0.66
447
- bIII : `float`
448
- Fitting paramters
449
- default: 0.3
450
- zIII : `float`
451
- Fitting paramters
452
- default: 11.6
453
- param : `dict`
454
- Allows to pass in above parameters as dict.
455
- e.g. param = dict(aIII=0.66, bIII=0.3, zIII=11.6)
456
- default: None
646
+ get_attribute : `bool`
647
+ If True, returns the merger rate density function instead of the value
648
+ default: False
649
+ kwargs : `dict`
650
+ Dictionary of merger rate density function fitting parameters.
651
+ default: n0=19.2*1e-9, aIII=0.66, bIII=0.3, zIII=11.6
652
+ n0 is the local merger rate density at low redshift in Mpc^-3 yr^-1
457
653
 
458
654
  Returns
459
655
  ----------
460
- rate_density : `float` or `numpy.ndarray` (nD array of floats)
461
- merger rate density
656
+ rate_density : `float` or `numpy.ndarray`
657
+ merger rate density in detector frame (Mpc^-3 yr^-1)
462
658
 
463
659
  Examples
464
660
  ----------
@@ -468,23 +664,55 @@ class CBCSourceRedshiftDistribution(object):
468
664
  >>> rate_density # Mpc^-3 yr^-1
469
665
  1.5107979464621443e-08
470
666
  """
471
- if param:
472
- n0 = param["n0"]
473
- aIII = param["aIII"]
474
- bIII = param["bIII"]
475
- zIII = param["zIII"]
667
+
668
+ identifier_dict = {}
669
+ identifier_dict['z_min'] = self.z_min
670
+ identifier_dict['z_max'] = self.z_max
671
+ identifier_dict['cosmology'] = self.cosmo
672
+ identifier_dict['event_type'] = self.event_type
673
+ identifier_dict['name'] = "merger_rate_density_bbh_popIII_ken2022"
674
+ identifier_dict['resolution'] = self.create_new_interpolator["merger_rate_density"]["resolution"]
675
+ param_dict = self.merger_rate_density_model_list["merger_rate_density_bbh_popIII_ken2022"]
676
+ param_dict.update(kwargs)
677
+ identifier_dict.update(param_dict)
678
+
679
+ zs_array = np.linspace(identifier_dict['z_min'], identifier_dict['z_max'], identifier_dict['resolution'])
680
+ Rzs = lambda zs: merger_rate_density_bbh_popIII_ken2022(
681
+ zs=zs,
682
+ n0=identifier_dict['n0'],
683
+ aIII=identifier_dict['aIII'],
684
+ bIII=identifier_dict['bIII'],
685
+ zIII=identifier_dict['zIII']
686
+ )
687
+
688
+ Rzs_object = FunctionConditioning(
689
+ function=Rzs,
690
+ x_array=zs_array,
691
+ param_dict_given=identifier_dict,
692
+ directory=self.directory,
693
+ sub_directory="merger_rate_density",
694
+ name=identifier_dict['name'],
695
+ create_new=self.create_new_interpolator["merger_rate_density"]["create_new"],
696
+ create_function_inverse=False,
697
+ create_function=True,
698
+ create_pdf=True,
699
+ create_rvs=True,
700
+ callback='function',
701
+ )
702
+
703
+ if get_attribute:
704
+ return Rzs_object
705
+ else:
706
+ return Rzs_object(zs)
476
707
 
477
- return merger_rate_density_bbh_popIII_ken2022(zs=zs, n0=n0, aIII=aIII, bIII=bIII, zIII=zIII)
478
708
 
479
- def merger_rate_density_bbh_primordial_ken2022(self,
480
- zs, n0=0.044 * 1e-9, t0=13.786885302009708, param=None
481
- ):
709
+ def merger_rate_density_bbh_primordial_ken2022(self, zs, get_attribute=False, **kwargs):
482
710
  """
483
711
  Function to compute the merger rate density (Primordial). Reference: Ng et al. 2022. The output is in detector frame and is unnormalized.
484
712
 
485
713
  Parameters
486
714
  ----------
487
- zs : `float`
715
+ zs : `float` or `numpy.ndarray`
488
716
  Source redshifts
489
717
  n0 : `float`
490
718
  normalization constant
@@ -510,13 +738,45 @@ class CBCSourceRedshiftDistribution(object):
510
738
  9.78691173794454e-10
511
739
  """
512
740
 
513
- if param:
514
- n0 = param["n0"]
515
- t0 = param["t0"]
741
+ identifier_dict = {}
742
+ identifier_dict['z_min'] = self.z_min
743
+ identifier_dict['z_max'] = self.z_max
744
+ identifier_dict['cosmology'] = self.cosmo
745
+ identifier_dict['event_type'] = self.event_type
746
+ identifier_dict['name'] = "merger_rate_density_bbh_primordial_ken2022"
747
+ identifier_dict['resolution'] = self.create_new_interpolator["merger_rate_density"]["resolution"]
748
+ param_dict = self.merger_rate_density_model_list["merger_rate_density_bbh_primordial_ken2022"]
749
+ param_dict.update(kwargs)
750
+ identifier_dict.update(param_dict)
751
+
752
+ zs_array = np.linspace(identifier_dict['z_min'], identifier_dict['z_max'], identifier_dict['resolution'])
753
+ Rzs = lambda zs: merger_rate_density_bbh_primordial_ken2022(
754
+ zs=zs,
755
+ n0=identifier_dict['n0'],
756
+ t0=identifier_dict['t0']
757
+ )
516
758
 
517
- return merger_rate_density_bbh_primordial_ken2022(zs=zs, cosmology=self.cosmo, n0=n0, t0=t0)
759
+ Rzs_object = FunctionConditioning(
760
+ function=Rzs,
761
+ x_array=zs_array,
762
+ param_dict_given=identifier_dict,
763
+ directory=self.directory,
764
+ sub_directory="merger_rate_density",
765
+ name=identifier_dict['name'],
766
+ create_new=self.create_new_interpolator["merger_rate_density"]["create_new"],
767
+ create_function_inverse=False,
768
+ create_function=True,
769
+ create_pdf=True,
770
+ create_rvs=True,
771
+ callback='function',
772
+ )
773
+
774
+ if get_attribute:
775
+ return Rzs_object
776
+ else:
777
+ return Rzs_object(zs)
518
778
 
519
- def create_lookup_table(self, z_min, z_max, directory):
779
+ def create_lookup_table(self):
520
780
  """
521
781
  Function to create a lookup table for the differential comoving volume
522
782
  and luminosity distance wrt redshift.
@@ -536,98 +796,96 @@ class CBCSourceRedshiftDistribution(object):
536
796
  Function to calculate the differential comoving volume
537
797
  """
538
798
 
539
- # initialing cosmological functions for fast calculation through interpolation
540
- resolution = self.c_n_i["z_to_luminosity_distance"]["resolution"]
541
- create_new = self.c_n_i["z_to_luminosity_distance"]["create_new"]
542
- spline1 = interpolator_from_pickle(
543
- param_dict_given= dict(z_min=z_min, z_max=z_max, cosmology=self.cosmo, resolution=resolution),
544
- directory=directory,
545
- sub_directory="z_to_luminosity_distance",
546
- name="z_to_luminosity_distance",
547
- x = np.linspace(z_min, z_max, resolution),
548
- pdf_func= lambda z_: self.cosmo.luminosity_distance(z_).value,
549
- conditioned_y=None,
550
- dimension=1,
551
- category="function",
799
+ z_min = 0.001 if self.z_min == 0. else self.z_min
800
+ z_max = self.z_max
801
+
802
+ resolution = self.create_new_interpolator["luminosity_distance"]["resolution"]
803
+ create_new = self.create_new_interpolator["luminosity_distance"]["create_new"]
804
+ zs = np.geomspace(0.001, z_max, 1000)
805
+ Dl = self.cosmo.luminosity_distance(zs).value
806
+
807
+ self.luminosity_distance = FunctionConditioning(
808
+ function=Dl,
809
+ x_array=zs,
810
+ conditioned_y_array=None,
811
+ param_dict_given=dict(z_min=z_min, z_max=z_max, cosmology=self.cosmo, resolution=resolution, details="luminosity_distance from astropy.cosmology"),
812
+ directory=self.directory,
813
+ sub_directory="luminosity_distance",
814
+ name="luminosity_distance",
552
815
  create_new=create_new,
816
+ create_function_inverse=True,
817
+ create_function=True,
818
+ create_pdf=False,
819
+ create_rvs=False,
820
+ callback='function',
553
821
  )
554
- self.z_to_luminosity_distance = njit(lambda z_: cubic_spline_interpolator(z_, spline1[0], spline1[1]))
555
- self.z_to_luminosity_distance.__doc__ = """
556
- Function to convert redshift to luminosity distance.
557
-
822
+ self.luminosity_distance.__doc__ = """
823
+ Redshift to luminosity distance conversion.
824
+
558
825
  Parameters
559
826
  ----------
560
- zs : `numpy.ndarray`
561
- 1D array of floats
827
+ zs : `numpy.ndarray` or `float`
562
828
  Source redshifts
563
829
 
564
830
  Returns
565
831
  ----------
566
832
  luminosity_distance : `numpy.ndarray`
567
- 1D array of floats
568
- luminosity distance
833
+ luminosity distance in Mpc
834
+
835
+ Examples
836
+ ----------
837
+ >>> from ler.gw_source_population import SourceGalaxyPopulationModel
838
+ >>> ler = SourceGalaxyPopulationModel() # with default LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
839
+ >>> luminosity_distance = ler.luminosity_distance(1.)
840
+ >>> luminosity_distance = ler.luminosity_distance.function(np.array([1., 2.]))
841
+ >>> redshift = ler.luminosity_distance.function_inverse(np.array([100., 200.]))
569
842
  """
570
843
 
571
- # Create a lookup table for the differential comoving volume
572
844
  # get differential co-moving volume interpolator
573
- resolution = self.c_n_i["differential_comoving_volume"]["resolution"]
574
- create_new = self.c_n_i["differential_comoving_volume"]["create_new"]
575
- spline2 = interpolator_from_pickle(
576
- param_dict_given= dict(z_min=z_min, z_max=z_max, cosmology=self.cosmo, resolution=resolution),
577
- directory=directory,
578
- sub_directory="differential_comoving_volume",
845
+ resolution = self.create_new_interpolator["differential_comoving_volume"]["resolution"]
846
+ create_new = self.create_new_interpolator["differential_comoving_volume"]["create_new"]
847
+ zs = np.geomspace(z_min, z_max, resolution)
848
+ dVcdz = self.cosmo.differential_comoving_volume(zs).value * 4 * np.pi # volume of shell in Mpc^3
849
+ self.differential_comoving_volume = FunctionConditioning(
850
+ function=dVcdz,
851
+ x_array=zs,
852
+ conditioned_y_array=None,
853
+ param_dict_given=dict(z_min=z_min, z_max=z_max, cosmology=self.cosmo, resolution=resolution, details="differential_comoving_volume from astropy.cosmology"),
854
+ directory=self.directory,
855
+ sub_directory="differential_comoving_volume",
579
856
  name="differential_comoving_volume",
580
- x = np.linspace(z_min, z_max, resolution),
581
- pdf_func= lambda z_: self.cosmo.differential_comoving_volume(z_).value * 4 * np.pi, # volume of shell
582
- conditioned_y=None,
583
- dimension=1,
584
- category="function",
585
857
  create_new=create_new,
858
+ create_function_inverse=False,
859
+ create_function=True,
860
+ create_pdf=False,
861
+ create_rvs=False,
862
+ callback='function',
586
863
  )
587
- self.differential_comoving_volume = njit(lambda z_: cubic_spline_interpolator(z_, spline2[0], spline2[1]))
588
864
  self.differential_comoving_volume.__doc__ = """
589
- Function to calculate the differential comoving volume.
865
+ Redshift to differential comoving volume conversion.
590
866
 
591
867
  Parameters
592
868
  ----------
593
- zs : `numpy.ndarray`
594
- 1D array of floats
869
+ zs : `numpy.ndarray` or `float`
595
870
  Source redshifts
596
871
 
597
872
  Returns
598
873
  ----------
599
- differential_comoving_volume : `float`
600
- 1D array of floats
601
- differential comoving volume
602
- """
603
-
604
- @property
605
- def sample_source_redshift(self):
606
- """
607
- Function to sample source redshifts (detector frame) between z_min and z_max from the detector galaxy population
608
-
609
- Parameters
610
- ----------
611
- size : `int`
612
- Number of samples to generate
874
+ differential_comoving_volume : `numpy.ndarray`
875
+ differential comoving volume in Mpc^3
613
876
 
614
- Returns
877
+ Examples
615
878
  ----------
616
- zs :
617
- Source redshifts
879
+ >>> from ler.len_galaxy_population import OpticalDepth
880
+ >>> ler = OpticalDepth() # with default LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
881
+ >>> differential_comoving_volume = ler.differential_comoving_volume(1.)
882
+ >>> differential_comoving_volume = ler.differential_comoving_volume.function(np.array([1., 2.]))
618
883
  """
619
- return self._sample_source_redshift
620
-
621
- @sample_source_redshift.setter
622
- def sample_source_redshift(self, prior):
623
- # prior has to be a function
624
- if callable(prior):
625
- self._sample_source_redshift = prior
626
-
884
+
627
885
  @property
628
886
  def merger_rate_density(self):
629
887
  """
630
- Function to get the merger rate density function wrt redshift. The output is in detector frame and is unnormalized.
888
+ Source frame merger rate density function wrt redshift.
631
889
 
632
890
  Parameters
633
891
  ----------
@@ -649,20 +907,66 @@ class CBCSourceRedshiftDistribution(object):
649
907
  return self._merger_rate_density
650
908
 
651
909
  @merger_rate_density.setter
652
- def merger_rate_density(self, merger_rate_density):
653
- # error_msg = ValueError(f"merger_rate_density must be one of {self.merger_rate_density_model_list}")
654
- # check if it is a string
655
- if isinstance(merger_rate_density, str):
656
- try:
657
- self._merger_rate_density = getattr(self, merger_rate_density)
658
- except:
659
- raise error_msg
660
- # check if it is a function
661
- elif callable(merger_rate_density):
662
- self._merger_rate_density = merger_rate_density
910
+ def merger_rate_density(self, function):
911
+
912
+ if function in self.merger_rate_density_model_list:
913
+ print(f"using ler available merger rate density model: {function}")
914
+ args = self.merger_rate_density_param
915
+ if args is None:
916
+ self._merger_rate_density = getattr(self, function)(zs=None, get_attribute=True)
917
+ else:
918
+ self._merger_rate_density = getattr(self, function)(zs=None, get_attribute=True, **args)
919
+
920
+ elif callable(function):
921
+ print("using user provided custom merger rate density function")
922
+ self._merger_rate_density = FunctionConditioning(function=None, x_array=None,create_function=function)
923
+
924
+ elif isinstance(function, object):
925
+ print("using user provided custom merger rate density class/object")
926
+ self._merger_rate_density = function
927
+
663
928
  else:
664
- raise error_msg
665
-
929
+ raise ValueError("merger_rate_density must be a function or a string from the available merger rate density model list")
930
+
931
+ # @property
932
+ # def source_redshift(self):
933
+ # """
934
+ # Function to sample source redshifts from pdf of merger rate density (detector frame).
935
+
936
+ # Parameters
937
+ # ----------
938
+ # size : `int`
939
+ # Number of samples to draw
940
+
941
+ # Returns
942
+ # ----------
943
+ # source_redshift : `numpy.ndarray` (1D array of floats)
944
+ # Array of source redshifts
945
+ # """
946
+
947
+ # return self._source_redshift
948
+
949
+ # @source_redshift.setter
950
+ # def source_redshift(self, prior):
951
+ # if isinstance(prior, str):
952
+ # args = self.gw_param_samplers_params["source_redshift"]
953
+ # if args is None:
954
+ # self._source_redshift = getattr(self, prior)(
955
+ # size=None, get_attribute=True
956
+ # )
957
+ # else:
958
+ # self._source_redshift = getattr(self, prior)(
959
+ # size=None, get_attribute=True, param=args
960
+ # )
961
+ # elif isinstance(prior, object):
962
+ # print("using user provided custom source redshift class/object")
963
+ # self._source_redshift = prior
964
+ # elif callable(prior):
965
+ # print("using user provided custom source redshift function")
966
+ # self._source_redshift = FunctionConditioning(function=None, x_array=None, create_rvs=prior)
967
+ # else:
968
+ # raise ValueError("Invalid input for source_redshift. Must be a string or a callable function.")
969
+
666
970
  @property
667
971
  def merger_rate_density_model_list(self):
668
972
  """
@@ -671,15 +975,35 @@ class CBCSourceRedshiftDistribution(object):
671
975
 
672
976
  self._merger_rate_density_model_list = dict(
673
977
  merger_rate_density_bbh_popI_II_oguri2018=dict(
674
- R0=23.9 * 1e-9, b2=1.6, b3=2.0, b4=30
978
+ R0=23.9 * 1e-9, b2=1.6, b3=2.1, b4=30
979
+ ),
980
+ sfr_madau_fragos2017=dict(
981
+ a=0.01, b=2.6, c=3.2, d=6.2
982
+ ),
983
+ sfr_madau_dickinson2014=dict(
984
+ a=0.015, b=2.7, c=2.9, d=5.6
985
+ ),
986
+ sfr_with_td=dict(
987
+ R0=23.9 * 1e-9, a=0.01, b=2.6, c=3.2, d=6.2, td_min=10e-3, td_max=10.0
675
988
  ),
676
- star_formation_rate_madau_dickinson2014=dict(af=2.7, bf=5.6, cf=2.9),
677
989
  merger_rate_density_bbh_popIII_ken2022=dict(
678
990
  n0=19.2 * 1e-9, aIII=0.66, bIII=0.3, zIII=11.6
679
991
  ),
680
992
  merger_rate_density_bbh_primordial_ken2022=dict(
681
993
  n0=0.044 * 1e-9, t0=13.786885302009708
682
994
  ),
995
+ sfr_madau_fragos2017_with_bbh_dt=dict(
996
+ R0=23.9 * 1e-9,
997
+ ),
998
+ sfr_madau_dickinson2014_with_bbh_dt=dict(
999
+ R0=23.9 * 1e-9,
1000
+ ),
1001
+ sfr_madau_fragos2017_with_bns_dt=dict(
1002
+ R0=105.5 * 1e-9,
1003
+ ),
1004
+ sfr_madau_dickinson2014_with_bns_dt=dict(
1005
+ R0=105.5 * 1e-9,
1006
+ ),
683
1007
  )
684
1008
 
685
- return self._merger_rate_density_model_list
1009
+ return self._merger_rate_density_model_list