3
3
import logging
4
4
import warnings
5
5
from contextlib import contextmanager
6
+ from pathlib import Path
6
7
from typing import Callable , List , Literal , Optional , Text , Union
7
8
8
9
import numpy as np
9
10
import spey
10
11
import tqdm
11
- from scipy .stats import moment , multivariate_normal
12
- from spey .backends .default_pdf import CorrelatedBackground , ThirdMomentExpansion
12
+ from scipy .stats import moment , multivariate_normal , norm
13
+ from spey .backends .default_pdf import (
14
+ CorrelatedBackground ,
15
+ EffectiveSigma ,
16
+ ThirdMomentExpansion ,
17
+ )
18
+ from spey .helper_functions import covariance_to_correlation
13
19
from spey .optimizer .core import fit
14
20
15
21
from . import WorkspaceInterpreter
@@ -78,7 +84,8 @@ class Simplify(spey.ConverterBase):
78
84
fittype (``Text``, default ``"postfit"``): what type of fitting should be performed ``"postfit"``
79
85
or ``"prefit"``.
80
86
convert_to (``Text``, default ``"default_pdf.correlated_background"``): conversion type. Should
81
- be either ``"default_pdf.correlated_background"`` or ``"default_pdf.third_moment_expansion"``.
87
+ be either ``"default_pdf.correlated_background"``, ``"default_pdf.third_moment_expansion"``
88
+ or ``"default_pdf.effective_sigma"``.
82
89
number_of_samples (``int``, default ``1000``): number of samples to be generated in order to estimate
83
90
contract the uncertainties into a single value.
84
91
control_region_indices (``List[int]`` or ``List[Text]``, default ``None``): indices or names of the control and
@@ -171,13 +178,15 @@ def __call__(
171
178
statistical_model : spey .StatisticalModel ,
172
179
fittype : Literal ["postfit" , "prefit" ] = "postfit" ,
173
180
convert_to : Literal [
174
- "default_pdf.correlated_background" , "default_pdf.third_moment_expansion"
181
+ "default_pdf.correlated_background" ,
182
+ "default_pdf.third_moment_expansion" ,
183
+ "default_pdf.effective_sigma" ,
175
184
] = "default_pdf.correlated_background" ,
176
185
number_of_samples : int = 1000 ,
177
186
control_region_indices : Optional [Union [List [int ], List [Text ]]] = None ,
178
187
include_modifiers_in_control_model : bool = False ,
179
188
save_model : Optional [Text ] = None ,
180
- ) -> Union [CorrelatedBackground , ThirdMomentExpansion ]:
189
+ ) -> Union [CorrelatedBackground , ThirdMomentExpansion , EffectiveSigma ]:
181
190
182
191
assert statistical_model .backend_type == "pyhf" , (
183
192
"This method is currently only available for `pyhf` full statistical models."
@@ -390,6 +399,13 @@ def __call__(
390
399
# in the full statistical model!
391
400
background_yields = np .mean (samples , axis = 0 )
392
401
402
+ save_kwargs = {
403
+ "covariance_matrix" : covariance_matrix ,
404
+ "background_yields" : background_yields ,
405
+ "data" : data ,
406
+ "channel_order" : stat_model_pyhf .config .channels ,
407
+ }
408
+
393
409
third_moments = []
394
410
if convert_to == "default_pdf.correlated_background" :
395
411
backend = CorrelatedBackground (
@@ -400,6 +416,7 @@ def __call__(
400
416
)
401
417
elif convert_to == "default_pdf.third_moment_expansion" :
402
418
third_moments = moment (samples , moment = 3 , axis = 0 )
419
+ save_kwargs .update ({"third_moments" : third_moments })
403
420
404
421
backend = ThirdMomentExpansion (
405
422
signal_yields = signal_yields ,
@@ -408,21 +425,37 @@ def __call__(
408
425
covariance_matrix = covariance_matrix ,
409
426
third_moment = third_moments ,
410
427
)
428
+ elif convert_to == "default_pdf.effective_sigma" :
429
+ # Get 68% quantiles
430
+ q = (1.0 - (norm .cdf (1.0 ) - norm .cdf (- 1.0 ))) / 2.0
431
+ absolute_uncertainty_envelops = np .stack (
432
+ [np .quantile (samples , q , axis = 0 ), np .quantile (samples , 1 - q , axis = 0 )],
433
+ axis = 1 ,
434
+ )
435
+ save_kwargs .update (
436
+ {"absolute_uncertainty_envelops" : absolute_uncertainty_envelops }
437
+ )
438
+
439
+ backend = EffectiveSigma (
440
+ signal_yields = signal_yields ,
441
+ background_yields = background_yields ,
442
+ data = data ,
443
+ correlation_matrix = covariance_to_correlation (
444
+ covariance_matrix = covariance_matrix
445
+ ),
446
+ absolute_uncertainty_envelops = absolute_uncertainty_envelops ,
447
+ )
411
448
else :
412
449
raise ConversionError (
413
450
"Currently available conversion methods are "
414
- + "'default_pdf.correlated_background', 'default_pdf.third_moment_expansion'"
451
+ + "'default_pdf.correlated_background', 'default_pdf.third_moment_expansion',"
452
+ + " 'default_pdf.effective_sigma'"
415
453
)
416
454
417
455
if save_model is not None :
418
- if save_model .endswith (".npz" ):
419
- np .savez_compressed (
420
- save_model ,
421
- covariance_matrix = covariance_matrix ,
422
- background_yields = background_yields ,
423
- third_moments = third_moments ,
424
- data = data ,
425
- channel_order = stat_model_pyhf .config .channels ,
426
- )
456
+ save_path = Path (save_model )
457
+ if save_path .suffix != ".npz" :
458
+ save_path = save_path .with_suffix (".npz" )
459
+ np .savez_compressed (str (save_path ), ** save_kwargs )
427
460
428
461
return backend
0 commit comments