# rf514_RooCustomizer¶

Using the RooCustomizer to create multiple PDFs that share a lot of properties, but have unique parameters for each category. As an extra complication, some of the new parameters need to be functions of a mass parameter.

Author: Harshal Shende, Stephan Hageboeck (C++ version)
This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Sunday, November 27, 2022 at 11:07 AM.

In [1]:
import ROOT

E = ROOT.RooRealVar("Energy", "Energy", 0, 3000)

meanG = ROOT.RooRealVar("meanG", "meanG", 100.0, 0.0, 3000.0)
sigmaG = ROOT.RooRealVar("sigmaG", "sigmaG", 3.0)
gauss = ROOT.RooGaussian("gauss", "gauss", E, meanG, sigmaG)

pol1 = ROOT.RooRealVar("pol1", "Constant of the polynomial", 1, -10, 10)
linear = ROOT.RooPolynomial("linear", "linear", E, pol1)

yieldSig = ROOT.RooRealVar("yieldSig", "yieldSig", 1, 0, 1.0e4)
yieldBkg = ROOT.RooRealVar("yieldBkg", "yieldBkg", 1, 0, 1.0e4)

model = ROOT.RooAddPdf("model", "S + B model", [gauss, linear], [yieldSig, yieldBkg])

print("The proto model before customisation:\n")
model.Print("T")  # "T" prints the model as a tree

Welcome to JupyROOT 6.27/01
The proto model before customisation:



Build the categories

In [2]:
sample = ROOT.RooCategory("sample", "sample", {"Sample1": 1, "Sample2": 2, "Sample3": 3})


## Start to customise the proto model that was defined above.¶

We need two sets for bookkeeping of PDF nodes:

In [3]:
newLeafs = ROOT.RooArgSet()
allCustomiserNodes = ROOT.RooArgSet()

1. Each sample should have its own mean for the gaussian The customiser will make copies of meanG for each category. These will all appear in the set newLeafs, which will own the new nodes.
In [4]:
cust = ROOT.RooCustomizer(model, sample, newLeafs, allCustomiserNodes)
cust.splitArg(meanG, sample)

1. Each sample should have its own signal yield, but there is an extra complication: We need the yields 1 and 2 to be a function of the variable "mass". For this, we pre-define nodes with exacly the names that the customiser would have created automatically, that is, "_", and we register them in the set of customiser nodes. The customiser will pick them up instead of creating new ones. If we don't provide one (e.g. for "yieldSig_Sample3"), it will be created automatically by cloning yieldSig.
In [5]:
mass = ROOT.RooRealVar("M", "M", 1, 0, 12000)
yield1 = ROOT.RooFormulaVar("yieldSig_Sample1", "Signal yield in the first sample", "M/3.360779", mass)
yield2 = ROOT.RooFormulaVar("yieldSig_Sample2", "Signal yield in the second sample", "M/2", mass)

Out[5]:
True

Instruct the customiser to replace all yieldSig nodes for each sample:

In [6]:
cust.splitArg(yieldSig, sample)


Now we can start building the PDFs for all categories:

In [7]:
pdf1 = cust.build("Sample1")
pdf2 = cust.build("Sample2")
pdf3 = cust.build("Sample3")


And we inspect the two PDFs

In [8]:
print("\nPDF 1 with a yield depending on M:\n")
pdf1.Print("T")
print("\nPDF 2 with a yield depending on M:\n")
pdf2.Print("T")
print("\nPDF 3 with a free yield:\n")
pdf3.Print("T")

print("\nThe following leafs have been created automatically while customising:\n")
newLeafs.Print("V")

PDF 1 with a yield depending on M:

PDF 2 with a yield depending on M:

PDF 3 with a free yield:

The following leafs have been created automatically while customising:

0x8794870/V- RooRealVar::Energy = 1500
0x3e2d9a0/V- RooRealVar::pol1 = 1
0x287ca90/V- RooRealVar::yieldBkg = 1
0x8c58f10/V- RooGaussian::gauss_Sample1 = 0 [Auto,Dirty]
0x8794870/V- RooRealVar::Energy = 1500
0x8650980/V- RooRealVar::sigmaG = 3
0x970b440/V- RooRealVar::meanG_Sample1 = 100
0x9cc1080/V- RooFormulaVar::yieldSig_Sample1 = 0.29755 [Auto,Clean]
0x97f2340/V- RooRealVar::M = 1
0x8794870/V- RooRealVar::Energy = 1500
0x3e2d9a0/V- RooRealVar::pol1 = 1
0x287ca90/V- RooRealVar::yieldBkg = 1
0x9dbf250/V- RooGaussian::gauss_Sample2 = 0 [Auto,Dirty]
0x8794870/V- RooRealVar::Energy = 1500
0x8650980/V- RooRealVar::sigmaG = 3
0x962fe40/V- RooRealVar::meanG_Sample2 = 100
0x9da9e60/V- RooFormulaVar::yieldSig_Sample2 = 0.5 [Auto,Clean]
0x97f2340/V- RooRealVar::M = 1
0x8794870/V- RooRealVar::Energy = 1500
0x3e2d9a0/V- RooRealVar::pol1 = 1
0x287ca90/V- RooRealVar::yieldBkg = 1
0x9d7d8d0/V- RooGaussian::gauss_Sample3 = 0 [Auto,Dirty]
0x8794870/V- RooRealVar::Energy = 1500
0x8650980/V- RooRealVar::sigmaG = 3
0x9d85b00/V- RooRealVar::meanG_Sample3 = 100
0x9c26e90/V- RooRealVar::yieldSig_Sample3 = 1
1) RooRealVar::    meanG_Sample1 = 100
2) RooRealVar::    meanG_Sample2 = 100
3) RooRealVar::    meanG_Sample3 = 100
4) RooRealVar:: yieldSig_Sample3 = 1


If we needed to set reasonable values for the means of the gaussians, this could be done as follows:

In [9]:
meanG1 = allCustomiserNodes["meanG_Sample1"]
meanG1.setVal(200)
meanG2 = allCustomiserNodes["meanG_Sample2"]
meanG2.setVal(300)

print(
"\nThe following leafs have been used while customising\n\t(partial overlap with the set of automatically created leaves.\n\ta new customiser for a different PDF could reuse them if necessary.):"
)
allCustomiserNodes.Print("V")

del cust

The following leafs have been used while customising
(partial overlap with the set of automatically created leaves.
a new customiser for a different PDF could reuse them if necessary.):
1) RooFormulaVar:: yieldSig_Sample1 = 0.29755
2) RooFormulaVar:: yieldSig_Sample2 = 0.5
3) RooRealVar::    meanG_Sample1 = 200
4) RooRealVar::    meanG_Sample2 = 300
5) RooRealVar::    meanG_Sample3 = 100
6) RooRealVar:: yieldSig_Sample3 = 1