From $ROOTSYS/tutorials/math/testUnfold5d.C

// Author: Stefan Schmitt
// DESY, 14.10.2008

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

#include <iostream>
#include <cmath>
#include <map>
#include <TMath.h>
#include <TCanvas.h>
#include <TStyle.h>
#include <TGraph.h>
#include <TFile.h>
#include <TH1.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 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
//
///////////////////////////////////////////////////////////////////////

// #define PRINT_MATRIX_L

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

  //==============================================
  // step 1 : open output file
  TFile *outputFile=new TFile("testUnfold5_results.root","recreate");

  //==============================================
  // step 2 : read binning schemes and input histograms
  TFile *inputFile=new TFile("testUnfold5_histograms.root");

  outputFile->cd();

  TUnfoldBinning *detectorBinning,*generatorBinning;

  inputFile->GetObject("detector",detectorBinning);
  inputFile->GetObject("generator",generatorBinning);

  if((!detectorBinning)||(!generatorBinning)) {
     cout<<"problem to read binning schemes\n";
  }

  // save binning schemes to output file
  detectorBinning->Write();
  generatorBinning->Write();

  // read histograms
  TH1 *histDataReco,*histDataTruth;
  TH2 *histMCGenRec;

  inputFile->GetObject("histDataReco",histDataReco);
  inputFile->GetObject("histDataTruth",histDataTruth);
  inputFile->GetObject("histMCGenRec",histMCGenRec);

  histDataReco->Write();
  histDataTruth->Write();
  histMCGenRec->Write();

  if((!histDataReco)||(!histDataTruth)||(!histMCGenRec)) {
     cout<<"problem to read input histograms\n";
  }

  //========================
  // Step 3: unfolding

 // preserve the area
  TUnfold::EConstraint constraintMode= TUnfold::kEConstraintArea;

  // basic choice of regularisation scheme:
  //    curvature (second derivative)
  TUnfold::ERegMode regMode = TUnfold::kRegModeCurvature;

  // density flags
  TUnfoldDensity::EDensityMode densityFlags=
    TUnfoldDensity::kDensityModeBinWidth;

  // detailed steering for regularisation
  const char *REGULARISATION_DISTRIBUTION=0;
  const char *REGULARISATION_AXISSTEERING="*[B]";

  // set up matrix of migrations
  TUnfoldDensity unfold(histMCGenRec,TUnfold::kHistMapOutputHoriz,
                        regMode,constraintMode,densityFlags,
                        generatorBinning,detectorBinning,
                        REGULARISATION_DISTRIBUTION,
                        REGULARISATION_AXISSTEERING);

  // define the input vector (the measured data distribution)
  unfold.SetInput(histDataReco /* ,0.0,1.0 */);

  // print matrix of regularisation conditions
#ifdef PRINT_MATRIX_L
  TH2 *histL= unfold.GetL("L");
  for(Int_t j=1;j<=histL->GetNbinsY();j++) {
     cout<<"L["<<unfold.GetLBinning()->GetBinName(j)<<"]";
     for(Int_t i=1;i<=histL->GetNbinsX();i++) {
        Double_t c=histL->GetBinContent(i,j);
        if(c!=0.0) cout<<" ["<<i<<"]="<<c;
     }
     cout<<"\n";
  }
#endif
  // run the unfolding
  //
  // here, tau is determined by scanning the global correlation coefficients

  Int_t nScan=30;
  TSpline *rhoLogTau=0;
  TGraph *lCurve=0;

  // for determining tau, scan the correlation coefficients
  // correlation coefficients may be probed for all distributions
  // or only for selected distributions
  // underflow/overflow bins may be included/excluded
  //
  const char *SCAN_DISTRIBUTION="signal";
  const char *SCAN_AXISSTEERING=0;

  Int_t iBest=unfold.ScanTau(nScan,0.,0.,&rhoLogTau,
                             TUnfoldDensity::kEScanTauRhoMax,
                             SCAN_DISTRIBUTION,SCAN_AXISSTEERING,
                             &lCurve);

  // create graphs with one point to visualize best choice of tau
  Double_t t[1],rho[1],x[1],y[1];
  rhoLogTau->GetKnot(iBest,t[0],rho[0]);
  lCurve->GetPoint(iBest,x[0],y[0]);
  TGraph *bestRhoLogTau=new TGraph(1,t,rho);
  TGraph *bestLCurve=new TGraph(1,x,y);
  Double_t *tAll=new Double_t[nScan],*rhoAll=new Double_t[nScan];
  for(Int_t i=0;i<nScan;i++) {
     rhoLogTau->GetKnot(i,tAll[i],rhoAll[i]);
  }
  TGraph *knots=new TGraph(nScan,tAll,rhoAll);

  cout<<"chi**2="<<unfold.GetChi2A()<<"+"<<unfold.GetChi2L()
      <<" / "<<unfold.GetNdf()<<"\n";


  //===========================
  // Step 4: retreive and plot unfolding results

  // get unfolding output
  TH1 *histDataUnfold=unfold.GetOutput("unfolded signal",0,0,0,kFALSE);
  // get MOnte Carlo reconstructed data
  TH1 *histMCReco=histMCGenRec->ProjectionY("histMCReco",0,-1,"e");
  TH1 *histMCTruth=histMCGenRec->ProjectionX("histMCTruth",0,-1,"e");
  Double_t scaleFactor=histDataTruth->GetSumOfWeights()/
     histMCTruth->GetSumOfWeights();
  histMCReco->Scale(scaleFactor);
  histMCTruth->Scale(scaleFactor);
  // get matrix of probabilities
  TH2 *histProbability=unfold.GetProbabilityMatrix("histProbability");
  // get global correlation coefficients
  TH1 *histGlobalCorr=unfold.GetRhoItotal("histGlobalCorr",0,0,0,kFALSE);
  TH1 *histGlobalCorrScan=unfold.GetRhoItotal
     ("histGlobalCorrScan",0,SCAN_DISTRIBUTION,SCAN_AXISSTEERING,kFALSE);
  TH2 *histCorrCoeff=unfold.GetRhoIJtotal("histCorrCoeff",0,0,0,kFALSE);

  TCanvas canvas;
  canvas.Print("testUnfold5.ps[");

  //========== page 1 ============
  // unfolding control plots
  // input, matrix, output
  // tau-scan, global correlations, correlation coefficients
  canvas.Clear();
  canvas.Divide(3,2);

  // (1) all bins, compare to original MC distribution
  canvas.cd(1);
  histDataReco->SetMinimum(0.0);
  histDataReco->Draw("E");
  histMCReco->SetLineColor(kBlue);
  histMCReco->Draw("SAME HIST");
  // (2) matrix of probabilities
  canvas.cd(2);
  histProbability->Draw("BOX");
  // (3) unfolded data, data truth, MC truth
  canvas.cd(3);
  gPad->SetLogy();
  histDataUnfold->Draw("E");
  histDataTruth->SetLineColor(kBlue);
  histDataTruth->Draw("SAME HIST");
  histMCTruth->SetLineColor(kRed);
  histMCTruth->Draw("SAME HIST");
  // (4) scan of correlation vs tau
  canvas.cd(4);
  rhoLogTau->Draw();
  knots->Draw("*");
  bestRhoLogTau->SetMarkerColor(kRed);
  bestRhoLogTau->Draw("*");
  // (5) global correlation coefficients for the distributions
  //     used during the scan
  canvas.cd(5);
  //histCorrCoeff->Draw("BOX");
  histGlobalCorrScan->Draw("HIST");
  // (6) L-curve
  canvas.cd(6);
  lCurve->Draw("AL");
  bestLCurve->SetMarkerColor(kRed);
  bestLCurve->Draw("*");


  canvas.Print("testUnfold5.ps");

  canvas.Print("testUnfold5.ps]");

}
 testUnfold5d.C:1
 testUnfold5d.C:2
 testUnfold5d.C:3
 testUnfold5d.C:4
 testUnfold5d.C:5
 testUnfold5d.C:6
 testUnfold5d.C:7
 testUnfold5d.C:8
 testUnfold5d.C:9
 testUnfold5d.C:10
 testUnfold5d.C:11
 testUnfold5d.C:12
 testUnfold5d.C:13
 testUnfold5d.C:14
 testUnfold5d.C:15
 testUnfold5d.C:16
 testUnfold5d.C:17
 testUnfold5d.C:18
 testUnfold5d.C:19
 testUnfold5d.C:20
 testUnfold5d.C:21
 testUnfold5d.C:22
 testUnfold5d.C:23
 testUnfold5d.C:24
 testUnfold5d.C:25
 testUnfold5d.C:26
 testUnfold5d.C:27
 testUnfold5d.C:28
 testUnfold5d.C:29
 testUnfold5d.C:30
 testUnfold5d.C:31
 testUnfold5d.C:32
 testUnfold5d.C:33
 testUnfold5d.C:34
 testUnfold5d.C:35
 testUnfold5d.C:36
 testUnfold5d.C:37
 testUnfold5d.C:38
 testUnfold5d.C:39
 testUnfold5d.C:40
 testUnfold5d.C:41
 testUnfold5d.C:42
 testUnfold5d.C:43
 testUnfold5d.C:44
 testUnfold5d.C:45
 testUnfold5d.C:46
 testUnfold5d.C:47
 testUnfold5d.C:48
 testUnfold5d.C:49
 testUnfold5d.C:50
 testUnfold5d.C:51
 testUnfold5d.C:52
 testUnfold5d.C:53
 testUnfold5d.C:54
 testUnfold5d.C:55
 testUnfold5d.C:56
 testUnfold5d.C:57
 testUnfold5d.C:58
 testUnfold5d.C:59
 testUnfold5d.C:60
 testUnfold5d.C:61
 testUnfold5d.C:62
 testUnfold5d.C:63
 testUnfold5d.C:64
 testUnfold5d.C:65
 testUnfold5d.C:66
 testUnfold5d.C:67
 testUnfold5d.C:68
 testUnfold5d.C:69
 testUnfold5d.C:70
 testUnfold5d.C:71
 testUnfold5d.C:72
 testUnfold5d.C:73
 testUnfold5d.C:74
 testUnfold5d.C:75
 testUnfold5d.C:76
 testUnfold5d.C:77
 testUnfold5d.C:78
 testUnfold5d.C:79
 testUnfold5d.C:80
 testUnfold5d.C:81
 testUnfold5d.C:82
 testUnfold5d.C:83
 testUnfold5d.C:84
 testUnfold5d.C:85
 testUnfold5d.C:86
 testUnfold5d.C:87
 testUnfold5d.C:88
 testUnfold5d.C:89
 testUnfold5d.C:90
 testUnfold5d.C:91
 testUnfold5d.C:92
 testUnfold5d.C:93
 testUnfold5d.C:94
 testUnfold5d.C:95
 testUnfold5d.C:96
 testUnfold5d.C:97
 testUnfold5d.C:98
 testUnfold5d.C:99
 testUnfold5d.C:100
 testUnfold5d.C:101
 testUnfold5d.C:102
 testUnfold5d.C:103
 testUnfold5d.C:104
 testUnfold5d.C:105
 testUnfold5d.C:106
 testUnfold5d.C:107
 testUnfold5d.C:108
 testUnfold5d.C:109
 testUnfold5d.C:110
 testUnfold5d.C:111
 testUnfold5d.C:112
 testUnfold5d.C:113
 testUnfold5d.C:114
 testUnfold5d.C:115
 testUnfold5d.C:116
 testUnfold5d.C:117
 testUnfold5d.C:118
 testUnfold5d.C:119
 testUnfold5d.C:120
 testUnfold5d.C:121
 testUnfold5d.C:122
 testUnfold5d.C:123
 testUnfold5d.C:124
 testUnfold5d.C:125
 testUnfold5d.C:126
 testUnfold5d.C:127
 testUnfold5d.C:128
 testUnfold5d.C:129
 testUnfold5d.C:130
 testUnfold5d.C:131
 testUnfold5d.C:132
 testUnfold5d.C:133
 testUnfold5d.C:134
 testUnfold5d.C:135
 testUnfold5d.C:136
 testUnfold5d.C:137
 testUnfold5d.C:138
 testUnfold5d.C:139
 testUnfold5d.C:140
 testUnfold5d.C:141
 testUnfold5d.C:142
 testUnfold5d.C:143
 testUnfold5d.C:144
 testUnfold5d.C:145
 testUnfold5d.C:146
 testUnfold5d.C:147
 testUnfold5d.C:148
 testUnfold5d.C:149
 testUnfold5d.C:150
 testUnfold5d.C:151
 testUnfold5d.C:152
 testUnfold5d.C:153
 testUnfold5d.C:154
 testUnfold5d.C:155
 testUnfold5d.C:156
 testUnfold5d.C:157
 testUnfold5d.C:158
 testUnfold5d.C:159
 testUnfold5d.C:160
 testUnfold5d.C:161
 testUnfold5d.C:162
 testUnfold5d.C:163
 testUnfold5d.C:164
 testUnfold5d.C:165
 testUnfold5d.C:166
 testUnfold5d.C:167
 testUnfold5d.C:168
 testUnfold5d.C:169
 testUnfold5d.C:170
 testUnfold5d.C:171
 testUnfold5d.C:172
 testUnfold5d.C:173
 testUnfold5d.C:174
 testUnfold5d.C:175
 testUnfold5d.C:176
 testUnfold5d.C:177
 testUnfold5d.C:178
 testUnfold5d.C:179
 testUnfold5d.C:180
 testUnfold5d.C:181
 testUnfold5d.C:182
 testUnfold5d.C:183
 testUnfold5d.C:184
 testUnfold5d.C:185
 testUnfold5d.C:186
 testUnfold5d.C:187
 testUnfold5d.C:188
 testUnfold5d.C:189
 testUnfold5d.C:190
 testUnfold5d.C:191
 testUnfold5d.C:192
 testUnfold5d.C:193
 testUnfold5d.C:194
 testUnfold5d.C:195
 testUnfold5d.C:196
 testUnfold5d.C:197
 testUnfold5d.C:198
 testUnfold5d.C:199
 testUnfold5d.C:200
 testUnfold5d.C:201
 testUnfold5d.C:202
 testUnfold5d.C:203
 testUnfold5d.C:204
 testUnfold5d.C:205
 testUnfold5d.C:206
 testUnfold5d.C:207
 testUnfold5d.C:208
 testUnfold5d.C:209
 testUnfold5d.C:210
 testUnfold5d.C:211
 testUnfold5d.C:212
 testUnfold5d.C:213
 testUnfold5d.C:214
 testUnfold5d.C:215
 testUnfold5d.C:216
 testUnfold5d.C:217
 testUnfold5d.C:218
 testUnfold5d.C:219
 testUnfold5d.C:220
 testUnfold5d.C:221
 testUnfold5d.C:222
 testUnfold5d.C:223
 testUnfold5d.C:224
 testUnfold5d.C:225
 testUnfold5d.C:226
 testUnfold5d.C:227
 testUnfold5d.C:228
 testUnfold5d.C:229
 testUnfold5d.C:230
 testUnfold5d.C:231
 testUnfold5d.C:232
 testUnfold5d.C:233
 testUnfold5d.C:234
 testUnfold5d.C:235
 testUnfold5d.C:236
 testUnfold5d.C:237
 testUnfold5d.C:238
 testUnfold5d.C:239
 testUnfold5d.C:240
 testUnfold5d.C:241
 testUnfold5d.C:242
 testUnfold5d.C:243
 testUnfold5d.C:244
 testUnfold5d.C:245
 testUnfold5d.C:246
 testUnfold5d.C:247
 testUnfold5d.C:248
 testUnfold5d.C:249
 testUnfold5d.C:250
 testUnfold5d.C:251
 testUnfold5d.C:252
 testUnfold5d.C:253
 testUnfold5d.C:254
 testUnfold5d.C:255
 testUnfold5d.C:256
 testUnfold5d.C:257
 testUnfold5d.C:258
 testUnfold5d.C:259
 testUnfold5d.C:260
 testUnfold5d.C:261
 testUnfold5d.C:262
 testUnfold5d.C:263
 testUnfold5d.C:264
 testUnfold5d.C:265