Drawing normalized data points with RooFit

Dear experts,

My question in short: How to draw a normalized histogram of a specific RooDataSet instance without any adjustment by my hand after drawing it.


I want to compare the shape of a physical quantity from two different datasets.

If I use TTree instance, I can make such comparison plot with the following commands.
Let’s say “tree1” and “tree2” as the name of trees and “mass” as physical quantity for the comparison

tree1->Draw("mass >> h1(100,0,1)")
h1 = tree1->GetHistogram()
h1->Scale(1./h1->Integral())
tree2->Draw("mass >> h2(100,0,1)")
h2 = tree2->GetHistogram()
h2->Scale(1./h2->Integral())
h1->Draw("")
h2->Draw("sames")

This works for me so far (some problems are there though… such like problems of range for y-axis and so on…).
But in this time, I migrated to RooFit and in this framework, a class like TTree is RooDataSet I think.
One can draw a histogram of “mass” distribution in RooDataSet by using RooRealVar and plotOn() method in RooDataSet. However, I cannot find the way to do a similar thing stated above in RooFit, drawing histogram which is normalized by its integral (to have unit area)

I tried Rescale option of plotOn() method, but it does not adjust the y-axis at all, so I should get my plot from a RooPlot instance and call some functions to adjust it by my hand every time.
So, my question is very simple: Is there an elegant way to draw a normalized histogram from a RooDataSet instance only by using plotOn() and its option?

Hi @Nikel ,

sorry for the high latency, we need @jonas 's help here, let’s ping him.

Cheers,
Enrico

Thanks, @eguiraud for reply.

It seems there are no people who are interested in this topic. So I have written some utility function for my purpose. Here I want to share my function.

template <typename T=RooDataSet>
void DrawNormalizedPlot(RooPlot *frame, T *obj, Color_t color = kBlack) {
    using namespace std;
    Int_t nBins         = frame->GetXaxis()->GetNbins();
    Double_t lowerBound = frame->GetXaxis()->GetBinLowEdge(1);
    Double_t upperBound = frame->GetXaxis()->GetBinLowEdge(nBins + 1);
    string cutString    = to_string(lowerBound) + "< ";
    cutString += frame->getPlotVar()->GetName();
    cutString += " && ";
    cutString += frame->getPlotVar()->GetName();
    cutString += " < " + to_string(upperBound);

    Double_t oldMaximum = frame->GetMaximum();
    Double_t sum        = obj->sumEntries(cutString.c_str());
    obj->plotOn(frame, RooFit::Rescale(1. / sum), RooFit::LineColor(color),
                RooFit::MarkerColor(color));
    Double_t newMaximum = frame->GetMaximum() / sum;
    if (newMaximum > oldMaximum)
        frame->SetMaximum(newMaximum);
    else
        frame->SetMaximum(oldMaximum);
}

This is working for me so far (there might be some bugs in here, I am not sure…).

However, I didn’t stop to find more elegeant way to draw a normalized plot to a RooPlot instance from RooAbsData one. If I could get some answer from experts, I would be very appreciated.

Cheers.

1 Like

@jonas has been travelling, I’m sure he will reply when he is back! :smiley:

Hi,

Apologies for the late reply. First of all, when you want to draw normalised data points in order that the integral is 1, you need to divide the content by the bin width. For histograms you should use h1->Scale(1./h1->Integral(), "width").

In Roofit when plotting RooAbsData you just need to call rescale and do for example:

data.plotOn(pl, RooFit::Rescale(1./(data.sumEntries()*pl->getFitRangeBinW())));

and you might need to reset the RooPlot maximum as you are doing in the code. I think this should be done automatically. I will open an issue for this

Lorenzo

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.