Multiplication of TEfficiency objects


I have multiple efficiencies from various cuts (called eff_sel) as well as from my trigger (eff_trig) and want to get an absolute efficiency when applying all efficiencies. Naively, I’d just use eff_abs = eff_trig * eff_sel1 * eff_sel2 * …, but ROOT does not offer a way to multiply TEfficiency objects.

Now, I did look at the ROOT documentation and found the methods Add() and Combine(). It is unclear to me whether these functions do what I want in my case:

If any efficiency is defined as eff = N_pass/N_tot, then, for the selection efficiencies, N_tot is always the same, only N_pass changes.

The efficiencies are about eff_trig <= 0.7, eff_sel \approx 0.95.

I tried Add() on all efficiency objects, but the absolute efficiency at the end was bigger than eff_trig, so Add() is definitely the wrong function to call. That I understand, as it simply adds passed and total histograms and 7/10 “+” 9/10 = 16/20 = 8/10 > 7/10.

Then I tried Combine() – with default values, as I have no idea what different weights I’d use – but in this case also, the resulting efficiency was bigger than eff_trig. Plus, for some reason, Compare() returns a TGraphAsymmErrors* which cannot be constructed back into a TEfficiency object.

Did I misunderstand anything up to this point? I feel like my use case should be pretty normal and thus implemented in a library such as ROOT. That’s why I guess I did something horribly wrong.

Trying to multiply the efficiencies, as would’ve tried naively, is cumbersome and I see no possibility of retaining a TEfficiency object when doing so:

// init of all histograms hPassed* and hTot* with correct binning
TEfficiency effTrig(hPassedTrig, hTotTrig);
TEfficiency eff1(hPassed1, hTot1);
TEfficiency eff2(hPassed2, hTot2);
vector<TEfficiency> effVec = {effTrig, eff1, eff2};

TH1D* hEff = hPassed1->Clone("hEff");
int nBins = hEff->GetBinsX();
for (int iBin=0; iBin<nBins; iBin++) {
    for (int iEff=0; iEff<effVec.size(); iEff++) {
        if (iEff==0) hEff->SetBinContent(iBin+1, effVec[iEff].GetEfficiency(iBin+1);
        else hEff->SetBinContent(iBin+1, hEff->GetBinContent(iBin+1)*effVec[iEff].GetEfficiency(iBin+1));

// Or I could do something like this
TH1D* hEff1 = hPassed1->Clone("hEff1");
// and for all other efficiencies, but this
// doesn't look cleaner, either. Also, it
// leaves me with a TH1D, not with a
// TEfficiency.

Is there something obvious I’m missing?


What you are doing with the multiplication you might get correct values of efficiency, but incorrect errors.
The point of the TEfficiency class is to provide the correct uncertainties.
We have not provided a way if multiplying them, but if I am not mistaken, what you would die to do is to get a total efficiency (and its uncertainties) after various section one after the other.
Then this case it is trivial, just create a new TEfficiency class using the passed histogram of the last TEfficiency object (the one representing the last selection) and the total histogram of the first TEfficiency object (representing the first selection).
No need to implement and use fancy Multiply methods.

Best Regards