ler 0.3.7__py3-none-any.whl → 0.3.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ler might be problematic. Click here for more details.
- ler/__init__.py +1 -1
- ler/gw_source_population/cbc_source_parameter_distribution.py +74 -31
- ler/gw_source_population/cbc_source_redshift_distribution.py +37 -28
- ler/gw_source_population/jit_functions.py +1 -1
- ler/image_properties/image_properties.py +46 -23
- ler/image_properties/multiprocessing_routine.py +26 -11
- ler/lens_galaxy_population/jit_functions.py +1 -0
- ler/lens_galaxy_population/lens_galaxy_parameter_distribution.py +23 -23
- ler/lens_galaxy_population/optical_depth.py +20 -18
- ler/rates/gwrates.py +593 -205
- ler/rates/ler copy.py +2097 -0
- ler/rates/ler.py +1068 -577
- ler/utils/plots.py +266 -223
- ler/utils/utils.py +44 -10
- {ler-0.3.7.dist-info → ler-0.3.9.dist-info}/METADATA +2 -2
- ler-0.3.9.dist-info/RECORD +25 -0
- {ler-0.3.7.dist-info → ler-0.3.9.dist-info}/WHEEL +1 -1
- ler-0.3.7.dist-info/RECORD +0 -24
- {ler-0.3.7.dist-info → ler-0.3.9.dist-info}/LICENSE +0 -0
- {ler-0.3.7.dist-info → ler-0.3.9.dist-info}/top_level.txt +0 -0
ler/utils/plots.py
CHANGED
|
@@ -63,13 +63,14 @@ def param_plot(
|
|
|
63
63
|
Examples
|
|
64
64
|
----------
|
|
65
65
|
>>> import matplotlib.pyplot as plt
|
|
66
|
+
>>> from ler.utils import param_plot
|
|
66
67
|
>>> from ler.rates import LeR
|
|
67
|
-
>>> ler = LeR()
|
|
68
|
+
>>> ler = LeR(verbose=False)
|
|
68
69
|
>>> param = ler.unlensed_cbc_statistics();
|
|
69
70
|
>>> rate, param_detectable = ler.unlensed_rate()
|
|
70
71
|
>>> plt.figure(figsize=(6, 4))
|
|
71
|
-
>>>
|
|
72
|
-
>>>
|
|
72
|
+
>>> param_plot(param_name='zs', param_dict=param, plot_label='all events')
|
|
73
|
+
>>> param_plot(param_name='zs', param_dict=param_detectable, plot_label='detectable events')
|
|
73
74
|
>>> plt.xlabel('source redshift')
|
|
74
75
|
>>> plt.ylabel('probability density')
|
|
75
76
|
>>> plt.title('source redshift distribution')
|
|
@@ -102,7 +103,7 @@ def param_plot(
|
|
|
102
103
|
plt.plot(x, kde(x), label=plot_label+" kde")
|
|
103
104
|
plt.legend()
|
|
104
105
|
|
|
105
|
-
def relative_mu_dt_unlensed(param, size=100):
|
|
106
|
+
def relative_mu_dt_unlensed(param, size=100, randomize=True):
|
|
106
107
|
"""
|
|
107
108
|
Function to generate relative magnification vs time delay difference for unlensed samples.
|
|
108
109
|
|
|
@@ -111,249 +112,291 @@ def relative_mu_dt_unlensed(param, size=100):
|
|
|
111
112
|
param : `dict`
|
|
112
113
|
dictionary of unlensed GW source parameters.
|
|
113
114
|
unlensed_param.keys() = ['m1', 'm2', 'z', 'snr', 'theta_jn', 'ra', 'dec', 'psi', 'phase', 'geocent_time']
|
|
115
|
+
size : `int`
|
|
116
|
+
number of samples.
|
|
117
|
+
default size = 100.
|
|
118
|
+
randomize : `bool`
|
|
119
|
+
if True, it will randomize the samples.
|
|
120
|
+
default randomize = True.
|
|
114
121
|
|
|
115
122
|
Returns
|
|
116
123
|
----------
|
|
117
124
|
dmu : `float.array`
|
|
118
|
-
relative magnification.
|
|
125
|
+
relative magnification: abs(mu2/mu1) or abs(dl1/dl2)**2.
|
|
119
126
|
dt : `float.array`
|
|
120
|
-
relative time delay.
|
|
121
|
-
|
|
127
|
+
relative time delay: abs(t1-t2) in days.
|
|
122
128
|
"""
|
|
123
129
|
|
|
124
130
|
t = param["geocent_time"]
|
|
125
131
|
mu = param["luminosity_distance"]
|
|
126
|
-
|
|
127
132
|
len_ = len(t)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
133
|
+
# randomize it
|
|
134
|
+
if randomize:
|
|
135
|
+
idx_ = np.random.permutation(len_)
|
|
136
|
+
t = t[idx_]
|
|
137
|
+
mu = mu[idx_]
|
|
138
|
+
|
|
139
|
+
# Ensure enough unique pairs can be formed
|
|
140
|
+
if size > (len(t) * (len(t) - 1)) // 2:
|
|
141
|
+
raise ValueError(f"size should be less than the number of unique pairs {len(t) * (len(t) - 1) // 2}")
|
|
142
|
+
|
|
143
|
+
# Generate unique pairs
|
|
144
|
+
# find idx1 and idx2
|
|
145
|
+
idx1 = np.array([])
|
|
146
|
+
idx2 = np.array([])
|
|
147
|
+
while len(idx1) < size:
|
|
148
|
+
idx1_ = np.random.choice(len_, size=size, replace=True)
|
|
149
|
+
idx2_ = np.random.choice(len_, size=size, replace=True)
|
|
150
|
+
idx1 = np.concatenate((idx1, idx1_))
|
|
151
|
+
idx2 = np.concatenate((idx2, idx2_))
|
|
152
|
+
idx = np.where(idx1 != idx2)[0]
|
|
153
|
+
idx1 = idx1[idx]
|
|
154
|
+
idx2 = idx2[idx]
|
|
155
|
+
idx1 = idx1[:size].astype(int)
|
|
156
|
+
idx2 = idx2[:size].astype(int)
|
|
157
|
+
|
|
158
|
+
dt = abs(t[idx1] - t[idx2]) / (60 * 60 * 24) # in days
|
|
159
|
+
dmu = abs(mu[idx1]/mu[idx2])**2
|
|
160
|
+
|
|
161
|
+
return dmu, dt
|
|
162
|
+
|
|
163
|
+
def relative_mu_dt_lensed(
|
|
164
|
+
lensed_param,
|
|
165
|
+
snr_threshold=[8.0, 8.0],
|
|
166
|
+
classification_type='morse_phase'
|
|
167
|
+
):
|
|
142
168
|
"""
|
|
143
169
|
Function to classify the lensed images wrt to the morse phase difference.
|
|
144
170
|
|
|
145
|
-
|
|
146
|
-
----------
|
|
147
|
-
lensed_param : `dict`
|
|
148
|
-
dictionary of lensed GW source parameters, lens galaxy parameters and image paramters.
|
|
149
|
-
lensed_param.keys() = ['zl', 'zs', 'sigma', 'q', 'e1', 'e2', 'gamma1', 'gamma2', 'Dl',
|
|
150
|
-
'Ds', 'Dls', 'theta_E', 'gamma', 'mass_1', 'mass_2', 'mass_1_source', 'mass_2_source',
|
|
151
|
-
'luminosity_distance', 'theta_jn', 'psi', 'phase', 'geocent_time', 'ra', 'dec', 'n_images',
|
|
152
|
-
'x0_image_positions', 'x1_image_positions', 'magnifications', 'time_delays', 'traces',
|
|
153
|
-
'determinants', 'image_type', 'weights', 'optimal_snr_net', 'L1', 'H1', 'V1']
|
|
154
|
-
snr_threshold : `float`
|
|
155
|
-
threshold for detection signal to noise ratio.
|
|
156
|
-
e.g. snr_threshold = [8.,8.] or [8.,6.] for subthreshold
|
|
157
|
-
|
|
158
|
-
Returns
|
|
159
|
-
----------
|
|
160
|
-
mu_rel0 : `float.array`
|
|
161
|
-
relative magnification for 0 degree phase difference.
|
|
162
|
-
dt_rel0 : `float.array`
|
|
163
|
-
relative time delay for 0 degree phase difference.
|
|
164
|
-
mu_rel90 : `float.array`
|
|
165
|
-
relative magnification for 90 degree phase difference.
|
|
166
|
-
dt_rel90 : `float.array`
|
|
167
|
-
relative time delay for 90 degree phase difference.
|
|
171
|
+
|
|
168
172
|
"""
|
|
169
173
|
|
|
170
174
|
# get magnifications, time_delays and snr
|
|
171
|
-
mu =
|
|
172
|
-
dt =
|
|
173
|
-
snr =
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
#
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
175
|
+
mu = lensed_param["magnifications"]
|
|
176
|
+
dt = lensed_param["time_delays"]
|
|
177
|
+
snr = lensed_param["optimal_snr_net"]
|
|
178
|
+
image_type = lensed_param["image_type"]
|
|
179
|
+
|
|
180
|
+
# pair images wrt to image_type
|
|
181
|
+
if classification_type == 'morse_phase':
|
|
182
|
+
dt_rel0 = []
|
|
183
|
+
mu_rel0 = []
|
|
184
|
+
dt_rel90 = []
|
|
185
|
+
mu_rel90 = []
|
|
186
|
+
for i in range(len(image_type)):
|
|
187
|
+
if image_type[i,0]==image_type[i,1]:
|
|
188
|
+
# snr check
|
|
189
|
+
# below will also take care of the nan values
|
|
190
|
+
if snr[i,0]>snr_threshold[0] and snr[i,1]>snr_threshold[1]:
|
|
191
|
+
dt_rel0.append(abs(dt[i,1]-dt[i,0])/ (60 * 60 * 24))
|
|
192
|
+
mu_rel0.append(abs(mu[i,1]/mu[i,0]))
|
|
193
|
+
else:
|
|
194
|
+
if snr[i,0]>snr_threshold[0] and snr[i,1]>snr_threshold[1]:
|
|
195
|
+
dt_rel90.append(abs(dt[i,1]-dt[i,0])/ (60 * 60 * 24))
|
|
196
|
+
mu_rel90.append(abs(mu[i,1]/mu[i,0]))
|
|
197
|
+
if image_type[i,0]==image_type[i,2]:
|
|
198
|
+
# snr check
|
|
199
|
+
# below will also take care of the nan values
|
|
200
|
+
if snr[i,0]>snr_threshold[0] and snr[i,2]>snr_threshold[1]:
|
|
201
|
+
dt_rel0.append(abs(dt[i,2]-dt[i,0])/ (60 * 60 * 24))
|
|
202
|
+
mu_rel0.append(abs(mu[i,2]/mu[i,0]))
|
|
203
|
+
else:
|
|
204
|
+
if snr[i,0]>snr_threshold[0] and snr[i,2]>snr_threshold[1]:
|
|
205
|
+
dt_rel90.append(abs(dt[i,2]-dt[i,0])/ (60 * 60 * 24))
|
|
206
|
+
mu_rel90.append(abs(mu[i,2]/mu[i,0]))
|
|
207
|
+
if image_type[i,0]==image_type[i,3]:
|
|
208
|
+
# snr check
|
|
209
|
+
# below will also take care of the nan values
|
|
210
|
+
if snr[i,0]>snr_threshold[0] and snr[i,3]>snr_threshold[1]:
|
|
211
|
+
dt_rel0.append(abs(dt[i,3]-dt[i,0])/ (60 * 60 * 24))
|
|
212
|
+
mu_rel0.append(abs(mu[i,3]/mu[i,0]))
|
|
213
|
+
else:
|
|
214
|
+
if snr[i,0]>snr_threshold[0] and snr[i,3]>snr_threshold[1]:
|
|
215
|
+
dt_rel90.append(abs(dt[i,3]-dt[i,0])/ (60 * 60 * 24))
|
|
216
|
+
mu_rel90.append(abs(mu[i,3]/mu[i,0]))
|
|
217
|
+
if image_type[i,1]==image_type[i,2]:
|
|
218
|
+
# snr check
|
|
219
|
+
# below will also take care of the nan values
|
|
220
|
+
if snr[i,1]>snr_threshold[0] and snr[i,2]>snr_threshold[1]:
|
|
221
|
+
dt_rel0.append(abs(dt[i,2]-dt[i,1])/ (60 * 60 * 24))
|
|
222
|
+
mu_rel0.append(abs(mu[i,2]/mu[i,1]))
|
|
223
|
+
else:
|
|
224
|
+
if snr[i,1]>snr_threshold[0] and snr[i,2]>snr_threshold[1]:
|
|
225
|
+
dt_rel90.append(abs(dt[i,2]-dt[i,1])/ (60 * 60 * 24))
|
|
226
|
+
mu_rel90.append(abs(mu[i,2]/mu[i,1]))
|
|
227
|
+
if image_type[i,1]==image_type[i,3]:
|
|
228
|
+
# snr check
|
|
229
|
+
# below will also take care of the nan values
|
|
230
|
+
if snr[i,1]>snr_threshold[0] and snr[i,3]>snr_threshold[1]:
|
|
231
|
+
dt_rel0.append(abs(dt[i,3]-dt[i,1])/ (60 * 60 * 24))
|
|
232
|
+
mu_rel0.append(abs(mu[i,3]/mu[i,1]))
|
|
233
|
+
else:
|
|
234
|
+
if snr[i,1]>snr_threshold[0] and snr[i,3]>snr_threshold[1]:
|
|
235
|
+
dt_rel90.append(abs(dt[i,3]-dt[i,1])/ (60 * 60 * 24))
|
|
236
|
+
mu_rel90.append(abs(mu[i,3]/mu[i,1]))
|
|
237
|
+
if image_type[i,2]==image_type[i,3]:
|
|
238
|
+
# snr check
|
|
239
|
+
# below will also take care of the nan values
|
|
240
|
+
if snr[i,2]>snr_threshold[0] and snr[i,3]>snr_threshold[1]:
|
|
241
|
+
dt_rel0.append(abs(dt[i,3]-dt[i,2])/ (60 * 60 * 24))
|
|
242
|
+
mu_rel0.append(abs(mu[i,3]/mu[i,2]))
|
|
243
|
+
else:
|
|
244
|
+
if snr[i,2]>snr_threshold[0] and snr[i,3]>snr_threshold[1]:
|
|
245
|
+
dt_rel90.append(abs(dt[i,3]-dt[i,2])/ (60 * 60 * 24))
|
|
246
|
+
mu_rel90.append(abs(mu[i,3]/mu[i,2]))
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
"dt_rel0": np.array(dt_rel0), "mu_rel0": np.array(mu_rel0),
|
|
250
|
+
"dt_rel90": np.array(dt_rel90), "mu_rel90": np.array(mu_rel90),
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if classification_type == 'arrival_time':
|
|
254
|
+
print('classification_type = arrival_time')
|
|
255
|
+
print('make sure that the images are sorted wrt to arrival time')
|
|
256
|
+
print('direct output from "ler" should be sorted')
|
|
257
|
+
dt_12, dt_13, dt_14, dt_23, dt_24, dt_34 = [], [], [], [], [], []
|
|
258
|
+
mu_12, mu_13, mu_14, mu_23, mu_24, mu_34 = [], [], [], [], [], []
|
|
259
|
+
|
|
260
|
+
for i in range(len(image_type)):
|
|
261
|
+
if snr[i,0]>snr_threshold[0] and snr[i,1]>snr_threshold[1]:
|
|
262
|
+
dt_12.append(abs(dt[i,1]-dt[i,0])/ (60 * 60 * 24))
|
|
263
|
+
mu_12.append(abs(mu[i,1]/mu[i,0]))
|
|
264
|
+
if snr[i,0]>snr_threshold[0] and snr[i,2]>snr_threshold[1]:
|
|
265
|
+
dt_13.append(abs(dt[i,2]-dt[i,0])/ (60 * 60 * 24))
|
|
266
|
+
mu_13.append(abs(mu[i,2]/mu[i,0]))
|
|
267
|
+
if snr[i,0]>snr_threshold[0] and snr[i,3]>snr_threshold[1]:
|
|
268
|
+
dt_14.append(abs(dt[i,3]-dt[i,0])/ (60 * 60 * 24))
|
|
269
|
+
mu_14.append(abs(mu[i,3]/mu[i,0]))
|
|
270
|
+
if snr[i,1]>snr_threshold[0] and snr[i,2]>snr_threshold[1]:
|
|
271
|
+
dt_23.append(abs(dt[i,2]-dt[i,1])/ (60 * 60 * 24))
|
|
272
|
+
mu_23.append(abs(mu[i,2]/mu[i,1]))
|
|
273
|
+
if snr[i,1]>snr_threshold[0] and snr[i,3]>snr_threshold[1]:
|
|
274
|
+
dt_24.append(abs(dt[i,3]-dt[i,1])/ (60 * 60 * 24))
|
|
275
|
+
mu_24.append(abs(mu[i,3]/mu[i,1]))
|
|
276
|
+
if snr[i,2]>snr_threshold[0] and snr[i,3]>snr_threshold[1]:
|
|
277
|
+
dt_34.append(abs(dt[i,3]-dt[i,2])/ (60 * 60 * 24))
|
|
278
|
+
mu_34.append(abs(mu[i,3]/mu[i,2]))
|
|
279
|
+
|
|
280
|
+
return {
|
|
281
|
+
"dt_12": np.array(dt_12), "mu_12": np.array(mu_12),
|
|
282
|
+
"dt_13": np.array(dt_13), "mu_13": np.array(mu_13),
|
|
283
|
+
"dt_14": np.array(dt_14), "mu_14": np.array(mu_14),
|
|
284
|
+
"dt_23": np.array(dt_23), "mu_23": np.array(mu_23),
|
|
285
|
+
"dt_24": np.array(dt_24), "mu_24": np.array(mu_24),
|
|
286
|
+
"dt_34": np.array(dt_34), "mu_34": np.array(mu_34),
|
|
287
|
+
}
|
|
247
288
|
|
|
248
289
|
def mu_vs_dt_plot(
|
|
249
290
|
x_array,
|
|
250
291
|
y_array,
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
colors="blue",
|
|
254
|
-
linestyles="-",
|
|
255
|
-
origin="upper",
|
|
292
|
+
xscale = 'log10',
|
|
293
|
+
yscale = 'log10',
|
|
256
294
|
alpha=0.6,
|
|
257
|
-
extent=
|
|
258
|
-
contour_levels=[
|
|
295
|
+
extent=None,
|
|
296
|
+
contour_levels=[10, 40, 68, 95],
|
|
297
|
+
colors=['blue', 'blue', 'blue', 'blue', 'blue'],
|
|
259
298
|
):
|
|
260
299
|
"""
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
300
|
+
Function to generate 2D KDE and plot the relative magnification vs time delay difference for lensed samples.
|
|
301
|
+
|
|
302
|
+
Parameters
|
|
303
|
+
----------
|
|
304
|
+
x_array : `float.array`
|
|
305
|
+
x array.
|
|
306
|
+
y_array : `float.array`
|
|
307
|
+
y array.
|
|
308
|
+
xscale : `str`
|
|
309
|
+
x-axis scale.
|
|
310
|
+
default xscale = 'log10'. other options: 'log', None.
|
|
311
|
+
yscale : `str`
|
|
312
|
+
y-axis scale.
|
|
313
|
+
default yscale = 'log10'. other options: 'log', None.
|
|
314
|
+
alpha : `float`
|
|
315
|
+
transparency of the contour plot.
|
|
316
|
+
default alpha = 0.6.
|
|
317
|
+
extent : `list`
|
|
318
|
+
extent of the plot.
|
|
319
|
+
default extent = None. It will consider the full range of x_array and y_array.
|
|
320
|
+
contour_levels : `list`
|
|
321
|
+
levels for contour plot.
|
|
322
|
+
default contour_levels = [10, 40, 68, 95].
|
|
323
|
+
colors : `str`
|
|
324
|
+
colors for contour plot.
|
|
325
|
+
default colors = ['blue', 'blue', 'blue', 'blue', 'blue'].
|
|
326
|
+
|
|
327
|
+
Examples
|
|
328
|
+
----------
|
|
329
|
+
>>> import numpy as np
|
|
330
|
+
>>> import matplotlib.pyplot as plt
|
|
331
|
+
>>> from ler.utils import param_plot, mu_vs_dt_plot, get_param_from_json, relative_mu_dt_unlensed, relative_mu_dt_lensed
|
|
332
|
+
>>> # get the parameters. For data generation, refer to the 'LeR complete example' in the documentation.
|
|
333
|
+
>>> unlensed_param = get_param_from_json('ler_data/unlensed_param.json')
|
|
334
|
+
>>> unlensed_param_detectable = get_param_from_json('ler_data/unlensed_param_detectable.json')
|
|
335
|
+
>>> lensed_param = get_param_from_json('ler_data/lensed_param.json')
|
|
336
|
+
>>> lensed_param_detectable = get_param_from_json('ler_data/lensed_param_detectable.json')
|
|
337
|
+
>>> # get the relative mu and dt
|
|
338
|
+
>>> ans = relative_mu_dt_lensed(lensed_param_detectable)
|
|
339
|
+
>>> dmu, dt = relative_mu_dt_unlensed(unlensed_param_detectable, size=1000, randomize=True)
|
|
340
|
+
>>> # plot
|
|
341
|
+
>>> plt.figure(figsize=(4, 4))
|
|
342
|
+
>>> mu_vs_dt_plot(ans['dt_rel90'], ans['mu_rel90'], colors='b')
|
|
343
|
+
>>> mu_vs_dt_plot(ans['dt_rel0'], ans['mu_rel0'], colors='g')
|
|
344
|
+
>>> mu_vs_dt_plot(dt, dmu, colors='r')
|
|
345
|
+
>>> # Create proxy artists for legend
|
|
346
|
+
>>> proxy1 = plt.Line2D([0], [0], linestyle='-', color='b', label=r'Lensed ($\Delta \phi=90$)')
|
|
347
|
+
>>> proxy2 = plt.Line2D([0], [0], linestyle='-', color='g', label=r'Lensed ($\Delta \phi=0$)')
|
|
348
|
+
>>> proxy3 = plt.Line2D([0], [0], linestyle='-', color='r', label=r'Unlensed')
|
|
349
|
+
>>> plt.legend(handles=[proxy1, proxy2, proxy3], loc='upper left')
|
|
350
|
+
>>> plt.xlim(-5, 2.5)
|
|
351
|
+
>>> plt.ylim(-2.5, 2.5)
|
|
352
|
+
>>> plt.grid(alpha=0.4)
|
|
353
|
+
>>> plt.show()
|
|
354
|
+
"""
|
|
299
355
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
356
|
+
x_min = min(x_array)
|
|
357
|
+
x_max = max(x_array)
|
|
358
|
+
y_min = min(y_array)
|
|
359
|
+
y_max = max(y_array)
|
|
303
360
|
|
|
304
|
-
"""
|
|
305
361
|
# applying cutt-off
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
& (x_array
|
|
309
|
-
& (y_array
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
levels = []
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
extent=np.log10(extent),
|
|
347
|
-
)
|
|
348
|
-
|
|
349
|
-
# labels
|
|
350
|
-
ax.xlabel(r"$log_{10}\Delta t$ (days)")
|
|
351
|
-
ax.ylabel(r"$\Delta log_{10}\mu$")
|
|
352
|
-
ax.title(r"relative magnification vs relative time delay")
|
|
353
|
-
|
|
354
|
-
# save figure
|
|
355
|
-
if savefig:
|
|
356
|
-
ax.savefig("mu_vs_dt.png", dpi=300, bbox_inches="tight")
|
|
357
|
-
|
|
358
|
-
return None
|
|
362
|
+
if extent:
|
|
363
|
+
x_min, x_max, y_min, y_max = extent
|
|
364
|
+
x_array = x_array[(x_array >= x_min) & (x_array <= x_max)]
|
|
365
|
+
y_array = y_array[(y_array >= y_min) & (y_array <= y_max)]
|
|
366
|
+
|
|
367
|
+
# convert to log scale
|
|
368
|
+
if xscale == 'log10':
|
|
369
|
+
x_array = np.log10(x_array)
|
|
370
|
+
x_min = np.log10(x_min)
|
|
371
|
+
x_max = np.log10(x_max)
|
|
372
|
+
if yscale == 'log10':
|
|
373
|
+
y_array = np.log10(y_array)
|
|
374
|
+
y_min = np.log10(y_min)
|
|
375
|
+
y_max = np.log10(y_max)
|
|
376
|
+
if xscale == 'log':
|
|
377
|
+
x_array = np.log(x_array)
|
|
378
|
+
x_min = np.log(x_min)
|
|
379
|
+
x_max = np.log(x_max)
|
|
380
|
+
if yscale == 'log':
|
|
381
|
+
y_array = np.log(y_array)
|
|
382
|
+
y_min = np.log(y_min)
|
|
383
|
+
y_max = np.log(y_max)
|
|
384
|
+
|
|
385
|
+
# Perform a kernel density estimation (KDE)
|
|
386
|
+
xy = np.vstack([x_array, y_array])
|
|
387
|
+
kde = gaussian_kde(xy)(xy)
|
|
388
|
+
|
|
389
|
+
# Define the levels for contour as percentiles of the density
|
|
390
|
+
levels = np.percentile(kde, [10, 40, 68, 95])
|
|
391
|
+
|
|
392
|
+
# Create a grid for contour plot
|
|
393
|
+
xgrid = np.linspace(x_min, x_max, 1000)
|
|
394
|
+
ygrid = np.linspace(y_min, y_max, 1000)
|
|
395
|
+
X1, Y1 = np.meshgrid(xgrid, ygrid)
|
|
396
|
+
Z1 = gaussian_kde(xy)(np.vstack([X1.ravel(), Y1.ravel()])).reshape(X1.shape)
|
|
397
|
+
|
|
398
|
+
if isinstance(colors, str):
|
|
399
|
+
colors = [colors] * len(contour_levels)
|
|
400
|
+
|
|
401
|
+
plt.contour(X1, Y1, Z1, levels=levels, colors=colors, alpha=alpha)
|
|
359
402
|
|
ler/utils/utils.py
CHANGED
|
@@ -69,15 +69,37 @@ def load_json(file_name):
|
|
|
69
69
|
|
|
70
70
|
return param
|
|
71
71
|
|
|
72
|
-
def
|
|
73
|
-
"""
|
|
72
|
+
def save_json(file_name, param):
|
|
73
|
+
"""Save a dictionary as a json file.
|
|
74
74
|
|
|
75
75
|
Parameters
|
|
76
76
|
----------
|
|
77
77
|
file_name : `str`
|
|
78
78
|
json file name for storing the parameters.
|
|
79
|
+
param : `dict`
|
|
80
|
+
dictionary to be saved as a json file.
|
|
81
|
+
"""
|
|
82
|
+
with open(file_name, "w", encoding="utf-8") as write_file:
|
|
83
|
+
json.dump(param, write_file)
|
|
84
|
+
|
|
85
|
+
def append_json(file_name, new_dictionary, old_dictionary=None, replace=False):
|
|
86
|
+
"""
|
|
87
|
+
Append (values with corresponding keys) and update a json file with a dictionary. There are four options:
|
|
88
|
+
|
|
89
|
+
1. If old_dictionary is provided, the values of the new dictionary will be appended to the old dictionary and save in the 'file_name' json file.
|
|
90
|
+
2. If replace is True, replace the json file (with the 'file_name') content with the new_dictionary.
|
|
91
|
+
3. If the file does not exist, create a new one with the new_dictionary.
|
|
92
|
+
4. If none of the above, append the new dictionary to the content of the json file.
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
file_name : `str`
|
|
97
|
+
json file name for storing the parameters.
|
|
79
98
|
new_dictionary : `dict`
|
|
80
99
|
dictionary to be appended to the json file.
|
|
100
|
+
old_dictionary : `dict`, optional
|
|
101
|
+
If provided the values of the new dictionary will be appended to the old dictionary and save in the 'file_name' json file.
|
|
102
|
+
Default is None.
|
|
81
103
|
replace : `bool`, optional
|
|
82
104
|
If True, replace the json file with the dictionary. Default is False.
|
|
83
105
|
|
|
@@ -139,7 +161,7 @@ def add_dict_values(dict1, dict2):
|
|
|
139
161
|
data_key = dict1.keys()
|
|
140
162
|
for key, value in dict2.items():
|
|
141
163
|
if key in data_key:
|
|
142
|
-
dict1[key] = np.concatenate((dict1[key], value))
|
|
164
|
+
dict1[key] = np.concatenate((dict1[key], value))
|
|
143
165
|
|
|
144
166
|
return dict1
|
|
145
167
|
|
|
@@ -187,15 +209,24 @@ def rejection_sample(pdf, xmin, xmax, size=100, chunk_size=10000):
|
|
|
187
209
|
"""
|
|
188
210
|
x = np.linspace(xmin, xmax, chunk_size)
|
|
189
211
|
y = pdf(x)
|
|
212
|
+
# Maximum value of the pdf
|
|
190
213
|
ymax = np.max(y)
|
|
214
|
+
|
|
191
215
|
# Rejection sample in chunks
|
|
192
216
|
x_sample = []
|
|
193
217
|
while len(x_sample) < size:
|
|
194
218
|
x_try = np.random.uniform(xmin, xmax, size=chunk_size)
|
|
219
|
+
pdf_x_try = pdf(x_try) # Calculate the pdf at the random x values
|
|
220
|
+
# this is for comparing with the pdf value at x_try, will be used to accept or reject the sample
|
|
195
221
|
y_try = np.random.uniform(0, ymax, size=chunk_size)
|
|
196
|
-
|
|
222
|
+
|
|
223
|
+
# Update the maximum value of the pdf
|
|
224
|
+
ymax = max(ymax, np.max(pdf_x_try))
|
|
225
|
+
|
|
226
|
+
# applying condition to accept the sample
|
|
197
227
|
# Add while retaining 1D shape of the list
|
|
198
|
-
x_sample += list(x_try[y_try <
|
|
228
|
+
x_sample += list(x_try[y_try < pdf_x_try])
|
|
229
|
+
|
|
199
230
|
# Transform the samples to a 1D numpy array
|
|
200
231
|
x_sample = np.array(x_sample).flatten()
|
|
201
232
|
# Return the correct number of samples
|
|
@@ -228,11 +259,11 @@ def rejection_sample2d(pdf, xmin, xmax, ymin, ymax, size=100, chunk_size=10000):
|
|
|
228
259
|
x_sample : `numpy.ndarray`
|
|
229
260
|
samples from the pdf in the x-axis.
|
|
230
261
|
"""
|
|
231
|
-
chunk_size = 10000
|
|
232
262
|
|
|
233
263
|
x = np.random.uniform(xmin, xmax, chunk_size)
|
|
234
264
|
y = np.random.uniform(ymin, ymax, chunk_size)
|
|
235
265
|
z = pdf(x, y)
|
|
266
|
+
# Maximum value of the pdf
|
|
236
267
|
zmax = np.max(z)
|
|
237
268
|
|
|
238
269
|
# Rejection sample in chunks
|
|
@@ -241,12 +272,15 @@ def rejection_sample2d(pdf, xmin, xmax, ymin, ymax, size=100, chunk_size=10000):
|
|
|
241
272
|
while len(x_sample) < size:
|
|
242
273
|
x_try = np.random.uniform(xmin, xmax, size=chunk_size)
|
|
243
274
|
y_try = np.random.uniform(ymin, ymax, size=chunk_size)
|
|
244
|
-
|
|
275
|
+
pdf_xy_try = pdf(x_try, y_try)
|
|
276
|
+
# this is for comparing with the pdf value at x_try, will be used to accept or reject the sample
|
|
245
277
|
z_try = np.random.uniform(0, zmax, size=chunk_size)
|
|
246
|
-
|
|
278
|
+
|
|
279
|
+
# Update the maximum value of the pdf
|
|
280
|
+
zmax = max(zmax, np.max(pdf_xy_try))
|
|
247
281
|
|
|
248
|
-
x_sample += list(x_try[z_try <
|
|
249
|
-
y_sample += list(y_try[z_try <
|
|
282
|
+
x_sample += list(x_try[z_try < pdf_xy_try])
|
|
283
|
+
y_sample += list(y_try[z_try < pdf_xy_try])
|
|
250
284
|
|
|
251
285
|
# Transform the samples to a 1D numpy array
|
|
252
286
|
x_sample = np.array(x_sample).flatten()
|