Code HistFactory Models in JSON.
With the HS3 standard, it is possible to code RooFit-Models of any kind as JSON files. In this tutorial, you can see how to code up a (simple) HistFactory-based model in JSON and import it into a RooWorkspace.
Author: Carsten Burgard
This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Wednesday, April 17, 2024 at 11:19 AM.
import ROOT
start by creating an empty workspace
ws = ROOT.RooWorkspace("workspace")
the RooJSONFactoryWSTool is responsible for importing and exporting things to and from your workspace
tool = ROOT.RooJSONFactoryWSTool(ws)
use it to import the information from your JSON file
tool.importJSON(ROOT.gROOT.GetTutorialDir().Data() + "/roofit/rf515_hfJSON.json")
ws.Print()
[#2] INFO:HistFactory -- Creating constraint for: gamma_stat_channel1_bin_0. Type of constraint: 1 [#2] INFO:HistFactory -- Creating constraint for: gamma_stat_channel1_bin_1. Type of constraint: 1 [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooPoisson::gamma_stat_channel1_bin_0_constraint [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooRealVar::nom_gamma_stat_channel1_bin_0 [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooProduct::gamma_stat_channel1_bin_0_poisMean [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) using existing copy of RooRealVar::gamma_stat_channel1_bin_0 for import of RooPoisson::gamma_stat_channel1_bin_0_constraint [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooConstVar::gamma_stat_channel1_bin_0_tau [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooPoisson::gamma_stat_channel1_bin_1_constraint [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooRealVar::nom_gamma_stat_channel1_bin_1 [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooProduct::gamma_stat_channel1_bin_1_poisMean [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) using existing copy of RooRealVar::gamma_stat_channel1_bin_1 for import of RooPoisson::gamma_stat_channel1_bin_1_constraint [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooConstVar::gamma_stat_channel1_bin_1_tau [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing dataset model_channel1_signal_dataHist [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing dataset model_channel1_background1_dataHist [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing dataset model_channel1_background2_dataHist [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing dataset observed RooWorkspace(workspace) workspace contents variables --------- (alpha_syst1,alpha_syst2,alpha_syst3,channelCat,gamma_stat_channel1_bin_0,gamma_stat_channel1_bin_1,mu,nom_alpha_syst1,nom_alpha_syst2,nom_alpha_syst3,nom_gamma_stat_channel1_bin_0,nom_gamma_stat_channel1_bin_1,obs_x_channel1) p.d.f.s ------- RooGaussian::alpha_syst1Constraint[ x=alpha_syst1 mean=nom_alpha_syst1 sigma=1 ] = 1 RooGaussian::alpha_syst2Constraint[ x=alpha_syst2 mean=nom_alpha_syst2 sigma=1 ] = 1 RooGaussian::alpha_syst3Constraint[ x=alpha_syst3 mean=nom_alpha_syst3 sigma=1 ] = 1 RooRealSumPdf::channel1_model[ model_channel1_signal_scaleFactors * model_channel1_signal_shapes + model_channel1_background1_scaleFactors * model_channel1_background1_shapes + model_channel1_background2_scaleFactors * model_channel1_background2_shapes ] = 220 RooPoisson::gamma_stat_channel1_bin_0_constraint[ x=nom_gamma_stat_channel1_bin_0 mean=gamma_stat_channel1_bin_0_poisMean ] = 0.019943 RooPoisson::gamma_stat_channel1_bin_1_constraint[ x=nom_gamma_stat_channel1_bin_1 mean=gamma_stat_channel1_bin_1_poisMean ] = 0.039861 RooSimultaneous::main[ indexCat=channelCat channel1=model_channel1 ] = 0.174888 RooProdPdf::model_channel1[ gamma_stat_channel1_bin_0_constraint * gamma_stat_channel1_bin_1_constraint * alpha_syst1Constraint * alpha_syst2Constraint * alpha_syst3Constraint * channel1_model(obs_x_channel1) ] = 0.174888 functions -------- RooStats::HistFactory::FlexibleInterpVar::background1_channel1_epsilon[ paramList=(alpha_syst2) ] = 1 RooStats::HistFactory::FlexibleInterpVar::background2_channel1_epsilon[ paramList=(alpha_syst3) ] = 1 RooProduct::gamma_stat_channel1_bin_0_poisMean[ gamma_stat_channel1_bin_0 * gamma_stat_channel1_bin_0_tau ] = 400 RooProduct::gamma_stat_channel1_bin_1_poisMean[ gamma_stat_channel1_bin_1 * gamma_stat_channel1_bin_1_tau ] = 100 RooHistFunc::hist_model_channel1_background1[ depList=(obs_x_channel1) ] = 0 RooHistFunc::hist_model_channel1_background2[ depList=(obs_x_channel1) ] = 100 RooHistFunc::hist_model_channel1_signal[ depList=(obs_x_channel1) ] = 10 ParamHistFunc::mc_stat_channel1[ ] = 1 RooBinWidthFunction::model_channel1_background1_binWidth[ HistFuncForBinWidth=hist_model_channel1_background1 ] = 2 RooProduct::model_channel1_background1_scaleFactors[ background1_channel1_epsilon ] = 1 RooProduct::model_channel1_background1_shapes[ model_channel1_background1_binWidth * mc_stat_channel1 * hist_model_channel1_background1 ] = 0 RooBinWidthFunction::model_channel1_background2_binWidth[ HistFuncForBinWidth=hist_model_channel1_background2 ] = 2 RooProduct::model_channel1_background2_scaleFactors[ background2_channel1_epsilon ] = 1 RooProduct::model_channel1_background2_shapes[ model_channel1_background2_binWidth * mc_stat_channel1 * hist_model_channel1_background2 ] = 200 RooBinWidthFunction::model_channel1_signal_binWidth[ HistFuncForBinWidth=hist_model_channel1_signal ] = 2 RooProduct::model_channel1_signal_scaleFactors[ mu * signal_channel1_epsilon ] = 1 RooProduct::model_channel1_signal_shapes[ model_channel1_signal_binWidth * hist_model_channel1_signal ] = 20 RooStats::HistFactory::FlexibleInterpVar::signal_channel1_epsilon[ paramList=(alpha_syst1) ] = 1 datasets -------- RooDataSet::observed(channelCat,obs_x_channel1) embedded datasets (in pdfs and functions) ----------------------------------------- RooDataHist::model_channel1_signal_dataHist(obs_x_channel1) RooDataHist::model_channel1_background1_dataHist(obs_x_channel1) RooDataHist::model_channel1_background2_dataHist(obs_x_channel1) named sets ---------- ModelConfig_GlobalObservables:(nom_alpha_syst1,nom_alpha_syst2,nom_alpha_syst3,nom_gamma_stat_channel1_bin_0,nom_gamma_stat_channel1_bin_1) ModelConfig_NuisParams:(alpha_syst1,alpha_syst2,alpha_syst3,channelCat,gamma_stat_channel1_bin_0,gamma_stat_channel1_bin_1) ModelConfig_Observables:(obs_x_channel1) ModelConfig_POI:(mu) generic objects --------------- RooStats::ModelConfig::ModelConfig
now, you can easily use your workspace to run your fit (as you usually would)
the model config is named after your pdf, i.e.
model = ws["ModelConfig"]
for resetting the parameters after the fit
params = model.GetPdf().getParameters(ws["observed"])
params_initial = params.snapshot()
we are fitting a clone of the model now,
result = model.fitTo(ws["observed"], ROOT.RooFit.Save(), ROOT.RooFit.PrintLevel(-1))
result.Print()
[#1] INFO:Minimization -- p.d.f. provides expected number of events, including extended term in likelihood. [#1] INFO:Minimization -- Including the following constraint terms in minimization: (gamma_stat_channel1_bin_0_constraint,gamma_stat_channel1_bin_1_constraint,alpha_syst1Constraint,alpha_syst2Constraint,alpha_syst3Constraint) [#1] INFO:Minimization -- The following global observables have been defined and their values are taken from the model: (nom_alpha_syst1,nom_alpha_syst2,nom_alpha_syst3,nom_gamma_stat_channel1_bin_0,nom_gamma_stat_channel1_bin_1) [#1] INFO:Fitting -- RooAbsPdf::fitTo(main) fixing normalization set for coefficient determination to observables in data [#1] INFO:Fitting -- using CPU computation library compiled with -mavx2 [#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_main_observed) Summation contains a RooNLLVar, using its error level [#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization [#1] INFO:NumericIntegration -- RooRealIntegral::init(_channel1_model_channel1_signal_shapes_Int[_channel1_obs_x_channel1]) using numeric integrator RooBinIntegrator to calculate Int(_channel1_obs_x_channel1) [#1] INFO:NumericIntegration -- RooRealIntegral::init(_channel1_model_channel1_background1_shapes_Int[_channel1_obs_x_channel1]) using numeric integrator RooBinIntegrator to calculate Int(_channel1_obs_x_channel1) [#1] INFO:NumericIntegration -- RooRealIntegral::init(_channel1_model_channel1_background2_shapes_Int[_channel1_obs_x_channel1]) using numeric integrator RooBinIntegrator to calculate Int(_channel1_obs_x_channel1) [#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization RooFitResult: minimized FCN value: -1032.86, estimated distance to minimum: 0.00022598 covariance matrix quality: Full, accurate covariance matrix Status : MINIMIZE=0 HESSE=0 Floating Parameter FinalValue +/- Error -------------------- -------------------------- alpha_syst1 -4.9433e-03 +/- 9.93e-01 alpha_syst2 -9.4921e-03 +/- 9.82e-01 alpha_syst3 1.5278e-02 +/- 9.48e-01 gamma_stat_channel1_bin_0 9.9956e-01 +/- 4.93e-02 gamma_stat_channel1_bin_1 1.0051e+00 +/- 8.02e-02 mu 1.1095e+00 +/- 6.04e-01
reset parameters, such that we are not double-fitting the model in the closure check.
params.assign(params_initial)
in the end, you can again write to json the result will be not completely identical to the JSON file you used as an input, but it will work just the same
tool.exportJSON("myWorkspace.json")
True
You can again import it if you want and check for closure
ws_2 = ROOT.RooWorkspace("workspace")
tool_2 = ROOT.RooJSONFactoryWSTool(ws_2)
tool_2.importJSON("myWorkspace.json")
ws_2.Print()
model_2 = ws_2["ModelConfig"]
result = model_2.fitTo(ws_2["observed"], ROOT.RooFit.Save(), ROOT.RooFit.PrintLevel(-1))
result.Print()
[#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooRealVar::alpha_syst1 [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooRealVar::alpha_syst2 [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooRealVar::alpha_syst3 [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooRealVar::gamma_stat_channel1_bin_0 [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooRealVar::gamma_stat_channel1_bin_1 [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooRealVar::mu [#2] INFO:HistFactory -- Creating constraint for: gamma_stat_channel1_bin_0. Type of constraint: 1 [#2] INFO:HistFactory -- Creating constraint for: gamma_stat_channel1_bin_1. Type of constraint: 1 [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooPoisson::gamma_stat_channel1_bin_0_constraint [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooRealVar::nom_gamma_stat_channel1_bin_0 [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooProduct::gamma_stat_channel1_bin_0_poisMean [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) using existing copy of RooRealVar::gamma_stat_channel1_bin_0 for import of RooPoisson::gamma_stat_channel1_bin_0_constraint [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooConstVar::gamma_stat_channel1_bin_0_tau [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooPoisson::gamma_stat_channel1_bin_1_constraint [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooRealVar::nom_gamma_stat_channel1_bin_1 [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooProduct::gamma_stat_channel1_bin_1_poisMean [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) using existing copy of RooRealVar::gamma_stat_channel1_bin_1 for import of RooPoisson::gamma_stat_channel1_bin_1_constraint [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing RooConstVar::gamma_stat_channel1_bin_1_tau [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing dataset model_channel1_background1_dataHist [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing dataset model_channel1_background2_dataHist [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing dataset model_channel1_signal_dataHist [#1] INFO:ObjectHandling -- RooWorkspace::import(workspace) importing dataset observed RooWorkspace(workspace) workspace contents variables --------- (alpha_syst1,alpha_syst2,alpha_syst3,channelCat,gamma_stat_channel1_bin_0,gamma_stat_channel1_bin_1,mu,nom_alpha_syst1,nom_alpha_syst2,nom_alpha_syst3,nom_gamma_stat_channel1_bin_0,nom_gamma_stat_channel1_bin_1,obs_x_channel1) p.d.f.s ------- RooGaussian::alpha_syst1Constraint[ x=alpha_syst1 mean=nom_alpha_syst1 sigma=1 ] = 1 RooGaussian::alpha_syst2Constraint[ x=alpha_syst2 mean=nom_alpha_syst2 sigma=1 ] = 1 RooGaussian::alpha_syst3Constraint[ x=alpha_syst3 mean=nom_alpha_syst3 sigma=1 ] = 1 RooRealSumPdf::channel1_model[ model_channel1_background1_scaleFactors * model_channel1_background1_shapes + model_channel1_background2_scaleFactors * model_channel1_background2_shapes + model_channel1_signal_scaleFactors * model_channel1_signal_shapes ] = 220 RooPoisson::gamma_stat_channel1_bin_0_constraint[ x=nom_gamma_stat_channel1_bin_0 mean=gamma_stat_channel1_bin_0_poisMean ] = 0.019943 RooPoisson::gamma_stat_channel1_bin_1_constraint[ x=nom_gamma_stat_channel1_bin_1 mean=gamma_stat_channel1_bin_1_poisMean ] = 0.039861 RooSimultaneous::main[ indexCat=channelCat channel1=model_channel1 ] = 0.174888 RooProdPdf::model_channel1[ gamma_stat_channel1_bin_0_constraint * gamma_stat_channel1_bin_1_constraint * alpha_syst2Constraint * alpha_syst3Constraint * alpha_syst1Constraint * channel1_model(obs_x_channel1) ] = 0.174888 functions -------- RooStats::HistFactory::FlexibleInterpVar::background1_channel1_epsilon[ paramList=(alpha_syst2) ] = 1 RooStats::HistFactory::FlexibleInterpVar::background2_channel1_epsilon[ paramList=(alpha_syst3) ] = 1 RooProduct::gamma_stat_channel1_bin_0_poisMean[ gamma_stat_channel1_bin_0 * gamma_stat_channel1_bin_0_tau ] = 400 RooProduct::gamma_stat_channel1_bin_1_poisMean[ gamma_stat_channel1_bin_1 * gamma_stat_channel1_bin_1_tau ] = 100 RooHistFunc::hist_model_channel1_background1[ depList=(obs_x_channel1) ] = 0 RooHistFunc::hist_model_channel1_background2[ depList=(obs_x_channel1) ] = 100 RooHistFunc::hist_model_channel1_signal[ depList=(obs_x_channel1) ] = 10 ParamHistFunc::mc_stat_channel1[ ] = 1 RooBinWidthFunction::model_channel1_background1_binWidth[ HistFuncForBinWidth=hist_model_channel1_background1 ] = 2 RooProduct::model_channel1_background1_scaleFactors[ background1_channel1_epsilon ] = 1 RooProduct::model_channel1_background1_shapes[ model_channel1_background1_binWidth * mc_stat_channel1 * hist_model_channel1_background1 ] = 0 RooBinWidthFunction::model_channel1_background2_binWidth[ HistFuncForBinWidth=hist_model_channel1_background2 ] = 2 RooProduct::model_channel1_background2_scaleFactors[ background2_channel1_epsilon ] = 1 RooProduct::model_channel1_background2_shapes[ model_channel1_background2_binWidth * mc_stat_channel1 * hist_model_channel1_background2 ] = 200 RooBinWidthFunction::model_channel1_signal_binWidth[ HistFuncForBinWidth=hist_model_channel1_signal ] = 2 RooProduct::model_channel1_signal_scaleFactors[ mu * signal_channel1_epsilon ] = 1 RooProduct::model_channel1_signal_shapes[ model_channel1_signal_binWidth * hist_model_channel1_signal ] = 20 RooStats::HistFactory::FlexibleInterpVar::signal_channel1_epsilon[ paramList=(alpha_syst1) ] = 1 datasets -------- RooDataSet::observed(channelCat,obs_x_channel1) embedded datasets (in pdfs and functions) ----------------------------------------- RooDataHist::model_channel1_background1_dataHist(obs_x_channel1) RooDataHist::model_channel1_background2_dataHist(obs_x_channel1) RooDataHist::model_channel1_signal_dataHist(obs_x_channel1) parameter snapshots ------------------- default_values = (alpha_syst1=0 +/- 1,alpha_syst2=0 +/- 1,alpha_syst3=0 +/- 1,gamma_stat_channel1_bin_0=1 +/- 0.05,gamma_stat_channel1_bin_1=1 +/- 0.1,mu=1) named sets ---------- ModelConfig_GlobalObservables:(nom_alpha_syst1,nom_alpha_syst2,nom_alpha_syst3,nom_gamma_stat_channel1_bin_0,nom_gamma_stat_channel1_bin_1) ModelConfig_NuisParams:(alpha_syst1,alpha_syst2,alpha_syst3,channelCat,gamma_stat_channel1_bin_0,gamma_stat_channel1_bin_1) ModelConfig_Observables:(obs_x_channel1) ModelConfig_POI:(mu) generic objects --------------- RooStats::ModelConfig::ModelConfig [#1] INFO:Minimization -- p.d.f. provides expected number of events, including extended term in likelihood. [#1] INFO:Minimization -- Including the following constraint terms in minimization: (gamma_stat_channel1_bin_0_constraint,gamma_stat_channel1_bin_1_constraint,alpha_syst2Constraint,alpha_syst3Constraint,alpha_syst1Constraint) [#1] INFO:Minimization -- The following global observables have been defined and their values are taken from the model: (nom_alpha_syst1,nom_alpha_syst2,nom_alpha_syst3,nom_gamma_stat_channel1_bin_0,nom_gamma_stat_channel1_bin_1) [#1] INFO:Fitting -- RooAbsPdf::fitTo(main) fixing normalization set for coefficient determination to observables in data [#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_main_observed) Summation contains a RooNLLVar, using its error level [#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization [#1] INFO:NumericIntegration -- RooRealIntegral::init(_channel1_model_channel1_background1_shapes_Int[_channel1_obs_x_channel1]) using numeric integrator RooBinIntegrator to calculate Int(_channel1_obs_x_channel1) [#1] INFO:NumericIntegration -- RooRealIntegral::init(_channel1_model_channel1_background2_shapes_Int[_channel1_obs_x_channel1]) using numeric integrator RooBinIntegrator to calculate Int(_channel1_obs_x_channel1) [#1] INFO:NumericIntegration -- RooRealIntegral::init(_channel1_model_channel1_signal_shapes_Int[_channel1_obs_x_channel1]) using numeric integrator RooBinIntegrator to calculate Int(_channel1_obs_x_channel1) [#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization RooFitResult: minimized FCN value: -1032.86, estimated distance to minimum: 0.00022598 covariance matrix quality: Full, accurate covariance matrix Status : MINIMIZE=0 HESSE=0 Floating Parameter FinalValue +/- Error -------------------- -------------------------- alpha_syst1 -4.9433e-03 +/- 9.93e-01 alpha_syst2 -9.4921e-03 +/- 9.82e-01 alpha_syst3 1.5278e-02 +/- 9.48e-01 gamma_stat_channel1_bin_0 9.9956e-01 +/- 4.93e-02 gamma_stat_channel1_bin_1 1.0051e+00 +/- 8.02e-02 mu 1.1095e+00 +/- 6.04e-01
Draw all canvases
from ROOT import gROOT
gROOT.GetListOfCanvases().Draw()