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
@@ -2,187 +2,185 @@
2
2
  """
3
3
  This module contains the LensGalaxyPopulation class, which is used to sample lens galaxy parameters, source parameters conditioned on the source being strongly lensed. \n
4
4
  The class inherits from the ImageProperties class, which is used calculate image properties (magnification, timedelays, source position, image position, morse phase). \n
5
- Either the class takes in initialized CompactBinaryPopulation class as input or inherits the CompactBinaryPopulation class with default params (if no input) \n
5
+ Either the class takes in initialized CBCSourceParameterDistribution class as input or inherits the CBCSourceParameterDistribution class with default params (if no input) \n
6
6
  """
7
7
 
8
8
  import warnings
9
9
  warnings.filterwarnings("ignore")
10
10
  import numpy as np
11
- from numba import njit
12
11
  from scipy.integrate import quad
13
- from lenstronomy.Util.param_util import phi_q2_ellipticity
14
-
15
- # for redshift to luminosity distance conversion
16
- from astropy.cosmology import LambdaCDM
12
+ # from lenstronomy.Util.param_util import phi_q2_ellipticity
13
+ from multiprocessing import Pool
14
+ from tqdm import tqdm
17
15
 
18
16
  # the following .py file will be called if they are not given in the class initialization
19
17
  from ..gw_source_population import CBCSourceParameterDistribution
20
18
  from .optical_depth import OpticalDepth
21
19
  from ..image_properties import ImageProperties
22
- from ..utils import add_dictionaries_together, trim_dictionary
23
- from .jit_functions import phi_cut_SIE, velocity_dispersion_z_dependent, lens_redshift_SDSS_catalogue
24
-
20
+ from ..utils import add_dictionaries_together, trim_dictionary, FunctionConditioning, interpolator_pickle_path
21
+ from .jit_functions import phi_cut_SIE, phi_q2_ellipticity_hemanta
22
+ from .mp import cross_section_mp, rjs_sie_mp
25
23
 
26
24
  class LensGalaxyParameterDistribution(CBCSourceParameterDistribution, ImageProperties, OpticalDepth):
27
25
  """
28
- Class to sample lens galaxy parameters, source parameters conditioned on the source being strongly lensed, and image properties \n
29
-
30
- Parameters
31
- ----------
32
- npool : `int`
33
- number of processors to use
34
- z_min : `float`
35
- minimum redshift
36
- z_max : `float`
37
- maximum redshift
38
- cosmology : `astropy.cosmology`
39
- Cosmology to use
40
- default: None/astropy.cosmology.FlatLambdaCDM(H0=70, Om0=0.3)
41
- event_type : `str`
42
- Type of event to generate.
43
- e.g. 'BBH', 'BNS', 'NSBH'
44
- default: 'BBH'
45
- lens_type : `str`
46
- Type of lens galaxy to generate.
47
- default: 'epl_galaxy'
48
- lens_functions, lens_priors, lens_priors_params : `dict`, `dict`, `dict`
49
- dictionary of lens functions, priors, and priors parameters
50
- Check for default/available lens functions, priors and corresponding input parameters by running,\n
26
+ Class to sample lens galaxy parameters, source parameters conditioned on the source being strongly lensed, and image properties \n
27
+
28
+ Parameters
29
+ ----------
30
+ npool : `int`
31
+ number of processors to use
32
+ z_min : `float`
33
+ minimum redshift
34
+ z_max : `float`
35
+ maximum redshift
36
+ cosmology : `astropy.cosmology`
37
+ Cosmology to use
38
+ default: None/astropy.cosmology.FlatLambdaCDM(H0=70, Om0=0.3)
39
+ event_type : `str`
40
+ Type of event to generate.
41
+ e.g. 'BBH', 'BNS', 'NSBH'
42
+ default: 'BBH'
43
+ lens_type : `str`
44
+ Type of lens galaxy to generate.
45
+ default: 'epl_shear_galaxy'
46
+ lens_functions, lens_priors, lens_priors_params : `dict`, `dict`, `dict`
47
+ dictionary of lens functions, priors, and priors parameters
48
+ Check for default/available lens functions, priors and corresponding input parameters by running,\n
49
+ >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
50
+ >>> lens = LensGalaxyParameterDistribution()
51
+ >>> print(lens.lens_functions)
52
+ >>> print(lens.lens_priors)
53
+ >>> print(lens.lens_priors_params)
54
+ directory : `str`
55
+ directory to store the interpolators
56
+ default: './interpolator_pickle'
57
+ **kwargs :
58
+ keyword arguments to pass to the parent classes
59
+
60
+ Examples
61
+ --------
51
62
  >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
52
63
  >>> lens = LensGalaxyParameterDistribution()
53
- >>> print(lens.lens_functions)
54
- >>> print(lens.lens_priors)
55
- >>> print(lens.lens_priors_params)
56
- directory : `str`
57
- directory to store the interpolators
58
- default: './interpolator_pickle'
59
- **kwargs :
60
- keyword arguments to pass to the parent classes
61
-
62
- Examples
63
- --------
64
- >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
65
- >>> lens = LensGalaxyParameterDistribution()
66
- >>> lensed_params = lens.sample_lens_parameters(size=1000)
67
- >>> lensed_params.keys()
68
-
69
- Instance Attributes
70
- ----------
71
- LensGalaxyPopulation class has the following instance attributes:\n
72
- +-------------------------------------+----------------------------------+
73
- | Atrributes | Type |
74
- +=====================================+==================================+
75
- |:attr:`~npool` | `int` |
76
- +-------------------------------------+----------------------------------+
77
- |:attr:`~z_min` | `float` |
78
- +-------------------------------------+----------------------------------+
79
- |:attr:`~z_max` | `float` |
80
- +-------------------------------------+----------------------------------+
81
- |:attr:`~cosmo` | `astropy.cosmology` |
82
- +-------------------------------------+----------------------------------+
83
- |:attr:`~event_type` | `str` |
84
- +-------------------------------------+----------------------------------+
85
- |:attr:`~directory` | `str` |
86
- +-------------------------------------+----------------------------------+
87
- |:attr:`~create_new_interpolator` | `dict` |
88
- +-------------------------------------+----------------------------------+
89
- |:attr:`~lens_param_samplers` | `dict` |
90
- +-------------------------------------+----------------------------------+
91
- |:attr:`~lens_param_samplers_params` | `dict` |
92
- +-------------------------------------+----------------------------------+
93
- |:attr:`~lens_sampler_names` | `dict` |
94
- +-------------------------------------+----------------------------------+
95
- |:attr:`~lens_functions` | `dict` |
96
- +-------------------------------------+----------------------------------+
97
- |:attr:`~normalization_pdf_z_lensed` | `float` |
98
- +-------------------------------------+----------------------------------+
99
-
100
- Instance Methods
101
- ----------
102
- LensGalaxyPopulation class has the following instance methods:\n
103
- +-------------------------------------+----------------------------------+
104
- | Methods | Type |
105
- +=====================================+==================================+
106
- |:meth:`~sample_lens_parameters` | Function to call the specific |
107
- | | galaxy lens parameters sampler |
108
- | | routine. |
109
- +-------------------------------------+----------------------------------+
110
- |:meth:`~sample_all_routine` | Function to sample galaxy lens |
111
- | | parameters along with the source |
112
- | | parameters. |
113
- +-------------------------------------+----------------------------------+
114
- |:meth:`~strongly_lensed_source_redshifts` |
115
- +-------------------------------------+----------------------------------+
116
- | | Function to sample source |
117
- | | redshifts conditioned on the |
118
- | | source being strongly lensed |
119
- +-------------------------------------+----------------------------------+
120
- |:meth:`~source_parameters` | Function to sample gw source |
121
- | | parameters |
122
- +-------------------------------------+----------------------------------+
123
- |:meth:`~lens_redshift_SDSS_catalogue`| Function to sample lens |
124
- | | redshifts, conditioned on the |
125
- | | lens being strongly lensed |
126
- +-------------------------------------+----------------------------------+
127
- |:meth:`~axis_rotation_angle_uniform` | Function to sample the axis |
128
- | | rotation angle of the elliptical |
129
- | | lens galaxy from a uniform |
130
- | | distribution |
131
- +-------------------------------------+----------------------------------+
132
- |:meth:`~shear_norm` | Function to sample the |
133
- | | elliptical lens galaxy shear |
134
- | | from a normal distribution |
135
- +-------------------------------------+----------------------------------+
136
- |:meth:`~mass_density_spectral_index_normal` |
137
- +-------------------------------------+----------------------------------+
138
- | | Function to sample the lens |
139
- | | galaxy spectral index of the |
140
- | | mass density profile from a |
141
- | | normal distribution |
142
- +-------------------------------------+----------------------------------+
143
- |:meth:`~compute_einstein_radii` | Function to compute the Einstein |
144
- | | radii of the lens galaxies |
145
- +-------------------------------------+----------------------------------+
146
- |:meth:`~rjs_with_cross_section_SIE` | Function to conduct rejection |
147
- | | sampling wrt einstein radius |
148
- +-------------------------------------+----------------------------------+
149
- |:meth:`~rjs_with_cross_section_SIE` | Function to conduct rejection |
150
- | | sampling wrt cross_section |
151
- +-------------------------------------+----------------------------------+
152
- |:attr:`~rejection_sample_sl` | Function to conduct rejection |
153
- | | sampling with the given rejection|
154
- | | sampling function |
155
- +-------------------------------------+----------------------------------+
156
- |:attr:`~sample_source_redshift_sl` | Function to sample source |
157
- | | redshifts conditioned on the |
158
- | | source being strongly lensed |
159
- +-------------------------------------+----------------------------------+
160
- |:attr:`~sample_lens_redshift` | Function to sample lens |
161
- | | redshifts, conditioned on the |
162
- | | lens being strongly lensed |
163
- +-------------------------------------+----------------------------------+
164
- |:attr:`~sample_axis_rotation_angle` | Function to sample the axis |
165
- | | rotation angle of the elliptical |
166
- | | lens galaxy from a uniform |
167
- | | distribution |
168
- +-------------------------------------+----------------------------------+
169
- |:attr:`~sample_shear` | Function to sample the |
170
- | | elliptical lens galaxy shear |
171
- | | from a normal distribution |
172
- +-------------------------------------+----------------------------------+
173
- |:attr:`~sample_mass_density_spectral_index` |
174
- +-------------------------------------+----------------------------------+
175
- | | Function to sample the lens |
176
- | | galaxy spectral index of the |
177
- | | mass density profile from a |
178
- | | normal distribution |
179
- +-------------------------------------+----------------------------------+
64
+ >>> lensed_params = lens.sample_lens_parameters(size=1000)
65
+ >>> lensed_params.keys()
66
+
67
+ Instance Attributes
68
+ ----------
69
+ LensGalaxyPopulation class has the following instance attributes:\n
70
+ +-------------------------------------+----------------------------------+
71
+ | Atrributes | Type |
72
+ +=====================================+==================================+
73
+ |:attr:`~npool` | `int` |
74
+ +-------------------------------------+----------------------------------+
75
+ |:attr:`~z_min` | `float` |
76
+ +-------------------------------------+----------------------------------+
77
+ |:attr:`~z_max` | `float` |
78
+ +-------------------------------------+----------------------------------+
79
+ |:attr:`~cosmo` | `astropy.cosmology` |
80
+ +-------------------------------------+----------------------------------+
81
+ |:attr:`~event_type` | `str` |
82
+ +-------------------------------------+----------------------------------+
83
+ |:attr:`~directory` | `str` |
84
+ +-------------------------------------+----------------------------------+
85
+ |:attr:`~create_new_interpolator` | `dict` |
86
+ +-------------------------------------+----------------------------------+
87
+ |:attr:`~lens_param_samplers` | `dict` |
88
+ +-------------------------------------+----------------------------------+
89
+ |:attr:`~lens_param_samplers_params` | `dict` |
90
+ +-------------------------------------+----------------------------------+
91
+ |:attr:`~lens_sampler_names` | `dict` |
92
+ +-------------------------------------+----------------------------------+
93
+ |:attr:`~lens_functions` | `dict` |
94
+ +-------------------------------------+----------------------------------+
95
+ |:attr:`~normalization_pdf_z_lensed` | `float` |
96
+ +-------------------------------------+----------------------------------+
97
+
98
+ Instance Methods
99
+ ----------
100
+ LensGalaxyPopulation class has the following instance methods:\n
101
+ +-------------------------------------+----------------------------------+
102
+ | Methods | Type |
103
+ +=====================================+==================================+
104
+ |:meth:`~sample_lens_parameters` | Function to call the specific |
105
+ | | galaxy lens parameters sampler |
106
+ | | routine. |
107
+ +-------------------------------------+----------------------------------+
108
+ |:meth:`~sample_all_routine_sie` | Function to sample galaxy lens |
109
+ | | parameters along with the source |
110
+ | | parameters. |
111
+ +-------------------------------------+----------------------------------+
112
+ |:meth:`~strongly_lensed_source_redshifts` |
113
+ +-------------------------------------+----------------------------------+
114
+ | | Function to sample source |
115
+ | | redshifts conditioned on the |
116
+ | | source being strongly lensed |
117
+ +-------------------------------------+----------------------------------+
118
+ |:meth:`~source_parameters` | Function to sample gw source |
119
+ | | parameters |
120
+ +-------------------------------------+----------------------------------+
121
+ |:meth:`~lens_redshift_SDSS_catalogue`| Function to sample lens |
122
+ | | redshifts, conditioned on the |
123
+ | | lens being strongly lensed |
124
+ +-------------------------------------+----------------------------------+
125
+ |:meth:`~axis_rotation_angle_uniform` | Function to sample the axis |
126
+ | | rotation angle of the elliptical |
127
+ | | lens galaxy from a uniform |
128
+ | | distribution |
129
+ +-------------------------------------+----------------------------------+
130
+ |:meth:`~shear_norm` | Function to sample the |
131
+ | | elliptical lens galaxy shear |
132
+ | | from a normal distribution |
133
+ +-------------------------------------+----------------------------------+
134
+ |:meth:`~density_profile_slope_normal` |
135
+ +-------------------------------------+----------------------------------+
136
+ | | Function to sample the lens |
137
+ | | galaxy spectral index of the |
138
+ | | mass density profile from a |
139
+ | | normal distribution |
140
+ +-------------------------------------+----------------------------------+
141
+ |:meth:`~compute_einstein_radii` | Function to compute the Einstein |
142
+ | | radii of the lens galaxies |
143
+ +-------------------------------------+----------------------------------+
144
+ |:meth:`~rjs_with_cross_section_sis` | Function to conduct rejection |
145
+ | | sampling wrt einstein radius |
146
+ +-------------------------------------+----------------------------------+
147
+ |:meth:`~rjs_with_cross_section_sie` | Function to conduct rejection |
148
+ | | sampling wrt cross_section |
149
+ +-------------------------------------+----------------------------------+
150
+ |:attr:`~rejection_sample_sl` | Function to conduct rejection |
151
+ | | sampling with the given rejection|
152
+ | | sampling function |
153
+ +-------------------------------------+----------------------------------+
154
+ |:attr:`~sample_source_redshift_sl` | Function to sample source |
155
+ | | redshifts conditioned on the |
156
+ | | source being strongly lensed |
157
+ +-------------------------------------+----------------------------------+
158
+ |:attr:`~sample_lens_redshift` | Function to sample lens |
159
+ | | redshifts, conditioned on the |
160
+ | | lens being strongly lensed |
161
+ +-------------------------------------+----------------------------------+
162
+ |:attr:`~sample_axis_rotation_angle` | Function to sample the axis |
163
+ | | rotation angle of the elliptical |
164
+ | | lens galaxy from a uniform |
165
+ | | distribution |
166
+ +-------------------------------------+----------------------------------+
167
+ |:attr:`~sample_shear` | Function to sample the |
168
+ | | elliptical lens galaxy shear |
169
+ | | from a normal distribution |
170
+ +-------------------------------------+----------------------------------+
171
+ |:attr:`~sample_density_profile_slope` |
172
+ +-------------------------------------+----------------------------------+
173
+ | | Function to sample the lens |
174
+ | | galaxy spectral index of the |
175
+ | | mass density profile from a |
176
+ | | normal distribution |
177
+ +-------------------------------------+----------------------------------+
180
178
  """
181
179
 
182
180
  # Attributes
183
181
  cbc_pop = None
184
- """:class:`~CompactBinaryPopulation` class\n
185
- This is an already initialized class that contains a function (CompactBinaryPopulation.sample_gw_parameters) that actually samples the source parameters.
182
+ """:class:`~CBCSourceParameterDistribution` class\n
183
+ This is an already initialized class that contains a function (CBCSourceParameterDistribution.sample_gw_parameters) that actually samples the source parameters.
186
184
  """
187
185
 
188
186
  z_min = None
@@ -216,85 +214,51 @@ class LensGalaxyParameterDistribution(CBCSourceParameterDistribution, ImagePrope
216
214
  z_max=10.0,
217
215
  cosmology=None,
218
216
  event_type="BBH",
219
- lens_type="epl_galaxy",
217
+ lens_type="epl_shear_galaxy",
220
218
  lens_functions= None,
221
- lens_priors=None,
222
- lens_priors_params=None,
219
+ lens_functions_params=None,
220
+ lens_param_samplers=None,
221
+ lens_param_samplers_params=None,
223
222
  directory="./interpolator_pickle",
224
223
  create_new_interpolator=False,
225
- **kwargs
224
+ buffer_size=1000,
225
+ **kwargs # for initialization of CBCSourceParameterDistribution class and ImageProperties class
226
226
  ):
227
-
228
- self.npool = npool
229
- self.z_min = z_min
230
- self.z_max = z_max
231
- self.cosmo = cosmology if cosmology else LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
232
- self.event_type = event_type
233
- self.directory = directory
234
- # initialize the interpolator's parameters
235
- self.create_new_interpolator = dict(
236
- redshift_distribution=dict(create_new=False, resolution=1000),
237
- z_to_luminosity_distance=dict(create_new=False, resolution=1000),
238
- velocity_dispersion=dict(create_new=False, resolution=1000),
239
- axis_ratio=dict(create_new=False, resolution=1000),
240
- optical_depth=dict(create_new=False, resolution=200),
241
- z_to_Dc=dict(create_new=False, resolution=1000),
242
- Dc_to_z=dict(create_new=False, resolution=1000),
243
- angular_diameter_distance=dict(create_new=False, resolution=1000),
244
- differential_comoving_volume=dict(create_new=False, resolution=1000),
245
- luminosity_distance_to_z=dict(create_new=False, resolution=1000),
246
- )
247
- if isinstance(create_new_interpolator, dict):
248
- self.create_new_interpolator.update(create_new_interpolator)
249
- elif create_new_interpolator is True:
250
- self.create_new_interpolator = dict(
251
- redshift_distribution=dict(create_new=True, resolution=1000),
252
- z_to_luminosity_distance=dict(create_new=True, resolution=1000),
253
- velocity_dispersion=dict(create_new=True, resolution=1000),
254
- axis_ratio=dict(create_new=True, resolution=1000),
255
- optical_depth=dict(create_new=True, resolution=200),
256
- z_to_Dc=dict(create_new=True, resolution=1000),
257
- Dc_to_z=dict(create_new=True, resolution=1000),
258
- angular_diameter_distance=dict(create_new=True, resolution=1000),
259
- differential_comoving_volume=dict(create_new=True, resolution=1000),
260
- luminosity_distance_to_z=dict(create_new=True, resolution=1000),
261
- )
262
-
263
- # dealing with prior functions and categorization
264
- self.lens_param_samplers, self.lens_param_samplers_params, self.lens_sampler_names, self.lens_functions = self.lens_priors_categorization(lens_type, lens_priors,
265
- lens_priors_params, lens_functions)
266
-
267
- # function initialization
268
- self.sample_lens_parameters_routine = getattr(self, self.lens_functions['param_sampler_type'])
269
- self.rejection_sample_sl = getattr(self, self.lens_functions['strong_lensing_condition'])
227
+ print("\nInitializing LensGalaxyParameterDistribution class...\n")
228
+ self.event_type = event_type # needed for the source population
229
+ self.buffer_size = buffer_size # buffer size for sampling lens parameters
270
230
 
271
231
  # initializing parent classes
272
- self.class_initialization_lens(params=kwargs);
273
-
274
- # initializing samplers
275
- # self.sample_velocity_dispersion and self.sample_axis_ratio are initialized in OpticalDepth class
276
- self.sample_source_redshift_sl = self.lens_param_samplers["source_redshift_sl"]
277
- self.sample_lens_redshift = self.lens_param_samplers["lens_redshift"]
278
- # self.sample_axis_ratio = self.lens_param_samplers["axis_ratio"]
279
- self.sample_axis_rotation_angle = self.lens_param_samplers[
280
- "axis_rotation_angle"
281
- ]
282
- self.sample_shear = self.lens_param_samplers["shear"]
283
- self.sample_mass_density_spectral_index = self.lens_param_samplers[
284
- "mass_density_spectral_index"
285
- ]
286
- self.sample_source_parameters = self.lens_param_samplers["source_parameters"]
287
-
288
- # extra care to the velocity dispersion sampler
289
- if self.lens_param_samplers["velocity_dispersion"] == "velocity_dispersion_ewoud":
290
- vd_inv_cdf = self.vd_inv_cdf
291
- zl_list = self.zl_list
292
- self.sample_velocity_dispersion = lambda size, zl: velocity_dispersion_z_dependent(size=size, zl=zl, zl_list=zl_list, vd_inv_cdf=vd_inv_cdf)
232
+ self.class_initialization_lens(
233
+ npool,
234
+ z_min,
235
+ z_max,
236
+ cosmology,
237
+ lens_type,
238
+ lens_functions,
239
+ lens_functions_params,
240
+ lens_param_samplers,
241
+ lens_param_samplers_params,
242
+ directory,
243
+ create_new_interpolator,
244
+ params=kwargs, # related parameters for CBCSourceParameterDistribution, ImageProperties classes
245
+ );
246
+
247
+ # function to sample source redshifts conditioned on the source being strongly lensed
248
+ self.sample_source_redshift_sl = getattr(self,self.lens_param_samplers["source_redshift_sl"])
249
+
250
+ # interpolated cross section function is not very accurate for rejection sampling
251
+ if self.lens_functions["cross_section"] == "interpolated_cross_section_function":
252
+ self.cross_section = self.cross_section_caustic_area
253
+ # function to sample lens parameters
254
+ self.sample_lens_parameters_routine = getattr(self, self.lens_functions['param_sampler_type'])
255
+ # function to rejection sample wrt lens cross section
256
+ self.rejection_sample_sl = getattr(self, self.lens_functions['strong_lensing_condition'])
293
257
 
294
258
  # To find the normalization constant of the pdf p(z)
295
259
  # this under the assumption that the event is strongly lensed
296
260
  # Define the merger-rate density function
297
- pdf_unnormalized_ = lambda z: self.merger_rate_density_detector_frame(np.array([z]), param=self.merger_rate_density_param) * self.strong_lensing_optical_depth(np.array([z]))
261
+ pdf_unnormalized_ = lambda z: self.merger_rate_density_detector_frame(np.array([z])) * self.optical_depth.function(np.array([z]))
298
262
  pdf_unnormalized = lambda z: pdf_unnormalized_(z)[0]
299
263
 
300
264
  self.normalization_pdf_z_lensed = quad(
@@ -303,17 +267,58 @@ class LensGalaxyParameterDistribution(CBCSourceParameterDistribution, ImagePrope
303
267
  self.z_max
304
268
  )[0]
305
269
 
306
- def class_initialization_lens(self, params=None):
270
+ def class_initialization_lens(self, npool, z_min, z_max, cosmology, lens_type, lens_functions, lens_functions_params, lens_param_samplers, lens_param_samplers_params, directory, create_new_interpolator, params):
307
271
  """
308
- Function to initialize the parent classes
272
+ Initialize the LensGalaxyParameterDistribution class.
273
+
274
+ Parameters
275
+ ----------
276
+ npool : `int`
277
+ number of processors to use for sampling
278
+ z_min : `float`
279
+ minimum redshift of the lens galaxy
280
+ z_max : `float`
281
+ maximum redshift of the lens galaxy
282
+ cosmology : `astropy.cosmology`
283
+ cosmology object
284
+ lens_type : `str`
285
+ type of the lens galaxy
286
+ lens_functions : `dict`
287
+ dictionary with the lens related functions
288
+ lens_functions_params : `dict`
289
+ dictionary with the parameters for the lens related functions
290
+ lens_param_samplers : `dict`
291
+ dictionary with the priors for the sampler
292
+ lens_param_samplers_params : `dict`
293
+ dictionary with the parameters for the priors of the sampler
294
+ directory : `str`
295
+ directory where the interpolators are saved
296
+ create_new_interpolator : `bool`
297
+ if True, creates a new interpolator
298
+ params : `dict`
299
+ additional parameters for the CBCSourceParameterDistribution and ImageProperties classes
309
300
 
310
- Parameters
311
- ----------
312
- params : `dict`
313
- dictionary of parameters to initialize the parent classes
314
301
  """
315
302
 
316
- # initialization of CompactBinaryPopulation class
303
+ # initialize the optical depth class
304
+ # this also initializes the lens related parameter samplers and functions:
305
+ # self.lens_param_samplers, self.lens_param_samplers_params, self.lens_functions, self.lens_functions_params
306
+ OpticalDepth.__init__(
307
+ self,
308
+ npool = npool,
309
+ z_min = z_min,
310
+ z_max = z_max,
311
+ cosmology=cosmology,
312
+ lens_type = lens_type,
313
+ lens_functions = lens_functions,
314
+ lens_functions_params = lens_functions_params,
315
+ lens_param_samplers=lens_param_samplers,
316
+ lens_param_samplers_params=lens_param_samplers_params,
317
+ directory=directory,
318
+ create_new_interpolator=create_new_interpolator,
319
+ )
320
+
321
+ # initialization of CBCSourceParameterDistribution class
317
322
  # it also initializes the CBCSourceRedshiftDistribution class
318
323
  # list of relevant initialized instances,
319
324
  # 1. self.sample_source_redshift
@@ -340,42 +345,18 @@ class LensGalaxyParameterDistribution(CBCSourceParameterDistribution, ImagePrope
340
345
  create_new_interpolator=self.create_new_interpolator,
341
346
  )
342
347
 
343
- # initialize the optical depth class
344
- # follwing attributes are initialized
345
- # 1. self.strong_lensing_optical_depth
346
- # 2. self.sample_velocity_dispersion
347
- # 3. self.sample_axis_ratio
348
- OpticalDepth.__init__(
349
- self,
350
- npool=self.npool,
351
- z_min=self.z_min,
352
- z_max=self.z_max,
353
- optical_depth_function=self.lens_functions["optical_depth"],
354
- sampler_priors=dict(
355
- velocity_dispersion=self.lens_param_samplers["velocity_dispersion"],
356
- axis_ratio=self.lens_param_samplers["axis_ratio"],
357
- ),
358
- sampler_priors_params=dict(
359
- velocity_dispersion=self.lens_param_samplers_params[
360
- "velocity_dispersion"],
361
- axis_ratio=self.lens_param_samplers_params["axis_ratio"],
362
- ),
363
- cosmology=self.cosmo,
364
- directory=self.directory,
365
- create_new_interpolator=self.create_new_interpolator,
366
- )
367
-
368
348
  # initialize the image properties class
369
349
  input_params_image = dict(
370
350
  n_min_images=2,
371
351
  n_max_images=4,
372
- geocent_time_min=1126259462.4,
373
- geocent_time_max=1126259462.4+365*24*3600*10,
352
+ time_window=365*24*3600*20,
353
+ # geocent_time_min=1126259462.4,
354
+ # geocent_time_max=1126259462.4+365*24*3600*2,
374
355
  lens_model_list=["EPL_NUMBA", "SHEAR"],
375
356
  )
376
357
  input_params_image.update(params)
377
358
 
378
- print("input_params_image", input_params_image)
359
+ # print("input_params_image", input_params_image)
379
360
  ImageProperties.__init__(
380
361
  self,
381
362
  npool=self.npool,
@@ -385,111 +366,147 @@ class LensGalaxyParameterDistribution(CBCSourceParameterDistribution, ImagePrope
385
366
  n_max_images=input_params_image["n_max_images"],
386
367
  lens_model_list=input_params_image["lens_model_list"],
387
368
  cosmology=self.cosmo,
388
- geocent_time_min=input_params_image["geocent_time_min"],
389
- geocent_time_max=input_params_image["geocent_time_max"],
369
+ time_window=input_params_image["time_window"],
370
+ # geocent_time_min=input_params_image["geocent_time_min"],
371
+ # geocent_time_max=input_params_image["geocent_time_max"],
390
372
  spin_zero=input_params["spin_zero"],
391
373
  spin_precession=input_params["spin_precession"],
392
374
  directory=self.directory,
393
375
  create_new_interpolator=self.create_new_interpolator,
394
376
  )
395
377
 
396
- def lens_priors_categorization(
397
- self, lens_type, lens_priors=None, lens_priors_params=None, lens_functions=None,
398
- ):
378
+ def sample_lens_parameters(self, size=1000,):
399
379
  """
400
- Function to categorize the lens priors/samplers
401
-
402
- Parameters
403
- ----------
404
- lens_type : `str`
405
- lens type
406
- e.g. 'epl_galaxy' for elliptical power-law galaxy
407
- lens_priors : `dict`
408
- dictionary of priors
409
- lens_priors_params : `dict`
410
- dictionary of priors parameters
411
- lens_functions : `dict`
412
- dictionary of lens functions
413
-
414
- Returns
415
- -------
416
- lens_priors_ : `dict`
417
- dictionary of priors
418
- lens_priors_params_ : `dict`
419
- dictionary of priors parameters
420
- lens_sampler_names_ : `dict`
421
- dictionary of sampler names
422
- lens_functions_ : `dict`
423
- dictionary of lens functions
380
+ Function to sample galaxy lens parameters along with the source parameters, conditioned on the source being strongly lensed.
381
+
382
+ Parameters
383
+ ----------
384
+ size : `int`
385
+ number of lens parameters to sample
386
+
387
+ Returns
388
+ -------
389
+ lens_parameters : `dict`
390
+ dictionary of sampled lens parameters and source parameters. \n
391
+ keys: \n
392
+ zl: lens redshifts \n
393
+ zs: source redshifts, lensed condition applied\n
394
+ sigma: velocity dispersions \n
395
+ q: axis ratios \n
396
+ theta_E: Einstein radii \n
397
+ phi: axis rotation angle \n
398
+ e1: ellipticity component 1 \n
399
+ e2: ellipticity component 2 \n
400
+ gamma1: shear component 1 \n
401
+ gamma2: shear component 2 \n
402
+ gamma: density profile slope distribution \n
403
+ geocent_time: time of arrival of the unlensed signal\n
404
+ phase: phase of the unlensed signal\n
405
+ psi: polarization angle of the unlensed signal\n
406
+ theta_jn: inclination angle of the unlensed signal\n
407
+ luminosity_distance: luminosity distance of the source\n
408
+ mass_1_source: mass 1 (larger) of the source\n
409
+ mass_2_source: mass 2 (smaller) of the source\n
410
+ ra: right ascension of the source\n
411
+ dec: declination of the source\n
412
+
413
+ Examples
414
+ --------
415
+ >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
416
+ >>> od = LensGalaxyParameterDistribution(lens_param_samplers=dict(velocity_dispersion="velocity_dispersion_ewoud"))
417
+ >>> print(od.sample_lens_parameters(size=10))
424
418
  """
425
419
 
426
- if lens_type == "epl_galaxy":
427
- lens_priors_ = dict(
428
- source_redshift_sl="strongly_lensed_source_redshifts",
429
- lens_redshift="lens_redshift_SDSS_catalogue",
430
- velocity_dispersion="velocity_dispersion_ewoud",
431
- axis_ratio="axis_ratio_rayleigh",
432
- axis_rotation_angle="axis_rotation_angle_uniform",
433
- shear="shear_norm",
434
- mass_density_spectral_index="mass_density_spectral_index_normal",
435
- source_parameters="sample_gw_parameters",
436
- )
437
- lens_priors_params_ = dict(
438
- source_redshift_sl=None,
439
- lens_redshift=None,
440
- velocity_dispersion=None,
441
- axis_ratio=dict(q_min=0.2, q_max=1.),
442
- axis_rotation_angle=dict(phi_min=0.0, phi_max=2 * np.pi),
443
- shear=dict(scale=0.05),
444
- mass_density_spectral_index=dict(mean=2.0, std=0.2),
445
- source_parameters=None,
446
- )
447
- lens_functions_ = dict(
448
- strong_lensing_condition="rjs_with_cross_section_SIE",
449
- optical_depth="optical_depth_SIE_hemanta",
450
- param_sampler_type="sample_all_routine",
451
- )
452
- else:
453
- raise ValueError("lens_type not recognized")
454
-
455
- # update the priors if input is given
456
- if lens_priors:
457
- lens_priors_.update(lens_priors)
458
- if lens_priors_params:
459
- lens_priors_params_.update(lens_priors_params)
460
- if lens_functions:
461
- lens_functions_.update(lens_functions)
462
-
463
- # dict of sampler names with description
464
- lens_sampler_names_ = dict(
465
- sample_source_redshift_sl="source parameters conditioned on the source being strongly lensed",
466
- sample_lens_redshift="lens redshift",
467
- sample_velocity_dispersion="velocity dispersion of elliptical galaxy",
468
- sample_axis_ratio="axis ratio of elliptical galaxy",
469
- sample_axis_rotation_angle="axis rotation angle of elliptical galaxy ",
470
- sample_shear="shear of elliptical galaxy",
471
- sample_mass_density_spectral_index="mass density spectral index of elliptical power-law galaxy",
472
- sample_source_parameters="source parameters other than redshift",
420
+ print(f"sampling lens parameters with {self.lens_functions['param_sampler_type']}...")
421
+
422
+ # get sample lens parameters, strongly lensed
423
+ lens_parameters = self.sample_lens_parameters_routine(
424
+ size=size
473
425
  )
474
426
 
475
- return(lens_priors_, lens_priors_params_, lens_sampler_names_, lens_functions_)
427
+ # sample gravitional waves source parameter
428
+ param = dict(zs=lens_parameters["zs"])
429
+ # zs won't be sampling again
430
+ gw_param = self.sample_gw_parameters(size=size, param=param)
431
+ # Add source params strongly lensed to the lens params
432
+ lens_parameters.update(gw_param)
476
433
 
477
- def sample_lens_parameters(
478
- self,
479
- size=1000,
480
- lens_parameters_input=None,
481
- ):
434
+ return lens_parameters
435
+
436
+ def sample_all_routine_sis_sl(self, size=1000):
482
437
  """
483
- Function to call the specific galaxy lens parameters sampler routine.
438
+ Function to sample galaxy lens parameters. SIS cross section is used for rejection sampling.
484
439
  """
485
440
 
486
- return self.sample_lens_parameters_routine(
487
- size=size, lens_parameters_input=lens_parameters_input
488
- )
441
+ buffer_size = self.buffer_size
442
+
443
+ # Sample source redshifts from the source population
444
+ # rejection sampled with optical depth
445
+ zs = self.sample_source_redshift_sl(size)
489
446
 
490
- def sample_all_routine(self, size=1000, lens_parameters_input=None):
447
+ # # Sample lens redshifts
448
+ zl = self.lens_redshift.rvs(size, zs)
449
+
450
+ sigma = np.zeros(size)
451
+ theta_E = np.zeros(size)
452
+
453
+ sigma_max = self.velocity_dispersion.info['sigma_max']
454
+
455
+ for i in tqdm(range(size), ncols=100, disable=False):
456
+ zs_ = zs[i]*np.ones(buffer_size)
457
+ zl_ = zl[i]*np.ones(buffer_size)
458
+
459
+ # cross_section_max calculation
460
+ theta_E_max = self.compute_einstein_radii(np.array([sigma_max]), np.array([zl[i]]), np.array([zs[i]]))[0]
461
+ cross_section_max = np.pi*theta_E_max**2
462
+
463
+ while True:
464
+ # Create a dictionary of the lens parameters; sigma, theta_E, q, phi, e1, e2
465
+ lens_parameters_ = self.sampling_routine_sie_nsl(zl_, zs_, size=buffer_size)
466
+
467
+ # Rejection sample based on the lensing probability, that is, rejection sample wrt theta_E
468
+ lens_parameters_, mask, cross_section_max_ = self.rjs_with_cross_section_sis(
469
+ lens_parameters_, cross_section_max
470
+ ) # proportional to pi theta_E^2
471
+
472
+ if cross_section_max_>cross_section_max:
473
+ cross_section_max = cross_section_max_
474
+
475
+ if np.sum(mask) > 0:
476
+ break
477
+
478
+ sigma[i] = lens_parameters_["sigma"][0]
479
+ theta_E[i] = lens_parameters_["theta_E"][0]
480
+
481
+ # sample additional lens parameters
482
+ # P(q|SL), P(gamma|SL), P(gamma1, gamma2|SL)
483
+ q = self.axis_ratio.rvs(size)
484
+ gamma = self.density_profile_slope_sl.rvs(size)
485
+ gamma1, gamma2 = self.external_shear_sl.rvs(size)
486
+
487
+ phi = self.axis_rotation_angle.rvs(size)
488
+ e1, e2 = phi_q2_ellipticity_hemanta(phi, q)
489
+
490
+ # Create a dictionary of the lens parameters
491
+ lens_parameters = {
492
+ "zl": zl,
493
+ "zs": zs,
494
+ "sigma": sigma,
495
+ "theta_E": theta_E,
496
+ "q": q,
497
+ "phi": phi,
498
+ "e1": e1,
499
+ "e2": e2,
500
+ "gamma": gamma,
501
+ "gamma1": gamma1,
502
+ "gamma2": gamma2,
503
+ }
504
+
505
+ return lens_parameters
506
+
507
+ def sample_all_routine_sie_sl(self, size=1000):
491
508
  """
492
- Function to sample galaxy lens parameters along with the source parameters.
509
+ Function to sample galaxy lens parameters. SIE cross section is used for rejection sampling.
493
510
 
494
511
  Parameters
495
512
  ----------
@@ -512,406 +529,416 @@ class LensGalaxyParameterDistribution(CBCSourceParameterDistribution, ImagePrope
512
529
  e2: ellipticity component 2 \n
513
530
  gamma1: shear component 1 \n
514
531
  gamma2: shear component 2 \n
515
- gamma: spectral index of the mass density distribution \n
516
- geocent_time: time of arrival of the unlensed signal\n
517
- phase: phase of the unlensed signal\n
518
- psi: polarization angle of the unlensed signal\n
519
- theta_jn: inclination angle of the unlensed signal\n
520
- luminosity_distance: luminosity distance of the source\n
521
- mass_1_source: mass 1 (larger) of the source\n
522
- mass_2_source: mass 2 (smaller) of the source\n
523
- ra: right ascension of the source\n
524
- dec: declination of the source\n
532
+ gamma: density profile slope distribution \n
525
533
 
526
534
  Examples
527
535
  --------
528
536
  >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
529
537
  >>> lens = LensGalaxyParameterDistribution()
530
- >>> lens.sample_all_routine(size=1000)
538
+ >>> lens.sample_all_routine_sie(size=1000)
531
539
  """
532
540
 
533
- if lens_parameters_input is None:
534
- lens_parameters_input = dict()
535
- samplers_params = self.lens_param_samplers_params.copy()
541
+ buffer_size = self.buffer_size
536
542
 
537
543
  # Sample source redshifts from the source population
538
544
  # rejection sampled with optical depth
539
- zs = self.sample_source_redshift_sl(size=size)
540
-
541
- # Sample lens redshifts
542
- zl = self.sample_lens_redshift(zs=zs)
543
-
544
- # Sample velocity dispersions
545
- try:
546
- sigma = self.sample_velocity_dispersion(len(zs))
547
- except:
548
- sigma = self.sample_velocity_dispersion(len(zs), zl)
549
-
550
- # Sample axis ratios
551
- try:
552
- q = self.sample_axis_ratio(sigma)
553
- except:
554
- q = self.sample_axis_ratio(len(sigma))
555
-
556
- # Compute the Einstein radii
557
- theta_E = self.compute_einstein_radii(sigma, zl, zs)
545
+ zs = self.sample_source_redshift_sl(size)
546
+
547
+ # # Sample lens redshifts
548
+ zl = self.lens_redshift.rvs(size, zs)
549
+
550
+ sigma = np.zeros(size)
551
+ theta_E = np.zeros(size)
552
+ q = np.zeros(size)
553
+
554
+ # # set-up multiprocessing args
555
+ # q_args_cdf_values = self.axis_ratio.cdf_values
556
+ # q_args_x_array = self.axis_ratio.x_array
557
+ # q_args_conditioned_y_array = self.axis_ratio.conditioned_y_array
558
+
559
+ # sigma_args_cdf_values = self.velocity_dispersion.cdf_values
560
+ # sigma_args_x_array = self.velocity_dispersion.x_array
561
+ # sigma_args_conditioned_y_array = self.velocity_dispersion.conditioned_y_array
562
+
563
+ # da_args_function_spline = self.angular_diameter_distance.function_spline
564
+ # da_args_x_array = self.angular_diameter_distance.x_array
565
+
566
+ # idx = np.arange(size)
567
+ # input_params = np.array([(idx[i], zs[i], zl[i], 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) for i in range(size)], dtype=object)
568
+
569
+ # with Pool(processes=self.npool) as pool:
570
+ # for result in tqdm(
571
+ # pool.imap_unordered(rjs_sie_mp, input_params),
572
+ # total=size,
573
+ # ncols=100,
574
+ # disable=False,
575
+ # ):
576
+ # (
577
+ # idx_,
578
+ # sigma_,
579
+ # theta_E_,
580
+ # q_,
581
+ # ) = result
582
+
583
+ # sigma[idx_] = sigma_
584
+ # theta_E[idx_] = theta_E_
585
+ # q[idx_] = q_
586
+ # phi = self.axis_rotation_angle.rvs(size)
587
+ # e1, e2 = phi_q2_ellipticity_hemanta(phi, q)
588
+
589
+ sigma_max = self.velocity_dispersion.info['sigma_max']
590
+
591
+ for i in tqdm(range(size), ncols=100, disable=False):
592
+ zs_ = zs[i]*np.ones(buffer_size)
593
+ zl_ = zl[i]*np.ones(buffer_size)
594
+
595
+ # cross_section_max calculation
596
+ theta_E_max = self.compute_einstein_radii(np.array([sigma_max]), np.array([zl[i]]), np.array([zs[i]]))[0]
597
+ sie_factor=1.
598
+ cross_section_max = sie_factor*np.pi*theta_E_max**2
599
+
600
+ while True:
601
+ # Create a dictionary of the lens parameters; sigma, theta_E, q, phi, e1, e2
602
+ lens_parameters_ = self.sampling_routine_sie_nsl(zl_, zs_, size=buffer_size)
603
+
604
+ # Rejection sample based on the lensing probability, that is, rejection sample wrt theta_E
605
+ lens_parameters_, mask, cross_section_max_ = self.rjs_with_cross_section_sie_feixu(
606
+ lens_parameters_, cross_section_max
607
+ ) # proportional to pi theta_E^2
608
+
609
+ if cross_section_max_>cross_section_max:
610
+ cross_section_max = cross_section_max_
611
+
612
+ if np.sum(mask) > 0:
613
+ break
614
+
615
+ sigma[i] = lens_parameters_["sigma"][0]
616
+ theta_E[i] = lens_parameters_["theta_E"][0]
617
+ q[i] = lens_parameters_["q"][0]
618
+
619
+ # sample additional lens parameters
620
+ # P(gamma|SL), P(gamma1, gamma2|SL)
621
+ gamma = self.density_profile_slope_sl.rvs(size)
622
+ gamma1, gamma2 = self.external_shear_sl.rvs(size)
623
+
624
+ phi = self.axis_rotation_angle.rvs(size)
625
+ e1, e2 = phi_q2_ellipticity_hemanta(phi, q)
558
626
 
559
627
  # Create a dictionary of the lens parameters
560
628
  lens_parameters = {
561
629
  "zl": zl,
562
630
  "zs": zs,
563
631
  "sigma": sigma,
564
- "q": q,
565
632
  "theta_E": theta_E,
633
+ "q": q,
634
+ "phi": phi,
635
+ "e1": e1,
636
+ "e2": e2,
637
+ "gamma": gamma,
638
+ "gamma1": gamma1,
639
+ "gamma2": gamma2,
566
640
  }
567
641
 
568
- # Rejection sample based on the lensing probability, that is, rejection sample wrt theta_E
569
- lens_parameters = self.rejection_sample_sl(
570
- lens_parameters
571
- ) # proportional to pi theta_E^2
572
-
573
- # Add the lensing parameter dictionaries together
574
- lens_parameters = add_dictionaries_together(
575
- lens_parameters, lens_parameters_input
576
- )
577
-
578
- # check the size of the lens parameters
579
- if len(lens_parameters["zl"]) < size:
580
- # Run iteratively until we have the right number of lensing parmaeters
581
- # print("current sampled size", len(lens_parameters["zl"]))
582
- return self.sample_all_routine(
583
- size=size, lens_parameters_input=lens_parameters
584
- )
585
- else:
586
- # Trim dicitionary to right size
587
- lens_parameters = trim_dictionary(lens_parameters, size)
588
-
589
- # Sample the axis rotation angle
590
- lens_parameters["phi"] = self.sample_axis_rotation_angle(size=size)
591
-
592
- # Transform the axis ratio and the angle, to ellipticities e1, e2, using lenstronomy
593
- lens_parameters["e1"], lens_parameters["e2"] = phi_q2_ellipticity(
594
- lens_parameters["phi"], lens_parameters["q"]
595
- )
596
-
597
- # Sample shears
598
- lens_parameters["gamma1"], lens_parameters["gamma2"] = self.sample_shear(
599
- size=size)
600
-
601
- # Sample the spectral index of the mass density distribution
602
- lens_parameters["gamma"] = self.sample_mass_density_spectral_index(
603
- size=size)
642
+ return lens_parameters
643
+
644
+ def sample_all_routine_epl_shear_sl(self, size=1000):
645
+ """
646
+ Function to sample galaxy lens parameters along. EPL shear cross section is used for rejection sampling.
647
+
648
+ Parameters
649
+ ----------
650
+ size : `int`
651
+ number of lens parameters to sample
652
+ lens_parameters_input : `dict`
653
+ dictionary of lens parameters to sample
654
+
655
+ Returns
656
+ -------
657
+ lens_parameters : `dict`
658
+ dictionary of lens parameters and source parameters (lens conditions applied): \n
659
+ zl: lens redshifts \n
660
+ zs: source redshifts, lensed condition applied\n
661
+ sigma: velocity dispersions \n
662
+ q: axis ratios \n
663
+ theta_E: Einstein radii \n
664
+ phi: axis rotation angle \n
665
+ e1: ellipticity component 1 \n
666
+ e2: ellipticity component 2 \n
667
+ gamma1: shear component 1 \n
668
+ gamma2: shear component 2 \n
669
+ gamma: density profile slope distribution \n
670
+
671
+ Examples
672
+ --------
673
+ >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
674
+ >>> lens = LensGalaxyParameterDistribution()
675
+ >>> lens.sample_all_routine_sie(size=1000)
676
+ """
604
677
 
605
- # sample gravitional waves source parameter
606
- param = dict(zs=lens_parameters["zs"])
607
- if samplers_params["source_parameters"]:
608
- param.update(self.sample_gw_parameters(size=size))
609
- gw_param = self.sample_source_parameters(size=size, param=param)
678
+ buffer_size = self.buffer_size
610
679
 
611
- # Add source params strongly lensed to the lens params
612
- lens_parameters.update(gw_param)
680
+ # Sample source redshifts from the source population
681
+ # rejection sampled with optical depth
682
+ zs = self.sample_source_redshift_sl(size)
683
+
684
+ # # Sample lens redshifts
685
+ zl = self.lens_redshift.rvs(size, zs)
686
+
687
+ sigma = np.zeros(size)
688
+ theta_E = np.zeros(size)
689
+ q = np.zeros(size)
690
+ phi = np.zeros(size)
691
+ gamma1 = np.zeros(size)
692
+ gamma2 = np.zeros(size)
693
+ gamma = np.zeros(size)
694
+
695
+ sigma_max = self.velocity_dispersion.info['sigma_max']
696
+
697
+ # this will take some time
698
+ for i in tqdm(range(size), ncols=100, disable=False):
699
+ zs_ = zs[i]*np.ones(buffer_size)
700
+ zl_ = zl[i]*np.ones(buffer_size)
701
+
702
+ # cross_section_max calculation
703
+ theta_E_max = self.compute_einstein_radii(np.array([sigma_max]), np.array([zl[i]]), np.array([zs[i]]))[0]
704
+ epl_factor=5.
705
+ cross_section_max = epl_factor*np.pi*theta_E_max**2
706
+
707
+ while True:
708
+ # Create a dictionary of the lens parameters, gamma, gamma1, gamma2, sigma, theta_E, q, phi, e1, e2
709
+ lens_parameters_ = self.sampling_routine_epl_shear_nsl(zl_, zs_, size=buffer_size)
710
+
711
+ # Rejection sample based on the lensing probability, that is, rejection sample wrt theta_E
712
+ lens_parameters_, mask, cross_section_max_ = self.rejection_sample_sl(
713
+ lens_parameters_, cross_section_max
714
+ ) # proportional to pi theta_E^2
715
+
716
+ if cross_section_max_>cross_section_max:
717
+ cross_section_max = cross_section_max_
718
+
719
+ # check the size of the lens parameters
720
+ if np.sum(mask) > 0:
721
+ break
722
+
723
+ sigma[i] = lens_parameters_["sigma"][0]
724
+ theta_E[i] = lens_parameters_["theta_E"][0]
725
+ q[i] = lens_parameters_["q"][0]
726
+ phi[i] = lens_parameters_["phi"][0]
727
+ gamma[i] = lens_parameters_["gamma"][0]
728
+ gamma1[i] = lens_parameters_["gamma1"][0]
729
+ gamma2[i] = lens_parameters_["gamma2"][0]
730
+ e1, e2 = phi_q2_ellipticity_hemanta(phi, q)
613
731
 
614
- return lens_parameters
732
+ # Create a dictionary of the lens parameters
733
+ lens_parameters = {
734
+ "zl": zl,
735
+ "zs": zs,
736
+ "sigma": sigma,
737
+ "theta_E": theta_E,
738
+ "q": q,
739
+ "phi": phi,
740
+ "e1": e1,
741
+ "e2": e2,
742
+ "gamma": gamma,
743
+ "gamma1": gamma1,
744
+ "gamma2": gamma2,
745
+ }
615
746
 
616
- def strongly_lensed_source_redshifts(self, size=1000):
747
+ return lens_parameters
748
+
749
+ def sampling_routine_sis_nsl(self, zl, zs, size=1000):
617
750
  """
618
- Function to sample source redshifts and other parameters, conditioned on the source being strongly lensed.
751
+ Function to sample SIS lens related parameters.
619
752
 
620
753
  Parameters
621
754
  ----------
755
+ zl : `float`
756
+ lens redshifts
757
+ zs : `float`
758
+ source redshifts
622
759
  size : `int`
623
760
  number of lens parameters to sample
624
761
 
625
762
  Returns
626
763
  -------
627
- redshifts : `float`
628
- source redshifts conditioned on the source being strongly lensed
629
-
630
- Examples
631
- --------
632
- >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
633
- >>> lens = LensGalaxyParameterDistribution()
634
- >>> lens.strongly_lensed_source_redshifts(size=1000)
635
- """
636
-
637
- z_max = self.z_max
638
-
639
- def zs_function(zs_sl):
640
- # get zs
641
- # self.sample_source_redshifts from CBCSourceRedshiftDistribution class
642
- zs = self.sample_zs(size) # this function is from CompactBinaryPopulation class
643
- # put strong lensing condition with optical depth
644
- tau = self.strong_lensing_optical_depth(zs)
645
- tau_max = self.strong_lensing_optical_depth(np.array([z_max]))[0] # tau increases with z
646
- r = np.random.uniform(0, tau_max, size=len(zs))
647
- # Add the strongly lensed source redshifts to the list
648
- # pick strongly lensed sources
649
- zs_sl += list(zs[r < tau]) # list concatenation
650
-
651
- # Check if the zs_sl are larger than requested size
652
- if len(zs_sl) >= size:
653
- # Trim list to right size
654
- zs_sl = zs_sl[:size]
655
- return zs_sl
656
- else:
657
- # Run iteratively until we have the right number of lensing parmaeters
658
- return zs_function(zs_sl)
659
-
660
- zs_sl = []
661
-
662
- return np.array(zs_function(zs_sl))
663
-
664
- def source_parameters(self, size, get_attribute=False, param=None):
764
+ lens_parameters : `dict`
765
+ dictionary of sampled lens parameters.
766
+ keys: sigma, theta_E
665
767
  """
666
- Function to sample gw source parameters
667
-
668
- Parameters
669
- ----------
670
- size : `int`
671
- Number of samples to draw
672
- param : `dict`
673
- Allows to pass in parameters as dict.
674
- param =
768
+ try:
769
+ sigma = self.velocity_dispersion.rvs(size, zl)
770
+ except:
771
+ sigma = self.velocity_dispersion.rvs(size)
675
772
 
676
- Returns
677
- ----------
678
- source_parameters : `dict`
679
- Dictionary of source parameters
680
- source_parameters.keys() = ['mass_1', 'mass_2', 'mass_1_source', 'mass_2_source', 'zs', 'luminosity_distance', 'inclination', 'polarization_angle', 'phase', 'geocent_time', 'ra', 'dec', 'a_1', 'a_2', 'tilt_1', 'tilt_2', 'phi_12', 'phi_jl']
773
+ # Compute the Einstein radii
774
+ theta_E = self.compute_einstein_radii(sigma, zl, zs)
681
775
 
682
- Examples
683
- --------
684
- >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
685
- >>> lens = LensGalaxyParameterDistribution()
686
- >>> lens.source_parameters(size=1000)
687
- """
776
+ # Create a dictionary of the lens parameters
777
+ lens_parameters = {
778
+ "zs": zs,
779
+ "zl": zl,
780
+ "sigma": sigma,
781
+ "theta_E": theta_E,
782
+ }
688
783
 
689
- if get_attribute:
690
- return lambda size: self.sample_gw_parameters(size=size, param=param)
691
- else:
692
- # sample gravitional waves source parameter
693
- return self.sample_gw_parameters(size=size, param=param)
784
+ return lens_parameters
694
785
 
695
- def lens_redshift_SDSS_catalogue(self, zs, get_attribute=False, param=None):
786
+ def sampling_routine_sie_nsl(self, zl, zs, size=1000):
696
787
  """
697
- Function to sample lens redshifts, conditioned on the lens being strongly lensed
788
+ Function to sample SIE lens related parameters.
698
789
 
699
790
  Parameters
700
791
  ----------
792
+ zl : `float`
793
+ lens redshifts
701
794
  zs : `float`
702
795
  source redshifts
703
- get_attribute : `bool`
704
- If True, returns a function that can be called with zs as input
796
+ size : `int`
797
+ number of lens parameters to sample
705
798
 
706
799
  Returns
707
800
  -------
708
- zl : `float`
709
- lens redshifts
710
-
711
- Examples
712
- --------
713
- >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
714
- >>> lens = LensGalaxyParameterDistribution()
715
- >>> lens.lens_redshift_SDSS_catalogue(zs=1.0)
716
- """
717
-
718
- splineDc = self.splineDc # spline coefficients for the comoving distance and redshifts
719
- splineDcInv = self.splineDcInv # spline coefficients for the redshifts and comoving distance
720
- u = np.linspace(0, 1, 500)
721
- cdf = (10 * u**3 - 15 * u**4 + 6 * u**5) # See the integral of Eq. A7 of https://arxiv.org/pdf/1807.07062.pdf (cdf)
722
- zs = np.array([zs]).reshape(-1)
723
-
724
- # lens redshifts
725
- #return self.Dc_to_z(lens_galaxy_Dc)
726
- if get_attribute:
727
- return njit(lambda zs: lens_redshift_SDSS_catalogue(zs, splineDc, splineDcInv, u, cdf))
728
- else:
729
- return lens_redshift_SDSS_catalogue(zs, splineDc, splineDcInv, u, cdf)
730
-
731
- def axis_rotation_angle_uniform(
732
- self, size=1000, phi_min=0.0, phi_max=2 * np.pi, get_attribute=False,param=None
733
- ):
801
+ lens_parameters : `dict`
802
+ dictionary of sampled lens parameters.
803
+ keys: sigma, q, phi
734
804
  """
735
- Function to sample the axis rotation angle of the elliptical lens galaxy from a uniform distribution.
736
805
 
737
- Parameters
738
- ----------
739
- size : `int`
740
- number of lens parameters to sample
741
- phi_min : `float`
742
- minimum axis rotation angle of the elliptical lens galaxy
743
- phi_max : `float`
744
- maximum axis rotation angle of the elliptical lens galaxy
745
- get_attribute : `bool`
746
- If True, returns a function that can be called with size as input
747
- param : `dict`
748
- Allows to pass in above parameters as dict.
749
- e.g. param = dict(phi_min=0.0, phi_max=2 * np.pi)
806
+ lens_parameters = self.sampling_routine_sis_nsl(zl, zs, size=size)
750
807
 
751
- Returns
752
- -------
753
- phi : `float`
754
- axis rotation angle of the elliptical lens galaxy
808
+ # Sample axis ratios
809
+ try:
810
+ q = self.axis_ratio.rvs(size, lens_parameters["sigma"])
811
+ except:
812
+ q = self.axis_ratio.rvs(size)
755
813
 
756
- Examples
757
- --------
758
- >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
759
- >>> lens = LensGalaxyParameterDistribution()
760
- >>> lens.axis_rotation_angle_uniform(size=1000)
761
- """
814
+ # Sample the axis rotation angle
815
+ phi = self.axis_rotation_angle.rvs(size)
762
816
 
763
- if param:
764
- phi_min = param["phi_min"]
765
- phi_max = param["phi_max"]
817
+ # Transform the axis ratio and the angle, to ellipticities e1, e2, using lenstronomy
818
+ # e1, e2 = phi_q2_ellipticity_hemanta(phi, q)
766
819
 
767
- if get_attribute:
768
- return njit(lambda size: np.random.uniform(phi_min, phi_max, size=size))
769
- else:
770
- # Draw the angles from a uniform distribution
771
- return np.random.uniform(phi_min, phi_max, size=size)
820
+ # Add the lensing parameter dictionaries together
821
+ lens_parameters["q"] = q
822
+ lens_parameters["phi"] = phi
823
+ # lens_parameters["e1"] = e1
824
+ # lens_parameters["e2"] = e2
772
825
 
773
- def shear_norm(self, size, scale=0.05, get_attribute=False, param=None):
826
+ return lens_parameters
827
+
828
+ def sampling_routine_epl_shear_nsl(self, zl, zs, size=1000):
774
829
  """
775
- Function to sample the elliptical lens galaxy shear from a normal distribution
830
+ Function to sample EPL and shear related parameters.
776
831
 
777
832
  Parameters
778
833
  ----------
834
+ zl : `float`
835
+ lens redshifts
836
+ zs : `float`
837
+ source redshifts
779
838
  size : `int`
780
839
  number of lens parameters to sample
781
- scale : `float`
782
- standard deviation of the normal distribution
783
- get_attribute : `bool`
784
- If True, returns a function that can be called with size as input
785
- param : `dict`
786
- Allows to pass in above parameters as dict.
787
- e.g. param = dict(scale=0.05)
788
840
 
789
841
  Returns
790
842
  -------
791
- gamma_1 : `float`
792
- shear component in the x-direction
793
- gamma_2 : `float`
794
- shear component in the y-direction
795
-
796
- Examples
797
- --------
798
- >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
799
- >>> lens = LensGalaxyParameterDistribution()
800
- >>> gamma_1, gamma_2 = lens.shear_norm(size=1000)
843
+ lens_parameters : `dict`
844
+ dictionary of sampled lens parameters.
845
+ keys: sigma, q, phi, gamma, gamma1, gamma2
801
846
  """
802
847
 
803
- if param:
804
- scale = param["scale"]
848
+ lens_parameters = self.sampling_routine_sie_nsl(zl, zs, size=size)
805
849
 
806
- if get_attribute:
807
- return njit(lambda size: np.random.normal(loc=0, scale=scale,size=(2,size)))
808
- else:
809
- # Draw an external shear from a normal distribution
810
- return np.random.normal(loc=0., scale=scale,size=(2,size))
850
+ # Sample the density profile slope distribution
851
+ gamma = self.density_profile_slope(size)
811
852
 
812
- def mass_density_spectral_index_normal(
813
- self, size=1000, mean=2.0, std=0.2, get_attribute=False, param=None
814
- ):
853
+ # Sample shears
854
+ gamma1, gamma2 = self.external_shear.rvs(size)
855
+
856
+ # Add the lensing parameter dictionaries together
857
+ lens_parameters["gamma"] = gamma
858
+ lens_parameters["gamma1"] = gamma1
859
+ lens_parameters["gamma2"] = gamma2
860
+
861
+ return lens_parameters
862
+
863
+ def strongly_lensed_source_redshifts(self, size=1000):
815
864
  """
816
- Function to sample the lens galaxy spectral index of the mass density profile from a normal distribution
865
+ Function to sample source redshifts, conditioned on the source being strongly lensed.
817
866
 
818
867
  Parameters
819
868
  ----------
820
869
  size : `int`
821
870
  number of lens parameters to sample
822
- mean : `float`
823
- mean of the normal distribution
824
- std : `float`
825
- standard deviation of the normal distribution
826
- param : `dict`
827
- Allows to pass in above parameters as dict.
828
- e.g. param = dict(mean=2.0, std=0.2)
829
871
 
830
872
  Returns
831
873
  -------
832
- gamma : `float`
833
- spectral index of the density profile
874
+ redshifts : `float`
875
+ source redshifts conditioned on the source being strongly lensed
834
876
 
835
877
  Examples
836
878
  --------
837
879
  >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
838
880
  >>> lens = LensGalaxyParameterDistribution()
839
- >>> lens.mass_density_spectral_index_normal(size=1000)
840
- """
841
-
842
- if param:
843
- mean = param["mean"]
844
- std = param["std"]
845
-
846
- if get_attribute:
847
- return njit(lambda size: np.random.normal(loc=mean, scale=std, size=size))
848
- else:
849
- # Draw the spectral index from a normal distribution
850
- return np.random.normal(loc=mean, scale=std, size=size)
851
-
852
- def compute_einstein_radii(self, sigma, zl, zs):
881
+ >>> lens.strongly_lensed_source_redshifts(size=1000)
853
882
  """
854
- Function to compute the Einstein radii of the lens galaxies
855
883
 
856
- Parameters
857
- ----------
858
- sigma : `float`
859
- velocity dispersion of the lens galaxy
860
- zl : `float`
861
- lens redshifts
862
- zs : `float`
863
- source redshifts
864
-
865
- Returns
866
- -------
867
- theta_E : `float`
868
- Einstein radii of the lens galaxies
884
+ z_max = self.z_max
869
885
 
870
- Examples
871
- --------
872
- >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
873
- >>> lens = LensGalaxyParameterDistribution()
874
- >>> sigma = 200.0
875
- >>> zl = 0.5
876
- >>> zs = 1.0
877
- >>> lens.compute_einstein_radii(sigma, zl, zs)
878
- """
886
+ def zs_function(zs_sl):
887
+ # get zs
888
+ # self.sample_source_redshifts from CBCSourceRedshiftDistribution class
889
+ zs = self.zs(size) # this function is from CBCSourceParameterDistribution class
890
+ # put strong lensing condition with optical depth
891
+ tau = self.optical_depth(zs)
892
+ tau_max = self.optical_depth(np.array([z_max]))[0] # tau increases with z
893
+ r = np.random.uniform(0, tau_max, size=len(zs))
894
+ # Add the strongly lensed source redshifts to the list
895
+ # pick strongly lensed sources
896
+ zs_sl += list(zs[r < tau]) # list concatenation
879
897
 
880
- # Compute the angular diameter distances
881
- Ds = self.angular_diameter_distance(zs)
882
- Dls = self.angular_diameter_distance_z1z2(zl, zs)
883
- # Compute the Einstein radii
884
- theta_E = (
885
- 4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / (Ds)
886
- ) # Note: km/s for sigma; Dls, Ds are in Mpc
898
+ # Check if the zs_sl are larger than requested size
899
+ if len(zs_sl) >= size:
900
+ # Trim list to right size
901
+ zs_sl = zs_sl[:size]
902
+ return zs_sl
903
+ else:
904
+ # Run iteratively until we have the right number of lensing parmaeters
905
+ return zs_function(zs_sl)
887
906
 
888
- return theta_E
907
+ zs_sl = []
889
908
 
890
- def rjs_with_cross_section_SIS(self, param_dict):
909
+ return np.array(zs_function(zs_sl))
910
+
911
+ def rjs_with_cross_section_sis(self, param_dict, cross_section_max=0.):
891
912
  """
892
- Function to conduct rejection sampling wrt einstein radius
913
+ Function to conduct rejection sampling wrt einstein radius
893
914
 
894
- Parameters
895
- ----------
896
- param_dict : `dict`
897
- dictionary of lens parameters and source parameters
915
+ Parameters
916
+ ----------
917
+ param_dict : `dict`
918
+ dictionary of lens parameters and source parameters
898
919
 
899
- Returns
900
- -------
901
- lens_params : `dict`
902
- dictionary of lens parameters after rejection sampling
920
+ Returns
921
+ -------
922
+ lens_params : `dict`
923
+ dictionary of lens parameters after rejection sampling
903
924
  """
904
925
 
905
926
  theta_E = param_dict["theta_E"]
906
927
  size = len(theta_E)
907
- theta_E_max = np.max(theta_E) # maximum einstein radius
908
- u = np.random.uniform(0, theta_E_max**2, size=size)
909
- mask = u < theta_E**2
928
+ cross_section = np.pi * theta_E**2
929
+
930
+ max_ = np.max(cross_section)
931
+ if cross_section_max>max_:
932
+ max_ = cross_section_max
933
+
934
+ mask = np.random.uniform(size=size) < (cross_section / max_)
910
935
 
911
936
  # return the dictionary with the mask applied
912
- return {key: val[mask] for key, val in param_dict.items()}
937
+ dict_ = {key: val[mask] for key, val in param_dict.items()}
938
+ dict_["cross_section"] = cross_section[mask]
939
+ return dict_, mask, max_
913
940
 
914
- def rjs_with_cross_section_SIE(self, param_dict):
941
+ def rjs_with_cross_section_sie_feixu(self, param_dict, cross_section_max=0.):
915
942
  """
916
943
  Function to conduct rejection sampling wrt cross_section
917
944
 
@@ -926,260 +953,165 @@ class LensGalaxyParameterDistribution(CBCSourceParameterDistribution, ImagePrope
926
953
  dictionary of lens parameters after rejection sampling
927
954
  """
928
955
 
956
+ #print("rjs_with_cross_section_sie_feixu")
929
957
  theta_E = param_dict["theta_E"]
930
958
  q = param_dict["q"]
931
- phi_cut = phi_cut_SIE(q)
932
959
  size = len(theta_E)
933
- cross_section = theta_E**2 * phi_cut
934
- max_ = np.max(cross_section) # maximum einstein radius
960
+ cross_section = np.pi * theta_E**2 * phi_cut_SIE(q)
961
+
962
+ max_ = np.max(cross_section)
963
+ if cross_section_max>max_:
964
+ max_ = cross_section_max
965
+
935
966
  u = np.random.uniform(0, max_, size=size)
936
967
  mask = u < cross_section
937
968
 
938
969
  # return the dictionary with the mask applied
939
- return {key: val[mask] for key, val in param_dict.items()}
940
-
941
- @property
942
- def sample_source_redshift_sl(self):
943
- """
944
- Function to sample source redshifts conditioned on the source being strongly lensed
945
-
946
- Parameters
947
- ----------
948
- size : `int`
949
- number samples to draw
950
-
951
- Returns
952
- -------
953
- zs : `numpy.ndarray` (1D array of floats)
954
- source redshifts conditioned on the source being strongly lensed
955
-
956
- Examples
957
- --------
958
- >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
959
- >>> lens = LensGalaxyParameterDistribution()
960
- >>> lens.sample_source_redshift_sl(size=1000)
961
- """
962
-
963
- return self._sample_source_redshift_sl
964
-
965
- @sample_source_redshift_sl.setter
966
- def sample_source_redshift_sl(self, prior):
967
- try:
968
- self._sample_source_redshift_sl = getattr(self, prior)
969
- except:
970
- self._sample_source_redshift_sl = prior
971
-
972
- @property
973
- def sample_source_parameters(self):
974
- """
975
- Function to sample source parameters conditioned on the source being strongly lensed
976
-
977
- Parameters
978
- ----------
979
- size : `int`
980
- number of lens parameters to sample
981
-
982
- Returns
983
- -------
984
- source_parameters : `dict`
985
- dictionary of source parameters conditioned on the source being strongly lensed
986
- """
987
- return self._sample_source_parameters
970
+ dict_ = {key: val[mask] for key, val in param_dict.items()}
971
+ dict_["cross_section"] = cross_section[mask]
972
+ return dict_, mask, max_
988
973
 
989
- @sample_source_parameters.setter
990
- def sample_source_parameters(self, prior):
991
- try:
992
- args = self.lens_param_samplers_params["source_parameters"]
993
- self._sample_source_parameters = getattr(self, prior)(size=None, get_attribute=True, param=args)
994
- except:
995
- self._sample_source_parameters = prior
996
-
997
- @property
998
- def sample_lens_redshift(self):
999
- """
1000
- Function to sample lens redshifts, conditioned on the lens being strongly lensed
1001
-
1002
- Parameters
1003
- ----------
1004
- zs : `numpy.ndarray` (1D array of floats)
1005
- source redshifts
1006
-
1007
- Returns
1008
- -------
1009
- zl : `numpy.ndarray` (1D array of floats)
1010
- lens redshifts corresponding to the source redshifts
1011
-
1012
- Examples
1013
- --------
1014
- >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
1015
- >>> lens = LensGalaxyParameterDistribution()
1016
- >>> zs = lens.sample_source_redshift_sl(size=1000)
1017
- >>> lens.sample_lens_redshift(zs=zs)
1018
- """
1019
-
1020
- return self._sample_lens_redshift
1021
-
1022
- @sample_lens_redshift.setter
1023
- def sample_lens_redshift(self, prior):
1024
- try:
1025
- args = self.lens_param_samplers_params["lens_redshift"]
1026
- self._sample_lens_redshift = getattr(self, prior)(zs=None, get_attribute=True, param=args)
1027
- except:
1028
- self._sample_lens_redshift = prior
1029
-
1030
- @property
1031
- def sample_axis_rotation_angle(self):
974
+ def rjs_with_cross_section(self, param_dict, cross_section_max=0.):
1032
975
  """
1033
- Function to sample the axis rotation angle of the elliptical lens galaxy from a uniform distribution
976
+ Function to conduct rejection sampling wrt cross_section of EPL+Shear lens
1034
977
 
1035
- Parameters
1036
- ----------
1037
- size : `int`
1038
- number of lens parameters to sample
1039
-
1040
- Returns
1041
- -------
1042
- phi : `float`
1043
- axis rotation angle of the elliptical lens galaxy
978
+ Parameters
979
+ ----------
980
+ param_dict : `dict`
981
+ dictionary of lens parameters and source parameters
1044
982
 
1045
- Examples
1046
- --------
1047
- >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
1048
- >>> lens = LensGalaxyParameterDistribution()
1049
- >>> lens.sample_axis_rotation_angle(size=1000)
983
+ Returns
984
+ -------
985
+ lens_params : `dict`
986
+ dictionary of lens parameters after rejection sampling
1050
987
  """
1051
- return self._sample_axis_rotation_angle
1052
988
 
1053
- @sample_axis_rotation_angle.setter
1054
- def sample_axis_rotation_angle(self, prior):
1055
- try:
1056
- args = self.lens_param_samplers_params["axis_rotation_angle"]
1057
- self._sample_axis_rotation_angle = getattr(self, prior)(size=None, get_attribute=True, param=args)
1058
- except:
1059
- self._sample_axis_rotation_angle = prior
989
+ theta_E_cut = 2.9243287409459857e-08 # this is numerically found
1060
990
 
1061
- @property
1062
- def sample_shear(self):
1063
- """
1064
- Function to sample the elliptical lens galaxy shear from a normal distribution
1065
-
1066
- Parameters
1067
- ----------
1068
- size : `int`
1069
- number of lens parameters to sample
991
+ # Pre-filter param_dict directly
992
+ size_original = len(param_dict["theta_E"])
993
+ idx_ = param_dict["theta_E"] > theta_E_cut
994
+ param_dict = {key: val[idx_]
995
+ for key, val in param_dict.items()}
1070
996
 
1071
- Returns
1072
- -------
1073
- gamma_1 : `float`
1074
- shear component in the x-direction
1075
- gamma_2 : `float`
1076
- shear component in the y-direction
1077
-
1078
- Examples
1079
- --------
1080
- >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
1081
- >>> lens = LensGalaxyParameterDistribution()
1082
- >>> gamma_1, gamma_2 = lens.shear_norm(size=1000)
1083
- """
997
+ size = len(param_dict["theta_E"]) # Update size after filtering
998
+ theta_E = param_dict["theta_E"]
999
+ e1, e2 = phi_q2_ellipticity_hemanta(param_dict["phi"], param_dict["q"])
1000
+ gamma = param_dict["gamma"]
1001
+ gamma1 = param_dict["gamma1"]
1002
+ gamma2 = param_dict["gamma2"]
1084
1003
 
1085
- return self._sample_shear
1004
+ cross_section = self.cross_section(theta_E, e1, e2, gamma, gamma1, gamma2)
1086
1005
 
1087
- @sample_shear.setter
1088
- def sample_shear(self, prior):
1089
- try:
1090
- args = self.lens_param_samplers_params["shear"]
1091
- self._sample_shear = getattr(self, prior)(size=None, get_attribute=True, param=args)
1092
- except:
1093
- self._sample_shear = prior
1094
-
1095
- @property
1096
- def sample_mass_density_spectral_index(self):
1097
- """
1098
- Function to sample the lens galaxy spectral index of the mass density profile from a normal distribution
1006
+ max_ = np.max(cross_section)
1007
+ if cross_section_max>max_:
1008
+ max_ = cross_section_max
1099
1009
 
1100
- Parameters
1101
- ----------
1102
- size : `int`
1103
- number of lens parameters to sample
1104
-
1105
- Returns
1106
- -------
1107
- gamma : `float`
1108
- spectral index of the density profile
1109
-
1110
- Examples
1111
- --------
1112
- >>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
1113
- >>> lens = LensGalaxyParameterDistribution()
1114
- >>> lens.mass_density_spectral_index_normal(size=1000)
1115
- """
1010
+ u = np.random.uniform(0, max_, size=size)
1011
+ mask = u < cross_section
1116
1012
 
1117
- return self._sample_mass_density_spectral_index
1013
+ # return the dictionary with the mask applied
1014
+ dict_ = {key: val[mask] for key, val in param_dict.items()}
1015
+ dict_["cross_section"] = cross_section[mask]
1118
1016
 
1119
- @sample_mass_density_spectral_index.setter
1120
- def sample_mass_density_spectral_index(self, prior):
1121
- try:
1122
- args = self.lens_param_samplers_params["mass_density_spectral_index"]
1123
- self._sample_mass_density_spectral_index = getattr(self, prior)(size=None, get_attribute=True, param=args)
1124
- except:
1125
- self._sample_mass_density_spectral_index = prior
1017
+ mask_complete = np.zeros(size_original, dtype=bool)
1018
+ mask_complete[idx_] = mask
1019
+ return dict_, mask_complete, max_
1126
1020
 
1127
- @property
1128
- def sample_source_parameters(self):
1021
+
1022
+ def rjs_with_cross_section_mp(self, param_dict, cross_section_max=0.):
1129
1023
  """
1130
- Function to sample source parameters conditioned on the source being strongly lensed
1024
+ Function to conduct rejection sampling wrt cross_section, multiprocessing
1131
1025
 
1132
- Parameters
1133
- ----------
1134
- size : `int`
1135
- number of lens parameters to sample
1026
+ Parameters
1027
+ ----------
1028
+ param_dict : `dict`
1029
+ dictionary of lens parameters and source parameters
1136
1030
 
1137
- Returns
1138
- -------
1139
- source_parameters : `dict`
1140
- dictionary of source parameters conditioned on the source being strongly lensed
1031
+ Returns
1032
+ -------
1033
+ lens_params : `dict`
1034
+ dictionary of lens parameters after rejection sampling
1141
1035
  """
1142
- return self._sample_source_parameters
1143
-
1144
- @sample_source_parameters.setter
1145
- def sample_source_parameters(self, prior):
1146
- try:
1147
- self._sample_source_parameters = getattr(self, prior)
1148
- except:
1149
- self._sample_source_parameters = prior
1150
1036
 
1037
+ theta_E_cut = 1e-09 # this is numerically found
1038
+ theta_E = param_dict["theta_E"]
1039
+ size_original = len(theta_E)
1151
1040
 
1152
- @property
1153
- def available_lens_prior_list_and_its_params(self):
1154
- """
1155
- Dictionary with list all the available priors and it's corresponding parameters. This is an immutable instance attribute.
1156
- """
1041
+ # Pre-filter param_dict directly
1157
1042
 
1158
- self._available_lens_prior_list_and_its_params = dict(
1159
- source_redshift_sl=dict(strongly_lensed_source_redshifts=None),
1160
- lens_redshift=dict(lens_redshift_SDSS_catalogue=None),
1161
- velocity_dispersion=self.available_velocity_dispersion_list_and_its_params,
1162
- axis_ratio=self.available_axis_ratio_list_and_its_params,
1163
- axis_rotation_angle=dict(axis_rotation_angle_uniform=dict(phi_min=0.0, phi_max=2 * np.pi)),
1164
- shear=dict(shear_norm=dict(scale=0.05)),
1165
- mass_density_spectral_index=dict(mass_density_spectral_index_normal=dict(mean=2.0, std=0.2)),
1166
- source_parameters=dict(sample_gw_parameters=None),
1167
- )
1168
-
1169
- return self._available_lens_prior_list_and_its_params
1170
-
1171
- @property
1172
- def available_lens_functions(self):
1173
- """
1174
- Dictionary with list all the available lens functions. This is an immutable instance attribute.
1175
- """
1176
-
1177
- self._available_lens_functions = dict(
1178
- strong_lensing_condition=["rjs_with_cross_section_SIE", "rjs_with_cross_section_SIS"],
1179
- optical_depth=["SIS", "optical_depth_SIS_haris","optical_depth_SIS_hemanta", "SIE", "optical_depth_SIE_hemanta"],
1180
- param_sampler_type=["sample_all_routine"],
1181
- )
1182
-
1183
- return self._available_lens_functions
1184
-
1043
+ idx_ = theta_E > theta_E_cut
1044
+ if np.sum(idx_) > 0:
1045
+
1046
+ param_dict = {key: val[idx_]
1047
+ for key, val in param_dict.items()}
1048
+ size = np.sum(idx_)
1049
+
1050
+ e1, e2 = phi_q2_ellipticity_hemanta(param_dict["phi"], param_dict["q"])
1051
+
1052
+ # Combine parameters into a single array for multiprocessing
1053
+ params = np.array([
1054
+ param_dict["theta_E"],
1055
+ e1,
1056
+ e2,
1057
+ param_dict["gamma"],
1058
+ param_dict["gamma1"],
1059
+ param_dict["gamma2"],
1060
+ np.arange(size, dtype=int)
1061
+ ]).T
1062
+
1063
+ cross_section = np.zeros(size) # Directly create filtered array
1064
+ # with Pool(processes=self.npool) as pool:
1065
+ # for result in tqdm(pool.imap_unordered(cross_section_mp, params), total=size,
1066
+ # ncols=100): # Remove total from tqdm
1067
+ # idx_, tau_ = result
1068
+ # cross_section[idx_] = tau_
1069
+ # without tqdm. Use map
1070
+ # Use multiprocessing to calculate cross-section values
1071
+ with Pool(processes=self.npool) as pool:
1072
+ for idx, tau in pool.imap_unordered(cross_section_mp, params):
1073
+ cross_section[idx] = tau
1074
+
1075
+ # Perform rejection sampling
1076
+ max_ = np.max(cross_section)
1077
+
1078
+ if cross_section_max>max_:
1079
+ max_ = cross_section_max
1080
+ random_values = np.random.uniform(0, max_, size=size)
1081
+ mask = random_values < cross_section
1082
+ else:
1083
+ print("No valid values found")
1084
+ mask = np.zeros(size, dtype=bool)
1085
+
1086
+ # Return the dictionary with the mask applied
1087
+ dict_ = {key: val[mask] for key, val in param_dict.items()}
1088
+ dict_["cross_section"] = cross_section[mask]
1089
+
1090
+ mask_complete = np.zeros(size_original, dtype=bool)
1091
+ mask_complete[idx_] = mask
1092
+ return dict_, mask_complete, max_
1093
+
1094
+ # @property
1095
+ # def sample_source_parameters(self):
1096
+ # """
1097
+ # Function to sample source parameters conditioned on the source being strongly lensed
1098
+
1099
+ # Parameters
1100
+ # ----------
1101
+ # size : `int`
1102
+ # number of lens parameters to sample
1103
+
1104
+ # Returns
1105
+ # -------
1106
+ # source_parameters : `dict`
1107
+ # dictionary of source parameters conditioned on the source being strongly lensed
1108
+ # """
1109
+ # return self._sample_source_parameters
1110
+
1111
+ # @sample_source_parameters.setter
1112
+ # def sample_source_parameters(self, prior):
1113
+ # try:
1114
+ # self._sample_source_parameters = getattr(self, prior)
1115
+ # except:
1116
+ # self._sample_source_parameters = prior
1185
1117