ler 0.3.7__py3-none-any.whl → 0.3.9__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.
- ler/__init__.py +1 -1
- ler/gw_source_population/cbc_source_parameter_distribution.py +74 -31
- ler/gw_source_population/cbc_source_redshift_distribution.py +37 -28
- ler/gw_source_population/jit_functions.py +1 -1
- ler/image_properties/image_properties.py +46 -23
- ler/image_properties/multiprocessing_routine.py +26 -11
- ler/lens_galaxy_population/jit_functions.py +1 -0
- ler/lens_galaxy_population/lens_galaxy_parameter_distribution.py +23 -23
- ler/lens_galaxy_population/optical_depth.py +20 -18
- ler/rates/gwrates.py +593 -205
- ler/rates/ler copy.py +2097 -0
- ler/rates/ler.py +1068 -577
- ler/utils/plots.py +266 -223
- ler/utils/utils.py +44 -10
- {ler-0.3.7.dist-info → ler-0.3.9.dist-info}/METADATA +2 -2
- ler-0.3.9.dist-info/RECORD +25 -0
- {ler-0.3.7.dist-info → ler-0.3.9.dist-info}/WHEEL +1 -1
- ler-0.3.7.dist-info/RECORD +0 -24
- {ler-0.3.7.dist-info → ler-0.3.9.dist-info}/LICENSE +0 -0
- {ler-0.3.7.dist-info → ler-0.3.9.dist-info}/top_level.txt +0 -0
ler/rates/ler copy.py
ADDED
|
@@ -0,0 +1,2097 @@
|
|
|
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
|
+
|