ler 0.4.2__py3-none-any.whl → 0.4.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (35) hide show
  1. ler/__init__.py +26 -26
  2. ler/gw_source_population/__init__.py +1 -0
  3. ler/gw_source_population/cbc_source_parameter_distribution.py +1073 -815
  4. ler/gw_source_population/cbc_source_redshift_distribution.py +618 -294
  5. ler/gw_source_population/jit_functions.py +484 -9
  6. ler/gw_source_population/sfr_with_time_delay.py +107 -0
  7. ler/image_properties/image_properties.py +41 -12
  8. ler/image_properties/multiprocessing_routine.py +5 -209
  9. ler/lens_galaxy_population/__init__.py +2 -0
  10. ler/lens_galaxy_population/epl_shear_cross_section.py +0 -0
  11. ler/lens_galaxy_population/jit_functions.py +101 -9
  12. ler/lens_galaxy_population/lens_galaxy_parameter_distribution.py +813 -881
  13. ler/lens_galaxy_population/lens_param_data/density_profile_slope_sl.txt +5000 -0
  14. ler/lens_galaxy_population/lens_param_data/external_shear_sl.txt +2 -0
  15. ler/lens_galaxy_population/lens_param_data/number_density_zl_zs.txt +48 -0
  16. ler/lens_galaxy_population/lens_param_data/optical_depth_epl_shear_vd_ewoud.txt +48 -0
  17. ler/lens_galaxy_population/mp copy.py +554 -0
  18. ler/lens_galaxy_population/mp.py +736 -138
  19. ler/lens_galaxy_population/optical_depth.py +2248 -616
  20. ler/rates/__init__.py +1 -2
  21. ler/rates/gwrates.py +126 -72
  22. ler/rates/ler.py +218 -111
  23. ler/utils/__init__.py +2 -0
  24. ler/utils/function_interpolation.py +322 -0
  25. ler/utils/gwsnr_training_data_generator.py +233 -0
  26. ler/utils/plots.py +1 -1
  27. ler/utils/test.py +1078 -0
  28. ler/utils/utils.py +492 -125
  29. {ler-0.4.2.dist-info → ler-0.4.3.dist-info}/METADATA +30 -17
  30. ler-0.4.3.dist-info/RECORD +34 -0
  31. {ler-0.4.2.dist-info → ler-0.4.3.dist-info}/WHEEL +1 -1
  32. ler/rates/ler copy.py +0 -2097
  33. ler-0.4.2.dist-info/RECORD +0 -25
  34. {ler-0.4.2.dist-info → ler-0.4.3.dist-info/licenses}/LICENSE +0 -0
  35. {ler-0.4.2.dist-info → ler-0.4.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,554 @@
1
+ import numpy as np
2
+ from scipy.integrate import quad
3
+ from numba import njit
4
+ from lenstronomy.LensModel.Solver.epl_shear_solver import caustics_epl_shear
5
+ from shapely.geometry import Polygon
6
+
7
+ from .jit_functions import phi_cut_SIE, axis_ratio_rayleigh, phi_q2_ellipticity_hemanta
8
+ from ..utils import inverse_transform_sampler, cubic_spline_interpolator
9
+
10
+ # for testing
11
+ from .jit_functions import phi_loc_bernardi
12
+
13
+
14
+ @njit
15
+ def optical_depth_sis4_mp(zs_array, splineDa, splinedVcdz, size=1000000, min_max=np.array([[50.0,420.0]]), sigma_args=np.array([2.32, 2.67, 0.0027439999999999995, 161.0]),):
16
+ """
17
+ Function to calculate the optical depth for SIS lens with velocity dispersion distribution independent on redshift. With montecarlo integration.
18
+ """
19
+
20
+ tau_list = []
21
+ for zs in zs_array:
22
+
23
+ # redshift of the lens between the source and the observer
24
+ zl = np.random.uniform(0, zs, size)
25
+ # velocity dispersion
26
+ sigma_min, sigma_max = min_max[0]
27
+ sigma = np.random.uniform(sigma_min, sigma_max, size)
28
+
29
+ ## Einstein radius calculation
30
+ # angular diameter distance
31
+ Da_zs = cubic_spline_interpolator(np.array([zs]), splineDa[0], splineDa[1])[0] # float
32
+ Da = cubic_spline_interpolator(zl, splineDa[0], splineDa[1]) # array
33
+ # einstein radius
34
+ Dls = (Da_zs*(1+zs) - Da*(1+zl))/(1+zs)
35
+ theta_E = (
36
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
37
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
38
+
39
+ # velocity dispersion distribution
40
+ phi_sigma = phi_loc_bernardi(sigma,
41
+ alpha = sigma_args[0],
42
+ beta = sigma_args[1],
43
+ phistar = sigma_args[2],
44
+ sigmastar = sigma_args[3],
45
+ )
46
+
47
+ # diffrential co-moving volume
48
+ dVcdz = cubic_spline_interpolator(zl, splinedVcdz[0], splinedVcdz[1])
49
+
50
+ tau_list.append((sigma_max-sigma_min)*(zs)*np.average( theta_E**2 /4 * phi_sigma * dVcdz ))
51
+
52
+ return(zs_array, np.array(tau_list))
53
+
54
+ def optical_depth_sis3_mp(params):
55
+ """
56
+ Function to calculate the optical depth for SIS lens with velocity dispersion distribution independent on redshift. With montecarlo integration.
57
+ """
58
+
59
+ size = 1000000 # integration size
60
+ # source redshift
61
+ zs = params[0]
62
+ # redshift of the lens between the source and the observer
63
+ zl = np.random.uniform(0, zs, size)
64
+ # velocity dispersion
65
+ sigma = np.random.uniform(50, 420., size)
66
+
67
+ ## Einstein radius calculation
68
+ # angular diameter distance
69
+ splineDa = params[4]
70
+ splineDa_coeff = splineDa[0]
71
+ splineDa_z_list = splineDa[1]
72
+ Da_zs = cubic_spline_interpolator(np.array([zs]), splineDa_coeff, splineDa_z_list)[0] # float
73
+ Da = cubic_spline_interpolator(zl, splineDa_coeff, splineDa_z_list) # array
74
+ # einstein radius
75
+ Dls = (Da_zs*(1+zs) - Da*(1+zl))/(1+zs)
76
+ theta_E = (
77
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
78
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
79
+
80
+ # velocity dispersion distribution
81
+ phi_sigma = phi_loc_bernardi(sigma, alpha = 2.32, beta = 2.67, phistar = 0.0027439999999999995, sigmastar = 161.0)
82
+
83
+ # diffrential co-moving volume
84
+ splinedVcdz = params[3]
85
+ dVcdz = cubic_spline_interpolator(zl, splinedVcdz[0], splinedVcdz[1])
86
+
87
+ tau = (420.0-50.0)*(zs)*np.average( theta_E**2 /4 * phi_sigma * dVcdz )
88
+
89
+ return(int(params[5]), tau)
90
+
91
+ def optical_depth_sis1_mp(params):
92
+ """
93
+ Function to calculate the optical depth for SIS lens with velocity dispersion distribution independent on redshift.
94
+ """
95
+
96
+ # integrand
97
+ zs = params[0]
98
+ no = params[1]
99
+ vd_inv_cdf = params[2]
100
+ vd_inv_cdf_coeff = vd_inv_cdf[0]
101
+ vd_list = vd_inv_cdf[1]
102
+ vd_sampler = njit(lambda size_: inverse_transform_sampler(size_, vd_inv_cdf_coeff, vd_list))
103
+
104
+ splineDa = params[4]
105
+ splineDa_coeff = splineDa[0]
106
+ splineDa_z_list = splineDa[1]
107
+ Da_zs = cubic_spline_interpolator(np.array([zs]), splineDa_coeff, splineDa_z_list)[0]
108
+ Da = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splineDa_coeff, splineDa_z_list)[0])
109
+
110
+ splinedVcdz = params[3]
111
+ dVcdz = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splinedVcdz[0], splinedVcdz[1])[0])
112
+
113
+ # integrand
114
+ # @njit makes it slower
115
+ def tau_integrand(zl, zs):
116
+
117
+ # velocity dispersion
118
+ size = 20000
119
+ sigma = vd_sampler(size)
120
+
121
+ # einstein radius
122
+ Dls = (Da_zs*(1+zs) - Da(zl)*(1+zl))/(1+zs)
123
+ theta_E = (
124
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
125
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
126
+
127
+ # cross section
128
+ cross_section_SIS = theta_E ** 2 # np.pi is ommited
129
+
130
+ result = cross_section_SIS/4 * no * dVcdz(zl)
131
+ # average
132
+ return np.mean(result)
133
+
134
+ return(int(params[5]), quad(tau_integrand, 0, params[0], args=(params[0]))[0])
135
+
136
+ def optical_depth_sis2_mp(params):
137
+ """
138
+ Function to calculate the optical depth for SIS lens with velocity dispersion distribution depending on redshift.
139
+
140
+ Parameters
141
+ ----------
142
+ params : `list`
143
+ list of parameters
144
+ params[0] = zs (source redshift, float)
145
+ params[1] = no (number density of lens galaxies, float)
146
+ params[2] = vd_inv_cdf (velocity dispersion inverse cdf coefficients and redshift list, list). This vd_inv_cdf(s) of each redshift.
147
+ params[3] = splineVcdz (differential comoving volume spline interpolator coefficients, list)
148
+ params[4] = splineDa (angular diameter distance spline interpolator coefficients and redshift list, list)
149
+ params[5] = idx (index to keep track of the operation, int)
150
+ params[6] = zl_list (list of lens redshifts, list). This use for choosing the right vd_inv_cdf(s) for each lens redshifts.
151
+
152
+ """
153
+
154
+ # integrand
155
+ zs = params[0]
156
+ no = params[1]
157
+ z_list = params[6]
158
+ vd_inv_cdf = params[2]
159
+ vd_inv_cdf_coeff = vd_inv_cdf[:,0]
160
+ vd_list = vd_inv_cdf[0,1]
161
+ vd_sampler = njit(lambda size_,zl_: inverse_transform_sampler(size_, vd_inv_cdf_coeff[np.searchsorted(z_list, zl_)], vd_list))
162
+
163
+ splineDa = params[4]
164
+ splineDa_coeff = splineDa[0]
165
+ splineDa_z_list = splineDa[1]
166
+ Da_zs = cubic_spline_interpolator(np.array([zs]), splineDa_coeff, splineDa_z_list)[0]
167
+ Da = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splineDa_coeff, splineDa_z_list)[0])
168
+
169
+ splinedVcdz = params[3]
170
+ dVcdz = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splinedVcdz[0], splinedVcdz[1])[0])
171
+
172
+ # integrand
173
+ # @njit makes it slower
174
+ def tau_integrand(zl, zs):
175
+
176
+ # velocity dispersion #
177
+ size = 20000
178
+ sigma = vd_sampler(size, zl)
179
+
180
+ # einstein radius
181
+ Dls = (Da_zs*(1+zs) - Da(zl)*(1+zl))/(1+zs)
182
+ theta_E = (
183
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
184
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
185
+
186
+ # cross section
187
+ cross_section_SIS = theta_E ** 2 # np.pi is ommited
188
+
189
+ result = cross_section_SIS/4 * no * dVcdz(zl)
190
+ # average
191
+ return np.mean(result)
192
+
193
+ return(int(params[5]), quad(tau_integrand, 0, params[0], args=(params[0]))[0])
194
+
195
+
196
+
197
+ def optical_depth_sie1_mp(params):
198
+
199
+ # integrand
200
+ zs = params[0]
201
+ no = params[1]
202
+ vd_inv_cdf = params[2]
203
+ vd_inv_cdf_coeff = vd_inv_cdf[0] # coefficients of the inverse cdf
204
+ vd_list = vd_inv_cdf[1] # original list of velocity dispersions
205
+ vd_sampler = njit(lambda size_: inverse_transform_sampler(size_, vd_inv_cdf_coeff, vd_list))
206
+
207
+ splineDa = params[4]
208
+ splineDa_coeff = splineDa[0] # coefficients of the angular diameter distance spline interpolator
209
+ splineDa_z_list = splineDa[1] # redshift list of the angular diameter distance spline interpolator
210
+ Da_zs = cubic_spline_interpolator(np.array([zs]), splineDa_coeff, splineDa_z_list)[0]
211
+ Da = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splineDa_coeff, splineDa_z_list)[0])
212
+
213
+ splinedVcdz = params[3]
214
+ dVcdz = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splinedVcdz[0], splinedVcdz[1])[0])
215
+
216
+ # integrand
217
+ # @njit makes it slower
218
+ def tau_integrand(zl, zs):
219
+ """
220
+ Function to calculate the optical depth for SIE lens with velocity dispersion distribution depending on redshift.
221
+
222
+ Parameters
223
+ ----------
224
+ params : `list`
225
+ list of parameters
226
+ params[0] = zs (source redshift, float)
227
+ params[1] = no (number density of lens galaxies, float)
228
+ params[2] = vd_inv_cdf (velocity dispersion inverse cdf coefficients and redshift list, list). This vd_inv_cdf(s) of each redshift.
229
+ params[3] = splineVcdz (differential comoving volume spline interpolator coefficients, list)
230
+ params[4] = splineDa (angular diameter distance spline interpolator coefficients and redshift list, list)
231
+ params[5] = idx (index to keep track of the operation, int)
232
+ params[6] = zl_list (list of lens redshifts, list). This use for choosing the right vd_inv_cdf(s) for each lens redshifts.
233
+
234
+ """
235
+
236
+ # velocity dispersion
237
+ size = 20000
238
+ sigma = vd_sampler(size)
239
+
240
+ # axis ratio
241
+ q = axis_ratio_rayleigh(sigma) # if SIS, q=array of 1.0
242
+
243
+ # einstein radius
244
+ Dls = (Da_zs*(1+zs) - Da(zl)*(1+zl))/(1+zs)
245
+ theta_E = (
246
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
247
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
248
+
249
+ # cross section
250
+ cross_section_SIS = theta_E ** 2 # np.pi is ommited
251
+
252
+ result = phi_cut_SIE(q) * cross_section_SIS/4 * no * dVcdz(zl)
253
+ # average
254
+ return np.mean(result)
255
+
256
+ return(int(params[5]), quad(tau_integrand, 0, params[0], args=(params[0]))[0])
257
+
258
+ def optical_depth_sie2_mp(params):
259
+ """
260
+ Function to calculate the optical depth for SIE lens with velocity dispersion distribution depending on redshift.
261
+
262
+ Parameters
263
+ ----------
264
+ params : `list`
265
+ list of parameters
266
+ params[0] = zs (source redshift, float)
267
+ params[1] = no (number density of lens galaxies, float)
268
+ params[2] = vd_inv_cdf (velocity dispersion inverse cdf coefficients and redshift list, list). This vd_inv_cdf(s) of each redshift.
269
+ params[3] = splineVcdz (differential comoving volume spline interpolator coefficients, list)
270
+ params[4] = splineDa (angular diameter distance spline interpolator coefficients and redshift list, list)
271
+ params[5] = idx (index to keep track of the operation, int)
272
+ params[6] = zl_list (list of lens redshifts, list). This use for choosing the right vd_inv_cdf(s) for each lens redshifts.
273
+
274
+ """
275
+
276
+ # integrand
277
+ zs = params[0]
278
+ no = params[1]
279
+ z_list = params[6]
280
+ vd_inv_cdf = params[2]
281
+ vd_inv_cdf_coeff = vd_inv_cdf[:,0]
282
+ vd_list = vd_inv_cdf[0,1]
283
+ vd_sampler = njit(lambda size_,zl_: inverse_transform_sampler(size_, vd_inv_cdf_coeff[np.searchsorted(z_list, zl_)], vd_list))
284
+
285
+ splineDa = params[4]
286
+ splineDa_coeff = splineDa[0]
287
+ splineDa_z_list = splineDa[1]
288
+ Da_zs = cubic_spline_interpolator(np.array([zs]), splineDa_coeff, splineDa_z_list)[0]
289
+ Da = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splineDa_coeff, splineDa_z_list)[0])
290
+
291
+ splinedVcdz = params[3]
292
+ dVcdz = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splinedVcdz[0], splinedVcdz[1])[0])
293
+
294
+ # @njit makes it slower
295
+ def tau_integrand(zl, zs):
296
+
297
+ # velocity dispersion #
298
+ size = 20000
299
+ sigma = vd_sampler(size, zl)
300
+
301
+ # axis ratio
302
+ q = axis_ratio_rayleigh(sigma) # if SIS, q=array of 1.0
303
+
304
+ # einstein radius
305
+ Dls = (Da_zs*(1+zs) - Da(zl)*(1+zl))/(1+zs)
306
+ theta_E = (
307
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
308
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
309
+
310
+ # cross section
311
+ cross_section_SIS = theta_E ** 2 # np.pi is ommited
312
+
313
+ result = phi_cut_SIE(q) * cross_section_SIS/4 * no * dVcdz(zl)
314
+ # average
315
+ return np.mean(result)
316
+
317
+ return(int(params[5]), quad(tau_integrand, 0, params[0], args=(params[0]))[0])
318
+
319
+
320
+ def optical_depth_epl_shear1_mp(params):
321
+ """
322
+ Function to calculate the optical depth for SIE lens with velocity dispersion distribution depending on redshift.
323
+ """
324
+
325
+ # integrand
326
+ zs = params[0]
327
+ no = params[1]
328
+ vd_inv_cdf = params[2]
329
+ vd_inv_cdf_coeff = vd_inv_cdf[0] # coefficients of the inverse cdf
330
+ vd_list = vd_inv_cdf[1] # original list of velocity dispersions
331
+ vd_sampler = lambda size_: inverse_transform_sampler(size_, vd_inv_cdf_coeff, vd_list)
332
+
333
+ splineDa = params[4]
334
+ splineDa_coeff = splineDa[0] # coefficients of the angular diameter distance spline interpolator
335
+ splineDa_z_list = splineDa[1] # redshift list of the angular diameter distance spline interpolator
336
+ Da_zs = cubic_spline_interpolator(np.array([zs]), splineDa_coeff, splineDa_z_list)[0]
337
+ Da = lambda zl_: cubic_spline_interpolator(np.array([zl_]), splineDa_coeff, splineDa_z_list)[0]
338
+
339
+ splinedVcdz = params[3]
340
+ dVcdz = lambda zl_: cubic_spline_interpolator(np.array([zl_]), splinedVcdz[0], splinedVcdz[1])[0]
341
+
342
+ # @njit makes it slower
343
+ def sample_lens_params(zl, zs, size):
344
+
345
+ # velocity dispersion #
346
+ sigma = vd_sampler(size)
347
+ # Sample axis ratios
348
+ q = axis_ratio_rayleigh(sigma)
349
+ # axis rotation angle
350
+ phi = np.random.uniform(0.0, 2 * np.pi, size)
351
+ # Transform the axis ratio and the angle, to ellipticities e1, e2, using lenstronomy
352
+ e1, e2 = phi_q2_ellipticity_hemanta(phi, q)
353
+ # Sample shears
354
+ gamma1, gamma2 = np.random.normal(loc=0, scale=0.05,size=(2,size))
355
+ # Sample the spectral index of the mass density distribution
356
+ gamma = np.random.normal(loc=2.0, scale=0.2, size=size)
357
+
358
+ # einstein radius
359
+ Dls = (Da_zs*(1+zs) - Da(zl)*(1+zl))/(1+zs)
360
+ theta_E = (
361
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
362
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
363
+
364
+ return theta_E, e1, e2, gamma1, gamma2, gamma
365
+
366
+ def tau_integrand(zl, zs):
367
+ size = 5000
368
+ final_size = 0
369
+ area_list = []
370
+
371
+ while final_size < size:
372
+ size_ = size - final_size
373
+ #print(f"size: {size_}")
374
+ theta_E, e1, e2, gamma1, gamma2, gamma = sample_lens_params(zl, zs, size=size_)
375
+
376
+ for i in range(size_):
377
+ kwargs_lens = [
378
+ {
379
+ "theta_E": theta_E[i],
380
+ "e1": e1[i],
381
+ "e2": e2[i],
382
+ "gamma": gamma[i],
383
+ "center_x": 0.0,
384
+ "center_y": 0.0,
385
+ },
386
+ {
387
+ "gamma1": gamma1[i],
388
+ "gamma2": gamma2[i],
389
+ "ra_0": 0,
390
+ "dec_0": 0,
391
+ },
392
+ ]
393
+
394
+ caustic_double_points = caustics_epl_shear(
395
+ kwargs_lens, return_which="double", maginf=-100
396
+ )
397
+ caustic = np.logical_not(np.isnan(caustic_double_points).any())
398
+
399
+ # If there is a nan, caustic=False, draw a new gamma
400
+ if caustic:
401
+ area_list.append(Polygon(caustic_double_points.T).area)
402
+
403
+ final_size = len(area_list)
404
+
405
+ result_EPL = np.array(area_list)/(4*np.pi) * no * dVcdz(zl)
406
+
407
+ return np.mean(result_EPL[(result_EPL<1.0) & (result_EPL>0.0)]) #, np.mean(result_SIS)
408
+
409
+ return(int(params[5]), quad(tau_integrand, 0, params[0], args=(params[0]))[0])
410
+
411
+ def optical_depth_epl_shear2_mp(params):
412
+ """
413
+ Function to calculate the optical depth for EPL+Shear lens with velocity dispersion distribution depending on redshift.
414
+
415
+ Parameters
416
+ ----------
417
+ params : `list`
418
+ list of parameters
419
+ params[0] = zs (source redshift, float)
420
+ params[1] = no (number density of lens galaxies, float)
421
+ params[2] = vd_inv_cdf (velocity dispersion inverse cdf coefficients and redshift list, list). This vd_inv_cdf(s) of each redshift.
422
+ params[3] = splineVcdz (differential comoving volume spline interpolator coefficients, list)
423
+ params[4] = splineDa (angular diameter distance spline interpolator coefficients and redshift list, list)
424
+ params[5] = idx (index to keep track of the operation, int)
425
+ params[6] = zl_list (list of lens redshifts, list). This use for choosing the right vd_inv_cdf(s) for each lens redshifts.
426
+
427
+ """
428
+
429
+ # integrand
430
+ zs = params[0]
431
+ no = params[1]
432
+ z_list = params[6]
433
+ vd_inv_cdf = params[2]
434
+ vd_inv_cdf_coeff = vd_inv_cdf[:,0]
435
+ vd_list = vd_inv_cdf[0,1]
436
+ vd_sampler = njit(lambda size_,zl_: inverse_transform_sampler(size_, vd_inv_cdf_coeff[np.searchsorted(z_list, zl_)], vd_list))
437
+
438
+ splineDa = params[4]
439
+ splineDa_coeff = splineDa[0]
440
+ splineDa_z_list = splineDa[1]
441
+ Da_zs = cubic_spline_interpolator(np.array([zs]), splineDa_coeff, splineDa_z_list)[0]
442
+ Da = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splineDa_coeff, splineDa_z_list)[0])
443
+
444
+ splinedVcdz = params[3]
445
+ dVcdz = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splinedVcdz[0], splinedVcdz[1])[0])
446
+
447
+ # @njit makes it slower
448
+ def sample_lens_params(zl, zs, size):
449
+
450
+ # velocity dispersion #
451
+ sigma = vd_sampler(size, zl)
452
+ # Sample axis ratios
453
+ q = axis_ratio_rayleigh(sigma)
454
+ # axis rotation angle
455
+ phi = np.random.uniform(0.0, 2 * np.pi, size)
456
+ # Transform the axis ratio and the angle, to ellipticities e1, e2, using lenstronomy
457
+ e1, e2 = phi_q2_ellipticity_hemanta(phi, q)
458
+ # Sample shears
459
+ gamma1, gamma2 = np.random.normal(loc=0, scale=0.05,size=(2,size))
460
+ # Sample the spectral index of the mass density distribution
461
+ gamma = np.random.normal(loc=2.0, scale=0.2, size=size)
462
+
463
+ # einstein radius
464
+ Dls = (Da_zs*(1+zs) - Da(zl)*(1+zl))/(1+zs)
465
+ theta_E = (
466
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
467
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
468
+
469
+ return theta_E, e1, e2, gamma1, gamma2, gamma
470
+
471
+ def tau_integrand(zl, zs):
472
+ size = 20000
473
+ final_size = 0
474
+ area_list = []
475
+
476
+ while final_size < size:
477
+ size = size - final_size
478
+ theta_E, e1, e2, gamma1, gamma2, gamma = sample_lens_params(zl, zs, size=size)
479
+
480
+ for i in range(size):
481
+ kwargs_lens = [
482
+ {
483
+ "theta_E": theta_E[i],
484
+ "e1": e1[i],
485
+ "e2": e2[i],
486
+ "gamma": gamma[i],
487
+ "center_x": 0.0,
488
+ "center_y": 0.0,
489
+ },
490
+ {
491
+ "gamma1": gamma1[i],
492
+ "gamma2": gamma2[i],
493
+ "ra_0": 0,
494
+ "dec_0": 0,
495
+ },
496
+ ]
497
+
498
+ caustic_double_points = caustics_epl_shear(
499
+ kwargs_lens, return_which="double", maginf=-100
500
+ )
501
+ caustic = np.logical_not(np.isnan(caustic_double_points).any())
502
+
503
+ # If there is a nan, caustic=False, draw a new gamma
504
+ if caustic:
505
+ area_list.append(Polygon(caustic_double_points.T).area)
506
+
507
+ final_size = len(area_list)
508
+
509
+ result_EPL = np.array(area_list)/(4*np.pi) * no * dVcdz(zl)
510
+
511
+ return np.mean(result_EPL[result_EPL<1.0]) #, np.mean(result_SIS)
512
+
513
+ return(int(params[5]), quad(tau_integrand, 0, params[0], args=(params[0]))[0])
514
+
515
+
516
+ def cross_section_epl_shear(params):
517
+
518
+ theta_E = params[0]
519
+ e1 = params[1]
520
+ e2 = params[2]
521
+ gamma1 = params[3]
522
+ gamma2 = params[4]
523
+ gamma = params[5]
524
+ idx = params[6]
525
+
526
+ kwargs_lens = [
527
+ {
528
+ "theta_E": theta_E,
529
+ "e1": e1,
530
+ "e2": e2,
531
+ "gamma": gamma,
532
+ "center_x": 0.0,
533
+ "center_y": 0.0,
534
+ },
535
+ {
536
+ "gamma1": gamma1,
537
+ "gamma2": gamma2,
538
+ "ra_0": 0,
539
+ "dec_0": 0,
540
+ },
541
+ ]
542
+
543
+ caustic_double_points = caustics_epl_shear(
544
+ kwargs_lens, return_which="double", maginf=-100
545
+ )
546
+ caustic = np.logical_not(np.isnan(caustic_double_points).any())
547
+
548
+ # If there is a nan, caustic=False, draw a new gamma
549
+ if caustic:
550
+ area = Polygon(caustic_double_points.T).area
551
+ else:
552
+ area = 0.0
553
+
554
+ return int(idx) , area