1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 // This class is used to store correction maps, raw input and results of the multiplicity
19 // measurement with the ITS or TPC
20 // It also contains functions to correct the spectrum using different methods.
21 // e.g. chi2 minimization and bayesian unfolding
23 // Author: Jan.Fiete.Grosse-Oetringhaus@cern.ch
25 #include "AliMultiplicityCorrection.h"
31 #include <TDirectory.h>
32 #include <TVirtualFitter.h>
37 #include <TCollection.h>
42 #include <TProfile2D.h>
44 ClassImp(AliMultiplicityCorrection)
46 const Int_t AliMultiplicityCorrection::fgkMaxInput = 250; // bins in measured histogram
47 const Int_t AliMultiplicityCorrection::fgkMaxParams = 250; // bins in unfolded histogram = number of fit params
49 TMatrixD* AliMultiplicityCorrection::fgCorrelationMatrix = 0;
50 TMatrixD* AliMultiplicityCorrection::fgCorrelationCovarianceMatrix = 0;
51 TVectorD* AliMultiplicityCorrection::fgCurrentESDVector = 0;
52 TVectorD* AliMultiplicityCorrection::fgEntropyAPriori = 0;
54 Bool_t AliMultiplicityCorrection::fgCreateBigBin = kTRUE;
55 AliMultiplicityCorrection::RegularizationType AliMultiplicityCorrection::fgRegularizationType = AliMultiplicityCorrection::kPol1;
56 Float_t AliMultiplicityCorrection::fgRegularizationWeight = 10000;
57 Int_t AliMultiplicityCorrection::fgNParamsMinuit = AliMultiplicityCorrection::fgkMaxParams;
59 TF1* AliMultiplicityCorrection::fgNBD = 0;
61 Float_t AliMultiplicityCorrection::fgBayesianSmoothing = 1; // smoothing parameter (0 = no smoothing)
62 Int_t AliMultiplicityCorrection::fgBayesianIterations = 100; // number of iterations in Bayesian method
64 // These are the areas where the quality of the unfolding results are evaluated
65 // Default defined here, call SetQualityRegions to change them
66 // unit is in multiplicity (not in bin!)
68 // SPD: peak area - flat area - low stat area
69 Int_t AliMultiplicityCorrection::fgQualityRegionsB[kQualityRegions] = {4, 60, 180};
70 Int_t AliMultiplicityCorrection::fgQualityRegionsE[kQualityRegions] = {20, 140, 210};
72 //____________________________________________________________________
73 void AliMultiplicityCorrection::SetQualityRegions(Bool_t SPDStudy)
76 // sets the quality region definition to TPC or SPD
81 // SPD: peak area - flat area - low stat area
82 fgQualityRegionsB[0] = 4;
83 fgQualityRegionsE[0] = 20;
85 fgQualityRegionsB[1] = 60;
86 fgQualityRegionsE[1] = 140;
88 fgQualityRegionsB[2] = 180;
89 fgQualityRegionsE[2] = 210;
91 Printf("AliMultiplicityCorrection::SetQualityRegions --> Enabled quality regions for SPD");
95 // TPC: peak area - flat area - low stat area
96 fgQualityRegionsB[0] = 4;
97 fgQualityRegionsE[0] = 12;
99 fgQualityRegionsB[1] = 25;
100 fgQualityRegionsE[1] = 55;
102 fgQualityRegionsB[2] = 88;
103 fgQualityRegionsE[2] = 108;
105 Printf("AliMultiplicityCorrection::SetQualityRegions --> Enabled quality regions for TPC");
109 //____________________________________________________________________
110 AliMultiplicityCorrection::AliMultiplicityCorrection() :
111 TNamed(), fCurrentESD(0), fCurrentCorrelation(0), fCurrentEfficiency(0), fLastBinLimit(0), fLastChi2MC(0), fLastChi2MCLimit(0), fLastChi2Residuals(0), fRatioAverage(0)
114 // default constructor
117 for (Int_t i = 0; i < kESDHists; ++i)
118 fMultiplicityESD[i] = 0;
120 for (Int_t i = 0; i < kMCHists; ++i)
122 fMultiplicityVtx[i] = 0;
123 fMultiplicityMB[i] = 0;
124 fMultiplicityINEL[i] = 0;
127 for (Int_t i = 0; i < kCorrHists; ++i)
130 fMultiplicityESDCorrected[i] = 0;
133 for (Int_t i = 0; i < kQualityRegions; ++i)
137 //____________________________________________________________________
138 AliMultiplicityCorrection::AliMultiplicityCorrection(const Char_t* name, const Char_t* title) :
141 fCurrentCorrelation(0),
142 fCurrentEfficiency(0),
146 fLastChi2Residuals(0),
153 // do not add this hists to the directory
154 Bool_t oldStatus = TH1::AddDirectoryStatus();
155 TH1::AddDirectory(kFALSE);
157 /*Float_t binLimitsVtx[] = {-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10};
158 Float_t binLimitsN[] = {-0.5, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5,
159 10.5, 11.5, 12.5, 13.5, 14.5, 15.5, 16.5, 17.5, 18.5, 19.5,
160 20.5, 21.5, 22.5, 23.5, 24.5, 25.5, 26.5, 27.5, 28.5, 29.5,
161 30.5, 31.5, 32.5, 33.5, 34.5, 35.5, 36.5, 37.5, 38.5, 39.5,
162 40.5, 41.5, 42.5, 43.5, 44.5, 45.5, 46.5, 47.5, 48.5, 49.5,
163 50.5, 55.5, 60.5, 65.5, 70.5, 75.5, 80.5, 85.5, 90.5, 95.5,
164 100.5, 105.5, 110.5, 115.5, 120.5, 125.5, 130.5, 135.5, 140.5, 145.5,
165 150.5, 160.5, 170.5, 180.5, 190.5, 200.5, 210.5, 220.5, 230.5, 240.5,
166 250.5, 275.5, 300.5, 325.5, 350.5, 375.5, 400.5, 425.5, 450.5, 475.5,
168 //525.5, 550.5, 575.5, 600.5, 625.5, 650.5, 675.5, 700.5, 725.5,
169 //750.5, 775.5, 800.5, 825.5, 850.5, 875.5, 900.5, 925.5, 950.5, 975.5,
172 #define VTXBINNING 10, binLimitsVtx
173 #define NBINNING fgkMaxParams, binLimitsN*/
175 #define NBINNING 501, -0.5, 500.5
176 #define VTXBINNING 1, -10, 10
178 for (Int_t i = 0; i < kESDHists; ++i)
179 fMultiplicityESD[i] = new TH2F(Form("fMultiplicityESD%d", i), "fMultiplicityESD;vtx-z;Ntracks;Count", VTXBINNING, NBINNING);
181 for (Int_t i = 0; i < kMCHists; ++i)
183 fMultiplicityVtx[i] = dynamic_cast<TH2F*> (fMultiplicityESD[0]->Clone(Form("fMultiplicityVtx%d", i)));
184 fMultiplicityVtx[i]->SetTitle("fMultiplicityVtx;vtx-z;Npart");
186 fMultiplicityMB[i] = dynamic_cast<TH2F*> (fMultiplicityVtx[0]->Clone(Form("fMultiplicityMB%d", i)));
187 fMultiplicityMB[i]->SetTitle("fMultiplicityMB");
189 fMultiplicityINEL[i] = dynamic_cast<TH2F*> (fMultiplicityVtx[0]->Clone(Form("fMultiplicityINEL%d", i)));
190 fMultiplicityINEL[i]->SetTitle("fMultiplicityINEL");
193 for (Int_t i = 0; i < kCorrHists; ++i)
195 fCorrelation[i] = new TH3F(Form("fCorrelation%d", i), "fCorrelation;vtx-z;Npart;Ntracks", VTXBINNING, NBINNING, NBINNING);
196 fMultiplicityESDCorrected[i] = new TH1F(Form("fMultiplicityESDCorrected%d", i), "fMultiplicityESDCorrected;Npart;dN/dN", NBINNING);
199 TH1::AddDirectory(oldStatus);
202 //____________________________________________________________________
203 AliMultiplicityCorrection::~AliMultiplicityCorrection()
209 Printf("AliMultiplicityCorrection::~AliMultiplicityCorrection called");
211 for (Int_t i = 0; i < kESDHists; ++i)
213 if (fMultiplicityESD[i])
214 delete fMultiplicityESD[i];
215 fMultiplicityESD[i] = 0;
218 for (Int_t i = 0; i < kMCHists; ++i)
220 if (fMultiplicityVtx[i])
221 delete fMultiplicityVtx[i];
222 fMultiplicityVtx[i] = 0;
224 if (fMultiplicityMB[i])
225 delete fMultiplicityMB[i];
226 fMultiplicityMB[i] = 0;
228 if (fMultiplicityINEL[i])
229 delete fMultiplicityINEL[i];
230 fMultiplicityINEL[i] = 0;
233 for (Int_t i = 0; i < kCorrHists; ++i)
236 delete fCorrelation[i];
239 if (fMultiplicityESDCorrected[i])
240 delete fMultiplicityESDCorrected[i];
241 fMultiplicityESDCorrected[i] = 0;
245 //____________________________________________________________________
246 Long64_t AliMultiplicityCorrection::Merge(TCollection* list)
248 // Merge a list of AliMultiplicityCorrection objects with this (needed for
250 // Returns the number of merged objects (including this).
258 TIterator* iter = list->MakeIterator();
261 // collections of all histograms
262 TList collections[kESDHists+kMCHists*3+kCorrHists*2];
265 while ((obj = iter->Next())) {
267 AliMultiplicityCorrection* entry = dynamic_cast<AliMultiplicityCorrection*> (obj);
271 for (Int_t i = 0; i < kESDHists; ++i)
272 collections[i].Add(entry->fMultiplicityESD[i]);
274 for (Int_t i = 0; i < kMCHists; ++i)
276 collections[kESDHists+i].Add(entry->fMultiplicityVtx[i]);
277 collections[kESDHists+kMCHists+i].Add(entry->fMultiplicityMB[i]);
278 collections[kESDHists+kMCHists*2+i].Add(entry->fMultiplicityINEL[i]);
281 for (Int_t i = 0; i < kCorrHists; ++i)
282 collections[kESDHists+kMCHists*3+i].Add(entry->fCorrelation[i]);
284 for (Int_t i = 0; i < kCorrHists; ++i)
285 collections[kESDHists+kMCHists*3+kCorrHists+i].Add(entry->fMultiplicityESDCorrected[i]);
290 for (Int_t i = 0; i < kESDHists; ++i)
291 fMultiplicityESD[i]->Merge(&collections[i]);
293 for (Int_t i = 0; i < kMCHists; ++i)
295 fMultiplicityVtx[i]->Merge(&collections[kESDHists+i]);
296 fMultiplicityMB[i]->Merge(&collections[kESDHists+kMCHists+i]);
297 fMultiplicityINEL[i]->Merge(&collections[kESDHists+kMCHists*2+i]);
300 for (Int_t i = 0; i < kCorrHists; ++i)
301 fCorrelation[i]->Merge(&collections[kESDHists+kMCHists*3+i]);
303 for (Int_t i = 0; i < kCorrHists; ++i)
304 fMultiplicityESDCorrected[i]->Merge(&collections[kESDHists+kMCHists*3+kCorrHists+i]);
311 //____________________________________________________________________
312 Bool_t AliMultiplicityCorrection::LoadHistograms(const Char_t* dir)
315 // loads the histograms from a file
316 // if dir is empty a directory with the name of this object is taken (like in SaveHistogram)
322 if (!gDirectory->cd(dir))
325 // store old hists to delete them later
327 oldObjects.SetOwner(1);
328 for (Int_t i = 0; i < kESDHists; ++i)
329 if (fMultiplicityESD[i])
330 oldObjects.Add(fMultiplicityESD[i]);
332 for (Int_t i = 0; i < kMCHists; ++i)
334 if (fMultiplicityVtx[i])
335 oldObjects.Add(fMultiplicityVtx[i]);
336 if (fMultiplicityMB[i])
337 oldObjects.Add(fMultiplicityMB[i]);
338 if (fMultiplicityINEL[i])
339 oldObjects.Add(fMultiplicityINEL[i]);
342 for (Int_t i = 0; i < kCorrHists; ++i)
344 oldObjects.Add(fCorrelation[i]);
348 Bool_t success = kTRUE;
350 for (Int_t i = 0; i < kESDHists; ++i)
352 fMultiplicityESD[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityESD[i]->GetName()));
353 if (!fMultiplicityESD[i])
357 for (Int_t i = 0; i < kMCHists; ++i)
359 fMultiplicityVtx[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityVtx[i]->GetName()));
360 fMultiplicityMB[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityMB[i]->GetName()));
361 fMultiplicityINEL[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityINEL[i]->GetName()));
362 if (!fMultiplicityVtx[i] || !fMultiplicityMB[i] || !fMultiplicityINEL[i])
366 for (Int_t i = 0; i < kCorrHists; ++i)
368 fCorrelation[i] = dynamic_cast<TH3F*> (gDirectory->Get(fCorrelation[i]->GetName()));
369 if (!fCorrelation[i])
371 fMultiplicityESDCorrected[i] = dynamic_cast<TH1F*> (gDirectory->Get(fMultiplicityESDCorrected[i]->GetName()));
372 if (!fMultiplicityESDCorrected[i])
376 gDirectory->cd("..");
384 //____________________________________________________________________
385 void AliMultiplicityCorrection::SaveHistograms(const char* dir)
388 // saves the histograms
394 gDirectory->mkdir(dir);
397 for (Int_t i = 0; i < kESDHists; ++i)
398 if (fMultiplicityESD[i])
399 fMultiplicityESD[i]->Write();
401 for (Int_t i = 0; i < kMCHists; ++i)
403 if (fMultiplicityVtx[i])
404 fMultiplicityVtx[i]->Write();
405 if (fMultiplicityMB[i])
406 fMultiplicityMB[i]->Write();
407 if (fMultiplicityINEL[i])
408 fMultiplicityINEL[i]->Write();
411 for (Int_t i = 0; i < kCorrHists; ++i)
414 fCorrelation[i]->Write();
415 if (fMultiplicityESDCorrected[i])
416 fMultiplicityESDCorrected[i]->Write();
419 gDirectory->cd("..");
422 //____________________________________________________________________
423 void AliMultiplicityCorrection::FillGenerated(Float_t vtx, Bool_t triggered, Bool_t vertex, Int_t generated05, Int_t generated10, Int_t generated15, Int_t generated20, Int_t generatedAll)
426 // Fills an event from MC
431 fMultiplicityMB[0]->Fill(vtx, generated05);
432 fMultiplicityMB[1]->Fill(vtx, generated10);
433 fMultiplicityMB[2]->Fill(vtx, generated15);
434 fMultiplicityMB[3]->Fill(vtx, generated20);
435 fMultiplicityMB[4]->Fill(vtx, generatedAll);
439 fMultiplicityVtx[0]->Fill(vtx, generated05);
440 fMultiplicityVtx[1]->Fill(vtx, generated10);
441 fMultiplicityVtx[2]->Fill(vtx, generated15);
442 fMultiplicityVtx[3]->Fill(vtx, generated20);
443 fMultiplicityVtx[4]->Fill(vtx, generatedAll);
447 fMultiplicityINEL[0]->Fill(vtx, generated05);
448 fMultiplicityINEL[1]->Fill(vtx, generated10);
449 fMultiplicityINEL[2]->Fill(vtx, generated15);
450 fMultiplicityINEL[3]->Fill(vtx, generated20);
451 fMultiplicityINEL[4]->Fill(vtx, generatedAll);
454 //____________________________________________________________________
455 void AliMultiplicityCorrection::FillMeasured(Float_t vtx, Int_t measured05, Int_t measured10, Int_t measured15, Int_t measured20)
458 // Fills an event from ESD
461 fMultiplicityESD[0]->Fill(vtx, measured05);
462 fMultiplicityESD[1]->Fill(vtx, measured10);
463 fMultiplicityESD[2]->Fill(vtx, measured15);
464 fMultiplicityESD[3]->Fill(vtx, measured20);
467 //____________________________________________________________________
468 void AliMultiplicityCorrection::FillCorrection(Float_t vtx, Int_t generated05, Int_t generated10, Int_t generated15, Int_t generated20, Int_t generatedAll, Int_t measured05, Int_t measured10, Int_t measured15, Int_t measured20)
471 // Fills an event into the correlation map with the information from MC and ESD
474 fCorrelation[0]->Fill(vtx, generated05, measured05);
475 fCorrelation[1]->Fill(vtx, generated10, measured10);
476 fCorrelation[2]->Fill(vtx, generated15, measured15);
477 fCorrelation[3]->Fill(vtx, generated20, measured20);
479 fCorrelation[4]->Fill(vtx, generatedAll, measured05);
480 fCorrelation[5]->Fill(vtx, generatedAll, measured10);
481 fCorrelation[6]->Fill(vtx, generatedAll, measured15);
482 fCorrelation[7]->Fill(vtx, generatedAll, measured20);
485 //____________________________________________________________________
486 Double_t AliMultiplicityCorrection::RegularizationPol0(TVectorD& params)
488 // homogenity term for minuit fitting
489 // pure function of the parameters
490 // prefers constant function (pol0)
494 // ignore the first bin here. on purpose...
495 for (Int_t i=2; i<fgNParamsMinuit; ++i)
497 Double_t right = params[i];
498 Double_t left = params[i-1];
502 Double_t diff = 1 - left / right;
510 //____________________________________________________________________
511 Double_t AliMultiplicityCorrection::RegularizationPol1(TVectorD& params)
513 // homogenity term for minuit fitting
514 // pure function of the parameters
515 // prefers linear function (pol1)
519 // ignore the first bin here. on purpose...
520 for (Int_t i=2+1; i<fgNParamsMinuit; ++i)
522 if (params[i-1] == 0)
525 Double_t right = params[i];
526 Double_t middle = params[i-1];
527 Double_t left = params[i-2];
529 Double_t der1 = (right - middle);
530 Double_t der2 = (middle - left);
532 Double_t diff = (der1 - der2) / middle;
540 //____________________________________________________________________
541 Double_t AliMultiplicityCorrection::RegularizationLog(TVectorD& params)
543 // homogenity term for minuit fitting
544 // pure function of the parameters
545 // prefers linear function (pol1)
549 /*Float_t der[fgkMaxParams];
551 for (Int_t i=0; i<fgkMaxParams-1; ++i)
552 der[i] = params[i+1] - params[i];
554 for (Int_t i=0; i<fgkMaxParams-6; ++i)
556 for (Int_t j=1; j<=5; ++j)
558 Double_t diff = der[i+j] - der[i];
563 // ignore the first bin here. on purpose...
564 for (Int_t i=2+1; i<fgNParamsMinuit; ++i)
566 if (params[i-1] == 0)
569 Double_t right = log(params[i]);
570 Double_t middle = log(params[i-1]);
571 Double_t left = log(params[i-2]);
573 Double_t der1 = (right - middle);
574 Double_t der2 = (middle - left);
576 Double_t diff = (der1 - der2) / middle;
584 //____________________________________________________________________
585 Double_t AliMultiplicityCorrection::RegularizationTotalCurvature(TVectorD& params)
587 // homogenity term for minuit fitting
588 // pure function of the parameters
589 // minimizes the total curvature (from Unfolding Methods In High-Energy Physics Experiments,
590 // V. Blobel (Hamburg U.) . DESY 84/118, Dec 1984. 40pp.
594 // ignore the first bin here. on purpose...
595 for (Int_t i=3; i<fgNParamsMinuit; ++i)
597 Double_t right = params[i];
598 Double_t middle = params[i-1];
599 Double_t left = params[i-2];
601 Double_t der1 = (right - middle);
602 Double_t der2 = (middle - left);
604 Double_t diff = (der1 - der2);
612 //____________________________________________________________________
613 Double_t AliMultiplicityCorrection::RegularizationEntropy(TVectorD& params)
615 // homogenity term for minuit fitting
616 // pure function of the parameters
617 // calculates entropy, from
618 // The method of reduced cross-entropy (M. Schmelling 1993)
620 Double_t paramSum = 0;
621 // ignore the first bin here. on purpose...
622 for (Int_t i=1; i<fgNParamsMinuit; ++i)
623 paramSum += params[i];
626 for (Int_t i=1; i<fgNParamsMinuit; ++i)
628 //Double_t tmp = params[i] / paramSum;
629 Double_t tmp = params[i];
630 if (tmp > 0 && (*fgEntropyAPriori)[i] > 0)
631 chi2 += tmp * TMath::Log(tmp / (*fgEntropyAPriori)[i]);
637 //____________________________________________________________________
638 void AliMultiplicityCorrection::MinuitNBD(Int_t& unused1, Double_t* unused2, Double_t& chi2, Double_t *params, Int_t unused3)
641 // fit function for minuit
643 // func = new TF1("nbd", "[0] * TMath::Binomial([2]+TMath::Nint(x)-1, [2]-1) * pow([1] / ([1]+[2]), TMath::Nint(x)) * pow(1 + [1]/[2], -[2])", 0, 50);
644 // func->SetParNames("scaling", "averagen", "k");
645 // func->SetParLimits(0, 0.001, fCurrentESD->GetMaximum() * 1000);
646 // func->SetParLimits(1, 0.001, 1000);
647 // func->SetParLimits(2, 0.001, 1000);
650 fgNBD->SetParameters(params[0], params[1], params[2]);
652 Double_t params2[fgkMaxParams];
654 for (Int_t i=0; i<fgkMaxParams; ++i)
655 params2[i] = fgNBD->Eval(i);
657 MinuitFitFunction(unused1, unused2, chi2, params2, unused3);
659 printf("%f %f %f --> %f\n", params[0], params[1], params[2], chi2);
662 //____________________________________________________________________
663 void AliMultiplicityCorrection::MinuitFitFunction(Int_t&, Double_t*, Double_t& chi2, Double_t *params, Int_t)
666 // fit function for minuit
667 // does: (m - Ad)W(m - Ad) where m = measured, A correlation matrix, d = guess, W = covariance matrix
671 static TVectorD paramsVector(fgNParamsMinuit);
672 for (Int_t i=0; i<fgNParamsMinuit; ++i)
673 paramsVector[i] = params[i] * params[i];
675 // calculate penalty factor
676 Double_t penaltyVal = 0;
677 switch (fgRegularizationType)
680 case kPol0: penaltyVal = RegularizationPol0(paramsVector); break;
681 case kPol1: penaltyVal = RegularizationPol1(paramsVector); break;
682 case kCurvature: penaltyVal = RegularizationTotalCurvature(paramsVector); break;
683 case kEntropy: penaltyVal = RegularizationEntropy(paramsVector); break;
684 case kLog: penaltyVal = RegularizationLog(paramsVector); break;
687 //if (penaltyVal > 1e10)
688 // paramsVector2.Print();
690 penaltyVal *= fgRegularizationWeight;
693 TVectorD measGuessVector(fgkMaxInput);
694 measGuessVector = (*fgCorrelationMatrix) * paramsVector;
697 measGuessVector -= (*fgCurrentESDVector);
699 //measGuessVector.Print();
701 TVectorD copy(measGuessVector);
704 // this step can be optimized because currently only the diagonal elements of fgCorrelationCovarianceMatrix are used
705 // normal way is like this:
706 // measGuessVector *= (*fgCorrelationCovarianceMatrix);
707 // optimized way like this:
708 for (Int_t i=0; i<fgkMaxInput; ++i)
709 measGuessVector[i] *= (*fgCorrelationCovarianceMatrix)(i, i);
711 //measGuessVector.Print();
713 // reduce influence of first bin
716 // (Ad - m) W (Ad - m)
717 // the factor 1e6 prevents that a very small number (measGuessVector[i]) is multiplied with a very
718 // big number ((*fgCorrelationCovarianceMatrix)(i, i)) (see ApplyMinuitFit)
719 Double_t chi2FromFit = measGuessVector * copy * 1e6;
721 chi2 = chi2FromFit + penaltyVal;
723 static Int_t callCount = 0;
724 if ((callCount++ % 10000) == 0)
725 printf("%d) %f %f --> %f\n", callCount, chi2FromFit, penaltyVal, chi2);
728 //____________________________________________________________________
729 void AliMultiplicityCorrection::DrawGuess(Double_t *params)
732 // draws residuals of solution suggested by params and effect of regularization
736 static TVectorD paramsVector(fgNParamsMinuit);
737 for (Int_t i=0; i<fgNParamsMinuit; ++i)
738 paramsVector[i] = params[i] * params[i];
741 TVectorD measGuessVector(fgkMaxInput);
742 measGuessVector = (*fgCorrelationMatrix) * paramsVector;
745 measGuessVector -= (*fgCurrentESDVector);
747 TVectorD copy(measGuessVector);
750 // this step can be optimized because currently only the diagonal elements of fgCorrelationCovarianceMatrix are used
751 // normal way is like this:
752 // measGuessVector *= (*fgCorrelationCovarianceMatrix);
753 // optimized way like this:
754 for (Int_t i=0; i<fgkMaxInput; ++i)
755 measGuessVector[i] *= (*fgCorrelationCovarianceMatrix)(i, i);
757 // (Ad - m) W (Ad - m)
758 // the factor 1e6 prevents that a very small number (measGuessVector[i]) is multiplied with a very
759 // big number ((*fgCorrelationCovarianceMatrix)(i, i)) (see ApplyMinuitFit)
760 //Double_t chi2FromFit = measGuessVector * copy * 1e6;
763 TH1* residuals = new TH1F("residuals", "residuals", fgkMaxInput, -0.5, fgkMaxInput - 0.5);
764 for (Int_t i=0; i<fgkMaxInput; ++i)
765 residuals->SetBinContent(i+1, measGuessVector(i) * copy(i) * 1e6);
766 new TCanvas; residuals->DrawCopy(); gPad->SetLogy();
769 if (fgRegularizationType != kPol1) {
770 Printf("Drawing not supported");
774 TH1* penalty = new TH1F("penalty", "penalty", fgNParamsMinuit, -0.5, fgNParamsMinuit - 0.5);
776 for (Int_t i=2; i<fgNParamsMinuit; ++i)
778 if (params[i-1] == 0)
781 Double_t right = params[i];
782 Double_t middle = params[i-1];
783 Double_t left = params[i-2];
785 Double_t der1 = (right - middle);
786 Double_t der2 = (middle - left);
788 Double_t diff = (der1 - der2) / middle;
790 penalty->SetBinContent(i, diff * diff);
792 new TCanvas; penalty->DrawCopy(); gPad->SetLogy();
795 //____________________________________________________________________
796 void AliMultiplicityCorrection::SetupCurrentHists(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Bool_t createBigBin)
799 // fills fCurrentESD, fCurrentCorrelation
800 // resets fMultiplicityESDCorrected
803 Bool_t display = kFALSE;
805 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
807 fMultiplicityESDCorrected[correlationID]->Reset();
808 fMultiplicityESDCorrected[correlationID]->Sumw2();
810 fCurrentESD = fMultiplicityESD[inputRange]->ProjectionY("fCurrentESD"); //"fCurrentESD", -1, -1, "e");
811 fCurrentESD->Sumw2();
813 // empty under/overflow bins in x, otherwise Project3D takes them into account
814 TH3* hist = fCorrelation[correlationID];
815 for (Int_t y=1; y<=hist->GetYaxis()->GetNbins(); ++y)
817 for (Int_t z=1; z<=hist->GetZaxis()->GetNbins(); ++z)
819 hist->SetBinContent(0, y, z, 0);
820 hist->SetBinContent(hist->GetXaxis()->GetNbins()+1, y, z, 0);
824 fCurrentCorrelation = hist->Project3D("zy");
825 //((TH2*) fCurrentCorrelation)->Rebin2D(2, 1);
826 //fMultiplicityESDCorrected[correlationID]->Rebin(2);
827 fCurrentCorrelation->Sumw2();
829 Printf("AliMultiplicityCorrection::SetupCurrentHists: Statistics information: %.f entries in correlation map; %.f entries in measured spectrum", fCurrentCorrelation->Integral(), fCurrentESD->Integral());
834 for (Int_t i=1; i<=fCurrentESD->GetNbinsX(); ++i)
836 if (fCurrentESD->GetBinContent(i) <= 5)
843 if (fLastBinLimit > 0)
849 canvas = new TCanvas("StatSolution", "StatSolution", 1000, 800);
850 canvas->Divide(2, 2);
853 fCurrentESD->GetXaxis()->SetRangeUser(0, 200);
854 fCurrentESD->SetStats(kFALSE);
855 fCurrentESD->SetTitle(";measured multiplicity");
856 fCurrentESD->DrawCopy();
860 fCurrentCorrelation->GetXaxis()->SetRangeUser(0, 250);
861 fCurrentCorrelation->GetYaxis()->SetRangeUser(0, 250);
862 fCurrentCorrelation->SetTitle(";true multiplicity;measured multiplicity");
863 fCurrentCorrelation->SetStats(kFALSE);
864 fCurrentCorrelation->DrawCopy("COLZ");
867 printf("Bin limit in measured spectrum is %d.\n", fLastBinLimit);
868 fCurrentESD->SetBinContent(fLastBinLimit, fCurrentESD->Integral(fLastBinLimit, fCurrentESD->GetNbinsX()));
869 for (Int_t i=fLastBinLimit+1; i<=fCurrentESD->GetNbinsX(); ++i)
871 fCurrentESD->SetBinContent(i, 0);
872 fCurrentESD->SetBinError(i, 0);
874 // the error is set to sqrt(N), better solution possible?, sum of relative errors of all contributions???
875 fCurrentESD->SetBinError(fLastBinLimit, TMath::Sqrt(fCurrentESD->GetBinContent(fLastBinLimit)));
877 printf("This bin has now %f +- %f entries\n", fCurrentESD->GetBinContent(fLastBinLimit), fCurrentESD->GetBinError(fLastBinLimit));
879 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
881 fCurrentCorrelation->SetBinContent(i, fLastBinLimit, fCurrentCorrelation->Integral(i, i, fLastBinLimit, fCurrentCorrelation->GetNbinsY()));
882 // the error is set to sqrt(N), better solution possible?, sum of relative errors of all contributions???
883 fCurrentCorrelation->SetBinError(i, fLastBinLimit, TMath::Sqrt(fCurrentCorrelation->GetBinContent(i, fLastBinLimit)));
885 for (Int_t j=fLastBinLimit+1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
887 fCurrentCorrelation->SetBinContent(i, j, 0);
888 fCurrentCorrelation->SetBinError(i, j, 0);
892 printf("Adjusted correlation matrix!\n");
897 fCurrentESD->DrawCopy();
901 fCurrentCorrelation->DrawCopy("COLZ");
906 #if 0 // does not help
907 // null bins with one entry
908 Int_t nNulledBins = 0;
909 for (Int_t x=1; x<=fCurrentCorrelation->GetXaxis()->GetNbins(); ++x)
910 for (Int_t y=1; y<=fCurrentCorrelation->GetYaxis()->GetNbins(); ++y)
912 if (fCurrentCorrelation->GetBinContent(x, y) == 1)
914 fCurrentCorrelation->SetBinContent(x, y, 0);
915 fCurrentCorrelation->SetBinError(x, y, 0);
920 Printf("Nulled %d bins", nNulledBins);
923 fCurrentEfficiency = GetEfficiency(inputRange, eventType);
924 //fCurrentEfficiency->Rebin(2);
925 //fCurrentEfficiency->Scale(0.5);
928 //____________________________________________________________________
929 TH1* AliMultiplicityCorrection::GetEfficiency(Int_t inputRange, EventType eventType)
932 // calculates efficiency for given event type
938 case kTrVtx : divisor = fMultiplicityVtx[inputRange]->ProjectionY("divisor", -1, -1, "e"); break;
939 case kMB: divisor = fMultiplicityMB[inputRange]->ProjectionY("divisor", -1, -1, "e"); break;
940 case kINEL: divisor = fMultiplicityINEL[inputRange]->ProjectionY("divisor", -1, -1, "e"); break;
942 TH1* eff = fMultiplicityVtx[inputRange]->ProjectionY("CurrentEfficiency", -1, -1, "e");
943 eff->Divide(eff, divisor, 1, 1, "B");
947 //____________________________________________________________________
948 void AliMultiplicityCorrection::SetRegularizationParameters(RegularizationType type, Float_t weight, Int_t minuitParams)
951 // sets the parameters for chi2 minimization
954 fgRegularizationType = type;
955 fgRegularizationWeight = weight;
957 printf("AliMultiplicityCorrection::SetRegularizationParameters --> Regularization set to %d with weight %f\n", (Int_t) type, weight);
959 if (minuitParams > 0)
961 fgNParamsMinuit = minuitParams;
962 printf("AliMultiplicityCorrection::SetRegularizationParameters --> Number of MINUIT iterations set to %d\n", minuitParams);
966 //____________________________________________________________________
967 void AliMultiplicityCorrection::SetBayesianParameters(Float_t smoothing, Int_t nIterations)
970 // sets the parameters for Bayesian unfolding
973 fgBayesianSmoothing = smoothing;
974 fgBayesianIterations = nIterations;
976 printf("AliMultiplicityCorrection::SetBayesianParameters --> Paramaters set to %d iterations with smoothing %f\n", fgBayesianIterations, fgBayesianSmoothing);
979 //____________________________________________________________________
980 Int_t AliMultiplicityCorrection::UnfoldWithMinuit(TH1* correlation, TH1* aEfficiency, TH1* measured, TH1* initialConditions, TH1* result, Bool_t check)
983 // implemenation of unfolding (internal function)
985 // unfolds <measured> using response from <correlation> and effiency <aEfficiency>
986 // output is in <result>
987 // <initialConditions> set the initial values for the minimization, if 0 <measured> is used
988 // if <check> is true no unfolding is made, instead only the chi2 without unfolding is printed
990 // returns minuit status (0 = success), (-1 when check was set)
994 measured->Scale(1.0 / measured->Integral());
996 if (!fgCorrelationMatrix)
997 fgCorrelationMatrix = new TMatrixD(fgkMaxInput, fgNParamsMinuit);
998 if (!fgCorrelationCovarianceMatrix)
999 fgCorrelationCovarianceMatrix = new TMatrixD(fgkMaxInput, fgkMaxInput);
1000 if (!fgCurrentESDVector)
1001 fgCurrentESDVector = new TVectorD(fgkMaxInput);
1002 if (!fgEntropyAPriori)
1003 fgEntropyAPriori = new TVectorD(fgNParamsMinuit);
1005 fgCorrelationMatrix->Zero();
1006 fgCorrelationCovarianceMatrix->Zero();
1007 fgCurrentESDVector->Zero();
1008 fgEntropyAPriori->Zero();
1010 // normalize correction for given nPart
1011 for (Int_t i=1; i<=correlation->GetNbinsX(); ++i)
1013 Double_t sum = correlation->Integral(i, i, 1, correlation->GetNbinsY());
1016 Float_t maxValue = 0;
1018 for (Int_t j=1; j<=correlation->GetNbinsY(); ++j)
1020 // find most probably value
1021 if (maxValue < correlation->GetBinContent(i, j))
1023 maxValue = correlation->GetBinContent(i, j);
1028 correlation->SetBinContent(i, j, correlation->GetBinContent(i, j) / sum);
1029 correlation->SetBinError(i, j, correlation->GetBinError(i, j) / sum);
1031 if (i <= fgNParamsMinuit && j <= fgkMaxInput)
1032 (*fgCorrelationMatrix)(j-1, i-1) = correlation->GetBinContent(i, j);
1035 //printf("MPV for Ntrue = %f is %f\n", fCurrentCorrelation->GetXaxis()->GetBinCenter(i), fCurrentCorrelation->GetYaxis()->GetBinCenter(maxBin));
1038 // Initialize TMinuit via generic fitter interface
1039 TVirtualFitter *minuit = TVirtualFitter::Fitter(0, fgNParamsMinuit);
1040 Double_t arglist[100];
1042 // disable any output (-1), unfortuantly we do not see warnings anymore then. Have to find another way...
1044 minuit->ExecuteCommand("SET PRINT", arglist, 1);
1046 // however, enable warnings
1047 //minuit->ExecuteCommand("SET WAR", arglist, 0);
1049 // set minimization function
1050 minuit->SetFCN(MinuitFitFunction);
1052 for (Int_t i=0; i<fgNParamsMinuit; i++)
1053 (*fgEntropyAPriori)[i] = 1;
1055 if (!initialConditions) {
1056 initialConditions = measured;
1058 printf("Using different starting conditions...\n");
1059 //new TCanvas; initialConditions->DrawCopy();
1060 initialConditions->Scale(1.0 / initialConditions->Integral());
1063 for (Int_t i=0; i<fgNParamsMinuit; i++)
1064 if (initialConditions->GetBinContent(i+1) > 0)
1065 (*fgEntropyAPriori)[i] = initialConditions->GetBinContent(i+1);
1067 Double_t* results = new Double_t[fgNParamsMinuit+1];
1068 for (Int_t i=0; i<fgNParamsMinuit; ++i)
1070 results[i] = initialConditions->GetBinContent(i+1);
1074 results[i] = TMath::Max(results[i], 1e-3);
1076 Float_t stepSize = 0.1;
1078 // minuit sees squared values to prevent it from going negative...
1079 results[i] = TMath::Sqrt(results[i]);
1080 //stepSize /= results[i]; // keep relative step size
1082 minuit->SetParameter(i, Form("param%d", i), results[i], stepSize, 0, 0);
1084 //minuit->SetParameter(fgkMaxParams, "alpha", 1e4, 1, 0, 0);
1085 // bin 0 is filled with value from bin 1 (otherwise it's 0)
1086 //minuit->SetParameter(0, "param0", (results[1] > minStartValue) ? results[1] : minStartValue, 0.1, 0, 0);
1088 //minuit->SetParameter(0, "param0", 0, 0, 0, 0);
1090 for (Int_t i=0; i<fgkMaxInput; ++i)
1092 (*fgCurrentESDVector)[i] = measured->GetBinContent(i+1);
1093 if (measured->GetBinError(i+1) > 0)
1094 (*fgCorrelationCovarianceMatrix)(i, i) = (Double_t) 1e-6 / measured->GetBinError(i+1) / measured->GetBinError(i+1);
1096 if ((*fgCorrelationCovarianceMatrix)(i, i) > 1e7)
1097 (*fgCorrelationCovarianceMatrix)(i, i) = 0;
1102 MinuitFitFunction(dummy, 0, chi2, results, 0);
1104 printf("Chi2 of initial parameters is = %f\n", chi2);
1112 // first param is number of iterations, second is precision....
1114 //arglist[1] = 1e-5;
1115 //minuit->ExecuteCommand("SCAN", arglist, 0);
1116 Int_t status = minuit->ExecuteCommand("MIGRAD", arglist, 1);
1117 printf("MINUIT status is %d\n", status);
1118 //minuit->ExecuteCommand("MIGRAD", arglist, 1);
1119 //minuit->ExecuteCommand("MIGRAD", arglist, 1);
1120 //printf("!!!!!!!!!!!!!! MIGRAD finished: Starting MINOS !!!!!!!!!!!!!!");
1121 //minuit->ExecuteCommand("MINOS", arglist, 0);
1123 for (Int_t i=0; i<fgNParamsMinuit; ++i)
1125 if (aEfficiency->GetBinContent(i+1) > 0)
1127 results[i] = minuit->GetParameter(i);
1128 result->SetBinContent(i+1, results[i] * results[i] / aEfficiency->GetBinContent(i+1));
1129 // error is : (relError) * (value) = (minuit->GetParError(i) / minuit->GetParameter(i)) * (minuit->GetParameter(i) * minuit->GetParameter(i))
1130 result->SetBinError(i+1, minuit->GetParError(i) * results[i] / aEfficiency->GetBinContent(i+1));
1134 result->SetBinContent(i+1, 0);
1135 result->SetBinError(i+1, 0);
1145 //____________________________________________________________________
1146 Int_t AliMultiplicityCorrection::ApplyMinuitFit(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Bool_t check, TH1* initialConditions)
1149 // correct spectrum using minuit chi2 method
1151 // for description of parameters, see UnfoldWithMinuit
1154 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1155 SetupCurrentHists(inputRange, fullPhaseSpace, eventType, fgCreateBigBin);
1157 return UnfoldWithMinuit(fCurrentCorrelation, fCurrentEfficiency, fCurrentESD, initialConditions, fMultiplicityESDCorrected[correlationID], check);
1160 //____________________________________________________________________
1161 void AliMultiplicityCorrection::ApplyNBDFit(Int_t inputRange, Bool_t fullPhaseSpace)
1164 // correct spectrum using minuit chi2 method applying a NBD fit
1167 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1169 SetupCurrentHists(inputRange, fullPhaseSpace, kTrVtx, kFALSE);
1171 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
1173 fgCorrelationMatrix = new TMatrixD(fgkMaxParams, fgkMaxParams);
1174 fgCorrelationCovarianceMatrix = new TMatrixD(fgkMaxParams, fgkMaxParams);
1175 fgCurrentESDVector = new TVectorD(fgkMaxParams);
1177 // normalize correction for given nPart
1178 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
1180 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
1183 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
1186 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
1187 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
1189 if (i <= fgkMaxParams && j <= fgkMaxParams)
1190 (*fgCorrelationMatrix)(j-1, i-1) = fCurrentCorrelation->GetBinContent(i, j);
1194 for (Int_t i=0; i<fgkMaxParams; ++i)
1196 (*fgCurrentESDVector)[i] = fCurrentESD->GetBinContent(i+1);
1197 if (fCurrentESD->GetBinError(i+1) > 0)
1198 (*fgCorrelationCovarianceMatrix)(i, i) = 1.0 / (fCurrentESD->GetBinError(i+1) * fCurrentESD->GetBinError(i+1));
1201 // Create NBD function
1204 fgNBD = new TF1("nbd", "[0] * TMath::Binomial([2]+TMath::Nint(x)-1, [2]-1) * pow([1] / ([1]+[2]), TMath::Nint(x)) * pow(1 + [1]/[2], -[2])", 0, 250);
1205 fgNBD->SetParNames("scaling", "averagen", "k");
1208 // Initialize TMinuit via generic fitter interface
1209 TVirtualFitter *minuit = TVirtualFitter::Fitter(0, 3);
1211 minuit->SetFCN(MinuitNBD);
1212 minuit->SetParameter(0, "param0", 1, 0.1, 0.001, fCurrentESD->GetMaximum() * 1000);
1213 minuit->SetParameter(1, "param1", 10, 1, 0.001, 1000);
1214 minuit->SetParameter(2, "param2", 2, 1, 0.001, 1000);
1216 Double_t arglist[100];
1218 minuit->ExecuteCommand("SET PRINT", arglist, 1);
1219 minuit->ExecuteCommand("MIGRAD", arglist, 0);
1220 //minuit->ExecuteCommand("MINOS", arglist, 0);
1222 fgNBD->SetParameters(minuit->GetParameter(0), minuit->GetParameter(1), minuit->GetParameter(2));
1224 for (Int_t i=0; i<fgkMaxParams; ++i)
1226 printf("%d : %f\n", i, fgNBD->Eval(i));
1227 if (fgNBD->Eval(i) > 0)
1229 fMultiplicityESDCorrected[correlationID]->SetBinContent(i+1, fgNBD->Eval(i));
1230 fMultiplicityESDCorrected[correlationID]->SetBinError(i+1, 0);
1235 //____________________________________________________________________
1236 void AliMultiplicityCorrection::DrawHistograms()
1239 // draws the histograms of this class
1244 TCanvas* canvas1 = new TCanvas("fMultiplicityESD", "fMultiplicityESD", 900, 600);
1245 canvas1->Divide(3, 2);
1246 for (Int_t i = 0; i < kESDHists; ++i)
1249 fMultiplicityESD[i]->DrawCopy("COLZ");
1250 printf("%d --> %f\n", i, (Float_t) fMultiplicityESD[i]->ProjectionY()->GetMean());
1255 TCanvas* canvas2 = new TCanvas("fMultiplicityMC", "fMultiplicityMC", 900, 600);
1256 canvas2->Divide(3, 2);
1257 for (Int_t i = 0; i < kMCHists; ++i)
1260 fMultiplicityVtx[i]->DrawCopy("COLZ");
1261 printf("%d --> %f\n", i, fMultiplicityVtx[i]->ProjectionY()->GetMean());
1264 TCanvas* canvas3 = new TCanvas("fCorrelation", "fCorrelation", 900, 900);
1265 canvas3->Divide(3, 3);
1266 for (Int_t i = 0; i < kCorrHists; ++i)
1269 TH3* hist = dynamic_cast<TH3*> (fCorrelation[i]->Clone());
1270 for (Int_t y=1; y<=hist->GetYaxis()->GetNbins(); ++y)
1272 for (Int_t z=1; z<=hist->GetZaxis()->GetNbins(); ++z)
1274 hist->SetBinContent(0, y, z, 0);
1275 hist->SetBinContent(hist->GetXaxis()->GetNbins()+1, y, z, 0);
1278 TH1* proj = hist->Project3D("zy");
1279 proj->DrawCopy("COLZ");
1283 //____________________________________________________________________
1284 void AliMultiplicityCorrection::DrawComparison(const char* name, Int_t inputRange, Bool_t fullPhaseSpace, Bool_t /*normalizeESD*/, TH1* mcHist, Bool_t simple)
1288 Int_t esdCorrId = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1291 tmpStr.Form("%s_DrawComparison_%d", name, esdCorrId);
1293 if (fMultiplicityESDCorrected[esdCorrId]->Integral() == 0)
1295 printf("ERROR. Unfolded histogram is empty\n");
1299 //regain measured distribution used for unfolding, because the bins at high mult. were modified in SetupCurrentHists
1300 fCurrentESD = fMultiplicityESD[esdCorrId]->ProjectionY();
1301 fCurrentESD->Sumw2();
1302 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
1304 // normalize unfolded result to 1
1305 fMultiplicityESDCorrected[esdCorrId]->Scale(1.0 / fMultiplicityESDCorrected[esdCorrId]->Integral());
1307 //fCurrentESD->Scale(mcHist->Integral(2, 200));
1310 /*TH1* ratio = (TH1*) fMultiplicityESDCorrected[esdCorrId]->Clone("ratio");
1311 ratio->Divide(mcHist);
1312 ratio->Draw("HIST");
1313 ratio->Fit("pol0", "W0", "", 20, 120);
1314 Float_t scalingFactor = ratio->GetFunction("pol0")->GetParameter(0);
1316 mcHist->Scale(scalingFactor);*/
1318 // find bin with <= 50 entries. this is used as limit for the chi2 calculation
1319 Int_t mcBinLimit = 0;
1320 for (Int_t i=20; i<mcHist->GetNbinsX(); ++i)
1322 if (mcHist->GetBinContent(i) > 50)
1329 Printf("AliMultiplicityCorrection::DrawComparison: MC bin limit is %d", mcBinLimit);
1333 if (mcHist->Integral() > 0)
1334 mcHist->Scale(1.0 / mcHist->Integral());
1336 // calculate residual
1338 // for that we convolute the response matrix with the gathered result
1339 // if normalizeESD is not set, the histogram is already normalized, this needs to be passed to CalculateMultiplicityESD
1340 TH1* tmpESDEfficiencyRecorrected = (TH1*) fMultiplicityESDCorrected[esdCorrId]->Clone("tmpESDEfficiencyRecorrected");
1341 tmpESDEfficiencyRecorrected->Multiply(fCurrentEfficiency);
1342 TH2* convoluted = CalculateMultiplicityESD(tmpESDEfficiencyRecorrected, esdCorrId);
1343 TH1* convolutedProj = convoluted->ProjectionY("convolutedProj", -1, -1, "e");
1344 if (convolutedProj->Integral() > 0)
1346 convolutedProj->Scale(1.0 / convolutedProj->Integral());
1349 printf("ERROR: convolutedProj is empty. Something went wrong calculating the convoluted histogram.\n");
1351 TH1* residual = (TH1*) convolutedProj->Clone("residual");
1352 residual->SetTitle("Residuals;Ntracks;(folded unfolded measured - measured) / e");
1354 residual->Add(fCurrentESD, -1);
1355 //residual->Divide(residual, fCurrentESD, 1, 1, "B");
1357 TH1* residualHist = new TH1F("residualHist", "residualHist", 51, -5, 5);
1361 for (Int_t i=1; i<=residual->GetNbinsX(); ++i)
1363 if (fCurrentESD->GetBinError(i) > 0)
1365 Float_t value = residual->GetBinContent(i) / fCurrentESD->GetBinError(i);
1366 if (i > 1 && i <= fLastBinLimit)
1367 chi2 += value * value;
1368 Printf("%d --> %f (%f)", i, value * value, chi2);
1369 residual->SetBinContent(i, value);
1370 residualHist->Fill(value);
1374 //printf("Residual bin %d set to 0\n", i);
1375 residual->SetBinContent(i, 0);
1377 convolutedProj->SetBinError(i, 0);
1378 residual->SetBinError(i, 0);
1380 fLastChi2Residuals = chi2;
1382 new TCanvas; residualHist->DrawCopy();
1384 //residualHist->Fit("gaus", "N");
1385 //delete residualHist;
1387 printf("Difference (Residuals) is %f for bin 2-%d\n", fLastChi2Residuals, fLastBinLimit);
1389 TCanvas* canvas1 = 0;
1392 canvas1 = new TCanvas(tmpStr, tmpStr, 900, 400);
1393 canvas1->Divide(2, 1);
1397 canvas1 = new TCanvas(tmpStr, tmpStr, 1200, 1200);
1398 canvas1->Divide(2, 3);
1402 TH1* proj = (TH1*) mcHist->Clone("proj");
1404 proj->GetXaxis()->SetRangeUser(0, 200);
1405 proj->SetTitle(";true multiplicity;Entries");
1406 proj->SetStats(kFALSE);
1408 fMultiplicityESDCorrected[esdCorrId]->SetLineColor(2);
1410 if (proj->GetEntries() > 0) {
1411 proj->DrawCopy("HIST");
1412 fMultiplicityESDCorrected[esdCorrId]->DrawCopy("SAME HIST E");
1415 fMultiplicityESDCorrected[esdCorrId]->DrawCopy("HIST E");
1419 TLegend* legend = new TLegend(0.3, 0.8, 0.93, 0.93);
1420 legend->AddEntry(proj, "true distribution");
1421 legend->AddEntry(fMultiplicityESDCorrected[esdCorrId], "unfolded distribution");
1422 legend->SetFillColor(0);
1424 // unfortunately does not work. maybe a bug? --> legend->SetTextSizePixels(14);
1429 fCurrentESD->GetXaxis()->SetRangeUser(0, 200);
1430 //fCurrentESD->SetLineColor(2);
1431 fCurrentESD->SetTitle(";measured multiplicity;Entries");
1432 fCurrentESD->SetStats(kFALSE);
1433 fCurrentESD->DrawCopy("HIST E");
1435 convolutedProj->SetLineColor(2);
1436 //proj2->SetMarkerColor(2);
1437 //proj2->SetMarkerStyle(5);
1438 convolutedProj->DrawCopy("HIST SAME");
1440 legend = new TLegend(0.3, 0.8, 0.93, 0.93);
1441 legend->AddEntry(fCurrentESD, "measured distribution");
1442 legend->AddEntry(convolutedProj, "R #otimes unfolded distribution");
1443 legend->SetFillColor(0);
1446 //TH1* diffMCUnfolded = dynamic_cast<TH1*> (proj->Clone("diffMCUnfolded"));
1447 //diffMCUnfolded->Add(fMultiplicityESDCorrected[esdCorrId], -1);
1451 fLastChi2MCLimit = 0;
1453 for (Int_t i=2; i<=200; ++i)
1455 if (proj->GetBinContent(i) != 0)
1457 Float_t value = (proj->GetBinContent(i) - fMultiplicityESDCorrected[esdCorrId]->GetBinContent(i)) / proj->GetBinContent(i);
1458 chi2 += value * value;
1459 chi += TMath::Abs(value);
1461 //printf("%d %f\n", i, chi);
1464 fLastChi2MCLimit = i;
1475 for (Int_t i=1; i<=diffMCUnfolded->GetNbinsX(); ++i)
1477 if (fMultiplicityESDCorrected[esdCorrId]->GetBinError(i) > 0)
1479 Double_t value = diffMCUnfolded->GetBinContent(i) / fMultiplicityESDCorrected[esdCorrId]->GetBinError(i);
1481 value = 1e8; //prevent arithmetic exception
1482 else if (value < -1e8)
1486 chi2 += value * value;
1487 chi += TMath::Abs(value);
1489 diffMCUnfolded->SetBinContent(i, value);
1493 //printf("diffMCUnfolded bin %d set to 0\n", i);
1494 diffMCUnfolded->SetBinContent(i, 0);
1497 fLastChi2MCLimit = i;
1504 printf("limits %d %d\n", fLastChi2MCLimit, limit);
1505 fLastChi2MCLimit = limit;
1507 printf("Difference (from MC) is %f for bin 2-150. Limit is %d.\n", fLastChi2MC, fLastChi2MCLimit);*/
1513 diffMCUnfolded->SetTitle("#chi^{2};Npart;(MC - Unfolded) / e(unfolded)");
1514 //diffMCUnfolded->GetYaxis()->SetRangeUser(-20, 20);
1515 diffMCUnfolded->GetXaxis()->SetRangeUser(0, 200);
1516 diffMCUnfolded->DrawCopy("HIST");
1518 TH1F* fluctuation = new TH1F("fluctuation", "fluctuation", 20, -5, 5);
1519 for (Int_t i=20; i<=diffMCUnfolded->GetNbinsX(); ++i)
1520 fluctuation->Fill(diffMCUnfolded->GetBinContent(i));
1522 //new TCanvas; fluctuation->DrawCopy();
1523 delete fluctuation;*/
1525 /*TLegend* legend = new TLegend(0.6, 0.7, 0.85, 0.85);
1526 legend->AddEntry(fMultiplicityESDCorrected, "ESD corrected");
1527 legend->AddEntry(fMultiplicityMC, "MC");
1528 legend->AddEntry(fMultiplicityESD, "ESD");
1532 //residual->GetYaxis()->SetRangeUser(-0.2, 0.2);
1533 residual->GetXaxis()->SetRangeUser(0, 200);
1534 residual->DrawCopy();
1538 TH1* ratio = (TH1*) fMultiplicityESDCorrected[esdCorrId]->Clone("ratio");
1539 ratio->Divide(mcHist);
1540 ratio->SetTitle("Ratio;true multiplicity;Unfolded / MC");
1541 ratio->GetYaxis()->SetRangeUser(0.5, 1.5);
1542 ratio->GetXaxis()->SetRangeUser(0, 200);
1543 ratio->SetStats(kFALSE);
1544 ratio->Draw("HIST");
1546 Double_t ratioChi2 = 0;
1548 fLastChi2MCLimit = 0;
1549 for (Int_t i=2; i<=150; ++i)
1551 Float_t value = ratio->GetBinContent(i) - 1;
1553 value = 1e8; //prevent arithmetic exception
1554 else if (value < -1e8)
1557 ratioChi2 += value * value;
1558 fRatioAverage += TMath::Abs(value);
1560 if (ratioChi2 < 0.1)
1561 fLastChi2MCLimit = i;
1563 fRatioAverage /= 149;
1565 printf("Sum over (ratio-1)^2 (2..150) is %f; average of |ratio-1| is %f\n", ratioChi2, fRatioAverage);
1567 fLastChi2MC = ratioChi2;
1571 const Int_t kFFT = 128;
1572 Double_t fftReal[kFFT];
1573 Double_t fftImag[kFFT];
1575 for (Int_t i=0; i<kFFT; ++i)
1577 fftReal[i] = ratio->GetBinContent(i+1+10);
1579 //fftReal[i] = cos(TMath::Pi() * 5 * 2 * i / 128);
1583 FFT(-1, TMath::Nint(log(kFFT) / log(2)), fftReal, fftImag);
1585 TH1* fftResult = (TH1*) ratio->Clone("fftResult");
1586 fftResult->SetTitle("FFT;true multiplicity;coeff. (10...137)");
1587 TH1* fftResult2 = (TH1*) ratio->Clone("fftResult2");
1588 TH1* fftResult3 = (TH1*) ratio->Clone("fftResult3");
1590 fftResult2->Reset();
1591 fftResult3->Reset();
1592 fftResult->GetYaxis()->UnZoom();
1593 fftResult2->GetYaxis()->UnZoom();
1594 fftResult3->GetYaxis()->UnZoom();
1596 //Printf("AFTER FFT");
1597 for (Int_t i=0; i<kFFT; ++i)
1599 //Printf("%d: %f", i, fftReal[i]);
1600 fftResult->SetBinContent(i+1, fftReal[i]);
1601 /*if (i != 0 && TMath::Abs(fftReal[i]) > 0.5)
1603 Printf("Nulled %d", i);
1608 fftResult->SetLineColor(1);
1609 fftResult->DrawCopy();
1613 for (Int_t i=0; i<kFFT; ++i)
1615 //Printf("%d: %f", i, fftImag[i]);
1616 fftResult2->SetBinContent(i+1, fftImag[i]);
1618 fftResult3->SetBinContent(i+1, TMath::Sqrt(fftReal[i] * fftReal[i] + fftImag[i] * fftImag[i]));
1621 fftResult2->SetLineColor(2);
1622 fftResult2->DrawCopy("SAME");
1624 fftResult3->SetLineColor(4);
1625 fftResult3->DrawCopy("SAME");
1627 for (Int_t i=1; i<kFFT - 1; ++i)
1629 if (TMath::Sqrt(fftReal[i] * fftReal[i] + fftImag[i] * fftImag[i]) > 3)
1637 //fftReal[i] = (fftReal[i-1] + fftReal[i+1]) / 2;
1638 //fftImag[i] = (fftImag[i-1] + fftImag[i+1]) / 2;
1639 //Printf("Nulled %d to %f %f", i, fftReal[i], fftImag[i]);
1643 FFT(1, TMath::Nint(log(kFFT) / log(2)), fftReal, fftImag);
1645 TH1* fftResult4 = (TH1*) fftResult3->Clone("fftResult4");
1646 fftResult4->Reset();
1648 //Printf("AFTER BACK-TRAFO");
1649 for (Int_t i=0; i<kFFT; ++i)
1651 //Printf("%d: %f", i, fftReal[i]);
1652 fftResult4->SetBinContent(i+1+10, fftReal[i]);
1656 fftResult4->SetLineColor(4);
1657 fftResult4->DrawCopy("SAME");
1659 // plot (MC - Unfolded) / error (MC)
1662 TH1* diffMCUnfolded2 = dynamic_cast<TH1*> (proj->Clone("diffMCUnfolded2"));
1663 diffMCUnfolded2->Add(fMultiplicityESDCorrected[esdCorrId], -1);
1665 Int_t ndfQual[kQualityRegions];
1666 for (Int_t region=0; region<kQualityRegions; ++region)
1668 fQuality[region] = 0;
1669 ndfQual[region] = 0;
1673 Double_t newChi2 = 0;
1674 Double_t newChi2Limit150 = 0;
1676 for (Int_t i=1; i<=TMath::Min(diffMCUnfolded2->GetNbinsX(), fgkMaxParams+1); ++i)
1679 if (proj->GetBinError(i) > 0)
1681 value = diffMCUnfolded2->GetBinContent(i) / proj->GetBinError(i);
1682 newChi2 += value * value;
1683 if (i > 1 && i <= mcBinLimit)
1684 newChi2Limit150 += value * value;
1687 for (Int_t region=0; region<kQualityRegions; ++region)
1688 if (diffMCUnfolded2->GetXaxis()->GetBinCenter(i) >= fgQualityRegionsB[region] - 0.1 && diffMCUnfolded2->GetXaxis()->GetBinCenter(i) <= fgQualityRegionsE[region] + 0.1) // 0.1 to avoid e.g. 3.9999 < 4 problem
1690 fQuality[region] += TMath::Abs(value);
1695 diffMCUnfolded2->SetBinContent(i, value);
1698 // normalize region to the number of entries
1699 for (Int_t region=0; region<kQualityRegions; ++region)
1701 if (ndfQual[region] > 0)
1702 fQuality[region] /= ndfQual[region];
1703 Printf("Quality parameter %d (%d <= mult <= %d) is %f with %d df", region, fgQualityRegionsB[region], fgQualityRegionsE[region], fQuality[region], ndfQual[region]);
1708 // TODO another FAKE
1709 fLastChi2MC = newChi2Limit150 / (mcBinLimit - 1);
1710 Printf("Chi2 (2..%d) from (MC - Unfolded) / e(MC) is: %.2f ndf is %d --> chi2 / ndf = %.2f", mcBinLimit, newChi2Limit150, mcBinLimit - 1, fLastChi2MC);
1715 Printf("Chi2 (full range) from (MC - Unfolded) / e(MC) is: %.2f ndf is %d --> chi2 / ndf = %.2f", newChi2, ndf, ((ndf > 0) ? newChi2 / ndf : -1));
1717 diffMCUnfolded2->SetTitle("#chi^{2};Npart;(MC - Unfolded) / e(MC)");
1718 //diffMCUnfolded->GetYaxis()->SetRangeUser(-20, 20);
1719 diffMCUnfolded2->GetXaxis()->SetRangeUser(0, 200);
1720 diffMCUnfolded2->DrawCopy("HIST");
1723 canvas1->SaveAs(Form("%s.gif", canvas1->GetName()));
1726 //____________________________________________________________________
1727 void AliMultiplicityCorrection::FFT(Int_t dir, Int_t m, Double_t *x, Double_t *y)
1729 /*-------------------------------------------------------------------------
1730 This computes an in-place complex-to-complex FFT
1731 x and y are the real and imaginary arrays of 2^m points.
1732 dir = 1 gives forward transform
1733 dir = -1 gives reverse transform
1738 1 \ - j k 2 pi n / N
1739 X(n) = --- > x(k) e = forward transform
1748 X(n) = > x(k) e = forward transform
1754 Long_t nn, i, i1, j, k, i2, l, l1, l2;
1755 Double_t c1, c2, tx, ty, t1, t2, u1, u2, z;
1757 /* Calculate the number of points */
1759 for (i = 0; i < m; i++)
1762 /* Do the bit reversal */
1765 for (i= 0; i < nn - 1; i++) {
1782 /* Compute the FFT */
1786 for (l = 0; l < m; l++) {
1791 for (j = 0;j < l1; j++) {
1792 for (i = j; i < nn; i += l2) {
1794 t1 = u1 * x[i1] - u2 * y[i1];
1795 t2 = u1 * y[i1] + u2 * x[i1];
1801 z = u1 * c1 - u2 * c2;
1802 u2 = u1 * c2 + u2 * c1;
1805 c2 = TMath::Sqrt((1.0 - c1) / 2.0);
1808 c1 = TMath::Sqrt((1.0 + c1) / 2.0);
1811 /* Scaling for forward transform */
1813 for (i=0;i<nn;i++) {
1814 x[i] /= (Double_t)nn;
1815 y[i] /= (Double_t)nn;
1820 //____________________________________________________________________
1821 void AliMultiplicityCorrection::GetComparisonResults(Float_t* mc, Int_t* mcLimit, Float_t* residuals, Float_t* ratioAverage) const
1823 // Returns the chi2 between the MC and the unfolded ESD as well as between the ESD and the folded unfolded ESD
1824 // These values are computed during DrawComparison, thus this function picks up the
1830 *mcLimit = fLastChi2MCLimit;
1832 *residuals = fLastChi2Residuals;
1834 *ratioAverage = fRatioAverage;
1837 //____________________________________________________________________
1838 TH2F* AliMultiplicityCorrection::GetMultiplicityMC(Int_t i, EventType eventType)
1841 // returns the corresponding MC spectrum
1846 case kTrVtx : return fMultiplicityVtx[i]; break;
1847 case kMB : return fMultiplicityMB[i]; break;
1848 case kINEL : return fMultiplicityINEL[i]; break;
1854 //____________________________________________________________________
1855 TH1* AliMultiplicityCorrection::CalculateStdDev(TH1** results, Int_t max)
1857 // calculate standard deviation of (results[0] - results[k]) k=1...max-1
1858 // per bin one gets: sigma(r[0] - r[n]) / r[0]
1860 TH1* standardDeviation = (TH1*) results[0]->Clone("standardDeviation");
1861 standardDeviation->Reset();
1863 for (Int_t x=1; x<=results[0]->GetNbinsX(); x++)
1865 if (results[0]->GetBinContent(x) > 0)
1867 Double_t average = 0;
1868 for (Int_t n=1; n<max; ++n)
1869 average += results[n]->GetBinContent(x) - results[0]->GetBinContent(x);
1872 Double_t variance = 0;
1873 for (Int_t n=1; n<max; ++n)
1875 Double_t value = results[n]->GetBinContent(x) - results[0]->GetBinContent(x) - average;
1876 variance += value * value;
1880 Double_t standardDev = TMath::Sqrt(variance);
1881 standardDeviation->SetBinContent(x, standardDev / results[0]->GetBinContent(x));
1882 //Printf("sigma_%d is %f value %f --> error %f", x, standardDev, results[0]->GetBinContent(x), standardDev / results[0]->GetBinContent(x));
1886 return standardDeviation;
1889 //____________________________________________________________________
1890 TH1* AliMultiplicityCorrection::StatisticalUncertainty(MethodType methodType, Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Bool_t randomizeMeasured, Bool_t randomizeResponse, TH1* compareTo)
1893 // evaluates the uncertainty that arises from the non-infinite statistics in the response matrix
1894 // the function unfolds the spectrum using the default response matrix and several modified ones
1895 // the modified ones are created by randomizing each cell using poisson statistics with the mean = bin value
1896 // these unfolded results are compared to the first result gained with the default response OR to the histogram given
1897 // in <compareTo> (optional)
1899 // returns the error assigned to the measurement
1902 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1904 // initialize seed with current time
1905 gRandom->SetSeed(0);
1907 const Int_t kErrorIterations = 150;
1910 TH1* firstResult = 0;
1912 TH1** results = new TH1*[kErrorIterations];
1914 for (Int_t n=0; n<kErrorIterations; ++n)
1916 Printf("Iteration %d of %d...", n, kErrorIterations);
1918 // only done for chi2 minimization
1919 Bool_t createBigBin = kFALSE;
1920 if (methodType == kChi2Minimization)
1921 createBigBin = kTRUE;
1923 SetupCurrentHists(inputRange, fullPhaseSpace, eventType, createBigBin);
1925 TH1* measured = (TH1*) fCurrentESD->Clone("measured");
1929 if (randomizeResponse)
1931 // randomize response matrix
1932 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
1933 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
1934 fCurrentCorrelation->SetBinContent(i, j, gRandom->Poisson(fCurrentCorrelation->GetBinContent(i, j)));
1937 if (randomizeMeasured)
1939 // randomize measured spectrum
1940 for (Int_t x=1; x<=measured->GetNbinsX(); x++) // mult. axis
1942 Int_t randomValue = gRandom->Poisson(fCurrentESD->GetBinContent(x));
1943 measured->SetBinContent(x, randomValue);
1944 measured->SetBinError(x, TMath::Sqrt(randomValue));
1949 // only for bayesian method we have to do it before the call to Unfold...
1950 if (methodType == kBayesian)
1952 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
1954 // with this it is normalized to 1
1955 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
1957 // with this normalized to the given efficiency
1958 if (fCurrentEfficiency->GetBinContent(i) > 0)
1959 sum /= fCurrentEfficiency->GetBinContent(i);
1963 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
1967 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
1968 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
1972 fCurrentCorrelation->SetBinContent(i, j, 0);
1973 fCurrentCorrelation->SetBinError(i, j, 0);
1980 if (n == 0 && compareTo)
1982 // in this case we just store the histogram we want to compare to
1983 result = (TH1*) compareTo->Clone("compareTo");
1988 result = (TH1*) fMultiplicityESDCorrected[correlationID]->Clone(Form("result_%d", n));
1990 Int_t returnCode = -1;
1991 if (methodType == kChi2Minimization)
1993 returnCode = UnfoldWithMinuit(fCurrentCorrelation, fCurrentEfficiency, measured, 0, result, kFALSE);
1995 else if (methodType == kBayesian)
1996 returnCode = UnfoldWithBayesian(fCurrentCorrelation, fCurrentEfficiency, measured, 0, result, fgBayesianSmoothing, fgBayesianIterations);
1998 if (returnCode != 0)
2003 result->Scale(1.0 / result->Integral());
2007 firstResult = (TH1*) result->Clone("firstResult");
2009 maxError = (TH1*) result->Clone("maxError");
2015 TH1* ratio = (TH1*) firstResult->Clone("ratio");
2016 ratio->Divide(result);
2018 // find max. deviation
2019 for (Int_t x=1; x<=ratio->GetNbinsX(); x++)
2020 maxError->SetBinContent(x, TMath::Max(maxError->GetBinContent(x), TMath::Abs(1 - ratio->GetBinContent(x))));
2025 results[n] = result;
2028 // find covariance matrix
2029 // results[n] is X_x
2030 // cov. matrix is M_xy = E ( (X_x - E(X_x)) * (X_y - E(X_y))), with E() = expectation value
2032 Int_t nBins = results[0]->GetNbinsX();
2033 Float_t lowEdge = results[0]->GetXaxis()->GetBinLowEdge(1);
2034 Float_t upEdge = results[0]->GetXaxis()->GetBinUpEdge(nBins);
2036 // find average, E(X)
2037 TProfile* average = new TProfile("average", "average", nBins, lowEdge, upEdge);
2038 for (Int_t n=1; n<kErrorIterations; ++n)
2039 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2040 average->Fill(results[n]->GetXaxis()->GetBinCenter(x), results[n]->GetBinContent(x));
2041 //new TCanvas; average->DrawClone();
2044 TProfile2D* covMatrix = new TProfile2D("covMatrix", "covMatrix", nBins, lowEdge, upEdge, nBins, lowEdge, upEdge);
2046 for (Int_t n=1; n<kErrorIterations; ++n)
2047 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2048 for (Int_t y=1; y<=results[n]->GetNbinsX(); y++)
2050 // (X_x - E(X_x)) * (X_y - E(X_y)
2051 Float_t cov = (results[n]->GetBinContent(x) - average->GetBinContent(x)) * (results[n]->GetBinContent(y) - average->GetBinContent(y));
2052 covMatrix->Fill(results[n]->GetXaxis()->GetBinCenter(x), results[n]->GetXaxis()->GetBinCenter(y), cov);
2054 new TCanvas; covMatrix->DrawClone("COLZ");
2056 // // fill 2D histogram that contains deviation from first
2057 // TH2F* deviations = new TH2F("deviations", "deviations", nBins, lowEdge, upEdge, 1000, -0.01, 0.01);
2058 // for (Int_t n=1; n<kErrorIterations; ++n)
2059 // for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2060 // deviations->Fill(results[n]->GetXaxis()->GetBinCenter(x), results[n]->GetBinContent(x) - results[0]->GetBinContent(x));
2061 // //new TCanvas; deviations->DrawCopy("COLZ");
2063 // // get standard deviation "by hand"
2064 // for (Int_t x=1; x<=nBins; x++)
2066 // if (results[0]->GetBinContent(x) > 0)
2068 // TH1* proj = deviations->ProjectionY("projRMS", x, x, "e");
2069 // Float_t standardDev = proj->GetRMS(); // this is standard deviation in fact
2070 // //standardDeviation->SetBinContent(x, standardDev / results[0]->GetBinContent(x));
2071 // Printf("sigma_%d is %f value %f --> error %f", x, standardDev, results[0]->GetBinContent(x), standardDev / results[0]->GetBinContent(x));
2075 TH1* standardDeviation = CalculateStdDev(results, kErrorIterations);
2077 // compare maxError to RMS of profile (variable name: average)
2078 // first: calculate rms in percent of value
2079 TH1* rmsError = (TH1*) maxError->Clone("rmsError");
2082 // enable error to be standard deviation (see http://root.cern.ch/root/html/TProfile.html#TProfile:SetErrorOption)
2083 average->SetErrorOption("s");
2084 for (Int_t x=1; x<=rmsError->GetNbinsX(); x++)
2085 if (average->GetBinContent(x) > 0)
2086 rmsError->SetBinContent(x, average->GetBinError(x) / average->GetBinContent(x));
2088 // find maxError deviation from average (not from "first result"/mc as above)
2089 TH1* maxError2 = (TH1*) maxError->Clone("maxError2");
2091 for (Int_t n=1; n<kErrorIterations; ++n)
2092 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2093 if (average->GetBinContent(x) > 0)
2094 maxError2->SetBinContent(x, TMath::Max(maxError2->GetBinContent(x), TMath::Abs((results[n]->GetBinContent(x) - average->GetBinContent(x)) / average->GetBinContent(x))));
2096 //new TCanvas; maxError2->DrawCopy(); rmsError->SetLineColor(2); rmsError->DrawCopy("SAME"); standardDeviation->SetLineColor(3); standardDeviation->DrawCopy("SAME");
2098 // plot difference between average and MC/first result
2099 TH1* averageFirstRatio = (TH1*) results[0]->Clone("averageFirstRatio");
2100 averageFirstRatio->Reset();
2101 averageFirstRatio->Divide(results[0], average);
2103 //new TCanvas; results[0]->DrawCopy(); average->SetLineColor(2); average->DrawClone("SAME");
2104 //new TCanvas; averageFirstRatio->DrawCopy();
2107 for (Int_t n=0; n<kErrorIterations; ++n)
2111 // fill into result histogram
2112 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); ++i)
2113 fMultiplicityESDCorrected[correlationID]->SetBinContent(i, firstResult->GetBinContent(i));
2115 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); ++i)
2116 fMultiplicityESDCorrected[correlationID]->SetBinError(i, maxError->GetBinContent(i) * fMultiplicityESDCorrected[correlationID]->GetBinContent(i));
2118 return standardDeviation;
2121 //____________________________________________________________________
2122 void AliMultiplicityCorrection::ApplyBayesianMethod(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Float_t regPar, Int_t nIterations, TH1* initialConditions, Bool_t determineError)
2125 // correct spectrum using bayesian method
2128 // initialize seed with current time
2129 gRandom->SetSeed(0);
2131 SetupCurrentHists(inputRange, fullPhaseSpace, eventType, kFALSE);
2133 // normalize correction for given nPart
2134 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2136 // with this it is normalized to 1
2137 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
2139 // with this normalized to the given efficiency
2140 if (fCurrentEfficiency->GetBinContent(i) > 0)
2141 sum /= fCurrentEfficiency->GetBinContent(i);
2145 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
2149 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
2150 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
2154 fCurrentCorrelation->SetBinContent(i, j, 0);
2155 fCurrentCorrelation->SetBinError(i, j, 0);
2160 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
2162 if (UnfoldWithBayesian(fCurrentCorrelation, fCurrentEfficiency, fCurrentESD, initialConditions, fMultiplicityESDCorrected[correlationID], regPar, nIterations) != 0)
2165 if (!determineError)
2167 Printf("AliMultiplicityCorrection::ApplyBayesianMethod: WARNING: No errors calculated.");
2171 // evaluate errors, this is done by randomizing the measured spectrum following Poission statistics
2172 // this (new) measured spectrum is then unfolded and the different to the result from the "real" measured
2173 // spectrum calculated. This is performed N times and the sigma is taken as the statistical
2174 // error of the unfolding method itself.
2176 const Int_t kErrorIterations = 20;
2178 printf("Spectrum unfolded. Determining error (%d iterations)...\n", kErrorIterations);
2180 TH1* randomized = (TH1*) fCurrentESD->Clone("randomized");
2181 TH1* resultArray[kErrorIterations+1];
2182 for (Int_t n=0; n<kErrorIterations; ++n)
2184 // randomize the content of clone following a poisson with the mean = the value of that bin
2185 for (Int_t x=1; x<=randomized->GetNbinsX(); x++) // mult. axis
2187 Int_t randomValue = gRandom->Poisson(fCurrentESD->GetBinContent(x));
2188 //printf("%d --> %d\n", fCurrentESD->GetBinContent(x), randomValue);
2189 randomized->SetBinContent(x, randomValue);
2190 randomized->SetBinError(x, TMath::Sqrt(randomValue));
2193 TH1* result2 = (TH1*) fMultiplicityESDCorrected[correlationID]->Clone("result2");
2195 if (UnfoldWithBayesian(fCurrentCorrelation, fCurrentEfficiency, randomized, initialConditions, result2, regPar, nIterations) != 0)
2198 result2->Scale(1.0 / result2->Integral());
2200 resultArray[n+1] = result2;
2204 resultArray[0] = fMultiplicityESDCorrected[correlationID];
2205 TH1* error = CalculateStdDev(resultArray, kErrorIterations+1);
2207 for (Int_t n=0; n<kErrorIterations; ++n)
2208 delete resultArray[n+1];
2210 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); ++i)
2211 fMultiplicityESDCorrected[correlationID]->SetBinError(i, error->GetBinContent(i) * fMultiplicityESDCorrected[correlationID]->GetBinContent(i));
2216 //____________________________________________________________________
2217 Int_t AliMultiplicityCorrection::UnfoldWithBayesian(TH1* correlation, TH1* aEfficiency, TH1* measured, TH1* initialConditions, TH1* aResult, Float_t regPar, Int_t nIterations)
2220 // unfolds a spectrum
2223 if (measured->Integral() <= 0)
2225 Printf("AliMultiplicityCorrection::UnfoldWithBayesian: ERROR: The measured spectrum is empty");
2229 const Int_t kStartBin = 0;
2231 const Int_t kMaxM = fgkMaxInput; //<= fCurrentCorrelation->GetNbinsY(); // max measured axis
2232 const Int_t kMaxT = fgkMaxParams; //<= fCurrentCorrelation->GetNbinsX(); // max true axis
2234 // convergence limit: kMaxT * 0.001^2 = kMaxT * 1e-6 (e.g. 250 bins --> 2.5 e-4)
2235 const Double_t kConvergenceLimit = kMaxT * 1e-6;
2237 // store information in arrays, to increase processing speed (~ factor 5)
2238 Double_t measuredCopy[kMaxM];
2239 Double_t measuredError[kMaxM];
2240 Double_t prior[kMaxT];
2241 Double_t result[kMaxT];
2242 Double_t efficiency[kMaxT];
2244 Double_t response[kMaxT][kMaxM];
2245 Double_t inverseResponse[kMaxT][kMaxM];
2247 // for normalization
2248 Float_t measuredIntegral = measured->Integral();
2249 for (Int_t m=0; m<kMaxM; m++)
2251 measuredCopy[m] = measured->GetBinContent(m+1) / measuredIntegral;
2252 measuredError[m] = measured->GetBinError(m+1) / measuredIntegral;
2254 for (Int_t t=0; t<kMaxT; t++)
2256 response[t][m] = correlation->GetBinContent(t+1, m+1);
2257 inverseResponse[t][m] = 0;
2261 for (Int_t t=0; t<kMaxT; t++)
2263 efficiency[t] = aEfficiency->GetBinContent(t+1);
2264 prior[t] = measuredCopy[t];
2268 // pick prior distribution
2269 if (initialConditions)
2271 printf("Using different starting conditions...\n");
2272 // for normalization
2273 Float_t inputDistIntegral = initialConditions->Integral();
2274 for (Int_t i=0; i<kMaxT; i++)
2275 prior[i] = initialConditions->GetBinContent(i+1) / inputDistIntegral;
2278 //TH1F* convergence = new TH1F("convergence", "convergence", 200, 0.5, 200.5);
2281 for (Int_t i=0; i<nIterations || nIterations < 0; i++)
2283 //printf(" iteration %i \n", i);
2285 // calculate IR from Beyes theorem
2286 // IR_ji = R_ij * prior_i / sum_k(R_kj * prior_k)
2288 Double_t chi2Measured = 0;
2289 for (Int_t m=0; m<kMaxM; m++)
2292 for (Int_t t = kStartBin; t<kMaxT; t++)
2293 norm += response[t][m] * prior[t];
2295 // calc. chi2: (measured - response * prior) / error
2296 if (measuredError[m] > 0)
2298 Double_t value = (measuredCopy[m] - norm) / measuredError[m];
2299 chi2Measured += value * value;
2304 for (Int_t t = kStartBin; t<kMaxT; t++)
2305 inverseResponse[t][m] = response[t][m] * prior[t] / norm;
2309 for (Int_t t = kStartBin; t<kMaxT; t++)
2310 inverseResponse[t][m] = 0;
2313 //Printf("chi2Measured of the last prior is %e", chi2Measured);
2315 for (Int_t t = kStartBin; t<kMaxT; t++)
2318 for (Int_t m=0; m<kMaxM; m++)
2319 value += inverseResponse[t][m] * measuredCopy[m];
2321 if (efficiency[t] > 0)
2322 result[t] = value / efficiency[t];
2327 Double_t chi2LastIter = 0;
2328 // regularization (simple smoothing)
2329 for (Int_t t=kStartBin; t<kMaxT; t++)
2331 Float_t newValue = 0;
2332 // 0 bin excluded from smoothing
2333 if (t > kStartBin+1 && t<kMaxT-1)
2335 Float_t average = (result[t-1] + result[t] + result[t+1]) / 3;
2337 // weight the average with the regularization parameter
2338 newValue = (1 - regPar) * result[t] + regPar * average;
2341 newValue = result[t];
2343 // calculate chi2 (change from last iteration)
2344 if (prior[t] > 1e-5)
2346 Double_t diff = (prior[t] - newValue) / prior[t];
2347 chi2LastIter += diff * diff;
2350 prior[t] = newValue;
2352 //printf("Chi2 of %d iteration = %e\n", i, chi2LastIter);
2353 //convergence->Fill(i+1, chi2LastIter);
2355 if (nIterations < 0 && chi2LastIter < kConvergenceLimit)
2357 Printf("Stopped Bayesian unfolding after %d iterations at chi2(change since last iteration) of %e; chi2Measured of the last prior is %e", i, chi2LastIter, chi2Measured);
2362 // DrawComparison(Form("Bayesian_%d", i), mcTarget, correlationID, kTRUE, eventType);
2363 } // end of iterations
2365 //new TCanvas; convergence->DrawCopy(); gPad->SetLogy();
2366 //delete convergence;
2368 for (Int_t t=0; t<kMaxT; t++)
2369 aResult->SetBinContent(t+1, result[t]);
2374 // Calculate the covariance matrix, all arguments are taken from NIM,A362,487-498,1995
2376 /*printf("Calculating covariance matrix. This may take some time...\n");
2378 // TODO check if this is the right one...
2379 TH1* sumHist = GetMultiplicityMC(inputRange, eventType)->ProjectionY("sumHist", 1, GetMultiplicityMC(inputRange, eventType)->GetNbinsX());
2381 Int_t xBins = hInverseResponseBayes->GetNbinsX();
2382 Int_t yBins = hInverseResponseBayes->GetNbinsY();
2384 // calculate "unfolding matrix" Mij
2385 Float_t matrixM[251][251];
2386 for (Int_t i=1; i<=xBins; i++)
2388 for (Int_t j=1; j<=yBins; j++)
2390 if (fCurrentEfficiency->GetBinContent(i) > 0)
2391 matrixM[i-1][j-1] = hInverseResponseBayes->GetBinContent(i, j) / fCurrentEfficiency->GetBinContent(i);
2393 matrixM[i-1][j-1] = 0;
2397 Float_t* vectorn = new Float_t[yBins];
2398 for (Int_t j=1; j<=yBins; j++)
2399 vectorn[j-1] = fCurrentESD->GetBinContent(j);
2401 // first part of covariance matrix, depends on input distribution n(E)
2402 Float_t cov1[251][251];
2404 Float_t nEvents = fCurrentESD->Integral(); // N
2409 for (Int_t k=0; k<xBins; k++)
2411 printf("In Cov1: %d\n", k);
2412 for (Int_t l=0; l<yBins; l++)
2416 // sum_j Mkj Mlj n(Ej) * (1 - n(Ej) / N)
2417 for (Int_t j=0; j<yBins; j++)
2418 cov1[k][l] += matrixM[k][j] * matrixM[l][j] * vectorn[j]
2419 * (1.0 - vectorn[j] / nEvents);
2421 // - sum_i,j (i != j) Mki Mlj n(Ei) n(Ej) / N
2422 for (Int_t i=0; i<yBins; i++)
2423 for (Int_t j=0; j<yBins; j++)
2427 cov1[k][l] -= matrixM[k][i] * matrixM[l][j] * vectorn[i]
2428 * vectorn[j] / nEvents;
2433 printf("Cov1 finished\n");
2435 TH2F* cov = (TH2F*) hInverseResponseBayes->Clone("cov");
2438 for (Int_t i=1; i<=xBins; i++)
2439 for (Int_t j=1; j<=yBins; j++)
2440 cov->SetBinContent(i, j, cov1[i-1][j-1]);
2445 // second part of covariance matrix, depends on response matrix
2446 Float_t cov2[251][251];
2448 // Cov[P(Er|Cu), P(Es|Cu)] term
2449 Float_t covTerm[100][100][100];
2450 for (Int_t r=0; r<yBins; r++)
2451 for (Int_t u=0; u<xBins; u++)
2452 for (Int_t s=0; s<yBins; s++)
2455 covTerm[r][u][s] = 1.0 / sumHist->GetBinContent(u+1) * hResponse->GetBinContent(u+1, r+1)
2456 * (1.0 - hResponse->GetBinContent(u+1, r+1));
2458 covTerm[r][u][s] = - 1.0 / sumHist->GetBinContent(u+1) * hResponse->GetBinContent(u+1, r+1)
2459 * hResponse->GetBinContent(u+1, s+1);
2462 for (Int_t k=0; k<xBins; k++)
2463 for (Int_t l=0; l<yBins; l++)
2466 printf("In Cov2: %d %d\n", k, l);
2467 for (Int_t i=0; i<yBins; i++)
2468 for (Int_t j=0; j<yBins; j++)
2470 //printf("In Cov2: %d %d %d %d\n", k, l, i, j);
2471 // calculate Cov(Mki, Mlj) = sum{ru},{su} ...
2473 for (Int_t r=0; r<yBins; r++)
2474 for (Int_t u=0; u<xBins; u++)
2475 for (Int_t s=0; s<yBins; s++)
2477 if (hResponse->GetBinContent(u+1, r+1) == 0 || hResponse->GetBinContent(u+1, s+1) == 0
2478 || hResponse->GetBinContent(u+1, i+1) == 0)
2481 tmpCov += BayesCovarianceDerivate(matrixM, hResponse, fCurrentEfficiency, k, i, r, u)
2482 * BayesCovarianceDerivate(matrixM, hResponse, fCurrentEfficiency, l, j, s, u)
2486 cov2[k][l] += fCurrentESD->GetBinContent(i+1) * fCurrentESD->GetBinContent(j+1) * tmpCov;
2490 printf("Cov2 finished\n");
2492 for (Int_t i=1; i<=xBins; i++)
2493 for (Int_t j=1; j<=yBins; j++)
2494 cov->SetBinContent(i, j, cov1[i-1][j-1] + cov2[i-1][j-1]);
2497 cov->Draw("COLZ");*/
2500 //____________________________________________________________________
2501 Float_t AliMultiplicityCorrection::BayesCovarianceDerivate(Float_t matrixM[251][251], TH2* hResponse, Int_t k, Int_t i, Int_t r, Int_t u)
2504 // helper function for the covariance matrix of the bayesian method
2509 if (k == u && r == i)
2510 result += 1.0 / hResponse->GetBinContent(u+1, r+1);
2513 result -= 1.0 / fCurrentEfficiency->GetBinContent(u+1);
2516 result -= matrixM[u][i] * fCurrentEfficiency->GetBinContent(u+1) / hResponse->GetBinContent(u+1, i+1);
2518 result *= matrixM[k][i];
2523 //____________________________________________________________________
2524 void AliMultiplicityCorrection::ApplyLaszloMethod(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType)
2527 // correct spectrum using bayesian method
2532 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
2533 Int_t mcTarget = ((fullPhaseSpace == kFALSE) ? inputRange : 4);
2535 SetupCurrentHists(inputRange, fullPhaseSpace, eventType, kFALSE);
2537 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
2539 // TODO should be taken from correlation map
2540 //TH1* sumHist = GetMultiplicityMC(inputRange, eventType)->ProjectionY("sumHist", 1, GetMultiplicityMC(inputRange, eventType)->GetNbinsX());
2542 // normalize correction for given nPart
2543 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2545 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
2546 //Double_t sum = sumHist->GetBinContent(i);
2549 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
2552 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
2553 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
2558 fCurrentCorrelation->Draw("COLZ");
2561 fCurrentEfficiency = ((TH2*) fCurrentCorrelation)->ProjectionX("eff");
2563 // pick prior distribution
2564 TH1F* hPrior = (TH1F*)fCurrentESD->Clone("prior");
2565 Float_t norm = 1; //hPrior->Integral();
2566 for (Int_t t=1; t<=hPrior->GetNbinsX(); t++)
2567 hPrior->SetBinContent(t, hPrior->GetBinContent(t)/norm);
2569 // zero distribution
2570 TH1F* zero = (TH1F*)hPrior->Clone("zero");
2573 TH1F* hTemp = (TH1F*)fCurrentESD->Clone("temp");
2577 TH2F* hResponse = (TH2F*) fCurrentCorrelation;
2580 Int_t iterations = 25;
2581 for (Int_t i=0; i<iterations; i++)
2583 //printf(" iteration %i \n", i);
2585 for (Int_t m=1; m<=hResponse->GetNbinsY(); m++)
2588 for (Int_t t = 1; t<=hResponse->GetNbinsX(); t++)
2589 value += hResponse->GetBinContent(t, m) * hPrior->GetBinContent(t);
2590 hTemp->SetBinContent(m, value);
2591 //printf("%d %f %f %f\n", m, zero->GetBinContent(m), hPrior->GetBinContent(m), value);
2594 // regularization (simple smoothing)
2595 TH1F* hTrueSmoothed = (TH1F*) hTemp->Clone("truesmoothed");
2597 for (Int_t t=2; t<hTrueSmoothed->GetNbinsX(); t++)
2599 Float_t average = (hTemp->GetBinContent(t-1) / hTemp->GetBinWidth(t-1)
2600 + hTemp->GetBinContent(t) / hTemp->GetBinWidth(t)
2601 + hTemp->GetBinContent(t+1) / hTemp->GetBinWidth(t+1)) / 3.;
2602 average *= hTrueSmoothed->GetBinWidth(t);
2604 // weight the average with the regularization parameter
2605 hTrueSmoothed->SetBinContent(t, (1-regPar) * hTemp->GetBinContent(t) + regPar * average);
2608 for (Int_t m=1; m<=hResponse->GetNbinsY(); m++)
2609 hTemp->SetBinContent(m, zero->GetBinContent(m) + hPrior->GetBinContent(m) - hTrueSmoothed->GetBinContent(m));
2612 for (Int_t t=1; t<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); t++)
2614 fMultiplicityESDCorrected[correlationID]->SetBinContent(t, hTemp->GetBinContent(t));
2615 fMultiplicityESDCorrected[correlationID]->SetBinError(t, 0.05 * hTemp->GetBinContent(t)); // TODO
2617 //printf(" bin %d content %f \n", t, fMultiplicityESDCorrected[correlationID]->GetBinContent(t));
2621 // calculate chi2 (change from last iteration)
2624 // use smoothed true (normalized) as new prior
2625 norm = 1; //hTrueSmoothed->Integral();
2627 for (Int_t t=1; t<hTrueSmoothed->GetNbinsX(); t++)
2629 Float_t newValue = hTemp->GetBinContent(t)/norm;
2630 Float_t diff = hPrior->GetBinContent(t) - newValue;
2631 chi2 += (Double_t) diff * diff;
2633 hPrior->SetBinContent(t, newValue);
2636 printf("Chi2 of %d iteration = %.10f\n", i, chi2);
2639 DrawComparison(Form("Laszlo_%d", i), inputRange, fullPhaseSpace, kTRUE, GetMultiplicityMC(mcTarget, eventType)->ProjectionY());
2641 delete hTrueSmoothed;
2642 } // end of iterations
2644 DrawComparison("Laszlo", inputRange, fullPhaseSpace, kTRUE, GetMultiplicityMC(mcTarget, eventType)->ProjectionY());
2647 //____________________________________________________________________
2648 void AliMultiplicityCorrection::ApplyGaussianMethod(Int_t inputRange, Bool_t fullPhaseSpace)
2651 // correct spectrum using a simple Gaussian approach, that is model-dependent
2654 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
2655 Int_t mcTarget = ((fullPhaseSpace == kFALSE) ? inputRange : 4);
2657 SetupCurrentHists(inputRange, fullPhaseSpace, kTrVtx, kFALSE);
2659 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
2661 TH1D* correction = dynamic_cast<TH1D*> (fCurrentESD->Clone("GaussianMean"));
2662 correction->SetTitle("GaussianMean");
2664 TH1D* correctionWidth = dynamic_cast<TH1D*> (fCurrentESD->Clone("GaussianWidth"));
2665 correction->SetTitle("GaussianWidth");
2667 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2669 TH1D* proj = (dynamic_cast<TH2*> (fCurrentCorrelation))->ProjectionX("_px", i, i+1);
2670 proj->Fit("gaus", "0Q");
2671 correction->SetBinContent(i, proj->GetFunction("gaus")->GetParameter(1));
2672 correctionWidth->SetBinContent(i, proj->GetFunction("gaus")->GetParameter(2));
2676 // draw for debugging
2679 proj->GetFunction("gaus")->DrawCopy("SAME");
2682 TH1* target = fMultiplicityESDCorrected[correlationID];
2684 Int_t nBins = target->GetNbinsX()*10+1;
2685 Float_t* binning = new Float_t[nBins];
2686 for (Int_t i=1; i<=target->GetNbinsX(); ++i)
2687 for (Int_t j=0; j<10; ++j)
2688 binning[(i-1)*10 + j] = target->GetXaxis()->GetBinLowEdge(i) + target->GetXaxis()->GetBinWidth(i) / 10 * j;
2690 binning[nBins-1] = target->GetXaxis()->GetBinUpEdge(target->GetNbinsX());
2692 TH1F* fineBinned = new TH1F("targetFineBinned", "targetFineBinned", nBins-1, binning);
2694 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2696 Float_t mean = correction->GetBinContent(i);
2697 Float_t width = correctionWidth->GetBinContent(i);
2699 Int_t fillBegin = fineBinned->FindBin(mean - width * 5);
2700 Int_t fillEnd = fineBinned->FindBin(mean + width * 5);
2701 //printf("bin %d mean %f width %f, filling from %d to %d\n", i, mean, width, fillBegin, fillEnd);
2703 for (Int_t j=fillBegin; j <= fillEnd; ++j)
2705 fineBinned->AddBinContent(j, TMath::Gaus(fineBinned->GetXaxis()->GetBinCenter(j), mean, width, kTRUE) * fCurrentESD->GetBinContent(i));
2709 for (Int_t i=1; i<=target->GetNbinsX(); ++i)
2712 for (Int_t j=1; j<=10; ++j)
2713 sum += fineBinned->GetBinContent((i-1)*10 + j);
2714 target->SetBinContent(i, sum / 10);
2719 DrawComparison("Gaussian", inputRange, fullPhaseSpace, kFALSE, GetMultiplicityMC(mcTarget, kTrVtx)->ProjectionY());
2722 //____________________________________________________________________
2723 TH2F* AliMultiplicityCorrection::CalculateMultiplicityESD(TH1* inputMC, Int_t correlationMap)
2725 // runs the distribution given in inputMC through the response matrix identified by
2726 // correlationMap and produces a measured distribution
2727 // although it is a TH2F the vertex axis is not used at the moment and all entries are filled in mid-vertex
2728 // if normalized is set, inputMC is expected to be normalized to the bin width
2733 if (correlationMap < 0 || correlationMap >= kCorrHists)
2736 // empty under/overflow bins in x, otherwise Project3D takes them into account
2737 TH3* hist = fCorrelation[correlationMap];
2738 for (Int_t y=1; y<=hist->GetYaxis()->GetNbins(); ++y)
2740 for (Int_t z=1; z<=hist->GetZaxis()->GetNbins(); ++z)
2742 hist->SetBinContent(0, y, z, 0);
2743 hist->SetBinContent(hist->GetXaxis()->GetNbins()+1, y, z, 0);
2747 TH2* corr = (TH2*) hist->Project3D("zy");
2748 //corr->Rebin2D(2, 1);
2751 // normalize correction for given nPart
2752 for (Int_t i=1; i<=corr->GetNbinsX(); ++i)
2754 Double_t sum = corr->Integral(i, i, 1, corr->GetNbinsY());
2758 for (Int_t j=1; j<=corr->GetNbinsY(); ++j)
2761 corr->SetBinContent(i, j, corr->GetBinContent(i, j) / sum);
2762 corr->SetBinError(i, j, corr->GetBinError(i, j) / sum);
2766 TH2F* target = dynamic_cast<TH2F*> (fMultiplicityESD[0]->Clone(Form("%s_measured", inputMC->GetName())));
2769 for (Int_t meas=1; meas<=corr->GetNbinsY(); ++meas)
2771 Float_t measured = 0;
2774 for (Int_t gen=1; gen<=corr->GetNbinsX(); ++gen)
2776 Int_t mcGenBin = inputMC->GetXaxis()->FindBin(corr->GetXaxis()->GetBinCenter(gen));
2778 measured += inputMC->GetBinContent(mcGenBin) * corr->GetBinContent(gen, meas);
2779 error += inputMC->GetBinError(mcGenBin) * corr->GetBinContent(gen, meas);
2782 //printf("%f +- %f ; %f +- %f \n", inputMC->GetBinContent(meas), inputMC->GetBinError(meas), measured, error);
2784 target->SetBinContent(1 + target->GetNbinsX() / 2, meas, measured);
2785 target->SetBinError(1 + target->GetNbinsX() / 2, meas, error);
2791 //____________________________________________________________________
2792 void AliMultiplicityCorrection::SetGenMeasFromFunc(TF1* inputMC, Int_t id)
2794 // uses the given function to fill the input MC histogram and generates from that
2795 // the measured histogram by applying the response matrix
2796 // this can be used to evaluate if the methods work indepedently of the input
2798 // WARNING does not respect the vertex distribution, just fills central vertex bin
2803 if (id < 0 || id >= kESDHists)
2806 TH2F* mc = fMultiplicityVtx[id];
2810 for (Int_t i=1; i<=mc->GetNbinsY(); ++i)
2812 mc->SetBinContent(mc->GetNbinsX() / 2 + 1, i, inputMC->Eval(mc->GetYaxis()->GetBinCenter(i)) * mc->GetYaxis()->GetBinWidth(i));
2813 mc->SetBinError(mc->GetNbinsX() / 2 + 1, i, 0);
2819 TH1* proj = mc->ProjectionY();
2821 TString tmp(fMultiplicityESD[id]->GetName());
2822 delete fMultiplicityESD[id];
2823 fMultiplicityESD[id] = CalculateMultiplicityESD(proj, id);
2824 fMultiplicityESD[id]->SetName(tmp);