From $ROOTSYS/tutorials/math/testUnfold5a.C

// Author: Stefan Schmitt
// DESY, 14.10.2008

//  Version 17.0 example for multi-dimensional unfolding
//

#include <iostream>
#include <map>
#include <cmath>
#include <TMath.h>
#include <TRandom3.h>
#include <TFile.h>
#include <TTree.h>

using namespace std;

/*
  This file is part of TUnfold.

  TUnfold is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  TUnfold is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with TUnfold.  If not, see <http://www.gnu.org/licenses/>.
*/

///////////////////////////////////////////////////////////////////////
//
// Test program for the classes TUnfoldDensity and TUnfoldBinning
//
// A toy test of the TUnfold package
//
// This is an example of unfolding a two-dimensional distribution
// also using an auxillary measurement to constrain some background
//
// The example comprizes several macros
//   testUnfold5a.C   create root files with TTree objects for
//                      signal, background and data
//            -> write files  testUnfold5_signal.root
//                            testUnfold5_background.root
//                            testUnfold5_data.root
//
//   testUnfold5b.C   create a root file with the TUnfoldBinning objects
//            -> write file  testUnfold5_binning.root
//
//   testUnfold5c.C   loop over trees and fill histograms based on the
//                      TUnfoldBinning objects
//            -> read  testUnfold5_binning.root
//                     testUnfold5_signal.root
//                     testUnfold5_background.root
//                     testUnfold5_data.root
//
//            -> write testUnfold5_histograms.root
//
//   testUnfold5d.C   run the unfolding
//            -> read  testUnfold5_histograms.root
//            -> write testUnfold5_result.root
//                     testUnfold5_result.ps
//
///////////////////////////////////////////////////////////////////////

TRandom *g_rnd=0;

class ToyEvent {
public:
   void GenerateDataEvent(TRandom *rnd);
   void GenerateSignalEvent(TRandom *rnd);
   void GenerateBgrEvent(TRandom *rnd);
   // reconstructed quantities
   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; }

   // generator level quantities
   inline Double_t GetPtGen(void) const {
      if(IsSignal()) return fPtGen;
      else return -1.0;
   }
   inline Double_t GetEtaGen(void) const {
       if(IsSignal()) return fEtaGen;
       else return 999.0;
   }
   inline Bool_t IsSignal(void) const { return fIsSignal; }
protected:

   void GenerateSignalKinematics(TRandom *rnd,Bool_t isData);
   void GenerateBgrKinematics(TRandom *rnd,Bool_t isData);
   void GenerateReco(TRandom *rnd);

   // reconstructed quantities
   Double_t fPtRec;
   Double_t fEtaRec;
   Double_t fDiscriminator;
   Bool_t fIsTriggered;
   // generated quantities
   Double_t fPtGen;
   Double_t fEtaGen;
   Bool_t fIsSignal;

   static Double_t kDataSignalFraction;

};

void testUnfold5a()
{
  // random generator
  g_rnd=new TRandom3();

  // data and MC number of events
  const Int_t neventData         =  20000;
  Double_t const neventSignalMC  =2000000;
  Double_t const neventBgrMC     =2000000;

  Float_t etaRec,ptRec,discr,etaGen,ptGen;
  Int_t istriggered,issignal;

  //==================================================================
  // Step 1: generate data TTree

  TFile *dataFile=new TFile("testUnfold5_data.root","recreate");
  TTree *dataTree=new TTree("data","event");

  dataTree->Branch("etarec",&etaRec,"etarec/F");
  dataTree->Branch("ptrec",&ptRec,"ptrec/F");
  dataTree->Branch("discr",&discr,"discr/F");

  // for real data, only the triggered events are available
  dataTree->Branch("istriggered",&istriggered,"istriggered/I");
  // data truth parameters
  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;

     dataTree->Fill();

     if(!(nEvent%100000)) cout<<"   data event "<<nEvent<<"\n";

     if(istriggered) nTriggered++;
     nEvent++;

  }

  dataTree->Write();
  delete dataTree;
  delete dataFile;

  //==================================================================
  // Step 2: generate signal TTree

  TFile *signalFile=new TFile("testUnfold5_signal.root","recreate");
  TTree *signalTree=new TTree("signal","event");

  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";

     signalTree->Fill();
  }

  signalTree->Write();
  delete signalTree;
  delete signalFile;

  // ==============================================================
  // Step 3: generate background MC TTree

  TFile *bgrFile=new TFile("testUnfold5_background.root","recreate");
  TTree *bgrTree=new TTree("background","event");

  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";

     bgrTree->Fill();
  }

  bgrTree->Write();
  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=1;
   GenerateSignalKinematics(rnd,kFALSE);
   GenerateReco(rnd);
}

void ToyEvent::GenerateBgrEvent(TRandom *rnd) {
   fIsSignal=0;
   GenerateBgrKinematics(rnd,kFALSE);
   GenerateReco(rnd);
}

void ToyEvent::GenerateSignalKinematics(TRandom *rnd,Bool_t isData) {
   Double_t e_T0=0.5;
   Double_t e_T0_eta=0.0;
   Double_t e_n=2.0;
   Double_t e_n_eta=0.0;
   Double_t eta_p2=0.0;
   Double_t etaMax=4.0;
   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) {
      fEtaGen=TMath::Power(rnd->Uniform(),eta_p2)*etaMax;
      if(rnd->Uniform()>=0.5) fEtaGen= -fEtaGen;
   } else {
      fEtaGen=rnd->Uniform(-etaMax,etaMax);
   }
   Double_t n=e_n   + e_n_eta*fEtaGen;
   Double_t T0=e_T0 + e_T0_eta*fEtaGen;
   fPtGen=(TMath::Power(rnd->Uniform(),1./(1.-n))-1.)*T0;
   /*   static int print=100;
      if(print) {
         cout<<fEtaGen
            <<" "<<fPtGen
             <<"\n";
         print--;
         } */
}

void ToyEvent::GenerateBgrKinematics(TRandom *rnd,Bool_t isData) {
   fPtGen=0.0;
   fEtaGen=0.0;
   fPtRec=rnd->Exp(2.5);
   fEtaRec=rnd->Uniform(-3.,3.);
}

void ToyEvent::GenerateReco(TRandom *rnd) {
   if(fIsSignal) {
      Double_t expEta=TMath::Exp(fEtaGen);
      Double_t eGen=fPtGen*(expEta+1./expEta);
      Double_t sigmaE=0.1*TMath::Sqrt(eGen)+(0.01+0.002*TMath::Abs(fEtaGen))
         *eGen;
      Double_t eRec;
      do {
         eRec=rnd->Gaus(eGen,sigmaE);
      } while(eRec<=0.0);
      Double_t sigmaEta=0.1+0.02*fEtaGen;
      fEtaRec=rnd->Gaus(fEtaGen,sigmaEta);
      fPtRec=eRec/(expEta+1./expEta);
      do {
         Double_t tauDiscr=0.08-0.04/(1.+fPtRec/10.0);
         Double_t sigmaDiscr=0.01;
         fDiscriminator=1.0-rnd->Exp(tauDiscr)+rnd->Gaus(0.,sigmaDiscr);
      } while((fDiscriminator<=0.)||(fDiscriminator>=1.));
      /* static int print=100;
         if(print) {
         cout<<fEtaGen<<" "<<fPtGen
             <<" -> "<<fEtaRec<<" "<<fPtRec
             <<"\n";
         print--;
         } */
   } else {
      do {
         Double_t tauDiscr=0.15-0.05/(1.+fPtRec/5.0)+0.1*fEtaRec;
         Double_t sigmaDiscr=0.02+0.01*fEtaRec;
         fDiscriminator=rnd->Exp(tauDiscr)+rnd->Gaus(0.,sigmaDiscr);
      } while((fDiscriminator<=0.)||(fDiscriminator>=1.));
   }
   fIsTriggered=(rnd->Uniform()<1./(TMath::Exp(-fPtRec+3.5)+1.));
}
 testUnfold5a.C:1
 testUnfold5a.C:2
 testUnfold5a.C:3
 testUnfold5a.C:4
 testUnfold5a.C:5
 testUnfold5a.C:6
 testUnfold5a.C:7
 testUnfold5a.C:8
 testUnfold5a.C:9
 testUnfold5a.C:10
 testUnfold5a.C:11
 testUnfold5a.C:12
 testUnfold5a.C:13
 testUnfold5a.C:14
 testUnfold5a.C:15
 testUnfold5a.C:16
 testUnfold5a.C:17
 testUnfold5a.C:18
 testUnfold5a.C:19
 testUnfold5a.C:20
 testUnfold5a.C:21
 testUnfold5a.C:22
 testUnfold5a.C:23
 testUnfold5a.C:24
 testUnfold5a.C:25
 testUnfold5a.C:26
 testUnfold5a.C:27
 testUnfold5a.C:28
 testUnfold5a.C:29
 testUnfold5a.C:30
 testUnfold5a.C:31
 testUnfold5a.C:32
 testUnfold5a.C:33
 testUnfold5a.C:34
 testUnfold5a.C:35
 testUnfold5a.C:36
 testUnfold5a.C:37
 testUnfold5a.C:38
 testUnfold5a.C:39
 testUnfold5a.C:40
 testUnfold5a.C:41
 testUnfold5a.C:42
 testUnfold5a.C:43
 testUnfold5a.C:44
 testUnfold5a.C:45
 testUnfold5a.C:46
 testUnfold5a.C:47
 testUnfold5a.C:48
 testUnfold5a.C:49
 testUnfold5a.C:50
 testUnfold5a.C:51
 testUnfold5a.C:52
 testUnfold5a.C:53
 testUnfold5a.C:54
 testUnfold5a.C:55
 testUnfold5a.C:56
 testUnfold5a.C:57
 testUnfold5a.C:58
 testUnfold5a.C:59
 testUnfold5a.C:60
 testUnfold5a.C:61
 testUnfold5a.C:62
 testUnfold5a.C:63
 testUnfold5a.C:64
 testUnfold5a.C:65
 testUnfold5a.C:66
 testUnfold5a.C:67
 testUnfold5a.C:68
 testUnfold5a.C:69
 testUnfold5a.C:70
 testUnfold5a.C:71
 testUnfold5a.C:72
 testUnfold5a.C:73
 testUnfold5a.C:74
 testUnfold5a.C:75
 testUnfold5a.C:76
 testUnfold5a.C:77
 testUnfold5a.C:78
 testUnfold5a.C:79
 testUnfold5a.C:80
 testUnfold5a.C:81
 testUnfold5a.C:82
 testUnfold5a.C:83
 testUnfold5a.C:84
 testUnfold5a.C:85
 testUnfold5a.C:86
 testUnfold5a.C:87
 testUnfold5a.C:88
 testUnfold5a.C:89
 testUnfold5a.C:90
 testUnfold5a.C:91
 testUnfold5a.C:92
 testUnfold5a.C:93
 testUnfold5a.C:94
 testUnfold5a.C:95
 testUnfold5a.C:96
 testUnfold5a.C:97
 testUnfold5a.C:98
 testUnfold5a.C:99
 testUnfold5a.C:100
 testUnfold5a.C:101
 testUnfold5a.C:102
 testUnfold5a.C:103
 testUnfold5a.C:104
 testUnfold5a.C:105
 testUnfold5a.C:106
 testUnfold5a.C:107
 testUnfold5a.C:108
 testUnfold5a.C:109
 testUnfold5a.C:110
 testUnfold5a.C:111
 testUnfold5a.C:112
 testUnfold5a.C:113
 testUnfold5a.C:114
 testUnfold5a.C:115
 testUnfold5a.C:116
 testUnfold5a.C:117
 testUnfold5a.C:118
 testUnfold5a.C:119
 testUnfold5a.C:120
 testUnfold5a.C:121
 testUnfold5a.C:122
 testUnfold5a.C:123
 testUnfold5a.C:124
 testUnfold5a.C:125
 testUnfold5a.C:126
 testUnfold5a.C:127
 testUnfold5a.C:128
 testUnfold5a.C:129
 testUnfold5a.C:130
 testUnfold5a.C:131
 testUnfold5a.C:132
 testUnfold5a.C:133
 testUnfold5a.C:134
 testUnfold5a.C:135
 testUnfold5a.C:136
 testUnfold5a.C:137
 testUnfold5a.C:138
 testUnfold5a.C:139
 testUnfold5a.C:140
 testUnfold5a.C:141
 testUnfold5a.C:142
 testUnfold5a.C:143
 testUnfold5a.C:144
 testUnfold5a.C:145
 testUnfold5a.C:146
 testUnfold5a.C:147
 testUnfold5a.C:148
 testUnfold5a.C:149
 testUnfold5a.C:150
 testUnfold5a.C:151
 testUnfold5a.C:152
 testUnfold5a.C:153
 testUnfold5a.C:154
 testUnfold5a.C:155
 testUnfold5a.C:156
 testUnfold5a.C:157
 testUnfold5a.C:158
 testUnfold5a.C:159
 testUnfold5a.C:160
 testUnfold5a.C:161
 testUnfold5a.C:162
 testUnfold5a.C:163
 testUnfold5a.C:164
 testUnfold5a.C:165
 testUnfold5a.C:166
 testUnfold5a.C:167
 testUnfold5a.C:168
 testUnfold5a.C:169
 testUnfold5a.C:170
 testUnfold5a.C:171
 testUnfold5a.C:172
 testUnfold5a.C:173
 testUnfold5a.C:174
 testUnfold5a.C:175
 testUnfold5a.C:176
 testUnfold5a.C:177
 testUnfold5a.C:178
 testUnfold5a.C:179
 testUnfold5a.C:180
 testUnfold5a.C:181
 testUnfold5a.C:182
 testUnfold5a.C:183
 testUnfold5a.C:184
 testUnfold5a.C:185
 testUnfold5a.C:186
 testUnfold5a.C:187
 testUnfold5a.C:188
 testUnfold5a.C:189
 testUnfold5a.C:190
 testUnfold5a.C:191
 testUnfold5a.C:192
 testUnfold5a.C:193
 testUnfold5a.C:194
 testUnfold5a.C:195
 testUnfold5a.C:196
 testUnfold5a.C:197
 testUnfold5a.C:198
 testUnfold5a.C:199
 testUnfold5a.C:200
 testUnfold5a.C:201
 testUnfold5a.C:202
 testUnfold5a.C:203
 testUnfold5a.C:204
 testUnfold5a.C:205
 testUnfold5a.C:206
 testUnfold5a.C:207
 testUnfold5a.C:208
 testUnfold5a.C:209
 testUnfold5a.C:210
 testUnfold5a.C:211
 testUnfold5a.C:212
 testUnfold5a.C:213
 testUnfold5a.C:214
 testUnfold5a.C:215
 testUnfold5a.C:216
 testUnfold5a.C:217
 testUnfold5a.C:218
 testUnfold5a.C:219
 testUnfold5a.C:220
 testUnfold5a.C:221
 testUnfold5a.C:222
 testUnfold5a.C:223
 testUnfold5a.C:224
 testUnfold5a.C:225
 testUnfold5a.C:226
 testUnfold5a.C:227
 testUnfold5a.C:228
 testUnfold5a.C:229
 testUnfold5a.C:230
 testUnfold5a.C:231
 testUnfold5a.C:232
 testUnfold5a.C:233
 testUnfold5a.C:234
 testUnfold5a.C:235
 testUnfold5a.C:236
 testUnfold5a.C:237
 testUnfold5a.C:238
 testUnfold5a.C:239
 testUnfold5a.C:240
 testUnfold5a.C:241
 testUnfold5a.C:242
 testUnfold5a.C:243
 testUnfold5a.C:244
 testUnfold5a.C:245
 testUnfold5a.C:246
 testUnfold5a.C:247
 testUnfold5a.C:248
 testUnfold5a.C:249
 testUnfold5a.C:250
 testUnfold5a.C:251
 testUnfold5a.C:252
 testUnfold5a.C:253
 testUnfold5a.C:254
 testUnfold5a.C:255
 testUnfold5a.C:256
 testUnfold5a.C:257
 testUnfold5a.C:258
 testUnfold5a.C:259
 testUnfold5a.C:260
 testUnfold5a.C:261
 testUnfold5a.C:262
 testUnfold5a.C:263
 testUnfold5a.C:264
 testUnfold5a.C:265
 testUnfold5a.C:266
 testUnfold5a.C:267
 testUnfold5a.C:268
 testUnfold5a.C:269
 testUnfold5a.C:270
 testUnfold5a.C:271
 testUnfold5a.C:272
 testUnfold5a.C:273
 testUnfold5a.C:274
 testUnfold5a.C:275
 testUnfold5a.C:276
 testUnfold5a.C:277
 testUnfold5a.C:278
 testUnfold5a.C:279
 testUnfold5a.C:280
 testUnfold5a.C:281
 testUnfold5a.C:282
 testUnfold5a.C:283
 testUnfold5a.C:284
 testUnfold5a.C:285
 testUnfold5a.C:286
 testUnfold5a.C:287
 testUnfold5a.C:288
 testUnfold5a.C:289
 testUnfold5a.C:290
 testUnfold5a.C:291
 testUnfold5a.C:292
 testUnfold5a.C:293
 testUnfold5a.C:294
 testUnfold5a.C:295
 testUnfold5a.C:296
 testUnfold5a.C:297
 testUnfold5a.C:298
 testUnfold5a.C:299
 testUnfold5a.C:300
 testUnfold5a.C:301
 testUnfold5a.C:302
 testUnfold5a.C:303
 testUnfold5a.C:304
 testUnfold5a.C:305
 testUnfold5a.C:306
 testUnfold5a.C:307
 testUnfold5a.C:308
 testUnfold5a.C:309
 testUnfold5a.C:310
 testUnfold5a.C:311
 testUnfold5a.C:312
 testUnfold5a.C:313
 testUnfold5a.C:314
 testUnfold5a.C:315
 testUnfold5a.C:316
 testUnfold5a.C:317
 testUnfold5a.C:318
 testUnfold5a.C:319
 testUnfold5a.C:320
 testUnfold5a.C:321
 testUnfold5a.C:322
 testUnfold5a.C:323
 testUnfold5a.C:324
 testUnfold5a.C:325
 testUnfold5a.C:326
 testUnfold5a.C:327
 testUnfold5a.C:328
 testUnfold5a.C:329
 testUnfold5a.C:330
 testUnfold5a.C:331
 testUnfold5a.C:332
 testUnfold5a.C:333