@@ -32,6 +32,10 @@ def __init__(self, name, maptree, response_file, roi, flat_sky_pixels_sizes=0.17
32
32
# Store ROI
33
33
self ._roi = roi
34
34
35
+ # Set up the flat-sky projection
36
+
37
+ self ._flat_sky_projection = roi .get_flat_sky_projection (flat_sky_pixels_sizes )
38
+
35
39
# Read map tree (data)
36
40
37
41
self ._maptree = map_tree_factory (maptree , roi = roi )
@@ -65,12 +69,10 @@ def __init__(self, name, maptree, response_file, roi, flat_sky_pixels_sizes=0.17
65
69
self ._convolved_ext_sources = ConvolvedSourcesContainer ()
66
70
67
71
# By default all energy/nHit bins are used
68
- self ._all_planes = range (len (self ._maptree ))
69
- self ._active_planes = range (len (self ._maptree ))
70
-
71
- # Set up the flat-sky projection
72
+ self ._all_planes = list (self ._maptree .analysis_bins_labels )
72
73
73
- self ._flat_sky_projection = roi .get_flat_sky_projection (flat_sky_pixels_sizes )
74
+ # The active planes list always contains the list of *indexes* of the active planes
75
+ self ._active_planes_idx = range (len (self ._maptree ))
74
76
75
77
# Set up the transformations from the flat-sky projection to Healpix, as well as the list of active pixels
76
78
# (one for each energy/nHit bin). We make a separate transformation because different energy bins might have
@@ -132,7 +134,7 @@ def _compute_likelihood_biases(self):
132
134
obs = data_analysis_bin .observation_map .as_partial ()
133
135
bkg = data_analysis_bin .background_map .as_partial ()
134
136
135
- sat_model = np .maximum (obs - bkg , 1e-30 ).astype (np .float64 )
137
+ sat_model = np .clip (obs - bkg , 1e-50 , None ).astype (np .float64 )
136
138
137
139
self ._saturated_model_like_per_maptree [i ] = log_likelihood (obs , bkg , sat_model ) - this_log_factorial
138
140
@@ -144,11 +146,45 @@ def get_saturated_model_likelihood(self):
144
146
"""
145
147
return np .sum (self ._saturated_model_like_per_maptree )
146
148
147
- def set_active_measurements (self , bin_id_min , bin_id_max ):
149
+ def set_active_measurements (self , bin_id_min = None , bin_id_max = None , bin_list = None ):
150
+
151
+ # Check for legal input
152
+ if bin_id_min is not None :
153
+
154
+ assert bin_id_max is not None , "If you provide a minimum bin, you also need to provide a maximum bin"
155
+
156
+ # Make sure they are strings
157
+ bin_id_min = str (bin_id_min )
158
+ bin_id_max = str (bin_id_max )
159
+
160
+ assert bin_id_min in self ._all_planes and bin_id_max in self ._all_planes , "Illegal bin_names"
161
+
162
+ assert bin_list is None , "You can either provide a minimum and maximum bin, or a bin list, but not both"
148
163
149
- assert bin_id_min in self ._all_planes and bin_id_max in self ._all_planes , "Illegal bin_name numbers"
164
+ idx1 = self ._all_planes .index (bin_id_min )
165
+ idx2 = self ._all_planes .index (bin_id_max )
150
166
151
- self ._active_planes = range (bin_id_min , bin_id_max + 1 )
167
+ self ._active_planes_idx = range (idx1 , idx2 + 1 )
168
+
169
+ else :
170
+
171
+ assert bin_id_max is None , "If you provide a maximum bin, you also need to provide a minimum bin"
172
+
173
+ assert bin_list is not None
174
+
175
+ self ._active_planes_idx = []
176
+
177
+ for this_bin in bin_list :
178
+
179
+ try :
180
+
181
+ this_idx = self ._all_planes .index (str (this_bin ))
182
+
183
+ except ValueError :
184
+
185
+ raise ValueError ("Bin %s it not contained in this response" % this_bin )
186
+
187
+ self ._active_planes_idx .append (this_idx )
152
188
153
189
def display (self ):
154
190
@@ -179,7 +215,7 @@ def display(self):
179
215
print ("" )
180
216
print ("Active energy/nHit planes: " )
181
217
print ("---------------------------\n " )
182
- print (self ._active_planes )
218
+ print (self ._active_planes_idx )
183
219
184
220
def set_model (self , likelihood_model_instance ):
185
221
"""
@@ -231,13 +267,13 @@ def display_spectrum(self):
231
267
n_point_sources = self ._likelihood_model .get_number_of_point_sources ()
232
268
n_ext_sources = self ._likelihood_model .get_number_of_extended_sources ()
233
269
234
- total_counts = np .zeros (len (self ._active_planes ), dtype = float )
270
+ total_counts = np .zeros (len (self ._active_planes_idx ), dtype = float )
235
271
total_model = np .zeros_like (total_counts )
236
272
model_only = np .zeros_like (total_counts )
237
273
residuals = np .zeros_like (total_counts )
238
274
net_counts = np .zeros_like (total_counts )
239
275
240
- for i , energy_id in enumerate (self ._active_planes ):
276
+ for i , energy_id in enumerate (self ._active_planes_idx ):
241
277
242
278
data_analysis_bin = self ._maptree [energy_id ]
243
279
@@ -270,11 +306,11 @@ def display_spectrum(self):
270
306
271
307
fig , subs = plt .subplots (2 , 1 , gridspec_kw = {'height_ratios' : [2 , 1 ], 'hspace' : 0 })
272
308
273
- subs [0 ].errorbar (self ._active_planes , net_counts , yerr = np .sqrt (total_counts ),
309
+ subs [0 ].errorbar (self ._active_planes_idx , net_counts , yerr = np .sqrt (total_counts ),
274
310
capsize = 0 ,
275
311
color = 'black' , label = 'Net counts' , fmt = '.' )
276
312
277
- subs [0 ].plot (self ._active_planes , model_only , label = 'Convolved model' )
313
+ subs [0 ].plot (self ._active_planes_idx , model_only , label = 'Convolved model' )
278
314
279
315
subs [0 ].legend (bbox_to_anchor = (1.0 , 1.0 ), loc = "upper right" ,
280
316
numpoints = 1 )
@@ -283,21 +319,21 @@ def display_spectrum(self):
283
319
subs [1 ].axhline (0 , linestyle = '--' )
284
320
285
321
subs [1 ].errorbar (
286
- self ._active_planes , residuals ,
322
+ self ._active_planes_idx , residuals ,
287
323
yerr = np .ones (residuals .shape ),
288
324
capsize = 0 , fmt = '.'
289
325
)
290
326
291
- x_limits = [min (self ._active_planes ) - 0.5 , max (self ._active_planes ) + 0.5 ]
327
+ x_limits = [min (self ._active_planes_idx ) - 0.5 , max (self ._active_planes_idx ) + 0.5 ]
292
328
293
329
subs [0 ].set_yscale ("log" , nonposy = 'clip' )
294
330
subs [0 ].set_ylabel ("Counts per bin" )
295
331
subs [0 ].set_xticks ([])
296
332
297
333
subs [1 ].set_xlabel ("Analysis bin" )
298
334
subs [1 ].set_ylabel (r"$\frac{{cts - mod - bkg}}{\sqrt{mod + bkg}}$" )
299
- subs [1 ].set_xticks (self ._active_planes )
300
- subs [1 ].set_xticklabels (self ._active_planes )
335
+ subs [1 ].set_xticks (self ._active_planes_idx )
336
+ subs [1 ].set_xticklabels (self ._active_planes_idx )
301
337
302
338
subs [0 ].set_xlim (x_limits )
303
339
subs [1 ].set_xlim (x_limits )
@@ -323,16 +359,19 @@ def get_log_like(self):
323
359
324
360
for i , data_analysis_bin in enumerate (self ._maptree ):
325
361
326
- if i not in self ._active_planes :
362
+ if i not in self ._active_planes_idx :
327
363
continue
328
364
329
365
this_model_map_hpx = self ._get_expectation (data_analysis_bin , i , n_point_sources , n_ext_sources )
330
366
331
367
# Now compare with observation
332
368
bkg_renorm = self ._nuisance_parameters .values ()[0 ].value
333
369
334
- this_pseudo_log_like = log_likelihood (data_analysis_bin .observation_map .as_partial (),
335
- data_analysis_bin .background_map .as_partial () * bkg_renorm ,
370
+ obs = data_analysis_bin .observation_map .as_partial () # type: np.array
371
+ bkg = data_analysis_bin .background_map .as_partial () * bkg_renorm # type: np.array
372
+
373
+ this_pseudo_log_like = log_likelihood (obs ,
374
+ bkg ,
336
375
this_model_map_hpx )
337
376
338
377
total_log_like += this_pseudo_log_like - self ._log_factorials [i ] - self ._saturated_model_like_per_maptree [i ]
@@ -364,7 +403,7 @@ def get_simulated_dataset(self, name):
364
403
365
404
for i , data_analysis_bin in enumerate (self ._maptree ):
366
405
367
- if i not in self ._active_planes :
406
+ if i not in self ._active_planes_idx :
368
407
369
408
expectations .append (None )
370
409
@@ -389,7 +428,7 @@ def get_simulated_dataset(self, name):
389
428
# Substitute the observation and background for each data analysis bin
390
429
for i , (data_analysis_bin , orig_data_analysis_bin ) in enumerate (zip (self ._clone [0 ]._maptree , self ._maptree )):
391
430
392
- if i not in self ._active_planes :
431
+ if i not in self ._active_planes_idx :
393
432
394
433
continue
395
434
@@ -524,13 +563,13 @@ def display_fit(self, smoothing_kernel_sigma=0.1):
524
563
# The image is going to cover the diameter plus 20% padding
525
564
xsize = self ._get_optimal_xsize (resolution )
526
565
527
- n_active_planes = len (self ._active_planes )
566
+ n_active_planes = len (self ._active_planes_idx )
528
567
529
568
fig , subs = plt .subplots (n_active_planes , 3 , figsize = (8 , n_active_planes * 2 ))
530
569
531
- with progress_bar (len (self ._active_planes ), title = 'Smoothing maps' ) as prog_bar :
570
+ with progress_bar (len (self ._active_planes_idx ), title = 'Smoothing maps' ) as prog_bar :
532
571
533
- for i , plane_id in enumerate (self ._active_planes ):
572
+ for i , plane_id in enumerate (self ._active_planes_idx ):
534
573
535
574
data_analysis_bin = self ._maptree [plane_id ]
536
575
@@ -604,7 +643,7 @@ def display_stacked_image(self, smoothing_kernel_sigma=0.5):
604
643
# The image is going to cover the diameter plus 20% padding
605
644
xsize = self ._get_optimal_xsize (resolution )
606
645
607
- active_planes_bins = map (lambda x : self ._maptree [x ], self ._active_planes )
646
+ active_planes_bins = map (lambda x : self ._maptree [x ], self ._active_planes_idx )
608
647
609
648
# Get the center of the projection for this plane
610
649
this_ra , this_dec = self ._roi .ra_dec_center
0 commit comments