28def generateBinnedAsimov(pdf, x, n_events):
 
   30    Generate binned Asimov dataset for a continuous pdf. 
   31    One should in principle be able to use 
   32    pdf.generateBinned(x, n_events, RooFit::ExpectedData()). 
   33    Unfortunately it has a problem: it also has the bin bias that this tutorial 
   34    demostrates, to if we would use it, the biases would cancel out. 
   36    data_h = ROOT.RooDataHist(
"dataH", 
"dataH", {x})
 
   37    x_binning = x.getBinning()
 
   39    for i_bin 
in range(x.numBins()):
 
   40        x.setRange(
"bin", x_binning.binLow(i_bin), x_binning.binHigh(i_bin))
 
   41        integ = pdf.createIntegral(x, NormSet=x, Range=
"bin")
 
   42        ROOT.SetOwnership(integ, 
True)
 
   44        data_h.set(i_bin, n_events * integ.getVal(), -1)
 
   49def enableBinIntegrator(func, num_bins):
 
   51    Force numeric integration and do this numeric integration with the 
   52    RooBinIntegrator, which sums the function values at the bin centers. 
   54    custom_config = ROOT.RooNumIntConfig(func.getIntegratorConfig())
 
   55    custom_config.method1D().setLabel(
"RooBinIntegrator")
 
   56    custom_config.getConfigSection(
"RooBinIntegrator").setRealValue(
"numBins", num_bins)
 
   57    func.setIntegratorConfig(custom_config)
 
   58    func.forceNumInt(
True)
 
   61def disableBinIntegrator(func):
 
   63    Reset the integrator config to disable the RooBinIntegrator. 
   65    func.setIntegratorConfig()
 
   66    func.forceNumInt(
False)
 
   70ROOT.RooMsgService.instance().getStream(1).removeTopic(ROOT.RooFit.Minimization)
 
   71ROOT.RooMsgService.instance().getStream(1).removeTopic(ROOT.RooFit.Fitting)
 
   72ROOT.RooMsgService.instance().getStream(1).removeTopic(ROOT.RooFit.Generation)
 
   78x = ROOT.RooRealVar(
"x", 
"x", 0.1, 5.1)
 
   83c = ROOT.RooRealVar(
"c", 
"c", -1.8, -5, 5)
 
   84expo = ROOT.RooExponential(
"expo", 
"expo", x, c)
 
   88expo_data = generateBinnedAsimov(expo, x, 10000)
 
   93fit1 = expo.fitTo(expo_data, Save=
True, PrintLevel=-1, SumW2Error=
False)
 
  103enableBinIntegrator(expo, x.numBins())
 
  104fit2 = expo.fitTo(expo_data, Save=
True, PrintLevel=-1, SumW2Error=
False)
 
  106disableBinIntegrator(expo)
 
  112a = ROOT.RooRealVar(
"a", 
"a", -0.3, -5.0, 5.0)
 
  113powerlaw = ROOT.RooGenericPdf(
"powerlaw", 
"std::pow(x, a)", [x, a]);
 
  114powerlaw_data = generateBinnedAsimov(powerlaw, x, 10000)
 
  117fit3 = powerlaw.fitTo(powerlaw_data, Save=
True, PrintLevel=-1, SumW2Error=
False)
 
  127enableBinIntegrator(powerlaw, x.numBins())
 
  128fit4 = powerlaw.fitTo(powerlaw_data, Save=
True, PrintLevel=-1, SumW2Error=
False)
 
  130disableBinIntegrator(powerlaw)
 
  138fit5 = powerlaw.fitTo(powerlaw_data, IntegrateBins=1e-3, Save=
True, PrintLevel=-1, SumW2Error=
False)
 
  162mu = ROOT.RooRealVar(
"mu", 
"mu", 3.0, 0.1, 5.1)
 
  163sigma = ROOT.RooRealVar(
"sigma", 
"sigma", 0.5, 0.01, 5.0)
 
  164gauss = ROOT.RooGaussian(
"gauss", 
"gauss", x, mu, sigma)
 
  166nsig = ROOT.RooRealVar(
"nsig", 
"nsig", 10000, 0, 1e9)
 
  167nbkg = ROOT.RooRealVar(
"nbkg", 
"nbkg", 10000000, 0, 1e9)
 
  168frac = ROOT.RooRealVar(
"frac", 
"frac", nsig.getVal() / (nsig.getVal() + nbkg.getVal()), 0.0, 1.0)
 
  170model = ROOT.RooAddPdf(
"model", 
"model", [gauss, expo], [nsig, nbkg])
 
  172model_data = model.generateBinned(x)
 
  179fit6 = model.fitTo(model_data, Save=
True, PrintLevel=-1, SumW2Error=
False)
 
  195fit7 = model.fitTo(model_data, Offset=
"bin", Save=
True, PrintLevel=-1, SumW2Error=
False)