LCOV - code coverage report
Current view: top level - ANALYSIS/ANALYSISalice - AliUnfolding.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 806 0.1 %
Date: 2016-06-14 17:26:59 Functions: 1 34 2.9 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
       3             :  *                                                                        *
       4             :  * Author: The ALICE Off-line Project.                                    *
       5             :  * Contributors are mentioned in the code where appropriate.              *
       6             :  *                                                                        *
       7             :  * Permission to use, copy, modify and distribute this software and its   *
       8             :  * documentation strictly for non-commercial purposes is hereby granted   *
       9             :  * without fee, provided that the above copyright notice appears in all   *
      10             :  * copies and that both the copyright notice and this permission notice   *
      11             :  * appear in the supporting documentation. The authors make no claims     *
      12             :  * about the suitability of this software for any purpose. It is          *
      13             :  * provided "as is" without express or implied warranty.                  *
      14             :  **************************************************************************/
      15             : 
      16             : /* $Id: AliUnfolding.cxx 31168 2009-02-23 15:18:45Z jgrosseo $ */
      17             : 
      18             : // This class allows 1-dimensional unfolding.
      19             : // Methods that are implemented are chi2 minimization and bayesian unfolding.
      20             : //
      21             : //  Author: Jan.Fiete.Grosse-Oetringhaus@cern.ch
      22             : 
      23             : #include "AliUnfolding.h"
      24             : #include <TH1F.h>
      25             : #include <TH2F.h>
      26             : #include <TVirtualFitter.h>
      27             : #include <TMath.h>
      28             : #include <TCanvas.h>
      29             : #include <TF1.h>
      30             : #include <TExec.h>
      31             : #include "Riostream.h"
      32             : #include "TROOT.h"
      33             : 
      34             : using namespace std; //required for resolving the 'cout' symbol
      35             : 
      36             : TMatrixD* AliUnfolding::fgCorrelationMatrix = 0;
      37             : TMatrixD* AliUnfolding::fgCorrelationMatrixSquared = 0;
      38             : TMatrixD* AliUnfolding::fgCorrelationCovarianceMatrix = 0;
      39             : TVectorD* AliUnfolding::fgCurrentESDVector = 0;
      40             : TVectorD* AliUnfolding::fgEntropyAPriori = 0;
      41             : TVectorD* AliUnfolding::fgEfficiency = 0;
      42             : 
      43             : TAxis* AliUnfolding::fgUnfoldedAxis = 0;
      44             : TAxis* AliUnfolding::fgMeasuredAxis = 0;
      45             : 
      46             : TF1* AliUnfolding::fgFitFunction = 0;
      47             : 
      48             : AliUnfolding::MethodType AliUnfolding::fgMethodType = AliUnfolding::kInvalid;
      49             : Int_t AliUnfolding::fgMaxInput  = -1;  // bins in measured histogram
      50             : Int_t AliUnfolding::fgMaxParams = -1;  // bins in unfolded histogram = number of fit params
      51             : Float_t AliUnfolding::fgOverflowBinLimit = -1;
      52             : 
      53             : AliUnfolding::RegularizationType AliUnfolding::fgRegularizationType = AliUnfolding::kPol1;
      54             : Float_t AliUnfolding::fgRegularizationWeight = 10000;
      55             : Int_t AliUnfolding::fgSkipBinsBegin = 0;
      56             : Float_t AliUnfolding::fgMinuitStepSize = 0.1;                 // (usually not needed to be changed) step size in minimization
      57             : Float_t AliUnfolding::fgMinuitPrecision = 1e-6;               // minuit precision
      58             : Int_t   AliUnfolding::fgMinuitMaxIterations = 1000000;            // minuit maximum number of iterations
      59             : Double_t AliUnfolding::fgMinuitStrategy = 1.;                 // minuit strategy
      60             : Bool_t AliUnfolding::fgMinimumInitialValue = kFALSE;          // set all initial values at least to the smallest value among the initial values
      61             : Float_t AliUnfolding::fgMinimumInitialValueFix = -1;
      62             : Bool_t AliUnfolding::fgNormalizeInput = kFALSE;               // normalize input spectrum
      63             : Float_t AliUnfolding::fgNotFoundEvents = 0;
      64             : Bool_t AliUnfolding::fgSkipBin0InChi2 = kFALSE;
      65             : 
      66             : Float_t AliUnfolding::fgBayesianSmoothing  = 1;           // smoothing parameter (0 = no smoothing)
      67             : Int_t   AliUnfolding::fgBayesianIterations = 10;          // number of iterations in Bayesian method
      68             : 
      69             : Bool_t AliUnfolding::fgDebug = kFALSE;
      70             : 
      71             : Int_t AliUnfolding::fgCallCount = 0;
      72             : 
      73             : Int_t AliUnfolding::fgPowern = 5;
      74             : 
      75             : Double_t AliUnfolding::fChi2FromFit = 0.;
      76             : Double_t AliUnfolding::fPenaltyVal  = 0.;
      77             : Double_t AliUnfolding::fAvgResidual = 0.;
      78             : 
      79             : Int_t AliUnfolding::fgPrintChi2Details = 0;
      80             : 
      81             : TCanvas *AliUnfolding::fgCanvas = 0;
      82             : TH1 *AliUnfolding::fghUnfolded = 0;     
      83             : TH2 *AliUnfolding::fghCorrelation = 0;  
      84             : TH1 *AliUnfolding::fghEfficiency = 0;   
      85             : TH1 *AliUnfolding::fghMeasured = 0;     
      86             : 
      87         170 : ClassImp(AliUnfolding)
      88             : 
      89             : //____________________________________________________________________
      90             : void AliUnfolding::SetUnfoldingMethod(MethodType methodType)
      91             : {
      92             :   // set unfolding method
      93           0 :   fgMethodType = methodType; 
      94             :   
      95             :   const char* name = 0;
      96           0 :   switch (methodType)
      97             :   {
      98           0 :     case kInvalid: name = "INVALID"; break;
      99           0 :     case kChi2Minimization: name = "Chi2 Minimization"; break;
     100           0 :     case kBayesian: name = "Bayesian unfolding"; break;
     101           0 :     case kFunction: name = "Functional fit"; break;
     102             :   }
     103           0 :   Printf("AliUnfolding::SetUnfoldingMethod: %s enabled.", name);
     104           0 : }
     105             : 
     106             : //____________________________________________________________________
     107             : void AliUnfolding::SetCreateOverflowBin(Float_t overflowBinLimit) 
     108             : { 
     109             :   // enable the creation of a overflow bin that includes all statistics below the given limit
     110             :   
     111           0 :   fgOverflowBinLimit = overflowBinLimit; 
     112             :   
     113           0 :   Printf("AliUnfolding::SetCreateOverflowBin: overflow bin limit set to %f", overflowBinLimit);
     114           0 : }
     115             : 
     116             : //____________________________________________________________________
     117             : void AliUnfolding::SetSkipBinsBegin(Int_t nBins)
     118             : {
     119             :   // set number of skipped bins in regularization
     120             :   
     121           0 :   fgSkipBinsBegin = nBins;
     122             :   
     123           0 :   Printf("AliUnfolding::SetSkipBinsBegin: skipping %d bins at the beginning of the spectrum in the regularization.", fgSkipBinsBegin);
     124           0 : }
     125             : 
     126             : //____________________________________________________________________
     127             : void AliUnfolding::SetNbins(Int_t nMeasured, Int_t nUnfolded) 
     128             : { 
     129             :   // set number of bins in the input (measured) distribution and in the unfolded distribution
     130           0 :   fgMaxInput = nMeasured; 
     131           0 :   fgMaxParams = nUnfolded; 
     132             :   
     133           0 :   if (fgCorrelationMatrix)
     134             :   {
     135           0 :     delete fgCorrelationMatrix;
     136           0 :     fgCorrelationMatrix = 0;
     137           0 :   }
     138           0 :   if (fgCorrelationMatrixSquared)
     139             :   {
     140           0 :     fgCorrelationMatrixSquared = 0;
     141           0 :     delete fgCorrelationMatrixSquared;
     142             :   }
     143           0 :   if (fgCorrelationCovarianceMatrix)
     144             :   {
     145           0 :     delete fgCorrelationCovarianceMatrix;
     146           0 :     fgCorrelationCovarianceMatrix = 0;
     147           0 :   }
     148           0 :   if (fgCurrentESDVector)
     149             :   {
     150           0 :     delete fgCurrentESDVector;
     151           0 :     fgCurrentESDVector = 0;
     152           0 :   }
     153           0 :   if (fgEntropyAPriori)
     154             :   {
     155           0 :     delete fgEntropyAPriori;
     156           0 :     fgEntropyAPriori = 0;
     157           0 :   }
     158           0 :   if (fgEfficiency)
     159             :   {
     160           0 :     delete fgEfficiency;
     161           0 :     fgEfficiency = 0;
     162           0 :   }
     163           0 :   if (fgUnfoldedAxis)
     164             :   {
     165           0 :     delete fgUnfoldedAxis;
     166           0 :     fgUnfoldedAxis = 0;
     167           0 :   }
     168           0 :   if (fgMeasuredAxis)
     169             :   {
     170           0 :     delete fgMeasuredAxis;
     171           0 :     fgMeasuredAxis = 0;
     172           0 :   }
     173             :   
     174           0 :   Printf("AliUnfolding::SetNbins: Set %d measured bins and %d unfolded bins", nMeasured, nUnfolded);
     175           0 : }
     176             : 
     177             : //____________________________________________________________________
     178             : void AliUnfolding::SetChi2Regularization(RegularizationType type, Float_t weight)
     179             : {
     180             :   //
     181             :   // sets the parameters for chi2 minimization
     182             :   //
     183             : 
     184           0 :   fgRegularizationType = type;
     185           0 :   fgRegularizationWeight = weight;
     186             : 
     187           0 :   Printf("AliUnfolding::SetChi2Regularization --> Regularization set to %d with weight %f", (Int_t) type, weight);
     188           0 : }
     189             : 
     190             : //____________________________________________________________________
     191             : void AliUnfolding::SetBayesianParameters(Float_t smoothing, Int_t nIterations)
     192             : {
     193             :   //
     194             :   // sets the parameters for Bayesian unfolding
     195             :   //
     196             : 
     197           0 :   fgBayesianSmoothing = smoothing;
     198           0 :   fgBayesianIterations = nIterations;
     199             : 
     200           0 :   Printf("AliUnfolding::SetBayesianParameters --> Parameters set to %d iterations with smoothing %f", fgBayesianIterations, fgBayesianSmoothing);
     201           0 : }
     202             : 
     203             : //____________________________________________________________________
     204             : void AliUnfolding::SetFunction(TF1* function)
     205             : {
     206             :   // set function for unfolding with a fit function
     207             :   
     208           0 :   fgFitFunction = function;
     209             :   
     210           0 :   Printf("AliUnfolding::SetFunction: Set fit function with %d parameters.", function->GetNpar());
     211           0 : }
     212             : 
     213             : //____________________________________________________________________
     214             : Int_t AliUnfolding::Unfold(TH2* correlation, TH1* efficiency, TH1* measured, TH1* initialConditions, TH1* result, Bool_t check)
     215             : {
     216             :   // unfolds with unfolding method fgMethodType
     217             :   //
     218             :   // parameters:
     219             :   //  correlation: response matrix as measured vs. generated
     220             :   //  efficiency:  (optional) efficiency that is applied on the unfolded spectrum, i.e. it has to be in unfolded variables. If 0 no efficiency is applied.
     221             :   //  measured:    the measured spectrum
     222             :   //  initialConditions: (optional) initial conditions for the unfolding. if 0 the measured spectrum is used as initial conditions.
     223             :   //  result:      target for the unfolded result
     224             :   //  check:       depends on the unfolding method, see comments in specific functions
     225             :   //
     226             :   //  return code: see UnfoldWithMinuit/UnfoldWithBayesian/UnfoldWithFunction
     227             : 
     228           0 :   if (fgMaxInput == -1)
     229             :   {
     230           0 :     Printf("AliUnfolding::Unfold: WARNING. Number of measured bins not set with SetNbins. Using number of bins in measured distribution");
     231           0 :     fgMaxInput = measured->GetNbinsX();
     232           0 :   }
     233           0 :   if (fgMaxParams == -1)
     234             :   {
     235           0 :     Printf("AliUnfolding::Unfold: WARNING. Number of unfolded bins not set with SetNbins. Using number of bins in measured distribution");
     236           0 :     fgMaxParams = measured->GetNbinsX();
     237           0 :   }
     238             : 
     239           0 :   if (fgOverflowBinLimit > 0)
     240           0 :     CreateOverflowBin(correlation, measured);
     241             :     
     242           0 :   switch (fgMethodType)
     243             :   {
     244             :     case kInvalid:
     245             :     {
     246           0 :       Printf("AliUnfolding::Unfold: ERROR: Unfolding method not set. Use SetUnfoldingMethod. Exiting...");
     247           0 :       return -1;
     248             :     }
     249             :     case kChi2Minimization:
     250           0 :       return UnfoldWithMinuit(correlation, efficiency, measured, initialConditions, result, check);
     251             :     case kBayesian:
     252           0 :       return UnfoldWithBayesian(correlation, efficiency, measured, initialConditions, result);
     253             :     case kFunction:
     254           0 :       return UnfoldWithFunction(correlation, efficiency, measured, initialConditions, result);
     255             :   }
     256             : 
     257             : 
     258             : 
     259           0 :   return -1;
     260           0 : }
     261             : 
     262             : //____________________________________________________________________
     263             : void AliUnfolding::SetStaticVariables(TH2* correlation, TH1* measured, TH1* efficiency)
     264             : {
     265             :   // fill static variables needed for minuit fit
     266             : 
     267           0 :   if (!fgCorrelationMatrix)
     268           0 :     fgCorrelationMatrix = new TMatrixD(fgMaxInput, fgMaxParams);
     269           0 :   if (!fgCorrelationMatrixSquared)
     270           0 :     fgCorrelationMatrixSquared = new TMatrixD(fgMaxInput, fgMaxParams);
     271           0 :   if (!fgCorrelationCovarianceMatrix)
     272           0 :     fgCorrelationCovarianceMatrix = new TMatrixD(fgMaxInput, fgMaxInput);
     273           0 :   if (!fgCurrentESDVector)
     274           0 :     fgCurrentESDVector = new TVectorD(fgMaxInput);
     275           0 :   if (!fgEntropyAPriori)
     276           0 :     fgEntropyAPriori = new TVectorD(fgMaxParams);
     277           0 :   if (!fgEfficiency)
     278           0 :     fgEfficiency = new TVectorD(fgMaxParams);
     279           0 :   if (fgUnfoldedAxis)
     280             :   {
     281           0 :     delete fgUnfoldedAxis;
     282           0 :     fgUnfoldedAxis = 0;
     283           0 :   }
     284           0 :   if (!fgUnfoldedAxis) 
     285           0 :     fgUnfoldedAxis = new TAxis(*(correlation->GetXaxis()));
     286           0 :   if (fgMeasuredAxis)
     287             :   {
     288           0 :     delete fgMeasuredAxis;
     289           0 :     fgMeasuredAxis = 0;
     290           0 :   }
     291           0 :   if (!fgMeasuredAxis) 
     292           0 :     fgMeasuredAxis = new TAxis(*(correlation->GetYaxis()));
     293             : 
     294           0 :   fgCorrelationMatrix->Zero();
     295           0 :   fgCorrelationCovarianceMatrix->Zero();
     296           0 :   fgCurrentESDVector->Zero();
     297           0 :   fgEntropyAPriori->Zero();
     298             : 
     299             :   // normalize correction for given nPart
     300           0 :   for (Int_t i=1; i<=correlation->GetNbinsX(); ++i)
     301             :   {
     302           0 :     Double_t sum = correlation->Integral(i, i, 1, correlation->GetNbinsY());
     303           0 :     if (sum <= 0)
     304           0 :       continue;
     305             :     Float_t maxValue = 0;
     306             :     //    Int_t maxBin = -1;
     307           0 :     for (Int_t j=1; j<=correlation->GetNbinsY(); ++j)
     308             :     {
     309             :       // find most probably value
     310           0 :       if (maxValue < correlation->GetBinContent(i, j))
     311             :       {
     312           0 :         maxValue = correlation->GetBinContent(i, j);
     313             :         //        maxBin = j;
     314           0 :       }
     315             : 
     316             :       // npart sum to 1
     317           0 :       correlation->SetBinContent(i, j, correlation->GetBinContent(i, j) / sum);// * correlation->GetXaxis()->GetBinWidth(i));
     318           0 :       correlation->SetBinError(i, j, correlation->GetBinError(i, j) / sum);
     319             : 
     320           0 :       if (i <= fgMaxParams && j <= fgMaxInput)
     321             :       {
     322           0 :         (*fgCorrelationMatrix)(j-1, i-1) = correlation->GetBinContent(i, j);
     323           0 :         (*fgCorrelationMatrixSquared)(j-1, i-1) = correlation->GetBinContent(i, j) * correlation->GetBinContent(i, j);
     324           0 :       }
     325             :     }
     326             : 
     327             :     //printf("MPV for Ntrue = %f is %f\n", fCurrentCorrelation->GetXaxis()->GetBinCenter(i), fCurrentCorrelation->GetYaxis()->GetBinCenter(maxBin));
     328           0 :   }
     329             :     
     330             :   //normalize measured
     331             :   Float_t smallestError = 1;
     332           0 :   if (fgNormalizeInput)
     333             :   {
     334           0 :     Float_t sumMeasured = measured->Integral();
     335           0 :     measured->Scale(1.0 / sumMeasured);
     336           0 :     smallestError /= sumMeasured;
     337           0 :   }
     338             :   
     339           0 :   for (Int_t i=0; i<fgMaxInput; ++i)
     340             :   {
     341           0 :     (*fgCurrentESDVector)[i] = measured->GetBinContent(i+1);
     342           0 :     if (measured->GetBinError(i+1) > 0)
     343             :     {
     344           0 :       (*fgCorrelationCovarianceMatrix)(i, i) = (Double_t) 1e-6 / measured->GetBinError(i+1) / measured->GetBinError(i+1);
     345           0 :     }
     346             :     else // in this case put error of 1, otherwise 0 bins are not added to the chi2...
     347           0 :       (*fgCorrelationCovarianceMatrix)(i, i) = (Double_t) 1e-6 / smallestError / smallestError;
     348             : 
     349           0 :     if ((*fgCorrelationCovarianceMatrix)(i, i) > 1e7)
     350           0 :       (*fgCorrelationCovarianceMatrix)(i, i) = 0;
     351             :     //Printf("%d, %e", i, (*fgCorrelationCovarianceMatrix)(i, i));
     352             :   }
     353             : 
     354             :   // efficiency is expected to match bin width of result
     355           0 :   for (Int_t i=0; i<fgMaxParams; ++i)
     356             :   {
     357           0 :     (*fgEfficiency)(i) = efficiency->GetBinContent(i+1);
     358             :   }
     359             : 
     360           0 :   if (correlation->GetNbinsX() != fgMaxParams || correlation->GetNbinsY() != fgMaxInput)
     361           0 :     cout << "Response histo has incorrect dimensions; expect (" << fgMaxParams << ", " << fgMaxInput << "), got (" << correlation->GetNbinsX() << ", " << correlation->GetNbinsY() << ")" << endl;
     362             : 
     363           0 : }
     364             : 
     365             : //____________________________________________________________________
     366             : Int_t AliUnfolding::UnfoldWithMinuit(TH2* correlation, TH1* efficiency, TH1* measured, TH1* initialConditions, TH1* result, Bool_t check)
     367             : {
     368             :   //
     369             :   // implementation of unfolding (internal function)
     370             :   //
     371             :   // unfolds <measured> using response from <correlation> and effiency <efficiency>
     372             :   // output is in <result>
     373             :   // <initialConditions> set the initial values for the minimization, if 0 <measured> is used
     374             :   //   negative values in initialConditions mean that the given parameter is fixed to the absolute of the value
     375             :   // if <check> is true no unfolding is made, instead only the chi2 without unfolding is printed
     376             :   //
     377             :   // returns minuit status (0 = success), (-1 when check was set)
     378             :   //
     379             : 
     380           0 :   SetStaticVariables(correlation, measured, efficiency);
     381             :   
     382             :   // Initialize TMinuit via generic fitter interface
     383           0 :   Int_t params = fgMaxParams;
     384           0 :   if (fgNotFoundEvents > 0)
     385           0 :     params++;
     386             :     
     387           0 :   TVirtualFitter *minuit = TVirtualFitter::Fitter(0, params);
     388           0 :   Double_t arglist[100];
     389             :   //  minuit->SetDefaultFitter("Minuit2");
     390             : 
     391             :   // disable any output (-1), unfortuantly we do not see warnings anymore then. Have to find another way...
     392           0 :   arglist[0] = 0;
     393           0 :   minuit->ExecuteCommand("SET PRINT", arglist, 1);
     394             : 
     395             :   // however, enable warnings
     396             :   //minuit->ExecuteCommand("SET WAR", arglist, 0);
     397             : 
     398             :   // set minimization function
     399           0 :   minuit->SetFCN(Chi2Function);
     400             : 
     401             :   // set precision
     402           0 :   minuit->SetPrecision(fgMinuitPrecision);
     403             : 
     404           0 :   minuit->SetMaxIterations(fgMinuitMaxIterations);
     405             : 
     406           0 :   minuit->ExecuteCommand("SET STRATEGY",&fgMinuitStrategy,1);
     407             : 
     408           0 :   for (Int_t i=0; i<fgMaxParams; i++)
     409           0 :     (*fgEntropyAPriori)[i] = 1;
     410             : 
     411             :   // set initial conditions as a-priori distribution for MRX regularization
     412             :   /*
     413             :   for (Int_t i=0; i<fgMaxParams; i++)
     414             :     if (initialConditions && initialConditions->GetBinContent(i+1) > 0)
     415             :       (*fgEntropyAPriori)[i] = initialConditions->GetBinContent(i+1);
     416             :   */
     417             : 
     418           0 :   if (!initialConditions) {
     419             :     initialConditions = measured;
     420           0 :   } else {
     421           0 :     Printf("AliUnfolding::UnfoldWithMinuit: Using different initial conditions...");
     422             :     //new TCanvas; initialConditions->DrawCopy();
     423           0 :     if (fgNormalizeInput)
     424           0 :       initialConditions->Scale(1.0 / initialConditions->Integral());
     425             :   }
     426             : 
     427             :   // extract minimum value from initial conditions (if we set a value to 0 it will stay 0)
     428             :   Float_t minValue = 1e35;
     429           0 :   if (fgMinimumInitialValueFix < 0)
     430             :   {
     431           0 :     for (Int_t i=0; i<fgMaxParams; ++i)
     432             :     {
     433           0 :       Int_t bin = initialConditions->GetXaxis()->FindBin(result->GetXaxis()->GetBinCenter(i+1));
     434           0 :       if (initialConditions->GetBinContent(bin) > 0)
     435           0 :         minValue = TMath::Min(minValue, (Float_t) initialConditions->GetBinContent(bin));
     436             :     }
     437           0 :   }
     438             :   else
     439             :     minValue = fgMinimumInitialValueFix;
     440             :   
     441           0 :   Double_t* results = new Double_t[fgMaxParams+1];
     442           0 :   for (Int_t i=0; i<fgMaxParams; ++i)
     443             :   {
     444           0 :     Int_t bin = initialConditions->GetXaxis()->FindBin(result->GetXaxis()->GetBinCenter(i+1));
     445           0 :     results[i] = initialConditions->GetBinContent(bin);
     446             : 
     447             :     Bool_t fix = kFALSE;
     448           0 :     if (results[i] < 0)
     449             :     {
     450             :       fix = kTRUE;
     451           0 :       results[i] = -results[i];
     452           0 :     }
     453             :  
     454           0 :     if (!fix && fgMinimumInitialValue && results[i] < minValue)
     455           0 :       results[i] = minValue;
     456             :       
     457             :     // minuit sees squared values to prevent it from going negative...
     458           0 :     results[i] = TMath::Sqrt(results[i]);
     459             : 
     460           0 :     minuit->SetParameter(i, Form("param%d", i), results[i], (fix) ? 0 : fgMinuitStepSize, 0, 0);
     461             :   }
     462           0 :   if (fgNotFoundEvents > 0)
     463             :   {
     464           0 :     results[fgMaxParams] = efficiency->GetBinContent(1);
     465           0 :     minuit->SetParameter(fgMaxParams, "vtx0", results[fgMaxParams], fgMinuitStepSize / 100, 0.01, 0.80);
     466           0 :   }
     467             :   
     468           0 :   Int_t dummy = 0;
     469           0 :   Double_t chi2 = 0;
     470           0 :   Chi2Function(dummy, 0, chi2, results, 0);
     471           0 :   printf("AliUnfolding::UnfoldWithMinuit: Chi2 of initial parameters is = %f\n", chi2);
     472             : 
     473           0 :   if (check)
     474             :   {
     475           0 :     DrawGuess(results);
     476           0 :     delete[] results;
     477           0 :     return -1;
     478             :   }
     479             : 
     480             :   // first param is number of iterations, second is precision....
     481           0 :   arglist[0] = (float)fgMinuitMaxIterations;
     482             :   //  arglist[1] = 1e-5;
     483             :   //  minuit->ExecuteCommand("SET PRINT", arglist, 3);
     484             :   //  minuit->ExecuteCommand("SCAN", arglist, 0);
     485           0 :   Int_t status = minuit->ExecuteCommand("MIGRAD", arglist, 1);
     486           0 :   Printf("AliUnfolding::UnfoldWithMinuit: MINUIT status is %d", status);
     487             :   //printf("!!!!!!!!!!!!!! MIGRAD finished: Starting MINOS !!!!!!!!!!!!!!");
     488             :   //minuit->ExecuteCommand("MINOS", arglist, 0);
     489             : 
     490           0 :   if (fgNotFoundEvents > 0)
     491             :   {
     492           0 :     results[fgMaxParams] = minuit->GetParameter(fgMaxParams);
     493           0 :     Printf("Efficiency for bin 0 changed from %f to %f", efficiency->GetBinContent(1), results[fgMaxParams]);
     494           0 :     efficiency->SetBinContent(1, results[fgMaxParams]);
     495           0 :   }
     496             :   
     497           0 :   for (Int_t i=0; i<fgMaxParams; ++i)
     498             :   {
     499           0 :     results[i] = minuit->GetParameter(i);
     500           0 :     Double_t value = results[i] * results[i];
     501             :    // error is : 2 * (relError on results[i]) * (value) = 2 * (minuit->GetParError(i) / minuit->GetParameter(i)) * (minuit->GetParameter(i) * minuit->GetParameter(i))
     502             :     Double_t error = 0;
     503           0 :     if (TMath::IsNaN(minuit->GetParError(i)))
     504           0 :       Printf("WARNING: Parameter %d error is nan", i);
     505             :     else 
     506           0 :       error = 2 * minuit->GetParError(i) * results[i];
     507             :     
     508           0 :     if (efficiency)
     509             :     {   
     510             :       //printf("value before efficiency correction: %f\n",value);
     511           0 :       if (efficiency->GetBinContent(i+1) > 0)
     512             :       {
     513           0 :         value /= efficiency->GetBinContent(i+1);
     514           0 :         error /= efficiency->GetBinContent(i+1);
     515           0 :       }
     516             :       else
     517             :       {
     518             :         value = 0;
     519             :         error = 0;
     520             :       }
     521             :     }
     522             :     //printf("value after efficiency correction: %f +/- %f\n",value,error);
     523           0 :     result->SetBinContent(i+1, value);
     524           0 :     result->SetBinError(i+1, error);
     525             :   }
     526             : 
     527           0 :   Int_t tmpCallCount = fgCallCount;
     528           0 :   fgCallCount = 0; // needs to be 0 so that the Chi2Function prints its output
     529           0 :   Chi2Function(dummy, 0, chi2, results, 0);
     530             :   
     531           0 :   Printf("AliUnfolding::UnfoldWithMinuit: iterations %d. Chi2 of final parameters is = %f", tmpCallCount, chi2);
     532             :   
     533           0 :   delete[] results;
     534             : 
     535             :   return status;
     536           0 : }
     537             : 
     538             : //____________________________________________________________________
     539             : Int_t AliUnfolding::UnfoldWithBayesian(TH2* correlation, TH1* aEfficiency, TH1* measured, TH1* initialConditions, TH1* aResult)
     540             : {
     541             :   //
     542             :   // unfolds a spectrum using the Bayesian method
     543             :   //
     544             :   
     545           0 :   if (measured->Integral() <= 0)
     546             :   {
     547           0 :     Printf("AliUnfolding::UnfoldWithBayesian: ERROR: The measured spectrum is empty");
     548           0 :     return -1;
     549             :   }
     550             : 
     551             :   const Int_t kStartBin = 0;
     552             : 
     553           0 :   Int_t kMaxM = fgMaxInput;  //<= fCurrentCorrelation->GetNbinsY(); // max measured axis
     554           0 :   Int_t kMaxT = fgMaxParams; //<= fCurrentCorrelation->GetNbinsX(); // max true axis
     555             : 
     556             :   // convergence limit: kMaxT * 0.001^2 = kMaxT * 1e-6 (e.g. 250 bins --> 2.5 e-4)
     557           0 :   const Double_t kConvergenceLimit = kMaxT * 1e-6;
     558             : 
     559             :   // store information in arrays, to increase processing speed (~ factor 5)
     560           0 :   Double_t* measuredCopy = new Double_t[kMaxM];
     561           0 :   Double_t* measuredError = new Double_t[kMaxM];
     562           0 :   Double_t* prior = new Double_t[kMaxT];
     563           0 :   Double_t* result = new Double_t[kMaxT];
     564           0 :   Double_t* efficiency = new Double_t[kMaxT];
     565           0 :   Double_t* binWidths = new Double_t[kMaxT];
     566           0 :   Double_t* normResponse = new Double_t[kMaxT]; 
     567             : 
     568           0 :   Double_t** response = new Double_t*[kMaxT];
     569           0 :   Double_t** inverseResponse = new Double_t*[kMaxT];
     570           0 :   for (Int_t i=0; i<kMaxT; i++)
     571             :   {
     572           0 :     response[i] = new Double_t[kMaxM];
     573           0 :     inverseResponse[i] = new Double_t[kMaxM];
     574           0 :     normResponse[i] = 0;
     575             :   }
     576             : 
     577             :   // for normalization
     578           0 :   Float_t measuredIntegral = measured->Integral();
     579           0 :   for (Int_t m=0; m<kMaxM; m++)
     580             :   {
     581           0 :     measuredCopy[m] = measured->GetBinContent(m+1) / measuredIntegral;
     582           0 :     measuredError[m] = measured->GetBinError(m+1) / measuredIntegral;
     583             : 
     584           0 :     for (Int_t t=0; t<kMaxT; t++)
     585             :     {
     586           0 :       response[t][m] = correlation->GetBinContent(t+1, m+1);
     587           0 :       inverseResponse[t][m] = 0;
     588           0 :       normResponse[t] += correlation->GetBinContent(t+1, m+1);
     589             :     }
     590             :   }
     591             : 
     592           0 :   for (Int_t t=0; t<kMaxT; t++)
     593             :   {
     594           0 :     if (aEfficiency)
     595             :     {
     596           0 :       efficiency[t] = aEfficiency->GetBinContent(t+1);
     597           0 :     }
     598             :     else
     599           0 :       efficiency[t] = 1;
     600             :       
     601           0 :     prior[t] = measuredCopy[t];
     602           0 :     result[t] = 0;
     603           0 :     binWidths[t] = aResult->GetXaxis()->GetBinWidth(t+1);
     604             : 
     605           0 :     for (Int_t m=0; m<kMaxM; m++) { // Normalise response matrix
     606           0 :       if (normResponse[t] != 0) 
     607           0 :         response[t][m] /= normResponse[t];
     608             :       else
     609           0 :         Printf("AliUnfolding::UnfoldWithBayesian: Empty row,column in response matrix, for truth bin %d",t);
     610             :     }
     611             :   }
     612             : 
     613             :   // pick prior distribution
     614           0 :   if (initialConditions)
     615             :   {
     616           0 :     printf("Using different starting conditions...\n");
     617             :     // for normalization
     618           0 :     Float_t inputDistIntegral = initialConditions->Integral();
     619           0 :     for (Int_t i=0; i<kMaxT; i++)
     620           0 :       prior[i] = initialConditions->GetBinContent(i+1) / inputDistIntegral;
     621           0 :   }
     622             : 
     623             :   //TH1F* convergence = new TH1F("convergence", "convergence", 200, 0.5, 200.5);
     624             :   
     625             :   //new TCanvas;
     626             :   // unfold...
     627           0 :   for (Int_t i=0; i<fgBayesianIterations || fgBayesianIterations < 0; i++)
     628             :   {
     629           0 :     if (fgDebug)
     630           0 :       Printf("AliUnfolding::UnfoldWithBayesian: iteration %i", i);
     631             : 
     632             :     // calculate IR from Bayes theorem
     633             :     // IR_ji = R_ij * prior_i / sum_k(R_kj * prior_k)
     634             : 
     635             :     Double_t chi2Measured = 0;
     636           0 :     for (Int_t m=0; m<kMaxM; m++)
     637             :     {
     638             :       Float_t norm = 0;
     639           0 :       for (Int_t t = kStartBin; t<kMaxT; t++)
     640           0 :         norm += response[t][m] * prior[t] * efficiency[t];
     641             : 
     642             :       // calc. chi2: (measured - response * prior) / error
     643           0 :       if (measuredError[m] > 0)
     644             :       {
     645           0 :         Double_t value = (measuredCopy[m] - norm) / measuredError[m];
     646           0 :         chi2Measured += value * value;
     647           0 :       }
     648             : 
     649           0 :       if (norm > 0)
     650             :       {
     651           0 :         for (Int_t t = kStartBin; t<kMaxT; t++)
     652           0 :           inverseResponse[t][m] = response[t][m] * prior[t] * efficiency[t] / norm;
     653           0 :       }
     654             :       else
     655             :       {
     656           0 :         for (Int_t t = kStartBin; t<kMaxT; t++)
     657           0 :           inverseResponse[t][m] = 0;
     658             :       }
     659             :     }
     660             :     //Printf("chi2Measured of the last prior is %e", chi2Measured);
     661             : 
     662           0 :     for (Int_t t = kStartBin; t<kMaxT; t++)
     663             :     {
     664             :       Float_t value = 0;
     665           0 :       for (Int_t m=0; m<kMaxM; m++)
     666           0 :         value += inverseResponse[t][m] * measuredCopy[m];
     667             : 
     668           0 :       if (efficiency[t] > 0)
     669           0 :         result[t] = value / efficiency[t];
     670             :       else
     671           0 :         result[t] = 0;
     672             :     }
     673             :     
     674             :     /* 
     675             :     // draw intermediate result
     676             :     for (Int_t t=0; t<kMaxT; t++)
     677             :     {
     678             :       aResult->SetBinContent(t+1, result[t]);
     679             :     }
     680             :     aResult->SetMarkerStyle(24+i);
     681             :     aResult->SetMarkerColor(2);
     682             :     aResult->DrawCopy((i == 0) ? "P" : "PSAME");
     683             :     */
     684             :  
     685             :     Double_t chi2LastIter = 0;
     686             :     // regularization (simple smoothing)
     687           0 :     for (Int_t t=kStartBin; t<kMaxT; t++)
     688             :     {
     689             :       Float_t newValue = 0;
     690             :       
     691             :       // 0 bin excluded from smoothing
     692           0 :       if (t > kStartBin+2 && t<kMaxT-1)
     693             :       {
     694           0 :         Float_t average = (result[t-1] / binWidths[t-1] + result[t] / binWidths[t] + result[t+1] / binWidths[t+1]) / 3 * binWidths[t];
     695             : 
     696             :         // weight the average with the regularization parameter
     697           0 :         newValue = (1 - fgBayesianSmoothing) * result[t] + fgBayesianSmoothing * average;
     698           0 :       }
     699             :       else
     700           0 :         newValue = result[t];
     701             : 
     702             :       // calculate chi2 (change from last iteration)
     703           0 :       if (prior[t] > 1e-5)
     704             :       {
     705           0 :         Double_t diff = (prior[t] - newValue) / prior[t];
     706           0 :         chi2LastIter += diff * diff;
     707           0 :       }
     708             : 
     709           0 :       prior[t] = newValue;
     710             :     }
     711             :     //printf("Chi2 of %d iteration = %e\n", i, chi2LastIter);
     712             :     //convergence->Fill(i+1, chi2LastIter);
     713             : 
     714           0 :     if (fgBayesianIterations < 0 && chi2LastIter < kConvergenceLimit)
     715             :     {
     716           0 :       Printf("AliUnfolding::UnfoldWithBayesian: Stopped Bayesian unfolding after %d iterations at chi2(change since last iteration) of %e; chi2Measured of the last prior is %e", i, chi2LastIter, chi2Measured);
     717           0 :       break;
     718             :     }
     719           0 :   } // end of iterations
     720             : 
     721             :   //new TCanvas; convergence->DrawCopy(); gPad->SetLogy();
     722             :   //delete convergence;
     723             : 
     724             :   Float_t factor = 1;
     725           0 :   if (!fgNormalizeInput)
     726           0 :     factor = measuredIntegral;
     727           0 :   for (Int_t t=0; t<kMaxT; t++)
     728           0 :     aResult->SetBinContent(t+1, result[t] * factor);
     729             : 
     730           0 :   delete[] measuredCopy;
     731           0 :   delete[] measuredError;
     732           0 :   delete[] prior;
     733           0 :   delete[] result;
     734           0 :   delete[] efficiency;
     735           0 :   delete[] binWidths;
     736           0 :   delete[] normResponse;
     737             : 
     738           0 :   for (Int_t i=0; i<kMaxT; i++)
     739             :   {
     740           0 :     delete[] response[i];
     741           0 :     delete[] inverseResponse[i];
     742             :   }
     743           0 :   delete[] response;
     744           0 :   delete[] inverseResponse;
     745             :   
     746             :   return 0;
     747             : 
     748             :   // ********
     749             :   // Calculate the covariance matrix, all arguments are taken from NIM,A362,487-498,1995
     750             : 
     751             :   /*printf("Calculating covariance matrix. This may take some time...\n");
     752             : 
     753             :   // check if this is the right one...
     754             :   TH1* sumHist = GetMultiplicityMC(inputRange, eventType)->ProjectionY("sumHist", 1, GetMultiplicityMC(inputRange, eventType)->GetNbinsX());
     755             : 
     756             :   Int_t xBins = hInverseResponseBayes->GetNbinsX();
     757             :   Int_t yBins = hInverseResponseBayes->GetNbinsY();
     758             : 
     759             :   // calculate "unfolding matrix" Mij
     760             :   Float_t matrixM[251][251];
     761             :   for (Int_t i=1; i<=xBins; i++)
     762             :   {
     763             :     for (Int_t j=1; j<=yBins; j++)
     764             :     {
     765             :       if (fCurrentEfficiency->GetBinContent(i) > 0)
     766             :         matrixM[i-1][j-1] = hInverseResponseBayes->GetBinContent(i, j) / fCurrentEfficiency->GetBinContent(i);
     767             :       else
     768             :         matrixM[i-1][j-1] = 0;
     769             :     }
     770             :   }
     771             : 
     772             :   Float_t* vectorn = new Float_t[yBins];
     773             :   for (Int_t j=1; j<=yBins; j++)
     774             :     vectorn[j-1] = fCurrentESD->GetBinContent(j);
     775             : 
     776             :   // first part of covariance matrix, depends on input distribution n(E)
     777             :   Float_t cov1[251][251];
     778             : 
     779             :   Float_t nEvents = fCurrentESD->Integral(); // N
     780             : 
     781             :   xBins = 20;
     782             :   yBins = 20;
     783             : 
     784             :   for (Int_t k=0; k<xBins; k++)
     785             :   {
     786             :     printf("In Cov1: %d\n", k);
     787             :     for (Int_t l=0; l<yBins; l++)
     788             :     {
     789             :       cov1[k][l] = 0;
     790             : 
     791             :       // sum_j Mkj Mlj n(Ej) * (1 - n(Ej) / N)
     792             :       for (Int_t j=0; j<yBins; j++)
     793             :         cov1[k][l] += matrixM[k][j] * matrixM[l][j] * vectorn[j]
     794             :           * (1.0 - vectorn[j] / nEvents);
     795             : 
     796             :       // - sum_i,j (i != j) Mki Mlj n(Ei) n(Ej) / N
     797             :       for (Int_t i=0; i<yBins; i++)
     798             :         for (Int_t j=0; j<yBins; j++)
     799             :         {
     800             :           if (i == j)
     801             :             continue;
     802             :           cov1[k][l] -= matrixM[k][i] * matrixM[l][j] * vectorn[i]
     803             :             * vectorn[j] / nEvents;
     804             :          }
     805             :     }
     806             :   }
     807             : 
     808             :   printf("Cov1 finished\n");
     809             : 
     810             :   TH2F* cov = (TH2F*) hInverseResponseBayes->Clone("cov");
     811             :   cov->Reset();
     812             : 
     813             :   for (Int_t i=1; i<=xBins; i++)
     814             :     for (Int_t j=1; j<=yBins; j++)
     815             :       cov->SetBinContent(i, j, cov1[i-1][j-1]);
     816             : 
     817             :   new TCanvas;
     818             :   cov->Draw("COLZ");
     819             : 
     820             :   // second part of covariance matrix, depends on response matrix
     821             :   Float_t cov2[251][251];
     822             : 
     823             :   // Cov[P(Er|Cu), P(Es|Cu)] term
     824             :   Float_t covTerm[100][100][100];
     825             :   for (Int_t r=0; r<yBins; r++)
     826             :     for (Int_t u=0; u<xBins; u++)
     827             :       for (Int_t s=0; s<yBins; s++)
     828             :       {
     829             :         if (r == s)
     830             :           covTerm[r][u][s] = 1.0 / sumHist->GetBinContent(u+1) * hResponse->GetBinContent(u+1, r+1)
     831             :             * (1.0 - hResponse->GetBinContent(u+1, r+1));
     832             :         else
     833             :           covTerm[r][u][s] = - 1.0 / sumHist->GetBinContent(u+1) * hResponse->GetBinContent(u+1, r+1)
     834             :             * hResponse->GetBinContent(u+1, s+1);
     835             :       }
     836             : 
     837             :   for (Int_t k=0; k<xBins; k++)
     838             :     for (Int_t l=0; l<yBins; l++)
     839             :     {
     840             :       cov2[k][l] = 0;
     841             :       printf("In Cov2: %d %d\n", k, l);
     842             :       for (Int_t i=0; i<yBins; i++)
     843             :         for (Int_t j=0; j<yBins; j++)
     844             :         {
     845             :           //printf("In Cov2: %d %d %d %d\n", k, l, i, j);
     846             :           // calculate Cov(Mki, Mlj) = sum{ru},{su} ...
     847             :           Float_t tmpCov = 0;
     848             :           for (Int_t r=0; r<yBins; r++)
     849             :             for (Int_t u=0; u<xBins; u++)
     850             :               for (Int_t s=0; s<yBins; s++)
     851             :               {
     852             :                 if (hResponse->GetBinContent(u+1, r+1) == 0 || hResponse->GetBinContent(u+1, s+1) == 0
     853             :                   || hResponse->GetBinContent(u+1, i+1) == 0)
     854             :                   continue;
     855             : 
     856             :                 tmpCov += BayesCovarianceDerivate(matrixM, hResponse, fCurrentEfficiency, k, i, r, u)
     857             :                   * BayesCovarianceDerivate(matrixM, hResponse, fCurrentEfficiency, l, j, s, u)
     858             :                   * covTerm[r][u][s];
     859             :               }
     860             : 
     861             :           cov2[k][l] += fCurrentESD->GetBinContent(i+1) * fCurrentESD->GetBinContent(j+1) * tmpCov;
     862             :         }
     863             :     }
     864             : 
     865             :   printf("Cov2 finished\n");
     866             : 
     867             :   for (Int_t i=1; i<=xBins; i++)
     868             :     for (Int_t j=1; j<=yBins; j++)
     869             :       cov->SetBinContent(i, j, cov1[i-1][j-1] + cov2[i-1][j-1]);
     870             : 
     871             :   new TCanvas;
     872             :   cov->Draw("COLZ");*/
     873           0 : }
     874             : 
     875             : //____________________________________________________________________
     876             : Double_t AliUnfolding::RegularizationPol0(TVectorD& params)
     877             : {
     878             :   // homogenity term for minuit fitting
     879             :   // pure function of the parameters
     880             :   // prefers constant function (pol0)
     881             :   //
     882             :   // Does not take into account efficiency
     883             :   Double_t chi2 = 0;
     884             : 
     885           0 :   for (Int_t i=1+fgSkipBinsBegin; i<fgMaxParams; ++i)
     886             :   {
     887           0 :     Double_t right  = params[i] / fgUnfoldedAxis->GetBinWidth(i+1);
     888           0 :     Double_t left   = params[i-1] / fgUnfoldedAxis->GetBinWidth(i);
     889             : 
     890           0 :     if (left != 0)
     891             :     {
     892           0 :       Double_t diff = (right - left);
     893           0 :       chi2 += diff * diff / left / ((fgUnfoldedAxis->GetBinWidth(i+1) + fgUnfoldedAxis->GetBinWidth(i)) / 2);
     894           0 :     }
     895             :   }
     896             : 
     897           0 :   return chi2 / 100.0;
     898             : }
     899             : 
     900             : //____________________________________________________________________
     901             : Double_t AliUnfolding::RegularizationPol1(TVectorD& params)
     902             : {
     903             :   // homogenity term for minuit fitting
     904             :   // pure function of the parameters
     905             :   // prefers linear function (pol1)
     906             :   //
     907             :   // Does not take into account efficiency
     908             :   Double_t chi2 = 0;
     909             : 
     910           0 :   for (Int_t i=2+fgSkipBinsBegin; i<fgMaxParams; ++i)
     911             :   {
     912           0 :     if (params[i-1] == 0)
     913             :       continue;
     914             : 
     915           0 :     Double_t right  = params[i] / fgUnfoldedAxis->GetBinWidth(i+1);
     916           0 :     Double_t middle = params[i-1] / fgUnfoldedAxis->GetBinWidth(i);
     917           0 :     Double_t left   = params[i-2] / fgUnfoldedAxis->GetBinWidth(i-1);
     918             : 
     919           0 :     Double_t der1 = (right - middle) / ((fgUnfoldedAxis->GetBinWidth(i+1) + fgUnfoldedAxis->GetBinWidth(i)) / 2);
     920           0 :     Double_t der2 = (middle - left) / ((fgUnfoldedAxis->GetBinWidth(i) + fgUnfoldedAxis->GetBinWidth(i-1)) / 2);
     921             : 
     922             :     //Double_t diff = (der1 - der2) / middle;
     923             :     //chi2 += diff * diff;
     924           0 :     chi2 += (der1 - der2) * (der1 - der2) / middle * fgUnfoldedAxis->GetBinWidth(i);
     925           0 :   }
     926             : 
     927           0 :   return chi2;
     928             : }
     929             : 
     930             : //____________________________________________________________________
     931             : Double_t AliUnfolding::RegularizationLog(TVectorD& params)
     932             : {
     933             :   // homogenity term for minuit fitting
     934             :   // pure function of the parameters
     935             :   // prefers logarithmic function (log)
     936             :   //
     937             :   // Does not take into account efficiency
     938             : 
     939             :   Double_t chi2 = 0;
     940             : 
     941           0 :   for (Int_t i=2+fgSkipBinsBegin; i<fgMaxParams; ++i)
     942             :   {
     943           0 :     if (params[i-1] == 0 || params[i] == 0 || params[i-2] == 0)
     944             :      continue;
     945             : 
     946           0 :     Double_t right  = log(params[i] / fgUnfoldedAxis->GetBinWidth(i+1));
     947           0 :     Double_t middle = log(params[i-1] / fgUnfoldedAxis->GetBinWidth(i));
     948           0 :     Double_t left   = log(params[i-2] / fgUnfoldedAxis->GetBinWidth(i-1));
     949             :     
     950           0 :     Double_t der1 = (right - middle) / ((fgUnfoldedAxis->GetBinWidth(i+1) + fgUnfoldedAxis->GetBinWidth(i)) / 2);
     951           0 :     Double_t der2 = (middle - left) / ((fgUnfoldedAxis->GetBinWidth(i) + fgUnfoldedAxis->GetBinWidth(i-1)) / 2);
     952             :     
     953             :     //Double_t error = 1. / params[i] + 4. / params[i-1] + 1. / params[i-2];
     954             : 
     955             :     //if (fgCallCount == 0)
     956             :     //  Printf("%d %f %f", i, (der1 - der2) * (der1 - der2), error);
     957           0 :     chi2 += (der1 - der2) * (der1 - der2);// / error;
     958           0 :   }
     959             : 
     960           0 :   return chi2;
     961             : }
     962             : 
     963             : //____________________________________________________________________
     964             : Double_t AliUnfolding::RegularizationTotalCurvature(TVectorD& params)
     965             : {
     966             :   // homogenity term for minuit fitting
     967             :   // pure function of the parameters
     968             :   // minimizes the total curvature (from Unfolding Methods In High-Energy Physics Experiments,
     969             :   // V. Blobel (Hamburg U.) . DESY 84/118, Dec 1984. 40pp.
     970             :   //
     971             :   // Does not take into account efficiency
     972             : 
     973             :   Double_t chi2 = 0;
     974             : 
     975           0 :   for (Int_t i=2+fgSkipBinsBegin; i<fgMaxParams; ++i)
     976             :   {
     977           0 :     Double_t right  = params[i];
     978           0 :     Double_t middle = params[i-1];
     979           0 :     Double_t left   = params[i-2];
     980             : 
     981           0 :     Double_t der1 = (right - middle);
     982           0 :     Double_t der2 = (middle - left);
     983             : 
     984           0 :     Double_t diff = (der1 - der2);
     985             : 
     986           0 :     chi2 += diff * diff;
     987             :   }
     988             : 
     989           0 :   return chi2 * 1e4;
     990             : }
     991             : 
     992             : //____________________________________________________________________
     993             : Double_t AliUnfolding::RegularizationEntropy(TVectorD& params)
     994             : {
     995             :   // homogenity term for minuit fitting
     996             :   // pure function of the parameters
     997             :   // calculates entropy, from
     998             :   // The method of reduced cross-entropy (M. Schmelling 1993)
     999             :   //
    1000             :   // Does not take into account efficiency
    1001             : 
    1002             :   Double_t paramSum = 0;
    1003             :   
    1004           0 :   for (Int_t i=fgSkipBinsBegin; i<fgMaxParams; ++i)
    1005           0 :     paramSum += params[i];
    1006             : 
    1007             :   Double_t chi2 = 0;
    1008           0 :   for (Int_t i=fgSkipBinsBegin; i<fgMaxParams; ++i)
    1009             :   {
    1010           0 :     Double_t tmp = params[i] / paramSum;
    1011             :     //Double_t tmp = params[i];
    1012           0 :     if (tmp > 0 && (*fgEntropyAPriori)[i] > 0)
    1013             :     {
    1014           0 :       chi2 += tmp * TMath::Log(tmp / (*fgEntropyAPriori)[i]);
    1015           0 :     }
    1016             :     else
    1017           0 :       chi2 += 100;
    1018             :   }
    1019             : 
    1020           0 :   return -chi2;
    1021             : }
    1022             : 
    1023             : //____________________________________________________________________
    1024             : Double_t AliUnfolding::RegularizationRatio(TVectorD& params)
    1025             : {
    1026             :   // homogenity term for minuit fitting
    1027             :   // pure function of the parameters
    1028             :   //
    1029             :   // Does not take into account efficiency
    1030             : 
    1031             :   Double_t chi2 = 0;
    1032             : 
    1033           0 :   for (Int_t i=5+fgSkipBinsBegin; i<fgMaxParams; ++i)
    1034             :   {
    1035           0 :     if (params[i-1] == 0 || params[i] == 0)
    1036             :       continue;
    1037             : 
    1038           0 :     Double_t right  = params[i] / fgUnfoldedAxis->GetBinWidth(i+1);
    1039           0 :     Double_t middle = params[i-1] / fgUnfoldedAxis->GetBinWidth(i);
    1040           0 :     Double_t left   = params[i-2] / fgUnfoldedAxis->GetBinWidth(i-1);
    1041           0 :     Double_t left2   = params[i-3] / fgUnfoldedAxis->GetBinWidth(i-2);
    1042           0 :     Double_t left3   = params[i-4] / fgUnfoldedAxis->GetBinWidth(i-3);
    1043           0 :     Double_t left4   = params[i-5] / fgUnfoldedAxis->GetBinWidth(i-4);
    1044             : 
    1045             :     //Double_t diff = left / middle - middle / right;
    1046             :     //Double_t diff = 2 * left / middle - middle / right - left2 / left;
    1047           0 :     Double_t diff = 4 * left2 / left - middle / right - left / middle - left3 / left2 - left4 / left3;
    1048             :     
    1049           0 :     chi2 += diff * diff;// / middle;
    1050           0 :   }
    1051             : 
    1052           0 :   return chi2;
    1053             : }
    1054             : 
    1055             : //____________________________________________________________________
    1056             : Double_t AliUnfolding::RegularizationPowerLaw(TVectorD& params)
    1057             : {
    1058             :   // homogenity term for minuit fitting
    1059             :   // pure function of the parameters
    1060             :   // prefers power law with n = -5
    1061             :   //
    1062             :   // Does not take into account efficiency
    1063             : 
    1064             :   Double_t chi2 = 0;
    1065             : 
    1066             :   Double_t right = 0.;
    1067             :   Double_t middle = 0.;
    1068             :   Double_t left = 0.;
    1069             : 
    1070           0 :   for (Int_t i=2+fgSkipBinsBegin; i<fgMaxParams; ++i)
    1071             :   {
    1072           0 :     if (params[i] < 1e-8 || params[i-1] < 1e-8 || params[i-2] < 1e-8)
    1073             :       continue;
    1074             : 
    1075           0 :     if (fgUnfoldedAxis->GetBinWidth(i+1) < 1e-8 || fgUnfoldedAxis->GetBinWidth(i) < 1e-8 || fgUnfoldedAxis->GetBinWidth(i-1) < 1e-8)
    1076             :       continue;
    1077             :     
    1078           0 :     middle = TMath::Power(params[i-1] / fgUnfoldedAxis->GetBinWidth(i),fgPowern);
    1079             : 
    1080           0 :     if(middle>0) {
    1081           0 :       right  = TMath::Power(params[i] / fgUnfoldedAxis->GetBinWidth(i+1),fgPowern)/middle;
    1082             : 
    1083           0 :       left   = TMath::Power(params[i-2] / fgUnfoldedAxis->GetBinWidth(i-1),fgPowern)/middle;
    1084             :       
    1085             :       middle = 1.;
    1086             :       
    1087           0 :       Double_t der1 = (right - middle) / ((fgUnfoldedAxis->GetBinWidth(i+1) + fgUnfoldedAxis->GetBinWidth(i)) / 2);
    1088           0 :       Double_t der2 = (middle - left) / ((fgUnfoldedAxis->GetBinWidth(i) + fgUnfoldedAxis->GetBinWidth(i-1)) / 2);
    1089             :     
    1090           0 :       chi2 += (der1 - der2) * (der1 - der2)/ ( fgUnfoldedAxis->GetBinWidth(i+1)/2. + fgUnfoldedAxis->GetBinWidth(i) + fgUnfoldedAxis->GetBinWidth(i-1)/2.)/( fgUnfoldedAxis->GetBinWidth(i+1)/2. + fgUnfoldedAxis->GetBinWidth(i) + fgUnfoldedAxis->GetBinWidth(i-1)/2.);// / error;
    1091             :       //   printf("i: %d chi2 = %f\n",i,chi2);
    1092           0 :     }
    1093             : 
    1094             :   }
    1095             : 
    1096           0 :   return chi2;
    1097             : }
    1098             : 
    1099             : //____________________________________________________________________
    1100             : Double_t AliUnfolding::RegularizationLogLog(TVectorD& params)
    1101             : {
    1102             :   // homogenity term for minuit fitting
    1103             :   // pure function of the parameters
    1104             :   // prefers a powerlaw (linear on a log-log scale)
    1105             :   //
    1106             :   // The calculation takes into account the efficiencies
    1107             : 
    1108             :   Double_t chi2 = 0;
    1109             : 
    1110           0 :   for (Int_t i=2+fgSkipBinsBegin; i<fgMaxParams; ++i)
    1111             :   {
    1112           0 :     if (params[i-1] == 0 || params[i] == 0 || params[i-2] == 0)
    1113             :      continue;
    1114           0 :     if ((*fgEfficiency)(i-1) == 0 || (*fgEfficiency)(i) == 0 || (*fgEfficiency)(i-2) == 0)
    1115             :      continue;
    1116             : 
    1117           0 :     Double_t right  = log(params[i] / (*fgEfficiency)(i) / fgUnfoldedAxis->GetBinWidth(i+1));
    1118           0 :     Double_t middle = log(params[i-1] / (*fgEfficiency)(i-1) / fgUnfoldedAxis->GetBinWidth(i));
    1119           0 :     Double_t left   = log(params[i-2] / (*fgEfficiency)(i-2) / fgUnfoldedAxis->GetBinWidth(i-1));
    1120             :     
    1121           0 :     Double_t der1 = (right - middle) / ( log(fgUnfoldedAxis->GetBinCenter(i+1)) - log(fgUnfoldedAxis->GetBinCenter(i)) );
    1122           0 :     Double_t der2 = (middle - left) /( log(fgUnfoldedAxis->GetBinCenter(i)) - log(fgUnfoldedAxis->GetBinCenter(i-1)) );
    1123             :     
    1124           0 :     double tmp = (log(fgUnfoldedAxis->GetBinCenter(i+1)) - log(fgUnfoldedAxis->GetBinCenter(i-1)))/2.;
    1125           0 :     Double_t dder = (der1-der2) / tmp;
    1126             : 
    1127           0 :     chi2 += dder * dder;
    1128           0 :   }
    1129             : 
    1130           0 :   return chi2;
    1131             : }
    1132             : 
    1133             : 
    1134             : 
    1135             : //____________________________________________________________________
    1136             : void AliUnfolding::Chi2Function(Int_t&, Double_t*, Double_t& chi2, Double_t *params, Int_t)
    1137             : {
    1138             :   //
    1139             :   // fit function for minuit
    1140             :   // does: (m - Ad)W(m - Ad) where m = measured, A correlation matrix, d = guess, W = covariance matrix
    1141             :   //
    1142             :   
    1143             :   // TODO use static members for the variables here to speed up processing (no construction/deconstruction)
    1144             : 
    1145             :   // d = guess
    1146           0 :   TVectorD paramsVector(fgMaxParams);
    1147           0 :   for (Int_t i=0; i<fgMaxParams; ++i)
    1148           0 :     paramsVector[i] = params[i] * params[i];
    1149             : 
    1150             :   // calculate penalty factor
    1151             :   Double_t penaltyVal = 0;
    1152             : 
    1153           0 :   switch (fgRegularizationType)
    1154             :   {
    1155             :     case kNone:       break;
    1156           0 :     case kPol0:       penaltyVal = RegularizationPol0(paramsVector); break;
    1157           0 :     case kPol1:       penaltyVal = RegularizationPol1(paramsVector); break;
    1158           0 :     case kCurvature:  penaltyVal = RegularizationTotalCurvature(paramsVector); break;
    1159           0 :     case kEntropy:    penaltyVal = RegularizationEntropy(paramsVector); break;
    1160           0 :     case kLog:        penaltyVal = RegularizationLog(paramsVector); break;
    1161           0 :     case kRatio:      penaltyVal = RegularizationRatio(paramsVector); break;
    1162           0 :     case kPowerLaw:   penaltyVal = RegularizationPowerLaw(paramsVector); break;
    1163           0 :     case kLogLog:     penaltyVal = RegularizationLogLog(paramsVector); break;
    1164             :   }
    1165             : 
    1166           0 :   penaltyVal *= fgRegularizationWeight; //beta*PU
    1167             : 
    1168             :   // Ad
    1169           0 :   TVectorD measGuessVector(fgMaxInput);
    1170           0 :   measGuessVector = (*fgCorrelationMatrix) * paramsVector;
    1171             : 
    1172             :   // Ad - m
    1173           0 :   measGuessVector -= (*fgCurrentESDVector);
    1174             :   
    1175             : #if 0
    1176             :   // new error calcuation using error on the guess
    1177             :   
    1178             :   // error from guess
    1179             :   TVectorD errorGuessVector(fgMaxInput);
    1180             :   //errorGuessVector = (*fgCorrelationMatrixSquared) * paramsVector;
    1181             :   errorGuessVector = (*fgCorrelationMatrix) * paramsVector;
    1182             : 
    1183             :   Double_t chi2FromFit = 0;
    1184             :   for (Int_t i=0; i<fgMaxInput; ++i)
    1185             :   {
    1186             :     Float_t error = 1;
    1187             :     if (errorGuessVector(i) > 0)
    1188             :       error = errorGuessVector(i);
    1189             :     chi2FromFit += measGuessVector(i) * measGuessVector(i) / error;
    1190             :   }
    1191             : 
    1192             : #else
    1193             :   // old error calcuation using the error on the measured
    1194           0 :   TVectorD copy(measGuessVector);
    1195             : 
    1196             :   // (Ad - m) W
    1197             :   // this step can be optimized because currently only the diagonal elements of fgCorrelationCovarianceMatrix are used
    1198             :   // normal way is like this:
    1199             :   // measGuessVector *= (*fgCorrelationCovarianceMatrix);
    1200             :   // optimized way like this:
    1201           0 :   for (Int_t i=0; i<fgMaxInput; ++i)
    1202           0 :     measGuessVector[i] *= (*fgCorrelationCovarianceMatrix)(i, i);
    1203             : 
    1204             : 
    1205           0 :   if (fgSkipBin0InChi2)
    1206           0 :     measGuessVector[0] = 0;
    1207             : 
    1208             :   // (Ad - m) W (Ad - m)
    1209             :   // the factor 1e6 prevents that a very small number (measGuessVector[i]) is multiplied with a very
    1210             :   // big number ((*fgCorrelationCovarianceMatrix)(i, i)) (see UnfoldWithMinuit)
    1211           0 :   Double_t chi2FromFit = measGuessVector * copy * 1e6;
    1212             : #endif
    1213             : 
    1214             :   Double_t notFoundEventsConstraint = 0;
    1215             :   Double_t currentNotFoundEvents = 0;
    1216             :   Double_t errorNotFoundEvents = 0;
    1217             :   
    1218           0 :   if (fgNotFoundEvents > 0)
    1219             :   {
    1220           0 :     for (Int_t i=0; i<fgMaxParams; ++i)
    1221             :     {
    1222           0 :       Double_t eff = (1.0 / (*fgEfficiency)(i) - 1);
    1223           0 :       if (i == 0)
    1224           0 :         eff = (1.0 / params[fgMaxParams] - 1);
    1225           0 :       currentNotFoundEvents += eff * paramsVector(i);
    1226           0 :       errorNotFoundEvents += eff * eff * paramsVector(i); // error due to guess (paramsVector)
    1227           0 :       if (i <= 3)
    1228           0 :         errorNotFoundEvents += (eff * 0.03) * (eff * 0.03) * paramsVector(i) * paramsVector(i); // error on eff
    1229             :       //      if ((fgCallCount % 10000) == 0)
    1230             :         //Printf("%d %f %f %f", i, (*fgEfficiency)(i), paramsVector(i), currentNotFoundEvents);
    1231             :     }
    1232           0 :     errorNotFoundEvents += fgNotFoundEvents;
    1233             :     // TODO add error on background, background estimate
    1234             :     
    1235           0 :     notFoundEventsConstraint = (currentNotFoundEvents - fgNotFoundEvents) * (currentNotFoundEvents - fgNotFoundEvents) / errorNotFoundEvents;
    1236           0 :   }
    1237             :   
    1238             :   Float_t avg = 0;
    1239             :   Float_t sum = 0;
    1240             :   Float_t currentMult = 0;
    1241             :   // try to match dn/deta
    1242           0 :   for (Int_t i=0; i<fgMaxParams; ++i)
    1243             :   {
    1244           0 :     avg += paramsVector(i) * currentMult;
    1245           0 :     sum += paramsVector(i);
    1246           0 :     currentMult += fgUnfoldedAxis->GetBinWidth(i);
    1247             :   }
    1248           0 :   avg /= sum;
    1249             :   Float_t chi2Avg = 0; //(avg - 3.73) * (avg - 3.73) * 100;
    1250             : 
    1251           0 :   chi2 = chi2FromFit + penaltyVal + notFoundEventsConstraint + chi2Avg;
    1252             : 
    1253           0 :   if ((fgCallCount++ % 1000) == 0)
    1254             :   {
    1255             : 
    1256           0 :     Printf("AliUnfolding::Chi2Function: Iteration %d (ev %d %d +- %f) (%f) (%f): %f %f %f %f --> %f", fgCallCount-1, (Int_t) fgNotFoundEvents, (Int_t) currentNotFoundEvents, TMath::Sqrt(errorNotFoundEvents), params[fgMaxParams-1], avg, chi2FromFit, penaltyVal, notFoundEventsConstraint, chi2Avg, chi2);
    1257             : 
    1258             :     //for (Int_t i=0; i<fgMaxInput; ++i)
    1259             :     //  Printf("%d: %f", i, measGuessVector(i) * copy(i) * 1e6);
    1260             :   }
    1261             : 
    1262           0 :   fChi2FromFit = chi2FromFit;
    1263           0 :   fPenaltyVal = penaltyVal;
    1264           0 : }
    1265             : 
    1266             : //____________________________________________________________________
    1267             : void AliUnfolding::MakePads() {
    1268           0 :     TPad *presult = new TPad("presult","result",0,0.4,1,1);
    1269           0 :     presult->SetNumber(1);
    1270           0 :     presult->Draw();
    1271           0 :     presult->SetLogy();
    1272           0 :     TPad *pres = new TPad("pres","residuals",0,0.2,1,0.4);
    1273           0 :     pres->SetNumber(2);
    1274           0 :     pres->Draw();
    1275           0 :     TPad *ppen = new TPad("ppen","penalty",0,0.0,1,0.2);
    1276           0 :     ppen->SetNumber(3);
    1277           0 :     ppen->Draw();
    1278             :  
    1279           0 : }
    1280             : //____________________________________________________________________
    1281             : void AliUnfolding::DrawResults(TH2* correlation, TH1* efficiency, TH1* measured, TH1* initialConditions, TCanvas *canv, Int_t reuseHists,TH1 *unfolded)
    1282             : {
    1283             :   // Draw histograms of
    1284             :   //   - Result folded with response
    1285             :   //   - Penalty factors
    1286             :   //   - Chisquare contributions
    1287             :   // (Useful for debugging/sanity checks and the interactive unfolder)
    1288             :   //
    1289             :   // If a canvas pointer is given (canv != 0), it will be used for all
    1290             :   // plots; 3 pads are made if needed.
    1291             : 
    1292             : 
    1293             :   Int_t blankCanvas = 0;
    1294             :   TVirtualPad *presult = 0;
    1295             :   TVirtualPad *pres = 0; 
    1296             :   TVirtualPad *ppen = 0;
    1297             :   
    1298           0 :   if (canv) {
    1299           0 :     canv->cd();
    1300           0 :     presult = canv->GetPad(1);
    1301           0 :     pres = canv->GetPad(2);
    1302           0 :     ppen = canv->GetPad(3); 
    1303           0 :     if (presult == 0 || pres == 0 || ppen == 0) {
    1304           0 :       canv->Clear();
    1305           0 :       MakePads();
    1306             :       blankCanvas = 1;
    1307           0 :       presult = canv->GetPad(1);
    1308           0 :       pres = canv->GetPad(2);
    1309           0 :       ppen = canv->GetPad(3); 
    1310           0 :     } 
    1311             :   }
    1312             :   else {
    1313           0 :     presult = new TCanvas;
    1314           0 :     pres = new TCanvas;
    1315           0 :     ppen = new TCanvas;
    1316             :   }
    1317             : 
    1318             : 
    1319           0 :   if (fgMaxInput == -1)
    1320             :   {
    1321           0 :     Printf("AliUnfolding::Unfold: WARNING. Number of measured bins not set with SetNbins. Using number of bins in measured distribution");
    1322           0 :     fgMaxInput = measured->GetNbinsX();
    1323           0 :   }
    1324           0 :   if (fgMaxParams == -1)
    1325             :   {
    1326           0 :     Printf("AliUnfolding::Unfold: WARNING. Number of unfolded bins not set with SetNbins. Using number of bins in measured distribution");
    1327           0 :     fgMaxParams = initialConditions->GetNbinsX();
    1328           0 :   }
    1329             : 
    1330           0 :   if (fgOverflowBinLimit > 0)
    1331           0 :     CreateOverflowBin(correlation, measured);
    1332             : 
    1333             :   // Uses Minuit methods
    1334             : 
    1335           0 :   SetStaticVariables(correlation, measured, efficiency);
    1336             : 
    1337           0 :   Double_t* params = new Double_t[fgMaxParams+1];
    1338           0 :   for (Int_t i=0; i<fgMaxParams; ++i)
    1339             :   {
    1340           0 :     params[i] = initialConditions->GetBinContent(i+1) * efficiency->GetBinContent(i+1);
    1341             : 
    1342           0 :     if (params[i] < 0)
    1343           0 :       params[i] = -params[i];
    1344           0 :     params[i]=TMath::Sqrt(params[i]);
    1345             :   } 
    1346             : 
    1347           0 :   Double_t chi2;
    1348           0 :   Int_t dummy;
    1349             : 
    1350             :   //fgPrintChi2Details = kTRUE;
    1351           0 :   fgCallCount = 0; // To make sure that Chi2Function prints the components
    1352           0 :   Chi2Function(dummy, 0, chi2, params, 0);
    1353             : 
    1354           0 :   presult->cd();
    1355           0 :   TH1 *meas2 = (TH1*)measured->Clone("meas2");
    1356           0 :   meas2->SetTitle("meas2");
    1357           0 :   meas2->SetName("meas2");
    1358           0 :   meas2->SetLineColor(1);
    1359           0 :   meas2->SetLineWidth(2);
    1360           0 :   meas2->SetMarkerColor(meas2->GetLineColor());
    1361           0 :   meas2->SetMarkerStyle(20);
    1362           0 :   Float_t scale = unfolded->GetXaxis()->GetBinWidth(1)/meas2->GetXaxis()->GetBinWidth(1);
    1363           0 :   meas2->Scale(scale);
    1364           0 :   if (blankCanvas)
    1365           0 :     meas2->DrawCopy();
    1366             :   else
    1367           0 :     meas2->DrawCopy("same");
    1368             :   //meas2->GetXaxis()->SetLimits(0,fgMaxInput);
    1369           0 :   meas2->SetBit(kCannotPick);
    1370           0 :   DrawGuess(params, presult, pres, ppen, reuseHists,unfolded);
    1371           0 :   delete [] params;
    1372           0 : }
    1373             : //____________________________________________________________________
    1374             : void AliUnfolding::RedrawInteractive() {
    1375             :   // 
    1376             :   // Helper function for interactive unfolding
    1377             :   //
    1378           0 :   DrawResults(fghCorrelation,fghEfficiency,fghMeasured,fghUnfolded,fgCanvas,1,fghUnfolded);
    1379           0 : }
    1380             : //____________________________________________________________________
    1381             : void AliUnfolding::InteractiveUnfold(TH2* correlation, TH1* efficiency, TH1* measured, TH1* initialConditions) 
    1382             : {
    1383             :   //
    1384             :   // Function to do interactive unfolding
    1385             :   // A canvas is drawn with the unfolding result
    1386             :   // Change the histogram with your mouse and all histograms 
    1387             :   // will be updated automatically
    1388             : 
    1389           0 :   fgCanvas = new TCanvas("UnfoldingCanvas","Interactive unfolding",500,800);
    1390           0 :   fgCanvas->cd();
    1391             : 
    1392           0 :   MakePads();
    1393             : 
    1394           0 :   if (fghUnfolded) {
    1395           0 :     delete fghUnfolded; fghUnfolded = 0;
    1396           0 :   }
    1397             :   
    1398           0 :   gROOT->SetEditHistograms(kTRUE);
    1399             : 
    1400           0 :   fghUnfolded = new TH1F("AliUnfoldingfghUnfolded","Unfolded result (Interactive unfolder",efficiency->GetNbinsX(),efficiency->GetXaxis()->GetXmin(),efficiency->GetXaxis()->GetXmax());
    1401             : 
    1402           0 :   fghCorrelation = correlation;
    1403           0 :   fghEfficiency = efficiency;
    1404           0 :   fghMeasured = measured;
    1405             : 
    1406           0 :   if(fgMinuitMaxIterations>0)
    1407           0 :     UnfoldWithMinuit(correlation,efficiency,measured,initialConditions,fghUnfolded,kFALSE);
    1408             :   else
    1409           0 :     fghUnfolded = initialConditions;
    1410             : 
    1411           0 :   fghUnfolded->SetLineColor(2);
    1412           0 :   fghUnfolded->SetMarkerColor(2);
    1413           0 :   fghUnfolded->SetLineWidth(2);
    1414             : 
    1415             : 
    1416           0 :   fgCanvas->cd(1);
    1417           0 :   fghUnfolded->Draw();
    1418           0 :   DrawResults(correlation,efficiency,measured,fghUnfolded,fgCanvas,kFALSE,fghUnfolded);
    1419             : 
    1420           0 :   TExec *execRedraw = new TExec("redraw","AliUnfolding::RedrawInteractive()");
    1421           0 :   fghUnfolded->GetListOfFunctions()->Add(execRedraw);
    1422           0 : }
    1423             : //____________________________________________________________________
    1424             : void AliUnfolding::DrawGuess(Double_t *params, TVirtualPad *pfolded, TVirtualPad *pres, TVirtualPad *ppen, Int_t reuseHists,TH1* unfolded)
    1425             : {
    1426             :   //
    1427             :   // draws residuals of solution suggested by params and effect of regularization
    1428             :   //
    1429             : 
    1430           0 :   if (pfolded == 0)
    1431           0 :     pfolded = new TCanvas;
    1432           0 :   if (ppen == 0)
    1433           0 :     ppen = new TCanvas;
    1434           0 :   if (pres == 0)
    1435           0 :     pres = new TCanvas;
    1436             :   
    1437             :   // d
    1438           0 :   TVectorD paramsVector(fgMaxParams);
    1439           0 :   for (Int_t i=0; i<fgMaxParams; ++i)
    1440           0 :     paramsVector[i] = params[i] * params[i];
    1441             : 
    1442             :   // Ad
    1443           0 :   TVectorD measGuessVector(fgMaxInput);
    1444           0 :   measGuessVector = (*fgCorrelationMatrix) * paramsVector;
    1445             : 
    1446             :   TH1* folded = 0;
    1447           0 :   if (reuseHists) 
    1448           0 :     folded = dynamic_cast<TH1*>(gROOT->FindObject("__hfolded"));
    1449           0 :   if (!reuseHists || folded == 0) {
    1450           0 :     if (fgMeasuredAxis->GetXbins()->GetArray()) // variable bins
    1451           0 :       folded = new TH1F("__hfolded","Folded histo from AliUnfolding",fgMeasuredAxis->GetNbins(),fgMeasuredAxis->GetXbins()->GetArray());
    1452             :     else
    1453           0 :       folded = new TH1F("__hfolded","Folded histo from AliUnfolding",fgMeasuredAxis->GetNbins(),fgMeasuredAxis->GetXmin(),fgMeasuredAxis->GetXmax());
    1454             :   }
    1455             : 
    1456           0 :   folded->SetBit(kCannotPick);
    1457           0 :   folded->SetLineColor(4);
    1458           0 :   folded->SetLineWidth(2);
    1459             : 
    1460           0 :   for (Int_t ibin =0; ibin < fgMaxInput; ibin++) 
    1461           0 :     folded->SetBinContent(ibin+1, measGuessVector[ibin]);
    1462             : 
    1463           0 :   Float_t scale = unfolded->GetXaxis()->GetBinWidth(1)/folded->GetXaxis()->GetBinWidth(1);
    1464           0 :   folded->Scale(scale);
    1465             : 
    1466           0 :   pfolded->cd();
    1467             : 
    1468           0 :   folded->Draw("same");
    1469             : 
    1470             :   // Ad - m
    1471           0 :   measGuessVector -= (*fgCurrentESDVector);
    1472             : 
    1473           0 :   TVectorD copy(measGuessVector);
    1474             : 
    1475             :   // (Ad - m) W
    1476             :   // this step can be optimized because currently only the diagonal elements of fgCorrelationCovarianceMatrix are used
    1477             :   // normal way is like this:
    1478             :   // measGuessVector *= (*fgCorrelationCovarianceMatrix);
    1479             :   // optimized way like this:
    1480           0 :   for (Int_t i=0; i<fgMaxInput; ++i)
    1481           0 :     measGuessVector[i] *= (*fgCorrelationCovarianceMatrix)(i, i);
    1482             : 
    1483             :   // (Ad - m) W (Ad - m)
    1484             :   // the factor 1e6 prevents that a very small number (measGuessVector[i]) is multiplied with a very
    1485             :   // big number ((*fgCorrelationCovarianceMatrix)(i, i)) (see ApplyMinuitFit)
    1486             :   //Double_t chi2FromFit = measGuessVector * copy * 1e6;
    1487             : 
    1488             :   // draw residuals
    1489             :   // Double_t pTarray[fgMaxParams+1];
    1490             :   // for(int i=0; i<fgMaxParams; i++) {
    1491             :   //   pTarray[i] = fgUnfoldedAxis->GetBinCenter(i)-0.5*fgUnfoldedAxis->GetBinWidth(i);
    1492             :   // }
    1493             :   //  pTarray[fgMaxParams] = fgUnfoldedAxis->GetBinCenter(fgMaxParams-1)+0.5*fgUnfoldedAxis->GetBinWidth(fgMaxParams-1);
    1494             :   //  TH1* residuals = new TH1F("residuals", "residuals", fgMaxParams,pTarray);
    1495             :   //  TH1* residuals = new TH1F("residuals", "residuals", fgMaxInput, -0.5, fgMaxInput - 0.5);
    1496             :   // for (Int_t i=0; i<fgMaxInput; ++i)
    1497             :   //   residuals->SetBinContent(i+1, measGuessVector(i) * copy(i) * 1e6);7
    1498           0 :   TH1* residuals = GetResidualsPlot(params);
    1499           0 :   residuals->GetXaxis()->SetTitleSize(0.06);
    1500           0 :   residuals->GetXaxis()->SetTitleOffset(0.7);
    1501           0 :   residuals->GetXaxis()->SetLabelSize(0.07);
    1502           0 :   residuals->GetYaxis()->SetTitleSize(0.08);
    1503           0 :   residuals->GetYaxis()->SetTitleOffset(0.5);
    1504           0 :   residuals->GetYaxis()->SetLabelSize(0.06);
    1505           0 :   pres->cd(); residuals->DrawCopy(); gPad->SetLogy();
    1506             :     
    1507             : 
    1508             :   // draw penalty
    1509           0 :   TH1* penalty = GetPenaltyPlot(params);
    1510           0 :   penalty->GetXaxis()->SetTitleSize(0.06);
    1511           0 :   penalty->GetXaxis()->SetTitleOffset(0.7);
    1512           0 :   penalty->GetXaxis()->SetLabelSize(0.07);
    1513           0 :   penalty->GetYaxis()->SetTitleSize(0.08);
    1514           0 :   penalty->GetYaxis()->SetTitleOffset(0.5);
    1515           0 :   penalty->GetYaxis()->SetLabelSize(0.06);
    1516           0 :   ppen->cd(); penalty->DrawCopy(); gPad->SetLogy();
    1517           0 : }
    1518             : 
    1519             : //____________________________________________________________________
    1520             : TH1* AliUnfolding::GetResidualsPlot(TH1* corrected)
    1521             : {
    1522             :   //
    1523             :   // MvL: THIS MUST BE INCORRECT. 
    1524             :   // Need heff to calculate params from TH1 'corrected'
    1525             :   //
    1526             : 
    1527             :   //
    1528             :   // fill residuals histogram of solution suggested by params and effect of regularization
    1529             :   //
    1530             : 
    1531           0 :   Double_t* params = new Double_t[fgMaxParams];
    1532           0 :   for (Int_t i=0; i<fgMaxParams; i++)
    1533           0 :     params[i] = 0;
    1534             : 
    1535           0 :   for (Int_t i=0; i<TMath::Min(fgMaxParams, corrected->GetNbinsX()); i++)
    1536           0 :     params[i] = TMath::Sqrt(TMath::Abs(corrected->GetBinContent(i+1)*(*fgEfficiency)(i)));
    1537             : 
    1538           0 :   TH1 * plot = GetResidualsPlot(params);
    1539           0 :   delete [] params;
    1540           0 :   return plot;
    1541             : }
    1542             : 
    1543             : //____________________________________________________________________
    1544             : TH1* AliUnfolding::GetResidualsPlot(Double_t* params)
    1545             : {
    1546             :   //
    1547             :   // fill residuals histogram of solution suggested by params and effect of regularization
    1548             :   //
    1549             : 
    1550             :   // d
    1551           0 :   TVectorD paramsVector(fgMaxParams);
    1552           0 :   for (Int_t i=0; i<fgMaxParams; ++i)
    1553           0 :     paramsVector[i] = params[i] * params[i];
    1554             : 
    1555             :   // Ad
    1556           0 :   TVectorD measGuessVector(fgMaxInput);
    1557           0 :   measGuessVector = (*fgCorrelationMatrix) * paramsVector;
    1558             : 
    1559             :   // Ad - m
    1560           0 :   measGuessVector -= (*fgCurrentESDVector);
    1561             : 
    1562           0 :   TVectorD copy(measGuessVector);
    1563             : 
    1564             :   // (Ad - m) W
    1565             :   // this step can be optimized because currently only the diagonal elements of fgCorrelationCovarianceMatrix are used
    1566             :   // normal way is like this:
    1567             :   // measGuessVector *= (*fgCorrelationCovarianceMatrix);
    1568             :   // optimized way like this:
    1569           0 :   for (Int_t i=0; i<fgMaxInput; ++i)
    1570           0 :     measGuessVector[i] *= (*fgCorrelationCovarianceMatrix)(i, i);
    1571             : 
    1572             :   // (Ad - m) W (Ad - m)
    1573             :   // the factor 1e6 prevents that a very small number (measGuessVector[i]) is multiplied with a very
    1574             :   // big number ((*fgCorrelationCovarianceMatrix)(i, i)) (see ApplyMinuitFit)
    1575             :   //Double_t chi2FromFit = measGuessVector * copy * 1e6;
    1576             : 
    1577             :   // draw residuals
    1578             :   TH1* residuals = 0;
    1579           0 :   if (fgMeasuredAxis->GetXbins()->GetArray()) // variable bins
    1580           0 :     residuals = new TH1F("residuals", "residuals;unfolded pos;residual",fgMeasuredAxis->GetNbins(),fgMeasuredAxis->GetXbins()->GetArray());
    1581             :   else
    1582           0 :     residuals = new TH1F("residuals", "residuals;unfolded pos;residual",fgMeasuredAxis->GetNbins(),fgMeasuredAxis->GetXmin(), fgMeasuredAxis->GetXmax());
    1583             :   //  TH1* residuals = new TH1F("residuals", "residuals", fgMaxInput, -0.5, fgMaxInput - 0.5);
    1584             : 
    1585             :   Double_t sumResiduals = 0.; 
    1586           0 :   for (Int_t i=0; i<fgMaxInput; ++i) {
    1587           0 :     residuals->SetBinContent(i+1, measGuessVector(i) * copy(i) * 1e6);
    1588           0 :     sumResiduals += measGuessVector(i) * copy(i) * 1e6;
    1589             :   }
    1590           0 :   fAvgResidual = sumResiduals/(double)fgMaxInput;
    1591             :  
    1592             :   return residuals;
    1593           0 : }
    1594             : 
    1595             : //____________________________________________________________________
    1596             : TH1* AliUnfolding::GetPenaltyPlot(TH1* corrected)
    1597             : {
    1598             :   // draws the penalty factors as function of multiplicity of the current selected regularization
    1599             : 
    1600           0 :   Double_t* params = new Double_t[fgMaxParams];
    1601           0 :   for (Int_t i=0; i<fgMaxParams; i++)
    1602           0 :     params[i] = 0;
    1603             : 
    1604           0 :   for (Int_t i=0; i<TMath::Min(fgMaxParams, corrected->GetNbinsX()); i++)
    1605           0 :     params[i] = (*fgEfficiency)(i)*corrected->GetBinContent(i+1);
    1606             :   
    1607           0 :   TH1* penalty = GetPenaltyPlot(params);
    1608             :   
    1609           0 :   delete[] params;
    1610             :   
    1611           0 :   return penalty;
    1612             : }
    1613             : 
    1614             : //____________________________________________________________________
    1615             : TH1* AliUnfolding::GetPenaltyPlot(Double_t* params)
    1616             : {
    1617             :   // draws the penalty factors as function of multiplicity of the current selected regularization
    1618             :   
    1619             :   //TH1* penalty = new TH1F("penalty", ";unfolded multiplicity;penalty factor", fgMaxParams, -0.5, fgMaxParams - 0.5);
    1620             :   //  TH1* penalty = new TH1F("penalty", ";unfolded pos;penalty factor", fgMaxParams, fgUnfoldedAxis->GetBinCenter(0)-0.5*fgUnfoldedAxis->GetBinWidth(0),fgUnfoldedAxis->GetBinCenter(fgMaxParams)+0.5*fgUnfoldedAxis->GetBinWidth(fgMaxParams) );
    1621             : 
    1622             :   TH1* penalty = 0;
    1623           0 :   if (fgUnfoldedAxis->GetXbins()->GetArray())
    1624           0 :     penalty = new TH1F("penalty", ";unfolded pos;penalty factor", fgUnfoldedAxis->GetNbins(),fgUnfoldedAxis->GetXbins()->GetArray());
    1625             :   else
    1626           0 :     penalty = new TH1F("penalty", ";unfolded pos;penalty factor", fgUnfoldedAxis->GetNbins(),fgUnfoldedAxis->GetXmin(),fgUnfoldedAxis->GetXmax());
    1627             : 
    1628           0 :   for (Int_t i=1+fgSkipBinsBegin; i<fgMaxParams; ++i)
    1629             :   {
    1630             :     Double_t diff = 0;
    1631           0 :     if (fgRegularizationType == kPol0)
    1632             :     {
    1633           0 :       Double_t right  = params[i] / fgUnfoldedAxis->GetBinWidth(i+1);
    1634           0 :       Double_t left   = params[i-1] / fgUnfoldedAxis->GetBinWidth(i);
    1635             : 
    1636           0 :       if (left != 0)
    1637             :       {
    1638           0 :         Double_t diffTmp = (right - left);
    1639           0 :         diff = diffTmp * diffTmp / left / ((fgUnfoldedAxis->GetBinWidth(i+1) + fgUnfoldedAxis->GetBinWidth(i)) / 2) / 100;
    1640           0 :       }
    1641           0 :     } 
    1642           0 :     if (fgRegularizationType == kPol1 && i > 1+fgSkipBinsBegin) 
    1643             :     {
    1644           0 :       if (params[i-1] == 0)
    1645           0 :         continue;
    1646             : 
    1647           0 :       Double_t right  = params[i] / fgUnfoldedAxis->GetBinWidth(i+1);
    1648           0 :       Double_t middle = params[i-1] / fgUnfoldedAxis->GetBinWidth(i);
    1649           0 :       Double_t left   = params[i-2] / fgUnfoldedAxis->GetBinWidth(i-1);
    1650             : 
    1651           0 :       Double_t der1 = (right - middle) / ((fgUnfoldedAxis->GetBinWidth(i+1) + fgUnfoldedAxis->GetBinWidth(i)) / 2);
    1652           0 :       Double_t der2 = (middle - left) / ((fgUnfoldedAxis->GetBinWidth(i) + fgUnfoldedAxis->GetBinWidth(i-1)) / 2);
    1653             : 
    1654           0 :       diff = (der1 - der2) * (der1 - der2) / middle;
    1655           0 :     }
    1656             : 
    1657           0 :     if (fgRegularizationType == kLog && i > 1+fgSkipBinsBegin) 
    1658             :     {
    1659           0 :       if (params[i-1] == 0)
    1660           0 :         continue;
    1661             :   
    1662           0 :       Double_t right  = log(params[i]);
    1663           0 :       Double_t middle = log(params[i-1]);
    1664           0 :       Double_t left   = log(params[i-2]);
    1665             :       
    1666           0 :       Double_t der1 = (right - middle);
    1667           0 :       Double_t der2 = (middle - left);
    1668             :   
    1669             :       //Double_t error = 1. / params[i] + 4. / params[i-1] + 1. / params[i-2];
    1670             :       //Printf("%d %f %f", i, (der1 - der2) * (der1 - der2), error);
    1671             :        
    1672           0 :       diff = (der1 - der2) * (der1 - der2);// / error;
    1673           0 :     }
    1674           0 :     if (fgRegularizationType == kCurvature && i > 1+fgSkipBinsBegin)
    1675             :     {
    1676           0 :       Double_t right  = params[i];    // params are sqrt
    1677           0 :       Double_t middle = params[i-1];
    1678           0 :       Double_t left   = params[i-2];
    1679             :       
    1680           0 :       Double_t der1 = (right - middle)/0.5/(fgUnfoldedAxis->GetBinWidth(i-1) + fgUnfoldedAxis->GetBinWidth(i));
    1681           0 :       Double_t der2 = (middle - left)/0.5/(fgUnfoldedAxis->GetBinWidth(i) + fgUnfoldedAxis->GetBinWidth(i+1));
    1682             :       
    1683           0 :       diff = (der1 - der2)/(fgUnfoldedAxis->GetBinWidth(i-1) + fgUnfoldedAxis->GetBinWidth(i) + fgUnfoldedAxis->GetBinWidth(i-1))*3.0;
    1684           0 :       diff = 1e4*diff*diff;
    1685           0 :     }
    1686           0 :     if (fgRegularizationType == kPowerLaw && i > 1+fgSkipBinsBegin) 
    1687             :     {
    1688             : 
    1689           0 :       if (params[i] < 1e-8 || params[i-1] < 1e-8 || params[i-2] < 1e-8)
    1690           0 :         continue;
    1691             :       
    1692           0 :       if (fgUnfoldedAxis->GetBinWidth(i+1) < 1e-8 || fgUnfoldedAxis->GetBinWidth(i) < 1e-8 || fgUnfoldedAxis->GetBinWidth(i) < 1e-8)
    1693           0 :         continue;
    1694             :       
    1695           0 :       double middle = TMath::Power(params[i-1] / fgUnfoldedAxis->GetBinWidth(i),fgPowern);
    1696             : 
    1697           0 :       if(middle>0) {
    1698           0 :         double right  = TMath::Power(params[i] / fgUnfoldedAxis->GetBinWidth(i+1),fgPowern)/middle;
    1699             :         
    1700           0 :         double left   = TMath::Power(params[i-2] / fgUnfoldedAxis->GetBinWidth(i-1),fgPowern)/middle;
    1701             :         
    1702             :         middle = 1.;
    1703             :         
    1704           0 :         Double_t der1 = (right - middle) / ((fgUnfoldedAxis->GetBinWidth(i+1) + fgUnfoldedAxis->GetBinWidth(i)) / 2);
    1705           0 :         Double_t der2 = (middle - left) / ((fgUnfoldedAxis->GetBinWidth(i) + fgUnfoldedAxis->GetBinWidth(i-1)) / 2);
    1706             :         
    1707           0 :         diff = (der1 - der2) * (der1 - der2);// / error;
    1708           0 :       }
    1709           0 :     }
    1710             : 
    1711           0 :     if (fgRegularizationType == kLogLog && i > 1+fgSkipBinsBegin) 
    1712             :     {
    1713             : 
    1714           0 :       if (params[i] < 1e-8 || params[i-1] < 1e-8 || params[i-2] < 1e-8)
    1715           0 :         continue;
    1716             : 
    1717           0 :       Double_t right  = log(params[i] / (*fgEfficiency)(i) / fgUnfoldedAxis->GetBinWidth(i+1));
    1718           0 :       Double_t middle = log(params[i-1] / (*fgEfficiency)(i-1) / fgUnfoldedAxis->GetBinWidth(i));
    1719           0 :       Double_t left   = log(params[i-2] / (*fgEfficiency)(i-2) / fgUnfoldedAxis->GetBinWidth(i-1));
    1720             :       
    1721           0 :       Double_t der1 = (right - middle) / ( log(fgUnfoldedAxis->GetBinCenter(i+1)) - log(fgUnfoldedAxis->GetBinCenter(i)) );
    1722           0 :       Double_t der2 = (middle - left) /( log(fgUnfoldedAxis->GetBinCenter(i)) - log(fgUnfoldedAxis->GetBinCenter(i-1)) );
    1723             :       
    1724           0 :       double tmp = (log(fgUnfoldedAxis->GetBinCenter(i+1)) - log(fgUnfoldedAxis->GetBinCenter(i-1)))/2.;
    1725           0 :       Double_t dder = (der1-der2) / tmp;
    1726             :       
    1727           0 :       diff = dder * dder;
    1728           0 :     }
    1729             :     
    1730           0 :     penalty->SetBinContent(i, diff*fgRegularizationWeight);
    1731             :     
    1732             :     //Printf("%d %f %f %f %f", i-1, left, middle, right, diff);
    1733           0 :   }
    1734             :   
    1735           0 :   return penalty;
    1736           0 : }
    1737             : 
    1738             : //____________________________________________________________________
    1739             : void AliUnfolding::TF1Function(Int_t& unused1, Double_t* unused2, Double_t& chi2, Double_t *params, Int_t unused3)
    1740             : {
    1741             :   //
    1742             :   // fit function for minuit
    1743             :   // uses the TF1 stored in fgFitFunction
    1744             :   //
    1745             : 
    1746           0 :   for (Int_t i=0; i<fgFitFunction->GetNpar(); i++)
    1747           0 :     fgFitFunction->SetParameter(i, params[i]);
    1748             : 
    1749           0 :   Double_t* params2 = new Double_t[fgMaxParams];
    1750             : 
    1751           0 :   for (Int_t i=0; i<fgMaxParams; ++i)
    1752           0 :     params2[i] = fgFitFunction->Eval(i);
    1753             : 
    1754           0 :   Chi2Function(unused1, unused2, chi2, params2, unused3);
    1755             :   
    1756           0 :   delete[] params2;
    1757             : 
    1758           0 :   if (fgDebug)
    1759           0 :     Printf("%f", chi2);
    1760           0 : }
    1761             : 
    1762             : //____________________________________________________________________
    1763             : Int_t AliUnfolding::UnfoldWithFunction(TH2* correlation, TH1* efficiency, TH1* measured, TH1* /* initialConditions */, TH1* aResult)
    1764             : {
    1765             :   //
    1766             :   // correct spectrum using minuit chi2 method applying a functional fit
    1767             :   //
    1768             :   
    1769           0 :   if (!fgFitFunction)
    1770             :   {
    1771           0 :     Printf("AliUnfolding::UnfoldWithFunction: ERROR fit function not set. Exiting.");
    1772           0 :     return -1;
    1773             :   }    
    1774             :   
    1775           0 :   SetChi2Regularization(kNone, 0);
    1776             :   
    1777           0 :   SetStaticVariables(correlation, measured, efficiency);
    1778             :   
    1779             :   // Initialize TMinuit via generic fitter interface
    1780           0 :   TVirtualFitter *minuit = TVirtualFitter::Fitter(0, fgFitFunction->GetNpar());
    1781             : 
    1782           0 :   minuit->SetFCN(TF1Function);
    1783           0 :   for (Int_t i=0; i<fgFitFunction->GetNpar(); i++)
    1784             :   {
    1785           0 :     Double_t lower, upper;
    1786           0 :     fgFitFunction->GetParLimits(i, lower, upper);
    1787           0 :     minuit->SetParameter(i, Form("param%d",i), fgFitFunction->GetParameter(i), fgMinuitStepSize, lower, upper);
    1788           0 :   }
    1789             : 
    1790           0 :   Double_t arglist[100];
    1791           0 :   arglist[0] = 0;
    1792           0 :   minuit->ExecuteCommand("SET PRINT", arglist, 1);
    1793           0 :   minuit->ExecuteCommand("SCAN", arglist, 0);
    1794           0 :   minuit->ExecuteCommand("MIGRAD", arglist, 0);
    1795             :   //minuit->ExecuteCommand("MINOS", arglist, 0);
    1796             : 
    1797           0 :   for (Int_t i=0; i<fgFitFunction->GetNpar(); i++)
    1798           0 :     fgFitFunction->SetParameter(i, minuit->GetParameter(i));
    1799             : 
    1800           0 :   for (Int_t i=0; i<fgMaxParams; ++i)
    1801             :   {
    1802           0 :     Double_t value = fgFitFunction->Eval(i);
    1803           0 :     if (fgDebug)
    1804           0 :       Printf("%d : %f", i, value);
    1805             :     
    1806           0 :     if (efficiency)
    1807             :     {
    1808           0 :       if (efficiency->GetBinContent(i+1) > 0)
    1809             :       {
    1810           0 :         value /= efficiency->GetBinContent(i+1);
    1811           0 :       }
    1812             :       else
    1813             :         value = 0;
    1814             :     }
    1815           0 :     aResult->SetBinContent(i+1, value);
    1816           0 :     aResult->SetBinError(i+1, 0);
    1817             :   }
    1818             :   
    1819             :   return 0;
    1820           0 : }
    1821             : 
    1822             : //____________________________________________________________________
    1823             : void AliUnfolding::CreateOverflowBin(TH2* correlation, TH1* measured)
    1824             : {
    1825             :   // Finds the first bin where the content is below fgStatLimit and combines all values for this bin and larger bins
    1826             :   // The same limit is applied to the correlation  
    1827             :   
    1828             :   Int_t lastBin = 0;
    1829           0 :   for (Int_t i=1; i<=measured->GetNbinsX(); ++i)
    1830             :   {
    1831           0 :     if (measured->GetBinContent(i) <= fgOverflowBinLimit)
    1832             :     {
    1833             :       lastBin = i;
    1834           0 :       break;
    1835             :     }
    1836             :   }
    1837             :   
    1838           0 :   if (lastBin == 0)
    1839             :   {
    1840           0 :     Printf("AliUnfolding::CreateOverflowBin: WARNING: First bin is already below limit of %f", fgOverflowBinLimit);
    1841           0 :     return;
    1842             :   }
    1843             :   
    1844           0 :   Printf("AliUnfolding::CreateOverflowBin: Bin limit in measured spectrum determined to be %d", lastBin);
    1845             :   
    1846             :   TCanvas* canvas = 0;
    1847             : 
    1848           0 :   if (fgDebug)
    1849             :   {
    1850           0 :     canvas = new TCanvas("StatSolution", "StatSolution", 1000, 800);
    1851           0 :     canvas->Divide(2, 2);
    1852             : 
    1853           0 :     canvas->cd(1);
    1854           0 :     measured->SetStats(kFALSE);
    1855           0 :     measured->DrawCopy();
    1856           0 :     gPad->SetLogy();
    1857             : 
    1858           0 :     canvas->cd(2);
    1859           0 :     correlation->SetStats(kFALSE);
    1860           0 :     correlation->DrawCopy("COLZ");
    1861           0 :   }
    1862             : 
    1863           0 :   measured->SetBinContent(lastBin, measured->Integral(lastBin, measured->GetNbinsX()));
    1864           0 :   for (Int_t i=lastBin+1; i<=measured->GetNbinsX(); ++i)
    1865             :   {
    1866           0 :     measured->SetBinContent(i, 0);
    1867           0 :     measured->SetBinError(i, 0);
    1868             :   }
    1869             :   // the error is set to sqrt(N), better solution possible?, sum of relative errors of all contributions???
    1870           0 :   measured->SetBinError(lastBin, TMath::Sqrt(measured->GetBinContent(lastBin)));
    1871             : 
    1872           0 :   Printf("AliUnfolding::CreateOverflowBin: This bin has now %f +- %f entries", measured->GetBinContent(lastBin), measured->GetBinError(lastBin));
    1873             : 
    1874           0 :   for (Int_t i=1; i<=correlation->GetNbinsX(); ++i)
    1875             :   {
    1876           0 :     correlation->SetBinContent(i, lastBin, correlation->Integral(i, i, lastBin, correlation->GetNbinsY()));
    1877             :     // the error is set to sqrt(N), better solution possible?, sum of relative errors of all contributions???
    1878           0 :     correlation->SetBinError(i, lastBin, TMath::Sqrt(correlation->GetBinContent(i, lastBin)));
    1879             : 
    1880           0 :     for (Int_t j=lastBin+1; j<=correlation->GetNbinsY(); ++j)
    1881             :     {
    1882           0 :       correlation->SetBinContent(i, j, 0);
    1883           0 :       correlation->SetBinError(i, j, 0);
    1884             :     }
    1885             :   }
    1886             : 
    1887           0 :   Printf("AliUnfolding::CreateOverflowBin: Adjusted correlation matrix!");
    1888             : 
    1889           0 :   if (canvas)
    1890             :   {
    1891           0 :     canvas->cd(3);
    1892           0 :     measured->DrawCopy();
    1893           0 :     gPad->SetLogy();
    1894             : 
    1895           0 :     canvas->cd(4);
    1896           0 :     correlation->DrawCopy("COLZ");
    1897           0 :   }
    1898           0 : }
    1899             : 
    1900             : Int_t AliUnfolding::UnfoldGetBias(TH2* correlation, TH1* efficiency, TH1* measured, TH1* initialConditions, TH1* result)
    1901             : {
    1902             :   // unfolds and assigns bias as errors with Eq. 19 of Cowan, "a survey of unfolding methods for particle physics"
    1903             :   // b_i = sum_j dmu_i/dn_j (nu_j - n_j) with nu_j as folded guess, n_j as data
    1904             :   // dmu_i/dn_j is found numerically by changing the bin content and re-unfolding
    1905             :   //
    1906             :   // return code: 0 (success) -1 (error: from Unfold(...) )
    1907             : 
    1908           0 :   if (Unfold(correlation, efficiency, measured, initialConditions, result) != 0)
    1909           0 :     return -1;
    1910             : 
    1911           0 :   TMatrixD matrix(fgMaxInput, fgMaxParams);
    1912             :   
    1913           0 :   TH1* newResult[4];
    1914           0 :   for (Int_t loop=0; loop<4; loop++)
    1915           0 :     newResult[loop] = (TH1*) result->Clone(Form("newresult_%d", loop));
    1916             :     
    1917             :   // change bin-by-bin and built matrix of effects
    1918           0 :   for (Int_t m=0; m<fgMaxInput; m++)
    1919             :   {
    1920           0 :     if (measured->GetBinContent(m+1) < 1)
    1921             :       continue;
    1922             :       
    1923           0 :     for (Int_t loop=0; loop<4; loop++)
    1924             :     {
    1925             :       //Printf("%d %d", i, loop);
    1926             :       Float_t factor = 1;
    1927           0 :       switch (loop)
    1928             :       {
    1929           0 :         case 0: factor = 0.5; break;
    1930           0 :         case 1: factor = -0.5; break;
    1931           0 :         case 2: factor = 1; break;
    1932           0 :         case 3: factor = -1; break;
    1933           0 :         default: return -1;
    1934             :       }
    1935             :       
    1936           0 :       TH1* measuredClone = (TH1*) measured->Clone("measuredClone");
    1937             :   
    1938           0 :       measuredClone->SetBinContent(m+1, measured->GetBinContent(m+1) + factor * TMath::Sqrt(measured->GetBinContent(m+1)));
    1939             :       //new TCanvas; measuredClone->Draw("COLZ");
    1940             :     
    1941           0 :       newResult[loop]->Reset();
    1942           0 :       Unfold(correlation, efficiency, measuredClone, measuredClone, newResult[loop]);
    1943             :       // WARNING if we leave here, then nothing is calculated
    1944             :         //return -1;
    1945             :       
    1946           0 :       delete measuredClone;
    1947           0 :     }
    1948             :     
    1949           0 :     for (Int_t t=0; t<fgMaxParams; t++)
    1950             :     {
    1951             :       // one value
    1952             :       //matrix(i, j) = (result->GetBinContent(j+1) - newResult->GetBinContent(j+1)) / TMath::Sqrt(changedHist->GetBinContent(1, i+1));
    1953             :       
    1954             :       // four values from the derivate (procedure taken from ROOT -- suggestion by Ruben)
    1955             :       // = 1/2D * [ 8 (f(D/2) - f(-D/2)) - (f(D)-f(-D)) ]/3
    1956             :       
    1957             :       /*
    1958             :       // check formula
    1959             :       measured->SetBinContent(1, m+1, 100);
    1960             :       newResult[0]->SetBinContent(t+1, 5 * 0.5 + 10);
    1961             :       newResult[1]->SetBinContent(t+1, 5 * -0.5 + 10);
    1962             :       newResult[2]->SetBinContent(t+1, 5 * 1 + 10);
    1963             :       newResult[3]->SetBinContent(t+1, 5 * -1 + 10);
    1964             :       */
    1965             :       
    1966           0 :       matrix(m, t) = 0.5 / TMath::Sqrt(measured->GetBinContent(m+1)) * 
    1967           0 :         ( 8. * (newResult[0]->GetBinContent(t+1) - newResult[1]->GetBinContent(t+1)) - 
    1968           0 :               (newResult[2]->GetBinContent(t+1) - newResult[3]->GetBinContent(t+1))
    1969           0 :         ) / 3;
    1970             :     }
    1971           0 :   }
    1972             :   
    1973           0 :   for (Int_t loop=0; loop<4; loop++)
    1974           0 :     delete newResult[loop];
    1975             :   
    1976             :   // ...calculate folded guess  
    1977           0 :   TH1* convoluted = (TH1*) measured->Clone("convoluted");
    1978           0 :   convoluted->Reset();
    1979           0 :   for (Int_t m=0; m<fgMaxInput; m++)
    1980             :   {
    1981             :     Float_t value = 0;
    1982           0 :     for (Int_t t = 0; t<fgMaxParams; t++)
    1983             :     {
    1984           0 :       Float_t tmp = correlation->GetBinContent(t+1, m+1) * result->GetBinContent(t+1);
    1985           0 :       if (efficiency)
    1986           0 :         tmp *= efficiency->GetBinContent(t+1);
    1987           0 :       value += tmp;
    1988             :     }
    1989           0 :     convoluted->SetBinContent(m+1, value);
    1990             :   }
    1991             :   
    1992             :   // rescale
    1993           0 :   convoluted->Scale(measured->Integral() / convoluted->Integral());
    1994             :   
    1995             :   //new TCanvas; convoluted->Draw(); measured->Draw("SAME"); measured->SetLineColor(2);
    1996             :   //return;
    1997             :   
    1998             :   // difference
    1999           0 :   convoluted->Add(measured, -1);
    2000             :   
    2001             :   // ...and the bias
    2002           0 :   for (Int_t t = 0; t<fgMaxParams; t++)
    2003             :   {
    2004             :     Double_t error = 0;
    2005           0 :     for (Int_t m=0; m<fgMaxInput; m++)
    2006           0 :       error += matrix(m, t) * convoluted->GetBinContent(m+1); 
    2007           0 :     result->SetBinError(t+1, error);
    2008             :   }
    2009             :   
    2010             :   //new TCanvas; result->Draw(); gPad->SetLogy();
    2011             :   
    2012             :   return 0;
    2013           0 : }

Generated by: LCOV version 1.11