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
ler/rates/ler copy.py DELETED
@@ -1,2097 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- This module contains the main class for calculating the rates of detectable gravitational waves events. The class inherits the :class:`~ler.lens_galaxy_population.LensGalaxyParameterDistribution` class for source parameters and lens parameters sampling. It also finds the image properties. :class:`~ler.lens_galaxy_population.LensGalaxyParameterDistribution` inherits the :class:`~ler.gw_source_population.CBCSourceParameterDistribution`, :class:`~ler.image_properties.ImageProperties` and uses `gwsnr` package for SNR calculation.
4
- """
5
-
6
- import os
7
- import warnings
8
- warnings.filterwarnings("ignore")
9
- import contextlib
10
- import numpy as np
11
- from scipy.stats import norm
12
- from astropy.cosmology import LambdaCDM
13
- from ..lens_galaxy_population import LensGalaxyParameterDistribution
14
- from ..utils import load_json, append_json, get_param_from_json, batch_handler, add_dict_values
15
-
16
-
17
- class LeR(LensGalaxyParameterDistribution):
18
- """Class to sample of lensed and unlensed events and calculate it's rates. Please note that parameters of the simulated events are stored in json file but not as an attribute of the class. This saves RAM memory.
19
-
20
- Parameters
21
- ----------
22
- npool : `int`
23
- number of cores to use.
24
- default npool = 4.
25
- z_min : `float`
26
- minimum redshift.
27
- default z_min = 0.
28
- for popI_II, popIII, primordial, BNS z_min = 0., 5., 5., 0. respectively.
29
- z_max : `float`
30
- maximum redshift.
31
- default z_max = 10.
32
- for popI_II, popIII, primordial, BNS z_max = 10., 40., 40., 5. respectively.
33
- event_type : `str`
34
- type of event to generate.
35
- default event_type = 'BBH'. Other options are 'BNS', 'NSBH'.
36
- size : `int`
37
- number of samples for sampling.
38
- default size = 100000. To get stable rates, size should be large (>=1e6).
39
- batch_size : `int`
40
- batch size for SNR calculation.
41
- default batch_size = 50000.
42
- reduce the batch size if you are getting memory error.
43
- recommended batch_size = 200000, if size = 1000000.
44
- cosmology : `astropy.cosmology`
45
- cosmology to use for the calculation.
46
- default cosmology = LambdaCDM(H0=70, Om0=0.3, Ode0=0.7).
47
- snr_finder : `str` or `function`
48
- default snr_finder = 'gwsnr'.
49
- if None, the SNR will be calculated using the gwsnr package.
50
- if custom snr finder function is provided, the SNR will be calculated using a custom function. The custom function should follow the following signature:
51
- def snr_finder(gw_param_dict):
52
- ...
53
- return optimal_snr_dict
54
- where optimal_snr_dict.keys = ['optimal_snr_net']. Refer to `gwsnr` package's GWSNR.snr attribute for more details.
55
- pdet_finder : `function`
56
- default pdet_finder = None.
57
- The rate calculation uses either the pdet_finder or the snr_finder to calculate the detectable events. The custom pdet finder function should follow the following signature:
58
- def pdet_finder(gw_param_dict):
59
- ...
60
- return pdet_net_dict
61
- where pdet_net_dict.keys = ['pdet_net']. For example uses, refer to [GRB pdet example](https://ler.readthedocs.io/en/latest/examples/rates/grb%20detection%20rate.html).
62
- list_of_detectors : `list`
63
- list of detectors.
64
- default list_of_detectors = ['H1', 'L1', 'V1']. This is used for lensed SNR calculation wrt to the detectors. Provide 'None' if you only need net SNR/Pdet. Refer to ImageProperties.get_lensed_snrs for more details.
65
- json_file_names: `dict`
66
- names of the json files to strore the necessary parameters.
67
- default json_file_names = {'ler_params': 'LeR_params.json', 'unlensed_param': 'unlensed_param.json', 'unlensed_param_detectable': 'unlensed_param_detectable.json'}.
68
- interpolator_directory : `str`
69
- directory to store the interpolators.
70
- default interpolator_directory = './interpolator_pickle'. This is used for storing the various interpolators related to `ler` and `gwsnr` package.
71
- ler_directory : `str`
72
- directory to store the parameters.
73
- default ler_directory = './ler_data'. This is used for storing the parameters of the simulated events.
74
- verbose : `bool`
75
- default verbose = True.
76
- if True, the function will print all chosen parameters.
77
- Choose False to prevent anything from printing.
78
- kwargs : `keyword arguments`
79
- Note : kwargs takes input for initializing the :class:`~ler.lens_galaxy_population.LensGalaxyParameterDistribution`, :class:`~ler.gw_source_population.CBCSourceParameterDistribution`, :class:`~ler.gw_source_population.CBCSourceRedshiftDistribution` and :class:`~ler.image_properties.ImageProperties` classes. If snr_finder='gwsnr', then kwargs also takes input for initializing the :class:`~gwsnr.GWSNR` class. Please refer to the respective classes for more details.
80
-
81
- Examples
82
- ----------
83
- >>> from ler.rates import LeR
84
- >>> ler = LeR()
85
- >>> unlensed_params = ler.unlensed_cbc_statistics();
86
- >>> ler.unlensed_rate();
87
- >>> lensed_params = ler.lensed_cbc_statistics();
88
- >>> ler.lensed_rate();
89
- >>> ler.rate_ratio();
90
-
91
- Instance Attributes
92
- ----------
93
- LeR class has the following attributes, \n
94
- +-------------------------------------+----------------------------------+
95
- | Atrributes | Type |
96
- +=====================================+==================================+
97
- |:attr:`~npool` | `int` |
98
- +-------------------------------------+----------------------------------+
99
- |:attr:`~z_min` | `float` |
100
- +-------------------------------------+----------------------------------+
101
- |:attr:`~z_max` | `float` |
102
- +-------------------------------------+----------------------------------+
103
- |:attr:`~event_type` | `str` |
104
- +-------------------------------------+----------------------------------+
105
- |:attr:`~cosmo` | `astropy.cosmology` |
106
- +-------------------------------------+----------------------------------+
107
- |:attr:`~size` | `int` |
108
- +-------------------------------------+----------------------------------+
109
- |:attr:`~batch_size` | `int` |
110
- +-------------------------------------+----------------------------------+
111
- |:attr:`~json_file_names` | `dict` |
112
- +-------------------------------------+----------------------------------+
113
- |:attr:`~interpolator_directory` | `str` |
114
- +-------------------------------------+----------------------------------+
115
- |:attr:`~ler_directory` | `str` |
116
- +-------------------------------------+----------------------------------+
117
- |:attr:`~gwsnr` | `bool` |
118
- +-------------------------------------+----------------------------------+
119
- |:attr:`~gw_param_sampler_dict` | `dict` |
120
- +-------------------------------------+----------------------------------+
121
- |:attr:`~snr_calculator_dict` | `dict` |
122
- +-------------------------------------+----------------------------------+
123
- |:attr:`~list_of_detectors` | `list` |
124
- +-------------------------------------+----------------------------------+
125
- |:attr:`~unlensed_param` | `dict` |
126
- +-------------------------------------+----------------------------------+
127
- |:attr:`~unlensed_param_detectable` | `dict` |
128
- +-------------------------------------+----------------------------------+
129
- |:attr:`~lensed_param` | `dict` |
130
- +-------------------------------------+----------------------------------+
131
- |:attr:`~lensed_param_detectable` | `dict` |
132
- +-------------------------------------+----------------------------------+
133
-
134
- Instance Methods
135
- ----------
136
- LeR class has the following methods, \n
137
- +-------------------------------------+----------------------------------+
138
- | Methods | Description |
139
- +=====================================+==================================+
140
- |:meth:`~class_initialization` | Function to initialize the |
141
- | | parent classes |
142
- +-------------------------------------+----------------------------------+
143
- |:meth:`~gwsnr_intialization` | Function to initialize the |
144
- | | gwsnr class |
145
- +-------------------------------------+----------------------------------+
146
- |:meth:`~snr` | Function to get the snr with the |
147
- | | given parameters. |
148
- +-------------------------------------+----------------------------------+
149
- |:meth:`~snr_bilby` | Function to get the snr with the |
150
- | | given parameters using inner- |
151
- | | product method. |
152
- +-------------------------------------+----------------------------------+
153
- |:meth:`~pdet` | Function to get the pdet with |
154
- | | the given parameters. |
155
- +-------------------------------------+----------------------------------+
156
- |:meth:`~store_ler_params` | Function to store the all the |
157
- | | necessary parameters. |
158
- +-------------------------------------+----------------------------------+
159
- |:meth:`~unlensed_cbc_statistics` | Function to generate unlensed |
160
- | | GW source parameters in batches. |
161
- +-------------------------------------+----------------------------------+
162
- |:meth:`~unlensed_sampling_routine` | Function to generate unlensed |
163
- | | GW source parameters. It stores |
164
- | | the parameters of the generated |
165
- | | events in a json file. |
166
- +-------------------------------------+----------------------------------+
167
- |:meth:`~unlensed_rate` | Function to calculate the |
168
- | | unlensed rate. It also stores |
169
- | | the parameters of the detectable |
170
- | | unlesed events in a json file. |
171
- +-------------------------------------+----------------------------------+
172
- |:meth:`~lensed_cbc_statistics` | Function to generate lensed |
173
- | | GW source parameters. |
174
- +-------------------------------------+----------------------------------+
175
- |:meth:`~lensed_sampling_routine` | Function to generate lensed |
176
- | | GW source parameters. It stores |
177
- | | the parameters of the generated |
178
- | | events in a json file. |
179
- +-------------------------------------+----------------------------------+
180
- |:meth:`~lensed_rate` | Function to calculate the |
181
- | | lensed rate. It also stores the |
182
- | | parameters of the detectable |
183
- | | lensed events in a json file. |
184
- +-------------------------------------+----------------------------------+
185
- |:meth:`~rate_ratio` | Function to calculate the rate |
186
- | | ratio between lensed and |
187
- | | unlensed events. |
188
- +-------------------------------------+----------------------------------+
189
- |:meth:`~rate_comparision_with_rate_calculation |
190
- +-------------------------------------+----------------------------------+
191
- | | Function to calculate rates for |
192
- | | unleesed and lensed events and |
193
- | | compare it with the rate. It also|
194
- | | stores the parameters of the |
195
- | | detectable events in a json file.|
196
- +-------------------------------------+----------------------------------+
197
- |:meth:`~selecting_n_unlensed_detectable_events` |
198
- +-------------------------------------+----------------------------------+
199
- | | Function to select n unlensed |
200
- | | detectable events. It stores the |
201
- | | parameters of the detectable |
202
- | | unlesed events in a json file. |
203
- +-------------------------------------+----------------------------------+
204
- |:meth:`~selecting_n_lensed_detectable_events` |
205
- +-------------------------------------+----------------------------------+
206
- | | Function to select n lensed |
207
- | | detectable events. It stores the |
208
- | | parameters of the detectable |
209
- | | lensed events in a json file. |
210
- +-------------------------------------+----------------------------------+
211
-
212
- Note: `LeR` class also inherits all the instances from the :class:`~ler.lens_galaxy_population.LensGalaxyParameterDistribution` class. Please refer to the :class:`~ler.lens_galaxy_population.LensGalaxyParameterDistribution` class for more details.
213
- """
214
-
215
- # Attributes
216
-
217
- npool = None
218
- """``int`` \n
219
- Number of logical cores to use.
220
- """
221
-
222
- z_min = None
223
- """``float`` \n
224
- Minimum redshift of the source population
225
- """
226
-
227
- z_max = None
228
- """``float`` \n
229
- Maximum redshift of the source population
230
- """
231
-
232
- event_type = None
233
- """``str`` \n
234
- Type of event to generate. \n
235
- e.g. 'BBH', 'BNS', 'NSBH'
236
- """
237
-
238
- cosmo = None
239
- """``astropy.cosmology`` \n
240
- Cosmology to use for the calculation.
241
- """
242
-
243
- size = None
244
- """``int`` \n
245
- Number of samples for sampling.
246
- """
247
-
248
- batch_size = None
249
- """``int`` \n
250
- Batch size for sampling.
251
- """
252
-
253
- json_file_names = None
254
- """``dict`` \n
255
- Names of the json files to store the necessary parameters.
256
- """
257
-
258
- interpolator_directory = None
259
- """``str`` \n
260
- Directory to store the interpolators.
261
- """
262
-
263
- ler_directory = None
264
- """``str`` \n
265
- Directory to store the parameters.
266
- """
267
-
268
- gwsnr = None
269
- """``bool`` \n
270
- If True, the SNR will be calculated using the gwsnr package.
271
- """
272
-
273
- gw_param_sampler_dict = None
274
- """``dict`` \n
275
- Dictionary of parameters to initialize the ``CBCSourceParameterDistribution`` class.
276
- """
277
-
278
- snr_calculator_dict = None
279
- """``dict`` \n
280
- Dictionary of parameters to initialize the ``GWSNR`` class.
281
- """
282
-
283
- list_of_detectors = None
284
- """``list`` \n
285
- List of detectors.
286
- """
287
-
288
- unlensed_param = None
289
- """``dict`` \n
290
- Dictionary of unlensed GW source parameters. The included parameters and their units are as follows (for default settings):\n
291
- +--------------------+--------------+--------------------------------------+
292
- | Parameter | Units | Description |
293
- +====================+==============+======================================+
294
- | zs | | redshift of the source |
295
- +--------------------+--------------+--------------------------------------+
296
- | geocent_time | s | GPS time of coalescence |
297
- +--------------------+--------------+--------------------------------------+
298
- | ra | rad | right ascension |
299
- +--------------------+--------------+--------------------------------------+
300
- | dec | rad | declination |
301
- +--------------------+--------------+--------------------------------------+
302
- | phase | rad | phase of GW at reference frequency |
303
- +--------------------+--------------+--------------------------------------+
304
- | psi | rad | polarization angle |
305
- +--------------------+--------------+--------------------------------------+
306
- | theta_jn | rad | inclination angle |
307
- +--------------------+--------------+--------------------------------------+
308
- | luminosity_distance| Mpc | luminosity distance |
309
- +--------------------+--------------+--------------------------------------+
310
- | mass_1_source | Msun | mass_1 of the compact binary |
311
- | | | (source frame) |
312
- +--------------------+--------------+--------------------------------------+
313
- | mass_2_source | Msun | mass_2 of the compact binary |
314
- | | | (source frame) |
315
- +--------------------+--------------+--------------------------------------+
316
- | mass_1 | Msun | mass_1 of the compact binary |
317
- | | | (detector frame) |
318
- +--------------------+--------------+--------------------------------------+
319
- | mass_2 | Msun | mass_2 of the compact binary |
320
- | | | (detector frame) |
321
- +--------------------+--------------+--------------------------------------+
322
- | L1 | | optimal snr of L1 |
323
- +--------------------+--------------+--------------------------------------+
324
- | H1 | | optimal snr of H1 |
325
- +--------------------+--------------+--------------------------------------+
326
- | V1 | | optimal snr of V1 |
327
- +--------------------+--------------+--------------------------------------+
328
- | optimal_snr_net | | optimal snr of the network |
329
- +--------------------+--------------+--------------------------------------+
330
- """
331
-
332
- unlensed_param_detectable = None
333
- """``dict`` \n
334
- Dictionary of detectable unlensed GW source parameters. It includes the same parameters as the :attr:`~unlensed_param` attribute.
335
- """
336
-
337
- lensed_param = None
338
- """``dict`` \n
339
- Dictionary of lens parameters, images parameters and lensed GW source parameters. The included parameters and their units are as follows (for default settings):\n
340
- +------------------------------+-----------+-------------------------------+
341
- | Parameter | Units | Description |
342
- +==============================+===========+===============================+
343
- | zl | | redshift of the lens |
344
- +------------------------------+-----------+-------------------------------+
345
- | zs | | redshift of the source |
346
- +------------------------------+-----------+-------------------------------+
347
- | sigma |km s^-1 | velocity dispersion |
348
- +------------------------------+-----------+-------------------------------+
349
- | q | | axis ratio |
350
- +------------------------------+-----------+-------------------------------+
351
- | theta_E | arcsec | Einstein radius |
352
- +------------------------------+-----------+-------------------------------+
353
- | phi | rad | axis rotation angle |
354
- +------------------------------+-----------+-------------------------------+
355
- | e1 | | ellipticity component 1 |
356
- +------------------------------+-----------+-------------------------------+
357
- | e2 | | ellipticity component 2 |
358
- +------------------------------+-----------+-------------------------------+
359
- | gamma1 | | shear component 1 |
360
- +------------------------------+-----------+-------------------------------+
361
- | gamma2 | | shear component 2 |
362
- +------------------------------+-----------+-------------------------------+
363
- | gamma | | shear |
364
- +------------------------------+-----------+-------------------------------+
365
- | ra | rad | right ascension |
366
- +------------------------------+-----------+-------------------------------+
367
- | dec | rad | declination |
368
- +------------------------------+-----------+-------------------------------+
369
- | phase | rad | phase of GW at reference freq |
370
- +------------------------------+-----------+-------------------------------+
371
- | psi | rad | polarization angle |
372
- +------------------------------+-----------+-------------------------------+
373
- | theta_jn | rad | inclination angle |
374
- +------------------------------+-----------+-------------------------------+
375
- | mass_1_source | Msun | mass_1 of the compact binary |
376
- | | | (source frame) |
377
- +------------------------------+-----------+-------------------------------+
378
- | mass_2_source | Msun | mass_2 of the compact binary |
379
- | | | (source frame) |
380
- +------------------------------+-----------+-------------------------------+
381
- | mass_1 | Msun | mass_1 of the compact binary |
382
- | | | (detector frame) |
383
- +------------------------------+-----------+-------------------------------+
384
- | mass_2 | Msun | mass_2 of the compact binary |
385
- | | | (detector frame) |
386
- +------------------------------+-----------+-------------------------------+
387
- | x0_image_positions | | x0 image positions |
388
- +------------------------------+-----------+-------------------------------+
389
- | x1_image_positions | | x1 image positions |
390
- +------------------------------+-----------+-------------------------------+
391
- | magnifications | | magnifications |
392
- +------------------------------+-----------+-------------------------------+
393
- | time_delays | | time delays |
394
- +------------------------------+-----------+-------------------------------+
395
- | image_type | | image type |
396
- +------------------------------+-----------+-------------------------------+
397
- | n_images | | number of images |
398
- +------------------------------+-----------+-------------------------------+
399
- | effective_luminosity_distance| Mpc | effective luminosity distance |
400
- +------------------------------+-----------+-------------------------------+
401
- | effective_geocent_time | s | effective GPS time of coalesc |
402
- +------------------------------+-----------+-------------------------------+
403
- | L1 | | optimal snr of L1 |
404
- +------------------------------+-----------+-------------------------------+
405
- | H1 | | optimal snr of H1 |
406
- +------------------------------+-----------+-------------------------------+
407
- | V1 | | optimal snr of V1 |
408
- +------------------------------+-----------+-------------------------------+
409
- | optimal_snr_net | | optimal snr of the network |
410
- +------------------------------+-----------+-------------------------------+
411
- """
412
-
413
- lensed_param_detectable = None
414
- """``dict`` \n
415
- Dictionary of detectable lensed GW source parameters.
416
- """
417
-
418
- def __init__(
419
- self,
420
- npool=int(4),
421
- z_min=0.0,
422
- z_max=10.0,
423
- event_type="BBH",
424
- size=100000,
425
- batch_size=50000,
426
- cosmology=None,
427
- snr_finder=None,
428
- pdet_finder=None,
429
- list_of_detectors=None,
430
- json_file_names=None,
431
- interpolator_directory="./interpolator_pickle",
432
- ler_directory="./ler_data",
433
- verbose=True,
434
- **kwargs,
435
- ):
436
-
437
- self.npool = npool
438
- self.z_min = z_min
439
- self.z_max = z_max
440
- self.event_type = event_type
441
- self.cosmo = cosmology if cosmology else LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
442
- self.size = size
443
- self.batch_size = batch_size
444
- self.json_file_names = dict(ler_params="ler_params.json", unlensed_param="unlensed_param.json", unlensed_param_detectable="unlensed_param_detectable.json", lensed_param="lensed_param.json", lensed_param_detectable="lensed_param_detectable.json")
445
- if json_file_names:
446
- self.json_file_names.update(json_file_names)
447
- self.interpolator_directory = interpolator_directory
448
- self.ler_directory = ler_directory
449
- # create directory if not exists
450
- if not os.path.exists(ler_directory):
451
- os.makedirs(ler_directory)
452
-
453
- def initialization():
454
- # initialization of parent class
455
- self.class_initialization(params=kwargs)
456
- # initialization self.snr and self.pdet from GWSNR class
457
- if not snr_finder and not pdet_finder:
458
- self.gwsnr_intialization(params=kwargs)
459
- self.gwsnr = True
460
- self.pdet = pdet_finder
461
- else:
462
- self.snr = snr_finder
463
- self.pdet = pdet_finder
464
- self.gwsnr = False
465
- self.list_of_detectors = list_of_detectors
466
-
467
- # store all the ler input parameters
468
- self.store_ler_params(output_jsonfile=self.json_file_names["ler_params"])
469
-
470
- # if verbose, prevent anything from printing
471
- if verbose:
472
- initialization()
473
- self.print_all_params()
474
- else:
475
- with contextlib.redirect_stdout(None):
476
- initialization()
477
-
478
- def print_all_params(self):
479
- """
480
- Function to print all the parameters.
481
- """
482
-
483
- # print all relevant functions and sampler priors
484
- print("\n LeR set up params:")
485
- print("npool = ", self.npool)
486
- print("z_min = ", self.z_min)
487
- print("z_max = ", self.z_max)
488
- print(f"event_type = '{self.event_type}'")
489
- print("size = ", self.size)
490
- print("batch_size = ", self.batch_size)
491
- print("cosmology = ", self.cosmo)
492
- if self.snr:
493
- print("snr_finder = ", self.snr)
494
- if self.pdet:
495
- print("pdet_finder = ", self.pdet)
496
- print("json_file_names = ", self.json_file_names)
497
- print("interpolator_directory = ", self.interpolator_directory)
498
- print("ler_directory = ", self.ler_directory)
499
-
500
- print("\n LeR also takes CBCSourceParameterDistribution params as kwargs, as follows:")
501
- print("source_priors=", self.gw_param_sampler_dict["source_priors"])
502
- print("source_priors_params=", self.gw_param_sampler_dict["source_priors_params"])
503
- print("spin_zero=", self.gw_param_sampler_dict["spin_zero"])
504
- print("spin_precession=", self.gw_param_sampler_dict["spin_precession"])
505
- print("create_new_interpolator=", self.gw_param_sampler_dict["create_new_interpolator"])
506
-
507
- print("\n LeR also takes LensGalaxyParameterDistribution params as kwargs, as follows:")
508
- print(f"lens_type = '{self.gw_param_sampler_dict['lens_type']}'")
509
- print("lens_functions = ", self.gw_param_sampler_dict["lens_functions"])
510
- print("lens_priors = ", self.gw_param_sampler_dict["lens_priors"])
511
- print("lens_priors_params = ", self.gw_param_sampler_dict["lens_priors_params"])
512
-
513
- print("\n Image properties:")
514
- print("n_min_images = ", self.n_min_images)
515
- print("n_max_images = ", self.n_max_images)
516
- print("geocent_time_min = ", self.geocent_time_min)
517
- print("geocent_time_max = ", self.geocent_time_max)
518
- print("lens_model_list = ", self.lens_model_list)
519
-
520
- if self.gwsnr:
521
- print("\n LeR also takes gwsnr.GWSNR params as kwargs, as follows:")
522
- print("mtot_min = ", self.snr_calculator_dict["mtot_min"])
523
- print("mtot_max = ", self.snr_calculator_dict["mtot_max"])
524
- print("ratio_min = ", self.snr_calculator_dict["ratio_min"])
525
- print("ratio_max = ", self.snr_calculator_dict["ratio_max"])
526
- print("mtot_resolution = ", self.snr_calculator_dict["mtot_resolution"])
527
- print("ratio_resolution = ", self.snr_calculator_dict["ratio_resolution"])
528
- print("sampling_frequency = ", self.snr_calculator_dict["sampling_frequency"])
529
- print(f"waveform_approximant = '{self.snr_calculator_dict['waveform_approximant']}'")
530
- print("minimum_frequency = ", self.snr_calculator_dict["minimum_frequency"])
531
- print(f"snr_type = '{self.snr_calculator_dict['snr_type']}'")
532
- print("psds = ", self.snr_calculator_dict["psds"])
533
- print("ifos = ", self.snr_calculator_dict["ifos"])
534
- print("interpolator_dir = ", self.snr_calculator_dict["interpolator_dir"])
535
- print("create_new_interpolator = ", self.snr_calculator_dict["create_new_interpolator"])
536
- print("gwsnr_verbose = ", self.snr_calculator_dict["gwsnr_verbose"])
537
- print("multiprocessing_verbose = ", self.snr_calculator_dict["multiprocessing_verbose"])
538
- print("mtot_cut = ", self.snr_calculator_dict["mtot_cut"])
539
- # del self.gwsnr
540
-
541
- print("\n For reference, the chosen source parameters are listed below:")
542
- print(f"merger_rate_density = '{self.gw_param_samplers['merger_rate_density']}'")
543
- print("merger_rate_density_params = ", self.gw_param_samplers_params["merger_rate_density"])
544
- print(f"source_frame_masses = '{self.gw_param_samplers['source_frame_masses']}'")
545
- print("source_frame_masses_params = ", self.gw_param_samplers_params["source_frame_masses"])
546
- print(f"geocent_time = '{self.gw_param_samplers['geocent_time']}'")
547
- print("geocent_time_params = ", self.gw_param_samplers_params["geocent_time"])
548
- print(f"ra = '{self.gw_param_samplers['ra']}'")
549
- print("ra_params = ", self.gw_param_samplers_params["ra"])
550
- print(f"dec = '{self.gw_param_samplers['dec']}'")
551
- print("dec_params = ", self.gw_param_samplers_params["dec"])
552
- print(f"phase = '{self.gw_param_samplers['phase']}'")
553
- print("phase_params = ", self.gw_param_samplers_params["phase"])
554
- print(f"psi = '{self.gw_param_samplers['psi']}'")
555
- print("psi_params = ", self.gw_param_samplers_params["psi"])
556
- print(f"theta_jn = '{self.gw_param_samplers['theta_jn']}'")
557
- print("theta_jn_params = ", self.gw_param_samplers_params["theta_jn"])
558
- if self.spin_zero==False:
559
- print(f"a_1 = '{self.gw_param_samplers['a_1']}'")
560
- print("a_1_params = ", self.gw_param_samplers_params["a_1"])
561
- print(f"a_2 = '{self.gw_param_samplers['a_2']}'")
562
- print("a_2_params = ", self.gw_param_samplers_params["a_2"])
563
- if self.spin_precession==True:
564
- print(f"tilt_1 = '{self.gw_param_samplers['tilt_1']}'")
565
- print("tilt_1_params = ", self.gw_param_samplers_params["tilt_1"])
566
- print(f"tilt_2 = '{self.gw_param_samplers['tilt_2']}'")
567
- print("tilt_2_params = ", self.gw_param_samplers_params["tilt_2"])
568
- print(f"phi_12 = '{self.gw_param_samplers['phi_12']}'")
569
- print("phi_12_params = ", self.gw_param_samplers_params["phi_12"])
570
- print(f"phi_jl = '{self.gw_param_samplers['phi_jl']}'")
571
- print("phi_jl_params = ", self.gw_param_samplers_params["phi_jl"])
572
-
573
- print("\n For reference, the chosen lens related parameters and functions are listed below:")
574
- print(f"lens_redshift = '{self.lens_param_samplers['lens_redshift']}'")
575
- print("lens_redshift_params = ", self.lens_param_samplers_params["lens_redshift"])
576
- print(f"velocity_dispersion = '{self.lens_param_samplers['velocity_dispersion']}'")
577
- print("velocity_dispersion_params = ", self.lens_param_samplers_params["velocity_dispersion"])
578
- print(f"axis_ratio = '{self.lens_param_samplers['axis_ratio']}'")
579
- print("axis_ratio_params = ", self.lens_param_samplers_params["axis_ratio"])
580
- print(f"axis_rotation_angle = '{self.lens_param_samplers['axis_rotation_angle']}'")
581
- print("axis_rotation_angle_params = ", self.lens_param_samplers_params["axis_rotation_angle"])
582
- print(f"shear = '{self.lens_param_samplers['shear']}'")
583
- print("shear_params = ", self.lens_param_samplers_params["shear"])
584
- print(f"mass_density_spectral_index = '{self.lens_param_samplers['mass_density_spectral_index']}'")
585
- print("mass_density_spectral_index_params = ", self.lens_param_samplers_params["mass_density_spectral_index"])
586
- # lens functions
587
- print("Lens functions:")
588
- print(f"strong_lensing_condition = '{self.lens_functions['strong_lensing_condition']}'")
589
- print(f"optical_depth = '{self.lens_functions['optical_depth']}'")
590
-
591
- @property
592
- def snr(self):
593
- """
594
- Function to get the snr with the given parameters.
595
-
596
- Parameters
597
- ----------
598
- gw_param_dict : `dict`
599
- dictionary of GW source parameters.
600
- mass_1 : `numpy.ndarray` or `float`
601
- mass_1 of the compact binary (detector frame) (Msun).
602
- mass_2 : `numpy.ndarray` or `float`
603
- mass_2 of the compact binary (detector frame) (Msun).
604
- luminosity_distance : `numpy.ndarray` or `float`
605
- luminosity distance of the source (Mpc).
606
- theta_jn : `numpy.ndarray` or `float`
607
- inclination angle of the source (rad).
608
- psi : `numpy.ndarray` or `float`
609
- polarization angle of the source (rad).
610
- phase : `numpy.ndarray` or `float`
611
- phase of GW at reference frequency (rad).
612
- geocent_time : `numpy.ndarray` or `float`
613
- GPS time of coalescence (s).
614
- ra : `numpy.ndarray` or `float`
615
- right ascension of the source (rad).
616
- dec : `numpy.ndarray` or `float`
617
- declination of the source (rad).
618
- a_1 : `numpy.ndarray` or `float`
619
- dimensionless spin magnitude of the more massive object.
620
- a_2 : `numpy.ndarray` or `float`
621
- dimensionless spin magnitude of the less massive object.
622
- tilt_1 : `numpy.ndarray` or `float`
623
- tilt angle of the more massive object spin.
624
- tilt_2 : `numpy.ndarray` or `float`
625
- tilt angle of the less massive object spin.
626
- phi_12 : `numpy.ndarray` or `float`
627
- azimuthal angle between the two spin vectors.
628
- phi_jl : `numpy.ndarray` or `float`
629
- azimuthal angle between total angular momentum and the orbital angular momentum.
630
-
631
- Returns
632
- ----------
633
- optimal_snr_list : `list`
634
- e.g. [optimal_snr_net, 'L1', 'H1', 'V1']
635
- optimal_snr_net : `numpy.ndarray` or `float`
636
- optimal snr of the network.
637
- 'H1' : `numpy.ndarray` or `float`
638
- optimal snr of H1.
639
- 'L1' : `numpy.ndarray` or `float`
640
- optimal snr of L1.
641
- 'V1' : `numpy.ndarray` or `float`
642
- optimal snr of V1.
643
- """
644
-
645
- return self._snr
646
-
647
- @snr.setter
648
- def snr(self, snr_finder):
649
- self._snr = snr_finder
650
-
651
- @property
652
- def unlensed_param(self):
653
- """
654
- Function to get data from the json file self.json_file_names["unlensed_param"].
655
-
656
- Returns
657
- ----------
658
- unlensed_param : `dict`
659
- dictionary of unlensed GW source parameters.
660
- """
661
-
662
- return get_param_from_json(self.ler_directory+"/"+self.json_file_names["unlensed_param"])
663
-
664
- @property
665
- def unlensed_param_detectable(self):
666
- """
667
- Function to get data from the json file self.json_file_names["unlensed_param_detectable"].
668
-
669
- Returns
670
- ----------
671
- unlensed_param_detectable : `dict`
672
- dictionary of unlensed GW source parameters.
673
- """
674
-
675
- return get_param_from_json(self.ler_directory+"/"+self.json_file_names["unlensed_param_detectable"])
676
-
677
- @property
678
- def lensed_param(self):
679
- """
680
- Function to get data from the json file self.json_file_names["lensed_param"].
681
-
682
- Returns
683
- ----------
684
- lensed_param : `dict`
685
- dictionary of lensed GW source parameters.
686
- """
687
-
688
- return get_param_from_json(self.ler_directory+"/"+self.json_file_names["lensed_param"])
689
-
690
- @property
691
- def lensed_param_detectable(self):
692
- """
693
- Function to get data from the json file self.json_file_names["lensed_param_detectable"].
694
-
695
- Returns
696
- ----------
697
- lensed_param_detectable : `dict`
698
- dictionary of lensed GW source parameters.
699
- """
700
-
701
- return get_param_from_json(self.ler_directory+"/"+self.json_file_names["lensed_param_detectable"])
702
-
703
- def class_initialization(self, params=None):
704
- """
705
- Function to initialize the parent classes.
706
-
707
- Parameters
708
- ----------
709
- params : `dict`
710
- dictionary of parameters to initialize the parent classes
711
- """
712
-
713
- # initialization of LensGalaxyParameterDistribution class
714
- # it also initializes the CBCSourceParameterDistribution and ImageProperties classes
715
- input_params = dict(
716
- z_min=self.z_min,
717
- z_max=self.z_max,
718
- cosmology=self.cosmo,
719
- event_type=self.event_type,
720
- lens_type="epl_galaxy",
721
- lens_functions= None,
722
- lens_priors=None,
723
- lens_priors_params=None,
724
- geocent_time_min=1126259462.4,
725
- geocent_time_max=1126259462.4+365*24*3600*20,
726
- source_priors=None,
727
- source_priors_params=None,
728
- spin_zero=True,
729
- spin_precession=False,
730
- directory=self.interpolator_directory,
731
- create_new_interpolator=False,
732
- )
733
- if params:
734
- for key, value in params.items():
735
- if key in input_params:
736
- input_params[key] = value
737
- self.gw_param_sampler_dict = input_params
738
- # initialization of clasess
739
- LensGalaxyParameterDistribution.__init__(
740
- self,
741
- z_min=input_params["z_min"],
742
- z_max=input_params["z_max"],
743
- cosmology=input_params["cosmology"],
744
- event_type=input_params["event_type"],
745
- lens_type=input_params["lens_type"],
746
- lens_functions=input_params["lens_functions"],
747
- lens_priors=input_params["lens_priors"],
748
- lens_priors_params=input_params["lens_priors_params"],
749
- geocent_time_min=input_params["geocent_time_min"],
750
- geocent_time_max=input_params["geocent_time_max"],
751
- source_priors=input_params["source_priors"],
752
- source_priors_params=input_params["source_priors_params"],
753
- spin_zero=input_params["spin_zero"],
754
- spin_precession=input_params["spin_precession"],
755
- directory=input_params["directory"],
756
- create_new_interpolator=input_params["create_new_interpolator"],
757
- )
758
-
759
- self.gw_param_sampler_dict["source_priors"]=self.gw_param_samplers.copy()
760
- self.gw_param_sampler_dict["source_priors_params"]=self.gw_param_samplers_params.copy()
761
- self.gw_param_sampler_dict["lens_priors"]=self.lens_param_samplers.copy()
762
- self.gw_param_sampler_dict["lens_priors_params"]=self.lens_param_samplers_params.copy()
763
- self.gw_param_sampler_dict["lens_functions"]=self.lens_functions.copy()
764
-
765
- def gwsnr_intialization(self, params=None):
766
- """
767
- Function to initialize the GWSNR class from the `gwsnr` package.
768
-
769
- Parameters
770
- ----------
771
- params : `dict`
772
- dictionary of parameters to initialize the gwsnr class
773
- """
774
- from gwsnr import GWSNR
775
-
776
- # initialization of GWSNR class
777
- input_params = dict(
778
- npool=self.npool,
779
- mtot_min=2.0,
780
- mtot_max=200,
781
- ratio_min=0.1,
782
- ratio_max=1.0,
783
- mtot_resolution=500,
784
- ratio_resolution=50,
785
- sampling_frequency=2048.0,
786
- waveform_approximant="IMRPhenomD",
787
- minimum_frequency=20.0,
788
- snr_type="interpolation",
789
- psds=None,
790
- ifos=None,
791
- interpolator_dir=self.interpolator_directory,
792
- create_new_interpolator=False,
793
- gwsnr_verbose=False,
794
- multiprocessing_verbose=True,
795
- mtot_cut=True,
796
- )
797
- # if self.event_type == "BNS":
798
- # input_params["mtot_max"]= 18.
799
- if params:
800
- for key, value in params.items():
801
- if key in input_params:
802
- input_params[key] = value
803
- self.snr_calculator_dict = input_params
804
- gwsnr = GWSNR(
805
- npool=input_params["npool"],
806
- mtot_min=input_params["mtot_min"],
807
- mtot_max=input_params["mtot_max"],
808
- ratio_min=input_params["ratio_min"],
809
- ratio_max=input_params["ratio_max"],
810
- mtot_resolution=input_params["mtot_resolution"],
811
- ratio_resolution=input_params["ratio_resolution"],
812
- sampling_frequency=input_params["sampling_frequency"],
813
- waveform_approximant=input_params["waveform_approximant"],
814
- minimum_frequency=input_params["minimum_frequency"],
815
- snr_type=input_params["snr_type"],
816
- psds=input_params["psds"],
817
- ifos=input_params["ifos"],
818
- interpolator_dir=input_params["interpolator_dir"],
819
- # create_new_interpolator=input_params["create_new_interpolator"],
820
- gwsnr_verbose=input_params["gwsnr_verbose"],
821
- multiprocessing_verbose=input_params["multiprocessing_verbose"],
822
- mtot_cut=input_params["mtot_cut"],
823
- )
824
-
825
- self.snr = gwsnr.snr
826
- self.list_of_detectors = gwsnr.detector_list
827
- self.snr_bilby = gwsnr.compute_bilby_snr
828
- self.snr_calculator_dict["mtot_max"] = gwsnr.mtot_max
829
- self.snr_calculator_dict["psds"] = gwsnr.psds_list
830
- #self.pdet = gwsnr.pdet
831
-
832
- def store_ler_params(self, output_jsonfile="ler_params.json"):
833
- """
834
- Function to store the all the necessary parameters. This is useful for reproducing the results. All the parameters stored are in string format to make it json compatible.
835
-
836
- Parameters
837
- ----------
838
- output_jsonfile : `str`
839
- name of the json file to store the parameters
840
- """
841
-
842
- # store param_sampler_dict, lensed_param_sampler_dict and snr_calculator_dict
843
- parameters_dict = dict(
844
- npool=str(self.npool),
845
- z_min=str(self.z_min),
846
- z_max=str(self.z_max),
847
- size=str(self.size),
848
- batch_size=str(self.batch_size),
849
- cosmology=str(self.cosmo),
850
- snr_finder=str(self.snr),
851
- json_file_names=str(self.json_file_names),
852
- interpolator_directory=str(self.interpolator_directory),
853
- )
854
-
855
- # cbc params
856
- param_sampler_dict = self.gw_param_sampler_dict.copy()
857
- # convert all dict values to str
858
- for key, value in param_sampler_dict.items():
859
- param_sampler_dict[key] = str(value)
860
- parameters_dict.update({"gw_param_sampler_dict": param_sampler_dict})
861
-
862
- # snr calculator params
863
- try:
864
- snr_calculator_dict = self.snr_calculator_dict.copy()
865
- for key, value in snr_calculator_dict.items():
866
- snr_calculator_dict[key] = str(value)
867
- parameters_dict.update({"snr_calculator_dict": snr_calculator_dict})
868
-
869
- file_name = output_jsonfile
870
- append_json(self.ler_directory+"/"+file_name, parameters_dict, replace=True)
871
- except:
872
- # if snr_calculator is custom function
873
- pass
874
-
875
- def unlensed_cbc_statistics(
876
- self, size=None, resume=False, save_batch=False, output_jsonfile=None,
877
- ):
878
- """
879
- Function to generate unlensed GW source parameters. This function calls the unlensed_sampling_routine function to generate the parameters in batches. The generated parameters are stored in a json file; and if save_batch=True, it keeps updating the file in batches.
880
-
881
- Parameters
882
- ----------
883
- size : `int`
884
- number of samples.
885
- default size = 100000.
886
- resume : `bool`
887
- resume = False (default) or True.
888
- if True, the function will resume from the last batch.
889
- save_batch : `bool`
890
- if True, the function will save the parameters in batches. if False, the function will save all the parameters at the end of sampling. save_batch=False is faster.
891
- output_jsonfile : `str`
892
- json file name for storing the parameters.
893
- default output_jsonfile = 'unlensed_params.json'. Note that this file will be stored in the self.ler_directory.
894
-
895
- Returns
896
- ----------
897
- unlensed_param : `dict`
898
- dictionary of unlensed GW source parameters. Refer to :attr:`~unlensed_param` for details.
899
-
900
- Examples
901
- ----------
902
- >>> from ler.rates import LeR
903
- >>> ler = LeR()
904
- >>> unlensed_param = ler.unlensed_cbc_statistics()
905
- """
906
-
907
- size = size or self.size
908
- output_jsonfile = output_jsonfile or self.json_file_names["unlensed_param"]
909
- self.json_file_names["unlensed_param"] = output_jsonfile
910
- output_path = os.path.join(self.ler_directory, output_jsonfile)
911
- print(f"unlensed params will be store in {output_path}")
912
-
913
- # sampling in batches
914
- if resume and os.path.exists(output_path):
915
- # get sample from json file
916
- self.dict_buffer = get_param_from_json(output_path)
917
- else:
918
- self.dict_buffer = None
919
-
920
- batch_handler(
921
- size=size,
922
- batch_size=self.batch_size,
923
- sampling_routine=self.unlensed_sampling_routine,
924
- output_jsonfile=output_path,
925
- save_batch=save_batch,
926
- resume=resume,
927
- )
928
-
929
- if save_batch:
930
- unlensed_param = get_param_from_json(output_path)
931
- else:
932
- # this if condition is required if there is nothing to save
933
- if self.dict_buffer:
934
- unlensed_param = self.dict_buffer.copy()
935
- # store all params in json file
936
- print(f"saving all unlensed_params in {output_path} ")
937
- append_json(output_path, unlensed_param, replace=True)
938
- else:
939
- print("unlensed_params already sampled.")
940
- unlensed_param = get_param_from_json(output_path)
941
- self.dict_buffer = None # save memory
942
-
943
- return unlensed_param
944
-
945
- def unlensed_sampling_routine(self, size, output_jsonfile, resume=False, save_batch=True):
946
- """
947
- Function to generate unlensed GW source parameters. This function also stores the parameters in json file in the current batch if save_batch=True.
948
-
949
- Parameters
950
- ----------
951
- size : `int`
952
- number of samples.
953
- default size = 100000.
954
- output_jsonfile : `str`
955
- json file name for storing the parameters.
956
- default output_jsonfile = 'unlensed_params.json'. Note that this file will be stored in the self.ler_directory.
957
- resume : `bool`
958
- resume = False (default) or True.
959
- if True, it appends the new samples to the existing json file.
960
- save_batch : `bool`
961
- if True, the function will save the parameters in batches. if False, the function will save all the parameters at the end of sampling. save_batch=False is faster.
962
-
963
- Returns
964
- ----------
965
- unlensed_param : `dict`
966
- dictionary of unlensed GW source parameters. Refer to :attr:`~unlensed_param` for details.
967
- """
968
-
969
- # get gw params
970
- print("sampling gw source params...")
971
- unlensed_param = self.sample_gw_parameters(size=size)
972
- # Get all of the signal to noise ratios
973
- if self.snr:
974
- print("calculating snrs...")
975
- snrs = self.snr(gw_param_dict=unlensed_param)
976
- unlensed_param.update(snrs)
977
- elif self.pdet:
978
- print("calculating pdet...")
979
- pdet = self.pdet(gw_param_dict=unlensed_param)
980
- unlensed_param.update(pdet)
981
-
982
- # adding batches
983
- if not save_batch:
984
- if self.dict_buffer is None:
985
- self.dict_buffer = unlensed_param
986
- else:
987
- for key, value in unlensed_param.items():
988
- self.dict_buffer[key] = np.concatenate((self.dict_buffer[key], value))
989
- else:
990
- # store all params in json file
991
- self.dict_buffer = append_json(file_name=output_jsonfile, new_dictionary=unlensed_param, old_dictionary=self.dict_buffer, replace=not (resume))
992
-
993
- return unlensed_param
994
-
995
- def unlensed_rate(
996
- self,
997
- unlensed_param=None,
998
- snr_threshold=8.0,
999
- output_jsonfile=None,
1000
- detectability_condition="step_function",
1001
- snr_recalculation=False,
1002
- snr_threshold_recalculation=5.5,
1003
- ):
1004
- """
1005
- Function to calculate the unlensed rate. This function also stores the parameters of the detectable events in json file.
1006
-
1007
- Parameters
1008
- ----------
1009
- unlensed_param : `dict` or `str`
1010
- dictionary of GW source parameters or json file name.
1011
- default unlensed_param = 'unlensed_params.json'.
1012
- snr_threshold : `float`
1013
- threshold for detection signal to noise ratio.
1014
- e.g. snr_threshold = 8.
1015
- output_jsonfile : `str`
1016
- json file name for storing the parameters of the detectable events.
1017
- default output_jsonfile = 'unlensed_params_detectable.json'.
1018
- detectability_condition : `str`
1019
- detectability condition.
1020
- default detectability_condition = 'step_function'.
1021
- other options are 'pdet'.
1022
- snr_recalculation : `bool`
1023
- if True, the SNR of centain events (snr>snr_threshold_recalculation)will be recalculate with 'inner-product' method. This is useful when the snr is calculated with 'ann' method of `gwsnr`.
1024
- default snr_recalculation = False.
1025
- snr_threshold_recalculation : `float`
1026
- threshold for recalculation of detection signal to noise ratio.
1027
-
1028
- Returns
1029
- ----------
1030
- total_rate : `float`
1031
- total unlensed rate (Mpc^-3 yr^-1).
1032
- unlensed_param : `dict`
1033
- dictionary of unlensed GW source parameters of the detectable events. Refer to :attr:`~unlensed_param` for details.
1034
-
1035
- Examples
1036
- ----------
1037
- >>> from ler.rates import LeR
1038
- >>> ler = LeR()
1039
- >>> ler.unlensed_cbc_statistics();
1040
- >>> total_rate, unlensed_param_detectable = ler.unlensed_rate()
1041
- """
1042
-
1043
- # call self.json_file_names["ler_param"] and for adding the final results
1044
- data = load_json(self.ler_directory+"/"+self.json_file_names["ler_params"])
1045
-
1046
- # get gw params from json file if not provided
1047
- if unlensed_param is None:
1048
- unlensed_param = self.json_file_names["unlensed_param"]
1049
- if type(unlensed_param) == str:
1050
- self.json_file_names["unlensed_param"] = unlensed_param
1051
- path_ = self.ler_directory+"/"+unlensed_param
1052
- print(f"getting unlensed_params from json file {path_}...")
1053
- unlensed_param = get_param_from_json(self.ler_directory+"/"+unlensed_param)
1054
- else:
1055
- print("using provided unlensed_param dict...")
1056
- unlensed_param = unlensed_param.copy()
1057
-
1058
- # recalculate snr if required
1059
- # this ensures that the snr is recalculated for the detectable events
1060
- # with inner product
1061
- total_events = len(unlensed_param["zs"])
1062
- if snr_recalculation:
1063
- # select only above centain snr threshold
1064
- param = unlensed_param["optimal_snr_net"]
1065
- idx_detectable = param > snr_threshold_recalculation
1066
- # reduce the size of the dict
1067
- for key, value in unlensed_param.items():
1068
- unlensed_param[key] = value[idx_detectable]
1069
- # recalculate more accurate snrs
1070
- snrs = self.snr_bilby(gw_param_dict=unlensed_param)
1071
- unlensed_param.update(snrs)
1072
-
1073
- if self.snr:
1074
- if "optimal_snr_net" not in unlensed_param:
1075
- raise ValueError("'optimal_snr_net' not in unlensed parm dict provided")
1076
- if detectability_condition == "step_function":
1077
- print("given detectability_condition == 'step_function'")
1078
- param = unlensed_param["optimal_snr_net"]
1079
- threshold = snr_threshold
1080
- elif detectability_condition == "pdet":
1081
- print("given detectability_condition == 'pdet'")
1082
- param = 1 - norm.cdf(snr_threshold - unlensed_param["optimal_snr_net"])
1083
- unlensed_param["pdet_net"] = param
1084
- threshold = 0.5
1085
- elif self.pdet:
1086
- if "pdet_net" in unlensed_param:
1087
- print("given detectability_condition == 'pdet'")
1088
- param = unlensed_param["pdet_net"]
1089
- threshold = 0.5
1090
- else:
1091
- raise ValueError("'pdet_net' not in unlensed parm dict provided")
1092
-
1093
- idx_detectable = param > threshold
1094
- detectable_events = np.sum(idx_detectable)
1095
- # montecarlo integration
1096
- # The total rate R = norm <Theta(rho-rhoc)>
1097
- total_rate = self.normalization_pdf_z * detectable_events / total_events
1098
- print(f"total unlensed rate (yr^-1) (with step function): {total_rate}")
1099
- print(f"number of simulated unlensed detectable events: {detectable_events}")
1100
- print(f"number of all simulated unlensed events: {total_events}")
1101
-
1102
- # store all detectable params in json file
1103
- for key, value in unlensed_param.items():
1104
- unlensed_param[key] = np.array(value)[idx_detectable]
1105
-
1106
- # store all detectable params in json file
1107
- if output_jsonfile is None:
1108
- output_jsonfile = self.json_file_names["unlensed_param_detectable"]
1109
- else:
1110
- self.json_file_names["unlensed_param_detectable"] = output_jsonfile
1111
- path_ = self.ler_directory+"/"+output_jsonfile
1112
- print(f"storing detectable unlensed params in {path_}")
1113
- append_json(self.ler_directory+"/"+output_jsonfile, unlensed_param, replace=True)
1114
-
1115
- # write the results
1116
- data["detectable_unlensed_rate_per_year"] = total_rate
1117
- data["detectability_condition"] = detectability_condition
1118
- append_json(self.ler_directory+"/"+self.json_file_names["ler_params"], data, replace=True)
1119
-
1120
- return total_rate, unlensed_param
1121
-
1122
- def lensed_cbc_statistics(
1123
- self, size=None, save_batch=False, resume=False, output_jsonfile=None,
1124
- ):
1125
- """
1126
- Function to generate lensed GW source parameters. This function calls the lensed_sampling_routine function to generate the parameters in batches. The generated parameters are stored in a json file; and if save_batch=True, it keeps updating the file in batches.
1127
-
1128
- Parameters
1129
- ----------
1130
- size : `int`
1131
- number of samples.
1132
- default size = 100000.
1133
- save_batch : `bool`
1134
- if True, the function will save the parameters in batches. if False, the function will save all the parameters at the end of sampling. save_batch=False is faster.
1135
- resume : `bool`
1136
- resume = False (default) or True.
1137
- if True, the function will resume from the last batch.
1138
- output_jsonfile : `str`
1139
- json file name for storing the parameters.
1140
- default output_jsonfile = 'lensed_params.json'.
1141
-
1142
- Returns
1143
- ----------
1144
- lensed_param : `dict`
1145
- dictionary of lensed GW source parameters. Refer to :attr:`~lensed_param` for details.
1146
-
1147
- Examples
1148
- ----------
1149
- >>> from ler.rates import LeR
1150
- >>> ler = LeR()
1151
- >>> lensed_param = ler.lensed_cbc_statistics()
1152
- """
1153
-
1154
- size = size or self.size
1155
- output_jsonfile = output_jsonfile or self.json_file_names["lensed_param"]
1156
- self.json_file_names["lensed_param"] = output_jsonfile
1157
- output_path = os.path.join(self.ler_directory, output_jsonfile)
1158
- print(f"lensed params will be store in {output_path}")
1159
-
1160
- # sampling in batches
1161
- if resume and os.path.exists(output_path):
1162
- # get sample from json file
1163
- self.dict_buffer = get_param_from_json(output_path)
1164
- else:
1165
- self.dict_buffer = None
1166
-
1167
- batch_handler(
1168
- size=size,
1169
- batch_size=self.batch_size,
1170
- sampling_routine=self.lensed_sampling_routine,
1171
- output_jsonfile=output_path,
1172
- save_batch=save_batch,
1173
- resume=resume,
1174
- )
1175
-
1176
- if save_batch:
1177
- lensed_param = get_param_from_json(output_path)
1178
- else:
1179
- # this if condition is required if there is nothing to save
1180
- if self.dict_buffer:
1181
- lensed_param = self.dict_buffer.copy()
1182
- # store all params in json file
1183
- print(f"saving all lensed_params in {output_path} ")
1184
- append_json(output_path, lensed_param, replace=True)
1185
- else:
1186
- print("lensed_params already sampled.")
1187
- lensed_param = get_param_from_json(output_path)
1188
- self.dict_buffer = None # save memory
1189
-
1190
- return lensed_param
1191
-
1192
- def lensed_sampling_routine(self, size, output_jsonfile, save_batch=True, resume=False):
1193
- """
1194
- Function to generate lensed GW source parameters. This function also stores the parameters in json file in the current batch if save_batch=True.
1195
-
1196
- Parameters
1197
- ----------
1198
- size : `int`
1199
- number of samples.
1200
- default size = 100000.
1201
- output_jsonfile : `str`
1202
- json file name for storing the parameters.
1203
- default output_jsonfile = 'lensed_params.json'. Note that this file will be stored in the self.ler_directory.
1204
- save_batch : `bool`
1205
- if True, the function will save the parameters in batches. if False, the function will save all the parameters at the end of sampling. save_batch=False is faster.
1206
- resume : `bool`
1207
- resume = False (default) or True.
1208
- if True, it appends the new samples to the existing json file.
1209
-
1210
- Returns
1211
- ----------
1212
- lensed_param : `dict`
1213
- dictionary of lensed GW source parameters. Refer to :attr:`~lensed_param` for details.
1214
- """
1215
-
1216
- print("sampling lensed params...")
1217
- lensed_param = {}
1218
-
1219
- while True:
1220
- # get lensed params
1221
- lensed_param_ = self.sample_lens_parameters(size=size)
1222
- # now get (strongly lensed) image paramters along with lens parameters
1223
- lensed_param_ = self.image_properties(lensed_param_)
1224
-
1225
- if len(lensed_param) == 0: # if empty
1226
- lensed_param = lensed_param_
1227
- else:
1228
- # replace the values of the keys
1229
- # idx defines the position that does not satisfy the strong lensing condition
1230
- for key, value in lensed_param_.items():
1231
- lensed_param[key][idx] = value
1232
-
1233
- # check for invalid samples
1234
- idx = lensed_param["n_images"] < 2
1235
-
1236
- if np.sum(idx) == 0:
1237
- break
1238
- else:
1239
- print(f"Invalid sample found. Resampling {np.sum(idx)} lensed events...")
1240
- size = np.sum(idx)
1241
-
1242
- # Get all of the signal to noise ratios
1243
- if self.snr:
1244
- print("calculating snrs...")
1245
- snrs, lensed_param = self.get_lensed_snrs(
1246
- lensed_param=lensed_param,
1247
- list_of_detectors=self.list_of_detectors,
1248
- snr_calculator=self.snr,
1249
- )
1250
- lensed_param.update(snrs)
1251
-
1252
- elif self.pdet:
1253
- print("calculating pdet...")
1254
- pdet, lensed_param = self.get_lensed_snrs(
1255
- lensed_param=lensed_param,
1256
- list_of_detectors=self.list_of_detectors,
1257
- pdet_calculator=self.pdet,
1258
- )
1259
- lensed_param.update(pdet)
1260
-
1261
- # adding batches
1262
- if not save_batch:
1263
- if self.dict_buffer is None:
1264
- self.dict_buffer = lensed_param
1265
- else:
1266
- for key, value in lensed_param.items():
1267
- self.dict_buffer[key] = np.concatenate((self.dict_buffer[key], value))
1268
- else:
1269
- # store all params in json file
1270
- self.dict_buffer = append_json(file_name=output_jsonfile, new_dictionary=lensed_param, old_dictionary=self.dict_buffer, replace=not (resume))
1271
-
1272
- return lensed_param
1273
-
1274
- def lensed_rate(
1275
- self,
1276
- lensed_param=None,
1277
- snr_threshold=[8.0,8.0],
1278
- num_img=[1,1],
1279
- output_jsonfile=None,
1280
- nan_to_num=True,
1281
- detectability_condition="step_function",
1282
- snr_recalculation=False,
1283
- snr_threshold_recalculation=[5.5,5.5],
1284
- ):
1285
- """
1286
- Function to calculate the lensed rate. This function also stores the parameters of the detectable events in json file.
1287
-
1288
- Parameters
1289
- ----------
1290
- lensed_param : `dict` or `str`
1291
- dictionary of GW source parameters or json file name.
1292
- default lensed_param = 'lensed_params.json'.
1293
- snr_threshold : `float`
1294
- threshold for detection signal to noise ratio.
1295
- default snr_threshold = [8.0,8.0].
1296
- num_img : `int`
1297
- number of images.
1298
- default num_img = [1,1]. Together with snr_threshold = [8.0,8.0], it means that two images with snr>8.0. Same condition can also be represented by snr_threshold = 8.0 and num_img = 2.
1299
- output_jsonfile : `str`
1300
- json file name for storing the parameters of the detectable events.
1301
- default output_jsonfile = 'lensed_params_detectable.json'.
1302
- nan_to_num : `bool`
1303
- if True, nan values will be converted to 0.
1304
- default nan_to_num = True.
1305
- detectability_condition : `str`
1306
- detectability condition.
1307
- default detectability_condition = 'step_function'.
1308
- other options are 'pdet'.
1309
- snr_recalculation : `bool`
1310
- if True, the SNR of centain events (snr>snr_threshold_recalculation)will be recalculate with 'inner-product' method. This is useful when the snr is calculated with 'ann' method of `gwsnr`.
1311
- default snr_recalculation = False.
1312
- snr_threshold_recalculation : `float`
1313
- threshold for recalculation of detection signal to noise ratio.
1314
- default snr_threshold_recalculation = [5.5,5.5].
1315
-
1316
- Returns
1317
- ----------
1318
- total_rate : `float`
1319
- total lensed rate (Mpc^-3 yr^-1).
1320
- lensed_param : `dict`
1321
- dictionary of lensed GW source parameters of the detectable events. Refer to :attr:`~lensed_param` for details.
1322
-
1323
- Examples
1324
- ----------
1325
- >>> from ler.rates import LeR
1326
- >>> ler = LeR()
1327
- >>> ler.lensed_cbc_statistics();
1328
- >>> total_rate, lensed_param_detectable = ler.lensed_rate()
1329
- """
1330
-
1331
- # call self.json_file_names["ler_param"] and for adding the final results
1332
- data = load_json(self.ler_directory+"/"+self.json_file_names["ler_params"])
1333
-
1334
- # get gw params from json file if not provided
1335
- if lensed_param is None:
1336
- lensed_param = self.json_file_names["lensed_param"]
1337
- if type(lensed_param) == str:
1338
- self.json_file_names["lensed_param"] = lensed_param
1339
- path_ = self.ler_directory+"/"+lensed_param
1340
- print(f"getting lensed_params from json file {path_} ")
1341
- lensed_param = get_param_from_json(self.ler_directory+"/"+lensed_param)
1342
- else:
1343
- print("using provided lensed_param dict...")
1344
- lensed_param = lensed_param.copy()
1345
-
1346
- # check for images with snr above threshold
1347
- # convert to array
1348
- snr_threshold_ = np.array([snr_threshold]).reshape(-1)
1349
- num_img_ = np.array([num_img]).reshape(-1)
1350
- # get descending sorted idx of snr_threshold
1351
- idx = np.argsort(-snr_threshold_)
1352
- snr_threshold = snr_threshold_[idx]
1353
- num_img = num_img_[idx]
1354
-
1355
- # get size of the lensed_param for a parameter
1356
- total_events = len(lensed_param["zs"])
1357
- # recalculate snr if required
1358
- # this ensures that the snr is recalculated for the detectable events
1359
- # with inner product
1360
- ############################
1361
- # for ANN SNR #
1362
- ############################
1363
- if snr_recalculation:
1364
- # dealing with provided snr_threshold_recalculation
1365
- snr_threshold_recalculation = np.array([snr_threshold_recalculation]).reshape(-1)
1366
- idx = np.argsort(-snr_threshold_recalculation)
1367
- snr_threshold_recalculation = snr_threshold_recalculation[idx]
1368
- num_img_recalculation = num_img[idx]
1369
-
1370
- # check optimal_snr_net is provided in dict
1371
- snr_param = lensed_param["optimal_snr_net"]
1372
- if "optimal_snr_net" in lensed_param.keys():
1373
- snr_param = -np.sort(-snr_param, axis=1) # sort snr in descending order
1374
- else:
1375
- print("optimal_snr_net not provided in lensed_param dict. Exiting...")
1376
- return None
1377
- # for each row: choose a threshold and check if the number of images above threshold. Sum over the images. If sum is greater than num_img, then snr_hit = True
1378
- j = 0
1379
- idx_max = 0
1380
- snr_hit = np.full(total_events, True) # boolean array to store the result of the threshold condition
1381
- for i in range(len(snr_threshold_recalculation)):
1382
- idx_max = idx_max + num_img_recalculation[i]
1383
- snr_hit = snr_hit & (np.sum((snr_param[:,j:idx_max] > snr_threshold_recalculation[i]), axis=1) >= num_img_recalculation[i])
1384
- j = idx_max
1385
-
1386
- # reduce the size of the dict
1387
- for key, value in lensed_param.items():
1388
- lensed_param[key] = value[snr_hit]
1389
- # recalculate more accurate snrs
1390
- print("calculating snrs...")
1391
- snrs, lensed_param = self.get_lensed_snrs(
1392
- snr_calculator=self.snr_bilby,
1393
- list_of_detectors=self.list_of_detectors,
1394
- lensed_param=lensed_param,
1395
- )
1396
- lensed_param.update(snrs)
1397
- ############################
1398
-
1399
- if self.snr:
1400
- if "optimal_snr_net" not in lensed_param:
1401
- raise ValueError("'optimal_snr_net' not in lensed parm dict provided")
1402
- if detectability_condition == "step_function":
1403
- print("given detectability_condition == 'step_function'")
1404
-
1405
- if "optimal_snr_net" in lensed_param.keys():
1406
- snr_param = lensed_param["optimal_snr_net"]
1407
- snr_param = -np.sort(-snr_param, axis=1) # sort snr in descending order
1408
- else:
1409
- print("snr not provided in lensed_param dict. Exiting...")
1410
- return None
1411
- snr_hit = np.full(len(snr_param), True) # boolean array to store the result of the threshold condition
1412
-
1413
- # for each row: choose a threshold and check if the number of images above threshold. Sum over the images. If sum is greater than num_img, then snr_hit = True
1414
- j = 0
1415
- idx_max = 0
1416
- for i in range(len(snr_threshold)):
1417
- idx_max = idx_max + num_img[i]
1418
- snr_hit = snr_hit & (np.sum((snr_param[:,j:idx_max] > snr_threshold[i]), axis=1) >= num_img[i])
1419
- j = idx_max
1420
-
1421
- # montecarlo integration
1422
- total_rate = self.normalization_pdf_z_lensed * np.sum(snr_hit)/total_events
1423
- print("total lensed rate (yr^-1) (with step function): {}".format(total_rate))
1424
-
1425
- elif detectability_condition == "pdet":
1426
- print("given detectability_condition == 'pdet'")
1427
- # pdet dimension is (size, n_max_images)
1428
- snr_param = lensed_param["optimal_snr_net"]
1429
- snr_param = -np.sort(-snr_param, axis=1) # sort snr in descending order
1430
-
1431
- pdet = np.ones(np.shape(snr_param))
1432
- j = 0
1433
- idx_max = 0
1434
- for i in range(len(snr_threshold)):
1435
- idx_max = idx_max + num_img[i]
1436
- pdet[:,j:idx_max] = 1 - norm.cdf(snr_threshold[i] - snr_param[:,j:idx_max])
1437
- j = idx_max
1438
-
1439
- snr_hit = np.prod(pdet, axis=1)>0.5
1440
- # montecarlo integration
1441
- total_rate = self.normalization_pdf_z_lensed * np.sum(snr_hit)/total_events
1442
- print(f"total lensed rate (yr^-1) (with pdet function): {total_rate}")
1443
-
1444
- elif self.pdet:
1445
- # check if pdet is provided in lensed_param dict
1446
- if "pdet_net" in lensed_param.keys():
1447
- print("given detectability_condition == 'pdet'")
1448
- pdet = lensed_param["pdet_net"]
1449
- pdet = -np.sort(-pdet, axis=1) # sort pdet in descending order
1450
- pdet = pdet[:,:np.sum(num_img)] # use only num_img images
1451
-
1452
- snr_hit = np.prod(pdet, axis=1)>0.5
1453
- # montecarlo integration
1454
- total_rate = self.normalization_pdf_z_lensed * np.sum(snr_hit)/total_events
1455
- print(f"total lensed rate (yr^-1) (with pdet function): {total_rate}")
1456
-
1457
- else:
1458
- raise ValueError("'pdet_net' not in unlensed parm dict provided")
1459
-
1460
- print(f"number of simulated lensed detectable events: {np.sum(snr_hit)}")
1461
- print(f"number of simulated all lensed events: {total_events}")
1462
- # store all detectable params in json file
1463
- if nan_to_num:
1464
- for key, value in lensed_param.items():
1465
- lensed_param[key] = np.nan_to_num(value[snr_hit])
1466
- else:
1467
- for key, value in lensed_param.items():
1468
- lensed_param[key] = value[snr_hit]
1469
-
1470
- # store all detectable params in json file
1471
- if output_jsonfile is None:
1472
- output_jsonfile = self.json_file_names["lensed_param_detectable"]
1473
- else:
1474
- self.json_file_names["lensed_param_detectable"] = output_jsonfile
1475
- path_ = self.ler_directory+"/"+output_jsonfile
1476
- print(f"storing detectable lensed params in {path_}")
1477
- append_json(self.ler_directory+"/"+output_jsonfile, lensed_param, replace=True)
1478
-
1479
- # write the results
1480
- data["detectable_lensed_rate_per_year"] = total_rate
1481
- data["detectability_condition"] = detectability_condition
1482
- append_json(self.ler_directory+"/"+self.json_file_names["ler_params"], data, replace=True)
1483
-
1484
- return total_rate, lensed_param
1485
-
1486
- def rate_ratio(self):
1487
- """
1488
- Function to calculate and display unlensed and lensed merger rate ratio. It will get the unlensed_rate and lensed_rate from files corresponding to the names included in self.json_file_ler_param.
1489
-
1490
- Returns
1491
- ----------
1492
- rate_ratio : `float`
1493
- rate ratio.
1494
-
1495
- Examples
1496
- ----------
1497
- >>> from ler.rates import LeR
1498
- >>> ler = LeR()
1499
- >>> ler.unlensed_cbc_statistics();
1500
- >>> ler.lensed_cbc_statistics();
1501
- >>> ler.unlensed_rate();
1502
- >>> ler.lensed_rate();
1503
- >>> ler.rate_ratio()
1504
- """
1505
-
1506
- # call json_file_ler_param and add the results
1507
- data = load_json(self.ler_directory+"/"+self.json_file_names["ler_params"])
1508
-
1509
- try:
1510
- unlensed_rate = data['detectable_unlensed_rate_per_year']
1511
- lensed_rate = data['detectable_lensed_rate_per_year']
1512
- except:
1513
- raise ValueError(f"detectable_unlensed_rate_per_year or 'detectable_lensed_rate_per_year' not found in {self.json_file_names['ler_params']} json file. Exiting...")
1514
-
1515
- rate_ratio = unlensed_rate / lensed_rate
1516
- # append the results
1517
- data['rate_ratio'] = rate_ratio
1518
- # write the results
1519
- append_json(self.ler_directory+"/"+self.json_file_names["ler_params"], data, replace=True)
1520
-
1521
- print(f"unlensed_rate: {unlensed_rate}")
1522
- print(f"lensed_rate: {lensed_rate}")
1523
- print(f"ratio: {rate_ratio}")
1524
-
1525
- return unlensed_rate / lensed_rate
1526
-
1527
- def rate_comparision_with_rate_calculation(
1528
- self,
1529
- unlensed_param=None,
1530
- snr_threshold_unlensed=8.0,
1531
- output_jsonfile_unlensed=None,
1532
- lensed_param=None,
1533
- snr_threshold_lensed=[8.0,8.0],
1534
- num_img=[1,1],
1535
- output_jsonfile_lensed=None,
1536
- nan_to_num=True,
1537
- detectability_condition="step_function",
1538
- ):
1539
- """
1540
- Function to calculate the unlensed and lensed rate and compare by computing the ratio. This function also stores the parameters of the detectable events in json file. If you use this function, you do not need to call the functions unlensed_rate and lensed_rate separately.
1541
-
1542
- Parameters
1543
- ----------
1544
- unlensed_param : `dict` or `str`
1545
- dictionary of GW source parameters or json file name.
1546
- default unlensed_param = 'unlensed_params.json'.
1547
- snr_threshold_unlensed : `float`
1548
- threshold for detection signal to noise ratio.
1549
- e.g. snr_threshold_unlensed = 8.
1550
- output_jsonfile_unlensed : `str`
1551
- json file name for storing the parameters of the detectable events.
1552
- default output_jsonfile_unlensed = 'unlensed_params_detectable.json'.
1553
- lensed_param : `dict` or `str`
1554
- dictionary of GW source parameters or json file name.
1555
- default lensed_param = 'lensed_params.json'.
1556
- snr_threshold_lensed : `float`
1557
- threshold for detection signal to noise ratio.
1558
- default snr_threshold_lensed = [8.0,8.0].
1559
- num_img : `int`
1560
- number of images.
1561
- default num_img = [1,1]. Together with snr_threshold = [8.0,8.0], it means that two images with snr>8.0. Same condition can also be represented by snr_threshold = 8.0 and num_img = 2.
1562
- output_jsonfile_lensed : `str`
1563
- json file name for storing the parameters of the detectable events.
1564
- default output_jsonfile_lensed = 'lensed_params_detectable.json'.
1565
- nan_to_num : `bool`
1566
- if True, nan values will be converted to 0.
1567
- default nan_to_num = True.
1568
- detectability_condition : `str`
1569
- detectability condition.
1570
- default detectability_condition = 'step_function'.
1571
- other options are 'pdet'.
1572
-
1573
- Returns
1574
- ----------
1575
- rate_ratio : `float`
1576
- rate ratio.
1577
- unlensed_param : `dict`
1578
- dictionary of unlensed GW source parameters of the detectable events. Refer to :attr:`~unlensed_param` for details.
1579
- lensed_param : `dict`
1580
- dictionary of lensed GW source parameters of the detectable events. Refer to :attr:`~lensed_param` for details.
1581
-
1582
- Examples
1583
- ----------
1584
- >>> from ler.rates import LeR
1585
- >>> ler = LeR()
1586
- >>> ler.unlensed_cbc_statistics();
1587
- >>> ler.lensed_cbc_statistics();
1588
- >>> rate_ratio, unlensed_param, lensed_param = ler.rate_comparision_with_rate_calculation()
1589
- """
1590
-
1591
- # call json_file_ler_param and add the results
1592
- data = load_json(self.ler_directory+"/"+self.json_file_names["ler_params"])
1593
-
1594
- # get unlensed rate
1595
- unlensed_rate, unlensed_param = self.unlensed_rate(
1596
- unlensed_param=unlensed_param,
1597
- snr_threshold=snr_threshold_unlensed,
1598
- output_jsonfile=output_jsonfile_unlensed,
1599
- detectability_condition=detectability_condition,
1600
- )
1601
- # get lensed rate
1602
- lensed_rate, lensed_param = self.lensed_rate(
1603
- lensed_param=lensed_param,
1604
- snr_threshold=snr_threshold_lensed,
1605
- num_img=num_img,
1606
- output_jsonfile=output_jsonfile_lensed,
1607
- nan_to_num=nan_to_num,
1608
- detectability_condition=detectability_condition,
1609
- )
1610
- # calculate rate ratio
1611
- rate_ratio = unlensed_rate / lensed_rate
1612
- # append the results
1613
- data['detectable_unlensed_rate_per_year'] = unlensed_rate
1614
- data['detectable_lensed_rate_per_year'] = lensed_rate
1615
- data['rate_ratio'] = rate_ratio
1616
- data['detectability_condition'] = detectability_condition
1617
- # write the results
1618
- append_json(self.ler_directory+"/"+self.json_file_names["ler_params"], data, replace=True)
1619
-
1620
- print(f"unlensed_rate (per year): {unlensed_rate}")
1621
- print(f"lensed_rate (per year): {lensed_rate}")
1622
- print(f"ratio: {rate_ratio}")
1623
-
1624
- return rate_ratio, unlensed_param, lensed_param
1625
-
1626
- def selecting_n_unlensed_detectable_events(
1627
- self,
1628
- size=100,
1629
- batch_size=None,
1630
- snr_threshold=8.0,
1631
- resume=False,
1632
- output_jsonfile="n_unlensed_param_detectable.json",
1633
- meta_data_file="meta_unlensed.json",
1634
- detectability_condition="step_function",
1635
- trim_to_size=True,
1636
- snr_recalculation=False,
1637
- snr_threshold_recalculation=5.5,
1638
- ):
1639
- """
1640
- Function to generate n unlensed detectable events. This fuction samples the unlensed parameters and save only the detectable events in json file. It also records metadata in the JSON file, which includes the total number of events and the cumulative rate of events. This functionality is particularly useful for generating a fixed or large number of detectable events until the event rates stabilize.
1641
-
1642
- Parameters
1643
- ----------
1644
- size : `int`
1645
- number of samples to be selected.
1646
- default size = 100.
1647
- batch_size : `int`
1648
- batch size for sampling.
1649
- default batch_size = 50000.
1650
- snr_threshold : `float`
1651
- threshold for detection signal to noise ratio.
1652
- e.g. snr_threshold = 8.
1653
- resume : `bool`
1654
- resume = False (default) or True.
1655
- if True, the function will resume from the last batch.
1656
- output_jsonfile : `str`
1657
- json file name for storing the parameters of the detectable events.
1658
- default output_jsonfile = 'n_unlensed_param_detectable.json'.
1659
- meta_data_file : `str`
1660
- json file name for storing the metadata.
1661
- default meta_data_file = 'meta_unlensed.json'.
1662
- detectability_condition : `str`
1663
- detectability condition.
1664
- default detectability_condition = 'step_function'.
1665
- other options are 'pdet'.
1666
- trim_to_size : `bool`
1667
- if True, the final result will be trimmed to size.
1668
- default trim_to_size = True.
1669
- snr_recalculation : `bool`
1670
- if True, the SNR of centain events (snr>snr_threshold_recalculation)will be recalculate with 'inner-product' method. This is useful when the snr is calculated with 'ann' method of `gwsnr`.
1671
- default snr_recalculation = False.
1672
- snr_threshold_recalculation : `float`
1673
- threshold for recalculation of detection signal to noise ratio.
1674
- default snr_threshold_recalculation = 5.5.
1675
-
1676
- Returns
1677
- ----------
1678
- param_final : `dict`
1679
- dictionary of unlensed GW source parameters of the detectable events. Refer to :attr:`~unlensed_param` for details.
1680
-
1681
- Examples
1682
- ----------
1683
- >>> from ler.rates import LeR
1684
- >>> ler = LeR()
1685
- >>> unlensed_param = ler.selecting_n_unlensed_detectable_events(size=100)
1686
- """
1687
-
1688
- meta_data_path = self.ler_directory+"/"+meta_data_file
1689
- output_path = self.ler_directory+"/"+output_jsonfile
1690
-
1691
- if batch_size is None:
1692
- batch_size = self.batch_size
1693
- else:
1694
- self.batch_size = batch_size
1695
-
1696
- if not resume:
1697
- n = 0 # iterator
1698
- events_total = 0
1699
- if os.path.exists(output_path):
1700
- os.remove(output_path)
1701
- if os.path.exists(meta_data_path):
1702
- os.remove(meta_data_path)
1703
- else:
1704
- # get sample size as size from json file
1705
- if os.path.exists(output_path):
1706
- param_final = get_param_from_json(output_path)
1707
- n = len(param_final["zs"])
1708
- events_total = load_json(meta_data_path)["events_total"][-1]
1709
- del param_final
1710
- else:
1711
- n = 0
1712
- events_total = 0
1713
-
1714
- buffer_file = self.ler_directory+"/"+"unlensed_params_buffer.json"
1715
- print("collected number of detectable events = ", n)
1716
- # loop until n samples are collected
1717
- while n < size:
1718
- # disable print statements
1719
- with contextlib.redirect_stdout(None):
1720
- self.dict_buffer = None
1721
- unlensed_param = self.unlensed_sampling_routine(
1722
- size=batch_size, output_jsonfile=buffer_file, save_batch=False,resume=False
1723
- )
1724
-
1725
- total_events_in_this_iteration = len(unlensed_param["zs"])
1726
- ############################
1727
- # for ANN SNR #
1728
- ############################
1729
- if snr_recalculation:
1730
- # select only above centain snr threshold
1731
- param = unlensed_param["optimal_snr_net"]
1732
- idx_detectable = param > snr_threshold_recalculation
1733
- # reduce the size of the dict
1734
- for key, value in unlensed_param.items():
1735
- unlensed_param[key] = value[idx_detectable]
1736
- # recalculate more accurate snrs
1737
- snrs = self.snr_bilby(gw_param_dict=unlensed_param)
1738
- unlensed_param.update(snrs)
1739
- ############################
1740
-
1741
- if self.snr:
1742
- if "optimal_snr_net" not in unlensed_param:
1743
- raise ValueError("'optimal_snr_net' not in unlensed parm dict provided")
1744
- if detectability_condition == "step_function":
1745
- #print("given detectability_condition == 'step_function'")
1746
- param = unlensed_param["optimal_snr_net"]
1747
- threshold = snr_threshold
1748
- elif detectability_condition == "pdet":
1749
- # print("given detectability_condition == 'pdet'")
1750
- param = 1 - norm.cdf(snr_threshold - unlensed_param["optimal_snr_net"])
1751
- unlensed_param["pdet_net"] = param
1752
- threshold = 0.5
1753
- elif self.pdet:
1754
- if "pdet_net" in unlensed_param:
1755
- #print("given detectability_condition == 'pdet'")
1756
- param = unlensed_param["pdet_net"]
1757
- threshold = 0.5
1758
- else:
1759
- raise ValueError("'pdet_net' not in unlensed parm dict provided")
1760
-
1761
- # index of detectable events
1762
- idx = param > threshold
1763
-
1764
- # store all params in json file
1765
- for key, value in unlensed_param.items():
1766
- unlensed_param[key] = value[idx]
1767
- append_json(file_name=output_path, new_dictionary=unlensed_param, replace=False)
1768
-
1769
- n += np.sum(idx)
1770
- events_total += total_events_in_this_iteration
1771
- total_rate = self.normalization_pdf_z * n / events_total
1772
-
1773
- # save meta data
1774
- meta_data = dict(events_total=[events_total], detectable_events=[float(n)], total_rate=[total_rate])
1775
- if os.path.exists(meta_data_path):
1776
- append_json(file_name=meta_data_path, new_dictionary=meta_data, replace=False)
1777
- else:
1778
- append_json(file_name=meta_data_path, new_dictionary=meta_data, replace=True)
1779
-
1780
- print("collected number of detectable events = ", n)
1781
- print("total number of events = ", events_total)
1782
- print(f"total unlensed rate (yr^-1): {total_rate}")
1783
-
1784
- print(f"storing detectable unlensed params in {output_path}")
1785
- print(f"storing meta data in {meta_data_path}")
1786
-
1787
- if trim_to_size:
1788
- # trim the final param dictionary
1789
- print(f"\n trmming final result to size={size}")
1790
- param_final = get_param_from_json(output_path)
1791
- # randomly select size number of samples
1792
- len_ = len(list(param_final.values())[0])
1793
- idx = np.random.choice(len_, size, replace=False)
1794
- # trim the final param dictionary, randomly, without repeating
1795
- for key, value in param_final.items():
1796
- param_final[key] = value[idx]
1797
-
1798
- # change meta data
1799
- meta_data = load_json(meta_data_path)
1800
- old_events_total = meta_data["events_total"][-1]
1801
- old_detectable_events = meta_data["detectable_events"][-1]
1802
-
1803
- # adjust the meta data
1804
- # following is to keep rate the same
1805
- new_events_total = np.round(size*old_events_total/old_detectable_events)
1806
- new_total_rate = self.normalization_pdf_z * size / new_events_total
1807
- meta_data["events_total"][-1] = new_events_total
1808
- meta_data["detectable_events"][-1] = size
1809
- meta_data["total_rate"][-1] = new_total_rate
1810
-
1811
-
1812
- print("collected number of detectable events = ", size)
1813
- print("total number of events = ", new_events_total)
1814
- print(f"total unlensed rate (yr^-1): {new_total_rate}")
1815
-
1816
- # save the meta data
1817
- append_json(meta_data_path, meta_data, replace=True)
1818
- # save the final param dictionary
1819
- append_json(output_path, param_final, replace=True)
1820
- else:
1821
- param_final = get_param_from_json(output_path)
1822
-
1823
- return param_final
1824
-
1825
- def selecting_n_lensed_detectable_events(
1826
- self,
1827
- size=100,
1828
- batch_size=None,
1829
- snr_threshold=[8.0,8.0],
1830
- num_img=[1,1],
1831
- resume=False,
1832
- detectability_condition="step_function",
1833
- output_jsonfile="n_lensed_params_detectable.json",
1834
- meta_data_file="meta_lensed.json",
1835
- trim_to_size=True,
1836
- nan_to_num=False,
1837
- snr_recalculation=False,
1838
- snr_threshold_recalculation=[5.5,5.5],
1839
- ):
1840
- """
1841
- Function to generate n lensed detectable events. This fuction only samples the lensed parameters and save only the detectable events in json file. It also records metadata in the JSON file, which includes the total number of events and the cumulative rate of events. This functionality is particularly useful for generating a fixed or large number of detectable events until the event rates stabilize.
1842
-
1843
- Parameters
1844
- ----------
1845
- size : `int`
1846
- number of samples.
1847
- default size = 100.
1848
- batch_size : `int`
1849
- batch size for sampling.
1850
- default batch_size = 50000.
1851
- snr_threshold : `float`
1852
- threshold for detection signal to noise ratio.
1853
- default snr_threshold = [8.0,8.0].
1854
- num_img : `int`
1855
- number of images.
1856
- default num_img = [1,1]. Together with snr_threshold = [8.0,8.0], it means that two images with snr>8.0. Same condition can also be represented by snr_threshold = 8.0 and num_img = 2.
1857
- resume : `bool`
1858
- resume = False (default) or True.
1859
- if True, it appends the new samples to the existing json file.
1860
- detectability_condition : `str`
1861
- detectability condition.
1862
- default detectability_condition = 'step_function'.
1863
- other options are 'pdet'.
1864
- output_jsonfile : `str`
1865
- json file name for storing the parameters of the detectable events.
1866
- default output_jsonfile = 'n_lensed_params_detectable.json'.
1867
- meta_data_file : `str`
1868
- json file name for storing the metadata.
1869
- default meta_data_file = 'meta_lensed.json'.
1870
- trim_to_size : `bool`
1871
- if True, the final result will be trimmed to size.
1872
- default trim_to_size = True.
1873
- nan_to_num : `bool`
1874
- if True, nan values will be converted to 0.
1875
- default nan_to_num = False.
1876
- snr_recalculation : `bool`
1877
- if True, the SNR of centain events (snr>snr_threshold_recalculation)will be recalculate with 'inner-product' method. This is useful when the snr is calculated with 'ann' method of `gwsnr`.
1878
- default snr_recalculation = False.
1879
- snr_threshold_recalculation : `float`
1880
- threshold for recalculation of detection signal to noise ratio.
1881
- default snr_threshold_recalculation = [5.5,5.5].
1882
-
1883
- Returns
1884
- ----------
1885
- param_final : `dict`
1886
- dictionary of lensed GW source parameters of the detectable events. Refer to :attr:`~lensed_param` for details.
1887
-
1888
- Examples
1889
- ----------
1890
- >>> from ler.rates import LeR
1891
- >>> ler = LeR()
1892
- >>> lensed_param = ler.selecting_n_lensed_detectable_events(size=100)
1893
- """
1894
-
1895
- meta_data_path = self.ler_directory+"/"+meta_data_file
1896
- output_path = self.ler_directory+"/"+output_jsonfile
1897
- if meta_data_path==output_path:
1898
- raise ValueError("meta_data_file and output_jsonfile cannot be same.")
1899
-
1900
- if batch_size is None:
1901
- batch_size = self.batch_size
1902
- else:
1903
- self.batch_size = batch_size
1904
-
1905
- if not resume:
1906
- n = 0 # iterator
1907
- events_total = 0
1908
- if os.path.exists(output_path):
1909
- os.remove(output_path)
1910
- if os.path.exists(meta_data_path):
1911
- os.remove(meta_data_path)
1912
- else:
1913
- # get sample size as size from json file
1914
- try:
1915
- param_final = get_param_from_json(output_path)
1916
- n = load_json(meta_data_path)["detectable_events"][-1]
1917
- events_total = load_json(meta_data_path)["events_total"][-1]
1918
- del param_final
1919
- except:
1920
- n = 0
1921
- events_total = 0
1922
-
1923
- # check for images with snr above threshold
1924
- # convert to array
1925
- snr_threshold = np.array([snr_threshold]).reshape(-1)
1926
- num_img = np.array([num_img]).reshape(-1)
1927
- # get descending sorted idx of snr_threshold
1928
- idx = np.argsort(-snr_threshold)
1929
- snr_threshold = snr_threshold[idx]
1930
- num_img = num_img[idx]
1931
-
1932
- buffer_file = self.ler_directory+"/"+"lensed_params_buffer.json"
1933
- print("collected number of detectable events = ", n)
1934
- # loop until n samples are collected
1935
- while n < size:
1936
- # disable print statements
1937
- with contextlib.redirect_stdout(None):
1938
- self.dict_buffer = None
1939
- lensed_param = self.lensed_sampling_routine(
1940
- size=self.batch_size, output_jsonfile=buffer_file, resume=False
1941
- ) # Dimensions are (size, n_max_images)
1942
-
1943
- total_events_in_this_iteration = len(lensed_param["zs"])
1944
- ############################
1945
- # for ANN SNR #
1946
- ############################
1947
- if snr_recalculation:
1948
- # dealing with provided snr_threshold_recalculation
1949
- snr_threshold_recalculation = np.array([snr_threshold_recalculation]).reshape(-1)
1950
- idx = np.argsort(-snr_threshold_recalculation)
1951
- snr_threshold_recalculation = snr_threshold_recalculation[idx]
1952
- num_img_recalculation = num_img[idx]
1953
-
1954
- # check optimal_snr_net is provided in dict
1955
- snr_param = lensed_param["optimal_snr_net"]
1956
- if "optimal_snr_net" in lensed_param.keys():
1957
- snr_param = -np.sort(-snr_param, axis=1) # sort snr in descending order
1958
- else:
1959
- raise ValueError("optimal_snr_net not provided in lensed_param dict. Exiting...")
1960
-
1961
- # for each row: choose a threshold and check if the number of images above threshold. Sum over the images. If sum is greater than num_img, then snr_hit = True
1962
- j = 0
1963
- idx_max = 0
1964
- snr_hit = np.full(len(snr_param), True) # boolean array to store the result of the threshold condition
1965
- for i, snr_th in enumerate(snr_threshold_recalculation):
1966
- idx_max = idx_max + num_img_recalculation[i]
1967
-
1968
- snr_hit = snr_hit & (np.sum((snr_param[:,j:idx_max] > snr_th), axis=1) >= num_img_recalculation[i])
1969
- j = idx_max
1970
-
1971
- # reduce the size of the dict
1972
- for key, value in lensed_param.items():
1973
- lensed_param[key] = value[snr_hit]
1974
- # recalculate more accurate snrs
1975
- print("calculating snrs...")
1976
- snrs, lensed_param = self.get_lensed_snrs(
1977
- snr_calculator=self.snr_bilby,
1978
- list_of_detectors=self.list_of_detectors,
1979
- lensed_param=lensed_param,
1980
- )
1981
- lensed_param.update(snrs)
1982
- ############################
1983
-
1984
- if detectability_condition == "step_function":
1985
- snr_hit = np.full(len(lensed_param["zs"]), True) # boolean array to store the result of the threshold condition
1986
- try:
1987
- snr_param = lensed_param["optimal_snr_net"]
1988
- snr_param = -np.sort(-snr_param, axis=1) # sort snr in descending order
1989
- except:
1990
- raise ValueError("snr not provided in lensed_param dict. Exiting...")
1991
-
1992
- # for each row: choose a threshold and check if the number of images above threshold. Sum over the images. If sum is greater than num_img, then snr_hit = True
1993
- j = 0
1994
- idx_max = 0
1995
- for i in range(len(snr_threshold)):
1996
- idx_max = idx_max + num_img[i]
1997
- snr_hit = snr_hit & (np.sum((snr_param[:,j:idx_max] > snr_threshold[i]), axis=1) >= num_img[i])
1998
- j = idx_max
1999
-
2000
- elif detectability_condition == "pdet":
2001
- # check if pdet is provided in unlensed_param dict
2002
- if "pdet_net" in lensed_param.keys():
2003
- pdet = lensed_param["pdet_net"]
2004
- pdet = -np.sort(-pdet, axis=1) # sort pdet in descending order
2005
- pdet = pdet[:,:np.sum(num_img)] # use only num_img images
2006
- else:
2007
- if "optimal_snr_net" in lensed_param.keys():
2008
- # pdet dimension is (size, n_max_images)
2009
- snr_param = lensed_param["optimal_snr_net"]
2010
- snr_param = -np.sort(-snr_param, axis=1) # sort snr in descending order
2011
-
2012
- pdet = np.ones(np.shape(snr_param))
2013
- j = 0
2014
- idx_max = 0
2015
- for i in range(len(snr_threshold)):
2016
- idx_max = idx_max + num_img[i]
2017
- pdet[:,j:idx_max] = 1 - norm.cdf(snr_threshold[i] - snr_param[:,j:idx_max])
2018
- j = idx_max
2019
- else:
2020
- print("pdet or optimal_snr_net not provided in lensed_param dict. Exiting...")
2021
- return None
2022
-
2023
- snr_hit = np.prod(pdet, axis=1)>0.5
2024
-
2025
- # store all params in json file
2026
- if nan_to_num:
2027
- for key, value in lensed_param.items():
2028
- lensed_param[key] = np.nan_to_num(value[snr_hit])
2029
- else:
2030
- for key, value in lensed_param.items():
2031
- lensed_param[key] = value[snr_hit]
2032
-
2033
- if os.path.exists(output_path):
2034
- try:
2035
- append_json(output_path, lensed_param, replace=False)
2036
- except:
2037
- append_json(output_path, lensed_param, replace=True)
2038
- else:
2039
- append_json(output_path, lensed_param, replace=True)
2040
-
2041
- n += np.sum(snr_hit)
2042
- events_total += total_events_in_this_iteration
2043
-
2044
- # save meta data
2045
- total_rate = self.normalization_pdf_z_lensed * n / events_total
2046
- meta_data = dict(events_total=[events_total], detectable_events=[float(n)], total_rate=[total_rate])
2047
- if os.path.exists(meta_data_path):
2048
- append_json(meta_data_path, meta_data, replace=False)
2049
- else:
2050
- append_json(meta_data_path, meta_data, replace=True)
2051
-
2052
- print("collected number of detectable events = ", n)
2053
- print("total number of events = ", events_total)
2054
- print(f"total lensed rate (yr^-1): {total_rate}")
2055
-
2056
- print(f"storing detectable lensed params in {output_path}")
2057
- print(f"storing meta data in {meta_data_path}")
2058
-
2059
- if trim_to_size:
2060
- # trim the final param dictionary
2061
- print(f"\n trmming final result to size={size}")
2062
- param_final = get_param_from_json(output_path)
2063
- # randomly select size number of samples
2064
- len_ = len(list(param_final.values())[0])
2065
- idx = np.random.choice(len_, size, replace=False)
2066
- # trim the final param dictionary
2067
- for key, value in param_final.items():
2068
- param_final[key] = value[idx]
2069
-
2070
- # change meta data
2071
- meta_data = load_json(meta_data_path)
2072
- old_events_total = meta_data["events_total"][-1]
2073
- old_detectable_events = meta_data["detectable_events"][-1]
2074
-
2075
- # adjust the meta data
2076
- # following is to keep rate the same
2077
- new_events_total = np.round(size * old_events_total/old_detectable_events)
2078
- new_total_rate = self.normalization_pdf_z_lensed * size / new_events_total
2079
- meta_data["events_total"][-1] = new_events_total
2080
- meta_data["detectable_events"][-1] = size
2081
- meta_data["total_rate"][-1] = new_total_rate
2082
-
2083
- print("collected number of detectable events = ", size)
2084
- print("total number of events = ", new_events_total)
2085
- print(f"total unlensed rate (yr^-1): {new_total_rate}")
2086
-
2087
- # save the meta data
2088
- append_json(meta_data_path, meta_data, replace=True)
2089
- # save the final param dictionary
2090
- append_json(output_path, param_final, replace=True)
2091
- else:
2092
- param_final = get_param_from_json(output_path)
2093
-
2094
- return param_final
2095
-
2096
-
2097
-