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.
- ler/__init__.py +26 -26
- ler/gw_source_population/__init__.py +1 -0
- ler/gw_source_population/cbc_source_parameter_distribution.py +1076 -818
- ler/gw_source_population/cbc_source_redshift_distribution.py +619 -295
- ler/gw_source_population/jit_functions.py +484 -9
- ler/gw_source_population/sfr_with_time_delay.py +107 -0
- ler/image_properties/image_properties.py +44 -13
- ler/image_properties/multiprocessing_routine.py +5 -209
- ler/lens_galaxy_population/__init__.py +2 -0
- ler/lens_galaxy_population/epl_shear_cross_section.py +0 -0
- ler/lens_galaxy_population/jit_functions.py +101 -9
- ler/lens_galaxy_population/lens_galaxy_parameter_distribution.py +817 -885
- ler/lens_galaxy_population/lens_param_data/density_profile_slope_sl.txt +5000 -0
- ler/lens_galaxy_population/lens_param_data/external_shear_sl.txt +2 -0
- ler/lens_galaxy_population/lens_param_data/number_density_zl_zs.txt +48 -0
- ler/lens_galaxy_population/lens_param_data/optical_depth_epl_shear_vd_ewoud.txt +48 -0
- ler/lens_galaxy_population/mp copy.py +554 -0
- ler/lens_galaxy_population/mp.py +736 -138
- ler/lens_galaxy_population/optical_depth.py +2248 -616
- ler/rates/__init__.py +1 -2
- ler/rates/gwrates.py +129 -75
- ler/rates/ler.py +257 -116
- ler/utils/__init__.py +2 -0
- ler/utils/function_interpolation.py +322 -0
- ler/utils/gwsnr_training_data_generator.py +233 -0
- ler/utils/plots.py +1 -1
- ler/utils/test.py +1078 -0
- ler/utils/utils.py +553 -125
- {ler-0.4.1.dist-info → ler-0.4.3.dist-info}/METADATA +22 -9
- ler-0.4.3.dist-info/RECORD +34 -0
- {ler-0.4.1.dist-info → ler-0.4.3.dist-info}/WHEEL +1 -1
- ler/rates/ler copy.py +0 -2097
- ler-0.4.1.dist-info/RECORD +0 -25
- {ler-0.4.1.dist-info → ler-0.4.3.dist-info/licenses}/LICENSE +0 -0
- {ler-0.4.1.dist-info → ler-0.4.3.dist-info}/top_level.txt +0 -0
|
@@ -1,485 +1,1354 @@
|
|
|
1
|
+
import os
|
|
1
2
|
from numba import njit
|
|
2
3
|
from multiprocessing import Pool
|
|
3
4
|
import numpy as np
|
|
4
5
|
from scipy.integrate import quad
|
|
5
|
-
from scipy.stats import gengamma
|
|
6
|
+
from scipy.stats import gengamma, gaussian_kde
|
|
7
|
+
from scipy.interpolate import CubicSpline
|
|
6
8
|
from astropy.cosmology import LambdaCDM
|
|
7
|
-
from
|
|
8
|
-
from .
|
|
9
|
+
from tqdm import tqdm
|
|
10
|
+
from lenstronomy.LensModel.Solver.epl_shear_solver import caustics_epl_shear
|
|
11
|
+
from shapely.geometry import Polygon
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
from ..utils import cubic_spline_interpolator, inverse_transform_sampler, cubic_spline_interpolator2d_array, save_pickle, interpolator_pickle_path, FunctionConditioning, inverse_transform_sampler2d, pdf_cubic_spline_interpolator2d_array, normal_pdf, normal_pdf_2d, load_txt_from_module
|
|
15
|
+
|
|
16
|
+
from .jit_functions import phi_cut_SIE, phi, phi_loc_bernardi, phi_q2_ellipticity_hemanta, lens_redshift_SDSS_catalogue_sis, axis_ratio_rayleigh_pdf
|
|
9
17
|
|
|
10
18
|
class OpticalDepth():
|
|
11
19
|
"""
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
45
|
-
>>> od = OpticalDepth()
|
|
46
|
-
>>> print(od.strong_lensing_optical_depth(0.5))
|
|
47
|
-
|
|
48
|
-
Instance Attributes
|
|
49
|
-
-------------------
|
|
50
|
-
OpticalDepth class has the following attributes:
|
|
51
|
-
+-------------------------------------+----------------------------------+
|
|
52
|
-
| Atrributes | Type |
|
|
53
|
-
+=====================================+==================================+
|
|
54
|
-
|:attr:`~npool` | `int` |
|
|
55
|
-
+-------------------------------------+----------------------------------+
|
|
56
|
-
|:attr:`~z_min` | `float` |
|
|
57
|
-
+-------------------------------------+----------------------------------+
|
|
58
|
-
|:attr:`~z_max` | `float` |
|
|
59
|
-
+-------------------------------------+----------------------------------+
|
|
60
|
-
|:attr:`~functions` | `dict` |
|
|
61
|
-
+-------------------------------------+----------------------------------+
|
|
62
|
-
|:attr:`~sampler_priors` | `dict` |
|
|
63
|
-
+-------------------------------------+----------------------------------+
|
|
64
|
-
|:attr:`~sampler_priors_params` | `dict` |
|
|
65
|
-
+-------------------------------------+----------------------------------+
|
|
66
|
-
|:attr:`~cosmo` | `astropy.cosmology` |
|
|
67
|
-
+-------------------------------------+----------------------------------+
|
|
68
|
-
|:attr:`~directory` | `str` |
|
|
69
|
-
+-------------------------------------+----------------------------------+
|
|
70
|
-
|:attr:`~c_n_i` | `dict` |
|
|
71
|
-
+-------------------------------------+----------------------------------+
|
|
72
|
-
|:attr:`~vd_inv_cdf` | `numpy.ndarray` |
|
|
73
|
-
+-------------------------------------+----------------------------------+
|
|
74
|
-
|:attr:`~available_velocity_dispersion_list_and_its_params` |
|
|
75
|
-
+-------------------------------------+----------------------------------+
|
|
76
|
-
| | `dict` |
|
|
77
|
-
+-------------------------------------+----------------------------------+
|
|
78
|
-
|:attr:`~available_axis_ratio_list_and_its_params` |
|
|
79
|
-
+-------------------------------------+----------------------------------+
|
|
80
|
-
| | `dict` |
|
|
81
|
-
+-------------------------------------+----------------------------------+
|
|
82
|
-
|:attr:`~available_optical_depth_list_and_its_params` |
|
|
83
|
-
+-------------------------------------+----------------------------------+
|
|
84
|
-
| | `dict` |
|
|
85
|
-
+-------------------------------------+----------------------------------+
|
|
86
|
-
|
|
87
|
-
Instance Methods
|
|
88
|
-
----------------
|
|
89
|
-
OpticalDepth class has the following methods:
|
|
90
|
-
+-------------------------------------+----------------------------------+
|
|
91
|
-
| Methods | Type |
|
|
92
|
-
+=====================================+==================================+
|
|
93
|
-
|:meth:`~create_lookup_table` | Function to create a lookup |
|
|
94
|
-
| | table for redshift dependent |
|
|
95
|
-
| | cosmological functions |
|
|
96
|
-
+-------------------------------------+----------------------------------+
|
|
97
|
-
|:meth:`~initialize_velocity_dispersion_sampler` |
|
|
98
|
-
+-------------------------------------+----------------------------------+
|
|
99
|
-
| | Function to initialize velocity |
|
|
100
|
-
| | dispersion sampler |
|
|
101
|
-
+-------------------------------------+----------------------------------+
|
|
102
|
-
|:meth:`~initialize_optical_depth_function` |
|
|
103
|
-
+-------------------------------------+----------------------------------+
|
|
104
|
-
| | Function to initialize optical |
|
|
105
|
-
| | depth function |
|
|
106
|
-
+-------------------------------------+----------------------------------+
|
|
107
|
-
|:meth:`~velocity_dispersion_gengamma`| Function to sample velocity |
|
|
108
|
-
| | dispersion from gengamma |
|
|
109
|
-
| | distribution |
|
|
110
|
-
+-------------------------------------+----------------------------------+
|
|
111
|
-
|:meth:`~velocity_dispersion_bernardi`| Function to sample velocity |
|
|
112
|
-
| | dispersion from Bernardi et al. |
|
|
113
|
-
| | (2010) |
|
|
114
|
-
+-------------------------------------+----------------------------------+
|
|
115
|
-
|:meth:`~velocity_dispersion_ewoud` | Function to sample velocity |
|
|
116
|
-
| | dispersion from Wempe et al. |
|
|
117
|
-
| | (2022) |
|
|
118
|
-
+-------------------------------------+----------------------------------+
|
|
119
|
-
|:meth:`~cross_section_SIS` | Function to compute the SIS |
|
|
120
|
-
| | cross-section |
|
|
121
|
-
+-------------------------------------+----------------------------------+
|
|
122
|
-
|:meth:`~tau_zl_zs` | Function to compute the optical |
|
|
123
|
-
| | depth integrand |
|
|
124
|
-
+-------------------------------------+----------------------------------+
|
|
125
|
-
|:meth:`~optical_depth_calculator` | Function to compute the optical |
|
|
126
|
-
| | depth without multiprocessing |
|
|
127
|
-
+-------------------------------------+----------------------------------+
|
|
128
|
-
|:meth:`~optical_depth_multiprocessing` |
|
|
129
|
-
+-------------------------------------+----------------------------------+
|
|
130
|
-
| | Function to compute the optical |
|
|
131
|
-
| | depth with multiprocessing |
|
|
132
|
-
+-------------------------------------+----------------------------------+
|
|
133
|
-
|:meth:`~optical_depth_SIS_haris` | Function to compute the strong |
|
|
134
|
-
| | lensing optical depth (SIS) |
|
|
135
|
-
| | Haris et al. (2018) (analytic) |
|
|
136
|
-
+-------------------------------------+----------------------------------+
|
|
137
|
-
|:meth:`~optical_depth_SIS_hemanta` | Function to compute the strong |
|
|
138
|
-
| | lensing optical depth (SIS) |
|
|
139
|
-
| | (numerical) |
|
|
140
|
-
+-------------------------------------+----------------------------------+
|
|
141
|
-
|:meth:`~optical_depth_SIE_hemanta` | Function to compute the strong |
|
|
142
|
-
| | lensing optical depth (SIE) |
|
|
143
|
-
| | (numerical) |
|
|
144
|
-
+-------------------------------------+----------------------------------+
|
|
145
|
-
|:meth:`~strong_lensing_optical_depth`| Function to compute the strong |
|
|
146
|
-
| | lensing optical depth |
|
|
147
|
-
+-------------------------------------+----------------------------------+
|
|
148
|
-
|:meth:`~sample_velocity_dispersion` | Function to sample velocity |
|
|
149
|
-
| | dispersion |
|
|
150
|
-
+-------------------------------------+----------------------------------+
|
|
151
|
-
|:meth:`~sample_axis_ratio` | Function to sample axis ratio |
|
|
152
|
-
+-------------------------------------+----------------------------------+
|
|
20
|
+
Class to calculate the optical depth, velocity dispersion and axis-ratio of a lens galaxy population.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
npool : int, optional
|
|
25
|
+
Number of processors to use for multiprocessing (default is 4).
|
|
26
|
+
z_min : float, optional
|
|
27
|
+
Minimum redshift of the lens galaxy population (default is 0.0).
|
|
28
|
+
z_max : float, optional
|
|
29
|
+
Maximum redshift of the lens galaxy population (default is 10.0).
|
|
30
|
+
cosmology : astropy.cosmology, optional
|
|
31
|
+
Cosmology object to use (default is FlatLambdaCDM with H0=70, Om0=0.3, Ode0=0.7).
|
|
32
|
+
lens_type : str, optional
|
|
33
|
+
Type of the lens galaxy. Must be one of ['sie_galaxy', 'epl_shear_galaxy', 'sis_galaxy'] (default is 'epl_shear_galaxy').
|
|
34
|
+
lens_functions : dict, optional
|
|
35
|
+
Dictionary with lens-related functions.
|
|
36
|
+
lens_functions_params : dict, optional
|
|
37
|
+
Dictionary with parameters for the lens-related functions.
|
|
38
|
+
lens_param_samplers : dict, optional
|
|
39
|
+
Dictionary of sampler functions for velocity dispersion and axis-ratio.
|
|
40
|
+
lens_param_samplers_params : dict, optional
|
|
41
|
+
Dictionary with parameters for the priors of the samplers.
|
|
42
|
+
directory : str, optional
|
|
43
|
+
Directory where the interpolators are saved (default is './interpolator_pickle').
|
|
44
|
+
If True, creates a new interpolator (default is False).
|
|
45
|
+
verbose : bool, optional
|
|
46
|
+
If True, prints additional information during initialization (default is False).
|
|
47
|
+
|
|
48
|
+
Raises
|
|
49
|
+
------
|
|
50
|
+
ValueError
|
|
51
|
+
If `lens_type` is not in ['sie_galaxy', 'epl_shear_galaxy', 'sis_galaxy'].
|
|
153
52
|
"""
|
|
154
53
|
|
|
155
54
|
def __init__(self,
|
|
156
55
|
npool=4,
|
|
157
|
-
z_min=0.
|
|
56
|
+
z_min=0.0,
|
|
158
57
|
z_max=10.0,
|
|
159
|
-
optical_depth_function=None,
|
|
160
|
-
sampler_priors=None,
|
|
161
|
-
sampler_priors_params=None,
|
|
162
58
|
cosmology=None,
|
|
59
|
+
lens_type="epl_shear_galaxy",
|
|
60
|
+
lens_functions= None,
|
|
61
|
+
lens_functions_params=None,
|
|
62
|
+
lens_param_samplers=None,
|
|
63
|
+
lens_param_samplers_params=None,
|
|
163
64
|
directory="./interpolator_pickle",
|
|
164
65
|
create_new_interpolator=False,
|
|
66
|
+
verbose=False,
|
|
165
67
|
):
|
|
166
|
-
|
|
68
|
+
|
|
69
|
+
print("\nInitializing OpticalDepth class\n")
|
|
70
|
+
if lens_type not in ["sie_galaxy", "epl_shear_galaxy", "sis_galaxy"]:
|
|
71
|
+
raise ValueError("lens_type not in ['sie_galaxy', 'epl_shear_galaxy', 'sis_galaxy']")
|
|
72
|
+
self.lens_type = lens_type
|
|
73
|
+
|
|
167
74
|
self.npool = npool
|
|
168
75
|
self.z_min = z_min
|
|
169
76
|
self.z_max = z_max
|
|
170
77
|
self.cosmo = cosmology if cosmology else LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
|
|
78
|
+
self.directory = directory
|
|
171
79
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
axis_ratio="axis_ratio_rayleigh",
|
|
175
|
-
)
|
|
176
|
-
if sampler_priors:
|
|
177
|
-
self.sampler_priors.update(sampler_priors)
|
|
178
|
-
self.sampler_priors_params = dict(
|
|
179
|
-
velocity_dispersion=dict(vd_min=0., vd_max=350.),
|
|
180
|
-
axis_ratio=dict(q_min=0.2, q_max=1.),
|
|
181
|
-
)
|
|
182
|
-
if sampler_priors_params:
|
|
183
|
-
self.sampler_priors_params.update(sampler_priors_params)
|
|
80
|
+
# decision dict fot creating interpolator
|
|
81
|
+
self.initialize_decision_dictionary(create_new_interpolator);
|
|
184
82
|
|
|
185
|
-
|
|
83
|
+
# default lens functions and samplers
|
|
84
|
+
self.lens_param_samplers, self.lens_param_samplers_params, self.lens_functions, self.lens_functions_params = self.default_lens_samplers_and_functions(lens_type)
|
|
186
85
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
86
|
+
# change default lens functions and samplers if user input is given
|
|
87
|
+
# if lens functions and samplers are given but not parameters, then use default parameters
|
|
88
|
+
# it updates self.lens_param_samplers, self.lens_param_samplers_params, self.lens_functions, self.lens_functions_params
|
|
89
|
+
self.lens_functions_and_sampler_categorization(lens_param_samplers, lens_param_samplers_params, lens_functions, lens_functions_params);
|
|
90
|
+
|
|
91
|
+
# setting up astropy cosmology functions
|
|
92
|
+
self.create_lookup_table_fuction();
|
|
93
|
+
|
|
94
|
+
if self.lens_functions['cross_section'] == "interpolated_cross_section_function":
|
|
95
|
+
self.create_cross_section_function();
|
|
96
|
+
self.cross_section = getattr(self, "interpolated_cross_section_function")
|
|
97
|
+
else:
|
|
98
|
+
self.cross_section = getattr(self, self.lens_functions['cross_section'])
|
|
99
|
+
self.nbrs=None
|
|
100
|
+
self.values=None
|
|
101
|
+
self.cross_section_spline=None
|
|
102
|
+
self.sis_area_array=None
|
|
103
|
+
|
|
104
|
+
# lens sampler initialization
|
|
105
|
+
self.velocity_dispersion = self.lens_param_samplers['velocity_dispersion']
|
|
106
|
+
self.axis_ratio = self.lens_param_samplers['axis_ratio']
|
|
107
|
+
self.axis_rotation_angle = self.lens_param_samplers['axis_rotation_angle']
|
|
108
|
+
self.density_profile_slope = self.lens_param_samplers['density_profile_slope']
|
|
109
|
+
self.external_shear = self.lens_param_samplers['external_shear']
|
|
110
|
+
self.lens_redshift = self.lens_param_samplers['lens_redshift']
|
|
111
|
+
self.density_profile_slope_sl = self.lens_param_samplers['density_profile_slope_sl']
|
|
112
|
+
self.external_shear_sl = self.lens_param_samplers['external_shear_sl']
|
|
113
|
+
|
|
114
|
+
# lens function initialization
|
|
115
|
+
self.optical_depth = self.lens_functions['optical_depth']
|
|
116
|
+
|
|
117
|
+
##################
|
|
118
|
+
# Initialization #
|
|
119
|
+
##################
|
|
120
|
+
def default_lens_samplers_and_functions(self, lens_type):
|
|
121
|
+
"""
|
|
122
|
+
Function to categorize the lens priors/samplers
|
|
123
|
+
|
|
124
|
+
Parameters
|
|
125
|
+
----------
|
|
126
|
+
lens_type : `str`
|
|
127
|
+
lens type
|
|
128
|
+
e.g. 'epl_shear_galaxy' for elliptical power-law galaxy
|
|
129
|
+
|
|
130
|
+
Returns
|
|
131
|
+
-------
|
|
132
|
+
lens_priors_ : `dict`
|
|
133
|
+
dictionary of priors
|
|
134
|
+
lens_priors_params_ : `dict`
|
|
135
|
+
dictionary of priors parameters
|
|
136
|
+
lens_sampler_names_ : `dict`
|
|
137
|
+
dictionary of sampler names
|
|
138
|
+
lens_functions_ : `dict`
|
|
139
|
+
dictionary of lens functions
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
if lens_type == "epl_shear_galaxy":
|
|
143
|
+
lens_priors_ = dict(
|
|
144
|
+
source_redshift_sl="strongly_lensed_source_redshifts",
|
|
145
|
+
lens_redshift="lens_redshift_SDSS_catalogue_hemanta", #"lens_redshift_SDSS_catalogue_numerical",
|
|
146
|
+
velocity_dispersion="velocity_dispersion_ewoud",
|
|
147
|
+
axis_ratio="axis_ratio_rayleigh",
|
|
148
|
+
axis_rotation_angle="axis_rotation_angle_uniform",
|
|
149
|
+
external_shear="external_shear_normal",
|
|
150
|
+
density_profile_slope="density_profile_slope_normal",
|
|
151
|
+
external_shear_sl="external_shear_normal",
|
|
152
|
+
density_profile_slope_sl="density_profile_slope_normal",
|
|
153
|
+
)
|
|
154
|
+
lens_priors_params_ = dict(
|
|
155
|
+
source_redshift_sl=None,
|
|
156
|
+
lens_redshift=None,
|
|
157
|
+
velocity_dispersion=dict(sigma_min=100., sigma_max=400., alpha=0.94, beta=1.85, phistar=2.099e-2*(self.cosmo.h/0.7)**3, sigmastar=113.78),
|
|
158
|
+
axis_ratio=dict(q_min=0.2, q_max=1.),
|
|
159
|
+
axis_rotation_angle=dict(phi_min=0.0, phi_max=2 * np.pi),
|
|
160
|
+
external_shear=dict(mean=0., std=0.05),
|
|
161
|
+
density_profile_slope=dict(mean=1.99, std=0.149),
|
|
162
|
+
external_shear_sl=dict(mean=0., std=0.05, name="external_shear_sl"),
|
|
163
|
+
density_profile_slope_sl=dict(mean=2.078, std=0.16, name="density_profile_slope_sl"),
|
|
164
|
+
)
|
|
165
|
+
lens_functions_ = dict(
|
|
166
|
+
param_sampler_type="sample_all_routine_sie_sl",
|
|
167
|
+
strong_lensing_condition="rjs_with_cross_section_sie_feixu",
|
|
168
|
+
optical_depth="optical_depth_numerical",
|
|
169
|
+
cross_section="interpolated_cross_section_function",
|
|
170
|
+
)
|
|
171
|
+
lens_functions_params_ = dict(
|
|
172
|
+
strong_lensing_condition=None,
|
|
173
|
+
optical_depth=None,
|
|
174
|
+
param_sampler_type=dict(fast_sampler=True), # not implemented yet
|
|
175
|
+
cross_section=None,
|
|
176
|
+
)
|
|
177
|
+
elif lens_type == "sie_galaxy":
|
|
178
|
+
lens_priors_ = dict(
|
|
179
|
+
source_redshift_sl="strongly_lensed_source_redshifts",
|
|
180
|
+
lens_redshift="lens_redshift_SDSS_catalogue_hemanta", #"lens_redshift_SDSS_catalogue_numerical",
|
|
181
|
+
velocity_dispersion="velocity_dispersion_ewoud",
|
|
182
|
+
axis_ratio="axis_ratio_rayleigh",
|
|
183
|
+
axis_rotation_angle="axis_rotation_angle_uniform",
|
|
184
|
+
external_shear="external_shear_normal",
|
|
185
|
+
density_profile_slope="density_profile_slope_normal",
|
|
186
|
+
external_shear_sl="external_shear_normal",
|
|
187
|
+
density_profile_slope_sl="density_profile_slope_normal",
|
|
188
|
+
)
|
|
189
|
+
lens_priors_params_ = dict(
|
|
190
|
+
source_redshift_sl=None,
|
|
191
|
+
lens_redshift=None,
|
|
192
|
+
velocity_dispersion=dict(sigma_min=100., sigma_max=400., alpha=0.94, beta=1.85, phistar=2.099e-2*(self.cosmo.h/0.7)**3, sigmastar=113.78),
|
|
193
|
+
axis_ratio=dict(q_min=0.2, q_max=1.),
|
|
194
|
+
axis_rotation_angle=dict(phi_min=0.0, phi_max=2 * np.pi),
|
|
195
|
+
external_shear=dict(mean=0., std=0.),
|
|
196
|
+
density_profile_slope=dict(mean=2., std=0.),
|
|
197
|
+
external_shear_sl=dict(mean=0., std=0.),
|
|
198
|
+
density_profile_slope_sl=dict(mean=2., std=0.),
|
|
199
|
+
)
|
|
200
|
+
lens_functions_ = dict(
|
|
201
|
+
strong_lensing_condition="rjs_with_cross_section_sie_feixu",
|
|
202
|
+
optical_depth="optical_depth_numerical",
|
|
203
|
+
param_sampler_type="sample_all_routine_sie_sl",
|
|
204
|
+
cross_section="cross_section_sie_feixu",
|
|
205
|
+
)
|
|
206
|
+
lens_functions_params_ = dict(
|
|
207
|
+
strong_lensing_condition=None,
|
|
208
|
+
optical_depth=dict(interpolated_cross_section=True),
|
|
209
|
+
param_sampler_type=None,
|
|
210
|
+
cross_section=None,
|
|
211
|
+
)
|
|
212
|
+
elif lens_type == "sis_galaxy":
|
|
213
|
+
lens_priors_ = dict(
|
|
214
|
+
source_redshift_sl="strongly_lensed_source_redshifts",
|
|
215
|
+
lens_redshift="lens_redshift_SDSS_catalogue_sis",
|
|
216
|
+
velocity_dispersion="velocity_dispersion_choi",
|
|
217
|
+
axis_ratio="axis_ratio_uniform",
|
|
218
|
+
axis_rotation_angle="axis_rotation_angle_uniform",
|
|
219
|
+
external_shear="external_shear_normal",
|
|
220
|
+
density_profile_slope="density_profile_slope_normal",
|
|
221
|
+
external_shear_sl="external_shear_normal",
|
|
222
|
+
density_profile_slope_sl="density_profile_slope_normal",
|
|
223
|
+
)
|
|
224
|
+
lens_priors_params_ = dict(
|
|
225
|
+
source_redshift_sl=None,
|
|
226
|
+
lens_redshift=None,
|
|
227
|
+
velocity_dispersion=dict(sigma_min = 10., sigma_max = 420., alpha = 2.32, beta = 2.67, phistar = 8.0e-3*self.cosmo.h**3, sigmastar = 161.0),
|
|
228
|
+
axis_ratio=dict(q_min=1., q_max=1.),
|
|
229
|
+
axis_rotation_angle=dict(phi_min=0.0, phi_max=0.),
|
|
230
|
+
external_shear=dict(mean=0., std=0.),
|
|
231
|
+
density_profile_slope=dict(mean=2., std=0.),
|
|
232
|
+
external_shear_sl=dict(mean=0., std=0.),
|
|
233
|
+
density_profile_slope_sl=dict(mean=2., std=0.),
|
|
234
|
+
)
|
|
235
|
+
lens_functions_ = dict(
|
|
236
|
+
strong_lensing_condition="rjs_with_cross_section_sis",
|
|
237
|
+
optical_depth="optical_depth_sis_haris",
|
|
238
|
+
param_sampler_type="sample_all_routine_sis_sl",
|
|
239
|
+
cross_section="cross_section_sis",
|
|
240
|
+
)
|
|
241
|
+
lens_functions_params_ = dict(
|
|
242
|
+
strong_lensing_condition=None,
|
|
243
|
+
optical_depth=dict(interpolated_cross_section=True),
|
|
244
|
+
param_sampler_type=None,
|
|
245
|
+
cross_section=None,
|
|
246
|
+
)
|
|
247
|
+
else:
|
|
248
|
+
raise ValueError("lens_type not recognized")
|
|
249
|
+
|
|
250
|
+
return(lens_priors_, lens_priors_params_, lens_functions_, lens_functions_params_)
|
|
251
|
+
|
|
252
|
+
def initialize_decision_dictionary(self, create_new_interpolator):
|
|
253
|
+
"""
|
|
254
|
+
Function to initialize decision dictionary for creating interpolator
|
|
255
|
+
|
|
256
|
+
Parameters
|
|
257
|
+
----------
|
|
258
|
+
create_new_interpolator : `dict` or `bool`
|
|
259
|
+
dictionary to create new interpolator for velocity dispersion and optical depth.
|
|
260
|
+
"""
|
|
261
|
+
|
|
262
|
+
# initialize the interpolator's parameters
|
|
263
|
+
self.create_new_interpolator = dict(
|
|
264
|
+
velocity_dispersion=dict(create_new=False, resolution=500),
|
|
265
|
+
axis_ratio=dict(create_new=False, resolution=500),
|
|
266
|
+
lens_redshift=dict(create_new=False, resolution=50),
|
|
267
|
+
optical_depth=dict(create_new=False, resolution=48),
|
|
268
|
+
comoving_distance=dict(create_new=False, resolution=500),
|
|
269
|
+
angular_diameter_distance=dict(create_new=False, resolution=500),
|
|
270
|
+
differential_comoving_volume=dict(create_new=False, resolution=500),
|
|
271
|
+
cross_section=dict(create_new=False, resolution=1000000),
|
|
272
|
+
density_profile_slope=dict(create_new=False, resolution=100),
|
|
273
|
+
lens_parameters_kde_sl=dict(create_new=False, resolution=5000),
|
|
196
274
|
)
|
|
197
275
|
if isinstance(create_new_interpolator, dict):
|
|
198
|
-
self.
|
|
276
|
+
self.create_new_interpolator.update(create_new_interpolator)
|
|
277
|
+
# if create_new_interpolator is True, create new interpolator for all
|
|
199
278
|
elif create_new_interpolator is True:
|
|
200
|
-
self.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
279
|
+
for key in self.create_new_interpolator.keys():
|
|
280
|
+
self.create_new_interpolator[key]['create_new'] = True
|
|
281
|
+
|
|
282
|
+
def lens_functions_and_sampler_categorization(self, lens_param_samplers, lens_param_samplers_params, lens_functions, lens_functions_params):
|
|
283
|
+
"""
|
|
284
|
+
Function to initialize velocity dispersion sampler with it's settings. The reason I am seperating this from lens_priors_categorization is only a specific parameters needs special attention.
|
|
285
|
+
|
|
286
|
+
Parameters
|
|
287
|
+
----------
|
|
288
|
+
lens_param_samplers : `str` or `function`
|
|
289
|
+
sampler name or function
|
|
290
|
+
lens_param_samplers_params : `dict`
|
|
291
|
+
sampler parameters
|
|
292
|
+
lens_functions : `str` or `function`
|
|
293
|
+
lens function name or function
|
|
294
|
+
lens_functions_params : `dict`
|
|
295
|
+
lens function parameters
|
|
296
|
+
"""
|
|
297
|
+
|
|
298
|
+
# update the priors if input is given
|
|
299
|
+
if lens_param_samplers:
|
|
300
|
+
self.lens_param_samplers.update(lens_param_samplers)
|
|
301
|
+
if lens_param_samplers_params:
|
|
302
|
+
self.lens_param_samplers_params.update(lens_param_samplers_params)
|
|
303
|
+
if lens_functions:
|
|
304
|
+
self.lens_functions.update(lens_functions)
|
|
305
|
+
if lens_functions_params:
|
|
306
|
+
self.lens_functions_params.update(lens_functions_params)
|
|
307
|
+
|
|
308
|
+
sampler_prior_names = ['lens_redshift', 'velocity_dispersion', 'axis_ratio', 'axis_rotation_angle', 'external_shear', 'density_profile_slope', 'external_shear_sl', 'density_profile_slope_sl']
|
|
309
|
+
|
|
310
|
+
# if there is user input sampler prior params
|
|
311
|
+
# you can't only give lens_param_samplers_params, you have to give lens_param_samplers as well if you want to update the sampler priors
|
|
312
|
+
for name in sampler_prior_names: # e.g. name='axis_ratio'
|
|
313
|
+
# avoid None
|
|
314
|
+
if (lens_param_samplers is not None) and (name in lens_param_samplers):
|
|
315
|
+
# if there is user input function name, update the sampler priors
|
|
316
|
+
sampler_name = lens_param_samplers[name] # e.g. 'axis_ratio_rayleigh'
|
|
317
|
+
# check input sampler is string or function
|
|
318
|
+
if isinstance(sampler_name, str):
|
|
319
|
+
# available lens samplers for name e.g. 'axis_ratio'
|
|
320
|
+
dict_ = self.available_lens_prior_list_and_its_params[name] # e.g. {'axis_ratio_padilla_strauss': {'q_min': 0.2, 'q_max': 1.0}, ....}
|
|
321
|
+
if sampler_name in dict_: # e.g. 'axis_ratio_padilla_strauss'
|
|
322
|
+
param_dict = dict_[sampler_name] # e.g. {'q_min': 0.2, 'q_max': 1.0}
|
|
323
|
+
if (lens_param_samplers_params is None) or (lens_param_samplers_params[name] is None): # not a dictionary
|
|
324
|
+
self.lens_param_samplers_params[name] = param_dict
|
|
325
|
+
else: # if there is user input lens_param_samplers_params
|
|
326
|
+
param_dict.update(lens_param_samplers_params[name])
|
|
327
|
+
self.lens_param_samplers_params[name].update(param_dict) # user inputs will override the default values
|
|
328
|
+
else:
|
|
329
|
+
raise ValueError(f"{name} sampler {sampler_name} not available.\n Available {name} samplers and its parameters are: {dict_[name]}")
|
|
330
|
+
elif not callable(lens_param_samplers[name]):
|
|
331
|
+
raise ValueError(f"Given {name} sampler should be either a string name of available sampler or a function")
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
lens_function_names = ['optical_depth', 'cross_section']
|
|
335
|
+
|
|
336
|
+
# if there is user input function, update the sampler priors
|
|
337
|
+
for name in lens_function_names:
|
|
338
|
+
if (lens_functions is not None) and (name in lens_functions):
|
|
339
|
+
function_name = lens_functions[name]
|
|
340
|
+
if isinstance(function_name, str):
|
|
341
|
+
# available lens functions for name e.g. 'optical_depth'
|
|
342
|
+
dict_ = self.available_lens_functions_and_its_params[name]
|
|
343
|
+
if function_name in dict_:
|
|
344
|
+
param_dict = dict_[function_name]
|
|
345
|
+
if (lens_functions_params is None) or (lens_functions_params[name] is None): # not a dictionary
|
|
346
|
+
self.lens_functions_params[name] = param_dict
|
|
347
|
+
else: # if there is user input lens_functions_params
|
|
348
|
+
param_dict.update(lens_functions_params[name])
|
|
349
|
+
self.lens_functions_params[name].update(param_dict) # user inputs will override the default values
|
|
350
|
+
else:
|
|
351
|
+
raise ValueError(f"{name} function {function_name} not available.\n Available {name} functions and its parameters are: {dict_[name]}")
|
|
352
|
+
elif not callable(lens_functions[name]):
|
|
353
|
+
raise ValueError(f"Given {name} function should be either a string name of available function or a function")
|
|
354
|
+
|
|
355
|
+
# setting up multiprocessor function for lens redshift
|
|
356
|
+
if self.lens_type == 'epl_shear_galaxy':
|
|
357
|
+
if self.lens_param_samplers['velocity_dispersion'] == 'velocity_dispersion_ewoud':
|
|
358
|
+
print('using lens_redshift_epl_shear2_mp')
|
|
359
|
+
from .mp import lens_redshift_epl_shear2_mp
|
|
360
|
+
self._helper_sl_disribution_mp = lens_redshift_epl_shear2_mp
|
|
361
|
+
else:
|
|
362
|
+
print('using lens_redshift_epl_shear1_mp')
|
|
363
|
+
from .mp import lens_redshift_epl_shear1_mp
|
|
364
|
+
self._helper_sl_disribution_mp = lens_redshift_epl_shear1_mp
|
|
365
|
+
elif self.lens_type == 'sie_galaxy':
|
|
366
|
+
if self.lens_param_samplers['velocity_dispersion'] == 'velocity_dispersion_ewoud':
|
|
367
|
+
if self.lens_functions['cross_section']=='interpolated_cross_section_function':
|
|
368
|
+
print('using lens_redshift_sie4_mp')
|
|
369
|
+
from .mp import lens_redshift_sie4_mp
|
|
370
|
+
self._helper_sl_disribution_mp = lens_redshift_sie4_mp
|
|
371
|
+
else:
|
|
372
|
+
print('using lens_redshift_sie2_mp')
|
|
373
|
+
from .mp import lens_redshift_sie2_mp
|
|
374
|
+
self._helper_sl_disribution_mp = lens_redshift_sie2_mp
|
|
375
|
+
else:
|
|
376
|
+
if self.lens_functions['cross_section']=='interpolated_cross_section_function':
|
|
377
|
+
print('using lens_redshift_sie3_mp')
|
|
378
|
+
from .mp import lens_redshift_sie3_mp
|
|
379
|
+
self._helper_sl_disribution_mp = lens_redshift_sie3_mp
|
|
380
|
+
else:
|
|
381
|
+
print('using lens_redshift_sie1_mp')
|
|
382
|
+
from .mp import lens_redshift_sie1_mp
|
|
383
|
+
self._helper_sl_disribution_mp = lens_redshift_sie1_mp
|
|
384
|
+
elif self.lens_type == 'sis_galaxy':
|
|
385
|
+
if self.lens_param_samplers['velocity_dispersion'] == 'velocity_dispersion_ewoud':
|
|
386
|
+
print('using lens_redshift_sis2_mp')
|
|
387
|
+
from .mp import lens_redshift_sis2_mp
|
|
388
|
+
self._helper_sl_disribution_mp = lens_redshift_sis2_mp
|
|
389
|
+
else:
|
|
390
|
+
print('using lens_redshift_sis1_mp')
|
|
391
|
+
from .mp import lens_redshift_sis1_mp
|
|
392
|
+
self._helper_sl_disribution_mp = lens_redshift_sis1_mp
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
#####################
|
|
396
|
+
# Sampler functions #
|
|
397
|
+
#####################
|
|
398
|
+
def axis_ratio_rayleigh(self, size, sigma, get_attribute=False, **kwargs):
|
|
399
|
+
"""
|
|
400
|
+
Function to sample axis ratio from rayleigh distribution with given velocity dispersion.
|
|
209
401
|
|
|
210
|
-
|
|
211
|
-
|
|
402
|
+
Parameters
|
|
403
|
+
----------
|
|
404
|
+
sigma : `float: array`
|
|
405
|
+
velocity dispersion of the lens galaxy
|
|
406
|
+
q_min, q_max : `float`
|
|
407
|
+
minimum and maximum axis ratio
|
|
408
|
+
get_attribute : `bool`
|
|
409
|
+
if True, returns a function that can be used to sample axis ratio
|
|
212
410
|
|
|
213
|
-
|
|
411
|
+
Returns
|
|
412
|
+
-------
|
|
413
|
+
q : `float: array`
|
|
414
|
+
axis ratio of the lens galaxy
|
|
214
415
|
|
|
215
|
-
|
|
216
|
-
|
|
416
|
+
Examples
|
|
417
|
+
--------
|
|
418
|
+
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
419
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(axis_ratio="axis_ratio_rayleigh"))
|
|
420
|
+
>>> print(od.axis_ratio(sigma=200.))
|
|
421
|
+
"""
|
|
217
422
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
423
|
+
identifier_dict = {'name': "axis_ratio_rayleigh"}
|
|
424
|
+
identifier_dict['velocity_dispersion'] = self.lens_param_samplers_params['velocity_dispersion']
|
|
425
|
+
if identifier_dict['velocity_dispersion']: # if velocity_dispersion is not None
|
|
426
|
+
identifier_dict['velocity_dispersion']['name'] = str(self.lens_param_samplers['velocity_dispersion'])
|
|
427
|
+
identifier_dict['resolution'] = self.create_new_interpolator["axis_ratio"]["resolution"]
|
|
428
|
+
param_dict = self.available_lens_prior_list_and_its_params["axis_ratio"]["axis_ratio_rayleigh"]
|
|
429
|
+
if param_dict:
|
|
430
|
+
param_dict.update(kwargs)
|
|
221
431
|
else:
|
|
222
|
-
|
|
432
|
+
param_dict = kwargs
|
|
433
|
+
identifier_dict.update(param_dict)
|
|
434
|
+
|
|
435
|
+
q_array = np.linspace(
|
|
436
|
+
identifier_dict["q_min"],
|
|
437
|
+
identifier_dict["q_max"],
|
|
438
|
+
identifier_dict["resolution"],
|
|
439
|
+
)
|
|
440
|
+
sigma_array = np.linspace(
|
|
441
|
+
identifier_dict['velocity_dispersion']["sigma_min"],
|
|
442
|
+
identifier_dict['velocity_dispersion']["sigma_max"],
|
|
443
|
+
500,
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
q_pdf = lambda q, sigma: axis_ratio_rayleigh_pdf(
|
|
447
|
+
q=q,
|
|
448
|
+
sigma=sigma,
|
|
449
|
+
q_min=identifier_dict["q_min"],
|
|
450
|
+
q_max=identifier_dict["q_max"],
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
q_object = FunctionConditioning(
|
|
454
|
+
function=q_pdf,
|
|
455
|
+
x_array=q_array,
|
|
456
|
+
conditioned_y_array=sigma_array,
|
|
457
|
+
param_dict_given=identifier_dict,
|
|
458
|
+
directory=self.directory,
|
|
459
|
+
sub_directory="axis_ratio",
|
|
460
|
+
name="axis_ratio_rayleigh",
|
|
461
|
+
create_new=self.create_new_interpolator["axis_ratio"]["create_new"],
|
|
462
|
+
create_function_inverse=False,
|
|
463
|
+
create_function=True,
|
|
464
|
+
create_pdf=True,
|
|
465
|
+
create_rvs=True,
|
|
466
|
+
callback='rvs',
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
return q_object if get_attribute else q_object(size, sigma)
|
|
223
470
|
|
|
224
|
-
def
|
|
471
|
+
def axis_ratio_padilla_strauss(self, size=1000, get_attribute=False, **kwargs):
|
|
225
472
|
"""
|
|
226
|
-
Function to
|
|
473
|
+
Function to sample axis ratio using Padilla and Strauss 2008 distribution for axis ratio
|
|
227
474
|
|
|
228
475
|
Parameters
|
|
229
476
|
----------
|
|
230
|
-
|
|
231
|
-
|
|
477
|
+
size : `int`
|
|
478
|
+
sample size
|
|
479
|
+
q_min, q_max : `float`
|
|
480
|
+
minimum and maximum axis ratio
|
|
481
|
+
get_attribute : `bool`
|
|
482
|
+
if True, returns a function that can be used to sample axis ratio
|
|
483
|
+
|
|
484
|
+
Returns
|
|
485
|
+
-------
|
|
486
|
+
q : `float: array`
|
|
487
|
+
axis ratio of the lens galaxy
|
|
488
|
+
|
|
489
|
+
Examples
|
|
490
|
+
--------
|
|
491
|
+
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
492
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(axis_ratio="axis_ratio_padilla_strauss"))
|
|
493
|
+
>>> print(od.axis_ratio(size=10))
|
|
232
494
|
"""
|
|
233
495
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
elif vd_name == "velocity_dispersion_ewoud":
|
|
264
|
-
if self.z_min==0.0:
|
|
265
|
-
self.zl_list = np.linspace(self.z_min+0.001, self.z_max, 100)
|
|
266
|
-
else:
|
|
267
|
-
self.zl_list = np.linspace(self.z_min, self.z_max, 100)
|
|
268
|
-
# setting up input parameters for interpolation
|
|
269
|
-
pdf_func_ = lambda vd_, zl_: phi(vd_, zl_, cosmology_h=self.cosmo.h)*self.differential_comoving_volume(np.array([zl_]))
|
|
270
|
-
conditioned_y_ = self.zl_list
|
|
271
|
-
dimension_ = 2
|
|
496
|
+
identifier_dict = {'name': "axis_ratio_padilla_strauss"}
|
|
497
|
+
identifier_dict['resolution'] = self.create_new_interpolator["axis_ratio"]["resolution"]
|
|
498
|
+
param_dict = self.available_lens_prior_list_and_its_params["axis_ratio"]["axis_ratio_padilla_strauss"]
|
|
499
|
+
if param_dict:
|
|
500
|
+
param_dict.update(kwargs)
|
|
501
|
+
else:
|
|
502
|
+
param_dict = kwargs
|
|
503
|
+
identifier_dict.update(param_dict)
|
|
504
|
+
|
|
505
|
+
# Using Padilla and Strauss 2008 distribution for axis ratio
|
|
506
|
+
q_array = np.array([0.04903276402927845, 0.09210526315789469, 0.13596491228070173, 0.20789473684210524, 0.2899703729522482, 0.3230132450331126, 0.35350877192982455, 0.37946148483792264, 0.4219298245614036, 0.4689525967235971, 0.5075026141512723, 0.5226472638550018, 0.5640350877192983, 0.6096491228070177, 0.6500000000000001, 0.6864848379226213, 0.7377192982456142, 0.7787295224817011, 0.8007581038689441, 0.822786685256187, 0.8668438480306729, 0.8973684210526317, 0.9254385964912283])
|
|
507
|
+
pdf = np.array([0.04185262687135349, 0.06114520695141845, 0.096997499638376, 0.1932510900336828, 0.39547914337673706, 0.49569751276216234, 0.6154609137685201, 0.7182049959882812, 0.920153741243567, 1.1573982157399754, 1.3353263628106684, 1.413149656448315, 1.5790713532948977, 1.7280185150744938, 1.8132994441344819, 1.8365803753840484, 1.8178662203211204, 1.748929843583365, 1.688182592496342, 1.6274353414093188, 1.4948487090314488, 1.402785526832393, 1.321844068356993])
|
|
508
|
+
|
|
509
|
+
q_object = FunctionConditioning(
|
|
510
|
+
function=pdf,
|
|
511
|
+
x_array=q_array,
|
|
512
|
+
conditioned_y_array=None,
|
|
513
|
+
param_dict_given=identifier_dict,
|
|
514
|
+
directory=self.directory,
|
|
515
|
+
sub_directory="axis_ratio",
|
|
516
|
+
name="axis_ratio_padilla_strauss",
|
|
517
|
+
create_new=self.create_new_interpolator["axis_ratio"]["create_new"],
|
|
518
|
+
create_function_inverse=False,
|
|
519
|
+
create_function=True,
|
|
520
|
+
create_pdf=True,
|
|
521
|
+
create_rvs=True,
|
|
522
|
+
callback='rvs',
|
|
523
|
+
)
|
|
272
524
|
|
|
525
|
+
return q_object if get_attribute else q_object(size)
|
|
526
|
+
|
|
527
|
+
def lens_redshift_SDSS_catalogue_numerical(self, size=1000, zs=None, get_attribute=False, **kwargs):
|
|
528
|
+
"""
|
|
529
|
+
Function to sample lens redshifts, conditioned on the lens being strongly lensed
|
|
530
|
+
|
|
531
|
+
Parameters
|
|
532
|
+
----------
|
|
533
|
+
size : `int`
|
|
534
|
+
sample size
|
|
535
|
+
zs : `float`
|
|
536
|
+
source redshifts
|
|
537
|
+
get_attribute : `bool`
|
|
538
|
+
if True, returns a function that can be used to sample lens redshifts
|
|
539
|
+
|
|
540
|
+
Returns
|
|
541
|
+
-------
|
|
542
|
+
zs : `float: array`
|
|
543
|
+
lens redshifts
|
|
544
|
+
|
|
545
|
+
Examples
|
|
546
|
+
--------
|
|
547
|
+
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
548
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(lens_redshift="lens_redshift_SDSS_catalogue_numerical"))
|
|
549
|
+
>>> print(od.lens_redshift(size=10, zs=1.0))
|
|
550
|
+
"""
|
|
551
|
+
|
|
552
|
+
identifier_dict = {}
|
|
553
|
+
identifier_dict['name'] = "lens_redshift_numerical_"+self.lens_type
|
|
554
|
+
identifier_dict['resolution'] = self.create_new_interpolator["lens_redshift"]["resolution"]
|
|
555
|
+
identifier_dict['z_min'] = self.z_min
|
|
556
|
+
identifier_dict['z_max'] = self.z_max
|
|
557
|
+
identifier_dict['cosmology'] = self.cosmo
|
|
558
|
+
identifier_dict['velocity_dispersion'] = self.lens_param_samplers_params['velocity_dispersion']
|
|
559
|
+
if identifier_dict['velocity_dispersion']: # if velocity_dispersion is not None
|
|
560
|
+
identifier_dict['velocity_dispersion']['name'] = str(self.lens_param_samplers['velocity_dispersion'])
|
|
561
|
+
identifier_dict['axis_ratio'] = self.lens_param_samplers_params['axis_ratio']
|
|
562
|
+
if identifier_dict['axis_ratio']: # if axis_ratio is not None
|
|
563
|
+
identifier_dict['axis_ratio']['name'] = str(self.lens_param_samplers['axis_ratio'])
|
|
564
|
+
identifier_dict['axis_rotation_angle'] = self.lens_param_samplers_params['axis_rotation_angle']
|
|
565
|
+
if identifier_dict['axis_rotation_angle']: # if axis_rotation_angle is not None
|
|
566
|
+
identifier_dict['axis_rotation_angle']['name'] = str(self.lens_param_samplers['axis_rotation_angle'])
|
|
567
|
+
identifier_dict['density_profile_slope'] = self.lens_param_samplers_params['density_profile_slope']
|
|
568
|
+
if identifier_dict['density_profile_slope']: # if density_profile_slope is not None
|
|
569
|
+
identifier_dict['density_profile_slope']['name'] = str(self.lens_param_samplers['density_profile_slope'])
|
|
570
|
+
identifier_dict['external_shear'] = self.lens_param_samplers_params['external_shear']
|
|
571
|
+
if identifier_dict['external_shear']: # if external_shear is not None
|
|
572
|
+
identifier_dict['external_shear']['name'] = str(self.lens_param_samplers['external_shear'])
|
|
573
|
+
|
|
574
|
+
param_dict = self.available_lens_prior_list_and_its_params["lens_redshift"]["lens_redshift_SDSS_catalogue_numerical"]
|
|
575
|
+
if param_dict:
|
|
576
|
+
param_dict.update(kwargs)
|
|
273
577
|
else:
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
578
|
+
param_dict = kwargs
|
|
579
|
+
identifier_dict.update(param_dict)
|
|
580
|
+
|
|
581
|
+
print("Numerically solving the lens redshift distribution...")
|
|
582
|
+
zs_resolution = self.create_new_interpolator["optical_depth"]["resolution"]
|
|
583
|
+
zs_array = np.geomspace(self.z_min+0.001, self.z_max, zs_resolution) if self.z_min==0 else np.geomspace(self.z_min, self.z_max, zs_resolution)
|
|
584
|
+
|
|
585
|
+
zl_scaled2d = []
|
|
586
|
+
for i, zs_ in enumerate(zs_array):
|
|
587
|
+
buffer_ = np.linspace(0.0001, zs_-0.0001, identifier_dict['resolution'])
|
|
588
|
+
zl_scaled2d.append(buffer_/zs_)
|
|
589
|
+
zl_scaled2d = np.array(zl_scaled2d)
|
|
590
|
+
|
|
591
|
+
_, it_exist = interpolator_pickle_path(
|
|
592
|
+
param_dict_given=identifier_dict,
|
|
593
|
+
directory=self.directory,
|
|
594
|
+
sub_directory="lens_redshift",
|
|
595
|
+
interpolator_name=identifier_dict['name'],
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
create_new = self.create_new_interpolator["lens_redshift"]["create_new"]
|
|
599
|
+
if not it_exist or create_new:
|
|
600
|
+
number_density = self.lens_redshift_multiprocessing(zl_scaled2d, zs_array)
|
|
601
|
+
# number density is zero for zl=0 and infinite for zl=zs
|
|
602
|
+
# Adding zero at the first element of each row
|
|
603
|
+
zl_scaled2d = np.hstack((np.zeros((zl_scaled2d.shape[0], 1)), zl_scaled2d))
|
|
604
|
+
number_density = np.hstack((np.zeros((number_density.shape[0], 1)), number_density))
|
|
605
|
+
# Adding one at the last element of each row of zl_scaled2d
|
|
606
|
+
zl_scaled2d = np.hstack((zl_scaled2d, np.ones((zl_scaled2d.shape[0], 1))))
|
|
607
|
+
# Adding zero at the last element of each row of density
|
|
608
|
+
number_density = np.hstack((number_density, np.zeros((number_density.shape[0], 1))))
|
|
609
|
+
else:
|
|
610
|
+
number_density=None
|
|
611
|
+
|
|
612
|
+
zl_object = FunctionConditioning(
|
|
613
|
+
function=number_density,
|
|
614
|
+
x_array=zl_scaled2d,
|
|
615
|
+
conditioned_y_array=zs_array,
|
|
616
|
+
param_dict_given=identifier_dict,
|
|
617
|
+
directory=self.directory,
|
|
618
|
+
sub_directory="lens_redshift",
|
|
619
|
+
name=identifier_dict['name'],
|
|
620
|
+
create_new=create_new,
|
|
621
|
+
create_function_inverse=False,
|
|
622
|
+
create_function=True,
|
|
623
|
+
create_pdf=True,
|
|
624
|
+
create_rvs=True,
|
|
625
|
+
callback='rvs',
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
# un-scaled lens redshift
|
|
629
|
+
cdf_values = zl_object.cdf_values
|
|
630
|
+
x_array = zl_object.x_array
|
|
631
|
+
y_array = zl_object.conditioned_y_array
|
|
632
|
+
function_spline = zl_object.function_spline
|
|
633
|
+
pdf_norm_const = zl_object.pdf_norm_const
|
|
634
|
+
|
|
635
|
+
zl_object.function = njit(lambda x, y: cubic_spline_interpolator2d_array(x/y, y, function_spline, x_array, y_array))
|
|
636
|
+
|
|
637
|
+
zl_object.pdf = njit(lambda x, y: pdf_cubic_spline_interpolator2d_array(x/y, y, pdf_norm_const, function_spline, x_array, y_array))
|
|
638
|
+
|
|
639
|
+
zl_object.rvs = njit(lambda size, y: inverse_transform_sampler2d(size, y, cdf_values, x_array, y_array)*y)
|
|
640
|
+
|
|
641
|
+
return zl_object if get_attribute else zl_object(size, zs)
|
|
642
|
+
|
|
643
|
+
def lens_redshift_SDSS_catalogue_hemanta(self, size=1000, zs=None, get_attribute=False, **kwargs):
|
|
644
|
+
"""
|
|
645
|
+
Function to sample lens redshifts, conditioned on the lens being strongly lensed
|
|
646
|
+
|
|
647
|
+
Parameters
|
|
648
|
+
----------
|
|
649
|
+
size : `int`
|
|
650
|
+
sample size
|
|
651
|
+
zs : `float`
|
|
652
|
+
source redshifts
|
|
653
|
+
get_attribute : `bool`
|
|
654
|
+
if True, returns a function that can be used to sample lens redshifts
|
|
655
|
+
|
|
656
|
+
Returns
|
|
657
|
+
-------
|
|
658
|
+
zs : `float: array`
|
|
659
|
+
lens redshifts
|
|
660
|
+
|
|
661
|
+
Examples
|
|
662
|
+
--------
|
|
663
|
+
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
664
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(lens_redshift="lens_redshift_SDSS_catalogue_numerical"))
|
|
665
|
+
>>> print(od.lens_redshift(size=10, zs=1.0))
|
|
666
|
+
"""
|
|
667
|
+
|
|
668
|
+
# default parameters
|
|
669
|
+
identifier_dict = {'name': 'lens_redshift_numerical_epl_shear_galaxy',
|
|
670
|
+
'resolution': 50,
|
|
671
|
+
'z_min': 0.0,
|
|
672
|
+
'z_max': 10.0,
|
|
673
|
+
'cosmology': LambdaCDM(H0=70, Om0=0.3, Ode0=0.7),
|
|
674
|
+
'velocity_dispersion': {'sigma_min': 100.0,
|
|
675
|
+
'sigma_max': 400.0,
|
|
676
|
+
'alpha': 0.94,
|
|
677
|
+
'beta': 1.85,
|
|
678
|
+
'phistar': 0.02099,
|
|
679
|
+
'sigmastar': 113.78,
|
|
680
|
+
'name': 'velocity_dispersion_ewoud'},
|
|
681
|
+
'axis_ratio': {'q_min': 0.2, 'q_max': 1.0, 'name': 'axis_ratio_rayleigh'},
|
|
682
|
+
'axis_rotation_angle': {'phi_min': 0.0,
|
|
683
|
+
'phi_max': 6.283185307179586,
|
|
684
|
+
'name': 'axis_rotation_angle_uniform'},
|
|
685
|
+
'density_profile_slope': {'mean': 1.99,
|
|
686
|
+
'std': 0.149,
|
|
687
|
+
'name': 'density_profile_slope_normal'},
|
|
688
|
+
'external_shear': {'mean': 0.0, 'std': 0.05, 'name': 'external_shear_normal'}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
print("Getting pre-computed lens redshift distribution...")
|
|
692
|
+
zs_resolution = 48
|
|
693
|
+
zs_array = np.geomspace(0.001, 10., zs_resolution)
|
|
694
|
+
zl_scaled2d = []
|
|
695
|
+
for i, zs_ in enumerate(zs_array):
|
|
696
|
+
buffer_ = np.linspace(0.0001, zs_-0.0001, identifier_dict['resolution'])
|
|
697
|
+
zl_scaled2d.append(buffer_/zs_)
|
|
698
|
+
zl_scaled2d = np.array(zl_scaled2d)
|
|
699
|
+
|
|
700
|
+
# get number_density
|
|
701
|
+
number_density = load_txt_from_module('ler', 'lens_galaxy_population.lens_param_data', 'number_density_zl_zs.txt')
|
|
702
|
+
|
|
703
|
+
# number density is zero for zl=0 and infinite for zl=zs
|
|
704
|
+
# Adding zero at the first element of each row
|
|
705
|
+
zl_scaled2d = np.hstack((np.zeros((zl_scaled2d.shape[0], 1)), zl_scaled2d))
|
|
706
|
+
# number_density = np.hstack((np.zeros((number_density.shape[0], 1)), number_density))
|
|
707
|
+
# Adding one at the last element of each row of zl_scaled2d
|
|
708
|
+
zl_scaled2d = np.hstack((zl_scaled2d, np.ones((zl_scaled2d.shape[0], 1))))
|
|
709
|
+
# Adding zero at the last element of each row of density
|
|
710
|
+
# number_density = np.hstack((number_density, np.zeros((number_density.shape[0], 1))))
|
|
711
|
+
|
|
712
|
+
zl_object = FunctionConditioning(
|
|
713
|
+
function=number_density,
|
|
714
|
+
x_array=zl_scaled2d,
|
|
715
|
+
conditioned_y_array=zs_array,
|
|
716
|
+
param_dict_given=identifier_dict,
|
|
283
717
|
directory=self.directory,
|
|
284
|
-
sub_directory=
|
|
285
|
-
name=
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
718
|
+
sub_directory="lens_redshift",
|
|
719
|
+
name=identifier_dict['name'],
|
|
720
|
+
create_new=False,
|
|
721
|
+
create_function_inverse=False,
|
|
722
|
+
create_function=True,
|
|
723
|
+
create_pdf=True,
|
|
724
|
+
create_rvs=True,
|
|
725
|
+
callback='rvs',
|
|
292
726
|
)
|
|
293
727
|
|
|
294
|
-
|
|
728
|
+
# un-scaled lens redshift
|
|
729
|
+
cdf_values = zl_object.cdf_values
|
|
730
|
+
x_array = zl_object.x_array
|
|
731
|
+
y_array = zl_object.conditioned_y_array
|
|
732
|
+
function_spline = zl_object.function_spline
|
|
733
|
+
pdf_norm_const = zl_object.pdf_norm_const
|
|
734
|
+
|
|
735
|
+
zl_object.function = njit(lambda x, y: cubic_spline_interpolator2d_array(x/y, y, function_spline, x_array, y_array))
|
|
295
736
|
|
|
296
|
-
|
|
737
|
+
zl_object.pdf = njit(lambda x, y: pdf_cubic_spline_interpolator2d_array(x/y, y, pdf_norm_const, function_spline, x_array, y_array))
|
|
738
|
+
|
|
739
|
+
zl_object.rvs = njit(lambda size, y: inverse_transform_sampler2d(size, y, cdf_values, x_array, y_array)*y)
|
|
740
|
+
|
|
741
|
+
return zl_object if get_attribute else zl_object(size, zs)
|
|
742
|
+
|
|
743
|
+
def intrinsic_lens_redshift(self, size=1000, get_attribute=False, **kwargs):
|
|
297
744
|
"""
|
|
298
|
-
Function to
|
|
745
|
+
Function to sample intrinsic lens redshifts, based on the intrinsic velocity dispersion of the lens galaxy.
|
|
299
746
|
|
|
300
747
|
Parameters
|
|
301
748
|
----------
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
749
|
+
size : `int`
|
|
750
|
+
sample size
|
|
751
|
+
zs : `float`
|
|
752
|
+
source redshifts
|
|
753
|
+
get_attribute : `bool`
|
|
754
|
+
if True, returns a function that can be used to sample lens redshifts
|
|
755
|
+
|
|
756
|
+
Returns
|
|
757
|
+
-------
|
|
758
|
+
zs : `float: array`
|
|
759
|
+
lens redshifts
|
|
760
|
+
"""
|
|
761
|
+
|
|
762
|
+
identifier_dict = {'name': "intrinsic_lens_redshift"}
|
|
763
|
+
identifier_dict['z_min'] = self.z_min
|
|
764
|
+
identifier_dict['z_max'] = self.z_max
|
|
765
|
+
identifier_dict['cosmology'] = self.cosmo
|
|
766
|
+
identifier_dict['velocity_dispersion'] = self.lens_param_samplers_params['velocity_dispersion']
|
|
767
|
+
if identifier_dict['velocity_dispersion']: # if velocity_dispersion is not None
|
|
768
|
+
identifier_dict['velocity_dispersion']['name'] = str(self.lens_param_samplers['velocity_dispersion'])
|
|
769
|
+
|
|
770
|
+
identifier_dict['resolution'] = 500
|
|
771
|
+
# param_dict = self.available_lens_prior_list_and_its_params["lens_redshift"]["intrinsic_lens_redshift"]
|
|
772
|
+
# if param_dict:
|
|
773
|
+
# param_dict.update(kwargs)
|
|
774
|
+
# else:
|
|
775
|
+
# param_dict = kwargs
|
|
776
|
+
# identifier_dict.update(param_dict)
|
|
777
|
+
|
|
778
|
+
_, it_exist = interpolator_pickle_path(
|
|
779
|
+
param_dict_given=identifier_dict,
|
|
780
|
+
directory=self.directory,
|
|
781
|
+
sub_directory="lens_redshift",
|
|
782
|
+
interpolator_name=identifier_dict['name'],
|
|
783
|
+
)
|
|
784
|
+
|
|
785
|
+
create_new = self.create_new_interpolator["lens_redshift"]["create_new"]
|
|
786
|
+
if not it_exist or create_new:
|
|
787
|
+
z_min = 0.001 if self.z_min==0 else self.z_min
|
|
788
|
+
z_max = self.z_max
|
|
789
|
+
zl_array = np.linspace(z_min, z_max, identifier_dict['resolution'])
|
|
790
|
+
integrand = lambda sigma, z: self.velocity_dispersion.function(np.array([sigma]), np.array([z]))[0]*self.differential_comoving_volume.function(np.array([z]))[0]
|
|
791
|
+
# integral = [quad(integrand, 10., 420., args=(z))[0] for z in zl_array]
|
|
792
|
+
integral = [quad(integrand, identifier_dict['velocity_dispersion']['sigma_min'], identifier_dict['velocity_dispersion']['sigma_max'], args=(z))[0] for z in zl_array]
|
|
793
|
+
else:
|
|
794
|
+
zl_array = None
|
|
795
|
+
integral=None
|
|
796
|
+
|
|
797
|
+
zl_object = FunctionConditioning(
|
|
798
|
+
function=integral,
|
|
799
|
+
x_array=zl_array,
|
|
800
|
+
param_dict_given=identifier_dict,
|
|
801
|
+
directory=self.directory,
|
|
802
|
+
sub_directory="lens_redshift",
|
|
803
|
+
name=identifier_dict['name'],
|
|
804
|
+
create_new=create_new,
|
|
805
|
+
create_function_inverse=False,
|
|
806
|
+
create_function=True,
|
|
807
|
+
create_pdf=True,
|
|
808
|
+
create_rvs=True,
|
|
809
|
+
callback='rvs',
|
|
810
|
+
)
|
|
811
|
+
|
|
812
|
+
return zl_object if get_attribute else zl_object(size)
|
|
813
|
+
|
|
814
|
+
def lens_redshift_multiprocessing(self, zl_scaled2d, zs1d):
|
|
815
|
+
"""
|
|
816
|
+
Compute the lens redshift distribution using multiprocessing.
|
|
817
|
+
|
|
818
|
+
Parameters
|
|
819
|
+
----------
|
|
820
|
+
zl_scaled2d : array_like
|
|
821
|
+
2D array of lens redshifts, scaled by the source redshift.
|
|
822
|
+
zs1d : array_like
|
|
823
|
+
1D array of source redshifts.
|
|
824
|
+
zl_distribution_name : str
|
|
825
|
+
Name of the lens redshift distribution to compute.
|
|
826
|
+
|
|
827
|
+
Returns
|
|
828
|
+
-------
|
|
829
|
+
density_array : array_like
|
|
830
|
+
2D array of the lens redshift distribution.
|
|
306
831
|
"""
|
|
832
|
+
|
|
833
|
+
sigma_args = self.lens_param_samplers_params["velocity_dispersion"]
|
|
834
|
+
sigma_args = [
|
|
835
|
+
sigma_args["sigma_min"],
|
|
836
|
+
sigma_args["sigma_max"],
|
|
837
|
+
sigma_args["alpha"],
|
|
838
|
+
sigma_args["beta"],
|
|
839
|
+
sigma_args["phistar"],
|
|
840
|
+
sigma_args["sigmastar"],
|
|
841
|
+
]
|
|
842
|
+
# 3. q; q_rvs = self.axis_ratio.rvs
|
|
843
|
+
try:
|
|
844
|
+
q_args = [
|
|
845
|
+
np.array(self.axis_ratio.cdf_values),
|
|
846
|
+
np.array(self.axis_ratio.x_array),
|
|
847
|
+
np.array(self.axis_ratio.conditioned_y_array),
|
|
848
|
+
]
|
|
849
|
+
except:
|
|
850
|
+
# SIS case
|
|
851
|
+
q_args = [
|
|
852
|
+
self.axis_ratio.info["q_min"],
|
|
853
|
+
self.axis_ratio.info["q_max"],
|
|
854
|
+
]
|
|
855
|
+
|
|
856
|
+
# 4. Da; Da_function = self.angular_diameter_distance.function
|
|
857
|
+
Da_args = [
|
|
858
|
+
np.array(self.angular_diameter_distance.function_spline),
|
|
859
|
+
np.array(self.angular_diameter_distance.x_array),
|
|
860
|
+
]
|
|
861
|
+
|
|
862
|
+
# 5. dVcdz; dVcdz_function = self.differential_comoving_volume.function
|
|
863
|
+
dVcdz_args = [
|
|
864
|
+
np.array(self.differential_comoving_volume.function_spline),
|
|
865
|
+
np.array(self.differential_comoving_volume.x_array),
|
|
866
|
+
]
|
|
867
|
+
|
|
868
|
+
# 6. idx; index to order the results
|
|
869
|
+
idx = np.arange(len(zs1d))
|
|
870
|
+
|
|
871
|
+
# 7. cross section
|
|
872
|
+
# cs_fn = self.cross_section_function
|
|
873
|
+
cs_args = [
|
|
874
|
+
self.nbrs,
|
|
875
|
+
np.array(self.values),
|
|
876
|
+
np.array(self.cross_section_spline),
|
|
877
|
+
np.array(self.sis_area_array),
|
|
878
|
+
]
|
|
879
|
+
|
|
880
|
+
# 8. phi; axis_rotation_angle = self.axis_rotation_angle.rvs
|
|
881
|
+
phi_args = self.lens_param_samplers_params["axis_rotation_angle"]
|
|
882
|
+
phi_args = [
|
|
883
|
+
phi_args["phi_min"],
|
|
884
|
+
phi_args["phi_max"],
|
|
885
|
+
]
|
|
886
|
+
|
|
887
|
+
# 9. shear; external_shear = self.external_shear.rvs
|
|
888
|
+
shear_args = self.lens_param_samplers_params["external_shear"]
|
|
889
|
+
shear_args = [
|
|
890
|
+
shear_args['mean'],
|
|
891
|
+
shear_args['std'],
|
|
892
|
+
]
|
|
893
|
+
|
|
894
|
+
# 10. slope; density_profile_slope = self.density_profile_slope.rvs
|
|
895
|
+
slope_args = self.lens_param_samplers_params["density_profile_slope"]
|
|
896
|
+
slope_args = [
|
|
897
|
+
slope_args['mean'],
|
|
898
|
+
slope_args['std'],
|
|
899
|
+
]
|
|
900
|
+
|
|
901
|
+
input_params = np.array([(zs1d[i], zl_scaled2d[i], sigma_args, q_args, Da_args, dVcdz_args, idx[i], cs_args, phi_args, shear_args, slope_args) for i in range(len(zs1d))], dtype=object)
|
|
902
|
+
|
|
903
|
+
print("Computing lens redshift distribution with multiprocessing...")
|
|
904
|
+
# with tqdm
|
|
905
|
+
mp_fn = self._helper_sl_disribution_mp
|
|
906
|
+
density_array = np.zeros_like(zl_scaled2d)
|
|
907
|
+
with Pool(processes=self.npool) as pool:
|
|
908
|
+
for result in tqdm(
|
|
909
|
+
pool.imap_unordered(mp_fn, input_params),
|
|
910
|
+
total=len(zs1d),
|
|
911
|
+
ncols=100,
|
|
912
|
+
disable=False,
|
|
913
|
+
):
|
|
914
|
+
# print(result)
|
|
915
|
+
(
|
|
916
|
+
iter_i,
|
|
917
|
+
density_,
|
|
918
|
+
) = result
|
|
919
|
+
|
|
920
|
+
density_array[iter_i] = density_
|
|
921
|
+
|
|
922
|
+
# # without multiprocessing, just for loop with tqdm
|
|
923
|
+
# density_array = np.zeros_like(zl_scaled2d)
|
|
924
|
+
# for i in range(len(zs1d)):
|
|
925
|
+
# iter_i, density_ = mp_fn(input_params[i])
|
|
926
|
+
# density_array[iter_i] = density_
|
|
927
|
+
# except:
|
|
928
|
+
# return input_params
|
|
929
|
+
|
|
930
|
+
return density_array
|
|
931
|
+
|
|
932
|
+
def axis_rotation_angle_uniform(self, size, get_attribute=False, **kwargs):
|
|
933
|
+
"""
|
|
934
|
+
Function to sample the axis rotation angle of the elliptical lens galaxy from a uniform distribution.
|
|
935
|
+
|
|
936
|
+
Parameters
|
|
937
|
+
----------
|
|
938
|
+
size : `int`
|
|
939
|
+
number of lens parameters to sample
|
|
940
|
+
get_attribute : `bool`
|
|
941
|
+
if True, returns a function that can be called with size as input
|
|
307
942
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
943
|
+
Returns
|
|
944
|
+
-------
|
|
945
|
+
phi : `numpy.ndarray`
|
|
946
|
+
axis rotation angle of the elliptical lens galaxy
|
|
947
|
+
|
|
948
|
+
Examples
|
|
949
|
+
--------
|
|
312
950
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
951
|
+
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
952
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(axis_rotation_angle="axis_rotation_angle_uniform"))
|
|
953
|
+
>>> print(od.axis_rotation_angle_uniform(size=10))
|
|
954
|
+
"""
|
|
316
955
|
|
|
956
|
+
identifier_dict = {'name': "axis_rotation_angle_uniform"}
|
|
957
|
+
param_dict = self.available_lens_prior_list_and_its_params["axis_rotation_angle"]["axis_rotation_angle_uniform"]
|
|
958
|
+
if param_dict:
|
|
959
|
+
param_dict.update(kwargs)
|
|
317
960
|
else:
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
else:
|
|
342
|
-
self.sample_axis_ratio = self.sampler_priors["axis_ratio"]
|
|
961
|
+
param_dict = kwargs
|
|
962
|
+
identifier_dict.update(param_dict)
|
|
963
|
+
|
|
964
|
+
low = param_dict["phi_min"]
|
|
965
|
+
high = param_dict["phi_max"]
|
|
966
|
+
phi_rvs = njit(lambda size: np.random.uniform(
|
|
967
|
+
low=low,
|
|
968
|
+
high=high,
|
|
969
|
+
size=size,
|
|
970
|
+
))
|
|
971
|
+
if param_dict["phi_max"] == param_dict["phi_min"]:
|
|
972
|
+
phi_pdf = lambda phi: 1. if phi == param_dict["phi_min"] else 0.
|
|
973
|
+
else:
|
|
974
|
+
phi_pdf = lambda phi: 1/(param_dict["phi_max"]-param_dict["phi_min"])
|
|
975
|
+
|
|
976
|
+
phi_object =FunctionConditioning(
|
|
977
|
+
function=None,
|
|
978
|
+
x_array=None,
|
|
979
|
+
param_dict_given=param_dict,
|
|
980
|
+
create_rvs=phi_rvs,
|
|
981
|
+
create_pdf=phi_pdf,
|
|
982
|
+
callback='rvs',
|
|
983
|
+
)
|
|
343
984
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
name=tau_name,
|
|
357
|
-
x = x_,
|
|
358
|
-
pdf_func= pdf_func_,
|
|
359
|
-
conditioned_y=None,
|
|
360
|
-
dimension=dimension_,
|
|
361
|
-
category=category_,
|
|
362
|
-
create_new=create_new_,
|
|
363
|
-
)
|
|
985
|
+
return phi_object if get_attribute else phi_object.rvs(size)
|
|
986
|
+
|
|
987
|
+
def axis_ratio_uniform(self, size, get_attribute=False, **kwargs):
|
|
988
|
+
"""
|
|
989
|
+
Function to sample the axis ratio of the elliptical lens galaxy from a uniform distribution.
|
|
990
|
+
|
|
991
|
+
Parameters
|
|
992
|
+
----------
|
|
993
|
+
size : `int`
|
|
994
|
+
number of lens parameters to sample
|
|
995
|
+
get_attribute : `bool`
|
|
996
|
+
if True, returns a function that can be called with size as input
|
|
364
997
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
998
|
+
Returns
|
|
999
|
+
-------
|
|
1000
|
+
q : `numpy.ndarray`
|
|
1001
|
+
axis ratio of the elliptical lens galaxy
|
|
1002
|
+
|
|
1003
|
+
Examples
|
|
1004
|
+
--------
|
|
368
1005
|
|
|
369
|
-
|
|
1006
|
+
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
1007
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(axis_ratio="axis_ratio_uniform"))
|
|
1008
|
+
>>> print(od.axis_ratio_uniform(size=10))
|
|
370
1009
|
"""
|
|
371
|
-
|
|
1010
|
+
|
|
1011
|
+
identifier_dict = {'name': "axis_ratio_uniform"}
|
|
1012
|
+
param_dict = self.available_lens_prior_list_and_its_params["axis_ratio"]["axis_ratio_uniform"]
|
|
1013
|
+
if param_dict:
|
|
1014
|
+
param_dict.update(kwargs)
|
|
1015
|
+
else:
|
|
1016
|
+
param_dict = kwargs
|
|
1017
|
+
identifier_dict.update(param_dict)
|
|
1018
|
+
|
|
1019
|
+
low = param_dict["q_min"]
|
|
1020
|
+
high = param_dict["q_max"]
|
|
1021
|
+
q_rvs = njit(lambda size: np.random.uniform(
|
|
1022
|
+
low=low,
|
|
1023
|
+
high=high,
|
|
1024
|
+
size=size,
|
|
1025
|
+
))
|
|
1026
|
+
if param_dict["q_max"] == param_dict["q_min"]:
|
|
1027
|
+
q_pdf = lambda q: 1. if q == param_dict["q_min"] else 0.
|
|
1028
|
+
else:
|
|
1029
|
+
q_pdf = lambda q: 1/(param_dict["q_max"]-param_dict["q_min"])
|
|
1030
|
+
|
|
1031
|
+
q_object =FunctionConditioning(
|
|
1032
|
+
function=None,
|
|
1033
|
+
x_array=None,
|
|
1034
|
+
param_dict_given=param_dict,
|
|
1035
|
+
create_rvs=q_rvs,
|
|
1036
|
+
create_pdf=q_pdf,
|
|
1037
|
+
callback='rvs',
|
|
1038
|
+
)
|
|
1039
|
+
|
|
1040
|
+
return q_object if get_attribute else q_object.rvs(size)
|
|
1041
|
+
|
|
1042
|
+
def external_shear_normal(self, size, get_attribute=False, **kwargs):
|
|
1043
|
+
"""
|
|
1044
|
+
Function to sample the external shear parameters from a normal distribution.
|
|
372
1045
|
|
|
373
1046
|
Parameters
|
|
374
1047
|
----------
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
q_min, q_max : `float`
|
|
378
|
-
minimum and maximum axis ratio
|
|
1048
|
+
size : `int`
|
|
1049
|
+
number of lens parameters to sample
|
|
379
1050
|
get_attribute : `bool`
|
|
380
|
-
if True, returns a function that can be
|
|
1051
|
+
if True, returns a function that can be called with size as input
|
|
381
1052
|
|
|
382
1053
|
Returns
|
|
383
1054
|
-------
|
|
384
|
-
|
|
385
|
-
|
|
1055
|
+
gamma_1 : `numpy.ndarray`
|
|
1056
|
+
shear component in the x-direction
|
|
1057
|
+
gamma_2 : `numpy.ndarray`
|
|
1058
|
+
shear component in the y-direction
|
|
386
1059
|
|
|
387
1060
|
Examples
|
|
388
1061
|
--------
|
|
1062
|
+
|
|
389
1063
|
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
390
|
-
>>> od = OpticalDepth(
|
|
391
|
-
>>> print(od.
|
|
1064
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(external_shear="external_shear_normal"))
|
|
1065
|
+
>>> print(od.external_shear_normal(size=10))
|
|
392
1066
|
"""
|
|
393
1067
|
|
|
1068
|
+
identifier_dict = {'name': "external_shear_normal"}
|
|
1069
|
+
param = self.available_lens_prior_list_and_its_params["external_shear"]["external_shear_normal"]
|
|
394
1070
|
if param:
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
1071
|
+
param.update(kwargs)
|
|
1072
|
+
else:
|
|
1073
|
+
param = kwargs
|
|
1074
|
+
identifier_dict.update(param)
|
|
1075
|
+
|
|
1076
|
+
mean = param["mean"]
|
|
1077
|
+
std = param["std"]
|
|
1078
|
+
shear_rvs = njit(lambda size: np.random.normal(
|
|
1079
|
+
loc=mean,
|
|
1080
|
+
scale=std,
|
|
1081
|
+
size=(2,size),
|
|
1082
|
+
))
|
|
1083
|
+
shear_pdf = njit(lambda shear1, shear2: normal_pdf_2d(
|
|
1084
|
+
x=shear1,
|
|
1085
|
+
y=shear2,
|
|
1086
|
+
mean_x=mean,
|
|
1087
|
+
mean_y=mean,
|
|
1088
|
+
std_x=std,
|
|
1089
|
+
std_y=std,
|
|
1090
|
+
))
|
|
1091
|
+
|
|
1092
|
+
shear_object =FunctionConditioning(
|
|
1093
|
+
function=None,
|
|
1094
|
+
x_array=None,
|
|
1095
|
+
param_dict_given=identifier_dict,
|
|
1096
|
+
create_rvs=shear_rvs,
|
|
1097
|
+
create_pdf=shear_pdf,
|
|
1098
|
+
callback='rvs',
|
|
1099
|
+
)
|
|
1100
|
+
|
|
1101
|
+
return shear_object if get_attribute else shear_object.rvs(size)
|
|
1102
|
+
|
|
1103
|
+
def external_shear_numerical_hemanta(self, size, get_attribute=False, **kwargs):
|
|
1104
|
+
"""
|
|
1105
|
+
Function to sample the external shear parameters from a normal distribution.
|
|
1106
|
+
|
|
1107
|
+
Parameters
|
|
1108
|
+
----------
|
|
1109
|
+
size : `int`
|
|
1110
|
+
number of lens parameters to sample
|
|
1111
|
+
get_attribute : `bool`
|
|
1112
|
+
if True, returns a function that can be called with size as input
|
|
1113
|
+
|
|
1114
|
+
Returns
|
|
1115
|
+
-------
|
|
1116
|
+
gamma_1 : `numpy.ndarray`
|
|
1117
|
+
shear component in the x-direction
|
|
1118
|
+
gamma_2 : `numpy.ndarray`
|
|
1119
|
+
shear component in the y-direction
|
|
1120
|
+
|
|
1121
|
+
Examples
|
|
1122
|
+
--------
|
|
1123
|
+
|
|
1124
|
+
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
1125
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(external_shear="external_shear_normal"))
|
|
1126
|
+
>>> print(od.external_shear_normal(size=10))
|
|
1127
|
+
"""
|
|
1128
|
+
|
|
1129
|
+
identifier_dict = {
|
|
1130
|
+
'name': 'external_shear_numerical_hemanta',
|
|
1131
|
+
'external_shear_normal': {'mean': 0., 'std': 0.05},
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
gamma1, gamma2 = load_txt_from_module('ler', 'lens_galaxy_population.lens_param_data', 'external_shear_sl.txt')
|
|
1135
|
+
|
|
1136
|
+
shear_object =FunctionConditioning(
|
|
1137
|
+
x_array=gamma1,
|
|
1138
|
+
y_array=gamma2,
|
|
1139
|
+
gaussian_kde=True,
|
|
1140
|
+
param_dict_given=identifier_dict,
|
|
1141
|
+
create_rvs=True,
|
|
1142
|
+
create_pdf=True,
|
|
1143
|
+
callback='rvs',
|
|
1144
|
+
)
|
|
1145
|
+
|
|
1146
|
+
return shear_object if get_attribute else shear_object.rvs(size)
|
|
1147
|
+
|
|
1148
|
+
def density_profile_slope_normal(self, size, get_attribute=False, **kwargs):
|
|
1149
|
+
"""
|
|
1150
|
+
Function to sample the lens galaxy density profile slope with normal distribution.
|
|
1151
|
+
|
|
1152
|
+
Parameters
|
|
1153
|
+
----------
|
|
1154
|
+
size : `int`
|
|
1155
|
+
number of lens parameters to sample
|
|
1156
|
+
get_attribute : `bool`
|
|
1157
|
+
if True, returns a function that can be used to sample velocity dispersion
|
|
1158
|
+
**kwargs : `dict`
|
|
1159
|
+
additional parameters to be passed to the function,
|
|
1160
|
+
e.g. `mean` and `std` for the normal distribution
|
|
1161
|
+
|
|
1162
|
+
Returns
|
|
1163
|
+
-------
|
|
1164
|
+
slope : `float`
|
|
1165
|
+
density profile slope of the lens galaxy
|
|
1166
|
+
|
|
1167
|
+
Examples
|
|
1168
|
+
--------
|
|
1169
|
+
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
1170
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(density_profile_slope="density_profile_slope_normal"))
|
|
1171
|
+
>>> print(od.density_profile_slope_normal(size=10))
|
|
1172
|
+
"""
|
|
1173
|
+
|
|
1174
|
+
identifier_dict = {'name': "density_profile_slope_normal"}
|
|
1175
|
+
|
|
1176
|
+
param = self.available_lens_prior_list_and_its_params["density_profile_slope"]["density_profile_slope_normal"]
|
|
1177
|
+
if param:
|
|
1178
|
+
param.update(kwargs)
|
|
1179
|
+
else:
|
|
1180
|
+
param = kwargs
|
|
1181
|
+
identifier_dict.update(param)
|
|
1182
|
+
|
|
1183
|
+
mean = param["mean"]
|
|
1184
|
+
std = param["std"]
|
|
1185
|
+
slope_rvs = njit(lambda size: np.random.normal(
|
|
1186
|
+
loc=mean,
|
|
1187
|
+
scale=std,
|
|
1188
|
+
size=size,
|
|
1189
|
+
))
|
|
1190
|
+
slope_pdf = njit(lambda slope: normal_pdf(
|
|
1191
|
+
x=slope,
|
|
1192
|
+
mean=mean,
|
|
1193
|
+
std=std,
|
|
1194
|
+
))
|
|
1195
|
+
|
|
1196
|
+
slope_object =FunctionConditioning(
|
|
1197
|
+
function=None,
|
|
1198
|
+
x_array=None,
|
|
1199
|
+
param_dict_given=identifier_dict,
|
|
1200
|
+
create_rvs=slope_rvs,
|
|
1201
|
+
create_pdf=slope_pdf,
|
|
1202
|
+
callback='rvs',
|
|
1203
|
+
)
|
|
1204
|
+
|
|
398
1205
|
if get_attribute:
|
|
399
|
-
return
|
|
1206
|
+
return slope_object
|
|
400
1207
|
else:
|
|
401
|
-
return
|
|
1208
|
+
return slope_rvs(size)
|
|
402
1209
|
|
|
403
|
-
def
|
|
1210
|
+
def density_profile_slope_numerical_hemanta(self, size, get_attribute=False, **kwargs):
|
|
1211
|
+
"""
|
|
1212
|
+
Function to sample the lens galaxy density profile slope with normal distribution.
|
|
1213
|
+
|
|
1214
|
+
Parameters
|
|
1215
|
+
----------
|
|
1216
|
+
size : `int`
|
|
1217
|
+
number of lens parameters to sample
|
|
1218
|
+
get_attribute : `bool`
|
|
1219
|
+
if True, returns a function that can be used to sample velocity dispersion
|
|
1220
|
+
**kwargs : `dict`
|
|
1221
|
+
additional parameters to be passed to the function,
|
|
1222
|
+
e.g. `mean` and `std` for the normal distribution
|
|
1223
|
+
|
|
1224
|
+
Returns
|
|
1225
|
+
-------
|
|
1226
|
+
slope : `float`
|
|
1227
|
+
density profile slope of the lens galaxy
|
|
1228
|
+
|
|
1229
|
+
Examples
|
|
1230
|
+
--------
|
|
1231
|
+
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
1232
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(density_profile_slope="density_profile_slope_normal"))
|
|
1233
|
+
>>> print(od.density_profile_slope_normal(size=10))
|
|
1234
|
+
"""
|
|
1235
|
+
|
|
1236
|
+
identifier_dict = {
|
|
1237
|
+
'name': 'density_profile_slope_numerical_hemanta',
|
|
1238
|
+
'density_profile_slope_normal': {'mean': 1.99, 'std': 0.149},
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
gamma = load_txt_from_module('ler', 'lens_galaxy_population.lens_param_data', 'density_profile_slope_sl.txt')
|
|
1242
|
+
|
|
1243
|
+
slope_object =FunctionConditioning(
|
|
1244
|
+
x_array=gamma,
|
|
1245
|
+
gaussian_kde=True,
|
|
1246
|
+
param_dict_given=identifier_dict,
|
|
1247
|
+
create_rvs=True,
|
|
1248
|
+
create_pdf=True,
|
|
1249
|
+
callback='rvs',
|
|
1250
|
+
)
|
|
1251
|
+
|
|
1252
|
+
return slope_object if get_attribute else slope_object.rvs(size)
|
|
1253
|
+
|
|
1254
|
+
def lens_redshift_SDSS_catalogue_sis(self, size, zs, get_attribute=False, **kwargs):
|
|
404
1255
|
"""
|
|
405
|
-
Function to sample
|
|
1256
|
+
Function to sample lens redshifts, conditioned on the lens being strongly lensed
|
|
406
1257
|
|
|
407
1258
|
Parameters
|
|
408
1259
|
----------
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
q_min, q_max : `float`
|
|
412
|
-
minimum and maximum axis ratio
|
|
1260
|
+
zs : `float`
|
|
1261
|
+
source redshifts
|
|
413
1262
|
get_attribute : `bool`
|
|
414
|
-
|
|
1263
|
+
If True, returns a function that can be called with zs as input
|
|
415
1264
|
|
|
416
1265
|
Returns
|
|
417
1266
|
-------
|
|
418
|
-
|
|
419
|
-
|
|
1267
|
+
zl : `float`
|
|
1268
|
+
lens redshifts
|
|
420
1269
|
|
|
421
1270
|
Examples
|
|
422
1271
|
--------
|
|
423
|
-
>>> from ler.lens_galaxy_population import
|
|
424
|
-
>>>
|
|
425
|
-
>>>
|
|
1272
|
+
>>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
|
|
1273
|
+
>>> lens = LensGalaxyParameterDistribution()
|
|
1274
|
+
>>> lens.lens_redshift_SDSS_catalogue_sis(zs=1.0)
|
|
426
1275
|
"""
|
|
427
1276
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
1277
|
+
# # Old way
|
|
1278
|
+
# splineDc = self.comoving_distance.function_spline # spline coefficients for the comoving distance and redshifts
|
|
1279
|
+
# splineDcInv = self.comoving_distance.function_inverse_spline # spline coefficients for the redshifts and comoving distance
|
|
1280
|
+
# u = np.linspace(0, 1, 500)
|
|
1281
|
+
# 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)
|
|
1282
|
+
# zs = np.array([zs]).reshape(-1)
|
|
1283
|
+
|
|
1284
|
+
# New way
|
|
1285
|
+
identifier_dict = {'name': "lens_redshift_SDSS_catalogue_sis"}
|
|
1286
|
+
identifier_dict['z_min'] = self.z_min
|
|
1287
|
+
identifier_dict['z_max'] = self.z_max
|
|
1288
|
+
identifier_dict['cosmology'] = LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
|
|
1289
|
+
identifier_dict['velocity_dispersion'] = dict(sigma_min = 10., sigma_max = 420., alpha = 2.32, beta = 2.67, phistar = 8.0e-3*self.cosmo.h**3, sigmastar = 161.0)
|
|
1290
|
+
identifier_dict['resolution'] = self.create_new_interpolator["lens_redshift"]["resolution"]
|
|
1291
|
+
param_dict = self.available_lens_prior_list_and_its_params["lens_redshift"]["lens_redshift_SDSS_catalogue_sis"]
|
|
1292
|
+
if param_dict:
|
|
1293
|
+
param_dict.update(kwargs)
|
|
1294
|
+
else:
|
|
1295
|
+
param_dict = kwargs
|
|
1296
|
+
identifier_dict.update(param_dict)
|
|
435
1297
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
1298
|
+
zl_resolution = identifier_dict['resolution']
|
|
1299
|
+
x_array = np.linspace(0., 1., zl_resolution)
|
|
1300
|
+
pdf_ = lambda x: 30* x**2 * (1-x)**2 # Haris et al. 2018 (A7)
|
|
439
1301
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
name="axis_ratio_spline_coeff",
|
|
445
|
-
x = q,
|
|
446
|
-
pdf_func=None,
|
|
447
|
-
y=pdf,
|
|
448
|
-
conditioned_y=None,
|
|
449
|
-
dimension=1,
|
|
450
|
-
category="function",
|
|
451
|
-
create_new=True,
|
|
452
|
-
)
|
|
453
|
-
|
|
454
|
-
resolution = self.c_n_i["axis_ratio"]["resolution"]
|
|
455
|
-
create_new = self.c_n_i["axis_ratio"]["create_new"]
|
|
456
|
-
q_array = np.linspace(q_min, q_max, resolution)
|
|
457
|
-
pdf_array = cubic_spline_interpolator(q_array, spline_coeff[0], spline_coeff[1])
|
|
458
|
-
|
|
459
|
-
q_inv_cdf = interpolator_from_pickle(
|
|
460
|
-
param_dict_given = dict(parameter="axis_ratio", pdf="Padilla and Strauss 2008 distribution for axis ratio", q_min=q_min, q_max=q_max, resolution=resolution),
|
|
1302
|
+
zl_object = FunctionConditioning(
|
|
1303
|
+
function=pdf_,
|
|
1304
|
+
x_array=x_array,
|
|
1305
|
+
param_dict_given=identifier_dict,
|
|
461
1306
|
directory=self.directory,
|
|
462
|
-
sub_directory="
|
|
463
|
-
name=
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
create_new=create_new,
|
|
1307
|
+
sub_directory="lens_redshift",
|
|
1308
|
+
name=identifier_dict['name'],
|
|
1309
|
+
create_new=self.create_new_interpolator["lens_redshift"]["create_new"],
|
|
1310
|
+
create_function_inverse=False,
|
|
1311
|
+
create_function=True,
|
|
1312
|
+
create_pdf=True,
|
|
1313
|
+
create_rvs=True,
|
|
1314
|
+
callback='rvs',
|
|
471
1315
|
)
|
|
472
1316
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
1317
|
+
cdf_values_zl = zl_object.cdf_values
|
|
1318
|
+
function_spline_zl = zl_object.function_spline
|
|
1319
|
+
pdf_norm_const = zl_object.pdf_norm_const
|
|
1320
|
+
x_array_zl = zl_object.x_array
|
|
1321
|
+
|
|
1322
|
+
spline_Dc = self.comoving_distance.function_spline
|
|
1323
|
+
x_array_Dc = self.comoving_distance.x_array
|
|
1324
|
+
inverse_spline_Dc = self.comoving_distance.function_inverse_spline
|
|
1325
|
+
z_array_Dc = self.comoving_distance.z_array
|
|
1326
|
+
|
|
1327
|
+
@njit
|
|
1328
|
+
def zl_rvs(size, zs):
|
|
1329
|
+
r = inverse_transform_sampler(size, cdf_values_zl, x_array_zl)
|
|
1330
|
+
zs_Dc = cubic_spline_interpolator(zs, spline_Dc, x_array_Dc)
|
|
1331
|
+
zl_Dc = zs_Dc * r
|
|
1332
|
+
return cubic_spline_interpolator(zl_Dc, inverse_spline_Dc, z_array_Dc)
|
|
1333
|
+
|
|
1334
|
+
@njit
|
|
1335
|
+
def zl_pdf(zl, zs):
|
|
1336
|
+
r = zl / zs
|
|
1337
|
+
return cubic_spline_interpolator(r, function_spline_zl, x_array_zl)/pdf_norm_const
|
|
1338
|
+
|
|
1339
|
+
@njit
|
|
1340
|
+
def zl_function(zl, zs):
|
|
1341
|
+
r = zl / zs
|
|
1342
|
+
return cubic_spline_interpolator(r, function_spline_zl, x_array_zl)
|
|
1343
|
+
|
|
1344
|
+
zl_object.function = zl_function
|
|
1345
|
+
zl_object.pdf = zl_pdf
|
|
1346
|
+
zl_object.rvs = zl_rvs
|
|
481
1347
|
|
|
482
|
-
|
|
1348
|
+
return zl_object if get_attribute else zl_object.rvs(size, zs)
|
|
1349
|
+
|
|
1350
|
+
|
|
1351
|
+
def velocity_dispersion_gengamma(self, size, get_attribute=False, **kwargs):
|
|
483
1352
|
"""
|
|
484
1353
|
Function to sample velocity dispersion from gengamma distribution
|
|
485
1354
|
|
|
@@ -504,20 +1373,50 @@ class OpticalDepth():
|
|
|
504
1373
|
Examples
|
|
505
1374
|
--------
|
|
506
1375
|
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
507
|
-
>>> od = OpticalDepth(
|
|
508
|
-
>>> print(od.
|
|
509
|
-
|
|
1376
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(velocity_dispersion="velocity_dispersion_gengamma"), lens_param_samplers_params=dict(velocity_dispersion=dict(a=2.32 / 2.67, c=2.67)))
|
|
1377
|
+
>>> print(od.velocity_dispersion(size=10))
|
|
510
1378
|
"""
|
|
511
1379
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
1380
|
+
identifier_dict = {'name': "velocity_dispersion_gengamma"}
|
|
1381
|
+
identifier_dict['z_min'] = self.z_min
|
|
1382
|
+
identifier_dict['z_max'] = self.z_max
|
|
1383
|
+
identifier_dict['cosmology'] = self.cosmo
|
|
1384
|
+
identifier_dict['resolution'] = self.create_new_interpolator["velocity_dispersion"]["resolution"]
|
|
1385
|
+
param_dict = self.available_lens_prior_list_and_its_params["velocity_dispersion"]["velocity_dispersion_gengamma"]
|
|
1386
|
+
if param_dict:
|
|
1387
|
+
param_dict.update(kwargs)
|
|
518
1388
|
else:
|
|
519
|
-
|
|
520
|
-
|
|
1389
|
+
param_dict = kwargs
|
|
1390
|
+
identifier_dict.update(param_dict)
|
|
1391
|
+
|
|
1392
|
+
# setting up inputs for the interpolator
|
|
1393
|
+
sigma_array = np.linspace(
|
|
1394
|
+
identifier_dict['sigma_min'],
|
|
1395
|
+
identifier_dict['sigma_max'],
|
|
1396
|
+
identifier_dict["resolution"]
|
|
1397
|
+
)
|
|
1398
|
+
pdf_func_ = lambda sigma_: gengamma.pdf(
|
|
1399
|
+
sigma_/identifier_dict['sigmastar'],
|
|
1400
|
+
a= identifier_dict['alpha']/identifier_dict['beta'],
|
|
1401
|
+
c= identifier_dict['beta'],
|
|
1402
|
+
) # gengamma pdf
|
|
1403
|
+
|
|
1404
|
+
sigma_object = FunctionConditioning(
|
|
1405
|
+
function=pdf_func_,
|
|
1406
|
+
x_array=sigma_array,
|
|
1407
|
+
param_dict_given=identifier_dict,
|
|
1408
|
+
directory=self.directory,
|
|
1409
|
+
sub_directory="velocity_dispersion",
|
|
1410
|
+
name=identifier_dict['name'],
|
|
1411
|
+
create_new=self.create_new_interpolator["velocity_dispersion"]['create_new'],
|
|
1412
|
+
create_function_inverse=False,
|
|
1413
|
+
create_function=True,
|
|
1414
|
+
create_pdf=True,
|
|
1415
|
+
create_rvs=True,
|
|
1416
|
+
callback='rvs',
|
|
1417
|
+
)
|
|
1418
|
+
|
|
1419
|
+
return sigma_object if get_attribute else sigma_object.rvs(size)
|
|
521
1420
|
|
|
522
1421
|
def velocity_dispersion_bernardi(self, size, get_attribute=False, **kwargs):
|
|
523
1422
|
"""
|
|
@@ -538,16 +1437,53 @@ class OpticalDepth():
|
|
|
538
1437
|
Examples
|
|
539
1438
|
--------
|
|
540
1439
|
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
541
|
-
>>> od = OpticalDepth(
|
|
542
|
-
>>> print(od.
|
|
1440
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(velocity_dispersion="velocity_dispersion_bernardi"))
|
|
1441
|
+
>>> print(od.velocity_dispersion(size=10))
|
|
543
1442
|
"""
|
|
544
1443
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
1444
|
+
identifier_dict = {'name': "velocity_dispersion_bernardi"}
|
|
1445
|
+
identifier_dict['z_min'] = self.z_min
|
|
1446
|
+
identifier_dict['z_max'] = self.z_max
|
|
1447
|
+
identifier_dict['cosmology'] = self.cosmo
|
|
1448
|
+
identifier_dict['name'] = "velocity_dispersion_bernardi"
|
|
1449
|
+
identifier_dict['resolution'] = self.create_new_interpolator["velocity_dispersion"]["resolution"]
|
|
1450
|
+
param_dict = self.available_lens_prior_list_and_its_params["velocity_dispersion"]["velocity_dispersion_bernardi"]
|
|
1451
|
+
if param_dict:
|
|
1452
|
+
param_dict.update(kwargs)
|
|
549
1453
|
else:
|
|
550
|
-
|
|
1454
|
+
param_dict = kwargs
|
|
1455
|
+
identifier_dict.update(param_dict)
|
|
1456
|
+
|
|
1457
|
+
# setting up inputs for the interpolator
|
|
1458
|
+
sigma_array = np.linspace(
|
|
1459
|
+
identifier_dict['sigma_min'],
|
|
1460
|
+
identifier_dict['sigma_max'],
|
|
1461
|
+
identifier_dict["resolution"]
|
|
1462
|
+
)
|
|
1463
|
+
number_density_function = lambda sigma: phi_loc_bernardi(
|
|
1464
|
+
sigma,
|
|
1465
|
+
alpha=self.lens_param_samplers_params["velocity_dispersion"]['alpha'],
|
|
1466
|
+
beta=self.lens_param_samplers_params["velocity_dispersion"]['beta'],
|
|
1467
|
+
phistar=self.lens_param_samplers_params["velocity_dispersion"]['phistar'],
|
|
1468
|
+
sigmastar=self.lens_param_samplers_params["velocity_dispersion"]['sigmastar'],
|
|
1469
|
+
)
|
|
1470
|
+
|
|
1471
|
+
sigma_object = FunctionConditioning(
|
|
1472
|
+
function=number_density_function,
|
|
1473
|
+
x_array=sigma_array,
|
|
1474
|
+
param_dict_given=identifier_dict,
|
|
1475
|
+
directory=self.directory,
|
|
1476
|
+
sub_directory="velocity_dispersion",
|
|
1477
|
+
name=identifier_dict['name'],
|
|
1478
|
+
create_new=self.create_new_interpolator["velocity_dispersion"]['create_new'],
|
|
1479
|
+
create_function_inverse=False,
|
|
1480
|
+
create_function=True,
|
|
1481
|
+
create_pdf=True,
|
|
1482
|
+
create_rvs=True,
|
|
1483
|
+
callback='rvs',
|
|
1484
|
+
)
|
|
1485
|
+
|
|
1486
|
+
return sigma_object if get_attribute else sigma_object.rvs(size)
|
|
551
1487
|
|
|
552
1488
|
def velocity_dispersion_ewoud(self, size, zl, get_attribute=False, **kwargs):
|
|
553
1489
|
"""
|
|
@@ -570,27 +1506,125 @@ class OpticalDepth():
|
|
|
570
1506
|
Examples
|
|
571
1507
|
--------
|
|
572
1508
|
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
573
|
-
>>> od = OpticalDepth(
|
|
574
|
-
>>> print(od.
|
|
1509
|
+
>>> od = OpticalDepth(lens_param_samplers=dict(velocity_dispersion="velocity_dispersion_ewoud"))
|
|
1510
|
+
>>> print(od.velocity_dispersion(size=10, zl=0.5))
|
|
575
1511
|
"""
|
|
576
1512
|
|
|
577
|
-
|
|
578
|
-
z_min = self.z_min
|
|
579
|
-
|
|
580
|
-
|
|
1513
|
+
identifier_dict = {'name': "velocity_dispersion_ewoud"}
|
|
1514
|
+
identifier_dict['z_min'] = self.z_min
|
|
1515
|
+
identifier_dict['z_max'] = self.z_max
|
|
1516
|
+
identifier_dict['cosmology'] = self.cosmo
|
|
1517
|
+
identifier_dict['name'] = "velocity_dispersion_ewoud"
|
|
1518
|
+
identifier_dict['resolution'] = self.create_new_interpolator["velocity_dispersion"]["resolution"]
|
|
1519
|
+
param_dict = self.available_lens_prior_list_and_its_params["velocity_dispersion"]["velocity_dispersion_ewoud"].copy()
|
|
1520
|
+
if param_dict:
|
|
1521
|
+
param_dict.update(kwargs)
|
|
1522
|
+
else:
|
|
1523
|
+
param_dict = kwargs
|
|
1524
|
+
identifier_dict.update(param_dict)
|
|
1525
|
+
|
|
1526
|
+
# setting up inputs for the interpolator
|
|
1527
|
+
sigma_array = np.linspace(
|
|
1528
|
+
identifier_dict['sigma_min'],
|
|
1529
|
+
identifier_dict['sigma_max'],
|
|
1530
|
+
identifier_dict["resolution"]
|
|
1531
|
+
)
|
|
1532
|
+
number_density_function = lambda sigma, zl: phi(
|
|
1533
|
+
sigma,
|
|
1534
|
+
zl,
|
|
1535
|
+
alpha=self.lens_param_samplers_params["velocity_dispersion"]['alpha'],
|
|
1536
|
+
beta=self.lens_param_samplers_params["velocity_dispersion"]['beta'],
|
|
1537
|
+
phistar=self.lens_param_samplers_params["velocity_dispersion"]['phistar'],
|
|
1538
|
+
sigmastar=self.lens_param_samplers_params["velocity_dispersion"]['sigmastar'],
|
|
1539
|
+
)
|
|
581
1540
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
1541
|
+
zl_array = np.geomspace(self.z_min+0.001, self.z_max, 500) if self.z_min==0 else np.geomspace(self.z_min, self.z_max, 500)
|
|
1542
|
+
|
|
1543
|
+
sigma_object = FunctionConditioning(
|
|
1544
|
+
function=number_density_function,
|
|
1545
|
+
x_array=sigma_array,
|
|
1546
|
+
conditioned_y_array=zl_array,
|
|
1547
|
+
param_dict_given=identifier_dict,
|
|
1548
|
+
directory=self.directory,
|
|
1549
|
+
sub_directory="velocity_dispersion",
|
|
1550
|
+
name=identifier_dict['name'],
|
|
1551
|
+
create_new=self.create_new_interpolator["velocity_dispersion"]['create_new'],
|
|
1552
|
+
create_function_inverse=False,
|
|
1553
|
+
create_function=True,
|
|
1554
|
+
create_pdf=True,
|
|
1555
|
+
create_rvs=True,
|
|
1556
|
+
callback='rvs',
|
|
1557
|
+
)
|
|
587
1558
|
|
|
588
|
-
if get_attribute
|
|
589
|
-
|
|
1559
|
+
return sigma_object if get_attribute else sigma_object.rvs(size, zl)
|
|
1560
|
+
|
|
1561
|
+
##################
|
|
1562
|
+
# Lens functions #
|
|
1563
|
+
##################
|
|
1564
|
+
def optical_depth_numerical(self, zs, get_attribute=False, **kwargs):
|
|
1565
|
+
|
|
1566
|
+
identifier_dict = {'name': "optical_depth_numerical"}
|
|
1567
|
+
identifier_dict['resolution'] = self.create_new_interpolator["optical_depth"]["resolution"]
|
|
1568
|
+
identifier_dict['z_min'] = self.z_min
|
|
1569
|
+
identifier_dict['z_max'] = self.z_max
|
|
1570
|
+
identifier_dict['cosmology'] = self.cosmo
|
|
1571
|
+
identifier_dict['velocity_dispersion'] = self.lens_param_samplers_params['velocity_dispersion']
|
|
1572
|
+
if identifier_dict['velocity_dispersion']: # if velocity_dispersion is not None
|
|
1573
|
+
identifier_dict['velocity_dispersion']['name'] = str(self.lens_param_samplers['velocity_dispersion'])
|
|
1574
|
+
identifier_dict['axis_ratio'] = self.lens_param_samplers_params['axis_ratio']
|
|
1575
|
+
if identifier_dict['axis_ratio']: # if axis_ratio is not None
|
|
1576
|
+
identifier_dict['axis_ratio']['name'] = str(self.lens_param_samplers['axis_ratio'])
|
|
1577
|
+
identifier_dict['axis_rotation_angle'] = self.lens_param_samplers_params['axis_rotation_angle']
|
|
1578
|
+
if identifier_dict['axis_rotation_angle']: # if axis_rotation_angle is not None
|
|
1579
|
+
identifier_dict['axis_rotation_angle']['name'] = str(self.lens_param_samplers['axis_rotation_angle'])
|
|
1580
|
+
identifier_dict['density_profile_slope'] = self.lens_param_samplers_params['density_profile_slope']
|
|
1581
|
+
if identifier_dict['density_profile_slope']: # if density_profile_slope is not None
|
|
1582
|
+
identifier_dict['density_profile_slope']['name'] = str(self.lens_param_samplers['density_profile_slope'])
|
|
1583
|
+
identifier_dict['external_shear'] = self.lens_param_samplers_params['external_shear']
|
|
1584
|
+
if identifier_dict['external_shear']: # if external_shear is not None
|
|
1585
|
+
identifier_dict['external_shear']['name'] = str(self.lens_param_samplers['external_shear'])
|
|
1586
|
+
|
|
1587
|
+
param_dict = self.available_lens_functions_and_its_params["optical_depth"]["optical_depth_numerical"]
|
|
1588
|
+
if param_dict:
|
|
1589
|
+
param_dict.update(kwargs)
|
|
590
1590
|
else:
|
|
591
|
-
|
|
1591
|
+
param_dict = kwargs
|
|
1592
|
+
identifier_dict.update(param_dict)
|
|
1593
|
+
|
|
1594
|
+
z_min = self.z_min if self.z_min>0. else 0.001
|
|
1595
|
+
z_max = self.z_max
|
|
1596
|
+
resolution = identifier_dict['resolution']
|
|
1597
|
+
zs_array = np.geomspace(
|
|
1598
|
+
z_min,
|
|
1599
|
+
z_max,
|
|
1600
|
+
resolution
|
|
1601
|
+
)
|
|
1602
|
+
|
|
1603
|
+
def tau(zs):
|
|
1604
|
+
# self.lens_redshift.function gives cross-section
|
|
1605
|
+
integrand = lambda zl_, zs_: self.lens_redshift.function(np.array([zl_]), np.array([zs_]))[0]
|
|
1606
|
+
integral = [quad(integrand, 0.0, z, args=(z))[0] for z in zs]
|
|
1607
|
+
return integral
|
|
1608
|
+
|
|
1609
|
+
tau_object = FunctionConditioning(
|
|
1610
|
+
function=tau,
|
|
1611
|
+
x_array=zs_array,
|
|
1612
|
+
conditioned_y_array=None,
|
|
1613
|
+
param_dict_given=identifier_dict,
|
|
1614
|
+
directory=self.directory,
|
|
1615
|
+
sub_directory="optical_depth",
|
|
1616
|
+
name=identifier_dict['name'],
|
|
1617
|
+
create_new=self.create_new_interpolator["optical_depth"]["create_new"],
|
|
1618
|
+
create_function_inverse=False,
|
|
1619
|
+
create_function=True,
|
|
1620
|
+
create_pdf=True,
|
|
1621
|
+
create_rvs=True,
|
|
1622
|
+
callback='function',
|
|
1623
|
+
)
|
|
592
1624
|
|
|
593
|
-
|
|
1625
|
+
return tau_object if get_attribute else tau_object.function(zs)
|
|
1626
|
+
|
|
1627
|
+
def cross_section_sis(self, sigma, zl, zs, **kwargs):
|
|
594
1628
|
"""
|
|
595
1629
|
Function to compute the SIS cross-section
|
|
596
1630
|
|
|
@@ -612,85 +1646,82 @@ class OpticalDepth():
|
|
|
612
1646
|
--------
|
|
613
1647
|
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
614
1648
|
>>> od = OpticalDepth()
|
|
615
|
-
>>> print(od.
|
|
1649
|
+
>>> print(od.cross_section_sis(sigma=200., zl=0.5, zs=1.0))
|
|
616
1650
|
"""
|
|
617
|
-
zl = np.array([zl]).reshape(-1)
|
|
618
|
-
zs = np.array([zs]).reshape(-1)
|
|
619
|
-
Ds = self.angular_diameter_distance(zs)
|
|
620
|
-
Dls = self.angular_diameter_distance_z1z2(zl, zs)
|
|
621
|
-
theta_E = (
|
|
622
|
-
4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / (Ds)
|
|
623
|
-
) # Note: km/s for sigma; Dls, Ds are in Mpc
|
|
624
1651
|
|
|
1652
|
+
theta_E = self.compute_einstein_radii(sigma, zl, zs)
|
|
625
1653
|
return np.pi * theta_E**2
|
|
626
1654
|
|
|
627
|
-
def
|
|
1655
|
+
def compute_einstein_radii(self, sigma, zl, zs):
|
|
628
1656
|
"""
|
|
629
|
-
Function to compute the
|
|
1657
|
+
Function to compute the Einstein radii of the lens galaxies
|
|
630
1658
|
|
|
631
1659
|
Parameters
|
|
632
1660
|
----------
|
|
1661
|
+
sigma : `float`
|
|
1662
|
+
velocity dispersion of the lens galaxy
|
|
633
1663
|
zl : `float`
|
|
634
|
-
|
|
1664
|
+
lens redshifts
|
|
635
1665
|
zs : `float`
|
|
636
|
-
|
|
1666
|
+
source redshifts
|
|
637
1667
|
|
|
638
1668
|
Returns
|
|
639
1669
|
-------
|
|
640
|
-
|
|
641
|
-
|
|
1670
|
+
theta_E : `float`
|
|
1671
|
+
Einstein radii of the lens galaxies in radians. Multiply by
|
|
642
1672
|
|
|
643
1673
|
Examples
|
|
644
1674
|
--------
|
|
645
|
-
>>> from ler.lens_galaxy_population import
|
|
646
|
-
>>>
|
|
647
|
-
>>>
|
|
1675
|
+
>>> from ler.lens_galaxy_population import LensGalaxyParameterDistribution
|
|
1676
|
+
>>> lens = LensGalaxyParameterDistribution()
|
|
1677
|
+
>>> sigma = 200.0
|
|
1678
|
+
>>> zl = 0.5
|
|
1679
|
+
>>> zs = 1.0
|
|
1680
|
+
>>> lens.compute_einstein_radii(sigma, zl, zs)
|
|
648
1681
|
"""
|
|
649
|
-
zl = np.array([zl]).reshape(-1)
|
|
650
|
-
zs = np.array([zs]).reshape(-1)
|
|
651
|
-
# size=5000 will take ~ 48s to run, with ewoud vd sampler
|
|
652
|
-
try:
|
|
653
|
-
sigma = self.sample_velocity_dispersion(size=5000)
|
|
654
|
-
except:
|
|
655
|
-
sigma = self.sample_velocity_dispersion(size=5000, zl=zl)
|
|
656
1682
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
#
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
1683
|
+
# Compute the angular diameter distances
|
|
1684
|
+
Ds = self.angular_diameter_distance(zs)
|
|
1685
|
+
Dls = self.angular_diameter_distance_z1z2(zl, zs)
|
|
1686
|
+
# Compute the Einstein radii
|
|
1687
|
+
theta_E = (
|
|
1688
|
+
4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / (Ds)
|
|
1689
|
+
) # Note: km/s for sigma; Dls, Ds are in Mpc
|
|
1690
|
+
|
|
1691
|
+
return theta_E
|
|
1692
|
+
|
|
1693
|
+
def cross_section_sie_feixu(self, sigma, zl, zs, q, **kwargs):
|
|
664
1694
|
"""
|
|
665
|
-
Function to compute the
|
|
1695
|
+
Function to compute the SIE cross-section from Fei Xu et al. (2021)
|
|
666
1696
|
|
|
667
1697
|
Parameters
|
|
668
1698
|
----------
|
|
1699
|
+
sigma : `float`
|
|
1700
|
+
velocity dispersion of the lens galaxy
|
|
1701
|
+
zl : `float`
|
|
1702
|
+
redshift of the lens galaxy
|
|
669
1703
|
zs : `float`
|
|
670
|
-
source
|
|
1704
|
+
redshift of the source galaxy
|
|
671
1705
|
|
|
672
1706
|
Returns
|
|
673
1707
|
-------
|
|
674
|
-
|
|
675
|
-
|
|
1708
|
+
cross_section : `float`
|
|
1709
|
+
SIE cross-section
|
|
676
1710
|
|
|
677
1711
|
Examples
|
|
678
1712
|
--------
|
|
679
1713
|
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
680
1714
|
>>> od = OpticalDepth()
|
|
681
|
-
>>> print(od.
|
|
1715
|
+
>>> print(od.cross_section_sie_feixu(sigma=200., zl=0.5, zs=1.0, q=1.0))
|
|
682
1716
|
"""
|
|
683
1717
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
for z in zs:
|
|
687
|
-
tau_list.append(quad(self.tau_zl_zs, 0, z, args=(z))[0])
|
|
688
|
-
|
|
689
|
-
return np.array(tau_list)
|
|
1718
|
+
# phi_cut_SIE already includes the factor of pi
|
|
1719
|
+
return phi_cut_SIE(q)*self.cross_section_sis(sigma=sigma, zl=zl, zs=zs)
|
|
690
1720
|
|
|
691
|
-
def
|
|
1721
|
+
def optical_depth_epl_shear_hemanta(self, zs, get_attribute=False, **kwargs):
|
|
692
1722
|
"""
|
|
693
|
-
Function to compute the
|
|
1723
|
+
Function to compute the strong lensing optical depth (EPL with shear). \n
|
|
1724
|
+
LambdaCDM(H0=70, Om0=0.3, Ode0=0.7) was used to derive the following equation. This is the analytic version of optical depth from z=0 to z=zs.
|
|
694
1725
|
|
|
695
1726
|
Parameters
|
|
696
1727
|
----------
|
|
@@ -700,37 +1731,66 @@ class OpticalDepth():
|
|
|
700
1731
|
Returns
|
|
701
1732
|
-------
|
|
702
1733
|
tau : `float`
|
|
703
|
-
optical depth
|
|
704
|
-
|
|
1734
|
+
strong lensing optical depth
|
|
1735
|
+
|
|
705
1736
|
Examples
|
|
706
1737
|
--------
|
|
707
1738
|
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
708
1739
|
>>> od = OpticalDepth()
|
|
709
|
-
>>> print(od.
|
|
1740
|
+
>>> print(od.optical_depth_epl_shear_lambdacdm(zs=1.0))
|
|
710
1741
|
"""
|
|
711
1742
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
1743
|
+
# setting up input parameters for interpolation
|
|
1744
|
+
identifier_dict = {'name': 'optical_depth_numerical',
|
|
1745
|
+
'resolution': 48,
|
|
1746
|
+
'z_min': 0.0,
|
|
1747
|
+
'z_max': 10.0,
|
|
1748
|
+
'cosmology': LambdaCDM(H0=70, Om0=0.3, Ode0=0.7),
|
|
1749
|
+
'velocity_dispersion': {'sigma_min': 100.0,
|
|
1750
|
+
'sigma_max': 400.0,
|
|
1751
|
+
'alpha': 0.94,
|
|
1752
|
+
'beta': 1.85,
|
|
1753
|
+
'phistar': 0.02099,
|
|
1754
|
+
'sigmastar': 113.78,
|
|
1755
|
+
'name': 'velocity_dispersion_ewoud'},
|
|
1756
|
+
'axis_ratio': {'q_min': 0.2, 'q_max': 1.0, 'name': 'axis_ratio_rayleigh'},
|
|
1757
|
+
'axis_rotation_angle': {'phi_min': 0.0,
|
|
1758
|
+
'phi_max': 6.283185307179586,
|
|
1759
|
+
'name': 'axis_rotation_angle_uniform'},
|
|
1760
|
+
'density_profile_slope': {'mean': 1.99,
|
|
1761
|
+
'std': 0.149,
|
|
1762
|
+
'name': 'density_profile_slope_normal'},
|
|
1763
|
+
'external_shear': {'mean': 0.0, 'std': 0.05, 'name': 'external_shear_normal'}
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
print("Getting pre-computed optical depth for EPL+Shear lenses...")
|
|
723
1767
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
1768
|
+
zs_arr = np.geomspace(
|
|
1769
|
+
0.001,
|
|
1770
|
+
10,
|
|
1771
|
+
identifier_dict['resolution']
|
|
1772
|
+
)
|
|
1773
|
+
tau_arr = load_txt_from_module('ler', 'lens_galaxy_population.lens_param_data', 'optical_depth_epl_shear_vd_ewoud.txt')
|
|
727
1774
|
|
|
728
|
-
|
|
729
|
-
|
|
1775
|
+
tau_object = FunctionConditioning(
|
|
1776
|
+
function=tau_arr,
|
|
1777
|
+
x_array=zs_arr,
|
|
1778
|
+
conditioned_y_array=None,
|
|
1779
|
+
param_dict_given=identifier_dict,
|
|
1780
|
+
directory=self.directory,
|
|
1781
|
+
sub_directory="optical_depth",
|
|
1782
|
+
name=identifier_dict['name'],
|
|
1783
|
+
create_new=self.create_new_interpolator["optical_depth"]["create_new"],
|
|
1784
|
+
create_function_inverse=False,
|
|
1785
|
+
create_function=True,
|
|
1786
|
+
create_pdf=True,
|
|
1787
|
+
create_rvs=True,
|
|
1788
|
+
callback='function',
|
|
1789
|
+
)
|
|
730
1790
|
|
|
731
|
-
return
|
|
1791
|
+
return tau_object if get_attribute else tau_object.function(zs)
|
|
732
1792
|
|
|
733
|
-
def
|
|
1793
|
+
def optical_depth_sis_haris(self, zs, get_attribute=False, **kwargs):
|
|
734
1794
|
"""
|
|
735
1795
|
Function to compute the strong lensing optical depth (SIS). \n
|
|
736
1796
|
LambdaCDM(H0=70, Om0=0.3, Ode0=0.7) was used to derive the following equation. This is the analytic version of optical depth from z=0 to z=zs.
|
|
@@ -749,106 +1809,455 @@ class OpticalDepth():
|
|
|
749
1809
|
--------
|
|
750
1810
|
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
751
1811
|
>>> od = OpticalDepth()
|
|
752
|
-
>>> print(od.
|
|
1812
|
+
>>> print(od.optical_depth_sis_haris(zs=1.0))
|
|
753
1813
|
"""
|
|
754
1814
|
|
|
755
|
-
# z to luminosity_distance (luminosity_distance) conversion
|
|
756
|
-
Dc = self.z_to_Dc(zs) * 1e-3 # 1e-3 converts Mpc to Gpc
|
|
1815
|
+
# # z to luminosity_distance (luminosity_distance) conversion
|
|
1816
|
+
# #Dc = self.z_to_Dc(zs) * 1e-3 # 1e-3 converts Mpc to Gpc
|
|
1817
|
+
# splineDc = self.splineDc
|
|
1818
|
+
|
|
1819
|
+
|
|
1820
|
+
|
|
1821
|
+
# if get_attribute:
|
|
1822
|
+
# return tau
|
|
1823
|
+
# else:
|
|
1824
|
+
# return tau(zs)
|
|
1825
|
+
identifier_dict = {'name': "optical_depth_sis_haris"}
|
|
1826
|
+
identifier_dict['z_min'] = self.z_min if self.z_min>0. else 0.001
|
|
1827
|
+
identifier_dict['z_max'] = self.z_max
|
|
1828
|
+
identifier_dict['cosmology'] = self.cosmo
|
|
1829
|
+
identifier_dict['resolution'] = self.create_new_interpolator["optical_depth"]["resolution"]
|
|
1830
|
+
param_dict = self.available_lens_functions_and_its_params["optical_depth"]["optical_depth_sis_haris"]
|
|
1831
|
+
if param_dict:
|
|
1832
|
+
param_dict.update(kwargs)
|
|
1833
|
+
else:
|
|
1834
|
+
param_dict = kwargs
|
|
1835
|
+
identifier_dict.update(param_dict)
|
|
1836
|
+
|
|
1837
|
+
zs_arr = np.geomspace(identifier_dict['z_min'], identifier_dict['z_max'], identifier_dict['resolution'])
|
|
1838
|
+
|
|
1839
|
+
def tau(zs):
|
|
1840
|
+
Dc = self.comoving_distance.function(zs)
|
|
1841
|
+
return (Dc * 1e-3 / 62.2) ** 3
|
|
1842
|
+
|
|
1843
|
+
tau_object = FunctionConditioning(
|
|
1844
|
+
function=tau,
|
|
1845
|
+
x_array=zs_arr,
|
|
1846
|
+
conditioned_y_array=None,
|
|
1847
|
+
param_dict_given=identifier_dict,
|
|
1848
|
+
directory=self.directory,
|
|
1849
|
+
sub_directory="optical_depth",
|
|
1850
|
+
name=identifier_dict['name'],
|
|
1851
|
+
create_new=self.create_new_interpolator["optical_depth"]["create_new"],
|
|
1852
|
+
create_function_inverse=False,
|
|
1853
|
+
create_function=True,
|
|
1854
|
+
create_pdf=True,
|
|
1855
|
+
create_rvs=True,
|
|
1856
|
+
callback='function',
|
|
1857
|
+
)
|
|
1858
|
+
|
|
1859
|
+
return tau_object if get_attribute else tau_object.function(zs)
|
|
1860
|
+
|
|
1861
|
+
#######################################
|
|
1862
|
+
# interpolated cross section function #
|
|
1863
|
+
#######################################
|
|
1864
|
+
def create_data_set(self, size=1000000):
|
|
1865
|
+
zs = np.random.uniform(0.01, 10.0, size-2)
|
|
1866
|
+
# inlcude z=0.01 and z=10.0
|
|
1867
|
+
zs = np.insert(zs, 0, 0.01)
|
|
1868
|
+
zs = np.append(zs, 10.0)
|
|
1869
|
+
|
|
1870
|
+
zl = np.zeros(size)
|
|
1871
|
+
for i in range(size):
|
|
1872
|
+
zl[i] = np.random.uniform(0.001, zs[i]-0.001)
|
|
1873
|
+
|
|
1874
|
+
sigma = np.random.uniform(self.lens_param_samplers_params["velocity_dispersion"]['sigma_min'], self.lens_param_samplers_params["velocity_dispersion"]['sigma_max'], size-2)
|
|
1875
|
+
# inlcude sigma_min and sigma_max
|
|
1876
|
+
sigma = np.insert(sigma, 0, self.lens_param_samplers_params["velocity_dispersion"]['sigma_min'])
|
|
1877
|
+
sigma = np.append(sigma, self.lens_param_samplers_params["velocity_dispersion"]['sigma_max'])
|
|
1878
|
+
|
|
1879
|
+
q = np.random.uniform(self.lens_param_samplers_params["axis_ratio"]['q_min'], self.lens_param_samplers_params["axis_ratio"]['q_max'], size-2)
|
|
1880
|
+
# inlcude q_min and q_max
|
|
1881
|
+
q = np.insert(q, 0, self.lens_param_samplers_params["axis_ratio"]['q_min'])
|
|
1882
|
+
q = np.append(q, self.lens_param_samplers_params["axis_ratio"]['q_max'])
|
|
1883
|
+
|
|
1884
|
+
phi = np.random.uniform(0.0, 2 * np.pi, size-2)
|
|
1885
|
+
# inlcude 0 and 2 * np.pi
|
|
1886
|
+
phi = np.insert(phi, 0, 0.0)
|
|
1887
|
+
phi = np.append(phi, 2 * np.pi)
|
|
1888
|
+
|
|
1889
|
+
e1, e2 = phi_q2_ellipticity_hemanta(phi, q)
|
|
1890
|
+
gamma1, gamma2 = np.random.normal(loc=0, scale=0.05, size=(2, size))
|
|
1891
|
+
gamma = np.random.normal(loc=2.0, scale=0.2, size=size)
|
|
1892
|
+
# Da_zs = od_epl_ewoud.angular_diameter_distance(np.array([zs]))[0]
|
|
1893
|
+
# einstein radius
|
|
1894
|
+
Ds = self.angular_diameter_distance.function(zs)
|
|
1895
|
+
Dls = self.angular_diameter_distance_z1z2(zl, zs)
|
|
1896
|
+
theta_E = (
|
|
1897
|
+
4.0 * np.pi * (sigma / 299792.458) ** 2 * Dls / (Ds)
|
|
1898
|
+
) # Note: km/s for sigma; Dls, Ds are in Mpc
|
|
1899
|
+
|
|
1900
|
+
return theta_E, e1, e2, gamma, gamma1, gamma2, q
|
|
1901
|
+
|
|
1902
|
+
def cross_section_caustic_area(self, theta_E, e1, e2, gamma, gamma1, gamma2):
|
|
1903
|
+
|
|
1904
|
+
size = theta_E.shape[0]
|
|
1905
|
+
area_list = np.zeros(size)
|
|
1906
|
+
for i in range(size):
|
|
1907
|
+
kwargs_lens = [
|
|
1908
|
+
{
|
|
1909
|
+
"theta_E": theta_E[i],
|
|
1910
|
+
"e1": e1[i],
|
|
1911
|
+
"e2": e2[i],
|
|
1912
|
+
"gamma": gamma[i],
|
|
1913
|
+
"center_x": 0.0,
|
|
1914
|
+
"center_y": 0.0,
|
|
1915
|
+
},
|
|
1916
|
+
{
|
|
1917
|
+
"gamma1": gamma1[i],
|
|
1918
|
+
"gamma2": gamma2[i],
|
|
1919
|
+
"ra_0": 0,
|
|
1920
|
+
"dec_0": 0,
|
|
1921
|
+
},
|
|
1922
|
+
]
|
|
1923
|
+
|
|
1924
|
+
caustic_double_points = caustics_epl_shear(
|
|
1925
|
+
kwargs_lens, return_which="double", maginf=-100
|
|
1926
|
+
)
|
|
1927
|
+
caustic = np.logical_not(np.isnan(caustic_double_points).any())
|
|
1928
|
+
|
|
1929
|
+
# If there is a nan, caustic=False, draw a new gamma
|
|
1930
|
+
if caustic:
|
|
1931
|
+
area_list[i] = (Polygon(caustic_double_points.T).area)
|
|
1932
|
+
|
|
1933
|
+
return np.array(area_list)
|
|
1934
|
+
|
|
1935
|
+
def cross_section_caustic_area_unit(self, e1, e2, gamma, gamma1, gamma2):
|
|
1936
|
+
|
|
1937
|
+
size = e1.shape[0]
|
|
1938
|
+
area_list = np.zeros(size)
|
|
1939
|
+
for i in range(size):
|
|
1940
|
+
kwargs_lens = [
|
|
1941
|
+
{
|
|
1942
|
+
"theta_E": 1.0,
|
|
1943
|
+
"e1": e1[i],
|
|
1944
|
+
"e2": e2[i],
|
|
1945
|
+
"gamma": gamma[i],
|
|
1946
|
+
"center_x": 0.0,
|
|
1947
|
+
"center_y": 0.0,
|
|
1948
|
+
},
|
|
1949
|
+
{
|
|
1950
|
+
"gamma1": gamma1[i],
|
|
1951
|
+
"gamma2": gamma2[i],
|
|
1952
|
+
"ra_0": 0,
|
|
1953
|
+
"dec_0": 0,
|
|
1954
|
+
},
|
|
1955
|
+
]
|
|
1956
|
+
|
|
1957
|
+
caustic_double_points = caustics_epl_shear(
|
|
1958
|
+
kwargs_lens, return_which="double", maginf=-100
|
|
1959
|
+
)
|
|
1960
|
+
caustic = np.logical_not(np.isnan(caustic_double_points).any())
|
|
757
1961
|
|
|
758
|
-
|
|
1962
|
+
# If there is a nan, caustic=False, draw a new gamma
|
|
1963
|
+
if caustic:
|
|
1964
|
+
area_list[i] = (Polygon(caustic_double_points.T).area)
|
|
1965
|
+
|
|
1966
|
+
return np.array(area_list)
|
|
759
1967
|
|
|
760
|
-
def
|
|
1968
|
+
def create_cross_section_function(self):
|
|
1969
|
+
|
|
1970
|
+
param_dict_given = dict(
|
|
1971
|
+
z_min=self.z_min,
|
|
1972
|
+
z_max=self.z_max,
|
|
1973
|
+
cosmology=self.cosmo,
|
|
1974
|
+
resolution=self.create_new_interpolator["cross_section"]["resolution"],
|
|
1975
|
+
sigma_min=self.lens_param_samplers_params["velocity_dispersion"]['sigma_min'],
|
|
1976
|
+
sigma_max=self.lens_param_samplers_params["velocity_dispersion"]['sigma_max'],
|
|
1977
|
+
q_min = self.lens_param_samplers_params["axis_ratio"]['q_min'],
|
|
1978
|
+
q_max = self.lens_param_samplers_params["axis_ratio"]['q_max'],
|
|
1979
|
+
)
|
|
1980
|
+
|
|
1981
|
+
file_path, it_exist = interpolator_pickle_path(
|
|
1982
|
+
param_dict_given=param_dict_given,
|
|
1983
|
+
directory=self.directory,
|
|
1984
|
+
sub_directory="cross_section_function",
|
|
1985
|
+
interpolator_name="cross_section_function",
|
|
1986
|
+
)
|
|
1987
|
+
|
|
1988
|
+
if (self.create_new_interpolator["cross_section"]["create_new"] is True) or (it_exist is False):
|
|
1989
|
+
|
|
1990
|
+
print(f"Interpolated cross section function will be created at {file_path}")
|
|
1991
|
+
print("Creating interpolated cross section function with sklearn NearestNeighbors, and this will be use for cross section calculation")
|
|
1992
|
+
|
|
1993
|
+
size_interpolation=1000
|
|
1994
|
+
theta_E, e1, e2, gamma, gamma1, gamma2, _ = self.create_data_set(size_interpolation)
|
|
1995
|
+
# sort
|
|
1996
|
+
idx = np.argsort(theta_E)
|
|
1997
|
+
theta_E, e1, e2, gamma, gamma1, gamma2 = theta_E[idx], e1[idx], e2[idx], gamma[idx], gamma1[idx], gamma2[idx]
|
|
1998
|
+
values1 = self.cross_section_caustic_area(theta_E, e1, e2, gamma, gamma1, gamma2)
|
|
1999
|
+
values2 = self.cross_section_caustic_area_unit(e1, e2, gamma, gamma1, gamma2)
|
|
2000
|
+
|
|
2001
|
+
x = np.pi*theta_E**2
|
|
2002
|
+
|
|
2003
|
+
idx_cs = (values2 > 0.0) & (values1 > 0.0) & (x > 0.0)
|
|
2004
|
+
value3 = values1[idx_cs]/values2[idx_cs]
|
|
2005
|
+
x = x[idx_cs]
|
|
2006
|
+
spline_coeff = CubicSpline(x, value3).c
|
|
2007
|
+
|
|
2008
|
+
# K nearest neighbors
|
|
2009
|
+
size = self.create_new_interpolator["cross_section"]["resolution"]
|
|
2010
|
+
iter_ = np.arange(size)
|
|
2011
|
+
_, e1, e2, gamma, gamma1, gamma2, _ = self.create_data_set(size)
|
|
2012
|
+
points = np.column_stack((e1, e2, gamma, gamma1, gamma2, iter_))
|
|
2013
|
+
from .mp import cross_section_unit_mp
|
|
2014
|
+
area_list = np.ones(size)
|
|
2015
|
+
with Pool(processes=8) as pool:
|
|
2016
|
+
for result in tqdm(
|
|
2017
|
+
pool.imap_unordered(cross_section_unit_mp, points),
|
|
2018
|
+
total=size,
|
|
2019
|
+
ncols=100,
|
|
2020
|
+
disable=False,
|
|
2021
|
+
):
|
|
2022
|
+
(
|
|
2023
|
+
iter_i,
|
|
2024
|
+
area,
|
|
2025
|
+
) = result
|
|
2026
|
+
area_list[int(iter_i)] = area
|
|
2027
|
+
|
|
2028
|
+
values = np.array(area_list)
|
|
2029
|
+
points = points[:, :-1]
|
|
2030
|
+
|
|
2031
|
+
from sklearn.neighbors import NearestNeighbors
|
|
2032
|
+
|
|
2033
|
+
# Fit nearest neighbor model
|
|
2034
|
+
nbrs = NearestNeighbors(n_neighbors=10).fit(points)
|
|
2035
|
+
|
|
2036
|
+
#print(mean_squared_error(values1, y_pred))
|
|
2037
|
+
|
|
2038
|
+
# save the cross_section_function as pickle
|
|
2039
|
+
save_pickle(file_path, [nbrs,values,spline_coeff,x])
|
|
2040
|
+
self.nbrs = nbrs
|
|
2041
|
+
self.values = values
|
|
2042
|
+
self.cross_section_spline = spline_coeff
|
|
2043
|
+
self.sis_area_array = x
|
|
2044
|
+
|
|
2045
|
+
else:
|
|
2046
|
+
from ..utils import load_pickle
|
|
2047
|
+
print(f"Interpolated cross section function loaded from {file_path}")
|
|
2048
|
+
load_ = load_pickle(file_path)
|
|
2049
|
+
self.nbrs, self.values, self.cross_section_spline, self.sis_area_array = load_
|
|
2050
|
+
|
|
2051
|
+
def interpolated_cross_section_function(self, theta_E, e1, e2, gamma, gamma1, gamma2, get_attribute=False, **kwargs):
|
|
2052
|
+
"""
|
|
2053
|
+
Function to compute the cross-section correction factor
|
|
2054
|
+
"""
|
|
2055
|
+
nbrs = self.nbrs
|
|
2056
|
+
values = self.values
|
|
2057
|
+
|
|
2058
|
+
points_ = np.array([e1, e2, gamma, gamma1, gamma2]).T
|
|
2059
|
+
_, indices = nbrs.kneighbors(points_)
|
|
2060
|
+
new_values_nn1 = np.mean(values[indices], axis=1)
|
|
2061
|
+
|
|
2062
|
+
theta_E_correction = cubic_spline_interpolator(np.pi*theta_E**2, self.cross_section_spline, self.sis_area_array)
|
|
2063
|
+
|
|
2064
|
+
return new_values_nn1*theta_E_correction
|
|
2065
|
+
|
|
2066
|
+
##########################
|
|
2067
|
+
# Cosmological functions #
|
|
2068
|
+
##########################
|
|
2069
|
+
def create_lookup_table_fuction(self):
|
|
761
2070
|
"""
|
|
762
2071
|
Functions to create lookup tables
|
|
763
2072
|
1. Redshift to co-moving distance.
|
|
764
2073
|
2. Co-moving distance to redshift.
|
|
765
2074
|
3. Redshift to angular diameter distance.
|
|
766
2075
|
|
|
2076
|
+
"""
|
|
2077
|
+
|
|
2078
|
+
z_max = self.z_max
|
|
2079
|
+
z_min = 0.001 if self.z_min == 0. else self.z_min
|
|
2080
|
+
# for co-moving distance
|
|
2081
|
+
resolution = self.create_new_interpolator["comoving_distance"]["resolution"]
|
|
2082
|
+
create_new = self.create_new_interpolator["comoving_distance"]["create_new"]
|
|
2083
|
+
zs = np.geomspace(z_min, z_max, resolution)
|
|
2084
|
+
Dc = self.cosmo.comoving_distance(zs).value # co-moving distance in Mpc
|
|
2085
|
+
self.comoving_distance = FunctionConditioning(
|
|
2086
|
+
function=Dc,
|
|
2087
|
+
x_array=zs,
|
|
2088
|
+
conditioned_y_array=None,
|
|
2089
|
+
param_dict_given=dict(z_min=z_min, z_max=z_max, cosmology=self.cosmo, resolution=resolution, details="comoving_distance from astropy.cosmology"),
|
|
2090
|
+
directory=self.directory,
|
|
2091
|
+
sub_directory="comoving_distance",
|
|
2092
|
+
name="comoving_distance",
|
|
2093
|
+
create_new=create_new,
|
|
2094
|
+
create_function_inverse=True,
|
|
2095
|
+
create_function=True,
|
|
2096
|
+
create_pdf=False,
|
|
2097
|
+
create_rvs=False,
|
|
2098
|
+
callback='function',
|
|
2099
|
+
)
|
|
2100
|
+
self.comoving_distance.__doc__ = """
|
|
2101
|
+
Redshift to comoving distance conversion.
|
|
2102
|
+
|
|
767
2103
|
Parameters
|
|
768
2104
|
----------
|
|
769
|
-
|
|
770
|
-
|
|
2105
|
+
zs : `numpy.ndarray` or `float`
|
|
2106
|
+
Source redshifts
|
|
2107
|
+
|
|
2108
|
+
Returns
|
|
2109
|
+
----------
|
|
2110
|
+
comoving_distance : `numpy.ndarray`
|
|
2111
|
+
comoving distance in Mpc
|
|
2112
|
+
|
|
2113
|
+
Examples
|
|
2114
|
+
----------
|
|
2115
|
+
>>> from ler.len_galaxy_population import OpticalDepth
|
|
2116
|
+
>>> ler = OpticalDepth() # with default LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
|
|
2117
|
+
>>> comoving_distance = ler.comoving_distance(1.)
|
|
2118
|
+
>>> comoving_distance = ler.comoving_distance.function(np.array([1., 2.]))
|
|
2119
|
+
>>> redshift = ler.comoving_distance.function_inverse(np.array([100., 200.]))
|
|
771
2120
|
"""
|
|
772
2121
|
|
|
773
|
-
|
|
774
|
-
resolution = self.
|
|
775
|
-
create_new = self.
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
conditioned_y=None,
|
|
784
|
-
dimension=1,
|
|
785
|
-
category="function",
|
|
786
|
-
create_new= create_new,
|
|
787
|
-
)
|
|
788
|
-
self.splineDc = splineDc
|
|
789
|
-
self.z_to_Dc = njit(lambda z_: cubic_spline_interpolator(z_, splineDc[0], splineDc[1]))
|
|
790
|
-
|
|
791
|
-
# for co-moving distance to redshift
|
|
792
|
-
resolution = self.c_n_i["Dc_to_z"]["resolution"]
|
|
793
|
-
create_new = self.c_n_i["Dc_to_z"]["create_new"]
|
|
794
|
-
splineDcInv = interpolator_from_pickle(
|
|
795
|
-
param_dict_given= dict(z_min=0.001, z_max=z_max, cosmology=self.cosmo, resolution=resolution),
|
|
2122
|
+
# for angular diameter distance
|
|
2123
|
+
resolution = self.create_new_interpolator["angular_diameter_distance"]["resolution"]
|
|
2124
|
+
create_new = self.create_new_interpolator["angular_diameter_distance"]["create_new"]
|
|
2125
|
+
zs = np.geomspace(z_min, z_max, resolution)
|
|
2126
|
+
Da = self.cosmo.angular_diameter_distance(zs).value
|
|
2127
|
+
self.angular_diameter_distance = FunctionConditioning(
|
|
2128
|
+
function=Da,
|
|
2129
|
+
x_array=zs,
|
|
2130
|
+
conditioned_y_array=None,
|
|
2131
|
+
param_dict_given=dict(z_min=z_min, z_max=z_max, cosmology=self.cosmo, resolution=resolution, details="angular_diameter_distance from astropy.cosmology"),
|
|
796
2132
|
directory=self.directory,
|
|
797
|
-
sub_directory="
|
|
798
|
-
name="
|
|
799
|
-
x = np.geomspace(0.001, z_max, resolution),
|
|
800
|
-
pdf_func= Dc,
|
|
801
|
-
conditioned_y=None,
|
|
802
|
-
dimension=1,
|
|
803
|
-
category="function_inverse",
|
|
2133
|
+
sub_directory="angular_diameter_distance",
|
|
2134
|
+
name="angular_diameter_distance",
|
|
804
2135
|
create_new=create_new,
|
|
2136
|
+
create_function_inverse=False,
|
|
2137
|
+
create_function=True,
|
|
2138
|
+
create_pdf=False,
|
|
2139
|
+
create_rvs=False,
|
|
2140
|
+
callback='function',
|
|
805
2141
|
)
|
|
806
|
-
self.
|
|
807
|
-
|
|
2142
|
+
self.angular_diameter_distance.__doc__ = """
|
|
2143
|
+
Redshift to angular diameter distance conversion.
|
|
808
2144
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
self.angular_diameter_distance = angular_diameter_distance
|
|
2145
|
+
Parameters
|
|
2146
|
+
----------
|
|
2147
|
+
zs : `numpy.ndarray` or `float`
|
|
2148
|
+
Source redshifts
|
|
2149
|
+
|
|
2150
|
+
Returns
|
|
2151
|
+
----------
|
|
2152
|
+
angular_diameter_distance : `numpy.ndarray`
|
|
2153
|
+
angular diameter distance in Mpc
|
|
2154
|
+
|
|
2155
|
+
Examples
|
|
2156
|
+
----------
|
|
2157
|
+
>>> from ler.len_galaxy_population import OpticalDepth
|
|
2158
|
+
>>> ler = OpticalDepth() # with default LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
|
|
2159
|
+
>>> angular_diameter_distance = ler.angular_diameter_distance(1.)
|
|
2160
|
+
>>> angular_diameter_distance = ler.angular_diameter_distance.function(np.array([1., 2.]))
|
|
2161
|
+
>>> redshift = ler.angular_diameter_distance.function_inverse(np.array([100., 200.]))
|
|
2162
|
+
"""
|
|
828
2163
|
|
|
829
2164
|
# for angular diameter distance between two redshifts
|
|
830
|
-
|
|
2165
|
+
angular_diameter_distance_z1z2 = lambda zl0, zs0: (self.angular_diameter_distance.function(zs0)*(1.+zs0) - self.angular_diameter_distance.function(zl0)*(1.+zl0))/(1.+zs0)
|
|
2166
|
+
self.angular_diameter_distance_z1z2 = FunctionConditioning(
|
|
2167
|
+
function=None,
|
|
2168
|
+
x_array=None,
|
|
2169
|
+
param_dict_given=dict(z_min=z_min, z_max=z_max, cosmology=self.cosmo, resolution=resolution, details="angular_diameter_distance_z1z2 from astropy.cosmology"),
|
|
2170
|
+
create_function=angular_diameter_distance_z1z2,
|
|
2171
|
+
callback='function',
|
|
2172
|
+
)
|
|
2173
|
+
self.angular_diameter_distance_z1z2.__doc__ = """
|
|
2174
|
+
Redshift to angular diameter distance conversion.
|
|
2175
|
+
|
|
2176
|
+
Parameters
|
|
2177
|
+
----------
|
|
2178
|
+
zl0 : `numpy.ndarray` or `float`
|
|
2179
|
+
Lens redshifts
|
|
2180
|
+
zs0 : `numpy.ndarray` or `float`
|
|
2181
|
+
Source redshifts
|
|
2182
|
+
|
|
2183
|
+
Returns
|
|
2184
|
+
----------
|
|
2185
|
+
angular_diameter_distance_z1z2 : `numpy.ndarray`
|
|
2186
|
+
angular diameter distance in Mpc
|
|
2187
|
+
|
|
2188
|
+
Examples
|
|
2189
|
+
----------
|
|
2190
|
+
>>> from ler.len_galaxy_population import OpticalDepth
|
|
2191
|
+
>>> ler = OpticalDepth() # with default LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
|
|
2192
|
+
>>> angular_diameter_distance_z1z2 = ler.angular_diameter_distance_z1z2(1., 2.)
|
|
2193
|
+
>>> angular_diameter_distance_z1z2 = ler.angular_diameter_distance_z1z2.function(np.array([1., 2.]), np.array([1., 2.]))
|
|
2194
|
+
"""
|
|
831
2195
|
|
|
832
2196
|
# get differential co-moving volume interpolator
|
|
833
|
-
resolution = self.
|
|
834
|
-
create_new = self.
|
|
835
|
-
|
|
836
|
-
|
|
2197
|
+
resolution = self.create_new_interpolator["differential_comoving_volume"]["resolution"]
|
|
2198
|
+
create_new = self.create_new_interpolator["differential_comoving_volume"]["create_new"]
|
|
2199
|
+
zs = np.geomspace(z_min, z_max, resolution)
|
|
2200
|
+
dVcdz = self.cosmo.differential_comoving_volume(zs).value * 4 * np.pi # volume of shell in Mpc^3
|
|
2201
|
+
self.differential_comoving_volume = FunctionConditioning(
|
|
2202
|
+
function=dVcdz,
|
|
2203
|
+
x_array=zs,
|
|
2204
|
+
conditioned_y_array=None,
|
|
2205
|
+
param_dict_given=dict(z_min=z_min, z_max=z_max, cosmology=self.cosmo, resolution=resolution, details="differential_comoving_volume from astropy.cosmology"),
|
|
837
2206
|
directory=self.directory,
|
|
838
|
-
sub_directory="differential_comoving_volume",
|
|
2207
|
+
sub_directory="differential_comoving_volume",
|
|
839
2208
|
name="differential_comoving_volume",
|
|
840
|
-
x = np.geomspace(0.001, z_max, resolution),
|
|
841
|
-
pdf_func= lambda z_: self.cosmo.differential_comoving_volume(z_).value * 4 * np.pi,
|
|
842
|
-
conditioned_y=None,
|
|
843
|
-
dimension=1,
|
|
844
|
-
category="function",
|
|
845
2209
|
create_new=create_new,
|
|
2210
|
+
create_function_inverse=False,
|
|
2211
|
+
create_function=True,
|
|
2212
|
+
create_pdf=False,
|
|
2213
|
+
create_rvs=False,
|
|
2214
|
+
callback='function',
|
|
846
2215
|
)
|
|
847
|
-
self.
|
|
848
|
-
|
|
2216
|
+
self.differential_comoving_volume.__doc__ = """
|
|
2217
|
+
Redshift to differential comoving volume conversion.
|
|
2218
|
+
|
|
2219
|
+
Parameters
|
|
2220
|
+
----------
|
|
2221
|
+
zs : `numpy.ndarray` or `float`
|
|
2222
|
+
Source redshifts
|
|
2223
|
+
|
|
2224
|
+
Returns
|
|
2225
|
+
----------
|
|
2226
|
+
differential_comoving_volume : `numpy.ndarray`
|
|
2227
|
+
differential comoving volume in Mpc^3
|
|
2228
|
+
|
|
2229
|
+
Examples
|
|
2230
|
+
----------
|
|
2231
|
+
>>> from ler.len_galaxy_population import OpticalDepth
|
|
2232
|
+
>>> ler = OpticalDepth() # with default LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)
|
|
2233
|
+
>>> differential_comoving_volume = ler.differential_comoving_volume(1.)
|
|
2234
|
+
>>> differential_comoving_volume = ler.differential_comoving_volume.function(np.array([1., 2.]))
|
|
2235
|
+
"""
|
|
2236
|
+
|
|
2237
|
+
########################
|
|
2238
|
+
# Attribute properties #
|
|
2239
|
+
########################
|
|
2240
|
+
# @property
|
|
2241
|
+
# def cross_section(self):
|
|
2242
|
+
# return self._cross_section
|
|
2243
|
+
|
|
2244
|
+
# @cross_section.setter
|
|
2245
|
+
# def cross_section(self, input_function):
|
|
2246
|
+
# if input_function in self.available_cross_section_list_and_its_params:
|
|
2247
|
+
# print(f"using ler available cross section function : {input_function}")
|
|
2248
|
+
# self._cross_section = getattr(self, input_function)(zs=None, get_attribute=True)
|
|
2249
|
+
# elif callable(input_function):
|
|
2250
|
+
# print(f"using user provided custom cross section function")
|
|
2251
|
+
# self._cross_section = input_function
|
|
2252
|
+
# elif isinstance(input_function, object):
|
|
2253
|
+
# print(f"using user provided custom cross section class/object")
|
|
2254
|
+
# self._cross_section = input_function
|
|
2255
|
+
# else:
|
|
2256
|
+
# raise ValueError("input_function not in available_cross_section_list_and_its_params")
|
|
2257
|
+
|
|
849
2258
|
|
|
850
2259
|
@property
|
|
851
|
-
def
|
|
2260
|
+
def optical_depth(self):
|
|
852
2261
|
"""
|
|
853
2262
|
Function to compute the strong lensing optical depth.
|
|
854
2263
|
|
|
@@ -866,26 +2275,34 @@ class OpticalDepth():
|
|
|
866
2275
|
--------
|
|
867
2276
|
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
868
2277
|
>>> od = OpticalDepth()
|
|
869
|
-
>>> print(od.
|
|
2278
|
+
>>> print(od.optical_depth(np.array([0.1,0.2,0.3])))
|
|
870
2279
|
"""
|
|
871
2280
|
|
|
872
|
-
return self.
|
|
2281
|
+
return self._optical_depth
|
|
873
2282
|
|
|
874
|
-
@
|
|
875
|
-
def
|
|
876
|
-
if
|
|
877
|
-
|
|
2283
|
+
@optical_depth.setter
|
|
2284
|
+
def optical_depth(self, input_function):
|
|
2285
|
+
if input_function in self.available_lens_functions_and_its_params['optical_depth']:
|
|
2286
|
+
print(f"using ler available optical depth function : {input_function}")
|
|
2287
|
+
args = self.lens_functions_params["optical_depth"]
|
|
2288
|
+
if args is None:
|
|
2289
|
+
self._optical_depth = getattr(self, input_function)(zs=None, get_attribute=True)
|
|
2290
|
+
else:
|
|
2291
|
+
self._optical_depth = getattr(self, input_function)(zs=None, get_attribute=True, **args)
|
|
2292
|
+
elif callable(input_function):
|
|
2293
|
+
print(f"using user provided custom optical depth function")
|
|
2294
|
+
self._optical_depth = FunctionConditioning(function=None, x_array=None, create_function=input_function)
|
|
2295
|
+
elif isinstance(input_function, object):
|
|
2296
|
+
print(f"using user provided custom optical depth class/object")
|
|
2297
|
+
self._optical_depth = input_function
|
|
878
2298
|
else:
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
self._strong_lensing_optical_depth = njit(lambda zs: cubic_spline_interpolator(zs, input_[0], input_[1]))
|
|
882
|
-
except:
|
|
883
|
-
raise ValueError("strong_lensing_optical_depth must be a callable function or spline interpolator array.")
|
|
2299
|
+
raise ValueError("input_function not in available_lens_functions_and_its_params['optical_depth']")
|
|
2300
|
+
|
|
884
2301
|
|
|
885
2302
|
@property
|
|
886
|
-
def
|
|
2303
|
+
def velocity_dispersion(self):
|
|
887
2304
|
"""
|
|
888
|
-
|
|
2305
|
+
Class object to sample velocity dispersion. `zl` is required only if velocity dispersion sampler is redshift dependent.
|
|
889
2306
|
|
|
890
2307
|
Parameters
|
|
891
2308
|
----------
|
|
@@ -903,20 +2320,34 @@ class OpticalDepth():
|
|
|
903
2320
|
--------
|
|
904
2321
|
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
905
2322
|
>>> od = OpticalDepth()
|
|
906
|
-
>>> print(od.
|
|
2323
|
+
>>> print(od.velocity_dispersion(size=10))
|
|
907
2324
|
"""
|
|
908
2325
|
|
|
909
|
-
return self.
|
|
2326
|
+
return self._velocity_dispersion
|
|
910
2327
|
|
|
911
|
-
@
|
|
912
|
-
def
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
2328
|
+
@velocity_dispersion.setter
|
|
2329
|
+
def velocity_dispersion(self, prior):
|
|
2330
|
+
|
|
2331
|
+
if prior in self.available_lens_prior_list_and_its_params["velocity_dispersion"]:
|
|
2332
|
+
print(f"using ler available velocity dispersion function : {prior}")
|
|
2333
|
+
args = self.lens_param_samplers_params["velocity_dispersion"]
|
|
2334
|
+
if prior=="velocity_dispersion_choi":
|
|
2335
|
+
prior = "velocity_dispersion_bernardi"
|
|
2336
|
+
if args is None:
|
|
2337
|
+
self._velocity_dispersion = getattr(self, prior)(size=None, zl=None, get_attribute=True)
|
|
2338
|
+
else:
|
|
2339
|
+
self._velocity_dispersion = getattr(self, prior)(size=None, zl=None, get_attribute=True, **args)
|
|
2340
|
+
elif callable(prior):
|
|
2341
|
+
print("using user provided custom velocity_dispersion function")
|
|
2342
|
+
self._velocity_dispersion = FunctionConditioning(function=None, x_array=None, create_rvs=prior)
|
|
2343
|
+
elif isinstance(prior, object):
|
|
2344
|
+
print("using user provided custom velocity_dispersion class/object")
|
|
2345
|
+
self._velocity_dispersion = prior
|
|
2346
|
+
else:
|
|
2347
|
+
raise ValueError(f"velocity_dispersion prior not in available_lens_prior_list_and_its_params['velocity_dispersion']")
|
|
917
2348
|
|
|
918
2349
|
@property
|
|
919
|
-
def
|
|
2350
|
+
def axis_ratio(self):
|
|
920
2351
|
"""
|
|
921
2352
|
Function to sample axis ratio from rayleigh distribution with given velocity dispersion.
|
|
922
2353
|
|
|
@@ -934,57 +2365,258 @@ class OpticalDepth():
|
|
|
934
2365
|
--------
|
|
935
2366
|
>>> from ler.lens_galaxy_population import OpticalDepth
|
|
936
2367
|
>>> od = OpticalDepth()
|
|
937
|
-
>>> print(od.
|
|
2368
|
+
>>> print(od.axis_ratio(sigma=200.))
|
|
938
2369
|
"""
|
|
939
2370
|
|
|
940
|
-
return self.
|
|
941
|
-
|
|
942
|
-
@sample_axis_ratio.setter
|
|
943
|
-
def sample_axis_ratio(self, prior):
|
|
944
|
-
try:
|
|
945
|
-
args = self.sampler_priors_params["axis_ratio"]
|
|
946
|
-
self._sample_axis_ratio = getattr(self, prior)(sigma=None, get_attribute=True, param=args)
|
|
947
|
-
except:
|
|
948
|
-
self._sample_axis_ratio = prior
|
|
2371
|
+
return self._axis_ratio
|
|
949
2372
|
|
|
2373
|
+
@axis_ratio.setter
|
|
2374
|
+
def axis_ratio(self, prior):
|
|
2375
|
+
if prior in self.available_lens_prior_list_and_its_params["axis_ratio"]:
|
|
2376
|
+
print(f"using ler available axis_ratio function : {prior}")
|
|
2377
|
+
args = self.lens_param_samplers_params["axis_ratio"]
|
|
2378
|
+
if args is None:
|
|
2379
|
+
self._axis_ratio = getattr(self, prior)(size=None,sigma=None, get_attribute=True)
|
|
2380
|
+
else:
|
|
2381
|
+
self._axis_ratio = getattr(self, prior)(size=None, sigma=None, get_attribute=True, **args)
|
|
2382
|
+
elif callable(prior):
|
|
2383
|
+
print("using user provided custom axis_ratio function")
|
|
2384
|
+
self._axis_ratio = FunctionConditioning(function=None, x_array=None, create_rvs=prior)
|
|
2385
|
+
elif isinstance(prior, object):
|
|
2386
|
+
print("using user provided custom axis_ratio class/object")
|
|
2387
|
+
self._axis_ratio = prior
|
|
2388
|
+
else:
|
|
2389
|
+
raise ValueError("prior not in available_lens_prior_list_and_its_params['axis_ratio']")
|
|
2390
|
+
|
|
950
2391
|
@property
|
|
951
|
-
def
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
2392
|
+
def lens_redshift(self):
|
|
2393
|
+
return self._lens_redshift
|
|
2394
|
+
|
|
2395
|
+
@lens_redshift.setter
|
|
2396
|
+
def lens_redshift(self, prior):
|
|
2397
|
+
if prior in self.available_lens_prior_list_and_its_params["lens_redshift"]:
|
|
2398
|
+
print(f"using ler available lens_redshift function : {prior}")
|
|
2399
|
+
args = self.lens_param_samplers_params["lens_redshift"]
|
|
2400
|
+
if args is None:
|
|
2401
|
+
self._lens_redshift = getattr(self, prior)(size=None, zs=None, get_attribute=True)
|
|
2402
|
+
else:
|
|
2403
|
+
self._lens_redshift = getattr(self, prior)(size=None, zs=None, get_attribute=True, **args)
|
|
2404
|
+
elif callable(prior):
|
|
2405
|
+
print("using user provided custom lens_redshift function")
|
|
2406
|
+
self._lens_redshift = FunctionConditioning(function=None, x_array=None, create_rvs=prior)
|
|
2407
|
+
elif isinstance(prior, object):
|
|
2408
|
+
print("using user provided custom lens_redshift class/object")
|
|
2409
|
+
self._lens_redshift = prior
|
|
2410
|
+
else:
|
|
2411
|
+
raise ValueError("prior not in available_lens_prior_list_and_its_params['lens_redshift']")
|
|
2412
|
+
|
|
2413
|
+
@property
|
|
2414
|
+
def axis_rotation_angle(self):
|
|
2415
|
+
return self._axis_rotation_angle
|
|
2416
|
+
|
|
2417
|
+
@axis_rotation_angle.setter
|
|
2418
|
+
def axis_rotation_angle(self, prior):
|
|
2419
|
+
if prior in self.available_lens_prior_list_and_its_params["axis_rotation_angle"]:
|
|
2420
|
+
print(f"using ler available axis_rotation_angle function : {prior}")
|
|
2421
|
+
args = self.lens_param_samplers_params["axis_rotation_angle"]
|
|
2422
|
+
if args is None:
|
|
2423
|
+
self._axis_rotation_angle = getattr(self, prior)(size=None, get_attribute=True)
|
|
2424
|
+
else:
|
|
2425
|
+
self._axis_rotation_angle = getattr(self, prior)(size=None, get_attribute=True, **args)
|
|
2426
|
+
elif callable(prior):
|
|
2427
|
+
print("using user provided custom axis_rotation_angle function")
|
|
2428
|
+
self._axis_rotation_angle = FunctionConditioning(function=None, x_array=None, create_rvs=prior)
|
|
2429
|
+
elif isinstance(prior, object):
|
|
2430
|
+
print("using user provided custom axis_rotation_angle class/object")
|
|
2431
|
+
self._axis_rotation_angle = prior
|
|
2432
|
+
else:
|
|
2433
|
+
raise ValueError("prior not in available_lens_prior_list_and_its_params['axis_rotation_angle']")
|
|
2434
|
+
|
|
2435
|
+
@property
|
|
2436
|
+
def external_shear(self):
|
|
2437
|
+
return self._external_shear
|
|
2438
|
+
|
|
2439
|
+
@external_shear.setter
|
|
2440
|
+
def external_shear(self, prior):
|
|
2441
|
+
if prior in self.available_lens_prior_list_and_its_params["external_shear"]:
|
|
2442
|
+
print(f"using ler available external_shear function : {prior}")
|
|
2443
|
+
args = self.lens_param_samplers_params["external_shear"]
|
|
2444
|
+
if args is None:
|
|
2445
|
+
self._external_shear = getattr(self, prior)(size=None, get_attribute=True)
|
|
2446
|
+
else:
|
|
2447
|
+
self._external_shear = getattr(self, prior)(size=None, get_attribute=True, **args)
|
|
2448
|
+
elif callable(prior):
|
|
2449
|
+
print("using user provided custom external_shear function")
|
|
2450
|
+
self._external_shear = FunctionConditioning(function=None, x_array=None, create_rvs=prior)
|
|
2451
|
+
elif isinstance(prior, object):
|
|
2452
|
+
print("using user provided custom external_shear class/object")
|
|
2453
|
+
self._external_shear = prior
|
|
2454
|
+
else:
|
|
2455
|
+
raise ValueError("prior not in available_lens_prior_list_and_its_params['external_shear']")
|
|
2456
|
+
|
|
2457
|
+
@property
|
|
2458
|
+
def external_shear_sl(self):
|
|
2459
|
+
return self._external_shear_sl
|
|
2460
|
+
|
|
2461
|
+
@external_shear_sl.setter
|
|
2462
|
+
def external_shear_sl(self, prior):
|
|
2463
|
+
if prior in self.available_lens_prior_list_and_its_params["external_shear_sl"]:
|
|
2464
|
+
print(f"using ler available external_shear_sl function : {prior}")
|
|
2465
|
+
args = self.lens_param_samplers_params["external_shear_sl"]
|
|
2466
|
+
if args is None:
|
|
2467
|
+
self._external_shear_sl = getattr(self, prior)(size=None, get_attribute=True)
|
|
2468
|
+
else:
|
|
2469
|
+
self._external_shear_sl = getattr(self, prior)(size=None, get_attribute=True, **args)
|
|
2470
|
+
elif callable(prior):
|
|
2471
|
+
print("using user provided custom external_shear_sl function")
|
|
2472
|
+
self._external_shear_sl = FunctionConditioning(function=None, x_array=None, create_rvs=prior)
|
|
2473
|
+
elif isinstance(prior, object):
|
|
2474
|
+
print("using user provided custom external_shear_sl class/object")
|
|
2475
|
+
self._external_shear_sl = prior
|
|
2476
|
+
else:
|
|
2477
|
+
raise ValueError("prior not in available_lens_prior_list_and_its_params['external_shear_sl']")
|
|
2478
|
+
|
|
2479
|
+
@property
|
|
2480
|
+
def density_profile_slope(self):
|
|
2481
|
+
return self._density_profile_slope
|
|
2482
|
+
|
|
2483
|
+
@density_profile_slope.setter
|
|
2484
|
+
def density_profile_slope(self, prior):
|
|
2485
|
+
if prior in self.available_lens_prior_list_and_its_params["density_profile_slope"]:
|
|
2486
|
+
print(f"using ler available density_profile_slope function : {prior}")
|
|
2487
|
+
args = self.lens_param_samplers_params["density_profile_slope"]
|
|
2488
|
+
if args is None:
|
|
2489
|
+
self._density_profile_slope = getattr(self, prior)(size=None, get_attribute=True)
|
|
2490
|
+
else:
|
|
2491
|
+
self._density_profile_slope = getattr(self, prior)(size=None, get_attribute=True, **args)
|
|
2492
|
+
elif callable(prior):
|
|
2493
|
+
print("using user provided custom density_profile_slope function")
|
|
2494
|
+
self._density_profile_slope = FunctionConditioning(function=None, x_array=None, create_rvs=prior)
|
|
2495
|
+
elif isinstance(prior, object):
|
|
2496
|
+
print("using user provided custom density_profile_slope class/object")
|
|
2497
|
+
self._density_profile_slope = prior
|
|
2498
|
+
else:
|
|
2499
|
+
raise ValueError("prior not in available_lens_prior_list_and_its_params['density_profile_slope']")
|
|
2500
|
+
|
|
2501
|
+
@property
|
|
2502
|
+
def density_profile_slope_sl(self):
|
|
2503
|
+
return self._density_profile_slope_sl
|
|
963
2504
|
|
|
2505
|
+
@density_profile_slope_sl.setter
|
|
2506
|
+
def density_profile_slope_sl(self, prior):
|
|
2507
|
+
if prior in self.available_lens_prior_list_and_its_params["density_profile_slope_sl"]:
|
|
2508
|
+
print(f"using ler available density_profile_slope_sl function : {prior}")
|
|
2509
|
+
args = self.lens_param_samplers_params["density_profile_slope_sl"]
|
|
2510
|
+
if args is None:
|
|
2511
|
+
self._density_profile_slope_sl = getattr(self, prior)(size=None, get_attribute=True)
|
|
2512
|
+
else:
|
|
2513
|
+
self._density_profile_slope_sl = getattr(self, prior)(size=None, get_attribute=True, **args)
|
|
2514
|
+
elif callable(prior):
|
|
2515
|
+
print("using user provided custom density_profile_slope_sl function")
|
|
2516
|
+
self._density_profile_slope_sl = FunctionConditioning(function=None, x_array=None, create_rvs=prior)
|
|
2517
|
+
elif isinstance(prior, object):
|
|
2518
|
+
print("using user provided custom density_profile_slope_sl class/object")
|
|
2519
|
+
self._density_profile_slope_sl = prior
|
|
2520
|
+
else:
|
|
2521
|
+
raise ValueError("prior not in available_lens_prior_list_and_its_params['density_profile_slope_sl']")
|
|
2522
|
+
|
|
2523
|
+
|
|
2524
|
+
####################################
|
|
2525
|
+
# Available samplers and functions #
|
|
2526
|
+
####################################
|
|
964
2527
|
@property
|
|
965
|
-
def
|
|
2528
|
+
def available_lens_prior_list_and_its_params(self):
|
|
966
2529
|
"""
|
|
967
|
-
|
|
2530
|
+
Dictionary with list all the available priors and it's corresponding parameters. This is an immutable instance attribute.
|
|
968
2531
|
"""
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
2532
|
+
|
|
2533
|
+
self._available_lens_prior_list_and_its_params = dict(
|
|
2534
|
+
source_redshift_sl = dict(
|
|
2535
|
+
strongly_lensed_source_redshifts=None
|
|
2536
|
+
),
|
|
2537
|
+
lens_redshift=dict(
|
|
2538
|
+
lens_redshift_SDSS_catalogue_sis=None,
|
|
2539
|
+
lens_redshift_SDSS_catalogue_numerical=None,
|
|
2540
|
+
lens_redshift_SDSS_catalogue_hemanta=None,
|
|
2541
|
+
),
|
|
2542
|
+
velocity_dispersion = dict(
|
|
2543
|
+
velocity_dispersion_gengamma = dict(
|
|
2544
|
+
sigma_min=100., sigma_max=400., alpha=0.94, beta=1.85, phistar=2.099e-2*(self.cosmo.h/0.7)**3, sigmastar=113.78
|
|
2545
|
+
),
|
|
2546
|
+
velocity_dispersion_choi = dict(
|
|
2547
|
+
sigma_min=100., sigma_max=400., alpha = 2.32, beta = 2.67, phistar = 8.0e-3*self.cosmo.h**3, sigmastar = 161.0
|
|
2548
|
+
),
|
|
2549
|
+
velocity_dispersion_bernardi = dict(
|
|
2550
|
+
sigma_min=100., sigma_max=400., alpha=0.94, beta=1.85, phistar=2.099e-2*(self.cosmo.h/0.7)**3, sigmastar=113.78
|
|
2551
|
+
),
|
|
2552
|
+
velocity_dispersion_ewoud = dict(
|
|
2553
|
+
sigma_min=100., sigma_max=400., alpha=0.94, beta=1.85, phistar=2.099e-2*(self.cosmo.h/0.7)**3, sigmastar=113.78
|
|
2554
|
+
),
|
|
2555
|
+
),
|
|
2556
|
+
axis_ratio = dict(
|
|
2557
|
+
axis_ratio_rayleigh = dict(q_min=0.2, q_max=1.0),
|
|
2558
|
+
axis_ratio_padilla_strauss = dict(q_min=0.2, q_max=1.0),
|
|
2559
|
+
axis_ratio_uniform = dict(q_min=0.2, q_max=1.0),
|
|
2560
|
+
),
|
|
2561
|
+
axis_rotation_angle = dict(
|
|
2562
|
+
axis_rotation_angle_uniform = dict(
|
|
2563
|
+
phi_min=0.0, phi_max=2 * np.pi
|
|
2564
|
+
),
|
|
2565
|
+
),
|
|
2566
|
+
external_shear = dict(
|
|
2567
|
+
external_shear_normal = dict(mean=0., std=0.05),
|
|
2568
|
+
),
|
|
2569
|
+
external_shear_sl = dict(
|
|
2570
|
+
external_shear_normal = dict(mean=0., std=0.05, name="external_shear_normal_sl"),
|
|
2571
|
+
external_shear_sl_numerical_hemanta = dict(external_shear_normal=dict(mean=0., std=0.05), name="external_shear_sl_numerical_hemanta"),
|
|
2572
|
+
),
|
|
2573
|
+
density_profile_slope = dict(
|
|
2574
|
+
density_profile_slope_normal=dict(mean=1.99, std=0.149),
|
|
2575
|
+
),
|
|
2576
|
+
density_profile_slope_sl = dict(
|
|
2577
|
+
density_profile_slope_normal=dict(mean=2.091, std=0.133, name="density_profile_slope_normal_sl"),
|
|
2578
|
+
density_profile_slope_sl_numerical_hemanta=dict(density_profile_slope_normal=dict(mean=1.99, std=0.149), name="density_profile_slope_sl_numerical_hemanta"),
|
|
2579
|
+
),
|
|
2580
|
+
source_parameters=dict(
|
|
2581
|
+
sample_gw_parameters=None
|
|
2582
|
+
),
|
|
973
2583
|
)
|
|
974
2584
|
|
|
975
|
-
return self.
|
|
2585
|
+
return self._available_lens_prior_list_and_its_params
|
|
976
2586
|
|
|
977
2587
|
@property
|
|
978
|
-
def
|
|
2588
|
+
def available_lens_functions_and_its_params(self):
|
|
979
2589
|
"""
|
|
980
|
-
|
|
2590
|
+
Dictionary with list all the available lens functions. This is an immutable instance attribute.
|
|
981
2591
|
"""
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
2592
|
+
|
|
2593
|
+
self._available_lens_functions_and_its_params = dict(
|
|
2594
|
+
strong_lensing_condition=dict(
|
|
2595
|
+
rjs_with_cross_section_sie_feixu=None,
|
|
2596
|
+
rjs_with_cross_section_sis=None,
|
|
2597
|
+
rjs_with_cross_section_mp=None,
|
|
2598
|
+
),
|
|
2599
|
+
optical_depth=dict(
|
|
2600
|
+
optical_depth_sis_haris=None,
|
|
2601
|
+
optical_depth_sie_hemanta=None,
|
|
2602
|
+
optical_depth_epl_shear_hemanta=None,
|
|
2603
|
+
optical_depth_numerical=None,
|
|
2604
|
+
),
|
|
2605
|
+
param_sampler_type=dict(
|
|
2606
|
+
sample_all_routine_sie_sl=None,
|
|
2607
|
+
sample_all_routine_sis_sl=None,
|
|
2608
|
+
sample_all_routine_epl_shear_sl=None,
|
|
2609
|
+
),
|
|
2610
|
+
cross_section=dict(
|
|
2611
|
+
cross_section_sie_feixu=None,
|
|
2612
|
+
cross_section_sis=None,
|
|
2613
|
+
cross_section_caustic_area=None,
|
|
2614
|
+
interpolated_cross_section_function=None,
|
|
2615
|
+
),
|
|
986
2616
|
)
|
|
987
|
-
|
|
2617
|
+
|
|
2618
|
+
return self._available_lens_functions_and_its_params
|
|
2619
|
+
|
|
988
2620
|
|
|
989
2621
|
|
|
990
2622
|
|