From $ROOTSYS/tutorials/math/testUnfold4.C

// Author: Stefan Schmitt
// DESY, 14.10.2008

//  Version 16.1, parallel to changes in TUnfold
//
//  History:
//    Version 16.0, parallel to changes in TUnfold
//    Version 15, use L-curve scan to scan the average correlation

#include <TMath.h>
#include <TCanvas.h>
#include <TRandom3.h>
#include <TFitter.h>
#include <TF1.h>
#include <TStyle.h>
#include <TVector.h>
#include <TGraph.h>

#include "TUnfoldDensity.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 class TUnfoldSys
//
// Simple toy tests of the TUnfold package
//
// Pseudo data (5000 events) are unfolded into three components
// The unfolding is performed once without and once with area constraint
//
// Ideally, the pulls may show that the result is biased if no constraint
// is applied. This is expected because the true data errors are not known,
// and instead the sqrt(data) errors are used.
//
///////////////////////////////////////////////////////////////////////

TRandom *rnd=0;

Int_t GenerateGenEvent(Int_t nmax,const Double_t *probability) {
   // choose an integer random number in the range [0,nmax]
   //    (the generator level bin)
   // depending on the probabilities
   //   probability[0],probability[1],...probability[nmax-1]
   Double_t f=rnd->Rndm();
   Int_t r=0;
   while((r<nmax)&&(f>=probability[r])) {
      f -= probability[r];
      r++;
   }
   return r;
}

Double_t GenerateRecEvent(const Double_t *shapeParm) {
   // return a coordinate (the reconstructed variable)
   // depending on shapeParm[]
   //  shapeParm[0]: fraction of events with Gaussian distribution
   //  shapeParm[1]: mean of Gaussian
   //  shapeParm[2]: width of Gaussian
   //  (1-shapeParm[0]): fraction of events with flat distribution
   //  shapeParm[3]: minimum of flat component
   //  shapeParm[4]: maximum of flat component
   Double_t f=rnd->Rndm();
   Double_t r;
   if(f<shapeParm[0]) {
      r=rnd->Gaus(shapeParm[1],shapeParm[2]);
   } else {
      r=rnd->Rndm()*(shapeParm[4]-shapeParm[3])+shapeParm[3];
   }
   return r;
}

void testUnfold4()
{
  // switch on histogram errors
  TH1::SetDefaultSumw2();

  // random generator
  rnd=new TRandom3();

  // data and MC number of events
  Double_t const nData0=    500.0;
  Double_t const nMC0  =  50000.0;

  // Binning
  // reconstructed variable (0-10)
  Int_t const nDet=15;
  Double_t const xminDet=0.0;
  Double_t const xmaxDet=15.0;

  // signal binning (three shapes: 0,1,2)
  Int_t const nGen=3;
  Double_t const xminGen=-0.5;
  Double_t const xmaxGen= 2.5;

  // parameters
  // fraction of events per signal shape
  static const Double_t genFrac[]={0.3,0.6,0.1};

  // signal shapes
  static const Double_t genShape[][5]=
     {{1.0,2.0,1.5,0.,15.},
      {1.0,7.0,2.5,0.,15.},
      {0.0,0.0,0.0,0.,15.}};

  // define DATA histograms
  // observed data distribution
  TH1D *histDetDATA=new TH1D("Yrec",";DATA(Yrec)",nDet,xminDet,xmaxDet);

  // define MC histograms
  // matrix of migrations
  TH2D *histGenDetMC=new TH2D("Yrec%Xgen","MC(Xgen,Yrec)",
                              nGen,xminGen,xmaxGen,nDet,xminDet,xmaxDet);

  TH1D *histUnfold=new TH1D("Xgen",";DATA(Xgen)",nGen,xminGen,xmaxGen);

  TH1D **histPullNC=new TH1D* [nGen];
  TH1D **histPullArea=new TH1D* [nGen];
  for(int i=0;i<nGen;i++) {
     histPullNC[i]=new TH1D(TString::Format("PullNC%d",i),"pull",15,-3.,3.);
     histPullArea[i]=new TH1D(TString::Format("PullArea%d",i),"pull",15,-3.,3.);
  }

  // this method is new in version 16 of TUnfold
  cout<<"TUnfold version is "<<TUnfold::GetTUnfoldVersion()<<"\n";

  for(int itoy=0;itoy<1000;itoy++) {
     if(!(itoy %10)) cout<<"toy iteration: "<<itoy<<"\n";
     histDetDATA->Reset();
     histGenDetMC->Reset();

     Int_t nData=rnd->Poisson(nData0);
     for(Int_t i=0;i<nData;i++) {
        Int_t iGen=GenerateGenEvent(nGen,genFrac);
        Double_t yObs=GenerateRecEvent(genShape[iGen]);
        histDetDATA->Fill(yObs);
     }
     
     Int_t nMC=rnd->Poisson(nMC0);
     for(Int_t i=0;i<nMC;i++) {
        Int_t iGen=GenerateGenEvent(nGen,genFrac);
        Double_t yObs=GenerateRecEvent(genShape[iGen]);
        histGenDetMC->Fill(iGen,yObs);
     }
     /* for(Int_t ix=0;ix<=histGenDetMC->GetNbinsX()+1;ix++) {
        for(Int_t iy=0;iy<=histGenDetMC->GetNbinsY()+1;iy++) {
           cout<<ix<<iy<<" : "<<histGenDetMC->GetBinContent(ix,iy)<<"\n";
        }
        } */
     //========================
     // unfolding
     
     // switch off info messages
#ifndef DEBUG
     gErrorIgnoreLevel = 1001;
#endif

     TUnfoldSys unfold(histGenDetMC,TUnfold::kHistMapOutputHoriz,
                       TUnfold::kRegModeSize,TUnfold::kEConstraintNone);
     // define the input vector (the measured data distribution)
     unfold.SetInput(histDetDATA,0.0,1.0);

     // run the unfolding
     unfold.ScanLcurve(50,0.,0.,0,0,0);

     // fill pull distributions without constraint
     unfold.GetOutput(histUnfold);

     for(int i=0;i<nGen;i++) {
        histPullNC[i]->Fill((histUnfold->GetBinContent(i+1)-genFrac[i]*nData0)/
                            histUnfold->GetBinError(i+1));
     }

     // repeat unfolding on the same data, now with Area constraint
     unfold.SetConstraint(TUnfold::kEConstraintArea);

     // run the unfolding
     unfold.ScanLcurve(50,0.,0.,0,0,0);

     // fill pull distributions with constraint
     unfold.GetOutput(histUnfold);

     for(int i=0;i<nGen;i++) {
        histPullArea[i]->Fill((histUnfold->GetBinContent(i+1)-genFrac[i]*nData0)/
                            histUnfold->GetBinError(i+1));
     }
     
  }
  TCanvas output;
  output.Divide(3,2);

  gStyle->SetOptFit(1111);
  
  for(int i=0;i<nGen;i++) {
     output.cd(i+1);
     histPullNC[i]->Fit("gaus");
     histPullNC[i]->Draw();
  }
  for(int i=0;i<nGen;i++) {
     output.cd(i+4);
     histPullArea[i]->Fit("gaus");
     histPullArea[i]->Draw();
  }
  output.SaveAs("testUnfold4.ps");
}
 testUnfold4.C:1
 testUnfold4.C:2
 testUnfold4.C:3
 testUnfold4.C:4
 testUnfold4.C:5
 testUnfold4.C:6
 testUnfold4.C:7
 testUnfold4.C:8
 testUnfold4.C:9
 testUnfold4.C:10
 testUnfold4.C:11
 testUnfold4.C:12
 testUnfold4.C:13
 testUnfold4.C:14
 testUnfold4.C:15
 testUnfold4.C:16
 testUnfold4.C:17
 testUnfold4.C:18
 testUnfold4.C:19
 testUnfold4.C:20
 testUnfold4.C:21
 testUnfold4.C:22
 testUnfold4.C:23
 testUnfold4.C:24
 testUnfold4.C:25
 testUnfold4.C:26
 testUnfold4.C:27
 testUnfold4.C:28
 testUnfold4.C:29
 testUnfold4.C:30
 testUnfold4.C:31
 testUnfold4.C:32
 testUnfold4.C:33
 testUnfold4.C:34
 testUnfold4.C:35
 testUnfold4.C:36
 testUnfold4.C:37
 testUnfold4.C:38
 testUnfold4.C:39
 testUnfold4.C:40
 testUnfold4.C:41
 testUnfold4.C:42
 testUnfold4.C:43
 testUnfold4.C:44
 testUnfold4.C:45
 testUnfold4.C:46
 testUnfold4.C:47
 testUnfold4.C:48
 testUnfold4.C:49
 testUnfold4.C:50
 testUnfold4.C:51
 testUnfold4.C:52
 testUnfold4.C:53
 testUnfold4.C:54
 testUnfold4.C:55
 testUnfold4.C:56
 testUnfold4.C:57
 testUnfold4.C:58
 testUnfold4.C:59
 testUnfold4.C:60
 testUnfold4.C:61
 testUnfold4.C:62
 testUnfold4.C:63
 testUnfold4.C:64
 testUnfold4.C:65
 testUnfold4.C:66
 testUnfold4.C:67
 testUnfold4.C:68
 testUnfold4.C:69
 testUnfold4.C:70
 testUnfold4.C:71
 testUnfold4.C:72
 testUnfold4.C:73
 testUnfold4.C:74
 testUnfold4.C:75
 testUnfold4.C:76
 testUnfold4.C:77
 testUnfold4.C:78
 testUnfold4.C:79
 testUnfold4.C:80
 testUnfold4.C:81
 testUnfold4.C:82
 testUnfold4.C:83
 testUnfold4.C:84
 testUnfold4.C:85
 testUnfold4.C:86
 testUnfold4.C:87
 testUnfold4.C:88
 testUnfold4.C:89
 testUnfold4.C:90
 testUnfold4.C:91
 testUnfold4.C:92
 testUnfold4.C:93
 testUnfold4.C:94
 testUnfold4.C:95
 testUnfold4.C:96
 testUnfold4.C:97
 testUnfold4.C:98
 testUnfold4.C:99
 testUnfold4.C:100
 testUnfold4.C:101
 testUnfold4.C:102
 testUnfold4.C:103
 testUnfold4.C:104
 testUnfold4.C:105
 testUnfold4.C:106
 testUnfold4.C:107
 testUnfold4.C:108
 testUnfold4.C:109
 testUnfold4.C:110
 testUnfold4.C:111
 testUnfold4.C:112
 testUnfold4.C:113
 testUnfold4.C:114
 testUnfold4.C:115
 testUnfold4.C:116
 testUnfold4.C:117
 testUnfold4.C:118
 testUnfold4.C:119
 testUnfold4.C:120
 testUnfold4.C:121
 testUnfold4.C:122
 testUnfold4.C:123
 testUnfold4.C:124
 testUnfold4.C:125
 testUnfold4.C:126
 testUnfold4.C:127
 testUnfold4.C:128
 testUnfold4.C:129
 testUnfold4.C:130
 testUnfold4.C:131
 testUnfold4.C:132
 testUnfold4.C:133
 testUnfold4.C:134
 testUnfold4.C:135
 testUnfold4.C:136
 testUnfold4.C:137
 testUnfold4.C:138
 testUnfold4.C:139
 testUnfold4.C:140
 testUnfold4.C:141
 testUnfold4.C:142
 testUnfold4.C:143
 testUnfold4.C:144
 testUnfold4.C:145
 testUnfold4.C:146
 testUnfold4.C:147
 testUnfold4.C:148
 testUnfold4.C:149
 testUnfold4.C:150
 testUnfold4.C:151
 testUnfold4.C:152
 testUnfold4.C:153
 testUnfold4.C:154
 testUnfold4.C:155
 testUnfold4.C:156
 testUnfold4.C:157
 testUnfold4.C:158
 testUnfold4.C:159
 testUnfold4.C:160
 testUnfold4.C:161
 testUnfold4.C:162
 testUnfold4.C:163
 testUnfold4.C:164
 testUnfold4.C:165
 testUnfold4.C:166
 testUnfold4.C:167
 testUnfold4.C:168
 testUnfold4.C:169
 testUnfold4.C:170
 testUnfold4.C:171
 testUnfold4.C:172
 testUnfold4.C:173
 testUnfold4.C:174
 testUnfold4.C:175
 testUnfold4.C:176
 testUnfold4.C:177
 testUnfold4.C:178
 testUnfold4.C:179
 testUnfold4.C:180
 testUnfold4.C:181
 testUnfold4.C:182
 testUnfold4.C:183
 testUnfold4.C:184
 testUnfold4.C:185
 testUnfold4.C:186
 testUnfold4.C:187
 testUnfold4.C:188
 testUnfold4.C:189
 testUnfold4.C:190
 testUnfold4.C:191
 testUnfold4.C:192
 testUnfold4.C:193
 testUnfold4.C:194
 testUnfold4.C:195
 testUnfold4.C:196
 testUnfold4.C:197
 testUnfold4.C:198
 testUnfold4.C:199
 testUnfold4.C:200
 testUnfold4.C:201
 testUnfold4.C:202
 testUnfold4.C:203
 testUnfold4.C:204
 testUnfold4.C:205
 testUnfold4.C:206
 testUnfold4.C:207
 testUnfold4.C:208
 testUnfold4.C:209
 testUnfold4.C:210
 testUnfold4.C:211
 testUnfold4.C:212
 testUnfold4.C:213
 testUnfold4.C:214
 testUnfold4.C:215
 testUnfold4.C:216
 testUnfold4.C:217
 testUnfold4.C:218
 testUnfold4.C:219
 testUnfold4.C:220
 testUnfold4.C:221
 testUnfold4.C:222
 testUnfold4.C:223