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

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

Potentially problematic release.


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

Files changed (35) hide show
  1. ler/__init__.py +26 -26
  2. ler/gw_source_population/__init__.py +1 -0
  3. ler/gw_source_population/cbc_source_parameter_distribution.py +1076 -818
  4. ler/gw_source_population/cbc_source_redshift_distribution.py +619 -295
  5. ler/gw_source_population/jit_functions.py +484 -9
  6. ler/gw_source_population/sfr_with_time_delay.py +107 -0
  7. ler/image_properties/image_properties.py +44 -13
  8. ler/image_properties/multiprocessing_routine.py +5 -209
  9. ler/lens_galaxy_population/__init__.py +2 -0
  10. ler/lens_galaxy_population/epl_shear_cross_section.py +0 -0
  11. ler/lens_galaxy_population/jit_functions.py +101 -9
  12. ler/lens_galaxy_population/lens_galaxy_parameter_distribution.py +817 -885
  13. ler/lens_galaxy_population/lens_param_data/density_profile_slope_sl.txt +5000 -0
  14. ler/lens_galaxy_population/lens_param_data/external_shear_sl.txt +2 -0
  15. ler/lens_galaxy_population/lens_param_data/number_density_zl_zs.txt +48 -0
  16. ler/lens_galaxy_population/lens_param_data/optical_depth_epl_shear_vd_ewoud.txt +48 -0
  17. ler/lens_galaxy_population/mp copy.py +554 -0
  18. ler/lens_galaxy_population/mp.py +736 -138
  19. ler/lens_galaxy_population/optical_depth.py +2248 -616
  20. ler/rates/__init__.py +1 -2
  21. ler/rates/gwrates.py +129 -75
  22. ler/rates/ler.py +257 -116
  23. ler/utils/__init__.py +2 -0
  24. ler/utils/function_interpolation.py +322 -0
  25. ler/utils/gwsnr_training_data_generator.py +233 -0
  26. ler/utils/plots.py +1 -1
  27. ler/utils/test.py +1078 -0
  28. ler/utils/utils.py +553 -125
  29. {ler-0.4.1.dist-info → ler-0.4.3.dist-info}/METADATA +22 -9
  30. ler-0.4.3.dist-info/RECORD +34 -0
  31. {ler-0.4.1.dist-info → ler-0.4.3.dist-info}/WHEEL +1 -1
  32. ler/rates/ler copy.py +0 -2097
  33. ler-0.4.1.dist-info/RECORD +0 -25
  34. {ler-0.4.1.dist-info → ler-0.4.3.dist-info/licenses}/LICENSE +0 -0
  35. {ler-0.4.1.dist-info → ler-0.4.3.dist-info}/top_level.txt +0 -0
@@ -1,170 +1,768 @@
1
1
  import numpy as np
2
2
  from scipy.integrate import quad
3
3
  from numba import njit
4
+ from lenstronomy.LensModel.Solver.epl_shear_solver import caustics_epl_shear
5
+ from shapely.geometry import Polygon
4
6
 
5
- from .jit_functions import phi_cut_SIE, axis_ratio_rayleigh
6
- from ..utils import inverse_transform_sampler, cubic_spline_interpolator
7
+ from .jit_functions import phi_cut_SIE, phi_q2_ellipticity_hemanta
8
+ from ..utils import inverse_transform_sampler, cubic_spline_interpolator, cubic_spline_interpolator2d_array, inverse_transform_sampler2d
7
9
 
8
- def optical_depth_sis_mp(params):
10
+ # for testing
11
+ from .jit_functions import phi_loc_bernardi, phi
12
+ # phi(s, z, alpha, beta, phistar, sigmastar)
9
13
 
10
- # integrand
11
- zs = params[0]
12
- no = params[1]
13
- vd_inv_cdf = params[2]
14
- vd_inv_cdf_coeff = vd_inv_cdf[0]
15
- vd_list = vd_inv_cdf[1]
16
- vd_sampler = njit(lambda size_: inverse_transform_sampler(size_, vd_inv_cdf_coeff, vd_list))
17
14
 
18
- splineDa = params[4]
19
- splineDa_coeff = splineDa[0]
20
- splineDa_z_list = splineDa[1]
21
- Da_zs = cubic_spline_interpolator(np.array([zs]), splineDa_coeff, splineDa_z_list)[0]
22
- Da = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splineDa_coeff, splineDa_z_list)[0])
15
+ def lens_redshift_sis1_mp(params):
23
16
 
24
- splinedVcdz = params[3]
25
- dVcdz = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splinedVcdz[0], splinedVcdz[1])[0])
17
+ size = 20000 # integration size
18
+ zs = params[0] # float
26
19
 
27
- # integrand
28
- # @njit makes it slower
29
- def tau_integrand(zl, zs):
20
+ # redshift of the lens between the source and the observer
21
+ zl_array = params[1]*zs # 1D array, unscaled
30
22
 
31
- # velocity dispersion
32
- size = 5000
33
- sigma = vd_sampler(size)
23
+ result_array = []
24
+ for i, zl in enumerate(zl_array):
25
+ # velocity dispersion distribution
26
+ sigma_min, sigma_max = params[2][0], params[2][1] # 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]), params[4][0], params[4][1])[0] # float
32
+ Da_zl = cubic_spline_interpolator(np.array([zl]), params[4][0], params[4][1])[0]
34
33
 
35
34
  # einstein radius
36
- Dls = (Da_zs*(1+zs) - Da(zl)*(1+zl))/(1+zs)
35
+ Dls = (Da_zs*(1+zs) - Da_zl*(1+zl))/(1+zs)
37
36
  theta_E = (
38
37
  4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
39
38
  ) # Note: km/s for sigma; Dls, Ds are in Mpc
40
39
 
41
- # cross section
42
- cross_section_SIS = theta_E ** 2 # np.pi is ommited
43
-
44
- result = cross_section_SIS/4 * no * dVcdz(zl)
45
- # average
46
- return np.mean(result)
47
-
48
- return(int(params[5]), quad(tau_integrand, 0, params[0], args=(params[0]))[0])
49
-
50
- def optical_depth_sie1_mp(params):
51
-
52
- # integrand
53
- zs = params[0]
54
- no = params[1]
55
- vd_inv_cdf = params[2]
56
- vd_inv_cdf_coeff = vd_inv_cdf[0]
57
- vd_list = vd_inv_cdf[1]
58
- vd_sampler = njit(lambda size_: inverse_transform_sampler(size_, vd_inv_cdf_coeff, vd_list))
59
-
60
- splineDa = params[4]
61
- splineDa_coeff = splineDa[0]
62
- splineDa_z_list = splineDa[1]
63
- Da_zs = cubic_spline_interpolator(np.array([zs]), splineDa_coeff, splineDa_z_list)[0]
64
- Da = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splineDa_coeff, splineDa_z_list)[0])
65
-
66
- splinedVcdz = params[3]
67
- dVcdz = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splinedVcdz[0], splinedVcdz[1])[0])
68
-
69
- # integrand
70
- # @njit makes it slower
71
- def tau_integrand(zl, zs):
72
- """
73
- Function to calculate the optical depth for SIE lens with velocity dispersion distribution depending on redshift.
74
-
75
- Parameters
76
- ----------
77
- params : `list`
78
- list of parameters
79
- params[0] = zs (source redshift, float)
80
- params[1] = no (number density of lens galaxies, float)
81
- params[2] = vd_inv_cdf (velocity dispersion inverse cdf coefficients and redshift list, list). This vd_inv_cdf(s) of each redshift.
82
- params[3] = splineVcdz (differential comoving volume spline interpolator coefficients, list)
83
- params[4] = splineDa (angular diameter distance spline interpolator coefficients and redshift list, list)
84
- params[5] = idx (index to keep track of the operation, int)
85
- params[6] = zl_list (list of lens redshifts, list). This use for choosing the right vd_inv_cdf(s) for each lens redshifts.
86
-
87
- """
40
+ # cross-section
41
+ area_array = np.pi*theta_E**2
42
+ # non-nan index
43
+ idx = np.logical_not(np.isnan(area_array))
44
+
45
+ # velocity dispersion distribution
46
+ phi_sigma = phi_loc_bernardi(
47
+ sigma=sigma,
48
+ alpha=params[2][2],
49
+ beta=params[2][3],
50
+ phistar=params[2][4],
51
+ sigmastar=params[2][5],
52
+ )
53
+
54
+ # diffrential co-moving volume
55
+ dVcdz = cubic_spline_interpolator(np.array([zl]), params[5][0], params[5][1])[0]
56
+
57
+ # cross-section
58
+ result_array.append((sigma_max-sigma_min)*np.average( area_array[idx] * phi_sigma[idx] * dVcdz )/(4*np.pi))
59
+
60
+ return(params[6], np.array(result_array))
61
+
62
+ def lens_redshift_sis2_mp(params):
88
63
 
89
- # velocity dispersion
90
- size = 5000
91
- sigma = vd_sampler(size)
64
+ size = 20000 # integration size
65
+ zs = params[0] # float
92
66
 
93
- # axis ratio
94
- q = axis_ratio_rayleigh(sigma) # if SIS, q=array of 1.0
67
+ # redshift of the lens between the source and the observer
68
+ zl_array = params[1]*zs # 1D array, unscaled
69
+
70
+ result_array = []
71
+ for i, zl in enumerate(zl_array):
72
+ # velocity dispersion distribution
73
+ sigma_min, sigma_max = params[2][0], params[2][1] # min_max[0]
74
+ sigma = np.random.uniform(sigma_min, sigma_max, size)
75
+
76
+ ## Einstein radius calculation
77
+ # angular diameter distance
78
+ Da_zs = cubic_spline_interpolator(np.array([zs]), params[4][0], params[4][1])[0] # float
79
+ Da_zl = cubic_spline_interpolator(np.array([zl]), params[4][0], params[4][1])[0]
95
80
 
96
81
  # einstein radius
97
- Dls = (Da_zs*(1+zs) - Da(zl)*(1+zl))/(1+zs)
82
+ Dls = (Da_zs*(1+zs) - Da_zl*(1+zl))/(1+zs)
98
83
  theta_E = (
99
84
  4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
100
85
  ) # Note: km/s for sigma; Dls, Ds are in Mpc
101
86
 
102
- # cross section
103
- cross_section_SIS = theta_E ** 2 # np.pi is ommited
104
-
105
- result = phi_cut_SIE(q) * cross_section_SIS/4 * no * dVcdz(zl)
106
- # average
107
- return np.mean(result)
108
-
109
- return(int(params[5]), quad(tau_integrand, 0, params[0], args=(params[0]))[0])
110
-
111
- def optical_depth_sie2_mp(params):
112
- """
113
- Function to calculate the optical depth for SIE lens with velocity dispersion distribution depending on redshift.
114
-
115
- Parameters
116
- ----------
117
- params : `list`
118
- list of parameters
119
- params[0] = zs (source redshift, float)
120
- params[1] = no (number density of lens galaxies, float)
121
- params[2] = vd_inv_cdf (velocity dispersion inverse cdf coefficients and redshift list, list). This vd_inv_cdf(s) of each redshift.
122
- params[3] = splineVcdz (differential comoving volume spline interpolator coefficients, list)
123
- params[4] = splineDa (angular diameter distance spline interpolator coefficients and redshift list, list)
124
- params[5] = idx (index to keep track of the operation, int)
125
- params[6] = zl_list (list of lens redshifts, list). This use for choosing the right vd_inv_cdf(s) for each lens redshifts.
126
-
127
- """
128
-
129
- # integrand
130
- zs = params[0]
131
- no = params[1]
132
- z_list = params[6]
133
- vd_inv_cdf = params[2]
134
- vd_inv_cdf_coeff = vd_inv_cdf[:,0]
135
- vd_list = vd_inv_cdf[0,1]
136
- vd_sampler = njit(lambda size_,zl_: inverse_transform_sampler(size_, vd_inv_cdf_coeff[np.searchsorted(z_list, zl_)], vd_list))
137
-
138
- splineDa = params[4]
139
- splineDa_coeff = splineDa[0]
140
- splineDa_z_list = splineDa[1]
141
- Da_zs = cubic_spline_interpolator(np.array([zs]), splineDa_coeff, splineDa_z_list)[0]
142
- Da = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splineDa_coeff, splineDa_z_list)[0])
143
-
144
- splinedVcdz = params[3]
145
- dVcdz = njit(lambda zl_: cubic_spline_interpolator(np.array([zl_]), splinedVcdz[0], splinedVcdz[1])[0])
146
-
147
- # @njit makes it slower
148
- def tau_integrand(zl, zs):
149
-
150
- # velocity dispersion #
151
- size = 5000
152
- sigma = vd_sampler(size, zl)
153
-
154
- # axis ratio
155
- q = axis_ratio_rayleigh(sigma) # if SIS, q=array of 1.0
87
+ # cross-section
88
+ area_array = np.pi*theta_E**2
89
+ # non-nan index
90
+ idx = np.logical_not(np.isnan(area_array))
91
+
92
+ # velocity dispersion distribution
93
+ zl_ = zl*np.ones(size)
94
+ phi_sigma = phi(
95
+ s=sigma,
96
+ z=zl_,
97
+ alpha=params[2][2],
98
+ beta=params[2][3],
99
+ phistar=params[2][4],
100
+ sigmastar=params[2][5],
101
+ )
102
+
103
+ # diffrential co-moving volume
104
+ dVcdz = cubic_spline_interpolator(np.array([zl]), params[5][0], params[5][1])[0]
105
+
106
+ # cross-section
107
+ result_array.append((sigma_max-sigma_min)*np.average( area_array[idx] * phi_sigma[idx] * dVcdz )/(4*np.pi))
108
+
109
+ return(params[6], np.array(result_array))
110
+
111
+ def lens_redshift_sie1_mp(params):
112
+
113
+ size = 20000 # integration size
114
+ zs = params[0] # float
115
+
116
+ # redshift of the lens between the source and the observer
117
+ zl_array = params[1]*zs # 1D array, unscaled
118
+
119
+ result_array = []
120
+ for i, zl in enumerate(zl_array):
121
+ # velocity dispersion distribution
122
+ sigma_min, sigma_max = params[2][0], params[2][1] # min_max[0]
123
+ sigma = np.random.uniform(sigma_min, sigma_max, size)
124
+
125
+ # axis ratio distribution
126
+ if len(params[3]) == 3:
127
+ print
128
+ q = inverse_transform_sampler2d(size, sigma, params[3][0], params[3][1], params[3][2])
129
+ else:
130
+ if isinstance(params[3][0], float):
131
+ q = np.random.uniform(params[3][0], params[3][1], size)
132
+ else:
133
+ q = inverse_transform_sampler(size, params[3][0], params[3][1])
134
+
135
+ ## Einstein radius calculation
136
+ # angular diameter distance
137
+ Da_zs = cubic_spline_interpolator(np.array([zs]), params[4][0], params[4][1])[0] # float
138
+ Da_zl = cubic_spline_interpolator(np.array([zl]), params[4][0], params[4][1])[0]
156
139
 
157
140
  # einstein radius
158
- Dls = (Da_zs*(1+zs) - Da(zl)*(1+zl))/(1+zs)
141
+ Dls = (Da_zs*(1+zs) - Da_zl*(1+zl))/(1+zs)
159
142
  theta_E = (
160
143
  4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
161
144
  ) # Note: km/s for sigma; Dls, Ds are in Mpc
162
145
 
163
- # cross section
164
- cross_section_SIS = theta_E ** 2 # np.pi is ommited
146
+ # cross-section
147
+ area_array = phi_cut_SIE(q) * np.pi*theta_E**2
148
+ # area_array_sis = np.pi*theta_E**2
149
+ # logic = area_array_sis < area_array
150
+ # # area_array should be less than area_array_sis
151
+ # if logic.any():
152
+ # raise(ValueError('area_array should be less than area_array_sis'))
153
+
154
+ # non-nan index
155
+ idx = np.logical_not(np.isnan(area_array))
156
+
157
+ # velocity dispersion distribution
158
+ phi_sigma = phi_loc_bernardi(
159
+ sigma=sigma,
160
+ alpha=params[2][2],
161
+ beta=params[2][3],
162
+ phistar=params[2][4],
163
+ sigmastar=params[2][5],
164
+ )
165
+
166
+ # diffrential co-moving volume
167
+ dVcdz = cubic_spline_interpolator(np.array([zl]), params[5][0], params[5][1])[0]
168
+
169
+ # cross-section
170
+ result_array.append((sigma_max-sigma_min)*np.average( area_array[idx] * phi_sigma[idx] * dVcdz )/(4*np.pi))
171
+
172
+ return(params[6], np.array(result_array))
173
+
174
+
175
+ def lens_redshift_sie2_mp(params):
176
+
177
+ size = 20000 # integration size
178
+ zs = params[0] # float
179
+
180
+ # redshift of the lens between the source and the observer
181
+ zl_array = params[1]*zs # 1D array, unscaled
182
+
183
+ result_array = []
184
+ for i, zl in enumerate(zl_array):
185
+ # velocity dispersion distribution
186
+ sigma_min, sigma_max = params[2][0], params[2][1] # min_max[0]
187
+ sigma = np.random.uniform(sigma_min, sigma_max, size)
188
+
189
+ # axis ratio distribution
190
+ if len(params[3]) == 3:
191
+ q = inverse_transform_sampler2d(size, sigma, params[3][0], params[3][1], params[3][2])
192
+ else:
193
+ if isinstance(params[3][0], float):
194
+ q = np.random.uniform(params[3][0], params[3][1], size)
195
+ else:
196
+ q = inverse_transform_sampler(size, params[3][0], params[3][1])
197
+
198
+ ## Einstein radius calculation
199
+ # angular diameter distance
200
+ Da_zs = cubic_spline_interpolator(np.array([zs]), params[4][0], params[4][1])[0] # float
201
+ Da_zl = cubic_spline_interpolator(np.array([zl]), params[4][0], params[4][1])[0]
202
+
203
+ # einstein radius
204
+ Dls = (Da_zs*(1+zs) - Da_zl*(1+zl))/(1+zs)
205
+ theta_E = (
206
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
207
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
208
+
209
+ # cross-section
210
+ area_array = phi_cut_SIE(q) * np.pi*theta_E**2
211
+ # non-nan index
212
+ idx = np.logical_not(np.isnan(area_array))
213
+
214
+ # velocity dispersion distribution
215
+ zl_ = zl*np.ones(size)
216
+ phi_sigma = phi(
217
+ s=sigma,
218
+ z=zl_,
219
+ alpha=params[2][2],
220
+ beta=params[2][3],
221
+ phistar=params[2][4],
222
+ sigmastar=params[2][5],
223
+ )
224
+
225
+ # diffrential co-moving volume
226
+ dVcdz = cubic_spline_interpolator(np.array([zl]), params[5][0], params[5][1])[0]
227
+
228
+ # cross-section
229
+ result_array.append((sigma_max-sigma_min)*np.average( area_array[idx] * phi_sigma[idx] * dVcdz )/(4*np.pi))
230
+
231
+ return(params[6], np.array(result_array))
232
+
233
+
234
+ def lens_redshift_sie3_mp(params):
235
+
236
+ size = 20000 # integration size
237
+ zs = params[0] # float
238
+
239
+ # redshift of the lens between the source and the observer
240
+ zl_array = params[1]*zs # 1D array, unscaled
241
+
242
+ result_array = []
243
+ for i, zl in enumerate(zl_array):
244
+ # velocity dispersion distribution
245
+ sigma_min, sigma_max = params[2][0], params[2][1] # min_max[0]
246
+ sigma = np.random.uniform(sigma_min, sigma_max, size)
247
+
248
+ # axis ratio distribution
249
+ if len(params[3]) == 3:
250
+ q = inverse_transform_sampler2d(size, sigma, params[3][0], params[3][1], params[3][2])
251
+ else:
252
+ if isinstance(params[3][0], float):
253
+ q = np.random.uniform(params[3][0], params[3][1], size)
254
+ else:
255
+ q = inverse_transform_sampler(size, params[3][0], params[3][1])
256
+
257
+ # axis rotation angle
258
+ psi = np.random.uniform(params[8][0], params[8][1], size)
259
+
260
+ # Transform the axis ratio and the angle, to ellipticities e1, e2, using lenstronomy
261
+ e1, e2 = phi_q2_ellipticity_hemanta(psi, q)
262
+
263
+ # Sample shears
264
+ gamma1, gamma2 = np.zeros((2,size))
265
+
266
+ # Sample the density profile slop of the mass density distribution
267
+ gamma = np.ones(size)*2.0
268
+
269
+ ## Einstein radius calculation
270
+ # angular diameter distance
271
+ Da_zs = cubic_spline_interpolator(np.array([zs]), params[4][0], params[4][1])[0] # float
272
+ Da_zl = cubic_spline_interpolator(np.array([zl]), params[4][0], params[4][1])[0]
273
+
274
+ # einstein radius
275
+ Dls = (Da_zs*(1+zs) - Da_zl*(1+zl))/(1+zs)
276
+ theta_E = (
277
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
278
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
279
+
280
+ # cross-section
281
+ nbrs = params[7][0]
282
+ values = params[7][1]
283
+ points_ = np.array([e1, e2, gamma, gamma1, gamma2]).T
284
+ _, indices = nbrs.kneighbors(points_)
285
+ new_values_nn1 = np.mean(values[indices], axis=1)
286
+ theta_E_correction = cubic_spline_interpolator(np.pi*theta_E**2, params[7][2], params[7][3])
287
+ area_array = new_values_nn1*theta_E_correction
288
+ idx = (area_array>=2.4906932608826035e-28) & (area_array<=1.972789211435565e-08)
289
+
290
+ # velocity dispersion distribution
291
+ phi_sigma = phi_loc_bernardi(
292
+ sigma=sigma,
293
+ alpha=params[2][2],
294
+ beta=params[2][3],
295
+ phistar=params[2][4],
296
+ sigmastar=params[2][5],
297
+ )
298
+
299
+ # diffrential co-moving volume
300
+ dVcdz = cubic_spline_interpolator(np.array([zl]), params[5][0], params[5][1])[0]
301
+
302
+ # cross-section
303
+ result_array.append((sigma_max-sigma_min)*np.average( area_array[idx] * phi_sigma[idx] * dVcdz )/(4*np.pi))
304
+
305
+ return(params[6], np.array(result_array))
306
+
307
+
308
+ def lens_redshift_sie4_mp(params):
309
+
310
+ size = 20000 # integration size
311
+ zs = params[0] # float
312
+
313
+ # redshift of the lens between the source and the observer
314
+ zl_array = params[1]*zs # 1D array, unscaled
315
+
316
+ result_array = []
317
+ for i, zl in enumerate(zl_array):
318
+ # velocity dispersion distribution
319
+ sigma_min, sigma_max = params[2][0], params[2][1] # min_max[0]
320
+ sigma = np.random.uniform(sigma_min, sigma_max, size)
321
+
322
+ # axis ratio distribution
323
+ if len(params[3]) == 3:
324
+ q = inverse_transform_sampler2d(size, sigma, params[3][0], params[3][1], params[3][2])
325
+ else:
326
+ if isinstance(params[3][0], float):
327
+ q = np.random.uniform(params[3][0], params[3][1], size)
328
+ else:
329
+ q = inverse_transform_sampler(size, params[3][0], params[3][1])
330
+
331
+ # axis rotation angle
332
+ psi = np.random.uniform(params[8][0], params[8][1], size)
333
+
334
+ # Transform the axis ratio and the angle, to ellipticities e1, e2, using lenstronomy
335
+ e1, e2 = phi_q2_ellipticity_hemanta(psi, q)
336
+
337
+ # Sample shears
338
+ gamma1, gamma2 = np.zeros((2,size))
339
+
340
+ # Sample the density profile slop of the mass density distribution
341
+ gamma = np.ones(size)*2.0
342
+
343
+ ## Einstein radius calculation
344
+ # angular diameter distance
345
+ Da_zs = cubic_spline_interpolator(np.array([zs]), params[4][0], params[4][1])[0] # float
346
+ Da_zl = cubic_spline_interpolator(np.array([zl]), params[4][0], params[4][1])[0]
347
+
348
+ # einstein radius
349
+ Dls = (Da_zs*(1+zs) - Da_zl*(1+zl))/(1+zs)
350
+ theta_E = (
351
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
352
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
353
+
354
+ # cross-section
355
+ nbrs = params[7][0]
356
+ values = params[7][1]
357
+ points_ = np.array([e1, e2, gamma, gamma1, gamma2]).T
358
+ _, indices = nbrs.kneighbors(points_)
359
+ new_values_nn1 = np.mean(values[indices], axis=1)
360
+ theta_E_correction = cubic_spline_interpolator(np.pi*theta_E**2, params[7][2], params[7][3])
361
+ area_array = new_values_nn1*theta_E_correction
362
+ idx = (area_array>=2.4906932608826035e-28) & (area_array<=1.972789211435565e-08)
363
+
364
+ # velocity dispersion distribution
365
+ zl_ = zl*np.ones(size)
366
+ phi_sigma = phi(
367
+ s=sigma,
368
+ z=zl_,
369
+ alpha=params[2][2],
370
+ beta=params[2][3],
371
+ phistar=params[2][4],
372
+ sigmastar=params[2][5],
373
+ )
374
+
375
+ # diffrential co-moving volume
376
+ dVcdz = cubic_spline_interpolator(np.array([zl]), params[5][0], params[5][1])[0]
377
+
378
+ # cross-section
379
+ result_array.append((sigma_max-sigma_min)*np.average( area_array[idx] * phi_sigma[idx] * dVcdz )/(4*np.pi))
380
+
381
+ return(params[6], np.array(result_array))
382
+
383
+
384
+ def lens_redshift_epl_shear1_mp(params):
385
+
386
+ size = 20000 # integration size
387
+ zs = params[0] # float
388
+
389
+ # redshift of the lens between the source and the observer
390
+ zl_array = params[1]*zs # 1D array, unscaled
391
+
392
+ result_array = []
393
+ for i, zl in enumerate(zl_array):
394
+ # velocity dispersion distribution
395
+ sigma_min, sigma_max = params[2][0], params[2][1] # min_max[0]
396
+ sigma = np.random.uniform(sigma_min, sigma_max, size)
397
+
398
+ # axis ratio distribution
399
+ if len(params[3]) == 3:
400
+ q = inverse_transform_sampler2d(size, sigma, params[3][0], params[3][1], params[3][2])
401
+ else:
402
+ if isinstance(params[3][0], float):
403
+ q = np.random.uniform(params[3][0], params[3][1], size)
404
+ else:
405
+ q = inverse_transform_sampler(size, params[3][0], params[3][1])
406
+
407
+ # axis rotation angle
408
+ psi = np.random.uniform(params[8][0], params[8][1], size)
409
+
410
+ # Transform the axis ratio and the angle, to ellipticities e1, e2, using lenstronomy
411
+ e1, e2 = phi_q2_ellipticity_hemanta(psi, q)
412
+
413
+ # Sample shears
414
+ gamma1, gamma2 = np.random.normal(loc=params[9][0], scale=params[9][1], size=(2,size))
415
+
416
+ # Sample the density profile slop of the mass density distribution
417
+ gamma = np.random.normal(loc=params[10][0], scale=params[10][1], size=size)
418
+
419
+ ## Einstein radius calculation
420
+ # angular diameter distance
421
+ Da_zs = cubic_spline_interpolator(np.array([zs]), params[4][0], params[4][1])[0] # float
422
+ Da_zl = cubic_spline_interpolator(np.array([zl]), params[4][0], params[4][1])[0]
423
+
424
+ # einstein radius
425
+ Dls = (Da_zs*(1+zs) - Da_zl*(1+zl))/(1+zs)
426
+ theta_E = (
427
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
428
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
429
+
430
+ # cross-section
431
+ nbrs = params[7][0]
432
+ if nbrs is not None:
433
+ values = params[7][1]
434
+ points_ = np.array([e1, e2, gamma, gamma1, gamma2]).T
435
+ _, indices = nbrs.kneighbors(points_)
436
+ new_values_nn1 = np.mean(values[indices], axis=1)
437
+ theta_E_correction = cubic_spline_interpolator(np.pi*theta_E**2, params[7][2], params[7][3])
438
+ area_array = new_values_nn1*theta_E_correction
439
+ else:
440
+ area_array = []
441
+ for i in range(size):
442
+ area_array.append(cross_section(theta_E[i], e1[i], e2[i], gamma[i], gamma1[i], gamma2[i]))
443
+ area_array = np.array(area_array)
444
+ idx = (area_array>=2.4906932608826035e-28) & (area_array<=1.972789211435565e-08)
445
+
446
+ # velocity dispersion distribution
447
+ phi_sigma = phi_loc_bernardi(
448
+ sigma=sigma,
449
+ alpha=params[2][2],
450
+ beta=params[2][3],
451
+ phistar=params[2][4],
452
+ sigmastar=params[2][5],
453
+ )
454
+
455
+ # diffrential co-moving volume
456
+ dVcdz = cubic_spline_interpolator(np.array([zl]), params[5][0], params[5][1])[0]
457
+
458
+ # cross-section
459
+ result_array.append((sigma_max-sigma_min)*np.average( area_array[idx] * phi_sigma[idx] * dVcdz )/(4*np.pi))
460
+
461
+ return(params[6], np.array(result_array))
462
+
463
+
464
+ def lens_redshift_epl_shear2_mp(params):
465
+
466
+
467
+ size = 20000 # integration size
468
+ zs = params[0] # float
469
+
470
+ # redshift of the lens between the source and the observer
471
+ zl_array = params[1]*zs # 1D array, unscaled
472
+
473
+ result_array = []
474
+ for i, zl in enumerate(zl_array):
475
+ # velocity dispersion distribution
476
+ sigma_min, sigma_max = params[2][0], params[2][1] # min_max[0]
477
+ sigma = np.random.uniform(sigma_min, sigma_max, size)
478
+
479
+ # axis ratio distribution
480
+ if len(params[3]) == 3:
481
+ q = inverse_transform_sampler2d(size, sigma, params[3][0], params[3][1], params[3][2])
482
+ else:
483
+ if isinstance(params[3][0], float):
484
+ q = np.random.uniform(params[3][0], params[3][1], size)
485
+ else:
486
+ q = inverse_transform_sampler(size, params[3][0], params[3][1])
487
+
488
+ # axis rotation angle
489
+ psi = np.random.uniform(params[8][0], params[8][1], size)
490
+
491
+ # Transform the axis ratio and the axis rotation angle, to ellipticities e1, e2, using lenstronomy
492
+ e1, e2 = phi_q2_ellipticity_hemanta(psi, q)
493
+
494
+ # Sample shears
495
+ gamma1, gamma2 = np.random.normal(loc=params[9][0], scale=params[9][1], size=(2,size))
496
+
497
+ # Sample the density profile slop of the mass density distribution
498
+ gamma = np.random.normal(loc=params[10][0], scale=params[10][1], size=size)
499
+
500
+ ## Einstein radius calculation
501
+ # angular diameter distance
502
+ Da_zs = cubic_spline_interpolator(np.array([zs]), params[4][0], params[4][1])[0] # float
503
+ Da_zl = cubic_spline_interpolator(np.array([zl]), params[4][0], params[4][1])[0]
504
+
505
+ # einstein radius
506
+ Dls = (Da_zs*(1+zs) - Da_zl*(1+zl))/(1+zs)
507
+ theta_E = (
508
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
509
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
510
+
511
+ # cross-section
512
+ nbrs = params[7][0]
513
+ if nbrs is not None:
514
+ values = params[7][1]
515
+ points_ = np.array([e1, e2, gamma, gamma1, gamma2]).T
516
+ _, indices = nbrs.kneighbors(points_)
517
+ new_values_nn1 = np.mean(values[indices], axis=1)
518
+ theta_E_correction = cubic_spline_interpolator(np.pi*theta_E**2, params[7][2], params[7][3])
519
+ area_array = new_values_nn1*theta_E_correction
520
+ else:
521
+ area_array = []
522
+ for i in range(size):
523
+ area_array.append(cross_section(theta_E[i], e1[i], e2[i], gamma[i], gamma1[i], gamma2[i]))
524
+ area_array = np.array(area_array)
525
+
526
+ # this is to avoid nan, inf, -inf
527
+ idx = (area_array>=2.4906932608826035e-28) & (area_array<=1.972789211435565e-08)
528
+
529
+ # velocity dispersion distribution
530
+ zl_ = zl*np.ones(size)
531
+ phi_sigma = phi(
532
+ s=sigma,
533
+ z=zl_,
534
+ alpha=params[2][2],
535
+ beta=params[2][3],
536
+ phistar=params[2][4],
537
+ sigmastar=params[2][5],
538
+ )
539
+
540
+ # diffrential co-moving volume
541
+ dVcdz = cubic_spline_interpolator(np.array([zl]), params[5][0], params[5][1])[0]
542
+
543
+ # cross-section
544
+ result_array.append((sigma_max-sigma_min)*np.average( area_array[idx] * phi_sigma[idx] * dVcdz )/(4*np.pi))
545
+
546
+ return(params[6], np.array(result_array))
547
+
548
+ def cross_section_unit_mp(params):
549
+
550
+ kwargs_lens = [
551
+ {
552
+ "theta_E": 1.0,
553
+ "e1": params[0],
554
+ "e2": params[1],
555
+ "gamma": params[2],
556
+ "center_x": 0.0,
557
+ "center_y": 0.0,
558
+ },
559
+ {
560
+ "gamma1": params[3],
561
+ "gamma2": params[4],
562
+ "ra_0": 0,
563
+ "dec_0": 0,
564
+ },
565
+ ]
566
+
567
+ caustic_double_points = caustics_epl_shear(
568
+ kwargs_lens, return_which="double", maginf=-100
569
+ )
570
+ caustic = np.logical_not(np.isnan(caustic_double_points).any())
571
+
572
+ # If there is a nan, caustic=False, draw a new gamma
573
+ if caustic:
574
+ area_ = (Polygon(caustic_double_points.T).area)
575
+ else:
576
+ area_ = 0.0
165
577
 
166
- result = phi_cut_SIE(q) * cross_section_SIS/4 * no * dVcdz(zl)
167
- # average
168
- return np.mean(result)
578
+ return params[5], area_
579
+
580
+ def cross_section_mp(params):
581
+
582
+ theta_E = params[0]
583
+ e1 = params[1]
584
+ e2 = params[2]
585
+ gamma = params[3]
586
+ gamma1 = params[4]
587
+ gamma2 = params[5]
588
+ idx = params[6]
589
+
590
+ kwargs_lens = [
591
+ {
592
+ "theta_E": theta_E,
593
+ "e1": e1,
594
+ "e2": e2,
595
+ "gamma": gamma,
596
+ "center_x": 0.0,
597
+ "center_y": 0.0,
598
+ },
599
+ {
600
+ "gamma1": gamma1,
601
+ "gamma2": gamma2,
602
+ "ra_0": 0,
603
+ "dec_0": 0,
604
+ },
605
+ ]
606
+
607
+ caustic_double_points = caustics_epl_shear(
608
+ kwargs_lens, return_which="double", maginf=-100
609
+ )
610
+ caustic = np.logical_not(np.isnan(caustic_double_points).any())
611
+
612
+ # If there is a nan, caustic=False, draw a new gamma
613
+ if caustic:
614
+ area = Polygon(caustic_double_points.T).area
615
+ else:
616
+ area = 0.0
617
+
618
+ return int(idx) , area
619
+
620
+ def cross_section_interpolated_mp(params):
621
+
622
+ # theta_E = params[0]
623
+ # e1 = np.array(params[1])
624
+ # e2 = np.array(params[2])
625
+ # gamma = np.array(params[3])
626
+ # gamma1 = np.array(params[4])
627
+ # gamma2 = np.array(params[5])
628
+ # idx = params[6]
629
+ # nbrs = params[7]
630
+ # values = params[8]
631
+ # cross_section_spline = params[9]
632
+ # sis_area_array = params[10]
633
+ theta_E, e1, e2, gamma, gamma1, gamma2, idx, nbrs, values, cross_section_spline, sis_area_array = params
634
+
635
+ points_ = np.array([e1, e2, gamma, gamma1, gamma2]).T
636
+ _, indices = nbrs.kneighbors(points_)
637
+ new_values_nn1 = np.mean(values[indices], axis=1)
638
+
639
+ theta_E_correction = cubic_spline_interpolator(np.pi*theta_E**2, cross_section_spline, sis_area_array)
640
+ area = new_values_nn1*theta_E_correction
641
+
642
+ return idx, area
643
+
644
+ def cross_section(theta_E, e1, e2, gamma, gamma1, gamma2):
645
+
646
+ kwargs_lens = [
647
+ {
648
+ "theta_E": theta_E,
649
+ "e1": e1,
650
+ "e2": e2,
651
+ "gamma": gamma,
652
+ "center_x": 0.0,
653
+ "center_y": 0.0,
654
+ },
655
+ {
656
+ "gamma1": gamma1,
657
+ "gamma2": gamma2,
658
+ "ra_0": 0,
659
+ "dec_0": 0,
660
+ },
661
+ ]
662
+
663
+ caustic_double_points = caustics_epl_shear(
664
+ kwargs_lens, return_which="double", maginf=-100
665
+ )
666
+ caustic = np.logical_not(np.isnan(caustic_double_points).any())
667
+
668
+ # If there is a nan, caustic=False, draw a new gamma
669
+ if caustic:
670
+ area = Polygon(caustic_double_points.T).area
671
+ else:
672
+ area = 0.0
673
+
674
+ return area
675
+
676
+ def rjs_sie_mp(params):
677
+
678
+ size = 1000 # integration size
679
+ zs = params[0] # float
680
+
681
+ # redshift of the lens between the source and the observer
682
+ zl_array = params[1]
683
+
684
+ while True:
685
+ # velocity dispersion distribution
686
+ # njit might give problem
687
+ if len(params[2]) == 2:
688
+ sigma = inverse_transform_sampler2d(size, zl_array, params[2][0], params[2][1], params[2][2])
689
+ else:
690
+ sigma = inverse_transform_sampler(size, params[2][0], params[2][1])
691
+
692
+ # axis ratio distribution
693
+ if len(params[3]) == 3:
694
+ q = inverse_transform_sampler2d(size, sigma, params[3][0], params[3][1], params[3][2])
695
+ else:
696
+ q = inverse_transform_sampler(size, params[3][0], params[3][1])
697
+
698
+ ## Einstein radius calculation
699
+ # angular diameter distance
700
+ Da_zs = cubic_spline_interpolator(np.array([zs]), params[4][0], params[4][1])[0] # float
701
+ Da_zl = cubic_spline_interpolator(np.array([zl]), params[4][0], params[4][1])[0]
702
+
703
+ # einstein radius
704
+ Dls = (Da_zs*(1+zs) - Da_zl*(1+zl))/(1+zs)
705
+ theta_E = (
706
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
707
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
708
+
709
+ # cross-section
710
+ cross_section = phi_cut_SIE(q) * np.pi*theta_E**2
711
+
712
+ # rejection sampling
713
+ max_ = np.max(cross_section) # maximum einstein radius
714
+ u = np.random.uniform(0, max_, size=size)
715
+ mask = u < cross_section
716
+ if np.sum(mask) > 0:
717
+ break
718
+
719
+ return(params[6], sigma[mask][0], q[mask][0], theta_E[mask][0])
720
+
721
+ def rjs_sie_mp(args):
722
+
723
+ idx, zs, zl, sigma_args_cdf_values, sigma_args_x_array, sigma_args_conditioned_y_array, q_args_cdf_values, q_args_x_array, q_args_conditioned_y_array, da_args_function_spline, da_args_x_array, buffer_size = args
724
+
725
+ zl_ = zl*np.ones(buffer_size) # need for sigma computation
726
+ max_value = 0.
727
+ while True:
728
+ # velocity dispersion distribution
729
+ if sigma_args_conditioned_y_array is not None:
730
+ sigma = inverse_transform_sampler2d(buffer_size, zl_, sigma_args_cdf_values, sigma_args_x_array, sigma_args_conditioned_y_array)
731
+ else:
732
+ sigma = inverse_transform_sampler(buffer_size, zl_, sigma_args_cdf_values, sigma_args_x_array)
733
+
734
+ # axis ratio distribution
735
+ if q_args_conditioned_y_array is not None:
736
+ q = inverse_transform_sampler2d(buffer_size, sigma, q_args_cdf_values, q_args_x_array, q_args_conditioned_y_array)
737
+ else:
738
+ q = inverse_transform_sampler(buffer_size, sigma, q_args_cdf_values, q_args_x_array)
739
+
740
+ ## Einstein radius calculation
741
+ # angular diameter distance
742
+ Da_zs = cubic_spline_interpolator(np.array([zs]), da_args_function_spline, da_args_x_array)[0] # float
743
+ Da_zl = cubic_spline_interpolator(np.array([zl]), da_args_function_spline, da_args_x_array)[0]
744
+
745
+ # einstein radius
746
+ Dls = (Da_zs*(1+zs) - Da_zl*(1+zl))/(1+zs)
747
+ theta_E = (
748
+ 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / Da_zs
749
+ ) # Note: km/s for sigma; Dls, Ds are in Mpc
750
+
751
+ # cross-section
752
+ cross_section = phi_cut_SIE(q) * np.pi*theta_E**2
753
+
754
+ # rejection sampling
755
+ max_ = np.max(cross_section) # maximum einstein radius
756
+ if max_ > max_value:
757
+ max_value = max_
758
+ u = np.random.uniform(0, max_value, size=buffer_size)
759
+ mask = u < cross_section
760
+ if np.sum(mask) > 0:
761
+ break
762
+
763
+ sigma_final = sigma[mask][0]
764
+ theta_E_final = theta_E[mask][0]
765
+ q_final = q[mask][0]
766
+ # print(idx)
169
767
 
170
- return(int(params[5]), quad(tau_integrand, 0, params[0], args=(params[0]))[0])
768
+ return(idx, sigma_final, theta_E_final, q_final)