This is an example of unfolding a two-dimensional distribution also using an auxiliary measurement to constrain some background
#include <iostream>
#include <cmath>
using std::cout;
class ToyEvent {
public:
void GenerateDataEvent(
TRandom *rnd);
void GenerateSignalEvent(
TRandom *rnd);
void GenerateBgrEvent(
TRandom *rnd);
inline Double_t GetPtRec(
void)
const {
return fPtRec; }
inline Double_t GetEtaRec(
void)
const {
return fEtaRec; }
inline Double_t GetDiscriminator(
void)
const {
return fDiscriminator; }
inline Bool_t IsTriggered(
void)
const {
return fIsTriggered; }
if(IsSignal()) return fPtGen;
else return -1.0;
}
if(IsSignal()) return fEtaGen;
else return 999.0;
}
inline Bool_t IsSignal(
void)
const {
return fIsSignal; }
protected:
};
void testUnfold5a()
{
const Int_t neventData = 20000;
Float_t etaRec,ptRec,discr,etaGen,ptGen;
Int_t istriggered,issignal;
TFile *dataFile=
new TFile(
"testUnfold5_data.root",
"recreate");
dataTree->
Branch(
"etarec",&etaRec,
"etarec/F");
dataTree->
Branch(
"ptrec",&ptRec,
"ptrec/F");
dataTree->
Branch(
"discr",&discr,
"discr/F");
dataTree->
Branch(
"istriggered",&istriggered,
"istriggered/I");
dataTree->
Branch(
"etagen",&etaGen,
"etagen/F");
dataTree->
Branch(
"ptgen",&ptGen,
"ptgen/F");
dataTree->
Branch(
"issignal",&issignal,
"issignal/I");
cout<<"fill data tree\n";
Int_t nEvent=0,nTriggered=0;
while(nTriggered<neventData) {
ToyEvent event;
event.GenerateDataEvent(g_rnd);
etaRec=event.GetEtaRec();
ptRec=event.GetPtRec();
discr=event.GetDiscriminator();
istriggered=event.IsTriggered() ? 1 : 0;
etaGen=event.GetEtaGen();
ptGen=event.GetPtGen();
issignal=event.IsSignal() ? 1 : 0;
if(!(nEvent%100000)) cout<<" data event "<<nEvent<<"\n";
if(istriggered) nTriggered++;
nEvent++;
}
delete dataTree;
delete dataFile;
TFile *signalFile=
new TFile(
"testUnfold5_signal.root",
"recreate");
signalTree->
Branch(
"etarec",&etaRec,
"etarec/F");
signalTree->
Branch(
"ptrec",&ptRec,
"ptrec/F");
signalTree->
Branch(
"discr",&discr,
"discr/F");
signalTree->
Branch(
"istriggered",&istriggered,
"istriggered/I");
signalTree->
Branch(
"etagen",&etaGen,
"etagen/F");
signalTree->
Branch(
"ptgen",&ptGen,
"ptgen/F");
cout<<"fill signal tree\n";
for(int ievent=0;ievent<neventSignalMC;ievent++) {
ToyEvent event;
event.GenerateSignalEvent(g_rnd);
etaRec=event.GetEtaRec();
ptRec=event.GetPtRec();
discr=event.GetDiscriminator();
istriggered=event.IsTriggered() ? 1 : 0;
etaGen=event.GetEtaGen();
ptGen=event.GetPtGen();
if(!(ievent%100000)) cout<<" signal event "<<ievent<<"\n";
}
delete signalTree;
delete signalFile;
TFile *bgrFile=
new TFile(
"testUnfold5_background.root",
"recreate");
bgrTree->
Branch(
"etarec",&etaRec,
"etarec/F");
bgrTree->
Branch(
"ptrec",&ptRec,
"ptrec/F");
bgrTree->
Branch(
"discr",&discr,
"discr/F");
bgrTree->
Branch(
"istriggered",&istriggered,
"istriggered/I");
cout<<"fill background tree\n";
for(int ievent=0;ievent<neventBgrMC;ievent++) {
ToyEvent event;
event.GenerateBgrEvent(g_rnd);
etaRec=event.GetEtaRec();
ptRec=event.GetPtRec();
discr=event.GetDiscriminator();
istriggered=event.IsTriggered() ? 1 : 0;
if(!(ievent%100000)) cout<<" background event "<<ievent<<"\n";
}
delete bgrTree;
delete bgrFile;
}
Double_t ToyEvent::kDataSignalFraction=0.8;
void ToyEvent::GenerateDataEvent(
TRandom *rnd) {
fIsSignal=rnd->
Uniform()<kDataSignalFraction;
if(IsSignal()) {
GenerateSignalKinematics(rnd,
kTRUE);
} else {
GenerateBgrKinematics(rnd,
kTRUE);
}
GenerateReco(rnd);
}
void ToyEvent::GenerateSignalEvent(
TRandom *rnd) {
fIsSignal=true;
GenerateSignalKinematics(rnd,
kFALSE);
GenerateReco(rnd);
}
void ToyEvent::GenerateBgrEvent(
TRandom *rnd) {
fIsSignal=false;
GenerateBgrKinematics(rnd,
kFALSE);
GenerateReco(rnd);
}
void ToyEvent::GenerateSignalKinematics(
TRandom *rnd,
Bool_t isData) {
if(isData) {
e_T0=0.6;
e_n=2.5;
e_T0_eta=0.05;
e_n_eta=-0.05;
eta_p2=1.5;
}
if(eta_p2>0.0) {
if(rnd->
Uniform()>=0.5) fEtaGen= -fEtaGen;
} else {
fEtaGen=rnd->
Uniform(-etaMax,etaMax);
}
}
void ToyEvent::GenerateBgrKinematics(
TRandom *rnd,
Bool_t isData) {
fPtGen=0.0;
fEtaGen=0.0;
fPtRec=rnd->
Exp(isData ? 2.5 : 2.5);
}
void ToyEvent::GenerateReco(
TRandom *rnd) {
if(fIsSignal) {
Double_t eGen=fPtGen*(expEta+1./expEta);
*eGen;
do {
eRec=rnd->
Gaus(eGen,sigmaE);
} while(eRec<=0.0);
fEtaRec=rnd->
Gaus(fEtaGen,sigmaEta);
fPtRec=eRec/(expEta+1./expEta);
do {
Double_t tauDiscr=0.08-0.04/(1.+fPtRec/10.0);
fDiscriminator=1.0-rnd->
Exp(tauDiscr)+rnd->
Gaus(0.,sigmaDiscr);
} while((fDiscriminator<=0.)||(fDiscriminator>=1.));
} else {
do {
Double_t tauDiscr=0.15-0.05/(1.+fPtRec/5.0)+0.1*fEtaRec;
fDiscriminator=rnd->
Exp(tauDiscr)+rnd->
Gaus(0.,sigmaDiscr);
} while((fDiscriminator<=0.)||(fDiscriminator>=1.));
}
}
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Random number generator class based on M.
This is the base class for the ROOT Random number generators.
virtual Double_t Gaus(Double_t mean=0, Double_t sigma=1)
Samples a random number from the standard Normal (Gaussian) Distribution with the given mean and sigm...
virtual Double_t Exp(Double_t tau)
Returns an exponential deviate.
virtual Double_t Uniform(Double_t x1=1)
Returns a uniform deviate on the interval (0, x1).
A TTree represents a columnar dataset.
virtual Int_t Fill()
Fill all branches.
TBranch * Branch(const char *name, T *obj, Int_t bufsize=32000, Int_t splitlevel=99)
Add a new branch, and infer the data type from the type of obj being passed.
Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) override
Write this object to the current directory.
T etaMax()
Function providing the maximum possible value of pseudorapidity for a non-zero rho,...
Double_t Exp(Double_t x)
Returns the base-e exponential function of x, which is e raised to the power x.
Double_t Sqrt(Double_t x)
Returns the square root of x.
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.