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>
36 #include <TCollection.h>
41 #include <TProfile2D.h>
44 ClassImp(AliMultiplicityCorrection)
46 // Defined where the efficiency drops below 1/3
47 // |eta| < 1.4 --> -0.3 ... 0.8
48 // |eta| < 1.3 --> -1.9 ... 2.4
49 // |eta| < 1.0 --> -5.6 ... 6.1
50 //Double_t AliMultiplicityCorrection::fgVtxRangeBegin[kESDHists] = { -10.0, -5.6, -1.9 };
51 //Double_t AliMultiplicityCorrection::fgVtxRangeEnd[kESDHists] = { 10.0, 6.1, 2.4 };
52 Double_t AliMultiplicityCorrection::fgVtxRangeBegin[kESDHists] = { -10.0, -5.5, -1.9 };
53 Double_t AliMultiplicityCorrection::fgVtxRangeEnd[kESDHists] = { 10.0, 5.5, 2.4 };
55 // These are the areas where the quality of the unfolding results are evaluated
56 // Default defined here, call SetQualityRegions to change them
57 // unit is in multiplicity (not in bin!)
58 // SPD: peak area - flat area - low stat area
59 Int_t AliMultiplicityCorrection::fgQualityRegionsB[kQualityRegions] = {1, 20, 70};
60 Int_t AliMultiplicityCorrection::fgQualityRegionsE[kQualityRegions] = {10, 65, 80};
62 //____________________________________________________________________
63 void AliMultiplicityCorrection::SetQualityRegions(Bool_t SPDStudy)
66 // sets the quality region definition to TPC or SPD
71 // SPD: peak area - flat area - low stat area
72 fgQualityRegionsB[0] = 1;
73 fgQualityRegionsE[0] = 10;
75 fgQualityRegionsB[1] = 20;
76 fgQualityRegionsE[1] = 65;
78 fgQualityRegionsB[2] = 70;
79 fgQualityRegionsE[2] = 80;
81 Printf("AliMultiplicityCorrection::SetQualityRegions --> Enabled quality regions for SPD");
85 // TPC: peak area - flat area - low stat area
86 fgQualityRegionsB[0] = 4;
87 fgQualityRegionsE[0] = 12;
89 fgQualityRegionsB[1] = 25;
90 fgQualityRegionsE[1] = 55;
92 fgQualityRegionsB[2] = 88;
93 fgQualityRegionsE[2] = 108;
95 Printf("AliMultiplicityCorrection::SetQualityRegions --> Enabled quality regions for TPC");
99 //____________________________________________________________________
100 AliMultiplicityCorrection::AliMultiplicityCorrection() :
101 TNamed(), fCurrentESD(0), fCurrentCorrelation(0), fCurrentEfficiency(0), fLastBinLimit(0), fLastChi2MC(0), fLastChi2MCLimit(0), fLastChi2Residuals(0), fRatioAverage(0), fVtxBegin(0), fVtxEnd(0)
104 // default constructor
107 for (Int_t i = 0; i < kESDHists; ++i)
109 fMultiplicityESD[i] = 0;
110 fTriggeredEvents[i] = 0;
111 fNoVertexEvents[i] = 0;
114 for (Int_t i = 0; i < kMCHists; ++i)
116 fMultiplicityVtx[i] = 0;
117 fMultiplicityMB[i] = 0;
118 fMultiplicityINEL[i] = 0;
119 fMultiplicityNSD[i] = 0;
122 for (Int_t i = 0; i < kCorrHists; ++i)
125 fMultiplicityESDCorrected[i] = 0;
128 for (Int_t i = 0; i < kQualityRegions; ++i)
132 //____________________________________________________________________
133 AliMultiplicityCorrection* AliMultiplicityCorrection::Open(const char* fileName, const char* folderName)
135 // opens the given file, reads the multiplicity from the given folder and returns the object
137 TFile* file = TFile::Open(fileName);
140 Printf("ERROR: Could not open %s", fileName);
144 Printf("AliMultiplicityCorrection::Open: Reading file %s", fileName);
146 AliMultiplicityCorrection* mult = new AliMultiplicityCorrection(folderName, folderName);
147 mult->LoadHistograms();
149 // TODO closing the file does not work here, because the histograms cannot be read anymore. LoadHistograms need to be adapted
154 //____________________________________________________________________
155 AliMultiplicityCorrection::AliMultiplicityCorrection(const Char_t* name, const Char_t* title) :
158 fCurrentCorrelation(0),
159 fCurrentEfficiency(0),
163 fLastChi2Residuals(0),
172 // do not add this hists to the directory
173 Bool_t oldStatus = TH1::AddDirectoryStatus();
174 TH1::AddDirectory(kFALSE);
176 /*Float_t binLimitsVtx[] = {-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10};
177 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,
178 10.5, 11.5, 12.5, 13.5, 14.5, 15.5, 16.5, 17.5, 18.5, 19.5,
179 20.5, 21.5, 22.5, 23.5, 24.5, 25.5, 26.5, 27.5, 28.5, 29.5,
180 30.5, 31.5, 32.5, 33.5, 34.5, 35.5, 36.5, 37.5, 38.5, 39.5,
181 40.5, 41.5, 42.5, 43.5, 44.5, 45.5, 46.5, 47.5, 48.5, 49.5,
182 50.5, 55.5, 60.5, 65.5, 70.5, 75.5, 80.5, 85.5, 90.5, 95.5,
183 100.5, 105.5, 110.5, 115.5, 120.5, 125.5, 130.5, 135.5, 140.5, 145.5,
184 150.5, 160.5, 170.5, 180.5, 190.5, 200.5, 210.5, 220.5, 230.5, 240.5,
185 250.5, 275.5, 300.5, 325.5, 350.5, 375.5, 400.5, 425.5, 450.5, 475.5,
187 //525.5, 550.5, 575.5, 600.5, 625.5, 650.5, 675.5, 700.5, 725.5,
188 //750.5, 775.5, 800.5, 825.5, 850.5, 875.5, 900.5, 925.5, 950.5, 975.5,
191 #define VTXBINNING 10, binLimitsVtx
192 #define NBINNING fgkMaxParams, binLimitsN*/
194 #define NBINNING 201, -0.5, 200.5
196 for (Int_t i = 0; i < kESDHists; ++i)
198 fMultiplicityESD[i] = new TH2F(Form("fMultiplicityESD%d", i), "fMultiplicityESD;vtx-z;measured multiplicity;Count", 1, fgVtxRangeBegin[i], fgVtxRangeEnd[i], NBINNING);
199 fTriggeredEvents[i] = new TH1F(Form("fTriggeredEvents%d", i), "fTriggeredEvents;measured multiplicity;Count", NBINNING);
200 fNoVertexEvents[i] = new TH1F(Form("fNoVertexEvents%d", i), "fNoVertexEvents;generated multiplicity;Count", NBINNING);
203 for (Int_t i = 0; i < kMCHists; ++i)
205 fMultiplicityVtx[i] = dynamic_cast<TH2F*> (fMultiplicityESD[i%3]->Clone(Form("fMultiplicityVtx%d", i)));
206 fMultiplicityVtx[i]->SetTitle("fMultiplicityVtx;vtx-z;Npart");
208 fMultiplicityMB[i] = dynamic_cast<TH2F*> (fMultiplicityVtx[i]->Clone(Form("fMultiplicityMB%d", i)));
209 fMultiplicityMB[i]->SetTitle("fMultiplicityMB");
211 fMultiplicityINEL[i] = dynamic_cast<TH2F*> (fMultiplicityVtx[i]->Clone(Form("fMultiplicityINEL%d", i)));
212 fMultiplicityINEL[i]->SetTitle("fMultiplicityINEL");
214 fMultiplicityNSD[i] = dynamic_cast<TH2F*> (fMultiplicityVtx[i]->Clone(Form("fMultiplicityNSD%d", i)));
215 fMultiplicityNSD[i]->SetTitle("fMultiplicityNSD");
218 for (Int_t i = 0; i < kCorrHists; ++i)
220 fCorrelation[i] = new TH3F(Form("fCorrelation%d", i), "fCorrelation;vtx-z;true multiplicity;measured multiplicity", 1, fgVtxRangeBegin[i%3], fgVtxRangeEnd[i%3], NBINNING, NBINNING);
221 fMultiplicityESDCorrected[i] = new TH1F(Form("fMultiplicityESDCorrected%d", i), "fMultiplicityESDCorrected;true multiplicity;Count", NBINNING);
224 TH1::AddDirectory(oldStatus);
226 AliUnfolding::SetNbins(120, 120);
227 AliUnfolding::SetSkipBinsBegin(1);
228 //AliUnfolding::SetNormalizeInput(kTRUE);
231 //____________________________________________________________________
232 void AliMultiplicityCorrection::Rebin2DY(TH2F*& hist, Int_t nBins, Double_t* newBins) const
235 // rebins the y axis of a two-dimensional histogram giving variable size binning (missing in ROOT v5/25/02)
238 TH2F* temp = new TH2F(hist->GetName(), Form("%s;%s;%s", hist->GetTitle(), hist->GetXaxis()->GetTitle(), hist->GetYaxis()->GetTitle()), hist->GetNbinsX(), hist->GetXaxis()->GetXmin(), hist->GetXaxis()->GetXmax(), nBins, newBins);
240 for (Int_t x=0; x<=hist->GetNbinsX()+1; x++)
241 for (Int_t y=0; y<=hist->GetNbinsY()+1; y++)
242 temp->Fill(hist->GetXaxis()->GetBinCenter(x), hist->GetYaxis()->GetBinCenter(y), hist->GetBinContent(x, y));
244 for (Int_t x=0; x<=temp->GetNbinsX()+1; x++)
245 for (Int_t y=0; y<=temp->GetNbinsY()+1; y++)
246 temp->SetBinError(x, y, TMath::Sqrt(temp->GetBinContent(x, y)));
252 //____________________________________________________________________
253 void AliMultiplicityCorrection::Rebin3DY(TH3F*& hist, Int_t nBins, Double_t* newBins) const
256 // rebins the y axis of a three-dimensional histogram giving variable size binning (missing in ROOT v5/25/02)
257 // this function is a mess - and it should have been Fons who should have gone through the pain of writing it! (JF)
260 // construct variable size arrays for fixed size binning axes because TH3 lacks some constructors
261 Double_t* xBins = new Double_t[hist->GetNbinsX()+1];
262 Double_t* zBins = new Double_t[hist->GetNbinsZ()+1];
264 for (Int_t x=1; x<=hist->GetNbinsX()+1; x++)
266 xBins[x-1] = hist->GetXaxis()->GetBinLowEdge(x);
267 //Printf("%d %f", x, xBins[x-1]);
270 for (Int_t z=1; z<=hist->GetNbinsZ()+1; z++)
272 zBins[z-1] = hist->GetZaxis()->GetBinLowEdge(z);
273 //Printf("%d %f", y, yBins[y-1]);
276 TH3F* temp = new TH3F(hist->GetName(), Form("%s;%s;%s;%s", hist->GetTitle(), hist->GetXaxis()->GetTitle(), hist->GetYaxis()->GetTitle(), hist->GetZaxis()->GetTitle()), hist->GetNbinsX(), xBins, nBins, newBins, hist->GetNbinsZ(), zBins);
278 for (Int_t x=0; x<=hist->GetNbinsX()+1; x++)
279 for (Int_t y=0; y<=hist->GetNbinsY()+1; y++)
280 for (Int_t z=0; z<=hist->GetNbinsZ()+1; z++)
281 temp->Fill(hist->GetXaxis()->GetBinCenter(x), hist->GetYaxis()->GetBinCenter(y), hist->GetZaxis()->GetBinCenter(z), hist->GetBinContent(x, y, z));
283 for (Int_t x=0; x<=temp->GetNbinsX()+1; x++)
284 for (Int_t y=0; y<=temp->GetNbinsY()+1; y++)
285 for (Int_t z=0; z<=hist->GetNbinsZ()+1; z++)
286 temp->SetBinError(x, y, z, TMath::Sqrt(temp->GetBinContent(x, y, z)));
295 //____________________________________________________________________
296 void AliMultiplicityCorrection::RebinGenerated(Int_t nBins05, Double_t* newBins05, Int_t nBins10, Double_t* newBins10, Int_t nBins13, Double_t* newBins13)
299 // Rebins the (and only the) generated multiplicity axis
302 Printf("Rebinning generated-multiplicity axis...");
304 // do not add this hists to the directory
305 Bool_t oldStatus = TH1::AddDirectoryStatus();
306 TH1::AddDirectory(kFALSE);
309 AliFatal("This function only works for three ESD hists!");
311 for (Int_t i = 0; i < kESDHists; ++i)
314 Double_t* newBins = 0;
334 fNoVertexEvents[i] = (TH1F*) fNoVertexEvents[i]->Rebin(nBins, fNoVertexEvents[i]->GetName(), newBins);
335 fMultiplicityESDCorrected[i] = (TH1F*) fMultiplicityESDCorrected[i]->Rebin(nBins, fMultiplicityESDCorrected[i]->GetName(), newBins);
338 Rebin2DY(fMultiplicityVtx[i], nBins, newBins);
339 Rebin2DY(fMultiplicityMB[i], nBins, newBins);
340 Rebin2DY(fMultiplicityINEL[i], nBins, newBins);
341 Rebin2DY(fMultiplicityNSD[i], nBins, newBins);
344 Rebin3DY(fCorrelation[i], nBins, newBins);
347 TH1::AddDirectory(oldStatus);
350 //____________________________________________________________________
351 AliMultiplicityCorrection::~AliMultiplicityCorrection()
357 Printf("AliMultiplicityCorrection::~AliMultiplicityCorrection called");
359 for (Int_t i = 0; i < kESDHists; ++i)
361 if (fMultiplicityESD[i])
362 delete fMultiplicityESD[i];
363 fMultiplicityESD[i] = 0;
365 if (fTriggeredEvents[i])
366 delete fTriggeredEvents[i];
367 fTriggeredEvents[i]= 0;
369 if (fNoVertexEvents[i])
370 delete fNoVertexEvents[i];
371 fNoVertexEvents[i]= 0;
374 for (Int_t i = 0; i < kMCHists; ++i)
376 if (fMultiplicityVtx[i])
377 delete fMultiplicityVtx[i];
378 fMultiplicityVtx[i] = 0;
380 if (fMultiplicityMB[i])
381 delete fMultiplicityMB[i];
382 fMultiplicityMB[i] = 0;
384 if (fMultiplicityINEL[i])
385 delete fMultiplicityINEL[i];
386 fMultiplicityINEL[i] = 0;
388 if (fMultiplicityNSD[i])
389 delete fMultiplicityNSD[i];
390 fMultiplicityNSD[i] = 0;
393 for (Int_t i = 0; i < kCorrHists; ++i)
396 delete fCorrelation[i];
399 if (fMultiplicityESDCorrected[i])
400 delete fMultiplicityESDCorrected[i];
401 fMultiplicityESDCorrected[i] = 0;
405 //____________________________________________________________________
406 Long64_t AliMultiplicityCorrection::Merge(const TCollection* list)
408 // Merge a list of AliMultiplicityCorrection objects with this (needed for
410 // Returns the number of merged objects (including this).
418 TIterator* iter = list->MakeIterator();
421 // collections of all histograms
422 TList collections[3*kESDHists+kMCHists*4+kCorrHists*2];
425 while ((obj = iter->Next())) {
427 AliMultiplicityCorrection* entry = dynamic_cast<AliMultiplicityCorrection*> (obj);
431 for (Int_t i = 0; i < kESDHists; ++i)
433 collections[i].Add(entry->fMultiplicityESD[i]);
434 collections[kESDHists+i].Add(entry->fTriggeredEvents[i]);
435 collections[kESDHists*2+i].Add(entry->fNoVertexEvents[i]);
438 for (Int_t i = 0; i < kMCHists; ++i)
440 collections[3*kESDHists+i].Add(entry->fMultiplicityVtx[i]);
441 collections[3*kESDHists+kMCHists+i].Add(entry->fMultiplicityMB[i]);
442 collections[3*kESDHists+kMCHists*2+i].Add(entry->fMultiplicityINEL[i]);
443 collections[3*kESDHists+kMCHists*3+i].Add(entry->fMultiplicityNSD[i]);
446 for (Int_t i = 0; i < kCorrHists; ++i)
447 collections[3*kESDHists+kMCHists*4+i].Add(entry->fCorrelation[i]);
449 for (Int_t i = 0; i < kCorrHists; ++i)
450 collections[3*kESDHists+kMCHists*4+kCorrHists+i].Add(entry->fMultiplicityESDCorrected[i]);
455 for (Int_t i = 0; i < kESDHists; ++i)
457 fMultiplicityESD[i]->Merge(&collections[i]);
458 fTriggeredEvents[i]->Merge(&collections[kESDHists+i]);
459 fNoVertexEvents[i]->Merge(&collections[2*kESDHists+i]);
462 for (Int_t i = 0; i < kMCHists; ++i)
464 fMultiplicityVtx[i]->Merge(&collections[3*kESDHists+i]);
465 fMultiplicityMB[i]->Merge(&collections[3*kESDHists+kMCHists+i]);
466 fMultiplicityINEL[i]->Merge(&collections[3*kESDHists+kMCHists*2+i]);
467 fMultiplicityNSD[i]->Merge(&collections[3*kESDHists+kMCHists*3+i]);
470 for (Int_t i = 0; i < kCorrHists; ++i)
471 fCorrelation[i]->Merge(&collections[3*kESDHists+kMCHists*4+i]);
473 for (Int_t i = 0; i < kCorrHists; ++i)
474 fMultiplicityESDCorrected[i]->Merge(&collections[3*kESDHists+kMCHists*4+kCorrHists+i]);
481 //____________________________________________________________________
482 Bool_t AliMultiplicityCorrection::LoadHistograms(const Char_t* dir)
485 // loads the histograms from a file
486 // if dir is empty a directory with the name of this object is taken (like in SaveHistogram)
492 if (!gDirectory->cd(dir))
495 // store old hists to delete them later
497 oldObjects.SetOwner(1);
498 for (Int_t i = 0; i < kESDHists; ++i)
500 if (fMultiplicityESD[i])
501 oldObjects.Add(fMultiplicityESD[i]);
502 if (fTriggeredEvents[i])
503 oldObjects.Add(fTriggeredEvents[i]);
504 if (fNoVertexEvents[i])
505 oldObjects.Add(fNoVertexEvents[i]);
508 for (Int_t i = 0; i < kMCHists; ++i)
510 if (fMultiplicityVtx[i])
511 oldObjects.Add(fMultiplicityVtx[i]);
512 if (fMultiplicityMB[i])
513 oldObjects.Add(fMultiplicityMB[i]);
514 if (fMultiplicityINEL[i])
515 oldObjects.Add(fMultiplicityINEL[i]);
516 if (fMultiplicityNSD[i])
517 oldObjects.Add(fMultiplicityNSD[i]);
520 for (Int_t i = 0; i < kCorrHists; ++i)
522 oldObjects.Add(fCorrelation[i]);
526 Bool_t success = kTRUE;
528 for (Int_t i = 0; i < kESDHists; ++i)
530 fMultiplicityESD[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityESD[i]->GetName()));
531 fTriggeredEvents[i] = dynamic_cast<TH1F*> (gDirectory->Get(fTriggeredEvents[i]->GetName()));
532 fNoVertexEvents[i] = dynamic_cast<TH1F*> (gDirectory->Get(fNoVertexEvents[i]->GetName()));
533 if (!fMultiplicityESD[i] || !fTriggeredEvents[i] || !fNoVertexEvents[i])
537 for (Int_t i = 0; i < kMCHists; ++i)
539 fMultiplicityVtx[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityVtx[i]->GetName()));
540 fMultiplicityMB[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityMB[i]->GetName()));
541 fMultiplicityINEL[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityINEL[i]->GetName()));
542 fMultiplicityNSD[i] = dynamic_cast<TH2F*> (gDirectory->Get(fMultiplicityNSD[i]->GetName()));
543 if (!fMultiplicityVtx[i] || !fMultiplicityMB[i] || !fMultiplicityINEL[i])
547 for (Int_t i = 0; i < kCorrHists; ++i)
549 fCorrelation[i] = dynamic_cast<TH3F*> (gDirectory->Get(fCorrelation[i]->GetName()));
550 if (!fCorrelation[i])
552 fMultiplicityESDCorrected[i] = dynamic_cast<TH1F*> (gDirectory->Get(fMultiplicityESDCorrected[i]->GetName()));
553 if (!fMultiplicityESDCorrected[i])
557 gDirectory->cd("..");
565 //____________________________________________________________________
566 void AliMultiplicityCorrection::SaveHistograms(const char* dir)
569 // saves the histograms
575 gDirectory->mkdir(dir);
578 for (Int_t i = 0; i < kESDHists; ++i)
580 if (fMultiplicityESD[i])
582 fMultiplicityESD[i]->Write();
583 fMultiplicityESD[i]->ProjectionY(Form("%s_px", fMultiplicityESD[i]->GetName()), 1, fMultiplicityESD[i]->GetNbinsX())->Write();
585 if (fTriggeredEvents[i])
586 fTriggeredEvents[i]->Write();
587 if (fNoVertexEvents[i])
588 fNoVertexEvents[i]->Write();
591 for (Int_t i = 0; i < kMCHists; ++i)
593 if (fMultiplicityVtx[i])
595 fMultiplicityVtx[i]->Write();
596 fMultiplicityVtx[i]->ProjectionY(Form("%s_px", fMultiplicityVtx[i]->GetName()), 1, fMultiplicityVtx[i]->GetNbinsX())->Write();
598 if (fMultiplicityMB[i])
600 fMultiplicityMB[i]->Write();
601 fMultiplicityMB[i]->ProjectionY(Form("%s_px", fMultiplicityMB[i]->GetName()), 1, fMultiplicityMB[i]->GetNbinsX())->Write();
603 if (fMultiplicityINEL[i])
605 fMultiplicityINEL[i]->Write();
606 fMultiplicityINEL[i]->ProjectionY(Form("%s_px", fMultiplicityINEL[i]->GetName()), 1, fMultiplicityINEL[i]->GetNbinsX())->Write();
608 if (fMultiplicityNSD[i])
610 fMultiplicityNSD[i]->Write();
611 fMultiplicityNSD[i]->ProjectionY(Form("%s_px", fMultiplicityNSD[i]->GetName()), 1, fMultiplicityNSD[i]->GetNbinsX())->Write();
615 for (Int_t i = 0; i < kCorrHists; ++i)
618 fCorrelation[i]->Write();
619 if (fMultiplicityESDCorrected[i])
620 fMultiplicityESDCorrected[i]->Write();
623 gDirectory->cd("..");
626 //____________________________________________________________________
627 void AliMultiplicityCorrection::FillGenerated(Float_t vtx, Bool_t triggered, Bool_t vertex, AliPWG0Helper::MCProcessType processType, Int_t generated05, Int_t generated10, Int_t generated14, Int_t generatedAll)
630 // Fills an event from MC
635 fMultiplicityMB[0]->Fill(vtx, generated05);
636 fMultiplicityMB[1]->Fill(vtx, generated10);
637 fMultiplicityMB[2]->Fill(vtx, generated14);
638 fMultiplicityMB[3]->Fill(vtx, generatedAll);
642 fMultiplicityVtx[0]->Fill(vtx, generated05);
643 fMultiplicityVtx[1]->Fill(vtx, generated10);
644 fMultiplicityVtx[2]->Fill(vtx, generated14);
645 fMultiplicityVtx[3]->Fill(vtx, generatedAll);
649 fMultiplicityINEL[0]->Fill(vtx, generated05);
650 fMultiplicityINEL[1]->Fill(vtx, generated10);
651 fMultiplicityINEL[2]->Fill(vtx, generated14);
652 fMultiplicityINEL[3]->Fill(vtx, generatedAll);
654 if (processType != AliPWG0Helper::kSD)
656 fMultiplicityNSD[0]->Fill(vtx, generated05);
657 fMultiplicityNSD[1]->Fill(vtx, generated10);
658 fMultiplicityNSD[2]->Fill(vtx, generated14);
659 fMultiplicityNSD[3]->Fill(vtx, generatedAll);
663 //____________________________________________________________________
664 void AliMultiplicityCorrection::FillMeasured(Float_t vtx, Int_t measured05, Int_t measured10, Int_t measured14)
667 // Fills an event from ESD
670 fMultiplicityESD[0]->Fill(vtx, measured05);
671 fMultiplicityESD[1]->Fill(vtx, measured10);
672 fMultiplicityESD[2]->Fill(vtx, measured14);
675 //____________________________________________________________________
676 void AliMultiplicityCorrection::FillTriggeredEvent(Int_t measured05, Int_t measured10, Int_t measured14)
679 // fills raw distribution of triggered events
682 fTriggeredEvents[0]->Fill(measured05);
683 fTriggeredEvents[1]->Fill(measured10);
684 fTriggeredEvents[2]->Fill(measured14);
687 //____________________________________________________________________
688 void AliMultiplicityCorrection::FillNoVertexEvent(Float_t vtx, Bool_t vertexReconstructed, Int_t generated05, Int_t generated10, Int_t generated14, Int_t measured05, Int_t measured10, Int_t measured14)
691 // fills raw distribution of triggered events
694 if (vtx > fgVtxRangeBegin[0] && vtx < fgVtxRangeEnd[0] && (!vertexReconstructed || measured05 == 0))
695 fNoVertexEvents[0]->Fill(generated05);
697 if (vtx > fgVtxRangeBegin[1] && vtx < fgVtxRangeEnd[1] && (!vertexReconstructed || measured10 == 0))
698 fNoVertexEvents[1]->Fill(generated10);
700 if (vtx > fgVtxRangeBegin[2] && vtx < fgVtxRangeEnd[2] && (!vertexReconstructed || measured14 == 0))
701 fNoVertexEvents[2]->Fill(generated14);
704 //____________________________________________________________________
705 void AliMultiplicityCorrection::FillCorrection(Float_t vtx, Int_t generated05, Int_t generated10, Int_t generated14, Int_t generatedAll, Int_t measured05, Int_t measured10, Int_t measured14)
708 // Fills an event into the correlation map with the information from MC and ESD
711 fCorrelation[0]->Fill(vtx, generated05, measured05);
712 fCorrelation[1]->Fill(vtx, generated10, measured10);
713 fCorrelation[2]->Fill(vtx, generated14, measured14);
715 fCorrelation[3]->Fill(vtx, generatedAll, measured05);
716 fCorrelation[4]->Fill(vtx, generatedAll, measured10);
717 fCorrelation[5]->Fill(vtx, generatedAll, measured14);
720 //____________________________________________________________________
721 void AliMultiplicityCorrection::SetupCurrentHists(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType)
724 // fills fCurrentESD, fCurrentCorrelation
725 // resets fMultiplicityESDCorrected
728 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
730 fMultiplicityESDCorrected[correlationID]->Reset();
731 fMultiplicityESDCorrected[correlationID]->Sumw2();
733 // project without under/overflow bins
735 Int_t end = fMultiplicityESD[inputRange]->GetXaxis()->GetNbins();
736 if (fVtxEnd > fVtxBegin)
741 fCurrentESD = fMultiplicityESD[inputRange]->ProjectionY("fCurrentESD", begin, end);
742 fCurrentESD->Sumw2();
744 // empty under/overflow bins in x, otherwise Project3D takes them into account
745 TH3* hist = fCorrelation[correlationID];
746 for (Int_t y=0; y<=hist->GetYaxis()->GetNbins()+1; ++y)
748 for (Int_t z=0; z<=hist->GetZaxis()->GetNbins()+1; ++z)
750 hist->SetBinContent(0, y, z, 0);
751 hist->SetBinContent(hist->GetXaxis()->GetNbins()+1, y, z, 0);
755 if (fVtxEnd > fVtxBegin)
756 hist->GetXaxis()->SetRange(fVtxBegin, fVtxEnd);
758 fCurrentCorrelation = (TH2*) hist->Project3D("zy");
759 fCurrentCorrelation->Sumw2();
761 Printf("AliMultiplicityCorrection::SetupCurrentHists: Statistics information: %.f entries in correlation map; %.f entries in measured spectrum", fCurrentCorrelation->Integral(), fCurrentESD->Integral());
763 #if 0 // does not help
764 // null bins with one entry
765 Int_t nNulledBins = 0;
766 for (Int_t x=1; x<=fCurrentCorrelation->GetXaxis()->GetNbins(); ++x)
767 for (Int_t y=1; y<=fCurrentCorrelation->GetYaxis()->GetNbins(); ++y)
769 if (fCurrentCorrelation->GetBinContent(x, y) == 1)
771 fCurrentCorrelation->SetBinContent(x, y, 0);
772 fCurrentCorrelation->SetBinError(x, y, 0);
777 Printf("Nulled %d bins", nNulledBins);
780 fCurrentEfficiency = GetEfficiency(inputRange, eventType);
781 //fCurrentEfficiency->Rebin(2);
782 //fCurrentEfficiency->Scale(0.5);
785 //____________________________________________________________________
786 TH1* AliMultiplicityCorrection::GetEfficiency(Int_t inputRange, EventType eventType)
789 // calculates efficiency for given event type
793 name1.Form("divisor%d", inputRange);
796 name2.Form("CurrentEfficiency%d", inputRange);
802 case kMB: divisor = fMultiplicityMB[inputRange]->ProjectionY(name1, 1, fMultiplicityMB[inputRange]->GetNbinsX(), "e"); break;
803 case kINEL: divisor = fMultiplicityINEL[inputRange]->ProjectionY(name1, 1, fMultiplicityINEL[inputRange]->GetNbinsX(), "e"); break;
804 case kNSD: divisor = fMultiplicityNSD[inputRange]->ProjectionY(name1, 1, fMultiplicityNSD[inputRange]->GetNbinsX(), "e"); break;
806 TH1* eff = fMultiplicityVtx[inputRange]->ProjectionY(name2, 1, fMultiplicityVtx[inputRange]->GetNbinsX(), "e");
808 if (eventType == kTrVtx)
810 for (Int_t i=0; i<= eff->GetNbinsX()+1; i++)
811 eff->SetBinContent(i, 1);
814 eff->Divide(eff, divisor, 1, 1, "B");
819 //____________________________________________________________________
820 TH1* AliMultiplicityCorrection::GetTriggerEfficiency(Int_t inputRange, EventType eventType)
823 // calculates efficiency for given event type
827 name1.Form("divisor%d", inputRange);
830 name2.Form("CurrentEfficiency%d", inputRange);
835 case kTrVtx : AliFatal("Not supported!"); break;
836 case kMB: divisor = fMultiplicityMB[inputRange]->ProjectionY (name1, 1, fMultiplicityMB[inputRange]->GetNbinsX(), "e"); break;
837 case kINEL: divisor = fMultiplicityINEL[inputRange]->ProjectionY(name1, 1, fMultiplicityINEL[inputRange]->GetNbinsX(), "e"); break;
838 case kNSD: divisor = fMultiplicityNSD[inputRange]->ProjectionY (name1, 1, fMultiplicityNSD[inputRange]->GetNbinsX(), "e"); break;
840 TH1* eff = fMultiplicityMB[inputRange]->ProjectionY(name2, 1, fMultiplicityMB[inputRange]->GetNbinsX(), "e");
842 eff->Divide(eff, divisor, 1, 1, "B");
846 //____________________________________________________________________
847 Int_t AliMultiplicityCorrection::ApplyMinuitFit(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Int_t zeroBinEvents, Bool_t check, TH1* initialConditions, Bool_t errorAsBias)
850 // correct spectrum using minuit chi2 method
852 // for description of parameters, see AliUnfolding::Unfold
855 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
857 //AliUnfolding::SetCreateOverflowBin(5);
858 AliUnfolding::SetUnfoldingMethod(AliUnfolding::kChi2Minimization);
859 AliUnfolding::SetMinimumInitialValue(kTRUE, 0.1);
861 // use here only vtx efficiency (to MB sample) which is always needed if we use the 0 bin
862 SetupCurrentHists(inputRange, fullPhaseSpace, (eventType == kTrVtx) ? kTrVtx : kMB);
864 // TODO set errors on measured with 0.5 * TMath::ChisquareQuantile(0.1, 20000)
865 // see PDG: Statistics / Poission or binomial data / Eq. 32.49a/b in 2004 edition
867 Calculate0Bin(inputRange, eventType, zeroBinEvents);
869 Int_t resultCode = -1;
870 if (errorAsBias == kFALSE)
872 resultCode = AliUnfolding::Unfold(fCurrentCorrelation, fCurrentEfficiency, fCurrentESD, initialConditions, fMultiplicityESDCorrected[correlationID], check);
876 resultCode = AliUnfolding::UnfoldGetBias(fCurrentCorrelation, fCurrentEfficiency, fCurrentESD, initialConditions, fMultiplicityESDCorrected[correlationID]);
879 // HACK store new vertex reco efficiency for bin 0, changing number of events with trigger and vertex in MC map
880 if (zeroBinEvents > 0)
882 Printf("WARNING: Stored vertex reco efficiency from unfolding for bin 0.");
883 fMultiplicityVtx[inputRange]->SetBinContent(1, 1, fMultiplicityMB[inputRange]->GetBinContent(1, 1) * fCurrentEfficiency->GetBinContent(1));
886 // correct for the trigger bias if requested
889 Printf("Applying trigger efficiency");
890 TH1* eff = GetTriggerEfficiency(inputRange, eventType);
891 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); i++)
893 fMultiplicityESDCorrected[correlationID]->SetBinContent(i, fMultiplicityESDCorrected[correlationID]->GetBinContent(i) / eff->GetBinContent(i));
894 fMultiplicityESDCorrected[correlationID]->SetBinError(i, fMultiplicityESDCorrected[correlationID]->GetBinError(i) / eff->GetBinContent(i));
901 //____________________________________________________________________
902 void AliMultiplicityCorrection::Calculate0Bin(Int_t inputRange, EventType eventType, Int_t zeroBinEvents)
906 if (eventType == kTrVtx)
909 Double_t fractionEventsInVertexRange = fMultiplicityESD[inputRange]->Integral(1, fMultiplicityESD[inputRange]->GetXaxis()->GetNbins()) / fMultiplicityESD[inputRange]->Integral(0, fMultiplicityESD[inputRange]->GetXaxis()->GetNbins() + 1);
911 // difference of fraction that is inside the considered range between triggered events and events with vertex
912 // Extension to NSD not needed, INEL and NSD vertex distributions are nature-given and unbiased!
913 Double_t differenceVtxDist = (fMultiplicityINEL[inputRange]->Integral(1, fMultiplicityINEL[inputRange]->GetXaxis()->GetNbins()) / fMultiplicityINEL[inputRange]->Integral(0, fMultiplicityINEL[inputRange]->GetXaxis()->GetNbins() + 1)) / (fMultiplicityVtx[inputRange]->Integral(1, fMultiplicityVtx[inputRange]->GetXaxis()->GetNbins()) / fMultiplicityVtx[inputRange]->Integral(0, fMultiplicityVtx[inputRange]->GetXaxis()->GetNbins() + 1));
915 Printf("Enabling 0 bin estimate for triggered events without vertex.");
916 Printf(" Events in 0 bin: %d", zeroBinEvents);
917 Printf(" Fraction in range: %.1f%%", fractionEventsInVertexRange * 100);
918 Printf(" Difference Vtx Dist: %f", differenceVtxDist);
920 AliUnfolding::SetNotFoundEvents(zeroBinEvents * fractionEventsInVertexRange * differenceVtxDist);
923 //____________________________________________________________________
924 void AliMultiplicityCorrection::FixTriggerEfficiencies(Int_t start)
927 // sets trigger and vertex efficiencies to 1 for large multiplicities where no event was simulated
930 for (Int_t etaRange = 0; etaRange < kMCHists; etaRange++)
932 for (Int_t i = 1; i <= fMultiplicityINEL[etaRange]->GetNbinsY(); i++)
934 if (fMultiplicityINEL[etaRange]->GetYaxis()->GetBinCenter(i) < start)
937 if (fMultiplicityINEL[etaRange]->GetBinContent(1, i) > 0)
940 fMultiplicityINEL[etaRange]->SetBinContent(1, i, 1);
941 fMultiplicityNSD[etaRange]->SetBinContent(1, i, 1);
942 fMultiplicityMB[etaRange]->SetBinContent(1, i, 1);
943 fMultiplicityVtx[etaRange]->SetBinContent(1, i, 1);
948 //____________________________________________________________________
949 Float_t AliMultiplicityCorrection::GetFraction0Generated(Int_t inputRange)
952 // returns the fraction of events that have 0 generated particles in the given range among all events without vertex OR 0 tracklets
955 TH1* multMB = GetNoVertexEvents(inputRange);
956 return multMB->GetBinContent(1) / multMB->Integral();
959 //____________________________________________________________________
960 Int_t AliMultiplicityCorrection::ApplyNBDFit(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType)
963 // correct spectrum using minuit chi2 method with a NBD function
965 // for description of parameters, see AliUnfolding::Unfold
968 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
970 AliUnfolding::SetUnfoldingMethod(AliUnfolding::kFunction);
971 SetupCurrentHists(inputRange, fullPhaseSpace, eventType);
973 TF1* func = new TF1("nbd", "[0] * TMath::Gamma([2]+x) / TMath::Gamma([2]) / TMath::Gamma(x+1) * pow([1] / ([1]+[2]), x) * pow(1.0 + [1]/[2], -[2])");
974 func->SetParNames("scaling", "averagen", "k");
975 func->SetParLimits(0, 0, 1000);
976 func->SetParLimits(1, 1, 50);
977 func->SetParLimits(2, 1, 10);
978 func->SetParameters(1, 10, 2);
979 AliUnfolding::SetFunction(func);
981 return AliUnfolding::Unfold(fCurrentCorrelation, fCurrentEfficiency, fCurrentESD, 0, fMultiplicityESDCorrected[correlationID]);
984 //____________________________________________________________________
985 void AliMultiplicityCorrection::DrawHistograms()
988 // draws the histograms of this class
993 TCanvas* canvas1 = new TCanvas("fMultiplicityESD", "fMultiplicityESD", 900, 600);
994 canvas1->Divide(3, 2);
995 for (Int_t i = 0; i < kESDHists; ++i)
998 fMultiplicityESD[i]->DrawCopy("COLZ");
999 printf("%d --> %f\n", i, (Float_t) fMultiplicityESD[i]->ProjectionY()->GetMean());
1004 TCanvas* canvas2 = new TCanvas("fMultiplicityMC", "fMultiplicityMC", 900, 600);
1005 canvas2->Divide(3, 2);
1006 for (Int_t i = 0; i < kMCHists; ++i)
1009 fMultiplicityVtx[i]->DrawCopy("COLZ");
1010 printf("%d --> %f\n", i, fMultiplicityVtx[i]->ProjectionY()->GetMean());
1013 TCanvas* canvas3 = new TCanvas("fCorrelation", "fCorrelation", 900, 900);
1014 canvas3->Divide(3, 3);
1015 for (Int_t i = 0; i < kCorrHists; ++i)
1018 TH3* hist = static_cast<TH3*> (fCorrelation[i]->Clone());
1019 for (Int_t y=1; y<=hist->GetYaxis()->GetNbins(); ++y)
1021 for (Int_t z=1; z<=hist->GetZaxis()->GetNbins(); ++z)
1023 hist->SetBinContent(0, y, z, 0);
1024 hist->SetBinContent(hist->GetXaxis()->GetNbins()+1, y, z, 0);
1027 TH1* proj = hist->Project3D("zy");
1028 proj->DrawCopy("COLZ");
1032 //____________________________________________________________________
1033 void AliMultiplicityCorrection::DrawComparison(const char* name, Int_t inputRange, Bool_t fullPhaseSpace, Bool_t /*normalizeESD*/, TH1* mcHist, Bool_t simple, EventType eventType)
1035 // draw comparison plots
1037 Int_t esdCorrId = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1040 tmpStr.Form("%s_DrawComparison_%d", name, esdCorrId);
1042 if (fMultiplicityESDCorrected[esdCorrId]->Integral() == 0)
1044 printf("ERROR. Unfolded histogram is empty\n");
1049 Int_t end = fMultiplicityESD[inputRange]->GetXaxis()->GetNbins();
1050 if (fVtxEnd > fVtxBegin)
1055 fCurrentESD = fMultiplicityESD[esdCorrId]->ProjectionY("fCurrentESD", begin, end);
1056 fCurrentESD->Sumw2();
1060 for (Int_t i=5; i<=mcHist->GetNbinsX(); ++i)
1062 if (mcHist->GetBinContent(i) > 0)
1063 mcMax = (Int_t) mcHist->GetXaxis()->GetBinCenter(i) + 2;
1067 for (Int_t i=5; i<=fMultiplicityESDCorrected[esdCorrId]->GetNbinsX(); ++i)
1068 if (fMultiplicityESDCorrected[esdCorrId]->GetBinContent(i) > 1)
1069 mcMax = (Int_t) fMultiplicityESDCorrected[esdCorrId]->GetXaxis()->GetBinCenter(i) + 2;
1071 Printf("AliMultiplicityCorrection::DrawComparison: MC bin limit is %d", mcMax);
1072 // calculate residual
1074 TH1* convolutedProj = (TH1*) GetConvoluted(esdCorrId, eventType)->Clone("convolutedProj");
1075 TH1* residual = GetResiduals(esdCorrId, eventType, tmp);
1077 TH1* residualHist = new TH1F("residualHist", "residualHist", 51, -5, 5);
1080 for (Int_t i=1; i<=TMath::Min(residual->GetNbinsX(), 75); ++i)
1082 Float_t value = residual->GetBinContent(i);
1083 // TODO has to get a parameter (used in Chi2Function, GetResiduals, and here)
1085 chi2 += value * value;
1086 Printf("%d --> %f (%f)", i, value * value, chi2);
1087 residualHist->Fill(value);
1088 convolutedProj->SetBinError(i, 0);
1090 fLastChi2Residuals = chi2;
1092 //new TCanvas; residualHist->DrawCopy();
1094 printf("Difference (Residuals) is %f\n", fLastChi2Residuals);
1096 TCanvas* canvas1 = 0;
1099 canvas1 = new TCanvas(tmpStr, tmpStr, 1200, 600);
1100 canvas1->Divide(2, 1);
1104 canvas1 = new TCanvas(tmpStr, tmpStr, 1200, 1200);
1105 canvas1->Divide(2, 3);
1109 canvas1->cd(1)->SetGridx();
1110 canvas1->cd(1)->SetGridy();
1111 canvas1->cd(1)->SetTopMargin(0.05);
1112 canvas1->cd(1)->SetRightMargin(0.05);
1113 canvas1->cd(1)->SetLeftMargin(0.12);
1114 canvas1->cd(1)->SetBottomMargin(0.12);
1115 TH1* proj = (TH1*) mcHist->Clone("proj");
1116 if (proj->GetEntries() > 0)
1117 AliPWG0Helper::NormalizeToBinWidth(proj);
1119 proj->GetXaxis()->SetRangeUser(0, mcMax);
1120 proj->GetYaxis()->SetTitleOffset(1.4);
1121 proj->SetTitle(Form(";True multiplicity in |#eta| < %.1f;Entries", (inputRange+1)*0.5));
1122 proj->SetStats(kFALSE);
1124 fMultiplicityESDCorrected[esdCorrId]->GetXaxis()->SetRangeUser(0, mcMax);
1125 fMultiplicityESDCorrected[esdCorrId]->GetYaxis()->SetRangeUser(0.1, fMultiplicityESDCorrected[esdCorrId]->GetMaximum() * 1.5);
1126 fMultiplicityESDCorrected[esdCorrId]->GetYaxis()->SetTitleOffset(1.4);
1127 fMultiplicityESDCorrected[esdCorrId]->SetTitle(Form(";True multiplicity in |#eta| < %.1f;Entries", (inputRange+1)*0.5));
1128 fMultiplicityESDCorrected[esdCorrId]->SetStats(kFALSE);
1130 fMultiplicityESDCorrected[esdCorrId]->SetLineColor(2);
1131 fMultiplicityESDCorrected[esdCorrId]->SetMarkerColor(2);
1133 TH1* esdCorrected = (TH1*) fMultiplicityESDCorrected[esdCorrId]->Clone("esdCorrected");
1134 AliPWG0Helper::NormalizeToBinWidth(esdCorrected);
1136 if (proj->GetEntries() > 0) {
1137 proj->DrawCopy("HIST");
1138 esdCorrected->DrawCopy("SAME HIST E");
1141 esdCorrected->DrawCopy("HIST E");
1145 TLegend* legend = new TLegend(0.3, 0.8, 0.93, 0.93);
1146 legend->AddEntry(proj, "True distribution");
1147 legend->AddEntry(fMultiplicityESDCorrected[esdCorrId], "Unfolded distribution");
1148 legend->SetFillColor(0);
1149 legend->SetTextSize(0.04);
1153 canvas1->cd(2)->SetGridx();
1154 canvas1->cd(2)->SetGridy();
1155 canvas1->cd(2)->SetTopMargin(0.05);
1156 canvas1->cd(2)->SetRightMargin(0.05);
1157 canvas1->cd(2)->SetLeftMargin(0.12);
1158 canvas1->cd(2)->SetBottomMargin(0.12);
1161 fCurrentESD->GetXaxis()->SetRangeUser(0, mcMax);
1162 fCurrentESD->SetTitle(Form(";Measured multiplicity in |#eta| < %.1f;Entries", (inputRange+1)*0.5));
1163 fCurrentESD->SetStats(kFALSE);
1164 fCurrentESD->GetYaxis()->SetTitleOffset(1.4);
1165 fCurrentESD->DrawCopy("HIST E");
1167 convolutedProj->SetLineColor(2);
1168 convolutedProj->SetMarkerColor(2);
1169 convolutedProj->SetMarkerStyle(5);
1170 convolutedProj->DrawCopy("HIST SAME P");
1172 legend = new TLegend(0.3, 0.8, 0.93, 0.93);
1173 legend->AddEntry(fCurrentESD, "Measured distribution");
1174 legend->AddEntry(convolutedProj, "R #otimes unfolded distribution", "P");
1175 legend->SetFillColor(0);
1176 legend->SetTextSize(0.04);
1182 residual->GetYaxis()->SetRangeUser(-5, 5);
1183 residual->GetXaxis()->SetRangeUser(0, mcMax);
1184 residual->SetStats(kFALSE);
1185 residual->DrawCopy();
1188 TH1* ratio = (TH1*) fMultiplicityESDCorrected[esdCorrId]->Clone("ratio");
1189 ratio->Divide(mcHist);
1190 ratio->SetTitle("Ratio;true multiplicity;Unfolded / MC");
1191 ratio->GetYaxis()->SetRangeUser(0.5, 1.5);
1192 ratio->GetXaxis()->SetRangeUser(0, mcMax);
1193 ratio->SetStats(kFALSE);
1194 ratio->Draw("HIST");
1196 // plot (MC - Unfolded) / error (MC)
1199 TH1* diffMCUnfolded2 = static_cast<TH1*> (proj->Clone("diffMCUnfolded2"));
1200 diffMCUnfolded2->Add(esdCorrected, -1);
1202 Int_t ndfQual[kQualityRegions];
1203 for (Int_t region=0; region<kQualityRegions; ++region)
1205 fQuality[region] = 0;
1206 ndfQual[region] = 0;
1209 Double_t newChi2 = 0;
1210 Double_t newChi2Limit150 = 0;
1212 for (Int_t i=1; i<=diffMCUnfolded2->GetNbinsX(); ++i)
1215 if (proj->GetBinError(i) > 0)
1217 value = diffMCUnfolded2->GetBinContent(i) / proj->GetBinError(i);
1218 newChi2 += value * value;
1219 if (i > 1 && i <= mcMax)
1220 newChi2Limit150 += value * value;
1223 for (Int_t region=0; region<kQualityRegions; ++region)
1224 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
1226 fQuality[region] += TMath::Abs(value);
1231 diffMCUnfolded2->SetBinContent(i, value);
1234 // normalize region to the number of entries
1235 for (Int_t region=0; region<kQualityRegions; ++region)
1237 if (ndfQual[region] > 0)
1238 fQuality[region] /= ndfQual[region];
1239 Printf("Quality parameter %d (%d <= mult <= %d) is %f with %d df", region, fgQualityRegionsB[region], fgQualityRegionsE[region], fQuality[region], ndfQual[region]);
1244 fLastChi2MC = newChi2Limit150 / (mcMax - 1);
1245 Printf("Chi2 (2..%d) from (MC - Unfolded) / e(MC) is: %.2f ndf is %d --> chi2 / ndf = %.2f", mcMax, newChi2Limit150, mcMax - 1, fLastChi2MC);
1250 Printf("Chi2 (full range) from (MC - Unfolded) / e(MC) is: %.2f ndf is %d --> chi2 / ndf = %.2f", newChi2, ndf, ((ndf > 0) ? newChi2 / ndf : -1));
1252 diffMCUnfolded2->SetTitle("#chi^{2};true multiplicity;(MC - Unfolded) / e(MC)");
1253 diffMCUnfolded2->GetYaxis()->SetRangeUser(-5, 5);
1254 diffMCUnfolded2->GetXaxis()->SetRangeUser(0, mcMax);
1255 diffMCUnfolded2->DrawCopy("HIST");
1258 // draw penalty factor
1260 TH1* penalty = AliUnfolding::GetPenaltyPlot(fMultiplicityESDCorrected[esdCorrId]);
1261 penalty->SetStats(0);
1262 penalty->GetXaxis()->SetRangeUser(0, mcMax);
1263 penalty->DrawCopy("HIST");
1267 //____________________________________________________________________
1268 void AliMultiplicityCorrection::FFT(Int_t dir, Int_t m, Double_t *x, Double_t *y) const
1270 /*-------------------------------------------------------------------------
1271 This computes an in-place complex-to-complex FFT
1272 x and y are the real and imaginary arrays of 2^m points.
1273 dir = 1 gives forward transform
1274 dir = -1 gives reverse transform
1279 1 \ - j k 2 pi n / N
1280 X(n) = --- > x(k) e = forward transform
1289 X(n) = > x(k) e = forward transform
1295 Long_t nn, i, i1, j, k, i2, l, l1, l2;
1296 Double_t c1, c2, tx, ty, t1, t2, u1, u2, z;
1298 /* Calculate the number of points */
1300 for (i = 0; i < m; i++)
1303 /* Do the bit reversal */
1306 for (i= 0; i < nn - 1; i++) {
1323 /* Compute the FFT */
1327 for (l = 0; l < m; l++) {
1332 for (j = 0;j < l1; j++) {
1333 for (i = j; i < nn; i += l2) {
1335 t1 = u1 * x[i1] - u2 * y[i1];
1336 t2 = u1 * y[i1] + u2 * x[i1];
1342 z = u1 * c1 - u2 * c2;
1343 u2 = u1 * c2 + u2 * c1;
1346 c2 = TMath::Sqrt((1.0 - c1) / 2.0);
1349 c1 = TMath::Sqrt((1.0 + c1) / 2.0);
1352 /* Scaling for forward transform */
1354 for (i=0;i<nn;i++) {
1355 x[i] /= (Double_t)nn;
1356 y[i] /= (Double_t)nn;
1361 //____________________________________________________________________
1362 void AliMultiplicityCorrection::GetComparisonResults(Float_t* const mc, Int_t* const mcLimit, Float_t* const residuals, Float_t* const ratioAverage) const
1364 // Returns the chi2 between the MC and the unfolded ESD as well as between the ESD and the folded unfolded ESD
1365 // These values are computed during DrawComparison, thus this function picks up the
1371 *mcLimit = fLastChi2MCLimit;
1373 *residuals = fLastChi2Residuals;
1375 *ratioAverage = fRatioAverage;
1378 //____________________________________________________________________
1379 TH2F* AliMultiplicityCorrection::GetMultiplicityMC(Int_t i, EventType eventType) const
1382 // returns the corresponding MC spectrum
1387 case kTrVtx : return fMultiplicityVtx[i]; break;
1388 case kMB : return fMultiplicityMB[i]; break;
1389 case kINEL : return fMultiplicityINEL[i]; break;
1390 case kNSD : return fMultiplicityNSD[i]; break;
1396 //____________________________________________________________________
1397 void AliMultiplicityCorrection::SetMultiplicityMC(Int_t i, EventType eventType, TH2F* const hist)
1400 // returns the corresponding MC spectrum
1405 case kTrVtx : fMultiplicityVtx[i] = hist; break;
1406 case kMB : fMultiplicityMB[i] = hist; break;
1407 case kINEL : fMultiplicityINEL[i] = hist; break;
1408 case kNSD : fMultiplicityNSD[i] = hist; break;
1412 //____________________________________________________________________
1413 TH1* AliMultiplicityCorrection::CalculateStdDev(TH1** results, Int_t max)
1415 // calculate standard deviation of (results[0] - results[k]) k=1...max-1
1416 // per bin one gets: sigma(r[0] - r[n]) / r[0]
1418 TH1* standardDeviation = (TH1*) results[0]->Clone("standardDeviation");
1419 standardDeviation->Reset();
1421 for (Int_t x=1; x<=results[0]->GetNbinsX(); x++)
1423 if (results[0]->GetBinContent(x) > 0)
1425 Double_t average = 0;
1426 for (Int_t n=1; n<max; ++n)
1427 average += results[n]->GetBinContent(x) - results[0]->GetBinContent(x);
1430 Double_t variance = 0;
1431 for (Int_t n=1; n<max; ++n)
1433 Double_t value = results[n]->GetBinContent(x) - results[0]->GetBinContent(x) - average;
1434 variance += value * value;
1438 Double_t standardDev = TMath::Sqrt(variance);
1439 standardDeviation->SetBinContent(x, standardDev / results[0]->GetBinContent(x));
1440 //Printf("sigma_%d is %f value %f --> error %f", x, standardDev, results[0]->GetBinContent(x), standardDev / results[0]->GetBinContent(x));
1444 return standardDeviation;
1447 //____________________________________________________________________
1448 TH1* AliMultiplicityCorrection::StatisticalUncertainty(AliUnfolding::MethodType methodType, Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Int_t zeroBinEvents, Bool_t randomizeMeasured, Bool_t randomizeResponse, const TH1* compareTo)
1451 // evaluates the uncertainty that arises from the non-infinite statistics in the response matrix
1452 // the function unfolds the spectrum using the default response matrix and several modified ones
1453 // the modified ones are created by randomizing each cell using poisson statistics with the mean = bin value
1454 // these unfolded results are compared to the first result gained with the default response OR to the histogram given
1455 // in <compareTo> (optional)
1457 // returns the error assigned to the measurement
1460 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1462 // initialize seed with current time
1463 gRandom->SetSeed(0);
1465 if (methodType == AliUnfolding::kChi2Minimization)
1467 Calculate0Bin(inputRange, eventType, zeroBinEvents);
1468 AliUnfolding::SetMinimumInitialValue(kTRUE, 0.1);
1471 AliUnfolding::SetUnfoldingMethod(methodType);
1473 const Int_t kErrorIterations = 20;
1476 TH1* firstResult = 0;
1478 TH1** results = new TH1*[kErrorIterations];
1480 for (Int_t n=0; n<kErrorIterations; ++n)
1482 Printf("Iteration %d of %d...", n, kErrorIterations);
1484 SetupCurrentHists(inputRange, fullPhaseSpace, eventType);
1486 TH1* measured = (TH1*) fCurrentESD->Clone("measured");
1490 if (randomizeResponse)
1492 // randomize response matrix
1493 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
1494 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
1495 fCurrentCorrelation->SetBinContent(i, j, gRandom->Poisson(fCurrentCorrelation->GetBinContent(i, j)));
1498 if (randomizeMeasured)
1500 // randomize measured spectrum
1501 for (Int_t x=1; x<=measured->GetNbinsX(); x++) // mult. axis
1503 Int_t randomValue = gRandom->Poisson(fCurrentESD->GetBinContent(x));
1504 measured->SetBinContent(x, randomValue);
1505 measured->SetBinError(x, TMath::Sqrt(randomValue));
1510 // only for bayesian method we have to do it before the call to Unfold...
1511 if (methodType == AliUnfolding::kBayesian)
1513 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
1515 // with this it is normalized to 1
1516 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
1518 // with this normalized to the given efficiency
1519 if (fCurrentEfficiency->GetBinContent(i) > 0)
1520 sum /= fCurrentEfficiency->GetBinContent(i);
1524 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
1528 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
1529 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
1533 fCurrentCorrelation->SetBinContent(i, j, 0);
1534 fCurrentCorrelation->SetBinError(i, j, 0);
1541 if (n == 0 && compareTo)
1543 // in this case we just store the histogram we want to compare to
1544 result = (TH1*) compareTo->Clone("compareTo");
1549 result = (TH1*) fMultiplicityESDCorrected[correlationID]->Clone(Form("result_%d", n));
1551 Int_t returnCode = AliUnfolding::Unfold(fCurrentCorrelation, fCurrentEfficiency, measured, 0, result);
1553 if (returnCode != 0)
1561 result->Scale(1.0 / result->Integral());
1565 firstResult = (TH1*) result->Clone("firstResult");
1567 maxError = (TH1*) result->Clone("maxError");
1573 TH1* ratio = (TH1*) firstResult->Clone("ratio");
1574 ratio->Divide(result);
1576 // find max. deviation
1577 for (Int_t x=1; x<=ratio->GetNbinsX(); x++)
1578 maxError->SetBinContent(x, TMath::Max(maxError->GetBinContent(x), TMath::Abs(1 - ratio->GetBinContent(x))));
1583 results[n] = result;
1586 // find covariance matrix
1587 // results[n] is X_x
1588 // cov. matrix is M_xy = E ( (X_x - E(X_x)) * (X_y - E(X_y))), with E() = expectation value
1590 Int_t nBins = results[0]->GetNbinsX();
1591 Float_t lowEdge = results[0]->GetXaxis()->GetBinLowEdge(1);
1592 Float_t upEdge = results[0]->GetXaxis()->GetBinUpEdge(nBins);
1594 // find average, E(X)
1595 TProfile* average = new TProfile("average", "average", nBins, lowEdge, upEdge);
1596 for (Int_t n=1; n<kErrorIterations; ++n)
1597 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
1598 average->Fill(results[n]->GetXaxis()->GetBinCenter(x), results[n]->GetBinContent(x));
1599 //new TCanvas; average->DrawClone();
1602 TProfile2D* covMatrix = new TProfile2D("covMatrix", "covMatrix", nBins, lowEdge, upEdge, nBins, lowEdge, upEdge);
1604 for (Int_t n=1; n<kErrorIterations; ++n)
1605 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
1606 for (Int_t y=1; y<=results[n]->GetNbinsX(); y++)
1608 // (X_x - E(X_x)) * (X_y - E(X_y)
1609 Float_t cov = (results[n]->GetBinContent(x) - average->GetBinContent(x)) * (results[n]->GetBinContent(y) - average->GetBinContent(y));
1610 covMatrix->Fill(results[n]->GetXaxis()->GetBinCenter(x), results[n]->GetXaxis()->GetBinCenter(y), cov);
1612 TCanvas* c = new TCanvas; c->cd(); covMatrix->DrawCopy("COLZ");
1614 // // fill 2D histogram that contains deviation from first
1615 // TH2F* deviations = new TH2F("deviations", "deviations", nBins, lowEdge, upEdge, 1000, -0.01, 0.01);
1616 // for (Int_t n=1; n<kErrorIterations; ++n)
1617 // for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
1618 // deviations->Fill(results[n]->GetXaxis()->GetBinCenter(x), results[n]->GetBinContent(x) - results[0]->GetBinContent(x));
1619 // //new TCanvas; deviations->DrawCopy("COLZ");
1621 // // get standard deviation "by hand"
1622 // for (Int_t x=1; x<=nBins; x++)
1624 // if (results[0]->GetBinContent(x) > 0)
1626 // TH1* proj = deviations->ProjectionY("projRMS", x, x, "e");
1627 // Float_t standardDev = proj->GetRMS(); // this is standard deviation in fact
1628 // //standardDeviation->SetBinContent(x, standardDev / results[0]->GetBinContent(x));
1629 // Printf("sigma_%d is %f value %f --> error %f", x, standardDev, results[0]->GetBinContent(x), standardDev / results[0]->GetBinContent(x));
1633 TH1* standardDeviation = CalculateStdDev(results, kErrorIterations);
1635 // compare maxError to RMS of profile (variable name: average)
1636 // first: calculate rms in percent of value
1637 TH1* rmsError = (TH1*) maxError->Clone("rmsError");
1640 // enable error to be standard deviation (see http://root.cern.ch/root/html/TProfile.html#TProfile:SetErrorOption)
1641 average->SetErrorOption("s");
1642 for (Int_t x=1; x<=rmsError->GetNbinsX(); x++)
1643 if (average->GetBinContent(x) > 0)
1644 rmsError->SetBinContent(x, average->GetBinError(x) / average->GetBinContent(x));
1646 // find maxError deviation from average (not from "first result"/mc as above)
1647 TH1* maxError2 = (TH1*) maxError->Clone("maxError2");
1649 for (Int_t n=1; n<kErrorIterations; ++n)
1650 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
1651 if (average->GetBinContent(x) > 0)
1652 maxError2->SetBinContent(x, TMath::Max(maxError2->GetBinContent(x), TMath::Abs((results[n]->GetBinContent(x) - average->GetBinContent(x)) / average->GetBinContent(x))));
1654 //new TCanvas; maxError2->DrawCopy(); rmsError->SetLineColor(2); rmsError->DrawCopy("SAME"); standardDeviation->SetLineColor(3); standardDeviation->DrawCopy("SAME");
1656 // plot difference between average and MC/first result
1657 TH1* averageFirstRatio = (TH1*) results[0]->Clone("averageFirstRatio");
1658 averageFirstRatio->Reset();
1659 averageFirstRatio->Divide(results[0], average);
1661 //new TCanvas; results[0]->DrawCopy(); average->SetLineColor(2); average->DrawClone("SAME");
1662 //new TCanvas; averageFirstRatio->DrawCopy();
1664 static TH1* temp = 0;
1667 temp = (TH1*) standardDeviation->Clone("temp");
1668 for (Int_t x=1; x<=results[0]->GetNbinsX(); x++)
1669 temp->SetBinContent(x, temp->GetBinContent(x) * results[0]->GetBinContent(x));
1673 // find difference from result[0] as TH2
1674 TH2F* pulls = new TH2F("pulls", "pulls;multiplicity;difference", nBins, lowEdge, upEdge, 1000, -10, 10);
1675 for (Int_t n=1; n<kErrorIterations; ++n)
1676 for (Int_t x=1; x<=results[n]->GetNbinsX(); x++)
1677 if (temp->GetBinContent(x) > 0)
1678 pulls->Fill(results[n]->GetXaxis()->GetBinCenter(x), (results[0]->GetBinContent(x) - results[n]->GetBinContent(x)) / temp->GetBinContent(x));
1679 new TCanvas("pulls", "pulls", 800, 600); pulls->DrawCopy(); pulls->FitSlicesY();
1683 for (Int_t n=0; n<kErrorIterations; ++n)
1687 // fill into result histogram
1688 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); ++i)
1689 fMultiplicityESDCorrected[correlationID]->SetBinContent(i, firstResult->GetBinContent(i));
1691 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); ++i)
1692 fMultiplicityESDCorrected[correlationID]->SetBinError(i, standardDeviation->GetBinContent(i) * fMultiplicityESDCorrected[correlationID]->GetBinContent(i));
1694 return standardDeviation;
1697 //____________________________________________________________________
1698 void AliMultiplicityCorrection::ApplyBayesianMethod(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType, Float_t regPar, Int_t nIterations, TH1* initialConditions, Int_t determineError)
1701 // correct spectrum using bayesian method
1705 // 1 = from randomizing
1706 // 2 = with UnfoldGetBias
1708 // initialize seed with current time
1709 gRandom->SetSeed(0);
1711 SetupCurrentHists(inputRange, fullPhaseSpace, eventType);
1713 // normalize correction for given nPart
1714 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
1716 // with this it is normalized to 1
1717 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
1719 // with this normalized to the given efficiency
1720 if (fCurrentEfficiency->GetBinContent(i) > 0)
1721 sum /= fCurrentEfficiency->GetBinContent(i);
1725 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
1729 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
1730 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
1734 fCurrentCorrelation->SetBinContent(i, j, 0);
1735 fCurrentCorrelation->SetBinError(i, j, 0);
1740 Int_t correlationID = inputRange + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1742 AliUnfolding::SetBayesianParameters(regPar, nIterations);
1743 AliUnfolding::SetUnfoldingMethod(AliUnfolding::kBayesian);
1745 if (determineError <= 1)
1747 if (AliUnfolding::Unfold(fCurrentCorrelation, fCurrentEfficiency, fCurrentESD, initialConditions, fMultiplicityESDCorrected[correlationID]) != 0)
1750 else if (determineError == 2)
1752 AliUnfolding::UnfoldGetBias(fCurrentCorrelation, fCurrentEfficiency, fCurrentESD, initialConditions, fMultiplicityESDCorrected[correlationID]);
1756 if (determineError == 0)
1758 Printf("AliMultiplicityCorrection::ApplyBayesianMethod: WARNING: No errors calculated.");
1762 // evaluate errors, this is done by randomizing the measured spectrum following Poission statistics
1763 // this (new) measured spectrum is then unfolded and the different to the result from the "real" measured
1764 // spectrum calculated. This is performed N times and the sigma is taken as the statistical
1765 // error of the unfolding method itself.
1767 const Int_t kErrorIterations = 20;
1769 Printf("Spectrum unfolded. Determining error (%d iterations)...", kErrorIterations);
1771 TH1* randomized = (TH1*) fCurrentESD->Clone("randomized");
1772 TH1* resultArray[kErrorIterations+1];
1773 for (Int_t n=0; n<kErrorIterations; ++n)
1775 // randomize the content of clone following a poisson with the mean = the value of that bin
1776 for (Int_t x=1; x<=randomized->GetNbinsX(); x++) // mult. axis
1778 Int_t randomValue = gRandom->Poisson(fCurrentESD->GetBinContent(x));
1779 //printf("%d --> %d\n", fCurrentESD->GetBinContent(x), randomValue);
1780 randomized->SetBinContent(x, randomValue);
1781 randomized->SetBinError(x, TMath::Sqrt(randomValue));
1784 TH1* result2 = (TH1*) fMultiplicityESDCorrected[correlationID]->Clone("result2");
1786 if (AliUnfolding::Unfold(fCurrentCorrelation, fCurrentEfficiency, randomized, initialConditions, result2) != 0)
1792 resultArray[n+1] = result2;
1796 resultArray[0] = fMultiplicityESDCorrected[correlationID];
1797 TH1* error = CalculateStdDev(resultArray, kErrorIterations+1);
1799 for (Int_t n=0; n<kErrorIterations; ++n)
1800 delete resultArray[n+1];
1802 Printf("Comparing bias and error:");
1803 for (Int_t i=1; i<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); ++i)
1805 Printf("Bin %d: Content: %f Error: %f Bias: %f", i, fMultiplicityESDCorrected[correlationID]->GetBinContent(i), error->GetBinContent(i) * fMultiplicityESDCorrected[correlationID]->GetBinContent(i), fMultiplicityESDCorrected[correlationID]->GetBinError(i));
1806 fMultiplicityESDCorrected[correlationID]->SetBinError(i, error->GetBinContent(i) * fMultiplicityESDCorrected[correlationID]->GetBinContent(i));
1812 //____________________________________________________________________
1813 Float_t AliMultiplicityCorrection::BayesCovarianceDerivate(Float_t matrixM[251][251], const TH2* hResponse, Int_t k, Int_t i, Int_t r, Int_t u)
1816 // helper function for the covariance matrix of the bayesian method
1821 if (k == u && r == i)
1822 result += 1.0 / hResponse->GetBinContent(u+1, r+1);
1825 result -= 1.0 / fCurrentEfficiency->GetBinContent(u+1);
1828 result -= matrixM[u][i] * fCurrentEfficiency->GetBinContent(u+1) / hResponse->GetBinContent(u+1, i+1);
1830 result *= matrixM[k][i];
1835 //____________________________________________________________________
1836 void AliMultiplicityCorrection::ApplyLaszloMethod(Int_t inputRange, Bool_t fullPhaseSpace, EventType eventType)
1839 // correct spectrum using bayesian method
1844 Int_t correlationID = inputRange; // + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1845 Int_t mcTarget = inputRange; //((fullPhaseSpace == kFALSE) ? inputRange : 4);
1847 SetupCurrentHists(inputRange, fullPhaseSpace, eventType);
1849 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
1851 // TODO should be taken from correlation map
1852 //TH1* sumHist = GetMultiplicityMC(inputRange, eventType)->ProjectionY("sumHist", 1, GetMultiplicityMC(inputRange, eventType)->GetNbinsX());
1854 // normalize correction for given nPart
1855 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
1857 Double_t sum = fCurrentCorrelation->Integral(i, i, 1, fCurrentCorrelation->GetNbinsY());
1858 //Double_t sum = sumHist->GetBinContent(i);
1861 for (Int_t j=1; j<=fCurrentCorrelation->GetNbinsY(); ++j)
1864 fCurrentCorrelation->SetBinContent(i, j, fCurrentCorrelation->GetBinContent(i, j) / sum);
1865 fCurrentCorrelation->SetBinError(i, j, fCurrentCorrelation->GetBinError(i, j) / sum);
1870 fCurrentCorrelation->Draw("COLZ");
1873 fCurrentEfficiency = ((TH2*) fCurrentCorrelation)->ProjectionX("eff");
1875 // pick prior distribution
1876 TH1F* hPrior = (TH1F*)fCurrentESD->Clone("prior");
1877 Float_t norm = 1; //hPrior->Integral();
1878 for (Int_t t=1; t<=hPrior->GetNbinsX(); t++)
1879 hPrior->SetBinContent(t, hPrior->GetBinContent(t)/norm);
1881 // zero distribution
1882 TH1F* zero = (TH1F*)hPrior->Clone("zero");
1885 TH1F* hTemp = (TH1F*)fCurrentESD->Clone("temp");
1889 TH2F* hResponse = (TH2F*) fCurrentCorrelation;
1892 Int_t iterations = 25;
1893 for (Int_t i=0; i<iterations; i++)
1895 //printf(" iteration %i \n", i);
1897 for (Int_t m=1; m<=hResponse->GetNbinsY(); m++)
1900 for (Int_t t = 1; t<=hResponse->GetNbinsX(); t++)
1901 value += hResponse->GetBinContent(t, m) * hPrior->GetBinContent(t);
1902 hTemp->SetBinContent(m, value);
1903 //printf("%d %f %f %f\n", m, zero->GetBinContent(m), hPrior->GetBinContent(m), value);
1906 // regularization (simple smoothing)
1907 TH1F* hTrueSmoothed = (TH1F*) hTemp->Clone("truesmoothed");
1909 for (Int_t t=2; t<hTrueSmoothed->GetNbinsX(); t++)
1911 Float_t average = (hTemp->GetBinContent(t-1) / hTemp->GetBinWidth(t-1)
1912 + hTemp->GetBinContent(t) / hTemp->GetBinWidth(t)
1913 + hTemp->GetBinContent(t+1) / hTemp->GetBinWidth(t+1)) / 3.;
1914 average *= hTrueSmoothed->GetBinWidth(t);
1916 // weight the average with the regularization parameter
1917 hTrueSmoothed->SetBinContent(t, (1-regPar) * hTemp->GetBinContent(t) + regPar * average);
1920 for (Int_t m=1; m<=hResponse->GetNbinsY(); m++)
1921 hTemp->SetBinContent(m, zero->GetBinContent(m) + hPrior->GetBinContent(m) - hTrueSmoothed->GetBinContent(m));
1924 for (Int_t t=1; t<=fMultiplicityESDCorrected[correlationID]->GetNbinsX(); t++)
1926 fMultiplicityESDCorrected[correlationID]->SetBinContent(t, hTemp->GetBinContent(t));
1927 fMultiplicityESDCorrected[correlationID]->SetBinError(t, 0.05 * hTemp->GetBinContent(t)); // TODO
1929 //printf(" bin %d content %f \n", t, fMultiplicityESDCorrected[correlationID]->GetBinContent(t));
1933 // calculate chi2 (change from last iteration)
1936 // use smoothed true (normalized) as new prior
1937 norm = 1; //hTrueSmoothed->Integral();
1939 for (Int_t t=1; t<hTrueSmoothed->GetNbinsX(); t++)
1941 Float_t newValue = hTemp->GetBinContent(t)/norm;
1942 Float_t diff = hPrior->GetBinContent(t) - newValue;
1943 chi2 += (Double_t) diff * diff;
1945 hPrior->SetBinContent(t, newValue);
1948 printf("Chi2 of %d iteration = %.10f\n", i, chi2);
1951 DrawComparison(Form("Laszlo_%d", i), inputRange, fullPhaseSpace, kTRUE, GetMultiplicityMC(mcTarget, eventType)->ProjectionY());
1953 delete hTrueSmoothed;
1954 } // end of iterations
1956 DrawComparison("Laszlo", inputRange, fullPhaseSpace, kTRUE, GetMultiplicityMC(mcTarget, eventType)->ProjectionY());
1959 //____________________________________________________________________
1960 void AliMultiplicityCorrection::ApplyGaussianMethod(Int_t inputRange, Bool_t fullPhaseSpace)
1963 // correct spectrum using a simple Gaussian approach, that is model-dependent
1966 Int_t correlationID = inputRange; // + ((fullPhaseSpace == kFALSE) ? 0 : 4);
1967 Int_t mcTarget = inputRange; //((fullPhaseSpace == kFALSE) ? inputRange : 4);
1969 SetupCurrentHists(inputRange, fullPhaseSpace, kTrVtx);
1971 fCurrentESD->Scale(1.0 / fCurrentESD->Integral());
1973 TH1D* correction = dynamic_cast<TH1D*> (fCurrentESD->Clone("GaussianMean"));
1974 correction->SetTitle("GaussianMean");
1976 TH1D* correctionWidth = dynamic_cast<TH1D*> (fCurrentESD->Clone("GaussianWidth"));
1977 correction->SetTitle("GaussianWidth");
1979 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
1981 TH1D* proj = (dynamic_cast<TH2*> (fCurrentCorrelation))->ProjectionX("_px", i, i+1);
1982 proj->Fit("gaus", "0Q");
1983 correction->SetBinContent(i, proj->GetFunction("gaus")->GetParameter(1));
1984 correctionWidth->SetBinContent(i, proj->GetFunction("gaus")->GetParameter(2));
1988 // draw for debugging
1991 proj->GetFunction("gaus")->DrawCopy("SAME");
1994 TH1* target = fMultiplicityESDCorrected[correlationID];
1996 Int_t nBins = target->GetNbinsX()*10+1;
1997 Float_t* binning = new Float_t[nBins];
1998 for (Int_t i=1; i<=target->GetNbinsX(); ++i)
1999 for (Int_t j=0; j<10; ++j)
2000 binning[(i-1)*10 + j] = target->GetXaxis()->GetBinLowEdge(i) + target->GetXaxis()->GetBinWidth(i) / 10 * j;
2002 binning[nBins-1] = target->GetXaxis()->GetBinUpEdge(target->GetNbinsX());
2004 TH1F* fineBinned = new TH1F("targetFineBinned", "targetFineBinned", nBins-1, binning);
2006 for (Int_t i=1; i<=fCurrentCorrelation->GetNbinsX(); ++i)
2008 Float_t mean = correction->GetBinContent(i);
2009 Float_t width = correctionWidth->GetBinContent(i);
2011 Int_t fillBegin = fineBinned->FindBin(mean - width * 5);
2012 Int_t fillEnd = fineBinned->FindBin(mean + width * 5);
2013 //printf("bin %d mean %f width %f, filling from %d to %d\n", i, mean, width, fillBegin, fillEnd);
2015 for (Int_t j=fillBegin; j <= fillEnd; ++j)
2017 fineBinned->AddBinContent(j, TMath::Gaus(fineBinned->GetXaxis()->GetBinCenter(j), mean, width, kTRUE) * fCurrentESD->GetBinContent(i));
2021 for (Int_t i=1; i<=target->GetNbinsX(); ++i)
2024 for (Int_t j=1; j<=10; ++j)
2025 sum += fineBinned->GetBinContent((i-1)*10 + j);
2026 target->SetBinContent(i, sum / 10);
2031 DrawComparison("Gaussian", inputRange, fullPhaseSpace, kFALSE, GetMultiplicityMC(mcTarget, kTrVtx)->ProjectionY());
2034 //____________________________________________________________________
2035 TH1* AliMultiplicityCorrection::GetConvoluted(Int_t i, EventType eventType)
2037 // convolutes the corrected histogram i with the response matrix
2039 TH1* corrected = (TH1*) fMultiplicityESDCorrected[i]->Clone("corrected");
2041 // undo efficiency correction (hist must not be deleted, is reused)
2042 TH1* efficiency = GetEfficiency(i, eventType);
2043 //new TCanvas; efficiency->DrawCopy();
2044 corrected->Multiply(efficiency);
2046 TH2* convoluted = CalculateMultiplicityESD(corrected, i);
2047 TH1* convolutedProj = convoluted->ProjectionY("GetConvoluted_convolutedProj", 1, convoluted->GetNbinsX());
2052 return convolutedProj;
2055 //____________________________________________________________________
2056 TH1* AliMultiplicityCorrection::GetResiduals(Int_t i, EventType eventType, Float_t& residualSum)
2058 // creates the residual histogram from the corrected histogram i corresponding to an eventType event sample using the corresponding correlation matrix
2059 // residual is : M - UT / eM
2060 // residualSum contains the squared sum of the residuals
2062 TH1* corrected = (TH1*) fMultiplicityESDCorrected[i]->Clone("corrected");
2063 TH1* convolutedProj = GetConvoluted(i, eventType);
2066 Int_t end = fMultiplicityESD[i]->GetNbinsX();
2067 if (fVtxEnd > fVtxBegin)
2072 TH1* measuredProj = fMultiplicityESD[i]->ProjectionY("measuredProj", begin, end);
2074 TH1* residuals = (TH1*) measuredProj->Clone("GetResiduals_residuals");
2075 residuals->SetTitle(";measured multiplicity;residuals (M-Ut)/e");
2076 residuals->Add(convolutedProj, -1);
2079 for (Int_t j=1; j<=residuals->GetNbinsX(); j++)
2081 if (measuredProj->GetBinContent(j) > 0)
2082 residuals->SetBinContent(j, residuals->GetBinContent(j) / TMath::Sqrt(measuredProj->GetBinContent(j)));
2083 residuals->SetBinError(j, 0);
2086 residualSum += residuals->GetBinContent(j) * residuals->GetBinContent(j);
2090 delete convolutedProj;
2091 delete measuredProj;
2096 //____________________________________________________________________
2097 TH2F* AliMultiplicityCorrection::CalculateMultiplicityESD(TH1* inputMC, Int_t correlationMap)
2099 // runs the distribution given in inputMC through the response matrix identified by
2100 // correlationMap and produces a measured distribution
2101 // although it is a TH2F the vertex axis is not used at the moment and all entries are filled in mid-vertex
2106 if (correlationMap < 0 || correlationMap >= kCorrHists)
2109 // empty under/overflow bins in x, otherwise Project3D takes them into account
2110 TH3* hist = fCorrelation[correlationMap];
2111 for (Int_t y=0; y<=hist->GetYaxis()->GetNbins()+1; ++y)
2113 for (Int_t z=0; z<=hist->GetZaxis()->GetNbins()+1; ++z)
2115 hist->SetBinContent(0, y, z, 0);
2116 hist->SetBinContent(hist->GetXaxis()->GetNbins()+1, y, z, 0);
2120 if (fVtxEnd > fVtxBegin)
2121 hist->GetXaxis()->SetRange(fVtxBegin, fVtxEnd);
2123 TH2* corr = (TH2*) hist->Project3D("zy");
2124 //corr->Rebin2D(2, 1);
2126 Printf("Correction histogram used for convolution has %f entries", corr->Integral());
2128 // normalize correction for given nPart
2129 for (Int_t i=1; i<=corr->GetNbinsX(); ++i)
2131 Double_t sum = corr->Integral(i, i, 1, corr->GetNbinsY());
2135 for (Int_t j=1; j<=corr->GetNbinsY(); ++j)
2138 corr->SetBinContent(i, j, corr->GetBinContent(i, j) / sum);
2139 corr->SetBinError(i, j, corr->GetBinError(i, j) / sum);
2143 TH2F* target = static_cast<TH2F*> (fMultiplicityESD[0]->Clone(Form("%s_measured", inputMC->GetName())));
2146 for (Int_t meas=1; meas<=corr->GetNbinsY(); ++meas)
2148 Float_t measured = 0;
2151 for (Int_t gen=1; gen<=corr->GetNbinsX(); ++gen)
2153 Int_t mcGenBin = inputMC->GetXaxis()->FindBin(corr->GetXaxis()->GetBinCenter(gen));
2155 measured += inputMC->GetBinContent(mcGenBin) * corr->GetBinContent(gen, meas);
2157 error += inputMC->GetBinError(mcGenBin) * corr->GetBinContent(gen, meas);
2160 //printf("%f +- %f ; %f +- %f \n", inputMC->GetBinContent(meas), inputMC->GetBinError(meas), measured, error);
2162 target->SetBinContent(1 + target->GetNbinsX() / 2, meas, measured);
2163 target->SetBinError(1 + target->GetNbinsX() / 2, meas, error);
2169 //____________________________________________________________________
2170 void AliMultiplicityCorrection::SetGenMeasFromFunc(const TF1* inputMC, Int_t id)
2172 // uses the given function to fill the input MC histogram and generates from that
2173 // the measured histogram by applying the response matrix
2174 // this can be used to evaluate if the methods work indepedently of the input
2176 // WARNING does not respect the vertex distribution, just fills central vertex bin
2181 if (id < 0 || id >= kESDHists)
2184 // fill histogram used for random generation
2185 TH1* tmp = fMultiplicityVtx[id]->ProjectionY("tmp");
2188 for (Int_t i=1; i<=tmp->GetNbinsX(); ++i)
2189 tmp->SetBinContent(i, inputMC->Eval(tmp->GetXaxis()->GetBinCenter(i)) * tmp->GetXaxis()->GetBinWidth(i));
2191 TH1* mcRnd = fMultiplicityVtx[id]->ProjectionY("mcRnd");
2193 mcRnd->FillRandom(tmp, (Int_t) tmp->Integral());
2195 //new TCanvas; tmp->Draw();
2196 //new TCanvas; mcRnd->Draw();
2198 // and move into 2d histogram
2199 TH1* mc = fMultiplicityVtx[id];
2201 for (Int_t i=1; i<=mc->GetNbinsY(); ++i)
2203 mc->SetBinContent(mc->GetNbinsX() / 2 + 1, i, mcRnd->GetBinContent(i));
2204 mc->SetBinError(mc->GetNbinsX() / 2 + 1, i, TMath::Sqrt(mcRnd->GetBinContent(i)));
2207 //new TCanvas; mc->Draw("COLZ");
2209 // now randomize the measured histogram; funcMeasured is used as pilot function to generated the measured entries
2210 TH1* funcMeasured = CalculateMultiplicityESD(tmp, id)->ProjectionY("funcMeasured");
2212 //new TCanvas; funcMeasured->Draw();
2214 fMultiplicityESD[id]->Reset();
2216 TH1* measRnd = fMultiplicityESD[id]->ProjectionY("measRnd");
2217 measRnd->FillRandom(funcMeasured, (Int_t) tmp->Integral());
2219 //new TCanvas; measRnd->Draw();
2221 fMultiplicityESD[id]->Reset();
2222 for (Int_t i=1; i<=fMultiplicityESD[id]->GetNbinsY(); ++i)
2224 fMultiplicityESD[id]->SetBinContent(fMultiplicityESD[id]->GetNbinsX() / 2 + 1, i, measRnd->GetBinContent(i));
2225 fMultiplicityESD[id]->SetBinError(fMultiplicityESD[id]->GetNbinsX() / 2 + 1, i, TMath::Sqrt(measRnd->GetBinContent(i)));