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 = 120; // bins in measured histogram
47 const Int_t AliMultiplicityCorrection::fgkMaxParams = 120; // 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 = 10; // 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] = {1, 20, 70};
70 Int_t AliMultiplicityCorrection::fgQualityRegionsE[kQualityRegions] = {10, 65, 80};
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] = 1;
83 fgQualityRegionsE[0] = 10;
85 fgQualityRegionsB[1] = 20;
86 fgQualityRegionsE[1] = 65;
88 fgQualityRegionsB[2] = 70;
89 fgQualityRegionsE[2] = 80;
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;
125 fMultiplicityNSD[i] = 0;
128 for (Int_t i = 0; i < kCorrHists; ++i)
131 fMultiplicityESDCorrected[i] = 0;
134 for (Int_t i = 0; i < kQualityRegions; ++i)
138 //____________________________________________________________________
139 AliMultiplicityCorrection* AliMultiplicityCorrection::Open(const char* fileName, const char* folderName)
141 // opens the given file, reads the multiplicity from the given folder and returns the object
143 TFile* file = TFile::Open(fileName);
146 Printf("ERROR: Could not open %s", fileName);
150 AliMultiplicityCorrection* mult = new AliMultiplicityCorrection(folderName, folderName);
151 mult->LoadHistograms();
153 // TODO closing the file does not work here, because the histograms cannot be read anymore. LoadHistograms need to be adapted
158 //____________________________________________________________________
159 AliMultiplicityCorrection::AliMultiplicityCorrection(const Char_t* name, const Char_t* title) :
162 fCurrentCorrelation(0),
163 fCurrentEfficiency(0),
167 fLastChi2Residuals(0),
174 // do not add this hists to the directory
175 Bool_t oldStatus = TH1::AddDirectoryStatus();
176 TH1::AddDirectory(kFALSE);
178 /*Float_t binLimitsVtx[] = {-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10};
179 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,
180 10.5, 11.5, 12.5, 13.5, 14.5, 15.5, 16.5, 17.5, 18.5, 19.5,
181 20.5, 21.5, 22.5, 23.5, 24.5, 25.5, 26.5, 27.5, 28.5, 29.5,
182 30.5, 31.5, 32.5, 33.5, 34.5, 35.5, 36.5, 37.5, 38.5, 39.5,
183 40.5, 41.5, 42.5, 43.5, 44.5, 45.5, 46.5, 47.5, 48.5, 49.5,
184 50.5, 55.5, 60.5, 65.5, 70.5, 75.5, 80.5, 85.5, 90.5, 95.5,
185 100.5, 105.5, 110.5, 115.5, 120.5, 125.5, 130.5, 135.5, 140.5, 145.5,
186 150.5, 160.5, 170.5, 180.5, 190.5, 200.5, 210.5, 220.5, 230.5, 240.5,
187 250.5, 275.5, 300.5, 325.5, 350.5, 375.5, 400.5, 425.5, 450.5, 475.5,
189 //525.5, 550.5, 575.5, 600.5, 625.5, 650.5, 675.5, 700.5, 725.5,
190 //750.5, 775.5, 800.5, 825.5, 850.5, 875.5, 900.5, 925.5, 950.5, 975.5,
193 #define VTXBINNING 10, binLimitsVtx
194 #define NBINNING fgkMaxParams, binLimitsN*/
196 #define NBINNING 201, -0.5, 200.5
197 #define VTXBINNING 1, -6, 6
199 for (Int_t i = 0; i < kESDHists; ++i)
200 fMultiplicityESD[i] = new TH2F(Form("fMultiplicityESD%d", i), "fMultiplicityESD;vtx-z;Ntracks;Count", VTXBINNING, NBINNING);
202 for (Int_t i = 0; i < kMCHists; ++i)
204 fMultiplicityVtx[i] = dynamic_cast<TH2F*> (fMultiplicityESD[0]->Clone(Form("fMultiplicityVtx%d", i)));
205 fMultiplicityVtx[i]->SetTitle("fMultiplicityVtx;vtx-z;Npart");
207 fMultiplicityMB[i] = dynamic_cast<TH2F*> (fMultiplicityVtx[0]->Clone(Form("fMultiplicityMB%d", i)));
208 fMultiplicityMB[i]->SetTitle("fMultiplicityMB");
210 fMultiplicityINEL[i] = dynamic_cast<TH2F*> (fMultiplicityVtx[0]->Clone(Form("fMultiplicityINEL%d", i)));
211 fMultiplicityINEL[i]->SetTitle("fMultiplicityINEL");
213 fMultiplicityNSD[i] = dynamic_cast<TH2F*> (fMultiplicityVtx[0]->Clone(Form("fMultiplicityNSD%d", i)));
214 fMultiplicityNSD[i]->SetTitle("fMultiplicityNSD");
217 for (Int_t i = 0; i < kCorrHists; ++i)
219 fCorrelation[i] = new TH3F(Form("fCorrelation%d", i), "fCorrelation;vtx-z;Npart;Ntracks", VTXBINNING, NBINNING, NBINNING);
220 fMultiplicityESDCorrected[i] = new TH1F(Form("fMultiplicityESDCorrected%d", i), "fMultiplicityESDCorrected;Npart;dN/dN", NBINNING);
223 TH1::AddDirectory(oldStatus);
226 //____________________________________________________________________
227 AliMultiplicityCorrection::~AliMultiplicityCorrection()
233 Printf("AliMultiplicityCorrection::~AliMultiplicityCorrection called");
235 for (Int_t i = 0; i < kESDHists; ++i)
237 if (fMultiplicityESD[i])
238 delete fMultiplicityESD[i];
239 fMultiplicityESD[i] = 0;
242 for (Int_t i = 0; i < kMCHists; ++i)
244 if (fMultiplicityVtx[i])
245 delete fMultiplicityVtx[i];
246 fMultiplicityVtx[i] = 0;
248 if (fMultiplicityMB[i])
249 delete fMultiplicityMB[i];
250 fMultiplicityMB[i] = 0;
252 if (fMultiplicityINEL[i])
253 delete fMultiplicityINEL[i];
254 fMultiplicityINEL[i] = 0;
256 if (fMultiplicityNSD[i])
257 delete fMultiplicityNSD[i];
258 fMultiplicityNSD[i] = 0;
261 for (Int_t i = 0; i < kCorrHists; ++i)
264 delete fCorrelation[i];
267 if (fMultiplicityESDCorrected[i])
268 delete fMultiplicityESDCorrected[i];
269 fMultiplicityESDCorrected[i] = 0;
273 //____________________________________________________________________
274 Long64_t AliMultiplicityCorrection::Merge(TCollection* list)
276 // Merge a list of AliMultiplicityCorrection objects with this (needed for
278 // Returns the number of merged objects (including this).
286 TIterator* iter = list->MakeIterator();
289 // collections of all histograms
290 TList collections[kESDHists+kMCHists*4+kCorrHists*2];
293 while ((obj = iter->Next())) {
295 AliMultiplicityCorrection* entry = dynamic_cast<AliMultiplicityCorrection*> (obj);
299 for (Int_t i = 0; i < kESDHists; ++i)
300 collections[i].Add(entry->fMultiplicityESD[i]);
302 for (Int_t i = 0; i < kMCHists; ++i)
304 collections[kESDHists+i].Add(entry->fMultiplicityVtx[i]);
305 collections[kESDHists+kMCHists+i].Add(entry->fMultiplicityMB[i]);
306 collections[kESDHists+kMCHists*2+i].Add(entry->fMultiplicityINEL[i]);
307 collections[kESDHists+kMCHists*3+i].Add(entry->fMultiplicityNSD[i]);
310 for (Int_t i = 0; i < kCorrHists; ++i)
311 collections[kESDHists+kMCHists*4+i].Add(entry->fCorrelation[i]);
313 for (Int_t i = 0; i < kCorrHists; ++i)
314 collections[kESDHists+kMCHists*4+kCorrHists+i].Add(entry->fMultiplicityESDCorrected[i]);
319 for (Int_t i = 0; i < kESDHists; ++i)
320 fMultiplicityESD[i]->Merge(&collections[i]);
322 for (Int_t i = 0; i < kMCHists; ++i)
324 fMultiplicityVtx[i]->Merge(&collections[kESDHists+i]);
325 fMultiplicityMB[i]->Merge(&collections[kESDHists+kMCHists+i]);
326 fMultiplicityINEL[i]->Merge(&collections[kESDHists+kMCHists*2+i]);
327 fMultiplicityNSD[i]->Merge(&collections[kESDHists+kMCHists*3+i]);
330 for (Int_t i = 0; i < kCorrHists; ++i)
331 fCorrelation[i]->Merge(&collections[kESDHists+kMCHists*4+i]);
333 for (Int_t i = 0; i < kCorrHists; ++i)
334 fMultiplicityESDCorrected[i]->Merge(&collections[kESDHists+kMCHists*4+kCorrHists+i]);
341 //____________________________________________________________________
342 Bool_t AliMultiplicityCorrection::LoadHistograms(const Char_t* dir)
345 // loads the histograms from a file
346 // if dir is empty a directory with the name of this object is taken (like in SaveHistogram)
352 if (!gDirectory->cd(dir))
355 // store old hists to delete them later
357 oldObjects.SetOwner(1);
358 for (Int_t i = 0; i < kESDHists; ++i)
359 if (fMultiplicityESD[i])
360 oldObjects.Add(fMultiplicityESD[i]);
362 for (Int_t i = 0; i < kMCHists; ++i)
364 if (fMultiplicityVtx[i])
365 oldObjects.Add(fMultiplicityVtx[i]);
366 if (fMultiplicityMB[i])
367 oldObjects.Add(fMultiplicityMB[i]);
368 if (fMultiplicityINEL[i])
369 oldObjects.Add(fMultiplicityINEL[i]);
370 if (fMultiplicityNSD[i])
371 oldObjects.Add(fMultiplicityNSD[i]);
374 for (Int_t i = 0; i < kCorrHists; ++i)
376 oldObjects.Add(fCorrelation[i]);
380 Bool_t success = kTRUE;
382 for (Int_t i = 0; i < kESDHists; ++i)
384 fMultiplicityESD[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityESD[i]->GetName()));
385 if (!fMultiplicityESD[i])
389 for (Int_t i = 0; i < kMCHists; ++i)
391 fMultiplicityVtx[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityVtx[i]->GetName()));
392 fMultiplicityMB[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityMB[i]->GetName()));
393 fMultiplicityINEL[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityINEL[i]->GetName()));
394 fMultiplicityNSD[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityNSD[i]->GetName()));
395 if (!fMultiplicityVtx[i] || !fMultiplicityMB[i] || !fMultiplicityINEL[i])
399 for (Int_t i = 0; i < kCorrHists; ++i)
401 fCorrelation[i] = dynamic_cast<TH3F*> (gDirectory->Get(fCorrelation[i]->GetName()));
402 if (!fCorrelation[i])
404 fMultiplicityESDCorrected[i] = dynamic_cast<TH1F*> (gDirectory->Get(fMultiplicityESDCorrected[i]->GetName()));
405 if (!fMultiplicityESDCorrected[i])
409 gDirectory->cd("..");
417 //____________________________________________________________________
418 void AliMultiplicityCorrection::SaveHistograms(const char* dir)
421 // saves the histograms
427 gDirectory->mkdir(dir);
430 for (Int_t i = 0; i < kESDHists; ++i)
431 if (fMultiplicityESD[i])
433 fMultiplicityESD[i]->Write();
434 fMultiplicityESD[i]->ProjectionY(Form("%s_px", fMultiplicityESD[i]->GetName()), 1, fMultiplicityESD[i]->GetNbinsX())->Write();
437 for (Int_t i = 0; i < kMCHists; ++i)
439 if (fMultiplicityVtx[i])
441 fMultiplicityVtx[i]->Write();
442 fMultiplicityVtx[i]->ProjectionY(Form("%s_px", fMultiplicityVtx[i]->GetName()), 1, fMultiplicityVtx[i]->GetNbinsX())->Write();
444 if (fMultiplicityMB[i])
446 fMultiplicityMB[i]->Write();
447 fMultiplicityMB[i]->ProjectionY(Form("%s_px", fMultiplicityMB[i]->GetName()), 1, fMultiplicityMB[i]->GetNbinsX())->Write();
449 if (fMultiplicityINEL[i])
451 fMultiplicityINEL[i]->Write();
452 fMultiplicityINEL[i]->ProjectionY(Form("%s_px", fMultiplicityINEL[i]->GetName()), 1, fMultiplicityINEL[i]->GetNbinsX())->Write();
454 if (fMultiplicityNSD[i])
456 fMultiplicityNSD[i]->Write();
457 fMultiplicityNSD[i]->ProjectionY(Form("%s_px", fMultiplicityNSD[i]->GetName()), 1, fMultiplicityNSD[i]->GetNbinsX())->Write();
461 for (Int_t i = 0; i < kCorrHists; ++i)
464 fCorrelation[i]->Write();
465 if (fMultiplicityESDCorrected[i])
466 fMultiplicityESDCorrected[i]->Write();
469 gDirectory->cd("..");
472 //____________________________________________________________________
473 void AliMultiplicityCorrection::FillGenerated(Float_t vtx, Bool_t triggered, Bool_t vertex, AliPWG0Helper::MCProcessType processType, Int_t generated05, Int_t generated10, Int_t generated15, Int_t generated20, Int_t generatedAll)
476 // Fills an event from MC
481 fMultiplicityMB[0]->Fill(vtx, generated05);
482 fMultiplicityMB[1]->Fill(vtx, generated10);
483 fMultiplicityMB[2]->Fill(vtx, generated15);
484 fMultiplicityMB[3]->Fill(vtx, generated20);
485 fMultiplicityMB[4]->Fill(vtx, generatedAll);
489 fMultiplicityVtx[0]->Fill(vtx, generated05);
490 fMultiplicityVtx[1]->Fill(vtx, generated10);
491 fMultiplicityVtx[2]->Fill(vtx, generated15);
492 fMultiplicityVtx[3]->Fill(vtx, generated20);
493 fMultiplicityVtx[4]->Fill(vtx, generatedAll);
497 fMultiplicityINEL[0]->Fill(vtx, generated05);
498 fMultiplicityINEL[1]->Fill(vtx, generated10);
499 fMultiplicityINEL[2]->Fill(vtx, generated15);
500 fMultiplicityINEL[3]->Fill(vtx, generated20);
501 fMultiplicityINEL[4]->Fill(vtx, generatedAll);
503 if (processType != AliPWG0Helper::kSD)
505 fMultiplicityNSD[0]->Fill(vtx, generated05);
506 fMultiplicityNSD[1]->Fill(vtx, generated10);
507 fMultiplicityNSD[2]->Fill(vtx, generated15);
508 fMultiplicityNSD[3]->Fill(vtx, generated20);
509 fMultiplicityNSD[4]->Fill(vtx, generatedAll);
513 //____________________________________________________________________
514 void AliMultiplicityCorrection::FillMeasured(Float_t vtx, Int_t measured05, Int_t measured10, Int_t measured15, Int_t measured20)
517 // Fills an event from ESD
520 fMultiplicityESD[0]->Fill(vtx, measured05);
521 fMultiplicityESD[1]->Fill(vtx, measured10);
522 fMultiplicityESD[2]->Fill(vtx, measured15);
523 fMultiplicityESD[3]->Fill(vtx, measured20);
526 //____________________________________________________________________
527 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)
530 // Fills an event into the correlation map with the information from MC and ESD
533 fCorrelation[0]->Fill(vtx, generated05, measured05);
534 fCorrelation[1]->Fill(vtx, generated10, measured10);
535 fCorrelation[2]->Fill(vtx, generated15, measured15);
536 fCorrelation[3]->Fill(vtx, generated20, measured20);
538 fCorrelation[4]->Fill(vtx, generatedAll, measured05);
539 fCorrelation[5]->Fill(vtx, generatedAll, measured10);
540 fCorrelation[6]->Fill(vtx, generatedAll, measured15);
541 fCorrelation[7]->Fill(vtx, generatedAll, measured20);
544 //____________________________________________________________________
545 Double_t AliMultiplicityCorrection::RegularizationPol0(TVectorD& params)
547 // homogenity term for minuit fitting
548 // pure function of the parameters
549 // prefers constant function (pol0)
553 // ignore the first bin here. on purpose...
554 for (Int_t i=2; i<fgNParamsMinuit; ++i)
556 Double_t right = params[i];
557 Double_t left = params[i-1];
561 Double_t diff = 1 - left / right;
569 //____________________________________________________________________
570 Double_t AliMultiplicityCorrection::RegularizationPol1(TVectorD& params)
572 // homogenity term for minuit fitting
573 // pure function of the parameters
574 // prefers linear function (pol1)
578 // ignore the first bin here. on purpose...
579 for (Int_t i=2+1; i<fgNParamsMinuit; ++i)
581 if (params[i-1] == 0)
584 Double_t right = params[i];
585 Double_t middle = params[i-1];
586 Double_t left = params[i-2];
588 Double_t der1 = (right - middle);
589 Double_t der2 = (middle - left);
591 Double_t diff = (der1 - der2) / middle;
599 //____________________________________________________________________
600 Double_t AliMultiplicityCorrection::RegularizationLog(TVectorD& params)
602 // homogenity term for minuit fitting
603 // pure function of the parameters
604 // prefers linear function (pol1)
608 /*Float_t der[fgkMaxParams];
610 for (Int_t i=0; i<fgkMaxParams-1; ++i)
611 der[i] = params[i+1] - params[i];
613 for (Int_t i=0; i<fgkMaxParams-6; ++i)
615 for (Int_t j=1; j<=5; ++j)
617 Double_t diff = der[i+j] - der[i];
622 // ignore the first bin here. on purpose...
623 for (Int_t i=2+1; i<fgNParamsMinuit; ++i)
625 if (params[i-1] == 0)
628 Double_t right = log(params[i]);
629 Double_t middle = log(params[i-1]);
630 Double_t left = log(params[i-2]);
632 Double_t der1 = (right - middle);
633 Double_t der2 = (middle - left);
635 Double_t diff = (der1 - der2) / middle;
643 //____________________________________________________________________
644 Double_t AliMultiplicityCorrection::RegularizationTotalCurvature(TVectorD& params)
646 // homogenity term for minuit fitting
647 // pure function of the parameters
648 // minimizes the total curvature (from Unfolding Methods In High-Energy Physics Experiments,
649 // V. Blobel (Hamburg U.) . DESY 84/118, Dec 1984. 40pp.
653 // ignore the first bin here. on purpose...
654 for (Int_t i=3; i<fgNParamsMinuit; ++i)
656 Double_t right = params[i];
657 Double_t middle = params[i-1];
658 Double_t left = params[i-2];
660 Double_t der1 = (right - middle);
661 Double_t der2 = (middle - left);
663 Double_t diff = (der1 - der2);
671 //____________________________________________________________________
672 Double_t AliMultiplicityCorrection::RegularizationEntropy(TVectorD& params)
674 // homogenity term for minuit fitting
675 // pure function of the parameters
676 // calculates entropy, from
677 // The method of reduced cross-entropy (M. Schmelling 1993)
679 Double_t paramSum = 0;
680 // ignore the first bin here. on purpose...
681 for (Int_t i=1; i<fgNParamsMinuit; ++i)
682 paramSum += params[i];
685 for (Int_t i=1; i<fgNParamsMinuit; ++i)
687 //Double_t tmp = params[i] / paramSum;
688 Double_t tmp = params[i];
689 if (tmp > 0 && (*fgEntropyAPriori)[i] > 0)
691 chi2 += tmp * TMath::Log(tmp / (*fgEntropyAPriori)[i]);
698 //____________________________________________________________________
699 void AliMultiplicityCorrection::MinuitNBD(Int_t& unused1, Double_t* unused2, Double_t& chi2, Double_t *params, Int_t unused3)
702 // fit function for minuit
704 // 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);
705 // func->SetParNames("scaling", "averagen", "k");
706 // func->SetParLimits(0, 0.001, fCurrentESD->GetMaximum() * 1000);
707 // func->SetParLimits(1, 0.001, 1000);
708 // func->SetParLimits(2, 0.001, 1000);
711 fgNBD->SetParameters(params[0], params[1], params[2]);
713 Double_t params2[fgkMaxParams];
715 for (Int_t i=0; i<fgkMaxParams; ++i)
716 params2[i] = fgNBD->Eval(i);
718 MinuitFitFunction(unused1, unused2, chi2, params2, unused3);
720 printf("%f %f %f --> %f\n", params[0], params[1], params[2], chi2);
723 //____________________________________________________________________
724 void AliMultiplicityCorrection::MinuitFitFunction(Int_t&, Double_t*, Double_t& chi2, Double_t *params, Int_t)
727 // fit function for minuit
728 // does: (m - Ad)W(m - Ad) where m = measured, A correlation matrix, d = guess, W = covariance matrix
732 static TVectorD paramsVector(fgNParamsMinuit);
733 for (Int_t i=0; i<fgNParamsMinuit; ++i)
734 paramsVector[i] = params[i] * params[i];
736 // calculate penalty factor
737 Double_t penaltyVal = 0;
738 switch (fgRegularizationType)
741 case kPol0: penaltyVal = RegularizationPol0(paramsVector); break;
742 case kPol1: penaltyVal = RegularizationPol1(paramsVector); break;
743 case kCurvature: penaltyVal = RegularizationTotalCurvature(paramsVector); break;
744 case kEntropy: penaltyVal = RegularizationEntropy(paramsVector); break;
745 case kLog: penaltyVal = RegularizationLog(paramsVector); break;
748 //if (penaltyVal > 1e10)
749 // paramsVector2.Print();
751 penaltyVal *= fgRegularizationWeight;
754 TVectorD measGuessVector(fgkMaxInput);
755 measGuessVector = (*fgCorrelationMatrix) * paramsVector;
758 measGuessVector -= (*fgCurrentESDVector);
760 //measGuessVector.Print();
762 TVectorD copy(measGuessVector);
765 // this step can be optimized because currently only the diagonal elements of fgCorrelationCovarianceMatrix are used
766 // normal way is like this:
767 // measGuessVector *= (*fgCorrelationCovarianceMatrix);
768 // optimized way like this:
769 for (Int_t i=0; i<fgkMaxInput; ++i)
770 measGuessVector[i] *= (*fgCorrelationCovarianceMatrix)(i, i);
772 //measGuessVector.Print();
774 // reduce influence of first bin
777 // (Ad - m) W (Ad - m)
778 // the factor 1e6 prevents that a very small number (measGuessVector[i]) is multiplied with a very
779 // big number ((*fgCorrelationCovarianceMatrix)(i, i)) (see ApplyMinuitFit)
780 Double_t chi2FromFit = measGuessVector * copy * 1e6;
782 chi2 = chi2FromFit + penaltyVal;
784 static Int_t callCount = 0;
785 if ((callCount++ % 10000) == 0)
786 printf("%d) %f %f --> %f\n", callCount, chi2FromFit, penaltyVal, chi2);
789 //____________________________________________________________________
790 void AliMultiplicityCorrection::DrawGuess(Double_t *params)
793 // draws residuals of solution suggested by params and effect of regularization
797 static TVectorD paramsVector(fgNParamsMinuit);
798 for (Int_t i=0; i<fgNParamsMinuit; ++i)
799 paramsVector[i] = params[i] * params[i];
802 TVectorD measGuessVector(fgkMaxInput);
803 measGuessVector = (*fgCorrelationMatrix) * paramsVector;
806 measGuessVector -= (*fgCurrentESDVector);
808 TVectorD copy(measGuessVector);
812 // this step can be optimized because currently only the diagonal elements of fgCorrelationCovarianceMatrix are used
813 // normal way is like this:
814 // measGuessVector *= (*fgCorrelationCovarianceMatrix);
815 // optimized way like this:
816 for (Int_t i=0; i<fgkMaxInput; ++i)
817 measGuessVector[i] *= (*fgCorrelationCovarianceMatrix)(i, i);
819 // (Ad - m) W (Ad - m)
820 // the factor 1e6 prevents that a very small number (measGuessVector[i]) is multiplied with a very
821 // big number ((*fgCorrelationCovarianceMatrix)(i, i)) (see ApplyMinuitFit)
822 //Double_t chi2FromFit = measGuessVector * copy * 1e6;
825 TH1* residuals = new TH1F("residuals", "residuals", fgkMaxInput, -0.5, fgkMaxInput - 0.5);
826 for (Int_t i=0; i<fgkMaxInput; ++i)
827 residuals->SetBinContent(i+1, measGuessVector(i) * copy(i) * 1e6);
828 new TCanvas; residuals->DrawCopy(); gPad->SetLogy();
831 if (fgRegularizationType != kPol1) {
832 Printf("Drawing not supported");
836 TH1* penalty = new TH1F("penalty", "penalty", fgNParamsMinuit, -0.5, fgNParamsMinuit - 0.5);
838 for (Int_t i=2+1; i<fgNParamsMinuit; ++i)
840 if (params[i-1] == 0)
843 Double_t right = params[i];
844 Double_t middle = params[i-1];
845 Double_t left = params[i-2];
847 Double_t der1 = (right - middle);
848 Double_t der2 = (middle - left);
850 Double_t diff = (der1 - der2) / middle;
852 penalty->SetBinContent(i-1, diff * diff);
854 //Printf("%d %f %f %f %f", i-1, left, middle, right, diff);
856 new TCanvas; penalty->DrawCopy(); gPad->SetLogy();
859 //____________________________________________________________________
860 void AliMultiplicityCorrection::SetupCurrentHists(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Bool_t createBigBin)
863 // fills fCurrentESD, fCurrentCorrelation
864 // resets fMultiplicityESDCorrected
867 Bool_t display = kFALSE;
869 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
871 fMultiplicityESDCorrected[correlationID]->Reset();
872 fMultiplicityESDCorrected[correlationID]->Sumw2();
874 // project without under/overflow bins
875 fCurrentESD = fMultiplicityESD[inputRange]->ProjectionY("fCurrentESD", 1, fMultiplicityESD[inputRange]->GetXaxis()->GetNbins());
876 fCurrentESD->Sumw2();
878 // empty under/overflow bins in x, otherwise Project3D takes them into account
879 TH3* hist = fCorrelation[correlationID];
880 for (Int_t y=0; y<=hist->GetYaxis()->GetNbins()+1; ++y)
882 for (Int_t z=0; z<=hist->GetZaxis()->GetNbins()+1; ++z)
884 hist->SetBinContent(0, y, z, 0);
885 hist->SetBinContent(hist->GetXaxis()->GetNbins()+1, y, z, 0);
889 fCurrentCorrelation = hist->Project3D("zy");
890 fCurrentCorrelation->Sumw2();
892 Printf("AliMultiplicityCorrection::SetupCurrentHists: Statistics information: %.f entries in correlation map; %.f entries in measured spectrum", fCurrentCorrelation->Integral(), fCurrentESD->Integral());
895 for (Int_t i=1; i<=fCurrentESD->GetNbinsX(); ++i)
897 if (fCurrentESD->GetBinContent(i) <= 5)
904 Printf("AliMultiplicityCorrection::SetupCurrentHists: Bin limit in measured spectrum determined to be %d", fLastBinLimit);
908 if (fLastBinLimit > 0)
914 canvas = new TCanvas("StatSolution", "StatSolution", 1000, 800);
915 canvas->Divide(2, 2);
918 fCurrentESD->GetXaxis()->SetRangeUser(0, 200);
919 fCurrentESD->SetStats(kFALSE);
920 fCurrentESD->SetTitle(";measured multiplicity");
921 fCurrentESD->DrawCopy();
925 fCurrentCorrelation->GetXaxis()->SetRangeUser(0, 250);
926 fCurrentCorrelation->GetYaxis()->SetRangeUser(0, 250);
927 fCurrentCorrelation->SetTitle(";true multiplicity;measured multiplicity");
928 fCurrentCorrelation->SetStats(kFALSE);
929 fCurrentCorrelation->DrawCopy("COLZ");
932 printf("Bin limit in measured spectrum is %d.\n", fLastBinLimit);
933 fCurrentESD->SetBinContent(fLastBinLimit, fCurrentESD->Integral(fLastBinLimit, fCurrentESD->GetNbinsX()));
934 for (Int_t i=fLastBinLimit+1; i<=fCurrentESD->GetNbinsX(); ++i)
936 fCurrentESD->SetBinContent(i, 0);
937 fCurrentESD->SetBinError(i, 0);
939 // the error is set to sqrt(N), better solution possible?, sum of relative errors of all contributions???
940 fCurrentESD->SetBinError(fLastBinLimit, TMath::Sqrt(fCurrentESD->GetBinContent(fLastBinLimit)));
942 printf("This bin has now %f +- %f entries\n", fCurrentESD->GetBinContent(fLastBinLimit), fCurrentESD->GetBinError(fLastBinLimit));
944 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
946 fCurrentCorrelation->SetBinContent(i, fLastBinLimit, fCurrentCorrelation->Integral(i, i, fLastBinLimit, fCurrentCorrelation->GetNbinsY()));
947 // the error is set to sqrt(N), better solution possible?, sum of relative errors of all contributions???
948 fCurrentCorrelation->SetBinError(i, fLastBinLimit, TMath::Sqrt(fCurrentCorrelation->GetBinContent(i, fLastBinLimit)));
950 for (Int_t j=fLastBinLimit+1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
952 fCurrentCorrelation->SetBinContent(i, j, 0);
953 fCurrentCorrelation->SetBinError(i, j, 0);
957 printf("Adjusted correlation matrix!\n");
962 fCurrentESD->DrawCopy();
966 fCurrentCorrelation->DrawCopy("COLZ");
971 #if 0 // does not help
972 // null bins with one entry
973 Int_t nNulledBins = 0;
974 for (Int_t x=1; x<=fCurrentCorrelation->GetXaxis()->GetNbins(); ++x)
975 for (Int_t y=1; y<=fCurrentCorrelation->GetYaxis()->GetNbins(); ++y)
977 if (fCurrentCorrelation->GetBinContent(x, y) == 1)
979 fCurrentCorrelation->SetBinContent(x, y, 0);
980 fCurrentCorrelation->SetBinError(x, y, 0);
985 Printf("Nulled %d bins", nNulledBins);
988 fCurrentEfficiency = GetEfficiency(inputRange, eventType);
989 //fCurrentEfficiency->Rebin(2);
990 //fCurrentEfficiency->Scale(0.5);
993 //____________________________________________________________________
994 TH1* AliMultiplicityCorrection::GetEfficiency(Int_t inputRange, EventType eventType)
997 // calculates efficiency for given event type
1003 case kTrVtx : break;
1004 case kMB: divisor = fMultiplicityMB[inputRange]->ProjectionY("divisor", 1, fMultiplicityMB[inputRange]->GetNbinsX(), "e"); break;
1005 case kINEL: divisor = fMultiplicityINEL[inputRange]->ProjectionY("divisor", 1, fMultiplicityINEL[inputRange]->GetNbinsX(), "e"); break;
1006 case kNSD: divisor = fMultiplicityNSD[inputRange]->ProjectionY("divisor", 1, fMultiplicityNSD[inputRange]->GetNbinsX(), "e"); break;
1008 TH1* eff = fMultiplicityVtx[inputRange]->ProjectionY("CurrentEfficiency", 1, fMultiplicityVtx[inputRange]->GetNbinsX(), "e");
1010 if (eventType == kTrVtx)
1012 for (Int_t i=0; i<= eff->GetNbinsX()+1; i++)
1013 eff->SetBinContent(i, 1);
1016 eff->Divide(eff, divisor, 1, 1, "B");
1021 //____________________________________________________________________
1022 TH1* AliMultiplicityCorrection::GetTriggerEfficiency(Int_t inputRange)
1025 // calculates efficiency for given event type
1028 TH1* divisor = fMultiplicityINEL[inputRange]->ProjectionY("divisor", 1, fMultiplicityINEL[inputRange]->GetNbinsX(), "e");
1029 TH1* eff = fMultiplicityMB[inputRange]->ProjectionY("CurrentEfficiency", 1, fMultiplicityMB[inputRange]->GetNbinsX(), "e");
1030 eff->Divide(eff, divisor, 1, 1, "B");
1034 //____________________________________________________________________
1035 void AliMultiplicityCorrection::SetRegularizationParameters(RegularizationType type, Float_t weight, Int_t minuitParams)
1038 // sets the parameters for chi2 minimization
1041 fgRegularizationType = type;
1042 fgRegularizationWeight = weight;
1044 printf("AliMultiplicityCorrection::SetRegularizationParameters --> Regularization set to %d with weight %f\n", (Int_t) type, weight);
1046 if (minuitParams > 0)
1048 fgNParamsMinuit = minuitParams;
1049 printf("AliMultiplicityCorrection::SetRegularizationParameters --> Number of MINUIT iterations set to %d\n", minuitParams);
1053 //____________________________________________________________________
1054 void AliMultiplicityCorrection::SetBayesianParameters(Float_t smoothing, Int_t nIterations)
1057 // sets the parameters for Bayesian unfolding
1060 fgBayesianSmoothing = smoothing;
1061 fgBayesianIterations = nIterations;
1063 printf("AliMultiplicityCorrection::SetBayesianParameters --> Paramaters set to %d iterations with smoothing %f\n", fgBayesianIterations, fgBayesianSmoothing);
1066 //____________________________________________________________________
1067 Int_t AliMultiplicityCorrection::UnfoldWithMinuit(TH1* correlation, TH1* aEfficiency, TH1* measured, TH1* initialConditions, TH1* result, Bool_t check)
1070 // implementation of unfolding (internal function)
1072 // unfolds <measured> using response from <correlation> and effiency <aEfficiency>
1073 // output is in <result>
1074 // <initialConditions> set the initial values for the minimization, if 0 <measured> is used
1075 // if <check> is true no unfolding is made, instead only the chi2 without unfolding is printed
1077 // returns minuit status (0 = success), (-1 when check was set)
1080 //normalize measured
1081 measured->Scale(1.0 / measured->Integral());
1083 if (!fgCorrelationMatrix)
1084 fgCorrelationMatrix = new TMatrixD(fgkMaxInput, fgNParamsMinuit);
1085 if (!fgCorrelationCovarianceMatrix)
1086 fgCorrelationCovarianceMatrix = new TMatrixD(fgkMaxInput, fgkMaxInput);
1087 if (!fgCurrentESDVector)
1088 fgCurrentESDVector = new TVectorD(fgkMaxInput);
1089 if (!fgEntropyAPriori)
1090 fgEntropyAPriori = new TVectorD(fgNParamsMinuit);
1092 fgCorrelationMatrix->Zero();
1093 fgCorrelationCovarianceMatrix->Zero();
1094 fgCurrentESDVector->Zero();
1095 fgEntropyAPriori->Zero();
1097 // normalize correction for given nPart
1098 for (Int_t i=1; i<=correlation->GetNbinsX(); ++i)
1100 Double_t sum = correlation->Integral(i, i, 1, correlation->GetNbinsY());
1103 Float_t maxValue = 0;
1105 for (Int_t j=1; j<=correlation->GetNbinsY(); ++j)
1107 // find most probably value
1108 if (maxValue < correlation->GetBinContent(i, j))
1110 maxValue = correlation->GetBinContent(i, j);
1115 correlation->SetBinContent(i, j, correlation->GetBinContent(i, j) / sum);
1116 correlation->SetBinError(i, j, correlation->GetBinError(i, j) / sum);
1118 if (i <= fgNParamsMinuit && j <= fgkMaxInput)
1119 (*fgCorrelationMatrix)(j-1, i-1) = correlation->GetBinContent(i, j);
1122 //printf("MPV for Ntrue = %f is %f\n", fCurrentCorrelation->GetXaxis()->GetBinCenter(i), fCurrentCorrelation->GetYaxis()->GetBinCenter(maxBin));
1125 // Initialize TMinuit via generic fitter interface
1126 TVirtualFitter *minuit = TVirtualFitter::Fitter(0, fgNParamsMinuit);
1127 Double_t arglist[100];
1129 // disable any output (-1), unfortuantly we do not see warnings anymore then. Have to find another way...
1131 minuit->ExecuteCommand("SET PRINT", arglist, 1);
1133 // however, enable warnings
1134 //minuit->ExecuteCommand("SET WAR", arglist, 0);
1136 // set minimization function
1137 minuit->SetFCN(MinuitFitFunction);
1139 for (Int_t i=0; i<fgNParamsMinuit; i++)
1140 (*fgEntropyAPriori)[i] = 1;
1142 if (!initialConditions) {
1143 initialConditions = measured;
1145 printf("Using different starting conditions...\n");
1146 //new TCanvas; initialConditions->DrawCopy();
1147 initialConditions->Scale(1.0 / initialConditions->Integral());
1150 for (Int_t i=0; i<fgNParamsMinuit; i++)
1151 if (initialConditions->GetBinContent(i+1) > 0)
1152 (*fgEntropyAPriori)[i] = initialConditions->GetBinContent(i+1);
1154 Double_t* results = new Double_t[fgNParamsMinuit+1];
1155 for (Int_t i=0; i<fgNParamsMinuit; ++i)
1157 results[i] = initialConditions->GetBinContent(i+1);
1161 results[i] = TMath::Max(results[i], 1e-3);
1163 Float_t stepSize = 0.1;
1165 // minuit sees squared values to prevent it from going negative...
1166 results[i] = TMath::Sqrt(results[i]);
1167 //stepSize /= results[i]; // keep relative step size
1169 minuit->SetParameter(i, Form("param%d", i), results[i], stepSize, 0, 0);
1171 //minuit->SetParameter(fgkMaxParams, "alpha", 1e4, 1, 0, 0);
1172 // bin 0 is filled with value from bin 1 (otherwise it's 0)
1173 //minuit->SetParameter(0, "param0", (results[1] > minStartValue) ? results[1] : minStartValue, 0.1, 0, 0);
1175 //minuit->SetParameter(0, "param0", 0, 0, 0, 0);
1177 for (Int_t i=0; i<fgkMaxInput; ++i)
1179 (*fgCurrentESDVector)[i] = measured->GetBinContent(i+1);
1180 if (measured->GetBinError(i+1) > 0)
1181 (*fgCorrelationCovarianceMatrix)(i, i) = (Double_t) 1e-6 / measured->GetBinError(i+1) / measured->GetBinError(i+1);
1183 if ((*fgCorrelationCovarianceMatrix)(i, i) > 1e7)
1184 (*fgCorrelationCovarianceMatrix)(i, i) = 0;
1185 //Printf("%d, %e", i, (*fgCorrelationCovarianceMatrix)(i, i));
1190 MinuitFitFunction(dummy, 0, chi2, results, 0);
1191 printf("Chi2 of initial parameters is = %f\n", chi2);
1200 // first param is number of iterations, second is precision....
1202 //arglist[1] = 1e-5;
1203 //minuit->ExecuteCommand("SCAN", arglist, 0);
1204 Int_t status = minuit->ExecuteCommand("MIGRAD", arglist, 1);
1205 printf("MINUIT status is %d\n", status);
1206 //minuit->ExecuteCommand("MIGRAD", arglist, 1);
1207 //minuit->ExecuteCommand("MIGRAD", arglist, 1);
1208 //printf("!!!!!!!!!!!!!! MIGRAD finished: Starting MINOS !!!!!!!!!!!!!!");
1209 //minuit->ExecuteCommand("MINOS", arglist, 0);
1211 //new TCanvas; aEfficiency->Draw();
1213 for (Int_t i=0; i<fgNParamsMinuit; ++i)
1215 results[i] = minuit->GetParameter(i);
1216 if (aEfficiency->GetBinContent(i+1) > 0)
1218 result->SetBinContent(i+1, results[i] * results[i] / aEfficiency->GetBinContent(i+1));
1219 // error is : (relError) * (value) = (minuit->GetParError(i) / minuit->GetParameter(i)) * (minuit->GetParameter(i) * minuit->GetParameter(i))
1220 result->SetBinError(i+1, minuit->GetParError(i) * results[i] / aEfficiency->GetBinContent(i+1));
1224 result->SetBinContent(i+1, 0);
1225 result->SetBinError(i+1, 0);
1228 //DrawGuess(results);
1235 //____________________________________________________________________
1236 Int_t AliMultiplicityCorrection::ApplyMinuitFit(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Bool_t check, TH1* initialConditions)
1239 // correct spectrum using minuit chi2 method
1241 // for description of parameters, see UnfoldWithMinuit
1244 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1245 SetupCurrentHists(inputRange, fullPhaseSpace, eventType, fgCreateBigBin);
1247 return UnfoldWithMinuit(fCurrentCorrelation, fCurrentEfficiency, fCurrentESD, initialConditions, fMultiplicityESDCorrected[correlationID], check);
1250 //____________________________________________________________________
1251 void AliMultiplicityCorrection::ApplyNBDFit(Int_t inputRange, Bool_t fullPhaseSpace)
1254 // correct spectrum using minuit chi2 method applying a NBD fit
1257 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1259 SetupCurrentHists(inputRange, fullPhaseSpace, kTrVtx, kFALSE);
1261 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
1263 fgCorrelationMatrix = new TMatrixD(fgkMaxParams, fgkMaxParams);
1264 fgCorrelationCovarianceMatrix = new TMatrixD(fgkMaxParams, fgkMaxParams);
1265 fgCurrentESDVector = new TVectorD(fgkMaxParams);
1267 // normalize correction for given nPart
1268 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
1270 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
1273 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
1276 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
1277 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
1279 if (i <= fgkMaxParams && j <= fgkMaxParams)
1280 (*fgCorrelationMatrix)(j-1, i-1) = fCurrentCorrelation->GetBinContent(i, j);
1284 for (Int_t i=0; i<fgkMaxParams; ++i)
1286 (*fgCurrentESDVector)[i] = fCurrentESD->GetBinContent(i+1);
1287 if (fCurrentESD->GetBinError(i+1) > 0)
1288 (*fgCorrelationCovarianceMatrix)(i, i) = 1.0 / (fCurrentESD->GetBinError(i+1) * fCurrentESD->GetBinError(i+1));
1291 // Create NBD function
1294 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);
1295 fgNBD->SetParNames("scaling", "averagen", "k");
1298 // Initialize TMinuit via generic fitter interface
1299 TVirtualFitter *minuit = TVirtualFitter::Fitter(0, 3);
1301 minuit->SetFCN(MinuitNBD);
1302 minuit->SetParameter(0, "param0", 1, 0.1, 0.001, fCurrentESD->GetMaximum() * 1000);
1303 minuit->SetParameter(1, "param1", 10, 1, 0.001, 1000);
1304 minuit->SetParameter(2, "param2", 2, 1, 0.001, 1000);
1306 Double_t arglist[100];
1308 minuit->ExecuteCommand("SET PRINT", arglist, 1);
1309 minuit->ExecuteCommand("MIGRAD", arglist, 0);
1310 //minuit->ExecuteCommand("MINOS", arglist, 0);
1312 fgNBD->SetParameters(minuit->GetParameter(0), minuit->GetParameter(1), minuit->GetParameter(2));
1314 for (Int_t i=0; i<fgkMaxParams; ++i)
1316 printf("%d : %f\n", i, fgNBD->Eval(i));
1317 if (fgNBD->Eval(i) > 0)
1319 fMultiplicityESDCorrected[correlationID]->SetBinContent(i+1, fgNBD->Eval(i));
1320 fMultiplicityESDCorrected[correlationID]->SetBinError(i+1, 0);
1325 //____________________________________________________________________
1326 void AliMultiplicityCorrection::DrawHistograms()
1329 // draws the histograms of this class
1334 TCanvas* canvas1 = new TCanvas("fMultiplicityESD", "fMultiplicityESD", 900, 600);
1335 canvas1->Divide(3, 2);
1336 for (Int_t i = 0; i < kESDHists; ++i)
1339 fMultiplicityESD[i]->DrawCopy("COLZ");
1340 printf("%d --> %f\n", i, (Float_t) fMultiplicityESD[i]->ProjectionY()->GetMean());
1345 TCanvas* canvas2 = new TCanvas("fMultiplicityMC", "fMultiplicityMC", 900, 600);
1346 canvas2->Divide(3, 2);
1347 for (Int_t i = 0; i < kMCHists; ++i)
1350 fMultiplicityVtx[i]->DrawCopy("COLZ");
1351 printf("%d --> %f\n", i, fMultiplicityVtx[i]->ProjectionY()->GetMean());
1354 TCanvas* canvas3 = new TCanvas("fCorrelation", "fCorrelation", 900, 900);
1355 canvas3->Divide(3, 3);
1356 for (Int_t i = 0; i < kCorrHists; ++i)
1359 TH3* hist = dynamic_cast<TH3*> (fCorrelation[i]->Clone());
1360 for (Int_t y=1; y<=hist->GetYaxis()->GetNbins(); ++y)
1362 for (Int_t z=1; z<=hist->GetZaxis()->GetNbins(); ++z)
1364 hist->SetBinContent(0, y, z, 0);
1365 hist->SetBinContent(hist->GetXaxis()->GetNbins()+1, y, z, 0);
1368 TH1* proj = hist->Project3D("zy");
1369 proj->DrawCopy("COLZ");
1373 //____________________________________________________________________
1374 void AliMultiplicityCorrection::DrawComparison(const char* name, Int_t inputRange, Bool_t fullPhaseSpace, Bool_t /*normalizeESD*/, TH1* mcHist, Bool_t simple)
1376 // draw comparison plots
1381 Int_t esdCorrId = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1384 tmpStr.Form("%s_DrawComparison_%d", name, esdCorrId);
1386 if (fMultiplicityESDCorrected[esdCorrId]->Integral() == 0)
1388 printf("ERROR. Unfolded histogram is empty\n");
1392 //regain measured distribution used for unfolding, because the bins at high mult. were modified in SetupCurrentHists
1393 fCurrentESD = fMultiplicityESD[esdCorrId]->ProjectionY("fCurrentESD", 1, fMultiplicityESD[inputRange]->GetXaxis()->GetNbins());
1394 fCurrentESD->Sumw2();
1395 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
1397 // normalize unfolded result to 1
1398 fMultiplicityESDCorrected[esdCorrId]->Scale(1.0 / fMultiplicityESDCorrected[esdCorrId]->Integral());
1400 //fCurrentESD->Scale(mcHist->Integral(2, 200));
1403 /*TH1* ratio = (TH1*) fMultiplicityESDCorrected[esdCorrId]->Clone("ratio");
1404 ratio->Divide(mcHist);
1405 ratio->Draw("HIST");
1406 ratio->Fit("pol0", "W0", "", 20, 120);
1407 Float_t scalingFactor = ratio->GetFunction("pol0")->GetParameter(0);
1409 mcHist->Scale(scalingFactor);*/
1411 // find bin with <= 50 entries. this is used as limit for the chi2 calculation
1412 Int_t mcBinLimit = 0;
1413 for (Int_t i=20; i<mcHist->GetNbinsX(); ++i)
1415 if (mcHist->GetBinContent(i) > 50)
1422 Printf("AliMultiplicityCorrection::DrawComparison: MC bin limit is %d", mcBinLimit);
1426 if (mcHist->Integral() > 0)
1427 mcHist->Scale(1.0 / mcHist->Integral());
1429 // calculate residual
1431 // for that we convolute the response matrix with the gathered result
1432 // if normalizeESD is not set, the histogram is already normalized, this needs to be passed to CalculateMultiplicityESD
1433 TH1* tmpESDEfficiencyRecorrected = (TH1*) fMultiplicityESDCorrected[esdCorrId]->Clone("tmpESDEfficiencyRecorrected");
1434 tmpESDEfficiencyRecorrected->Multiply(fCurrentEfficiency);
1435 TH2* convoluted = CalculateMultiplicityESD(tmpESDEfficiencyRecorrected, esdCorrId);
1436 TH1* convolutedProj = convoluted->ProjectionY("convolutedProj", -1, -1, "e");
1437 if (convolutedProj->Integral() > 0)
1439 convolutedProj->Scale(1.0 / convolutedProj->Integral());
1442 printf("ERROR: convolutedProj is empty. Something went wrong calculating the convoluted histogram.\n");
1444 TH1* residual = (TH1*) convolutedProj->Clone("residual");
1445 residual->SetTitle("Residuals;Ntracks;(folded unfolded measured - measured) / e");
1447 residual->Add(fCurrentESD, -1);
1448 //residual->Divide(residual, fCurrentESD, 1, 1, "B");
1450 TH1* residualHist = new TH1F("residualHist", "residualHist", 51, -5, 5);
1454 for (Int_t i=1; i<=residual->GetNbinsX(); ++i)
1456 if (fCurrentESD->GetBinError(i) > 0)
1458 Float_t value = residual->GetBinContent(i) / fCurrentESD->GetBinError(i);
1459 if (i > 1 && i <= fLastBinLimit)
1460 chi2 += value * value;
1461 Printf("%d --> %f (%f)", i, value * value, chi2);
1462 residual->SetBinContent(i, value);
1463 residualHist->Fill(value);
1467 //printf("Residual bin %d set to 0\n", i);
1468 residual->SetBinContent(i, 0);
1470 convolutedProj->SetBinError(i, 0);
1471 residual->SetBinError(i, 0);
1473 fLastChi2Residuals = chi2;
1475 new TCanvas; residualHist->DrawCopy();
1477 //residualHist->Fit("gaus", "N");
1478 //delete residualHist;
1480 printf("Difference (Residuals) is %f for bin 2-%d\n", fLastChi2Residuals, fLastBinLimit);
1482 TCanvas* canvas1 = 0;
1485 canvas1 = new TCanvas(tmpStr, tmpStr, 1200, 600);
1486 canvas1->Divide(2, 1);
1490 canvas1 = new TCanvas(tmpStr, tmpStr, 1200, 1200);
1491 canvas1->Divide(2, 3);
1495 canvas1->cd(1)->SetGridx();
1496 canvas1->cd(1)->SetGridy();
1497 canvas1->cd(1)->SetTopMargin(0.05);
1498 canvas1->cd(1)->SetRightMargin(0.05);
1499 canvas1->cd(1)->SetLeftMargin(0.12);
1500 canvas1->cd(1)->SetBottomMargin(0.12);
1501 TH1* proj = (TH1*) mcHist->Clone("proj");
1503 // normalize without 0 bin
1504 proj->Scale(1.0 / proj->Integral(2, proj->GetNbinsX()));
1505 Printf("Normalized without 0 bin!");
1506 proj->GetXaxis()->SetRangeUser(0, 200);
1507 proj->GetYaxis()->SetTitleOffset(1.4);
1508 //proj->SetLabelSize(0.05, "xy");
1509 //proj->SetTitleSize(0.05, "xy");
1510 proj->SetTitle(Form(";True multiplicity in |#eta| < %.1f;Entries", (inputRange+1)*0.5));
1511 proj->SetStats(kFALSE);
1513 fMultiplicityESDCorrected[esdCorrId]->SetLineColor(2);
1514 fMultiplicityESDCorrected[esdCorrId]->SetMarkerColor(2);
1515 //fMultiplicityESDCorrected[esdCorrId]->SetMarkerStyle(5);
1516 // normalize without 0 bin
1517 fMultiplicityESDCorrected[esdCorrId]->Scale(1.0 / fMultiplicityESDCorrected[esdCorrId]->Integral(2, fMultiplicityESDCorrected[esdCorrId]->GetNbinsX()));
1518 Printf("Normalized without 0 bin!");
1520 if (proj->GetEntries() > 0) {
1521 proj->DrawCopy("HIST");
1522 fMultiplicityESDCorrected[esdCorrId]->DrawCopy("SAME HIST E");
1525 fMultiplicityESDCorrected[esdCorrId]->DrawCopy("HIST E");
1529 TLegend* legend = new TLegend(0.3, 0.8, 0.93, 0.93);
1530 legend->AddEntry(proj, "True distribution");
1531 legend->AddEntry(fMultiplicityESDCorrected[esdCorrId], "Unfolded distribution");
1532 legend->SetFillColor(0);
1533 legend->SetTextSize(0.04);
1535 // unfortunately does not work. maybe a bug? --> legend->SetTextSizePixels(14);
1538 canvas1->cd(2)->SetGridx();
1539 canvas1->cd(2)->SetGridy();
1540 canvas1->cd(2)->SetTopMargin(0.05);
1541 canvas1->cd(2)->SetRightMargin(0.05);
1542 canvas1->cd(2)->SetLeftMargin(0.12);
1543 canvas1->cd(2)->SetBottomMargin(0.12);
1546 fCurrentESD->GetXaxis()->SetRangeUser(0, 200);
1547 //fCurrentESD->SetLineColor(2);
1548 fCurrentESD->SetTitle(Form(";Measured multiplicity in |#eta| < %.1f;Entries", (inputRange+1)*0.5));
1549 fCurrentESD->SetStats(kFALSE);
1550 fCurrentESD->GetYaxis()->SetTitleOffset(1.4);
1551 //fCurrentESD->SetLabelSize(0.05, "xy");
1552 //fCurrentESD->SetTitleSize(0.05, "xy");
1553 fCurrentESD->DrawCopy("HIST E");
1555 convolutedProj->SetLineColor(2);
1556 convolutedProj->SetMarkerColor(2);
1557 convolutedProj->SetMarkerStyle(5);
1558 //proj2->SetMarkerColor(2);
1559 //proj2->SetMarkerStyle(5);
1560 convolutedProj->DrawCopy("HIST SAME P");
1562 legend = new TLegend(0.3, 0.8, 0.93, 0.93);
1563 legend->AddEntry(fCurrentESD, "Measured distribution");
1564 legend->AddEntry(convolutedProj, "R #otimes unfolded distribution", "P");
1565 legend->SetFillColor(0);
1566 legend->SetTextSize(0.04);
1569 //TH1* diffMCUnfolded = dynamic_cast<TH1*> (proj->Clone("diffMCUnfolded"));
1570 //diffMCUnfolded->Add(fMultiplicityESDCorrected[esdCorrId], -1);
1574 fLastChi2MCLimit = 0;
1576 for (Int_t i=2; i<=200; ++i)
1578 if (proj->GetBinContent(i) != 0)
1580 Float_t value = (proj->GetBinContent(i) - fMultiplicityESDCorrected[esdCorrId]->GetBinContent(i)) / proj->GetBinContent(i);
1581 chi2 += value * value;
1582 chi += TMath::Abs(value);
1584 //printf("%d %f\n", i, chi);
1587 fLastChi2MCLimit = i;
1598 for (Int_t i=1; i<=diffMCUnfolded->GetNbinsX(); ++i)
1600 if (fMultiplicityESDCorrected[esdCorrId]->GetBinError(i) > 0)
1602 Double_t value = diffMCUnfolded->GetBinContent(i) / fMultiplicityESDCorrected[esdCorrId]->GetBinError(i);
1604 value = 1e8; //prevent arithmetic exception
1605 else if (value < -1e8)
1609 chi2 += value * value;
1610 chi += TMath::Abs(value);
1612 diffMCUnfolded->SetBinContent(i, value);
1616 //printf("diffMCUnfolded bin %d set to 0\n", i);
1617 diffMCUnfolded->SetBinContent(i, 0);
1620 fLastChi2MCLimit = i;
1627 printf("limits %d %d\n", fLastChi2MCLimit, limit);
1628 fLastChi2MCLimit = limit;
1630 printf("Difference (from MC) is %f for bin 2-150. Limit is %d.\n", fLastChi2MC, fLastChi2MCLimit);*/
1636 diffMCUnfolded->SetTitle("#chi^{2};Npart;(MC - Unfolded) / e(unfolded)");
1637 //diffMCUnfolded->GetYaxis()->SetRangeUser(-20, 20);
1638 diffMCUnfolded->GetXaxis()->SetRangeUser(0, 200);
1639 diffMCUnfolded->DrawCopy("HIST");
1641 TH1F* fluctuation = new TH1F("fluctuation", "fluctuation", 20, -5, 5);
1642 for (Int_t i=20; i<=diffMCUnfolded->GetNbinsX(); ++i)
1643 fluctuation->Fill(diffMCUnfolded->GetBinContent(i));
1645 //new TCanvas; fluctuation->DrawCopy();
1646 delete fluctuation;*/
1648 /*TLegend* legend = new TLegend(0.6, 0.7, 0.85, 0.85);
1649 legend->AddEntry(fMultiplicityESDCorrected, "ESD corrected");
1650 legend->AddEntry(fMultiplicityMC, "MC");
1651 legend->AddEntry(fMultiplicityESD, "ESD");
1655 residual->GetYaxis()->SetRangeUser(-5, 5);
1656 residual->GetXaxis()->SetRangeUser(0, 200);
1657 residual->DrawCopy();
1661 TH1* ratio = (TH1*) fMultiplicityESDCorrected[esdCorrId]->Clone("ratio");
1662 ratio->Divide(mcHist);
1663 ratio->SetTitle("Ratio;true multiplicity;Unfolded / MC");
1664 ratio->GetYaxis()->SetRangeUser(0.5, 1.5);
1665 ratio->GetXaxis()->SetRangeUser(0, 200);
1666 ratio->SetStats(kFALSE);
1667 ratio->Draw("HIST");
1669 Double_t ratioChi2 = 0;
1671 fLastChi2MCLimit = 0;
1672 for (Int_t i=2; i<=150; ++i)
1674 Float_t value = ratio->GetBinContent(i) - 1;
1676 value = 1e8; //prevent arithmetic exception
1677 else if (value < -1e8)
1680 ratioChi2 += value * value;
1681 fRatioAverage += TMath::Abs(value);
1683 if (ratioChi2 < 0.1)
1684 fLastChi2MCLimit = i;
1686 fRatioAverage /= 149;
1688 printf("Sum over (ratio-1)^2 (2..150) is %f; average of |ratio-1| is %f\n", ratioChi2, fRatioAverage);
1690 fLastChi2MC = ratioChi2;
1694 const Int_t kFFT = 128;
1695 Double_t fftReal[kFFT];
1696 Double_t fftImag[kFFT];
1698 for (Int_t i=0; i<kFFT; ++i)
1700 fftReal[i] = ratio->GetBinContent(i+1+10);
1702 //fftReal[i] = cos(TMath::Pi() * 5 * 2 * i / 128);
1706 FFT(-1, TMath::Nint(TMath::Log(kFFT) / TMath::Log(2)), fftReal, fftImag);
1708 TH1* fftResult = (TH1*) ratio->Clone("fftResult");
1709 fftResult->SetTitle("FFT;true multiplicity;coeff. (10...137)");
1710 TH1* fftResult2 = (TH1*) ratio->Clone("fftResult2");
1711 TH1* fftResult3 = (TH1*) ratio->Clone("fftResult3");
1713 fftResult2->Reset();
1714 fftResult3->Reset();
1715 fftResult->GetYaxis()->UnZoom();
1716 fftResult2->GetYaxis()->UnZoom();
1717 fftResult3->GetYaxis()->UnZoom();
1719 //Printf("AFTER FFT");
1720 for (Int_t i=0; i<kFFT; ++i)
1722 //Printf("%d: %f", i, fftReal[i]);
1723 fftResult->SetBinContent(i+1, fftReal[i]);
1724 /*if (i != 0 && TMath::Abs(fftReal[i]) > 0.5)
1726 Printf("Nulled %d", i);
1731 fftResult->SetLineColor(1);
1732 fftResult->DrawCopy();
1736 for (Int_t i=0; i<kFFT; ++i)
1738 //Printf("%d: %f", i, fftImag[i]);
1739 fftResult2->SetBinContent(i+1, fftImag[i]);
1741 fftResult3->SetBinContent(i+1, TMath::Sqrt(fftReal[i] * fftReal[i] + fftImag[i] * fftImag[i]));
1744 fftResult2->SetLineColor(2);
1745 fftResult2->DrawCopy("SAME");
1747 fftResult3->SetLineColor(4);
1748 fftResult3->DrawCopy("SAME");
1750 for (Int_t i=1; i<kFFT - 1; ++i)
1752 if (TMath::Sqrt(fftReal[i] * fftReal[i] + fftImag[i] * fftImag[i]) > 3)
1760 //fftReal[i] = (fftReal[i-1] + fftReal[i+1]) / 2;
1761 //fftImag[i] = (fftImag[i-1] + fftImag[i+1]) / 2;
1762 //Printf("Nulled %d to %f %f", i, fftReal[i], fftImag[i]);
1766 FFT(1, TMath::Nint(TMath::Log(kFFT) / TMath::Log(2)), fftReal, fftImag);
1768 TH1* fftResult4 = (TH1*) fftResult3->Clone("fftResult4");
1769 fftResult4->Reset();
1771 //Printf("AFTER BACK-TRAFO");
1772 for (Int_t i=0; i<kFFT; ++i)
1774 //Printf("%d: %f", i, fftReal[i]);
1775 fftResult4->SetBinContent(i+1+10, fftReal[i]);
1779 fftResult4->SetLineColor(4);
1780 fftResult4->DrawCopy("SAME");
1782 // plot (MC - Unfolded) / error (MC)
1785 TH1* diffMCUnfolded2 = dynamic_cast<TH1*> (proj->Clone("diffMCUnfolded2"));
1786 diffMCUnfolded2->Add(fMultiplicityESDCorrected[esdCorrId], -1);
1788 Int_t ndfQual[kQualityRegions];
1789 for (Int_t region=0; region<kQualityRegions; ++region)
1791 fQuality[region] = 0;
1792 ndfQual[region] = 0;
1796 Double_t newChi2 = 0;
1797 Double_t newChi2Limit150 = 0;
1799 for (Int_t i=1; i<=TMath::Min(diffMCUnfolded2->GetNbinsX(), fgkMaxParams+1); ++i)
1802 if (proj->GetBinError(i) > 0)
1804 value = diffMCUnfolded2->GetBinContent(i) / proj->GetBinError(i);
1805 newChi2 += value * value;
1806 if (i > 1 && i <= mcBinLimit)
1807 newChi2Limit150 += value * value;
1810 for (Int_t region=0; region<kQualityRegions; ++region)
1811 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
1813 fQuality[region] += TMath::Abs(value);
1818 diffMCUnfolded2->SetBinContent(i, value);
1821 // normalize region to the number of entries
1822 for (Int_t region=0; region<kQualityRegions; ++region)
1824 if (ndfQual[region] > 0)
1825 fQuality[region] /= ndfQual[region];
1826 Printf("Quality parameter %d (%d <= mult <= %d) is %f with %d df", region, fgQualityRegionsB[region], fgQualityRegionsE[region], fQuality[region], ndfQual[region]);
1831 // TODO another FAKE
1832 fLastChi2MC = newChi2Limit150 / (mcBinLimit - 1);
1833 Printf("Chi2 (2..%d) from (MC - Unfolded) / e(MC) is: %.2f ndf is %d --> chi2 / ndf = %.2f", mcBinLimit, newChi2Limit150, mcBinLimit - 1, fLastChi2MC);
1838 Printf("Chi2 (full range) from (MC - Unfolded) / e(MC) is: %.2f ndf is %d --> chi2 / ndf = %.2f", newChi2, ndf, ((ndf > 0) ? newChi2 / ndf : -1));
1840 diffMCUnfolded2->SetTitle("#chi^{2};Npart;(MC - Unfolded) / e(MC)");
1841 diffMCUnfolded2->GetYaxis()->SetRangeUser(-5, 5);
1842 diffMCUnfolded2->GetXaxis()->SetRangeUser(0, 200);
1843 diffMCUnfolded2->DrawCopy("HIST");
1846 canvas1->SaveAs(Form("%s.gif", canvas1->GetName()));
1849 //____________________________________________________________________
1850 void AliMultiplicityCorrection::FFT(Int_t dir, Int_t m, Double_t *x, Double_t *y)
1852 /*-------------------------------------------------------------------------
1853 This computes an in-place complex-to-complex FFT
1854 x and y are the real and imaginary arrays of 2^m points.
1855 dir = 1 gives forward transform
1856 dir = -1 gives reverse transform
1861 1 \ - j k 2 pi n / N
1862 X(n) = --- > x(k) e = forward transform
1871 X(n) = > x(k) e = forward transform
1877 Long_t nn, i, i1, j, k, i2, l, l1, l2;
1878 Double_t c1, c2, tx, ty, t1, t2, u1, u2, z;
1880 /* Calculate the number of points */
1882 for (i = 0; i < m; i++)
1885 /* Do the bit reversal */
1888 for (i= 0; i < nn - 1; i++) {
1905 /* Compute the FFT */
1909 for (l = 0; l < m; l++) {
1914 for (j = 0;j < l1; j++) {
1915 for (i = j; i < nn; i += l2) {
1917 t1 = u1 * x[i1] - u2 * y[i1];
1918 t2 = u1 * y[i1] + u2 * x[i1];
1924 z = u1 * c1 - u2 * c2;
1925 u2 = u1 * c2 + u2 * c1;
1928 c2 = TMath::Sqrt((1.0 - c1) / 2.0);
1931 c1 = TMath::Sqrt((1.0 + c1) / 2.0);
1934 /* Scaling for forward transform */
1936 for (i=0;i<nn;i++) {
1937 x[i] /= (Double_t)nn;
1938 y[i] /= (Double_t)nn;
1943 //____________________________________________________________________
1944 void AliMultiplicityCorrection::GetComparisonResults(Float_t* mc, Int_t* mcLimit, Float_t* residuals, Float_t* ratioAverage) const
1946 // Returns the chi2 between the MC and the unfolded ESD as well as between the ESD and the folded unfolded ESD
1947 // These values are computed during DrawComparison, thus this function picks up the
1953 *mcLimit = fLastChi2MCLimit;
1955 *residuals = fLastChi2Residuals;
1957 *ratioAverage = fRatioAverage;
1960 //____________________________________________________________________
1961 TH2F* AliMultiplicityCorrection::GetMultiplicityMC(Int_t i, EventType eventType)
1964 // returns the corresponding MC spectrum
1969 case kTrVtx : return fMultiplicityVtx[i]; break;
1970 case kMB : return fMultiplicityMB[i]; break;
1971 case kINEL : return fMultiplicityINEL[i]; break;
1972 case kNSD : return fMultiplicityNSD[i]; break;
1978 //____________________________________________________________________
1979 void AliMultiplicityCorrection::SetMultiplicityMC(Int_t i, EventType eventType, TH2F* hist)
1982 // returns the corresponding MC spectrum
1987 case kTrVtx : fMultiplicityVtx[i] = hist; break;
1988 case kMB : fMultiplicityMB[i] = hist; break;
1989 case kINEL : fMultiplicityINEL[i] = hist; break;
1990 case kNSD : fMultiplicityNSD[i] = hist; break;
1994 //____________________________________________________________________
1995 TH1* AliMultiplicityCorrection::CalculateStdDev(TH1** results, Int_t max)
1997 // calculate standard deviation of (results[0] - results[k]) k=1...max-1
1998 // per bin one gets: sigma(r[0] - r[n]) / r[0]
2000 TH1* standardDeviation = (TH1*) results[0]->Clone("standardDeviation");
2001 standardDeviation->Reset();
2003 for (Int_t x=1; x<=results[0]->GetNbinsX(); x++)
2005 if (results[0]->GetBinContent(x) > 0)
2007 Double_t average = 0;
2008 for (Int_t n=1; n<max; ++n)
2009 average += results[n]->GetBinContent(x) - results[0]->GetBinContent(x);
2012 Double_t variance = 0;
2013 for (Int_t n=1; n<max; ++n)
2015 Double_t value = results[n]->GetBinContent(x) - results[0]->GetBinContent(x) - average;
2016 variance += value * value;
2020 Double_t standardDev = TMath::Sqrt(variance);
2021 standardDeviation->SetBinContent(x, standardDev / results[0]->GetBinContent(x));
2022 //Printf("sigma_%d is %f value %f --> error %f", x, standardDev, results[0]->GetBinContent(x), standardDev / results[0]->GetBinContent(x));
2026 return standardDeviation;
2029 //____________________________________________________________________
2030 TH1* AliMultiplicityCorrection::StatisticalUncertainty(MethodType methodType, Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Bool_t randomizeMeasured, Bool_t randomizeResponse, TH1* compareTo)
2033 // evaluates the uncertainty that arises from the non-infinite statistics in the response matrix
2034 // the function unfolds the spectrum using the default response matrix and several modified ones
2035 // the modified ones are created by randomizing each cell using poisson statistics with the mean = bin value
2036 // these unfolded results are compared to the first result gained with the default response OR to the histogram given
2037 // in <compareTo> (optional)
2039 // returns the error assigned to the measurement
2042 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
2044 // initialize seed with current time
2045 gRandom->SetSeed(0);
2047 const Int_t kErrorIterations = 150;
2050 TH1* firstResult = 0;
2052 TH1** results = new TH1*[kErrorIterations];
2054 for (Int_t n=0; n<kErrorIterations; ++n)
2056 Printf("Iteration %d of %d...", n, kErrorIterations);
2058 // only done for chi2 minimization
2059 Bool_t createBigBin = kFALSE;
2060 if (methodType == kChi2Minimization)
2061 createBigBin = kTRUE;
2063 SetupCurrentHists(inputRange, fullPhaseSpace, eventType, createBigBin);
2065 TH1* measured = (TH1*) fCurrentESD->Clone("measured");
2069 if (randomizeResponse)
2071 // randomize response matrix
2072 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2073 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
2074 fCurrentCorrelation->SetBinContent(i, j, gRandom->Poisson(fCurrentCorrelation->GetBinContent(i, j)));
2077 if (randomizeMeasured)
2079 // randomize measured spectrum
2080 for (Int_t x=1; x<=measured->GetNbinsX(); x++) // mult. axis
2082 Int_t randomValue = gRandom->Poisson(fCurrentESD->GetBinContent(x));
2083 measured->SetBinContent(x, randomValue);
2084 measured->SetBinError(x, TMath::Sqrt(randomValue));
2089 // only for bayesian method we have to do it before the call to Unfold...
2090 if (methodType == kBayesian)
2092 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2094 // with this it is normalized to 1
2095 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
2097 // with this normalized to the given efficiency
2098 if (fCurrentEfficiency->GetBinContent(i) > 0)
2099 sum /= fCurrentEfficiency->GetBinContent(i);
2103 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
2107 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
2108 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
2112 fCurrentCorrelation->SetBinContent(i, j, 0);
2113 fCurrentCorrelation->SetBinError(i, j, 0);
2120 if (n == 0 && compareTo)
2122 // in this case we just store the histogram we want to compare to
2123 result = (TH1*) compareTo->Clone("compareTo");
2128 result = (TH1*) fMultiplicityESDCorrected[correlationID]->Clone(Form("result_%d", n));
2130 Int_t returnCode = -1;
2131 if (methodType == kChi2Minimization)
2133 returnCode = UnfoldWithMinuit(fCurrentCorrelation, fCurrentEfficiency, measured, 0, result, kFALSE);
2135 else if (methodType == kBayesian)
2136 returnCode = UnfoldWithBayesian(fCurrentCorrelation, fCurrentEfficiency, measured, 0, result, fgBayesianSmoothing, fgBayesianIterations);
2138 if (returnCode != 0)
2143 result->Scale(1.0 / result->Integral());
2147 firstResult = (TH1*) result->Clone("firstResult");
2149 maxError = (TH1*) result->Clone("maxError");
2155 TH1* ratio = (TH1*) firstResult->Clone("ratio");
2156 ratio->Divide(result);
2158 // find max. deviation
2159 for (Int_t x=1; x<=ratio->GetNbinsX(); x++)
2160 maxError->SetBinContent(x, TMath::Max(maxError->GetBinContent(x), TMath::Abs(1 - ratio->GetBinContent(x))));
2165 results[n] = result;
2168 // find covariance matrix
2169 // results[n] is X_x
2170 // cov. matrix is M_xy = E ( (X_x - E(X_x)) * (X_y - E(X_y))), with E() = expectation value
2172 Int_t nBins = results[0]->GetNbinsX();
2173 Float_t lowEdge = results[0]->GetXaxis()->GetBinLowEdge(1);
2174 Float_t upEdge = results[0]->GetXaxis()->GetBinUpEdge(nBins);
2176 // find average, E(X)
2177 TProfile* average = new TProfile("average", "average", nBins, lowEdge, upEdge);
2178 for (Int_t n=1; n<kErrorIterations; ++n)
2179 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2180 average->Fill(results[n]->GetXaxis()->GetBinCenter(x), results[n]->GetBinContent(x));
2181 //new TCanvas; average->DrawClone();
2184 TProfile2D* covMatrix = new TProfile2D("covMatrix", "covMatrix", nBins, lowEdge, upEdge, nBins, lowEdge, upEdge);
2186 for (Int_t n=1; n<kErrorIterations; ++n)
2187 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2188 for (Int_t y=1; y<=results[n]->GetNbinsX(); y++)
2190 // (X_x - E(X_x)) * (X_y - E(X_y)
2191 Float_t cov = (results[n]->GetBinContent(x) - average->GetBinContent(x)) * (results[n]->GetBinContent(y) - average->GetBinContent(y));
2192 covMatrix->Fill(results[n]->GetXaxis()->GetBinCenter(x), results[n]->GetXaxis()->GetBinCenter(y), cov);
2194 TCanvas* c = new TCanvas; c->cd(); covMatrix->DrawCopy("COLZ");
2196 // // fill 2D histogram that contains deviation from first
2197 // TH2F* deviations = new TH2F("deviations", "deviations", nBins, lowEdge, upEdge, 1000, -0.01, 0.01);
2198 // for (Int_t n=1; n<kErrorIterations; ++n)
2199 // for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2200 // deviations->Fill(results[n]->GetXaxis()->GetBinCenter(x), results[n]->GetBinContent(x) - results[0]->GetBinContent(x));
2201 // //new TCanvas; deviations->DrawCopy("COLZ");
2203 // // get standard deviation "by hand"
2204 // for (Int_t x=1; x<=nBins; x++)
2206 // if (results[0]->GetBinContent(x) > 0)
2208 // TH1* proj = deviations->ProjectionY("projRMS", x, x, "e");
2209 // Float_t standardDev = proj->GetRMS(); // this is standard deviation in fact
2210 // //standardDeviation->SetBinContent(x, standardDev / results[0]->GetBinContent(x));
2211 // Printf("sigma_%d is %f value %f --> error %f", x, standardDev, results[0]->GetBinContent(x), standardDev / results[0]->GetBinContent(x));
2215 TH1* standardDeviation = CalculateStdDev(results, kErrorIterations);
2217 // compare maxError to RMS of profile (variable name: average)
2218 // first: calculate rms in percent of value
2219 TH1* rmsError = (TH1*) maxError->Clone("rmsError");
2222 // enable error to be standard deviation (see http://root.cern.ch/root/html/TProfile.html#TProfile:SetErrorOption)
2223 average->SetErrorOption("s");
2224 for (Int_t x=1; x<=rmsError->GetNbinsX(); x++)
2225 if (average->GetBinContent(x) > 0)
2226 rmsError->SetBinContent(x, average->GetBinError(x) / average->GetBinContent(x));
2228 // find maxError deviation from average (not from "first result"/mc as above)
2229 TH1* maxError2 = (TH1*) maxError->Clone("maxError2");
2231 for (Int_t n=1; n<kErrorIterations; ++n)
2232 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2233 if (average->GetBinContent(x) > 0)
2234 maxError2->SetBinContent(x, TMath::Max(maxError2->GetBinContent(x), TMath::Abs((results[n]->GetBinContent(x) - average->GetBinContent(x)) / average->GetBinContent(x))));
2236 //new TCanvas; maxError2->DrawCopy(); rmsError->SetLineColor(2); rmsError->DrawCopy("SAME"); standardDeviation->SetLineColor(3); standardDeviation->DrawCopy("SAME");
2238 // plot difference between average and MC/first result
2239 TH1* averageFirstRatio = (TH1*) results[0]->Clone("averageFirstRatio");
2240 averageFirstRatio->Reset();
2241 averageFirstRatio->Divide(results[0], average);
2243 //new TCanvas; results[0]->DrawCopy(); average->SetLineColor(2); average->DrawClone("SAME");
2244 //new TCanvas; averageFirstRatio->DrawCopy();
2246 static TH1* temp = 0;
2249 temp = (TH1*) standardDeviation->Clone("temp");
2250 for (Int_t x=1; x<=results[0]->GetNbinsX(); x++)
2251 temp->SetBinContent(x, temp->GetBinContent(x) * results[0]->GetBinContent(x));
2255 // find difference from result[0] as TH2
2256 TH2F* pulls = new TH2F("pulls", "pulls;multiplicity;difference", nBins, lowEdge, upEdge, 1000, -10, 10);
2257 for (Int_t n=1; n<kErrorIterations; ++n)
2258 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
2259 if (temp->GetBinContent(x) > 0)
2260 pulls->Fill(results[n]->GetXaxis()->GetBinCenter(x), (results[0]->GetBinContent(x) - results[n]->GetBinContent(x)) / temp->GetBinContent(x));
2261 new TCanvas("pulls", "pulls", 800, 600); pulls->DrawCopy(); pulls->FitSlicesY();
2265 for (Int_t n=0; n<kErrorIterations; ++n)
2269 // fill into result histogram
2270 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); ++i)
2271 fMultiplicityESDCorrected[correlationID]->SetBinContent(i, firstResult->GetBinContent(i));
2273 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); ++i)
2274 fMultiplicityESDCorrected[correlationID]->SetBinError(i, maxError->GetBinContent(i) * fMultiplicityESDCorrected[correlationID]->GetBinContent(i));
2276 return standardDeviation;
2279 //____________________________________________________________________
2280 void AliMultiplicityCorrection::ApplyBayesianMethod(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Float_t regPar, Int_t nIterations, TH1* initialConditions, Bool_t determineError)
2283 // correct spectrum using bayesian method
2286 // initialize seed with current time
2287 gRandom->SetSeed(0);
2289 SetupCurrentHists(inputRange, fullPhaseSpace, eventType, kFALSE);
2291 // normalize correction for given nPart
2292 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2294 // with this it is normalized to 1
2295 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
2297 // with this normalized to the given efficiency
2298 if (fCurrentEfficiency->GetBinContent(i) > 0)
2299 sum /= fCurrentEfficiency->GetBinContent(i);
2303 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
2307 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
2308 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
2312 fCurrentCorrelation->SetBinContent(i, j, 0);
2313 fCurrentCorrelation->SetBinError(i, j, 0);
2318 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
2320 if (UnfoldWithBayesian(fCurrentCorrelation, fCurrentEfficiency, fCurrentESD, initialConditions, fMultiplicityESDCorrected[correlationID], regPar, nIterations) != 0)
2323 if (!determineError)
2325 Printf("AliMultiplicityCorrection::ApplyBayesianMethod: WARNING: No errors calculated.");
2329 // evaluate errors, this is done by randomizing the measured spectrum following Poission statistics
2330 // this (new) measured spectrum is then unfolded and the different to the result from the "real" measured
2331 // spectrum calculated. This is performed N times and the sigma is taken as the statistical
2332 // error of the unfolding method itself.
2334 const Int_t kErrorIterations = 20;
2336 printf("Spectrum unfolded. Determining error (%d iterations)...\n", kErrorIterations);
2338 TH1* randomized = (TH1*) fCurrentESD->Clone("randomized");
2339 TH1* resultArray[kErrorIterations+1];
2340 for (Int_t n=0; n<kErrorIterations; ++n)
2342 // randomize the content of clone following a poisson with the mean = the value of that bin
2343 for (Int_t x=1; x<=randomized->GetNbinsX(); x++) // mult. axis
2345 Int_t randomValue = gRandom->Poisson(fCurrentESD->GetBinContent(x));
2346 //printf("%d --> %d\n", fCurrentESD->GetBinContent(x), randomValue);
2347 randomized->SetBinContent(x, randomValue);
2348 randomized->SetBinError(x, TMath::Sqrt(randomValue));
2351 TH1* result2 = (TH1*) fMultiplicityESDCorrected[correlationID]->Clone("result2");
2353 if (UnfoldWithBayesian(fCurrentCorrelation, fCurrentEfficiency, randomized, initialConditions, result2, regPar, nIterations) != 0)
2356 result2->Scale(1.0 / result2->Integral());
2358 resultArray[n+1] = result2;
2362 resultArray[0] = fMultiplicityESDCorrected[correlationID];
2363 TH1* error = CalculateStdDev(resultArray, kErrorIterations+1);
2365 for (Int_t n=0; n<kErrorIterations; ++n)
2366 delete resultArray[n+1];
2368 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); ++i)
2369 fMultiplicityESDCorrected[correlationID]->SetBinError(i, error->GetBinContent(i) * fMultiplicityESDCorrected[correlationID]->GetBinContent(i));
2374 //____________________________________________________________________
2375 Int_t AliMultiplicityCorrection::UnfoldWithBayesian(TH1* correlation, TH1* aEfficiency, TH1* measured, TH1* initialConditions, TH1* aResult, Float_t regPar, Int_t nIterations)
2378 // unfolds a spectrum
2381 if (measured->Integral() <= 0)
2383 Printf("AliMultiplicityCorrection::UnfoldWithBayesian: ERROR: The measured spectrum is empty");
2387 const Int_t kStartBin = 0;
2389 const Int_t kMaxM = fgkMaxInput; //<= fCurrentCorrelation->GetNbinsY(); // max measured axis
2390 const Int_t kMaxT = fgkMaxParams; //<= fCurrentCorrelation->GetNbinsX(); // max true axis
2392 // convergence limit: kMaxT * 0.001^2 = kMaxT * 1e-6 (e.g. 250 bins --> 2.5 e-4)
2393 const Double_t kConvergenceLimit = kMaxT * 1e-6;
2395 // store information in arrays, to increase processing speed (~ factor 5)
2396 Double_t measuredCopy[kMaxM];
2397 Double_t measuredError[kMaxM];
2398 Double_t prior[kMaxT];
2399 Double_t result[kMaxT];
2400 Double_t efficiency[kMaxT];
2402 Double_t response[kMaxT][kMaxM];
2403 Double_t inverseResponse[kMaxT][kMaxM];
2405 // for normalization
2406 Float_t measuredIntegral = measured->Integral();
2407 for (Int_t m=0; m<kMaxM; m++)
2409 measuredCopy[m] = measured->GetBinContent(m+1) / measuredIntegral;
2410 measuredError[m] = measured->GetBinError(m+1) / measuredIntegral;
2412 for (Int_t t=0; t<kMaxT; t++)
2414 response[t][m] = correlation->GetBinContent(t+1, m+1);
2415 inverseResponse[t][m] = 0;
2419 for (Int_t t=0; t<kMaxT; t++)
2421 efficiency[t] = aEfficiency->GetBinContent(t+1);
2422 prior[t] = measuredCopy[t];
2426 // pick prior distribution
2427 if (initialConditions)
2429 printf("Using different starting conditions...\n");
2430 // for normalization
2431 Float_t inputDistIntegral = initialConditions->Integral();
2432 for (Int_t i=0; i<kMaxT; i++)
2433 prior[i] = initialConditions->GetBinContent(i+1) / inputDistIntegral;
2436 //TH1F* convergence = new TH1F("convergence", "convergence", 200, 0.5, 200.5);
2439 for (Int_t i=0; i<nIterations || nIterations < 0; i++)
2441 //printf(" iteration %i \n", i);
2443 // calculate IR from Beyes theorem
2444 // IR_ji = R_ij * prior_i / sum_k(R_kj * prior_k)
2446 Double_t chi2Measured = 0;
2447 for (Int_t m=0; m<kMaxM; m++)
2450 for (Int_t t = kStartBin; t<kMaxT; t++)
2451 norm += response[t][m] * prior[t];
2453 // calc. chi2: (measured - response * prior) / error
2454 if (measuredError[m] > 0)
2456 Double_t value = (measuredCopy[m] - norm) / measuredError[m];
2457 chi2Measured += value * value;
2462 for (Int_t t = kStartBin; t<kMaxT; t++)
2463 inverseResponse[t][m] = response[t][m] * prior[t] / norm;
2467 for (Int_t t = kStartBin; t<kMaxT; t++)
2468 inverseResponse[t][m] = 0;
2471 //Printf("chi2Measured of the last prior is %e", chi2Measured);
2473 for (Int_t t = kStartBin; t<kMaxT; t++)
2476 for (Int_t m=0; m<kMaxM; m++)
2477 value += inverseResponse[t][m] * measuredCopy[m];
2479 if (efficiency[t] > 0)
2480 result[t] = value / efficiency[t];
2485 // draw intermediate result
2487 for (Int_t t=0; t<kMaxT; t++)
2488 aResult->SetBinContent(t+1, result[t]);
2489 aResult->SetMarkerStyle(20+i);
2490 aResult->SetMarkerColor(2);
2491 aResult->DrawCopy("P SAME HIST");
2494 Double_t chi2LastIter = 0;
2495 // regularization (simple smoothing)
2496 for (Int_t t=kStartBin; t<kMaxT; t++)
2498 Float_t newValue = 0;
2500 // 0 bin excluded from smoothing
2501 if (t > kStartBin+2 && t<kMaxT-1)
2503 Float_t average = (result[t-1] + result[t] + result[t+1]) / 3;
2505 // weight the average with the regularization parameter
2506 newValue = (1 - regPar) * result[t] + regPar * average;
2509 newValue = result[t];
2511 // calculate chi2 (change from last iteration)
2512 if (prior[t] > 1e-5)
2514 Double_t diff = (prior[t] - newValue) / prior[t];
2515 chi2LastIter += diff * diff;
2518 prior[t] = newValue;
2520 //printf("Chi2 of %d iteration = %e\n", i, chi2LastIter);
2521 //convergence->Fill(i+1, chi2LastIter);
2523 if (nIterations < 0 && chi2LastIter < kConvergenceLimit)
2525 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);
2530 // DrawComparison(Form("Bayesian_%d", i), mcTarget, correlationID, kTRUE, eventType);
2531 } // end of iterations
2533 //new TCanvas; convergence->DrawCopy(); gPad->SetLogy();
2534 //delete convergence;
2536 for (Int_t t=0; t<kMaxT; t++)
2537 aResult->SetBinContent(t+1, result[t]);
2542 // Calculate the covariance matrix, all arguments are taken from NIM,A362,487-498,1995
2544 /*printf("Calculating covariance matrix. This may take some time...\n");
2546 // TODO check if this is the right one...
2547 TH1* sumHist = GetMultiplicityMC(inputRange, eventType)->ProjectionY("sumHist", 1, GetMultiplicityMC(inputRange, eventType)->GetNbinsX());
2549 Int_t xBins = hInverseResponseBayes->GetNbinsX();
2550 Int_t yBins = hInverseResponseBayes->GetNbinsY();
2552 // calculate "unfolding matrix" Mij
2553 Float_t matrixM[251][251];
2554 for (Int_t i=1; i<=xBins; i++)
2556 for (Int_t j=1; j<=yBins; j++)
2558 if (fCurrentEfficiency->GetBinContent(i) > 0)
2559 matrixM[i-1][j-1] = hInverseResponseBayes->GetBinContent(i, j) / fCurrentEfficiency->GetBinContent(i);
2561 matrixM[i-1][j-1] = 0;
2565 Float_t* vectorn = new Float_t[yBins];
2566 for (Int_t j=1; j<=yBins; j++)
2567 vectorn[j-1] = fCurrentESD->GetBinContent(j);
2569 // first part of covariance matrix, depends on input distribution n(E)
2570 Float_t cov1[251][251];
2572 Float_t nEvents = fCurrentESD->Integral(); // N
2577 for (Int_t k=0; k<xBins; k++)
2579 printf("In Cov1: %d\n", k);
2580 for (Int_t l=0; l<yBins; l++)
2584 // sum_j Mkj Mlj n(Ej) * (1 - n(Ej) / N)
2585 for (Int_t j=0; j<yBins; j++)
2586 cov1[k][l] += matrixM[k][j] * matrixM[l][j] * vectorn[j]
2587 * (1.0 - vectorn[j] / nEvents);
2589 // - sum_i,j (i != j) Mki Mlj n(Ei) n(Ej) / N
2590 for (Int_t i=0; i<yBins; i++)
2591 for (Int_t j=0; j<yBins; j++)
2595 cov1[k][l] -= matrixM[k][i] * matrixM[l][j] * vectorn[i]
2596 * vectorn[j] / nEvents;
2601 printf("Cov1 finished\n");
2603 TH2F* cov = (TH2F*) hInverseResponseBayes->Clone("cov");
2606 for (Int_t i=1; i<=xBins; i++)
2607 for (Int_t j=1; j<=yBins; j++)
2608 cov->SetBinContent(i, j, cov1[i-1][j-1]);
2613 // second part of covariance matrix, depends on response matrix
2614 Float_t cov2[251][251];
2616 // Cov[P(Er|Cu), P(Es|Cu)] term
2617 Float_t covTerm[100][100][100];
2618 for (Int_t r=0; r<yBins; r++)
2619 for (Int_t u=0; u<xBins; u++)
2620 for (Int_t s=0; s<yBins; s++)
2623 covTerm[r][u][s] = 1.0 / sumHist->GetBinContent(u+1) * hResponse->GetBinContent(u+1, r+1)
2624 * (1.0 - hResponse->GetBinContent(u+1, r+1));
2626 covTerm[r][u][s] = - 1.0 / sumHist->GetBinContent(u+1) * hResponse->GetBinContent(u+1, r+1)
2627 * hResponse->GetBinContent(u+1, s+1);
2630 for (Int_t k=0; k<xBins; k++)
2631 for (Int_t l=0; l<yBins; l++)
2634 printf("In Cov2: %d %d\n", k, l);
2635 for (Int_t i=0; i<yBins; i++)
2636 for (Int_t j=0; j<yBins; j++)
2638 //printf("In Cov2: %d %d %d %d\n", k, l, i, j);
2639 // calculate Cov(Mki, Mlj) = sum{ru},{su} ...
2641 for (Int_t r=0; r<yBins; r++)
2642 for (Int_t u=0; u<xBins; u++)
2643 for (Int_t s=0; s<yBins; s++)
2645 if (hResponse->GetBinContent(u+1, r+1) == 0 || hResponse->GetBinContent(u+1, s+1) == 0
2646 || hResponse->GetBinContent(u+1, i+1) == 0)
2649 tmpCov += BayesCovarianceDerivate(matrixM, hResponse, fCurrentEfficiency, k, i, r, u)
2650 * BayesCovarianceDerivate(matrixM, hResponse, fCurrentEfficiency, l, j, s, u)
2654 cov2[k][l] += fCurrentESD->GetBinContent(i+1) * fCurrentESD->GetBinContent(j+1) * tmpCov;
2658 printf("Cov2 finished\n");
2660 for (Int_t i=1; i<=xBins; i++)
2661 for (Int_t j=1; j<=yBins; j++)
2662 cov->SetBinContent(i, j, cov1[i-1][j-1] + cov2[i-1][j-1]);
2665 cov->Draw("COLZ");*/
2668 //____________________________________________________________________
2669 Float_t AliMultiplicityCorrection::BayesCovarianceDerivate(Float_t matrixM[251][251], TH2* hResponse, Int_t k, Int_t i, Int_t r, Int_t u)
2672 // helper function for the covariance matrix of the bayesian method
2677 if (k == u && r == i)
2678 result += 1.0 / hResponse->GetBinContent(u+1, r+1);
2681 result -= 1.0 / fCurrentEfficiency->GetBinContent(u+1);
2684 result -= matrixM[u][i] * fCurrentEfficiency->GetBinContent(u+1) / hResponse->GetBinContent(u+1, i+1);
2686 result *= matrixM[k][i];
2691 //____________________________________________________________________
2692 void AliMultiplicityCorrection::ApplyLaszloMethod(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType)
2695 // correct spectrum using bayesian method
2700 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
2701 Int_t mcTarget = ((fullPhaseSpace == kFALSE) ? inputRange : 4);
2703 SetupCurrentHists(inputRange, fullPhaseSpace, eventType, kFALSE);
2705 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
2707 // TODO should be taken from correlation map
2708 //TH1* sumHist = GetMultiplicityMC(inputRange, eventType)->ProjectionY("sumHist", 1, GetMultiplicityMC(inputRange, eventType)->GetNbinsX());
2710 // normalize correction for given nPart
2711 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2713 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
2714 //Double_t sum = sumHist->GetBinContent(i);
2717 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
2720 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
2721 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
2726 fCurrentCorrelation->Draw("COLZ");
2729 fCurrentEfficiency = ((TH2*) fCurrentCorrelation)->ProjectionX("eff");
2731 // pick prior distribution
2732 TH1F* hPrior = (TH1F*)fCurrentESD->Clone("prior");
2733 Float_t norm = 1; //hPrior->Integral();
2734 for (Int_t t=1; t<=hPrior->GetNbinsX(); t++)
2735 hPrior->SetBinContent(t, hPrior->GetBinContent(t)/norm);
2737 // zero distribution
2738 TH1F* zero = (TH1F*)hPrior->Clone("zero");
2741 TH1F* hTemp = (TH1F*)fCurrentESD->Clone("temp");
2745 TH2F* hResponse = (TH2F*) fCurrentCorrelation;
2748 Int_t iterations = 25;
2749 for (Int_t i=0; i<iterations; i++)
2751 //printf(" iteration %i \n", i);
2753 for (Int_t m=1; m<=hResponse->GetNbinsY(); m++)
2756 for (Int_t t = 1; t<=hResponse->GetNbinsX(); t++)
2757 value += hResponse->GetBinContent(t, m) * hPrior->GetBinContent(t);
2758 hTemp->SetBinContent(m, value);
2759 //printf("%d %f %f %f\n", m, zero->GetBinContent(m), hPrior->GetBinContent(m), value);
2762 // regularization (simple smoothing)
2763 TH1F* hTrueSmoothed = (TH1F*) hTemp->Clone("truesmoothed");
2765 for (Int_t t=2; t<hTrueSmoothed->GetNbinsX(); t++)
2767 Float_t average = (hTemp->GetBinContent(t-1) / hTemp->GetBinWidth(t-1)
2768 + hTemp->GetBinContent(t) / hTemp->GetBinWidth(t)
2769 + hTemp->GetBinContent(t+1) / hTemp->GetBinWidth(t+1)) / 3.;
2770 average *= hTrueSmoothed->GetBinWidth(t);
2772 // weight the average with the regularization parameter
2773 hTrueSmoothed->SetBinContent(t, (1-regPar) * hTemp->GetBinContent(t) + regPar * average);
2776 for (Int_t m=1; m<=hResponse->GetNbinsY(); m++)
2777 hTemp->SetBinContent(m, zero->GetBinContent(m) + hPrior->GetBinContent(m) - hTrueSmoothed->GetBinContent(m));
2780 for (Int_t t=1; t<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); t++)
2782 fMultiplicityESDCorrected[correlationID]->SetBinContent(t, hTemp->GetBinContent(t));
2783 fMultiplicityESDCorrected[correlationID]->SetBinError(t, 0.05 * hTemp->GetBinContent(t)); // TODO
2785 //printf(" bin %d content %f \n", t, fMultiplicityESDCorrected[correlationID]->GetBinContent(t));
2789 // calculate chi2 (change from last iteration)
2792 // use smoothed true (normalized) as new prior
2793 norm = 1; //hTrueSmoothed->Integral();
2795 for (Int_t t=1; t<hTrueSmoothed->GetNbinsX(); t++)
2797 Float_t newValue = hTemp->GetBinContent(t)/norm;
2798 Float_t diff = hPrior->GetBinContent(t) - newValue;
2799 chi2 += (Double_t) diff * diff;
2801 hPrior->SetBinContent(t, newValue);
2804 printf("Chi2 of %d iteration = %.10f\n", i, chi2);
2807 DrawComparison(Form("Laszlo_%d", i), inputRange, fullPhaseSpace, kTRUE, GetMultiplicityMC(mcTarget, eventType)->ProjectionY());
2809 delete hTrueSmoothed;
2810 } // end of iterations
2812 DrawComparison("Laszlo", inputRange, fullPhaseSpace, kTRUE, GetMultiplicityMC(mcTarget, eventType)->ProjectionY());
2815 //____________________________________________________________________
2816 void AliMultiplicityCorrection::ApplyGaussianMethod(Int_t inputRange, Bool_t fullPhaseSpace)
2819 // correct spectrum using a simple Gaussian approach, that is model-dependent
2822 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
2823 Int_t mcTarget = ((fullPhaseSpace == kFALSE) ? inputRange : 4);
2825 SetupCurrentHists(inputRange, fullPhaseSpace, kTrVtx, kFALSE);
2827 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
2829 TH1D* correction = dynamic_cast<TH1D*> (fCurrentESD->Clone("GaussianMean"));
2830 correction->SetTitle("GaussianMean");
2832 TH1D* correctionWidth = dynamic_cast<TH1D*> (fCurrentESD->Clone("GaussianWidth"));
2833 correction->SetTitle("GaussianWidth");
2835 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2837 TH1D* proj = (dynamic_cast<TH2*> (fCurrentCorrelation))->ProjectionX("_px", i, i+1);
2838 proj->Fit("gaus", "0Q");
2839 correction->SetBinContent(i, proj->GetFunction("gaus")->GetParameter(1));
2840 correctionWidth->SetBinContent(i, proj->GetFunction("gaus")->GetParameter(2));
2844 // draw for debugging
2847 proj->GetFunction("gaus")->DrawCopy("SAME");
2850 TH1* target = fMultiplicityESDCorrected[correlationID];
2852 Int_t nBins = target->GetNbinsX()*10+1;
2853 Float_t* binning = new Float_t[nBins];
2854 for (Int_t i=1; i<=target->GetNbinsX(); ++i)
2855 for (Int_t j=0; j<10; ++j)
2856 binning[(i-1)*10 + j] = target->GetXaxis()->GetBinLowEdge(i) + target->GetXaxis()->GetBinWidth(i) / 10 * j;
2858 binning[nBins-1] = target->GetXaxis()->GetBinUpEdge(target->GetNbinsX());
2860 TH1F* fineBinned = new TH1F("targetFineBinned", "targetFineBinned", nBins-1, binning);
2862 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2864 Float_t mean = correction->GetBinContent(i);
2865 Float_t width = correctionWidth->GetBinContent(i);
2867 Int_t fillBegin = fineBinned->FindBin(mean - width * 5);
2868 Int_t fillEnd = fineBinned->FindBin(mean + width * 5);
2869 //printf("bin %d mean %f width %f, filling from %d to %d\n", i, mean, width, fillBegin, fillEnd);
2871 for (Int_t j=fillBegin; j <= fillEnd; ++j)
2873 fineBinned->AddBinContent(j, TMath::Gaus(fineBinned->GetXaxis()->GetBinCenter(j), mean, width, kTRUE) * fCurrentESD->GetBinContent(i));
2877 for (Int_t i=1; i<=target->GetNbinsX(); ++i)
2880 for (Int_t j=1; j<=10; ++j)
2881 sum += fineBinned->GetBinContent((i-1)*10 + j);
2882 target->SetBinContent(i, sum / 10);
2887 DrawComparison("Gaussian", inputRange, fullPhaseSpace, kFALSE, GetMultiplicityMC(mcTarget, kTrVtx)->ProjectionY());
2890 //____________________________________________________________________
2891 TH2F* AliMultiplicityCorrection::CalculateMultiplicityESD(TH1* inputMC, Int_t correlationMap)
2893 // runs the distribution given in inputMC through the response matrix identified by
2894 // correlationMap and produces a measured distribution
2895 // although it is a TH2F the vertex axis is not used at the moment and all entries are filled in mid-vertex
2896 // if normalized is set, inputMC is expected to be normalized to the bin width
2901 if (correlationMap < 0 || correlationMap >= kCorrHists)
2904 // empty under/overflow bins in x, otherwise Project3D takes them into account
2905 TH3* hist = fCorrelation[correlationMap];
2906 for (Int_t y=0; y<=hist->GetYaxis()->GetNbins()+1; ++y)
2908 for (Int_t z=0; z<=hist->GetZaxis()->GetNbins()+1; ++z)
2910 hist->SetBinContent(0, y, z, 0);
2911 hist->SetBinContent(hist->GetXaxis()->GetNbins()+1, y, z, 0);
2915 TH2* corr = (TH2*) hist->Project3D("zy");
2916 //corr->Rebin2D(2, 1);
2918 Printf("Correction histogram used for convolution has %f entries", corr->Integral());
2920 // normalize correction for given nPart
2921 for (Int_t i=1; i<=corr->GetNbinsX(); ++i)
2923 Double_t sum = corr->Integral(i, i, 1, corr->GetNbinsY());
2927 for (Int_t j=1; j<=corr->GetNbinsY(); ++j)
2930 corr->SetBinContent(i, j, corr->GetBinContent(i, j) / sum);
2931 corr->SetBinError(i, j, corr->GetBinError(i, j) / sum);
2935 TH2F* target = dynamic_cast<TH2F*> (fMultiplicityESD[0]->Clone(Form("%s_measured", inputMC->GetName())));
2938 for (Int_t meas=1; meas<=corr->GetNbinsY(); ++meas)
2940 Float_t measured = 0;
2943 for (Int_t gen=1; gen<=corr->GetNbinsX(); ++gen)
2945 Int_t mcGenBin = inputMC->GetXaxis()->FindBin(corr->GetXaxis()->GetBinCenter(gen));
2947 measured += inputMC->GetBinContent(mcGenBin) * corr->GetBinContent(gen, meas);
2948 error += inputMC->GetBinError(mcGenBin) * corr->GetBinContent(gen, meas);
2951 //printf("%f +- %f ; %f +- %f \n", inputMC->GetBinContent(meas), inputMC->GetBinError(meas), measured, error);
2953 target->SetBinContent(1 + target->GetNbinsX() / 2, meas, measured);
2954 target->SetBinError(1 + target->GetNbinsX() / 2, meas, error);
2960 //____________________________________________________________________
2961 void AliMultiplicityCorrection::SetGenMeasFromFunc(TF1* inputMC, Int_t id)
2963 // uses the given function to fill the input MC histogram and generates from that
2964 // the measured histogram by applying the response matrix
2965 // this can be used to evaluate if the methods work indepedently of the input
2967 // WARNING does not respect the vertex distribution, just fills central vertex bin
2972 if (id < 0 || id >= kESDHists)
2975 // fill histogram used for random generation
2976 TH1* tmp = fMultiplicityVtx[id]->ProjectionY("tmp");
2979 for (Int_t i=1; i<=tmp->GetNbinsX(); ++i)
2980 tmp->SetBinContent(i, inputMC->Eval(tmp->GetXaxis()->GetBinCenter(i)) * tmp->GetXaxis()->GetBinWidth(i));
2982 TH1* mcRnd = fMultiplicityVtx[id]->ProjectionY("mcRnd");
2984 mcRnd->FillRandom(tmp, tmp->Integral());
2986 //new TCanvas; tmp->Draw();
2987 //new TCanvas; mcRnd->Draw();
2989 // and move into 2d histogram
2990 TH1* mc = fMultiplicityVtx[id];
2992 for (Int_t i=1; i<=mc->GetNbinsY(); ++i)
2994 mc->SetBinContent(mc->GetNbinsX() / 2 + 1, i, mcRnd->GetBinContent(i));
2995 mc->SetBinError(mc->GetNbinsX() / 2 + 1, i, TMath::Sqrt(mcRnd->GetBinContent(i)));
2998 //new TCanvas; mc->Draw("COLZ");
3000 // now randomize the measured histogram; funcMeasured is used as pilot function to generated the measured entries
3001 TH1* funcMeasured = CalculateMultiplicityESD(tmp, id)->ProjectionY("funcMeasured");
3003 //new TCanvas; funcMeasured->Draw();
3005 fMultiplicityESD[id]->Reset();
3007 TH1* measRnd = fMultiplicityESD[id]->ProjectionY("measRnd");
3008 measRnd->FillRandom(funcMeasured, tmp->Integral());
3010 //new TCanvas; measRnd->Draw();
3012 fMultiplicityESD[id]->Reset();
3013 for (Int_t i=1; i<=fMultiplicityESD[id]->GetNbinsY(); ++i)
3015 fMultiplicityESD[id]->SetBinContent(fMultiplicityESD[id]->GetNbinsX() / 2 + 1, i, measRnd->GetBinContent(i));
3016 fMultiplicityESD[id]->SetBinError(fMultiplicityESD[id]->GetNbinsX() / 2 + 1, i, TMath::Sqrt(measRnd->GetBinContent(i)));