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 // project without under/overflow bins
811 fCurrentESD = fMultiplicityESD[inputRange]->ProjectionY("fCurrentESD", 1, fMultiplicityESD[inputRange]->GetXaxis()->GetNbins());
812 fCurrentESD->Sumw2();
814 // empty under/overflow bins in x, otherwise Project3D takes them into account
815 TH3* hist = fCorrelation[correlationID];
816 for (Int_t y=0; y<=hist->GetYaxis()->GetNbins()+1; ++y)
818 for (Int_t z=0; z<=hist->GetZaxis()->GetNbins()+1; ++z)
820 hist->SetBinContent(0, y, z, 0);
821 hist->SetBinContent(hist->GetXaxis()->GetNbins()+1, y, z, 0);
825 fCurrentCorrelation = hist->Project3D("zy");
826 //((TH2*) fCurrentCorrelation)->Rebin2D(2, 1);
827 //fMultiplicityESDCorrected[correlationID]->Rebin(2);
828 fCurrentCorrelation->Sumw2();
830 Printf("AliMultiplicityCorrection::SetupCurrentHists: Statistics information: %.f entries in correlation map; %.f entries in measured spectrum", fCurrentCorrelation->Integral(), fCurrentESD->Integral());
835 for (Int_t i=1; i<=fCurrentESD->GetNbinsX(); ++i)
837 if (fCurrentESD->GetBinContent(i) <= 5)
844 if (fLastBinLimit > 0)
850 canvas = new TCanvas("StatSolution", "StatSolution", 1000, 800);
851 canvas->Divide(2, 2);
854 fCurrentESD->GetXaxis()->SetRangeUser(0, 200);
855 fCurrentESD->SetStats(kFALSE);
856 fCurrentESD->SetTitle(";measured multiplicity");
857 fCurrentESD->DrawCopy();
861 fCurrentCorrelation->GetXaxis()->SetRangeUser(0, 250);
862 fCurrentCorrelation->GetYaxis()->SetRangeUser(0, 250);
863 fCurrentCorrelation->SetTitle(";true multiplicity;measured multiplicity");
864 fCurrentCorrelation->SetStats(kFALSE);
865 fCurrentCorrelation->DrawCopy("COLZ");
868 printf("Bin limit in measured spectrum is %d.\n", fLastBinLimit);
869 fCurrentESD->SetBinContent(fLastBinLimit, fCurrentESD->Integral(fLastBinLimit, fCurrentESD->GetNbinsX()));
870 for (Int_t i=fLastBinLimit+1; i<=fCurrentESD->GetNbinsX(); ++i)
872 fCurrentESD->SetBinContent(i, 0);
873 fCurrentESD->SetBinError(i, 0);
875 // the error is set to sqrt(N), better solution possible?, sum of relative errors of all contributions???
876 fCurrentESD->SetBinError(fLastBinLimit, TMath::Sqrt(fCurrentESD->GetBinContent(fLastBinLimit)));
878 printf("This bin has now %f +- %f entries\n", fCurrentESD->GetBinContent(fLastBinLimit), fCurrentESD->GetBinError(fLastBinLimit));
880 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
882 fCurrentCorrelation->SetBinContent(i, fLastBinLimit, fCurrentCorrelation->Integral(i, i, fLastBinLimit, fCurrentCorrelation->GetNbinsY()));
883 // the error is set to sqrt(N), better solution possible?, sum of relative errors of all contributions???
884 fCurrentCorrelation->SetBinError(i, fLastBinLimit, TMath::Sqrt(fCurrentCorrelation->GetBinContent(i, fLastBinLimit)));
886 for (Int_t j=fLastBinLimit+1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
888 fCurrentCorrelation->SetBinContent(i, j, 0);
889 fCurrentCorrelation->SetBinError(i, j, 0);
893 printf("Adjusted correlation matrix!\n");
898 fCurrentESD->DrawCopy();
902 fCurrentCorrelation->DrawCopy("COLZ");
907 #if 0 // does not help
908 // null bins with one entry
909 Int_t nNulledBins = 0;
910 for (Int_t x=1; x<=fCurrentCorrelation->GetXaxis()->GetNbins(); ++x)
911 for (Int_t y=1; y<=fCurrentCorrelation->GetYaxis()->GetNbins(); ++y)
913 if (fCurrentCorrelation->GetBinContent(x, y) == 1)
915 fCurrentCorrelation->SetBinContent(x, y, 0);
916 fCurrentCorrelation->SetBinError(x, y, 0);
921 Printf("Nulled %d bins", nNulledBins);
924 fCurrentEfficiency = GetEfficiency(inputRange, eventType);
925 //fCurrentEfficiency->Rebin(2);
926 //fCurrentEfficiency->Scale(0.5);
929 //____________________________________________________________________
930 TH1* AliMultiplicityCorrection::GetEfficiency(Int_t inputRange, EventType eventType)
933 // calculates efficiency for given event type
939 case kTrVtx : divisor = fMultiplicityVtx[inputRange]->ProjectionY("divisor", -1, -1, "e"); break;
940 case kMB: divisor = fMultiplicityMB[inputRange]->ProjectionY("divisor", -1, -1, "e"); break;
941 case kINEL: divisor = fMultiplicityINEL[inputRange]->ProjectionY("divisor", -1, -1, "e"); break;
943 TH1* eff = fMultiplicityVtx[inputRange]->ProjectionY("CurrentEfficiency", -1, -1, "e");
944 eff->Divide(eff, divisor, 1, 1, "B");
948 //____________________________________________________________________
949 void AliMultiplicityCorrection::SetRegularizationParameters(RegularizationType type, Float_t weight, Int_t minuitParams)
952 // sets the parameters for chi2 minimization
955 fgRegularizationType = type;
956 fgRegularizationWeight = weight;
958 printf("AliMultiplicityCorrection::SetRegularizationParameters --> Regularization set to %d with weight %f\n", (Int_t) type, weight);
960 if (minuitParams > 0)
962 fgNParamsMinuit = minuitParams;
963 printf("AliMultiplicityCorrection::SetRegularizationParameters --> Number of MINUIT iterations set to %d\n", minuitParams);
967 //____________________________________________________________________
968 void AliMultiplicityCorrection::SetBayesianParameters(Float_t smoothing, Int_t nIterations)
971 // sets the parameters for Bayesian unfolding
974 fgBayesianSmoothing = smoothing;
975 fgBayesianIterations = nIterations;
977 printf("AliMultiplicityCorrection::SetBayesianParameters --> Paramaters set to %d iterations with smoothing %f\n", fgBayesianIterations, fgBayesianSmoothing);
980 //____________________________________________________________________
981 Int_t AliMultiplicityCorrection::UnfoldWithMinuit(TH1* correlation, TH1* aEfficiency, TH1* measured, TH1* initialConditions, TH1* result, Bool_t check)
984 // implemenation of unfolding (internal function)
986 // unfolds <measured> using response from <correlation> and effiency <aEfficiency>
987 // output is in <result>
988 // <initialConditions> set the initial values for the minimization, if 0 <measured> is used
989 // if <check> is true no unfolding is made, instead only the chi2 without unfolding is printed
991 // returns minuit status (0 = success), (-1 when check was set)
995 measured->Scale(1.0 / measured->Integral());
997 if (!fgCorrelationMatrix)
998 fgCorrelationMatrix = new TMatrixD(fgkMaxInput, fgNParamsMinuit);
999 if (!fgCorrelationCovarianceMatrix)
1000 fgCorrelationCovarianceMatrix = new TMatrixD(fgkMaxInput, fgkMaxInput);
1001 if (!fgCurrentESDVector)
1002 fgCurrentESDVector = new TVectorD(fgkMaxInput);
1003 if (!fgEntropyAPriori)
1004 fgEntropyAPriori = new TVectorD(fgNParamsMinuit);
1006 fgCorrelationMatrix->Zero();
1007 fgCorrelationCovarianceMatrix->Zero();
1008 fgCurrentESDVector->Zero();
1009 fgEntropyAPriori->Zero();
1011 // normalize correction for given nPart
1012 for (Int_t i=1; i<=correlation->GetNbinsX(); ++i)
1014 Double_t sum = correlation->Integral(i, i, 1, correlation->GetNbinsY());
1017 Float_t maxValue = 0;
1019 for (Int_t j=1; j<=correlation->GetNbinsY(); ++j)
1021 // find most probably value
1022 if (maxValue < correlation->GetBinContent(i, j))
1024 maxValue = correlation->GetBinContent(i, j);
1029 correlation->SetBinContent(i, j, correlation->GetBinContent(i, j) / sum);
1030 correlation->SetBinError(i, j, correlation->GetBinError(i, j) / sum);
1032 if (i <= fgNParamsMinuit && j <= fgkMaxInput)
1033 (*fgCorrelationMatrix)(j-1, i-1) = correlation->GetBinContent(i, j);
1036 //printf("MPV for Ntrue = %f is %f\n", fCurrentCorrelation->GetXaxis()->GetBinCenter(i), fCurrentCorrelation->GetYaxis()->GetBinCenter(maxBin));
1039 // Initialize TMinuit via generic fitter interface
1040 TVirtualFitter *minuit = TVirtualFitter::Fitter(0, fgNParamsMinuit);
1041 Double_t arglist[100];
1043 // disable any output (-1), unfortuantly we do not see warnings anymore then. Have to find another way...
1045 minuit->ExecuteCommand("SET PRINT", arglist, 1);
1047 // however, enable warnings
1048 //minuit->ExecuteCommand("SET WAR", arglist, 0);
1050 // set minimization function
1051 minuit->SetFCN(MinuitFitFunction);
1053 for (Int_t i=0; i<fgNParamsMinuit; i++)
1054 (*fgEntropyAPriori)[i] = 1;
1056 if (!initialConditions) {
1057 initialConditions = measured;
1059 printf("Using different starting conditions...\n");
1060 //new TCanvas; initialConditions->DrawCopy();
1061 initialConditions->Scale(1.0 / initialConditions->Integral());
1064 for (Int_t i=0; i<fgNParamsMinuit; i++)
1065 if (initialConditions->GetBinContent(i+1) > 0)
1066 (*fgEntropyAPriori)[i] = initialConditions->GetBinContent(i+1);
1068 Double_t* results = new Double_t[fgNParamsMinuit+1];
1069 for (Int_t i=0; i<fgNParamsMinuit; ++i)
1071 results[i] = initialConditions->GetBinContent(i+1);
1075 results[i] = TMath::Max(results[i], 1e-3);
1077 Float_t stepSize = 0.1;
1079 // minuit sees squared values to prevent it from going negative...
1080 results[i] = TMath::Sqrt(results[i]);
1081 //stepSize /= results[i]; // keep relative step size
1083 minuit->SetParameter(i, Form("param%d", i), results[i], stepSize, 0, 0);
1085 //minuit->SetParameter(fgkMaxParams, "alpha", 1e4, 1, 0, 0);
1086 // bin 0 is filled with value from bin 1 (otherwise it's 0)
1087 //minuit->SetParameter(0, "param0", (results[1] > minStartValue) ? results[1] : minStartValue, 0.1, 0, 0);
1089 //minuit->SetParameter(0, "param0", 0, 0, 0, 0);
1091 for (Int_t i=0; i<fgkMaxInput; ++i)
1093 (*fgCurrentESDVector)[i] = measured->GetBinContent(i+1);
1094 if (measured->GetBinError(i+1) > 0)
1095 (*fgCorrelationCovarianceMatrix)(i, i) = (Double_t) 1e-6 / measured->GetBinError(i+1) / measured->GetBinError(i+1);
1097 if ((*fgCorrelationCovarianceMatrix)(i, i) > 1e7)
1098 (*fgCorrelationCovarianceMatrix)(i, i) = 0;
1103 MinuitFitFunction(dummy, 0, chi2, results, 0);
1105 printf("Chi2 of initial parameters is = %f\n", chi2);
1113 // first param is number of iterations, second is precision....
1115 //arglist[1] = 1e-5;
1116 //minuit->ExecuteCommand("SCAN", arglist, 0);
1117 Int_t status = minuit->ExecuteCommand("MIGRAD", arglist, 1);
1118 printf("MINUIT status is %d\n", status);
1119 //minuit->ExecuteCommand("MIGRAD", arglist, 1);
1120 //minuit->ExecuteCommand("MIGRAD", arglist, 1);
1121 //printf("!!!!!!!!!!!!!! MIGRAD finished: Starting MINOS !!!!!!!!!!!!!!");
1122 //minuit->ExecuteCommand("MINOS", arglist, 0);
1124 for (Int_t i=0; i<fgNParamsMinuit; ++i)
1126 if (aEfficiency->GetBinContent(i+1) > 0)
1128 results[i] = minuit->GetParameter(i);
1129 result->SetBinContent(i+1, results[i] * results[i] / aEfficiency->GetBinContent(i+1));
1130 // error is : (relError) * (value) = (minuit->GetParError(i) / minuit->GetParameter(i)) * (minuit->GetParameter(i) * minuit->GetParameter(i))
1131 result->SetBinError(i+1, minuit->GetParError(i) * results[i] / aEfficiency->GetBinContent(i+1));
1135 result->SetBinContent(i+1, 0);
1136 result->SetBinError(i+1, 0);
1146 //____________________________________________________________________
1147 Int_t AliMultiplicityCorrection::ApplyMinuitFit(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Bool_t check, TH1* initialConditions)
1150 // correct spectrum using minuit chi2 method
1152 // for description of parameters, see UnfoldWithMinuit
1155 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1156 SetupCurrentHists(inputRange, fullPhaseSpace, eventType, fgCreateBigBin);
1158 return UnfoldWithMinuit(fCurrentCorrelation, fCurrentEfficiency, fCurrentESD, initialConditions, fMultiplicityESDCorrected[correlationID], check);
1161 //____________________________________________________________________
1162 void AliMultiplicityCorrection::ApplyNBDFit(Int_t inputRange, Bool_t fullPhaseSpace)
1165 // correct spectrum using minuit chi2 method applying a NBD fit
1168 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1170 SetupCurrentHists(inputRange, fullPhaseSpace, kTrVtx, kFALSE);
1172 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
1174 fgCorrelationMatrix = new TMatrixD(fgkMaxParams, fgkMaxParams);
1175 fgCorrelationCovarianceMatrix = new TMatrixD(fgkMaxParams, fgkMaxParams);
1176 fgCurrentESDVector = new TVectorD(fgkMaxParams);
1178 // normalize correction for given nPart
1179 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
1181 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
1184 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
1187 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
1188 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
1190 if (i <= fgkMaxParams && j <= fgkMaxParams)
1191 (*fgCorrelationMatrix)(j-1, i-1) = fCurrentCorrelation->GetBinContent(i, j);
1195 for (Int_t i=0; i<fgkMaxParams; ++i)
1197 (*fgCurrentESDVector)[i] = fCurrentESD->GetBinContent(i+1);
1198 if (fCurrentESD->GetBinError(i+1) > 0)
1199 (*fgCorrelationCovarianceMatrix)(i, i) = 1.0 / (fCurrentESD->GetBinError(i+1) * fCurrentESD->GetBinError(i+1));
1202 // Create NBD function
1205 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);
1206 fgNBD->SetParNames("scaling", "averagen", "k");
1209 // Initialize TMinuit via generic fitter interface
1210 TVirtualFitter *minuit = TVirtualFitter::Fitter(0, 3);
1212 minuit->SetFCN(MinuitNBD);
1213 minuit->SetParameter(0, "param0", 1, 0.1, 0.001, fCurrentESD->GetMaximum() * 1000);
1214 minuit->SetParameter(1, "param1", 10, 1, 0.001, 1000);
1215 minuit->SetParameter(2, "param2", 2, 1, 0.001, 1000);
1217 Double_t arglist[100];
1219 minuit->ExecuteCommand("SET PRINT", arglist, 1);
1220 minuit->ExecuteCommand("MIGRAD", arglist, 0);
1221 //minuit->ExecuteCommand("MINOS", arglist, 0);
1223 fgNBD->SetParameters(minuit->GetParameter(0), minuit->GetParameter(1), minuit->GetParameter(2));
1225 for (Int_t i=0; i<fgkMaxParams; ++i)
1227 printf("%d : %f\n", i, fgNBD->Eval(i));
1228 if (fgNBD->Eval(i) > 0)
1230 fMultiplicityESDCorrected[correlationID]->SetBinContent(i+1, fgNBD->Eval(i));
1231 fMultiplicityESDCorrected[correlationID]->SetBinError(i+1, 0);
1236 //____________________________________________________________________
1237 void AliMultiplicityCorrection::DrawHistograms()
1240 // draws the histograms of this class
1245 TCanvas* canvas1 = new TCanvas("fMultiplicityESD", "fMultiplicityESD", 900, 600);
1246 canvas1->Divide(3, 2);
1247 for (Int_t i = 0; i < kESDHists; ++i)
1250 fMultiplicityESD[i]->DrawCopy("COLZ");
1251 printf("%d --> %f\n", i, (Float_t) fMultiplicityESD[i]->ProjectionY()->GetMean());
1256 TCanvas* canvas2 = new TCanvas("fMultiplicityMC", "fMultiplicityMC", 900, 600);
1257 canvas2->Divide(3, 2);
1258 for (Int_t i = 0; i < kMCHists; ++i)
1261 fMultiplicityVtx[i]->DrawCopy("COLZ");
1262 printf("%d --> %f\n", i, fMultiplicityVtx[i]->ProjectionY()->GetMean());
1265 TCanvas* canvas3 = new TCanvas("fCorrelation", "fCorrelation", 900, 900);
1266 canvas3->Divide(3, 3);
1267 for (Int_t i = 0; i < kCorrHists; ++i)
1270 TH3* hist = dynamic_cast<TH3*> (fCorrelation[i]->Clone());
1271 for (Int_t y=1; y<=hist->GetYaxis()->GetNbins(); ++y)
1273 for (Int_t z=1; z<=hist->GetZaxis()->GetNbins(); ++z)
1275 hist->SetBinContent(0, y, z, 0);
1276 hist->SetBinContent(hist->GetXaxis()->GetNbins()+1, y, z, 0);
1279 TH1* proj = hist->Project3D("zy");
1280 proj->DrawCopy("COLZ");
1284 //____________________________________________________________________
1285 void AliMultiplicityCorrection::DrawComparison(const char* name, Int_t inputRange, Bool_t fullPhaseSpace, Bool_t /*normalizeESD*/, TH1* mcHist, Bool_t simple)
1287 // draw comparison plots
1292 Int_t esdCorrId = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1295 tmpStr.Form("%s_DrawComparison_%d", name, esdCorrId);
1297 if (fMultiplicityESDCorrected[esdCorrId]->Integral() == 0)
1299 printf("ERROR. Unfolded histogram is empty\n");
1303 //regain measured distribution used for unfolding, because the bins at high mult. were modified in SetupCurrentHists
1304 fCurrentESD = fMultiplicityESD[esdCorrId]->ProjectionY("fCurrentESD", 1, fMultiplicityESD[inputRange]->GetXaxis()->GetNbins());
1305 fCurrentESD->Sumw2();
1306 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
1308 // normalize unfolded result to 1
1309 fMultiplicityESDCorrected[esdCorrId]->Scale(1.0 / fMultiplicityESDCorrected[esdCorrId]->Integral());
1311 //fCurrentESD->Scale(mcHist->Integral(2, 200));
1314 /*TH1* ratio = (TH1*) fMultiplicityESDCorrected[esdCorrId]->Clone("ratio");
1315 ratio->Divide(mcHist);
1316 ratio->Draw("HIST");
1317 ratio->Fit("pol0", "W0", "", 20, 120);
1318 Float_t scalingFactor = ratio->GetFunction("pol0")->GetParameter(0);
1320 mcHist->Scale(scalingFactor);*/
1322 // find bin with <= 50 entries. this is used as limit for the chi2 calculation
1323 Int_t mcBinLimit = 0;
1324 for (Int_t i=20; i<mcHist->GetNbinsX(); ++i)
1326 if (mcHist->GetBinContent(i) > 50)
1333 Printf("AliMultiplicityCorrection::DrawComparison: MC bin limit is %d", mcBinLimit);
1337 if (mcHist->Integral() > 0)
1338 mcHist->Scale(1.0 / mcHist->Integral());
1340 // calculate residual
1342 // for that we convolute the response matrix with the gathered result
1343 // if normalizeESD is not set, the histogram is already normalized, this needs to be passed to CalculateMultiplicityESD
1344 TH1* tmpESDEfficiencyRecorrected = (TH1*) fMultiplicityESDCorrected[esdCorrId]->Clone("tmpESDEfficiencyRecorrected");
1345 tmpESDEfficiencyRecorrected->Multiply(fCurrentEfficiency);
1346 TH2* convoluted = CalculateMultiplicityESD(tmpESDEfficiencyRecorrected, esdCorrId);
1347 TH1* convolutedProj = convoluted->ProjectionY("convolutedProj", -1, -1, "e");
1348 if (convolutedProj->Integral() > 0)
1350 convolutedProj->Scale(1.0 / convolutedProj->Integral());
1353 printf("ERROR: convolutedProj is empty. Something went wrong calculating the convoluted histogram.\n");
1355 TH1* residual = (TH1*) convolutedProj->Clone("residual");
1356 residual->SetTitle("Residuals;Ntracks;(folded unfolded measured - measured) / e");
1358 residual->Add(fCurrentESD, -1);
1359 //residual->Divide(residual, fCurrentESD, 1, 1, "B");
1361 TH1* residualHist = new TH1F("residualHist", "residualHist", 51, -5, 5);
1365 for (Int_t i=1; i<=residual->GetNbinsX(); ++i)
1367 if (fCurrentESD->GetBinError(i) > 0)
1369 Float_t value = residual->GetBinContent(i) / fCurrentESD->GetBinError(i);
1370 if (i > 1 && i <= fLastBinLimit)
1371 chi2 += value * value;
1372 Printf("%d --> %f (%f)", i, value * value, chi2);
1373 residual->SetBinContent(i, value);
1374 residualHist->Fill(value);
1378 //printf("Residual bin %d set to 0\n", i);
1379 residual->SetBinContent(i, 0);
1381 convolutedProj->SetBinError(i, 0);
1382 residual->SetBinError(i, 0);
1384 fLastChi2Residuals = chi2;
1386 new TCanvas; residualHist->DrawCopy();
1388 //residualHist->Fit("gaus", "N");
1389 //delete residualHist;
1391 printf("Difference (Residuals) is %f for bin 2-%d\n", fLastChi2Residuals, fLastBinLimit);
1393 TCanvas* canvas1 = 0;
1396 canvas1 = new TCanvas(tmpStr, tmpStr, 900, 400);
1397 canvas1->Divide(2, 1);
1401 canvas1 = new TCanvas(tmpStr, tmpStr, 1200, 1200);
1402 canvas1->Divide(2, 3);
1406 TH1* proj = (TH1*) mcHist->Clone("proj");
1408 // normalize without 0 bin
1409 proj->Scale(1.0 / proj->Integral(2, proj->GetNbinsX()));
1410 Printf("Normalized without 0 bin!");
1411 proj->GetXaxis()->SetRangeUser(0, 200);
1412 proj->SetTitle(";true multiplicity;Entries");
1413 proj->SetStats(kFALSE);
1415 fMultiplicityESDCorrected[esdCorrId]->SetLineColor(2);
1416 // normalize without 0 bin
1417 fMultiplicityESDCorrected[esdCorrId]->Scale(1.0 / fMultiplicityESDCorrected[esdCorrId]->Integral(2, fMultiplicityESDCorrected[esdCorrId]->GetNbinsX()));
1418 Printf("Normalized without 0 bin!");
1420 if (proj->GetEntries() > 0) {
1421 proj->DrawCopy("HIST");
1422 fMultiplicityESDCorrected[esdCorrId]->DrawCopy("SAME HIST E");
1425 fMultiplicityESDCorrected[esdCorrId]->DrawCopy("HIST E");
1429 TLegend* legend = new TLegend(0.3, 0.8, 0.93, 0.93);
1430 legend->AddEntry(proj, "true distribution");
1431 legend->AddEntry(fMultiplicityESDCorrected[esdCorrId], "unfolded distribution");
1432 legend->SetFillColor(0);
1434 // unfortunately does not work. maybe a bug? --> legend->SetTextSizePixels(14);
1439 fCurrentESD->GetXaxis()->SetRangeUser(0, 200);
1440 //fCurrentESD->SetLineColor(2);
1441 fCurrentESD->SetTitle(";measured multiplicity;Entries");
1442 fCurrentESD->SetStats(kFALSE);
1443 fCurrentESD->DrawCopy("HIST E");
1445 convolutedProj->SetLineColor(2);
1446 //proj2->SetMarkerColor(2);
1447 //proj2->SetMarkerStyle(5);
1448 convolutedProj->DrawCopy("HIST SAME");
1450 legend = new TLegend(0.3, 0.8, 0.93, 0.93);
1451 legend->AddEntry(fCurrentESD, "measured distribution");
1452 legend->AddEntry(convolutedProj, "R #otimes unfolded distribution");
1453 legend->SetFillColor(0);
1456 //TH1* diffMCUnfolded = dynamic_cast<TH1*> (proj->Clone("diffMCUnfolded"));
1457 //diffMCUnfolded->Add(fMultiplicityESDCorrected[esdCorrId], -1);
1461 fLastChi2MCLimit = 0;
1463 for (Int_t i=2; i<=200; ++i)
1465 if (proj->GetBinContent(i) != 0)
1467 Float_t value = (proj->GetBinContent(i) - fMultiplicityESDCorrected[esdCorrId]->GetBinContent(i)) / proj->GetBinContent(i);
1468 chi2 += value * value;
1469 chi += TMath::Abs(value);
1471 //printf("%d %f\n", i, chi);
1474 fLastChi2MCLimit = i;
1485 for (Int_t i=1; i<=diffMCUnfolded->GetNbinsX(); ++i)
1487 if (fMultiplicityESDCorrected[esdCorrId]->GetBinError(i) > 0)
1489 Double_t value = diffMCUnfolded->GetBinContent(i) / fMultiplicityESDCorrected[esdCorrId]->GetBinError(i);
1491 value = 1e8; //prevent arithmetic exception
1492 else if (value < -1e8)
1496 chi2 += value * value;
1497 chi += TMath::Abs(value);
1499 diffMCUnfolded->SetBinContent(i, value);
1503 //printf("diffMCUnfolded bin %d set to 0\n", i);
1504 diffMCUnfolded->SetBinContent(i, 0);
1507 fLastChi2MCLimit = i;
1514 printf("limits %d %d\n", fLastChi2MCLimit, limit);
1515 fLastChi2MCLimit = limit;
1517 printf("Difference (from MC) is %f for bin 2-150. Limit is %d.\n", fLastChi2MC, fLastChi2MCLimit);*/
1523 diffMCUnfolded->SetTitle("#chi^{2};Npart;(MC - Unfolded) / e(unfolded)");
1524 //diffMCUnfolded->GetYaxis()->SetRangeUser(-20, 20);
1525 diffMCUnfolded->GetXaxis()->SetRangeUser(0, 200);
1526 diffMCUnfolded->DrawCopy("HIST");
1528 TH1F* fluctuation = new TH1F("fluctuation", "fluctuation", 20, -5, 5);
1529 for (Int_t i=20; i<=diffMCUnfolded->GetNbinsX(); ++i)
1530 fluctuation->Fill(diffMCUnfolded->GetBinContent(i));
1532 //new TCanvas; fluctuation->DrawCopy();
1533 delete fluctuation;*/
1535 /*TLegend* legend = new TLegend(0.6, 0.7, 0.85, 0.85);
1536 legend->AddEntry(fMultiplicityESDCorrected, "ESD corrected");
1537 legend->AddEntry(fMultiplicityMC, "MC");
1538 legend->AddEntry(fMultiplicityESD, "ESD");
1542 residual->GetYaxis()->SetRangeUser(-5, 5);
1543 residual->GetXaxis()->SetRangeUser(0, 200);
1544 residual->DrawCopy();
1548 TH1* ratio = (TH1*) fMultiplicityESDCorrected[esdCorrId]->Clone("ratio");
1549 ratio->Divide(mcHist);
1550 ratio->SetTitle("Ratio;true multiplicity;Unfolded / MC");
1551 ratio->GetYaxis()->SetRangeUser(0.5, 1.5);
1552 ratio->GetXaxis()->SetRangeUser(0, 200);
1553 ratio->SetStats(kFALSE);
1554 ratio->Draw("HIST");
1556 Double_t ratioChi2 = 0;
1558 fLastChi2MCLimit = 0;
1559 for (Int_t i=2; i<=150; ++i)
1561 Float_t value = ratio->GetBinContent(i) - 1;
1563 value = 1e8; //prevent arithmetic exception
1564 else if (value < -1e8)
1567 ratioChi2 += value * value;
1568 fRatioAverage += TMath::Abs(value);
1570 if (ratioChi2 < 0.1)
1571 fLastChi2MCLimit = i;
1573 fRatioAverage /= 149;
1575 printf("Sum over (ratio-1)^2 (2..150) is %f; average of |ratio-1| is %f\n", ratioChi2, fRatioAverage);
1577 fLastChi2MC = ratioChi2;
1581 const Int_t kFFT = 128;
1582 Double_t fftReal[kFFT];
1583 Double_t fftImag[kFFT];
1585 for (Int_t i=0; i<kFFT; ++i)
1587 fftReal[i] = ratio->GetBinContent(i+1+10);
1589 //fftReal[i] = cos(TMath::Pi() * 5 * 2 * i / 128);
1593 FFT(-1, TMath::Nint(TMath::Log(kFFT) / TMath::Log(2)), fftReal, fftImag);
1595 TH1* fftResult = (TH1*) ratio->Clone("fftResult");
1596 fftResult->SetTitle("FFT;true multiplicity;coeff. (10...137)");
1597 TH1* fftResult2 = (TH1*) ratio->Clone("fftResult2");
1598 TH1* fftResult3 = (TH1*) ratio->Clone("fftResult3");
1600 fftResult2->Reset();
1601 fftResult3->Reset();
1602 fftResult->GetYaxis()->UnZoom();
1603 fftResult2->GetYaxis()->UnZoom();
1604 fftResult3->GetYaxis()->UnZoom();
1606 //Printf("AFTER FFT");
1607 for (Int_t i=0; i<kFFT; ++i)
1609 //Printf("%d: %f", i, fftReal[i]);
1610 fftResult->SetBinContent(i+1, fftReal[i]);
1611 /*if (i != 0 && TMath::Abs(fftReal[i]) > 0.5)
1613 Printf("Nulled %d", i);
1618 fftResult->SetLineColor(1);
1619 fftResult->DrawCopy();
1623 for (Int_t i=0; i<kFFT; ++i)
1625 //Printf("%d: %f", i, fftImag[i]);
1626 fftResult2->SetBinContent(i+1, fftImag[i]);
1628 fftResult3->SetBinContent(i+1, TMath::Sqrt(fftReal[i] * fftReal[i] + fftImag[i] * fftImag[i]));
1631 fftResult2->SetLineColor(2);
1632 fftResult2->DrawCopy("SAME");
1634 fftResult3->SetLineColor(4);
1635 fftResult3->DrawCopy("SAME");
1637 for (Int_t i=1; i<kFFT - 1; ++i)
1639 if (TMath::Sqrt(fftReal[i] * fftReal[i] + fftImag[i] * fftImag[i]) > 3)
1647 //fftReal[i] = (fftReal[i-1] + fftReal[i+1]) / 2;
1648 //fftImag[i] = (fftImag[i-1] + fftImag[i+1]) / 2;
1649 //Printf("Nulled %d to %f %f", i, fftReal[i], fftImag[i]);
1653 FFT(1, TMath::Nint(TMath::Log(kFFT) / TMath::Log(2)), fftReal, fftImag);
1655 TH1* fftResult4 = (TH1*) fftResult3->Clone("fftResult4");
1656 fftResult4->Reset();
1658 //Printf("AFTER BACK-TRAFO");
1659 for (Int_t i=0; i<kFFT; ++i)
1661 //Printf("%d: %f", i, fftReal[i]);
1662 fftResult4->SetBinContent(i+1+10, fftReal[i]);
1666 fftResult4->SetLineColor(4);
1667 fftResult4->DrawCopy("SAME");
1669 // plot (MC - Unfolded) / error (MC)
1672 TH1* diffMCUnfolded2 = dynamic_cast<TH1*> (proj->Clone("diffMCUnfolded2"));
1673 diffMCUnfolded2->Add(fMultiplicityESDCorrected[esdCorrId], -1);
1675 Int_t ndfQual[kQualityRegions];
1676 for (Int_t region=0; region<kQualityRegions; ++region)
1678 fQuality[region] = 0;
1679 ndfQual[region] = 0;
1683 Double_t newChi2 = 0;
1684 Double_t newChi2Limit150 = 0;
1686 for (Int_t i=1; i<=TMath::Min(diffMCUnfolded2->GetNbinsX(), fgkMaxParams+1); ++i)
1689 if (proj->GetBinError(i) > 0)
1691 value = diffMCUnfolded2->GetBinContent(i) / proj->GetBinError(i);
1692 newChi2 += value * value;
1693 if (i > 1 && i <= mcBinLimit)
1694 newChi2Limit150 += value * value;
1697 for (Int_t region=0; region<kQualityRegions; ++region)
1698 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
1700 fQuality[region] += TMath::Abs(value);
1705 diffMCUnfolded2->SetBinContent(i, value);
1708 // normalize region to the number of entries
1709 for (Int_t region=0; region<kQualityRegions; ++region)
1711 if (ndfQual[region] > 0)
1712 fQuality[region] /= ndfQual[region];
1713 Printf("Quality parameter %d (%d <= mult <= %d) is %f with %d df", region, fgQualityRegionsB[region], fgQualityRegionsE[region], fQuality[region], ndfQual[region]);
1718 // TODO another FAKE
1719 fLastChi2MC = newChi2Limit150 / (mcBinLimit - 1);
1720 Printf("Chi2 (2..%d) from (MC - Unfolded) / e(MC) is: %.2f ndf is %d --> chi2 / ndf = %.2f", mcBinLimit, newChi2Limit150, mcBinLimit - 1, fLastChi2MC);
1725 Printf("Chi2 (full range) from (MC - Unfolded) / e(MC) is: %.2f ndf is %d --> chi2 / ndf = %.2f", newChi2, ndf, ((ndf > 0) ? newChi2 / ndf : -1));
1727 diffMCUnfolded2->SetTitle("#chi^{2};Npart;(MC - Unfolded) / e(MC)");
1728 diffMCUnfolded2->GetYaxis()->SetRangeUser(-5, 5);
1729 diffMCUnfolded2->GetXaxis()->SetRangeUser(0, 200);
1730 diffMCUnfolded2->DrawCopy("HIST");
1733 canvas1->SaveAs(Form("%s.gif", canvas1->GetName()));
1736 //____________________________________________________________________
1737 void AliMultiplicityCorrection::FFT(Int_t dir, Int_t m, Double_t *x, Double_t *y)
1739 /*-------------------------------------------------------------------------
1740 This computes an in-place complex-to-complex FFT
1741 x and y are the real and imaginary arrays of 2^m points.
1742 dir = 1 gives forward transform
1743 dir = -1 gives reverse transform
1748 1 \ - j k 2 pi n / N
1749 X(n) = --- > x(k) e = forward transform
1758 X(n) = > x(k) e = forward transform
1764 Long_t nn, i, i1, j, k, i2, l, l1, l2;
1765 Double_t c1, c2, tx, ty, t1, t2, u1, u2, z;
1767 /* Calculate the number of points */
1769 for (i = 0; i < m; i++)
1772 /* Do the bit reversal */
1775 for (i= 0; i < nn - 1; i++) {
1792 /* Compute the FFT */
1796 for (l = 0; l < m; l++) {
1801 for (j = 0;j < l1; j++) {
1802 for (i = j; i < nn; i += l2) {
1804 t1 = u1 * x[i1] - u2 * y[i1];
1805 t2 = u1 * y[i1] + u2 * x[i1];
1811 z = u1 * c1 - u2 * c2;
1812 u2 = u1 * c2 + u2 * c1;
1815 c2 = TMath::Sqrt((1.0 - c1) / 2.0);
1818 c1 = TMath::Sqrt((1.0 + c1) / 2.0);
1821 /* Scaling for forward transform */
1823 for (i=0;i<nn;i++) {
1824 x[i] /= (Double_t)nn;
1825 y[i] /= (Double_t)nn;
1830 //____________________________________________________________________
1831 void AliMultiplicityCorrection::GetComparisonResults(Float_t* mc, Int_t* mcLimit, Float_t* residuals, Float_t* ratioAverage) const
1833 // Returns the chi2 between the MC and the unfolded ESD as well as between the ESD and the folded unfolded ESD
1834 // These values are computed during DrawComparison, thus this function picks up the
1840 *mcLimit = fLastChi2MCLimit;
1842 *residuals = fLastChi2Residuals;
1844 *ratioAverage = fRatioAverage;
1847 //____________________________________________________________________
1848 TH2F* AliMultiplicityCorrection::GetMultiplicityMC(Int_t i, EventType eventType)
1851 // returns the corresponding MC spectrum
1856 case kTrVtx : return fMultiplicityVtx[i]; break;
1857 case kMB : return fMultiplicityMB[i]; break;
1858 case kINEL : return fMultiplicityINEL[i]; break;
1864 //____________________________________________________________________
1865 TH1* AliMultiplicityCorrection::CalculateStdDev(TH1** results, Int_t max)
1867 // calculate standard deviation of (results[0] - results[k]) k=1...max-1
1868 // per bin one gets: sigma(r[0] - r[n]) / r[0]
1870 TH1* standardDeviation = (TH1*) results[0]->Clone("standardDeviation");
1871 standardDeviation->Reset();
1873 for (Int_t x=1; x<=results[0]->GetNbinsX(); x++)
1875 if (results[0]->GetBinContent(x) > 0)
1877 Double_t average = 0;
1878 for (Int_t n=1; n<max; ++n)
1879 average += results[n]->GetBinContent(x) - results[0]->GetBinContent(x);
1882 Double_t variance = 0;
1883 for (Int_t n=1; n<max; ++n)
1885 Double_t value = results[n]->GetBinContent(x) - results[0]->GetBinContent(x) - average;
1886 variance += value * value;
1890 Double_t standardDev = TMath::Sqrt(variance);
1891 standardDeviation->SetBinContent(x, standardDev / results[0]->GetBinContent(x));
1892 //Printf("sigma_%d is %f value %f --> error %f", x, standardDev, results[0]->GetBinContent(x), standardDev / results[0]->GetBinContent(x));
1896 return standardDeviation;
1899 //____________________________________________________________________
1900 TH1* AliMultiplicityCorrection::StatisticalUncertainty(MethodType methodType, Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Bool_t randomizeMeasured, Bool_t randomizeResponse, TH1* compareTo)
1903 // evaluates the uncertainty that arises from the non-infinite statistics in the response matrix
1904 // the function unfolds the spectrum using the default response matrix and several modified ones
1905 // the modified ones are created by randomizing each cell using poisson statistics with the mean = bin value
1906 // these unfolded results are compared to the first result gained with the default response OR to the histogram given
1907 // in <compareTo> (optional)
1909 // returns the error assigned to the measurement
1912 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1914 // initialize seed with current time
1915 gRandom->SetSeed(0);
1917 const Int_t kErrorIterations = 150;
1920 TH1* firstResult = 0;
1922 TH1** results = new TH1*[kErrorIterations];
1924 for (Int_t n=0; n<kErrorIterations; ++n)
1926 Printf("Iteration %d of %d...", n, kErrorIterations);
1928 // only done for chi2 minimization
1929 Bool_t createBigBin = kFALSE;
1930 if (methodType == kChi2Minimization)
1931 createBigBin = kTRUE;
1933 SetupCurrentHists(inputRange, fullPhaseSpace, eventType, createBigBin);
1935 TH1* measured = (TH1*) fCurrentESD->Clone("measured");
1939 if (randomizeResponse)
1941 // randomize response matrix
1942 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
1943 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
1944 fCurrentCorrelation->SetBinContent(i, j, gRandom->Poisson(fCurrentCorrelation->GetBinContent(i, j)));
1947 if (randomizeMeasured)
1949 // randomize measured spectrum
1950 for (Int_t x=1; x<=measured->GetNbinsX(); x++) // mult. axis
1952 Int_t randomValue = gRandom->Poisson(fCurrentESD->GetBinContent(x));
1953 measured->SetBinContent(x, randomValue);
1954 measured->SetBinError(x, TMath::Sqrt(randomValue));
1959 // only for bayesian method we have to do it before the call to Unfold...
1960 if (methodType == kBayesian)
1962 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
1964 // with this it is normalized to 1
1965 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
1967 // with this normalized to the given efficiency
1968 if (fCurrentEfficiency->GetBinContent(i) > 0)
1969 sum /= fCurrentEfficiency->GetBinContent(i);
1973 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
1977 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
1978 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
1982 fCurrentCorrelation->SetBinContent(i, j, 0);
1983 fCurrentCorrelation->SetBinError(i, j, 0);
1990 if (n == 0 && compareTo)
1992 // in this case we just store the histogram we want to compare to
1993 result = (TH1*) compareTo->Clone("compareTo");
1998 result = (TH1*) fMultiplicityESDCorrected[correlationID]->Clone(Form("result_%d", n));
2000 Int_t returnCode = -1;
2001 if (methodType == kChi2Minimization)
2003 returnCode = UnfoldWithMinuit(fCurrentCorrelation, fCurrentEfficiency, measured, 0, result, kFALSE);
2005 else if (methodType == kBayesian)
2006 returnCode = UnfoldWithBayesian(fCurrentCorrelation, fCurrentEfficiency, measured, 0, result, fgBayesianSmoothing, fgBayesianIterations);
2008 if (returnCode != 0)
2013 result->Scale(1.0 / result->Integral());
2017 firstResult = (TH1*) result->Clone("firstResult");
2019 maxError = (TH1*) result->Clone("maxError");
2025 TH1* ratio = (TH1*) firstResult->Clone("ratio");
2026 ratio->Divide(result);
2028 // find max. deviation
2029 for (Int_t x=1; x<=ratio->GetNbinsX(); x++)
2030 maxError->SetBinContent(x, TMath::Max(maxError->GetBinContent(x), TMath::Abs(1 - ratio->GetBinContent(x))));
2035 results[n] = result;
2038 // find covariance matrix
2039 // results[n] is X_x
2040 // cov. matrix is M_xy = E ( (X_x - E(X_x)) * (X_y - E(X_y))), with E() = expectation value
2042 Int_t nBins = results[0]->GetNbinsX();
2043 Float_t lowEdge = results[0]->GetXaxis()->GetBinLowEdge(1);
2044 Float_t upEdge = results[0]->GetXaxis()->GetBinUpEdge(nBins);
2046 // find average, E(X)
2047 TProfile* average = new TProfile("average", "average", nBins, lowEdge, upEdge);
2048 for (Int_t n=1; n<kErrorIterations; ++n)
2049 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2050 average->Fill(results[n]->GetXaxis()->GetBinCenter(x), results[n]->GetBinContent(x));
2051 //new TCanvas; average->DrawClone();
2054 TProfile2D* covMatrix = new TProfile2D("covMatrix", "covMatrix", nBins, lowEdge, upEdge, nBins, lowEdge, upEdge);
2056 for (Int_t n=1; n<kErrorIterations; ++n)
2057 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2058 for (Int_t y=1; y<=results[n]->GetNbinsX(); y++)
2060 // (X_x - E(X_x)) * (X_y - E(X_y)
2061 Float_t cov = (results[n]->GetBinContent(x) - average->GetBinContent(x)) * (results[n]->GetBinContent(y) - average->GetBinContent(y));
2062 covMatrix->Fill(results[n]->GetXaxis()->GetBinCenter(x), results[n]->GetXaxis()->GetBinCenter(y), cov);
2064 new TCanvas; covMatrix->DrawClone("COLZ");
2066 // // fill 2D histogram that contains deviation from first
2067 // TH2F* deviations = new TH2F("deviations", "deviations", nBins, lowEdge, upEdge, 1000, -0.01, 0.01);
2068 // for (Int_t n=1; n<kErrorIterations; ++n)
2069 // for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2070 // deviations->Fill(results[n]->GetXaxis()->GetBinCenter(x), results[n]->GetBinContent(x) - results[0]->GetBinContent(x));
2071 // //new TCanvas; deviations->DrawCopy("COLZ");
2073 // // get standard deviation "by hand"
2074 // for (Int_t x=1; x<=nBins; x++)
2076 // if (results[0]->GetBinContent(x) > 0)
2078 // TH1* proj = deviations->ProjectionY("projRMS", x, x, "e");
2079 // Float_t standardDev = proj->GetRMS(); // this is standard deviation in fact
2080 // //standardDeviation->SetBinContent(x, standardDev / results[0]->GetBinContent(x));
2081 // Printf("sigma_%d is %f value %f --> error %f", x, standardDev, results[0]->GetBinContent(x), standardDev / results[0]->GetBinContent(x));
2085 TH1* standardDeviation = CalculateStdDev(results, kErrorIterations);
2087 // compare maxError to RMS of profile (variable name: average)
2088 // first: calculate rms in percent of value
2089 TH1* rmsError = (TH1*) maxError->Clone("rmsError");
2092 // enable error to be standard deviation (see http://root.cern.ch/root/html/TProfile.html#TProfile:SetErrorOption)
2093 average->SetErrorOption("s");
2094 for (Int_t x=1; x<=rmsError->GetNbinsX(); x++)
2095 if (average->GetBinContent(x) > 0)
2096 rmsError->SetBinContent(x, average->GetBinError(x) / average->GetBinContent(x));
2098 // find maxError deviation from average (not from "first result"/mc as above)
2099 TH1* maxError2 = (TH1*) maxError->Clone("maxError2");
2101 for (Int_t n=1; n<kErrorIterations; ++n)
2102 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2103 if (average->GetBinContent(x) > 0)
2104 maxError2->SetBinContent(x, TMath::Max(maxError2->GetBinContent(x), TMath::Abs((results[n]->GetBinContent(x) - average->GetBinContent(x)) / average->GetBinContent(x))));
2106 //new TCanvas; maxError2->DrawCopy(); rmsError->SetLineColor(2); rmsError->DrawCopy("SAME"); standardDeviation->SetLineColor(3); standardDeviation->DrawCopy("SAME");
2108 // plot difference between average and MC/first result
2109 TH1* averageFirstRatio = (TH1*) results[0]->Clone("averageFirstRatio");
2110 averageFirstRatio->Reset();
2111 averageFirstRatio->Divide(results[0], average);
2113 //new TCanvas; results[0]->DrawCopy(); average->SetLineColor(2); average->DrawClone("SAME");
2114 //new TCanvas; averageFirstRatio->DrawCopy();
2117 for (Int_t n=0; n<kErrorIterations; ++n)
2121 // fill into result histogram
2122 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); ++i)
2123 fMultiplicityESDCorrected[correlationID]->SetBinContent(i, firstResult->GetBinContent(i));
2125 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); ++i)
2126 fMultiplicityESDCorrected[correlationID]->SetBinError(i, maxError->GetBinContent(i) * fMultiplicityESDCorrected[correlationID]->GetBinContent(i));
2128 return standardDeviation;
2131 //____________________________________________________________________
2132 void AliMultiplicityCorrection::ApplyBayesianMethod(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Float_t regPar, Int_t nIterations, TH1* initialConditions, Bool_t determineError)
2135 // correct spectrum using bayesian method
2138 // initialize seed with current time
2139 gRandom->SetSeed(0);
2141 SetupCurrentHists(inputRange, fullPhaseSpace, eventType, kFALSE);
2143 // normalize correction for given nPart
2144 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2146 // with this it is normalized to 1
2147 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
2149 // with this normalized to the given efficiency
2150 if (fCurrentEfficiency->GetBinContent(i) > 0)
2151 sum /= fCurrentEfficiency->GetBinContent(i);
2155 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
2159 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
2160 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
2164 fCurrentCorrelation->SetBinContent(i, j, 0);
2165 fCurrentCorrelation->SetBinError(i, j, 0);
2170 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
2172 if (UnfoldWithBayesian(fCurrentCorrelation, fCurrentEfficiency, fCurrentESD, initialConditions, fMultiplicityESDCorrected[correlationID], regPar, nIterations) != 0)
2175 if (!determineError)
2177 Printf("AliMultiplicityCorrection::ApplyBayesianMethod: WARNING: No errors calculated.");
2181 // evaluate errors, this is done by randomizing the measured spectrum following Poission statistics
2182 // this (new) measured spectrum is then unfolded and the different to the result from the "real" measured
2183 // spectrum calculated. This is performed N times and the sigma is taken as the statistical
2184 // error of the unfolding method itself.
2186 const Int_t kErrorIterations = 20;
2188 printf("Spectrum unfolded. Determining error (%d iterations)...\n", kErrorIterations);
2190 TH1* randomized = (TH1*) fCurrentESD->Clone("randomized");
2191 TH1* resultArray[kErrorIterations+1];
2192 for (Int_t n=0; n<kErrorIterations; ++n)
2194 // randomize the content of clone following a poisson with the mean = the value of that bin
2195 for (Int_t x=1; x<=randomized->GetNbinsX(); x++) // mult. axis
2197 Int_t randomValue = gRandom->Poisson(fCurrentESD->GetBinContent(x));
2198 //printf("%d --> %d\n", fCurrentESD->GetBinContent(x), randomValue);
2199 randomized->SetBinContent(x, randomValue);
2200 randomized->SetBinError(x, TMath::Sqrt(randomValue));
2203 TH1* result2 = (TH1*) fMultiplicityESDCorrected[correlationID]->Clone("result2");
2205 if (UnfoldWithBayesian(fCurrentCorrelation, fCurrentEfficiency, randomized, initialConditions, result2, regPar, nIterations) != 0)
2208 result2->Scale(1.0 / result2->Integral());
2210 resultArray[n+1] = result2;
2214 resultArray[0] = fMultiplicityESDCorrected[correlationID];
2215 TH1* error = CalculateStdDev(resultArray, kErrorIterations+1);
2217 for (Int_t n=0; n<kErrorIterations; ++n)
2218 delete resultArray[n+1];
2220 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); ++i)
2221 fMultiplicityESDCorrected[correlationID]->SetBinError(i, error->GetBinContent(i) * fMultiplicityESDCorrected[correlationID]->GetBinContent(i));
2226 //____________________________________________________________________
2227 Int_t AliMultiplicityCorrection::UnfoldWithBayesian(TH1* correlation, TH1* aEfficiency, TH1* measured, TH1* initialConditions, TH1* aResult, Float_t regPar, Int_t nIterations)
2230 // unfolds a spectrum
2233 if (measured->Integral() <= 0)
2235 Printf("AliMultiplicityCorrection::UnfoldWithBayesian: ERROR: The measured spectrum is empty");
2239 const Int_t kStartBin = 0;
2241 const Int_t kMaxM = fgkMaxInput; //<= fCurrentCorrelation->GetNbinsY(); // max measured axis
2242 const Int_t kMaxT = fgkMaxParams; //<= fCurrentCorrelation->GetNbinsX(); // max true axis
2244 // convergence limit: kMaxT * 0.001^2 = kMaxT * 1e-6 (e.g. 250 bins --> 2.5 e-4)
2245 const Double_t kConvergenceLimit = kMaxT * 1e-6;
2247 // store information in arrays, to increase processing speed (~ factor 5)
2248 Double_t measuredCopy[kMaxM];
2249 Double_t measuredError[kMaxM];
2250 Double_t prior[kMaxT];
2251 Double_t result[kMaxT];
2252 Double_t efficiency[kMaxT];
2254 Double_t response[kMaxT][kMaxM];
2255 Double_t inverseResponse[kMaxT][kMaxM];
2257 // for normalization
2258 Float_t measuredIntegral = measured->Integral();
2259 for (Int_t m=0; m<kMaxM; m++)
2261 measuredCopy[m] = measured->GetBinContent(m+1) / measuredIntegral;
2262 measuredError[m] = measured->GetBinError(m+1) / measuredIntegral;
2264 for (Int_t t=0; t<kMaxT; t++)
2266 response[t][m] = correlation->GetBinContent(t+1, m+1);
2267 inverseResponse[t][m] = 0;
2271 for (Int_t t=0; t<kMaxT; t++)
2273 efficiency[t] = aEfficiency->GetBinContent(t+1);
2274 prior[t] = measuredCopy[t];
2278 // pick prior distribution
2279 if (initialConditions)
2281 printf("Using different starting conditions...\n");
2282 // for normalization
2283 Float_t inputDistIntegral = initialConditions->Integral();
2284 for (Int_t i=0; i<kMaxT; i++)
2285 prior[i] = initialConditions->GetBinContent(i+1) / inputDistIntegral;
2288 //TH1F* convergence = new TH1F("convergence", "convergence", 200, 0.5, 200.5);
2291 for (Int_t i=0; i<nIterations || nIterations < 0; i++)
2293 //printf(" iteration %i \n", i);
2295 // calculate IR from Beyes theorem
2296 // IR_ji = R_ij * prior_i / sum_k(R_kj * prior_k)
2298 Double_t chi2Measured = 0;
2299 for (Int_t m=0; m<kMaxM; m++)
2302 for (Int_t t = kStartBin; t<kMaxT; t++)
2303 norm += response[t][m] * prior[t];
2305 // calc. chi2: (measured - response * prior) / error
2306 if (measuredError[m] > 0)
2308 Double_t value = (measuredCopy[m] - norm) / measuredError[m];
2309 chi2Measured += value * value;
2314 for (Int_t t = kStartBin; t<kMaxT; t++)
2315 inverseResponse[t][m] = response[t][m] * prior[t] / norm;
2319 for (Int_t t = kStartBin; t<kMaxT; t++)
2320 inverseResponse[t][m] = 0;
2323 //Printf("chi2Measured of the last prior is %e", chi2Measured);
2325 for (Int_t t = kStartBin; t<kMaxT; t++)
2328 for (Int_t m=0; m<kMaxM; m++)
2329 value += inverseResponse[t][m] * measuredCopy[m];
2331 if (efficiency[t] > 0)
2332 result[t] = value / efficiency[t];
2337 Double_t chi2LastIter = 0;
2338 // regularization (simple smoothing)
2339 for (Int_t t=kStartBin; t<kMaxT; t++)
2341 Float_t newValue = 0;
2342 // 0 bin excluded from smoothing
2343 if (t > kStartBin+1 && t<kMaxT-1)
2345 Float_t average = (result[t-1] + result[t] + result[t+1]) / 3;
2347 // weight the average with the regularization parameter
2348 newValue = (1 - regPar) * result[t] + regPar * average;
2351 newValue = result[t];
2353 // calculate chi2 (change from last iteration)
2354 if (prior[t] > 1e-5)
2356 Double_t diff = (prior[t] - newValue) / prior[t];
2357 chi2LastIter += diff * diff;
2360 prior[t] = newValue;
2362 //printf("Chi2 of %d iteration = %e\n", i, chi2LastIter);
2363 //convergence->Fill(i+1, chi2LastIter);
2365 if (nIterations < 0 && chi2LastIter < kConvergenceLimit)
2367 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);
2372 // DrawComparison(Form("Bayesian_%d", i), mcTarget, correlationID, kTRUE, eventType);
2373 } // end of iterations
2375 //new TCanvas; convergence->DrawCopy(); gPad->SetLogy();
2376 //delete convergence;
2378 for (Int_t t=0; t<kMaxT; t++)
2379 aResult->SetBinContent(t+1, result[t]);
2384 // Calculate the covariance matrix, all arguments are taken from NIM,A362,487-498,1995
2386 /*printf("Calculating covariance matrix. This may take some time...\n");
2388 // TODO check if this is the right one...
2389 TH1* sumHist = GetMultiplicityMC(inputRange, eventType)->ProjectionY("sumHist", 1, GetMultiplicityMC(inputRange, eventType)->GetNbinsX());
2391 Int_t xBins = hInverseResponseBayes->GetNbinsX();
2392 Int_t yBins = hInverseResponseBayes->GetNbinsY();
2394 // calculate "unfolding matrix" Mij
2395 Float_t matrixM[251][251];
2396 for (Int_t i=1; i<=xBins; i++)
2398 for (Int_t j=1; j<=yBins; j++)
2400 if (fCurrentEfficiency->GetBinContent(i) > 0)
2401 matrixM[i-1][j-1] = hInverseResponseBayes->GetBinContent(i, j) / fCurrentEfficiency->GetBinContent(i);
2403 matrixM[i-1][j-1] = 0;
2407 Float_t* vectorn = new Float_t[yBins];
2408 for (Int_t j=1; j<=yBins; j++)
2409 vectorn[j-1] = fCurrentESD->GetBinContent(j);
2411 // first part of covariance matrix, depends on input distribution n(E)
2412 Float_t cov1[251][251];
2414 Float_t nEvents = fCurrentESD->Integral(); // N
2419 for (Int_t k=0; k<xBins; k++)
2421 printf("In Cov1: %d\n", k);
2422 for (Int_t l=0; l<yBins; l++)
2426 // sum_j Mkj Mlj n(Ej) * (1 - n(Ej) / N)
2427 for (Int_t j=0; j<yBins; j++)
2428 cov1[k][l] += matrixM[k][j] * matrixM[l][j] * vectorn[j]
2429 * (1.0 - vectorn[j] / nEvents);
2431 // - sum_i,j (i != j) Mki Mlj n(Ei) n(Ej) / N
2432 for (Int_t i=0; i<yBins; i++)
2433 for (Int_t j=0; j<yBins; j++)
2437 cov1[k][l] -= matrixM[k][i] * matrixM[l][j] * vectorn[i]
2438 * vectorn[j] / nEvents;
2443 printf("Cov1 finished\n");
2445 TH2F* cov = (TH2F*) hInverseResponseBayes->Clone("cov");
2448 for (Int_t i=1; i<=xBins; i++)
2449 for (Int_t j=1; j<=yBins; j++)
2450 cov->SetBinContent(i, j, cov1[i-1][j-1]);
2455 // second part of covariance matrix, depends on response matrix
2456 Float_t cov2[251][251];
2458 // Cov[P(Er|Cu), P(Es|Cu)] term
2459 Float_t covTerm[100][100][100];
2460 for (Int_t r=0; r<yBins; r++)
2461 for (Int_t u=0; u<xBins; u++)
2462 for (Int_t s=0; s<yBins; s++)
2465 covTerm[r][u][s] = 1.0 / sumHist->GetBinContent(u+1) * hResponse->GetBinContent(u+1, r+1)
2466 * (1.0 - hResponse->GetBinContent(u+1, r+1));
2468 covTerm[r][u][s] = - 1.0 / sumHist->GetBinContent(u+1) * hResponse->GetBinContent(u+1, r+1)
2469 * hResponse->GetBinContent(u+1, s+1);
2472 for (Int_t k=0; k<xBins; k++)
2473 for (Int_t l=0; l<yBins; l++)
2476 printf("In Cov2: %d %d\n", k, l);
2477 for (Int_t i=0; i<yBins; i++)
2478 for (Int_t j=0; j<yBins; j++)
2480 //printf("In Cov2: %d %d %d %d\n", k, l, i, j);
2481 // calculate Cov(Mki, Mlj) = sum{ru},{su} ...
2483 for (Int_t r=0; r<yBins; r++)
2484 for (Int_t u=0; u<xBins; u++)
2485 for (Int_t s=0; s<yBins; s++)
2487 if (hResponse->GetBinContent(u+1, r+1) == 0 || hResponse->GetBinContent(u+1, s+1) == 0
2488 || hResponse->GetBinContent(u+1, i+1) == 0)
2491 tmpCov += BayesCovarianceDerivate(matrixM, hResponse, fCurrentEfficiency, k, i, r, u)
2492 * BayesCovarianceDerivate(matrixM, hResponse, fCurrentEfficiency, l, j, s, u)
2496 cov2[k][l] += fCurrentESD->GetBinContent(i+1) * fCurrentESD->GetBinContent(j+1) * tmpCov;
2500 printf("Cov2 finished\n");
2502 for (Int_t i=1; i<=xBins; i++)
2503 for (Int_t j=1; j<=yBins; j++)
2504 cov->SetBinContent(i, j, cov1[i-1][j-1] + cov2[i-1][j-1]);
2507 cov->Draw("COLZ");*/
2510 //____________________________________________________________________
2511 Float_t AliMultiplicityCorrection::BayesCovarianceDerivate(Float_t matrixM[251][251], TH2* hResponse, Int_t k, Int_t i, Int_t r, Int_t u)
2514 // helper function for the covariance matrix of the bayesian method
2519 if (k == u && r == i)
2520 result += 1.0 / hResponse->GetBinContent(u+1, r+1);
2523 result -= 1.0 / fCurrentEfficiency->GetBinContent(u+1);
2526 result -= matrixM[u][i] * fCurrentEfficiency->GetBinContent(u+1) / hResponse->GetBinContent(u+1, i+1);
2528 result *= matrixM[k][i];
2533 //____________________________________________________________________
2534 void AliMultiplicityCorrection::ApplyLaszloMethod(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType)
2537 // correct spectrum using bayesian method
2542 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
2543 Int_t mcTarget = ((fullPhaseSpace == kFALSE) ? inputRange : 4);
2545 SetupCurrentHists(inputRange, fullPhaseSpace, eventType, kFALSE);
2547 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
2549 // TODO should be taken from correlation map
2550 //TH1* sumHist = GetMultiplicityMC(inputRange, eventType)->ProjectionY("sumHist", 1, GetMultiplicityMC(inputRange, eventType)->GetNbinsX());
2552 // normalize correction for given nPart
2553 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2555 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
2556 //Double_t sum = sumHist->GetBinContent(i);
2559 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
2562 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
2563 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
2568 fCurrentCorrelation->Draw("COLZ");
2571 fCurrentEfficiency = ((TH2*) fCurrentCorrelation)->ProjectionX("eff");
2573 // pick prior distribution
2574 TH1F* hPrior = (TH1F*)fCurrentESD->Clone("prior");
2575 Float_t norm = 1; //hPrior->Integral();
2576 for (Int_t t=1; t<=hPrior->GetNbinsX(); t++)
2577 hPrior->SetBinContent(t, hPrior->GetBinContent(t)/norm);
2579 // zero distribution
2580 TH1F* zero = (TH1F*)hPrior->Clone("zero");
2583 TH1F* hTemp = (TH1F*)fCurrentESD->Clone("temp");
2587 TH2F* hResponse = (TH2F*) fCurrentCorrelation;
2590 Int_t iterations = 25;
2591 for (Int_t i=0; i<iterations; i++)
2593 //printf(" iteration %i \n", i);
2595 for (Int_t m=1; m<=hResponse->GetNbinsY(); m++)
2598 for (Int_t t = 1; t<=hResponse->GetNbinsX(); t++)
2599 value += hResponse->GetBinContent(t, m) * hPrior->GetBinContent(t);
2600 hTemp->SetBinContent(m, value);
2601 //printf("%d %f %f %f\n", m, zero->GetBinContent(m), hPrior->GetBinContent(m), value);
2604 // regularization (simple smoothing)
2605 TH1F* hTrueSmoothed = (TH1F*) hTemp->Clone("truesmoothed");
2607 for (Int_t t=2; t<hTrueSmoothed->GetNbinsX(); t++)
2609 Float_t average = (hTemp->GetBinContent(t-1) / hTemp->GetBinWidth(t-1)
2610 + hTemp->GetBinContent(t) / hTemp->GetBinWidth(t)
2611 + hTemp->GetBinContent(t+1) / hTemp->GetBinWidth(t+1)) / 3.;
2612 average *= hTrueSmoothed->GetBinWidth(t);
2614 // weight the average with the regularization parameter
2615 hTrueSmoothed->SetBinContent(t, (1-regPar) * hTemp->GetBinContent(t) + regPar * average);
2618 for (Int_t m=1; m<=hResponse->GetNbinsY(); m++)
2619 hTemp->SetBinContent(m, zero->GetBinContent(m) + hPrior->GetBinContent(m) - hTrueSmoothed->GetBinContent(m));
2622 for (Int_t t=1; t<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); t++)
2624 fMultiplicityESDCorrected[correlationID]->SetBinContent(t, hTemp->GetBinContent(t));
2625 fMultiplicityESDCorrected[correlationID]->SetBinError(t, 0.05 * hTemp->GetBinContent(t)); // TODO
2627 //printf(" bin %d content %f \n", t, fMultiplicityESDCorrected[correlationID]->GetBinContent(t));
2631 // calculate chi2 (change from last iteration)
2634 // use smoothed true (normalized) as new prior
2635 norm = 1; //hTrueSmoothed->Integral();
2637 for (Int_t t=1; t<hTrueSmoothed->GetNbinsX(); t++)
2639 Float_t newValue = hTemp->GetBinContent(t)/norm;
2640 Float_t diff = hPrior->GetBinContent(t) - newValue;
2641 chi2 += (Double_t) diff * diff;
2643 hPrior->SetBinContent(t, newValue);
2646 printf("Chi2 of %d iteration = %.10f\n", i, chi2);
2649 DrawComparison(Form("Laszlo_%d", i), inputRange, fullPhaseSpace, kTRUE, GetMultiplicityMC(mcTarget, eventType)->ProjectionY());
2651 delete hTrueSmoothed;
2652 } // end of iterations
2654 DrawComparison("Laszlo", inputRange, fullPhaseSpace, kTRUE, GetMultiplicityMC(mcTarget, eventType)->ProjectionY());
2657 //____________________________________________________________________
2658 void AliMultiplicityCorrection::ApplyGaussianMethod(Int_t inputRange, Bool_t fullPhaseSpace)
2661 // correct spectrum using a simple Gaussian approach, that is model-dependent
2664 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
2665 Int_t mcTarget = ((fullPhaseSpace == kFALSE) ? inputRange : 4);
2667 SetupCurrentHists(inputRange, fullPhaseSpace, kTrVtx, kFALSE);
2669 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
2671 TH1D* correction = dynamic_cast<TH1D*> (fCurrentESD->Clone("GaussianMean"));
2672 correction->SetTitle("GaussianMean");
2674 TH1D* correctionWidth = dynamic_cast<TH1D*> (fCurrentESD->Clone("GaussianWidth"));
2675 correction->SetTitle("GaussianWidth");
2677 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2679 TH1D* proj = (dynamic_cast<TH2*> (fCurrentCorrelation))->ProjectionX("_px", i, i+1);
2680 proj->Fit("gaus", "0Q");
2681 correction->SetBinContent(i, proj->GetFunction("gaus")->GetParameter(1));
2682 correctionWidth->SetBinContent(i, proj->GetFunction("gaus")->GetParameter(2));
2686 // draw for debugging
2689 proj->GetFunction("gaus")->DrawCopy("SAME");
2692 TH1* target = fMultiplicityESDCorrected[correlationID];
2694 Int_t nBins = target->GetNbinsX()*10+1;
2695 Float_t* binning = new Float_t[nBins];
2696 for (Int_t i=1; i<=target->GetNbinsX(); ++i)
2697 for (Int_t j=0; j<10; ++j)
2698 binning[(i-1)*10 + j] = target->GetXaxis()->GetBinLowEdge(i) + target->GetXaxis()->GetBinWidth(i) / 10 * j;
2700 binning[nBins-1] = target->GetXaxis()->GetBinUpEdge(target->GetNbinsX());
2702 TH1F* fineBinned = new TH1F("targetFineBinned", "targetFineBinned", nBins-1, binning);
2704 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2706 Float_t mean = correction->GetBinContent(i);
2707 Float_t width = correctionWidth->GetBinContent(i);
2709 Int_t fillBegin = fineBinned->FindBin(mean - width * 5);
2710 Int_t fillEnd = fineBinned->FindBin(mean + width * 5);
2711 //printf("bin %d mean %f width %f, filling from %d to %d\n", i, mean, width, fillBegin, fillEnd);
2713 for (Int_t j=fillBegin; j <= fillEnd; ++j)
2715 fineBinned->AddBinContent(j, TMath::Gaus(fineBinned->GetXaxis()->GetBinCenter(j), mean, width, kTRUE) * fCurrentESD->GetBinContent(i));
2719 for (Int_t i=1; i<=target->GetNbinsX(); ++i)
2722 for (Int_t j=1; j<=10; ++j)
2723 sum += fineBinned->GetBinContent((i-1)*10 + j);
2724 target->SetBinContent(i, sum / 10);
2729 DrawComparison("Gaussian", inputRange, fullPhaseSpace, kFALSE, GetMultiplicityMC(mcTarget, kTrVtx)->ProjectionY());
2732 //____________________________________________________________________
2733 TH2F* AliMultiplicityCorrection::CalculateMultiplicityESD(TH1* inputMC, Int_t correlationMap)
2735 // runs the distribution given in inputMC through the response matrix identified by
2736 // correlationMap and produces a measured distribution
2737 // although it is a TH2F the vertex axis is not used at the moment and all entries are filled in mid-vertex
2738 // if normalized is set, inputMC is expected to be normalized to the bin width
2743 if (correlationMap < 0 || correlationMap >= kCorrHists)
2746 // empty under/overflow bins in x, otherwise Project3D takes them into account
2747 TH3* hist = fCorrelation[correlationMap];
2748 for (Int_t y=0; y<=hist->GetYaxis()->GetNbins()+1; ++y)
2750 for (Int_t z=0; z<=hist->GetZaxis()->GetNbins()+1; ++z)
2752 hist->SetBinContent(0, y, z, 0);
2753 hist->SetBinContent(hist->GetXaxis()->GetNbins()+1, y, z, 0);
2757 TH2* corr = (TH2*) hist->Project3D("zy");
2758 //corr->Rebin2D(2, 1);
2760 Printf("Correction histogram used for convolution has %f entries", corr->Integral());
2762 // normalize correction for given nPart
2763 for (Int_t i=1; i<=corr->GetNbinsX(); ++i)
2765 Double_t sum = corr->Integral(i, i, 1, corr->GetNbinsY());
2769 for (Int_t j=1; j<=corr->GetNbinsY(); ++j)
2772 corr->SetBinContent(i, j, corr->GetBinContent(i, j) / sum);
2773 corr->SetBinError(i, j, corr->GetBinError(i, j) / sum);
2777 TH2F* target = dynamic_cast<TH2F*> (fMultiplicityESD[0]->Clone(Form("%s_measured", inputMC->GetName())));
2780 for (Int_t meas=1; meas<=corr->GetNbinsY(); ++meas)
2782 Float_t measured = 0;
2785 for (Int_t gen=1; gen<=corr->GetNbinsX(); ++gen)
2787 Int_t mcGenBin = inputMC->GetXaxis()->FindBin(corr->GetXaxis()->GetBinCenter(gen));
2789 measured += inputMC->GetBinContent(mcGenBin) * corr->GetBinContent(gen, meas);
2790 error += inputMC->GetBinError(mcGenBin) * corr->GetBinContent(gen, meas);
2793 //printf("%f +- %f ; %f +- %f \n", inputMC->GetBinContent(meas), inputMC->GetBinError(meas), measured, error);
2795 target->SetBinContent(1 + target->GetNbinsX() / 2, meas, measured);
2796 target->SetBinError(1 + target->GetNbinsX() / 2, meas, error);
2802 //____________________________________________________________________
2803 void AliMultiplicityCorrection::SetGenMeasFromFunc(TF1* inputMC, Int_t id)
2805 // uses the given function to fill the input MC histogram and generates from that
2806 // the measured histogram by applying the response matrix
2807 // this can be used to evaluate if the methods work indepedently of the input
2809 // WARNING does not respect the vertex distribution, just fills central vertex bin
2814 if (id < 0 || id >= kESDHists)
2817 TH2F* mc = fMultiplicityVtx[id];
2821 for (Int_t i=1; i<=mc->GetNbinsY(); ++i)
2823 mc->SetBinContent(mc->GetNbinsX() / 2 + 1, i, inputMC->Eval(mc->GetYaxis()->GetBinCenter(i)) * mc->GetYaxis()->GetBinWidth(i));
2824 mc->SetBinError(mc->GetNbinsX() / 2 + 1, i, 0);
2830 TH1* proj = mc->ProjectionY();
2832 TString tmp(fMultiplicityESD[id]->GetName());
2833 delete fMultiplicityESD[id];
2834 fMultiplicityESD[id] = CalculateMultiplicityESD(proj, id);
2835 fMultiplicityESD[id]->SetName(tmp);