# Rf 2 0 4A_Extended Likelihood¶

Extended maximum likelihood fit in multiple ranges.

When an extended pdf and multiple ranges are used, the RooExtendPdf cannot correctly interpret the coefficients used for extension. This can be solved by using a RooAddPdf for extending the model.

Author: Stephan Hageboeck
This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Thursday, May 19, 2022 at 08:54 AM.

In [1]:
%%cpp -d
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooGaussian.h"
#include "RooChebychev.h"
#include "RooExtendPdf.h"
#include "RooFitResult.h"
#include "TCanvas.h"
#include "TAxis.h"
#include "RooPlot.h"
using namespace RooFit ;


## Setup component pdfs¶

Declare observable x

In [2]:
RooRealVar x("x","x",0,11) ;


Create two gaussian pdfs g1(x,mean1,sigma) anf g2(x,mean2,sigma) and their parameters

In [3]:
RooRealVar mean("mean","mean of gaussians",5) ;
RooRealVar sigma1("sigma1","width of gaussians",0.5) ;
RooRealVar sigma2("sigma2","width of gaussians",1) ;

RooGaussian sig1("sig1","Signal component 1",x,mean,sigma1) ;
RooGaussian sig2("sig2","Signal component 2",x,mean,sigma2) ;

[#0] WARNING:InputArguments -- The parameter 'sigma1' with range [-1e+30, 1e+30] of the RooGaussian 'sig1' exceeds the safe range of (0, inf). Advise to limit its range.
[#0] WARNING:InputArguments -- The parameter 'sigma2' with range [-1e+30, 1e+30] of the RooGaussian 'sig2' exceeds the safe range of (0, inf). Advise to limit its range.


Build chebychev polynomial pdf

In [4]:
RooRealVar a0("a0","a0",0.5,0.,1.) ;
RooRealVar a1("a1","a1",0.2,0.,1.) ;
RooChebychev bkg("bkg","Background",x,RooArgSet(a0,a1)) ;


Sum the signal components into a composite signal pdf

In [5]:
RooRealVar sig1frac("sig1frac","fraction of component 1 in signal",0.8,0.,1.) ;


## Extend the pdfs¶

Define signal range in which events counts are to be defined

In [6]:
x.setRange("signalRange",4,6) ;

[#1] INFO:Eval -- RooRealVar::setRange(x) new range named 'signalRange' created with bounds [4,6]


Associated nsig/nbkg as expected number of events with sig/bkg _in_therange "signalrange"

In [7]:
RooRealVar nsig("nsig","number of signal events in signalRange",500,0.,10000) ;
RooRealVar nbkg("nbkg","number of background events in signalRange",500,0,10000) ;


Use addpdf to extend the model. giving as many coefficients as pdfs switches on extension.

In [8]:
RooAddPdf  model("model","(g1+g2)+a", RooArgList(bkg,sig), RooArgList(nbkg,nsig)) ;


## Sample data, fit model¶

Generate 1000 events from model so that nsig,nbkg come out to numbers <<500 in fit

In [9]:
RooDataSet *data = model.generate(x,1000) ;

auto canv = new TCanvas("Canvas", "Canvas", 1500, 600);
canv->Divide(3,1);

[#0] WARNING:Eval -- Evaluating RooAddPdf without a defined normalization set. This can lead to ambiguos coefficients definition and incorrect results. Use RooAddPdf::fixCoefNormalization(nset) to provide a normalization set for defining uniquely RooAddPdf coefficients!

input_line_55:2:2: warning: 'data' shadows a declaration with the same name in the 'std' namespace; use '::data' to reference this declaration
RooDataSet *data = model.generate(x,1000) ;
^


## Fit full range¶

In [10]:
canv->cd(1);


Perform unbinned ml fit to data, full range

Important: The model needs to be copied when fitting with different ranges because the interpretation of the coefficients is tied to the fit range that's used in the first fit

In [11]:
RooAddPdf model1(model);
RooFitResult* r = model1.fitTo(*data,Save()) ;
r->Print() ;

RooPlot * frame = x.frame(Title("Full range fitted"));
data->plotOn(frame);
model1.plotOn(frame, VisualizeError(*r));
model1.plotOn(frame);
model1.paramOn(frame);
frame->Draw();

input_line_58:3:33: error: reference to 'data' is ambiguous
RooFitResult* r = model1.fitTo(*data,Save()) ;
^
input_line_55:2:14: note: candidate found by name lookup is '__cling_N528::data'
RooDataSet *data = model.generate(x,1000) ;
^
/usr/include/c++/9/bits/range_access.h:318:5: note: candidate found by name lookup is 'std::data'
data(initializer_list<_Tp> __il) noexcept
^
/usr/include/c++/9/bits/range_access.h:289:5: note: candidate found by name lookup is 'std::data'
data(_Container& __cont) noexcept(noexcept(__cont.data()))
^
/usr/include/c++/9/bits/range_access.h:299:5: note: candidate found by name lookup is 'std::data'
data(const _Container& __cont) noexcept(noexcept(__cont.data()))
^
/usr/include/c++/9/bits/range_access.h:309:5: note: candidate found by name lookup is 'std::data'
data(_Tp (&__array)[_Nm]) noexcept
^
input_line_58:7:1: error: reference to 'data' is ambiguous
data->plotOn(frame);
^
input_line_55:2:14: note: candidate found by name lookup is '__cling_N528::data'
RooDataSet *data = model.generate(x,1000) ;
^
/usr/include/c++/9/bits/range_access.h:318:5: note: candidate found by name lookup is 'std::data'
data(initializer_list<_Tp> __il) noexcept
^
/usr/include/c++/9/bits/range_access.h:289:5: note: candidate found by name lookup is 'std::data'
data(_Container& __cont) noexcept(noexcept(__cont.data()))
^
/usr/include/c++/9/bits/range_access.h:299:5: note: candidate found by name lookup is 'std::data'
data(const _Container& __cont) noexcept(noexcept(__cont.data()))
^
/usr/include/c++/9/bits/range_access.h:309:5: note: candidate found by name lookup is 'std::data'
data(_Tp (&__array)[_Nm]) noexcept
^


## Fit in two regions¶

In [12]:
canv->cd(2);
x.setRange("left",  0., 4.);
x.setRange("right", 6., 10.);

RooFitResult* r2 = model2.fitTo(*data,
Range("left,right"),
Save()) ;
r2->Print();

RooPlot * frame2 = x.frame(Title("Fit in left/right sideband"));
data->plotOn(frame2);
model2.plotOn(frame2, VisualizeError(*r2));
model2.plotOn(frame2);
model2.paramOn(frame2);
frame2->Draw();

input_line_59:7:34: error: reference to 'data' is ambiguous
RooFitResult* r2 = model2.fitTo(*data,
^
input_line_55:2:14: note: candidate found by name lookup is '__cling_N528::data'
RooDataSet *data = model.generate(x,1000) ;
^
/usr/include/c++/9/bits/range_access.h:318:5: note: candidate found by name lookup is 'std::data'
data(initializer_list<_Tp> __il) noexcept
^
/usr/include/c++/9/bits/range_access.h:289:5: note: candidate found by name lookup is 'std::data'
data(_Container& __cont) noexcept(noexcept(__cont.data()))
^
/usr/include/c++/9/bits/range_access.h:299:5: note: candidate found by name lookup is 'std::data'
data(const _Container& __cont) noexcept(noexcept(__cont.data()))
^
/usr/include/c++/9/bits/range_access.h:309:5: note: candidate found by name lookup is 'std::data'
data(_Tp (&__array)[_Nm]) noexcept
^
input_line_59:14:1: error: reference to 'data' is ambiguous
data->plotOn(frame2);
^
input_line_55:2:14: note: candidate found by name lookup is '__cling_N528::data'
RooDataSet *data = model.generate(x,1000) ;
^
/usr/include/c++/9/bits/range_access.h:318:5: note: candidate found by name lookup is 'std::data'
data(initializer_list<_Tp> __il) noexcept
^
/usr/include/c++/9/bits/range_access.h:289:5: note: candidate found by name lookup is 'std::data'
data(_Container& __cont) noexcept(noexcept(__cont.data()))
^
/usr/include/c++/9/bits/range_access.h:299:5: note: candidate found by name lookup is 'std::data'
data(const _Container& __cont) noexcept(noexcept(__cont.data()))
^
/usr/include/c++/9/bits/range_access.h:309:5: note: candidate found by name lookup is 'std::data'
data(_Tp (&__array)[_Nm]) noexcept
^


## Fit in one region¶

Note how restricting the region to only the left tail increases the fit uncertainty

In [13]:
canv->cd(3);
x.setRange("leftToMiddle",  0., 5.);

RooFitResult* r3 = model3.fitTo(*data,
Range("leftToMiddle"),
Save()) ;
r3->Print();

RooPlot * frame3 = x.frame(Title("Fit from left to middle"));
data->plotOn(frame3);
model3.plotOn(frame3, VisualizeError(*r3));
model3.plotOn(frame3);
model3.paramOn(frame3);
frame3->Draw();

canv->Draw();

input_line_60:6:34: error: reference to 'data' is ambiguous
RooFitResult* r3 = model3.fitTo(*data,
^
input_line_55:2:14: note: candidate found by name lookup is '__cling_N528::data'
RooDataSet *data = model.generate(x,1000) ;
^
/usr/include/c++/9/bits/range_access.h:318:5: note: candidate found by name lookup is 'std::data'
data(initializer_list<_Tp> __il) noexcept
^
/usr/include/c++/9/bits/range_access.h:289:5: note: candidate found by name lookup is 'std::data'
data(_Container& __cont) noexcept(noexcept(__cont.data()))
^
/usr/include/c++/9/bits/range_access.h:299:5: note: candidate found by name lookup is 'std::data'
data(const _Container& __cont) noexcept(noexcept(__cont.data()))
^
/usr/include/c++/9/bits/range_access.h:309:5: note: candidate found by name lookup is 'std::data'
data(_Tp (&__array)[_Nm]) noexcept
^
input_line_60:13:1: error: reference to 'data' is ambiguous
data->plotOn(frame3);
^
input_line_55:2:14: note: candidate found by name lookup is '__cling_N528::data'
RooDataSet *data = model.generate(x,1000) ;
^
/usr/include/c++/9/bits/range_access.h:318:5: note: candidate found by name lookup is 'std::data'
data(initializer_list<_Tp> __il) noexcept
^
/usr/include/c++/9/bits/range_access.h:289:5: note: candidate found by name lookup is 'std::data'
data(_Container& __cont) noexcept(noexcept(__cont.data()))
^
/usr/include/c++/9/bits/range_access.h:299:5: note: candidate found by name lookup is 'std::data'
data(const _Container& __cont) noexcept(noexcept(__cont.data()))
^
/usr/include/c++/9/bits/range_access.h:309:5: note: candidate found by name lookup is 'std::data'
data(_Tp (&__array)[_Nm]) noexcept
^


Draw all canvases

In [14]:
%jsroot on
gROOT->GetListOfCanvases()->Draw()