You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue describes the way of presenting SUSY limits as it has been agreed between ATLAS and CMS. An example from JHEP 12 (2019) 060 can be seen here:
Description of limit lines
Observed limit (thick solid dark-red line): all uncertainties are included in the fit as nuisance parameters, with the exception of the theoretical signal uncertainties (PDF, scales, etc.) on the inclusive cross section.
±1σ lines around observed limit (1) with style "thin dark-red dotted": re-run limit calculation (1) while increasing or decreasing the signal cross section by the theoretical signal uncertainties (PDF, scales, etc.).
Expected limit (less thick long-dashed dark-blue line): all uncertainties are included in the fit as nuisance parameters, with the exception of the theoretical signal uncertainties (PDF, scales, etc.) on the inclusive cross section.
±1σ band around expected limit (2) with style "yellow band": the band contours are the ±1σ results of the fit (2).
Implementation
Below an implementation of the calculation of the above CLs value using pyhf and cabinetry is presented.
Workspace
The workspace is created by a cabinetry configuration file. Is should be noted that this workspace includes multiple signal models, i.e. multiple signal Samples with different NormFactors each. An example of such configuration file can be seen here: config_excl_AnalysisChallenge_grid.yml.
Code snippet
# get model and observed data (pre-fit)model, data=cabinetry.model_utils.model_and_data(ws)
channels=model.config.channels# workspace and model without signal theory uncertainties. signal theory uncertainties have the string '_Signal_' in their name.signal_theory_names= [systematic['Name'] forsystematicincabinetry_config['Systematics'] if'_Signal_'insystematic['Name']]
pruned_ws=pyhf.Workspace(ws)._prune_and_rename(prune_modifiers=signal_theory_names)
pruned_model, _=cabinetry.model_utils.model_and_data(pruned_ws)
# signal normalisation parameter names (having the string 'Signal_norm' in their name).signal_norms= [paramforparaminmodel.config.par_namesif'Signal_norm'inparam]
# signal normalisation parameters indices for both full and pruned modelssignal_norms_idx= [model.config.par_map[norm]['slice'].startfornorminsignal_norms]
pruned_signal_norms_idx= [pruned_model.config.par_map[norm]['slice'].startfornorminsignal_norms]
# signal theory modifier indicessignal_theory_idx= [model.config.par_map[modifier]['slice'].startformodifierinsignal_theory_names]
deffix_and_calculate_CLs(param):
''' Fix all signal normalisation parameters to zero except the one specified by param then calculate expected and observed CLs values '''# Expected CLsprint(f"Calculating explected CLs for {param}")
# get the index of the param, this will be the new POIpruned_poi_index=cabinetry.model_utils._poi_index(pruned_model, poi_name=param)
# set POI to parampruned_model.config.set_poi(pruned_model.config.par_names[pruned_poi_index])
# indices of all the signal normalisation parameters except the poi_idxpruned_fixed_signal_norms_idx= [idxforidxinpruned_signal_norms_idxifidx!=pruned_poi_index]
# set the rest of signal normalisation parameters fixed at zeropruned_fix_pars=pruned_model.config.suggested_fixed().copy()
pruned_init_pars=pruned_model.config.suggested_init().copy()
foridxinpruned_fixed_signal_norms_idx:
pruned_fix_pars[idx] =Truepruned_init_pars[idx] =0.0# calculate expected CLs with respect to POItry:
_, CLs_exp_band=pyhf.infer.hypotest(1.0, asimov_dataset, pruned_model, init_pars=pruned_init_pars, fixed_params=pruned_fix_pars, return_expected_set=True)
# keep only ±1 sigma and convert to simple floatsCLs_exp_band=list(map(lambdax: float(x), CLs_exp_band[1:4]))
except:
CLs_exp_band=None# Observed CLsprint(f"Calculating observed CLs for {param}")
# get the index of the param, this will be the new POIpoi_index=cabinetry.model_utils._poi_index(model, poi_name=param)
# set POI to parammodel.config.set_poi(model.config.par_names[poi_index])
# indices of all the signal normalisation parameters except the poi_idxfixed_signal_norms_idx= [idxforidxinsignal_norms_idxifidx!=poi_index]
# set the rest of signal normalisation parameters fixed at zerofix_pars=model.config.suggested_fixed().copy()
init_pars=model.config.suggested_init().copy()
foridxinfixed_signal_norms_idx:
fix_pars[idx] =Trueinit_pars[idx] =0.0CLs_obs_band= []
# run three fits with different fixed signal theory NPsforsignal_theory_npin [-1.0, 0.0, 1.0]:
# fix signal theory NPsforidxinsignal_theory_idx:
fix_pars[idx] =Trueinit_pars[idx] =signal_theory_np# calculate observed CLs with respect to POItry:
CLs_obs=pyhf.infer.hypotest(1.0, data, model, init_pars=init_pars, fixed_params=fix_pars)
# convert to simple floatsCLs_obs=float(CLs_obs)
except:
CLs_obs=None# save resultsCLs_obs_band.append(CLs_obs)
return [CLs_obs_band, CLs_exp_band]
# results dictionarypost_fit_significance_results= {}
# loop over the signal parameters of the workspace and calculateforparaminsignal_norms:
result=fix_and_calculate_CLs[param]
post_fit_significance_results[param] =result
The text was updated successfully, but these errors were encountered:
This issue describes the way of presenting SUSY limits as it has been agreed between ATLAS and CMS. An example from JHEP 12 (2019) 060 can be seen here:
Description of limit lines
Implementation
Below an implementation of the calculation of the above CLs value using
pyhf
andcabinetry
is presented.Workspace
The workspace is created by a
cabinetry
configuration file. Is should be noted that this workspace includes multiple signal models, i.e. multiple signalSamples
with differentNormFactors
each. An example of such configuration file can be seen here: config_excl_AnalysisChallenge_grid.yml.Code snippet
The text was updated successfully, but these errors were encountered: