1 #include "AliPoissonCalculator.h"
2 // #include "AliForwardCorrectionManager.h"
12 // A class to calculate the multiplicity in @f$(x,y)@f$ bins
13 // using Poisson statistics.
15 // The input is assumed to be binned in @f$(x,y)@f$ as described by
16 // the 2D histogram passed to the Reset member function.
18 // The data is grouped in to regions as defined by the parameters
19 // fXLumping and fYLumping. The total number of cells and number of
20 // empty cells is then calculate in each region. The mean
21 // multiplicity over the region is then determined as
24 // \lange m\rangle = -\log\left(\frac{e}{t}\right)
26 // where @f$ e@f$ is the number of empty cells and @f$t@f$ is the
27 // total number of cells in the region. A correction for counting
28 // statistics, is then applied
30 // c &=& \frac{1}{1 - \exp{-\lange m\rangle}}
31 // &=& \frac{1}{1 - \frac{e}{t}}
33 // and the final number in each cell is then
35 // h_i c \lange m\rangle
37 // where @f$h_i@f$ is the number of hits in the cell @f$i@f$
42 const char* kBasicN = "basic";
43 const char* kEmptyN = "empty";
44 const char* kTotalN = "total";
45 const char* kBasicT = "Basic number of hits";
46 const char* kEmptyT = "Empty number of bins/region";
47 const char* kTotalT = "Total number of bins/region";
53 //____________________________________________________________________
54 AliPoissonCalculator::AliPoissonCalculator()
71 //____________________________________________________________________
72 AliPoissonCalculator::AliPoissonCalculator(const char*)
73 : TNamed("poissonCalculator", "Calculate N_ch using Poisson stat"),
88 //____________________________________________________________________
89 AliPoissonCalculator::AliPoissonCalculator(const AliPoissonCalculator& o)
91 fXLumping(o.fXLumping),
92 fYLumping(o.fYLumping),
105 //____________________________________________________________________
106 AliPoissonCalculator::~AliPoissonCalculator()
111 //____________________________________________________________________
113 AliPoissonCalculator::CleanUp()
115 if (fTotal) { delete fTotal; fTotal = 0; }
116 if (fEmpty) { delete fEmpty; fEmpty = 0; }
117 if (fBasic) { delete fBasic; fBasic = 0; }
118 if (fEmptyVsTotal) { delete fEmptyVsTotal; fEmptyVsTotal = 0; }
119 if (fMean) { delete fMean; fMean = 0; }
120 if (fOcc) { delete fOcc; fOcc = 0; }
121 if (fCorr) { delete fCorr; fCorr = 0; }
123 //____________________________________________________________________
124 AliPoissonCalculator&
125 AliPoissonCalculator::operator=(const AliPoissonCalculator& o)
127 if (&o == this) return *this;
128 TNamed::operator=(o);
129 fXLumping = o.fXLumping;
130 fYLumping = o.fYLumping;
137 //____________________________________________________________________
139 AliPoissonCalculator::Init(Int_t xLumping, Int_t yLumping)
144 if (xLumping > 0) fXLumping = xLumping;
145 if (yLumping > 0) fYLumping = yLumping;
147 //Create diagnostics if void
148 if (fEmptyVsTotal) return;
152 //____________________________________________________________________
154 AliPoissonCalculator::Define(const TAxis& xaxis, const TAxis& yaxis)
159 const Double_t* xBins = xaxis.GetXbins()->GetArray();
160 const Double_t* yBins = yaxis.GetXbins()->GetArray();
161 Int_t nX = xaxis.GetNbins();
162 Int_t nY = yaxis.GetNbins();
163 Double_t lX = xaxis.GetXmin();
164 Double_t hX = xaxis.GetXmax();
165 Double_t lY = yaxis.GetXmin();
166 Double_t hY = yaxis.GetXmax();
169 if (yBins) fBasic = new TH2D(kBasicN, kBasicT, nX, xBins, nY, yBins);
170 else fBasic = new TH2D(kBasicN, kBasicT, nX, xBins, nY, lY, hY);
173 if (yBins) fBasic = new TH2D(kBasicN, kBasicT, nX, lX, hX, nY, yBins);
174 else fBasic = new TH2D(kBasicN, kBasicT, nX, lX, hX, nY, lY, hY);
176 fBasic->SetXTitle(xaxis.GetTitle());
177 fBasic->SetYTitle(yaxis.GetTitle());
181 //____________________________________________________________________
182 void AliPoissonCalculator::MakeOutput()
184 Int_t n = fXLumping * fYLumping + 1;
185 fEmptyVsTotal = new TH2D("emptyVsTotal",
186 "# of empty # bins vs total # bins",
187 n, -.5, n-.5, n, -.5, n-.5);
188 fEmptyVsTotal->SetXTitle("Total # bins");
189 fEmptyVsTotal->SetYTitle("# empty bins");
190 fEmptyVsTotal->SetZTitle("Correlation");
191 fEmptyVsTotal->SetOption("colz");
192 fEmptyVsTotal->SetDirectory(0);
194 n = (fXLumping + fYLumping);
195 fMean = new TH1D("poissonMean", "Mean N_{ch} as calculated by Poisson",
197 fMean->SetXTitle("#bar{N_{ch}}=log(empty/total)");
198 fMean->SetYTitle("Events");
199 fMean->SetFillColor(kRed+1);
200 fMean->SetFillStyle(3001);
201 fMean->SetLineColor(kBlack);
202 fMean->SetDirectory(0);
204 fOcc = new TH1D("occupancy", "Occupancy = #int_{1}^{#infty}dN P(N)",
206 fOcc->SetXTitle("#int_{1}^{#infty}dN P(N) [%]");
207 fOcc->SetYTitle("Events");
208 fOcc->SetFillColor(kBlue+1);
209 fOcc->SetFillStyle(3001);
210 fOcc->SetLineColor(kBlack);
211 fOcc->SetDirectory(0);
213 fCorr = new TH2D("correction", "Correction as function of mean N_{ch}",
214 10*n+1, -.1, n+.1, 100, 0, 10);
215 fCorr->SetXTitle("#bar{N_{ch}}");
216 fCorr->SetYTitle("Correction 1/(1-e^{#bar{N_{c}}})");
217 fCorr->SetZTitle("Events");
218 fCorr->SetOption("colz");
219 fCorr->SetDirectory(0);
221 //____________________________________________________________________
223 AliPoissonCalculator::Output(TList* d)
226 if (!fEmptyVsTotal) MakeOutput();
227 d->Add(fEmptyVsTotal);
233 //____________________________________________________________________
235 AliPoissonCalculator::SetLumping(UShort_t nx, UShort_t ny)
237 if (nx == fXLumping && ny == fYLumping &&
238 fEmptyVsTotal && fTotal)
239 // Check if we have something to do.
245 //____________________________________________________________________
247 AliPoissonCalculator::CheckLumping(char which, Int_t nBins, Int_t lumping) const
249 if ((nBins % lumping) == 0) return lumping;
253 } while (l > 0 && ((nBins % l) != 0));
254 Warning("CheckLumping", "%c lumping %d is not a divisor of %d, set to %d",
255 which, lumping, nBins, l);
259 //____________________________________________________________________
261 AliPoissonCalculator::Reset(const TH2D* base)
266 if (fBasic && fTotal && fEmpty) {
275 Int_t nXF = base->GetNbinsX();
276 Double_t xMin = base->GetXaxis()->GetXmin();
277 Double_t xMax = base->GetXaxis()->GetXmax();
278 Int_t nYF = base->GetNbinsY();
279 Double_t yMin = base->GetYaxis()->GetXmin();
280 Double_t yMax = base->GetYaxis()->GetXmax();
282 fXLumping = CheckLumping('X', nXF, fXLumping);
283 fYLumping = CheckLumping('Y', nYF, fYLumping);
285 Int_t nY = nYF / fYLumping;
286 Int_t nX = nXF / fXLumping;
288 if (fBasic != base) {
289 fBasic = static_cast<TH2D*>(base->Clone(kBasicN));
290 fBasic->SetTitle(kBasicT);
291 fBasic->SetDirectory(0);
295 fTotal = new TH2D(kTotalN, kTotalT, nX, xMin, xMax, nY, yMin, yMax);
296 fTotal->SetDirectory(0);
297 fTotal->SetXTitle(fBasic->GetXaxis()->GetTitle());
298 fTotal->SetYTitle(fBasic->GetYaxis()->GetTitle());
301 fEmpty = static_cast<TH2D*>(fTotal->Clone(kEmptyN));
302 fEmpty->SetTitle(kEmptyT);
303 fEmpty->SetDirectory(0);
307 //____________________________________________________________________
309 AliPoissonCalculator::Fill(UShort_t x, UShort_t y, Bool_t hit, Double_t weight)
312 // Fill in an observation
318 // weight Weight if this
321 if (hit) fBasic->Fill(x, y, weight);
322 else fEmpty->Fill(x, y);
325 //____________________________________________________________________
327 AliPoissonCalculator::CalculateMean(Double_t empty, Double_t total) const
329 if (total <= 0) return 0;
330 if (empty < .001) empty = .001;
331 return -TMath::Log(empty/total);
333 //____________________________________________________________________
335 AliPoissonCalculator::CalculateCorrection(Double_t empty, Double_t total) const
337 if (total <= 0) return 0;
338 if (TMath::Abs(empty-total) < .001) empty = total - .001;
339 return 1 / (1 - empty / total);
342 //____________________________________________________________________
344 AliPoissonCalculator::GetReducedXBin(Int_t ix) const
346 if (!fBasic) return 0;
347 Double_t mx = fBasic->GetXaxis()->GetBinCenter(ix);
348 return GetReducedXBin(mx);
350 //____________________________________________________________________
352 AliPoissonCalculator::GetReducedXBin(Double_t x) const
354 if (!fEmpty) return 0;
355 return fEmpty->GetXaxis()->FindBin(x);
357 //____________________________________________________________________
359 AliPoissonCalculator::GetReducedYBin(Int_t iy) const
361 if (!fBasic) return 0;
362 Double_t my = fBasic->GetYaxis()->GetBinCenter(iy);
363 return GetReducedYBin(my);
365 //____________________________________________________________________
367 AliPoissonCalculator::GetReducedYBin(Double_t y) const
369 if (!fEmpty) return 0;
370 return fEmpty->GetYaxis()->FindBin(y);
375 //____________________________________________________________________
377 AliPoissonCalculator::Result(Bool_t correct)
380 // Calculate result and store in @a output
383 // The result histogram (fBase overwritten)
386 // Double_t total = fXLumping * fYLumping;
388 for (Int_t ix = 1; ix <= fBasic->GetNbinsX(); ix++) {
389 // Double_t x = fBasic->GetXaxis()->GetBinCenter(ix);
390 Int_t jx = GetReducedXBin(ix); // fEmpty->GetXaxis()->FindBin(x);
391 for (Int_t iy = 1; iy <= fBasic->GetNbinsY(); iy++) {
392 // Double_t y = fBasic->GetYaxis()->GetBinCenter(iy);
393 Int_t jy = GetReducedYBin(iy); // fEmpty->GetYaxis()->FindBin(y);
394 Double_t empty = fEmpty->GetBinContent(jx, jy);
395 Double_t total = fTotal->GetBinContent(jx, jy);
396 Double_t hits = fBasic->GetBinContent(ix,iy);
397 // Mean in region of interest
398 Double_t poissonM = CalculateMean(empty, total);
399 Double_t poissonC = (correct ? CalculateCorrection(empty, total) : 1);
401 Double_t poissonV = hits * poissonM * poissonC;
402 Double_t poissonE = TMath::Sqrt(poissonV);
403 if(poissonV > 0) poissonE = TMath::Sqrt(poissonV);
405 fBasic->SetBinContent(ix,iy,poissonV);
406 fBasic->SetBinError(ix,iy,poissonE);
412 //____________________________________________________________________
414 AliPoissonCalculator::FillDiagnostics()
416 for (Int_t ix = 1; ix <= fEmpty->GetNbinsX(); ix++) {
417 for (Int_t iy = 1; iy <= fEmpty->GetNbinsY(); iy++) {
418 Double_t empty = fEmpty->GetBinContent(ix, iy);
419 Double_t total = fTotal->GetBinContent(ix, iy);
420 Double_t mean = CalculateMean(empty, total);
421 Double_t corr = CalculateCorrection(empty, total);
422 fEmptyVsTotal->Fill(total, empty);
424 if (total > 1e-6) fOcc->Fill(100 * (1 - empty/total));
425 //Old fOcc->Fill(100 * (1 - TMath::PoissonI(0,mean)));
426 fCorr->Fill(mean, corr);
430 //____________________________________________________________________
432 AliPoissonCalculator::Print(const Option_t*) const
440 char ind[gROOT->GetDirLevel()+3];
441 for (Int_t i = 0; i < gROOT->GetDirLevel(); i++) ind[i] = ' ';
442 ind[gROOT->GetDirLevel()] = '\0';
443 std::cout << ind << ClassName() << ": " << GetName() << '\n'
445 << ind << " X lumping: " << fXLumping << '\n'
446 << ind << " Y lumping: " << fYLumping << '\n'
447 << std::noboolalpha << std::endl;
449 //____________________________________________________________________
451 AliPoissonCalculator::Browse(TBrowser* b)
454 // Browse this object
457 // b Object to browse
459 if (fTotal) b->Add(fTotal);
460 if (fEmpty) b->Add(fEmpty);
461 if (fBasic) b->Add(fBasic);
462 if (fEmptyVsTotal) b->Add(fEmptyVsTotal);
463 if (fMean) b->Add(fMean);
464 if (fOcc) b->Add(fOcc);
465 if (fCorr) b->Add(fCorr);