1 // This class calculates the inclusive charged particle density
2 // in each for the 5 FMD rings.
4 #include "AliFMDDensityCalculator.h"
9 #include "AliForwardCorrectionManager.h"
10 #include "AliFMDCorrDoubleHit.h"
11 #include "AliFMDCorrELossFit.h"
13 #include "AliForwardUtil.h"
19 #include <TStopwatch.h>
20 #include <TParameter.h>
25 ClassImp(AliFMDDensityCalculator)
30 //____________________________________________________________________
31 const char* AliFMDDensityCalculator::fgkFolderName = "fmdDensityCalculator";
33 //____________________________________________________________________
34 AliFMDDensityCalculator::AliFMDDensityCalculator()
42 fUsePhiAcceptance(kPhiCorrectNch),
56 fRecalculateEta(false),
57 fRecalculatePhi(false),
68 DGUARD(fDebug, 3, "Default CTOR of FMD density calculator");
71 //____________________________________________________________________
72 AliFMDDensityCalculator::AliFMDDensityCalculator(const char* title)
73 : TNamed(fgkFolderName, title),
80 fUsePhiAcceptance(kPhiCorrectNch),
94 fRecalculateEta(false),
95 fRecalculatePhi(false),
107 // name Name of object
109 DGUARD(fDebug, 3, "Named CTOR of FMD density calculator: %s", title);
110 fRingHistos.SetName(GetName());
111 fRingHistos.SetOwner();
112 fRingHistos.Add(new RingHistos(1, 'I'));
113 fRingHistos.Add(new RingHistos(2, 'I'));
114 fRingHistos.Add(new RingHistos(2, 'O'));
115 fRingHistos.Add(new RingHistos(3, 'I'));
116 fRingHistos.Add(new RingHistos(3, 'O'));
117 fSumOfWeights = new TH1D("sumOfWeights", "Sum of Landau weights",
119 fSumOfWeights->SetFillColor(kRed+1);
120 fSumOfWeights->SetXTitle("#sum_{i} a_{i} f_{i}(#Delta)");
121 fWeightedSum = new TH1D("weightedSum", "Weighted sum of Landau propability",
123 fWeightedSum->SetFillColor(kBlue+1);
124 fWeightedSum->SetXTitle("#sum_{i} i a_{i} f_{i}(#Delta)");
125 fCorrections = new TH1D("corrections", "Distribution of corrections",
127 fCorrections->SetFillColor(kBlue+1);
128 fCorrections->SetXTitle("correction");
130 fAccI = GenerateAcceptanceCorrection('I');
131 fAccO = GenerateAcceptanceCorrection('O');
133 fMaxWeights = new TH2D("maxWeights", "Maximum i of a_{i}'s to use",
135 fMaxWeights->SetXTitle("#eta");
136 fMaxWeights->SetDirectory(0);
138 fLowCuts = new TH2D("lowCuts", "Low cuts used", 1, 0, 1, 1, 0, 1);
139 fLowCuts->SetXTitle("#eta");
140 fLowCuts->SetDirectory(0);
144 //____________________________________________________________________
145 AliFMDDensityCalculator::AliFMDDensityCalculator(const
146 AliFMDDensityCalculator& o)
149 fSumOfWeights(o.fSumOfWeights),
150 fWeightedSum(o.fWeightedSum),
151 fCorrections(o.fCorrections),
152 fMaxParticles(o.fMaxParticles),
153 fUsePoisson(o.fUsePoisson),
154 fUsePhiAcceptance(o.fUsePhiAcceptance),
157 fFMD1iMax(o.fFMD1iMax),
158 fFMD2iMax(o.fFMD2iMax),
159 fFMD2oMax(o.fFMD2oMax),
160 fFMD3iMax(o.fFMD3iMax),
161 fFMD3oMax(o.fFMD3oMax),
162 fMaxWeights(o.fMaxWeights),
163 fLowCuts(o.fLowCuts),
164 fEtaLumping(o.fEtaLumping),
165 fPhiLumping(o.fPhiLumping),
168 fRecalculateEta(o.fRecalculateEta),
169 fRecalculatePhi(o.fRecalculatePhi),
170 fMinQuality(o.fMinQuality),
172 fDoTiming(o.fDoTiming),
173 fHTiming(o.fHTiming),
174 fMaxOutliers(o.fMaxOutliers),
175 fOutlierCut(o.fOutlierCut)
181 // o Object to copy from
183 DGUARD(fDebug, 3, "Copy CTOR of FMD density calculator");
184 TIter next(&o.fRingHistos);
186 while ((obj = next())) fRingHistos.Add(obj);
189 //____________________________________________________________________
190 AliFMDDensityCalculator::~AliFMDDensityCalculator()
195 DGUARD(fDebug, 3, "DTOR of FMD density calculator");
196 // fRingHistos.Delete();
199 //____________________________________________________________________
200 AliFMDDensityCalculator&
201 AliFMDDensityCalculator::operator=(const AliFMDDensityCalculator& o)
204 // Assignement operator
207 // o Object to assign from
210 // Reference to this object
212 DGUARD(fDebug, 3, "Assignment of FMD density calculator");
213 if (&o == this) return *this;
214 TNamed::operator=(o);
217 fMaxParticles = o.fMaxParticles;
218 fUsePoisson = o.fUsePoisson;
219 fUsePhiAcceptance = o.fUsePhiAcceptance;
222 fFMD1iMax = o.fFMD1iMax;
223 fFMD2iMax = o.fFMD2iMax;
224 fFMD2oMax = o.fFMD2oMax;
225 fFMD3iMax = o.fFMD3iMax;
226 fFMD3oMax = o.fFMD3oMax;
227 fMaxWeights = o.fMaxWeights;
228 fLowCuts = o.fLowCuts;
229 fEtaLumping = o.fEtaLumping;
230 fPhiLumping = o.fPhiLumping;
232 fRecalculateEta = o.fRecalculateEta;
233 fRecalculatePhi = o.fRecalculatePhi;
234 fMinQuality = o.fMinQuality;
236 fDoTiming = o.fDoTiming;
237 fHTiming = o.fHTiming;
238 fMaxOutliers = o.fMaxOutliers;
239 fOutlierCut = o.fOutlierCut;
241 fRingHistos.Delete();
242 TIter next(&o.fRingHistos);
244 while ((obj = next())) fRingHistos.Add(obj);
249 //____________________________________________________________________
251 AliFMDDensityCalculator::SetupForData(const TAxis& axis)
253 // Intialize this sub-algorithm
257 DGUARD(fDebug, 1, "Initialize FMD density calculator");
258 CacheMaxWeights(axis);
262 TIter next(&fRingHistos);
264 while ((o = static_cast<RingHistos*>(next()))) {
265 o->SetupForData(axis);
266 // o->fMultCut = fCuts.GetFixedCut(o->fDet, o->fRing);
267 // o->fPoisson.Init(o->fDet,o->fRing,fEtaLumping, fPhiLumping);
271 //____________________________________________________________________
272 AliFMDDensityCalculator::RingHistos*
273 AliFMDDensityCalculator::GetRingHistos(UShort_t d, Char_t r) const
276 // Get the ring histogram container
283 // Ring histogram container
287 case 1: idx = 0; break;
288 case 2: idx = 1 + (r == 'I' || r == 'i' ? 0 : 1); break;
289 case 3: idx = 3 + (r == 'I' || r == 'i' ? 0 : 1); break;
291 if (idx < 0 || idx >= fRingHistos.GetEntries()) {
292 AliWarning(Form("Index %d of FMD%d%c out of range", idx, d, r));
296 return static_cast<RingHistos*>(fRingHistos.At(idx));
299 //____________________________________________________________________
301 AliFMDDensityCalculator::GetMultCut(UShort_t d, Char_t r, Int_t ieta,
305 // Get the multiplicity cut. If the user has set fMultCut (via
306 // SetMultCut) then that value is used. If not, then the lower
307 // value of the fit range for the enery loss fits is returned.
310 // Lower cut on multiplicity
312 return fCuts.GetMultCut(d,r,ieta,errors);
315 //____________________________________________________________________
317 AliFMDDensityCalculator::GetMultCut(UShort_t d, Char_t r, Double_t eta,
321 // Get the multiplicity cut. If the user has set fMultCut (via
322 // SetMultCut) then that value is used. If not, then the lower
323 // value of the fit range for the enery loss fits is returned.
326 // Lower cut on multiplicity
328 return fCuts.GetMultCut(d,r,eta,errors);
331 //____________________________________________________________________
333 AliFMDDensityCalculator::Calculate(const AliESDFMD& fmd,
334 AliForwardUtil::Histos& hists,
340 // Do the calculations
343 // fmd AliESDFMD object (possibly) corrected for sharing
344 // hists Histogram cache
346 // lowFlux Low flux flag.
350 DGUARD(fDebug, 1, "Calculate density in FMD density calculator");
355 // First measurements of timing
356 // Re-calculation : fraction of sum 32.0% of total 18.1%
357 // N_{particle} : fraction of sum 15.2% of total 8.6%
358 // Correction : fraction of sum 26.4% of total 14.9%
359 // #phi acceptance : fraction of sum 0.2% of total 0.1%
360 // Copy to cache : fraction of sum 3.9% of total 2.2%
361 // Poisson calculation : fraction of sum 18.7% of total 10.6%
362 // Diagnostics : fraction of sum 3.7% of total 2.1%
363 Double_t reEtaTime = 0;
364 Double_t nPartTime = 0;
365 Double_t corrTime = 0;
366 Double_t rePhiTime = 0;
367 Double_t copyTime = 0;
368 Double_t poissonTime= 0;
369 Double_t diagTime = 0;
370 if (fDoTiming) totalT.Start(true);
372 Double_t etaCache[20*512]; // Same number of strips per ring
373 Double_t phiCache[20*512]; // whether it is inner our outer.
374 // We do not use TArrayD because we do not wont a bounds check
375 // TArrayD etaCache(20*512); // Same number of strips per ring
376 // TArrayD phiCache(20*512); // whether it is inner our outer.
378 // --- Loop over detectors -----------------------------------------
379 for (UShort_t d=1; d<=3; d++) {
380 UShort_t nr = (d == 1 ? 1 : 2);
381 for (UShort_t q=0; q<nr; q++) {
382 Char_t r = (q == 0 ? 'I' : 'O');
383 UShort_t ns= (q == 0 ? 20 : 40);
384 UShort_t nt= (q == 0 ? 512 : 256);
385 TH2D* h = hists.Get(d,r);
386 RingHistos* rh= GetRingHistos(d,r);
388 AliError(Form("No ring histogram found for FMD%d%c", d, r));
392 // rh->fPoisson.SetObject(d,r,vtxbin,cent);
393 rh->fPoisson.Reset(0);
396 // rh->ResetPoissonHistos(h, fEtaLumping, fPhiLumping);
398 // Reset our eta cache
399 // for (Int_t i = 0; i < 20*512; i++)
400 // etaCache[i] = phiCache[i] = AliESDFMD::kInvalidEta;
401 memset(etaCache, 0, sizeof(Double_t)*20*512);
402 memset(phiCache, 0, sizeof(Double_t)*20*512);
403 // etaCache.Reset(AliESDFMD::kInvalidEta);
404 // phiCache.Reset(AliESDFMD::kInvalidEta);
406 // --- Loop over sectors and strips ----------------------------
407 for (UShort_t s=0; s<ns; s++) {
408 for (UShort_t t=0; t<nt; t++) {
410 Float_t mult = fmd.Multiplicity(d,r,s,t);
411 Float_t phi = fmd.Phi(d,r,s,t) * TMath::DegToRad();
412 Float_t eta = fmd.Eta(d,r,s,t);
413 Double_t oldPhi = phi;
415 // --- Re-calculate eta - needed for satelittes ------------
416 if (fDoTiming) timer.Start(true);
417 if (eta == AliESDFMD::kInvalidEta || fRecalculateEta)
418 eta = AliForwardUtil::GetEtaFromStrip(d,r,s,t,ip.Z());
419 if (fDoTiming) reEtaTime += timer.CpuTime();
420 etaCache[s*nt+t] = eta;
422 // --- Check this strip ------------------------------------
423 rh->fTotal->Fill(eta);
424 if (mult == AliESDFMD::kInvalidMult) { // || mult > 20) {
425 // Do not count invalid stuff
426 rh->fELoss->Fill(-1);
427 // rh->fEvsN->Fill(mult,-1);
428 // rh->fEvsM->Fill(mult,-1);
432 AliWarningF("Raw multiplicity of FMD%d%c[%02d,%03d] = %f > 20",
434 // --- Automatic calculation of acceptance -----------------
435 rh->fGood->Fill(eta);
437 // --- If we asked to re-calculate phi for (x,y) IP --------
438 if (fDoTiming) timer.Start(true);
439 if (fRecalculatePhi) {
441 phi = AliForwardUtil::GetPhiFromStrip(r, t, phi, ip.X(), ip.Y());
443 phiCache[s*nt+t] = phi;
444 if (fDoTiming) rePhiTime += timer.CpuTime();
446 // --- Apply phi corner correction to eloss ----------------
447 if (fUsePhiAcceptance == kPhiCorrectELoss)
448 mult *= AcceptanceCorrection(r,t);
450 // --- Get the low multiplicity cut ------------------------
452 if (eta != AliESDFMD::kInvalidEta) cut = GetMultCut(d, r, eta,false);
453 else AliWarningF("Eta for FMD%d%c[%02d,%03d] is invalid: %f",
456 // --- Now caluculate Nch for this strip using fits --------
457 if (fDoTiming) timer.Start(true);
459 if (cut > 0 && mult > cut) n = NParticles(mult,d,r,eta,lowFlux);
460 rh->fELoss->Fill(mult);
461 // rh->fEvsN->Fill(mult,n);
462 // rh->fEtaVsN->Fill(eta, n);
463 if (fDoTiming) nPartTime += timer.CpuTime();
465 // --- Calculate correction if needed ----------------------
466 if (fDoTiming) timer.Start(true);
467 // Temporary stuff - remove Correction call
469 if (fUsePhiAcceptance == kPhiCorrectNch)
470 c = AcceptanceCorrection(r,t);
471 // Double_t c = Correction(d,r,t,eta,lowFlux);
472 if (fDoTiming) corrTime += timer.CpuTime();
473 fCorrections->Fill(c);
475 // rh->fEvsM->Fill(mult,n);
476 // rh->fEtaVsM->Fill(eta, n);
477 rh->fCorr->Fill(eta, c);
479 // --- Accumulate Poisson statistics -----------------------
480 Bool_t hit = (n > 0.9 && c > 0);
482 rh->fELossUsed->Fill(mult);
483 if (fRecalculatePhi) {
484 rh->fPhiBefore->Fill(oldPhi);
485 rh->fPhiAfter->Fill(phi);
488 rh->fPoisson.Fill(t,s,hit,1./c);
491 // --- If we use ELoss fits, apply now ---------------------
492 if (!fUsePoisson) rh->fDensity->Fill(eta,phi,n);
496 // --- Automatic acceptance - Calculate as an efficiency -------
497 // This is very fast, so we do not bother to time it
498 rh->fGood->Divide(rh->fGood, rh->fTotal, 1, 1, "B");
500 // --- Make a copy and reset as needed -------------------------
501 if (fDoTiming) timer.Start(true);
502 TH2D* hclone = fCache.Get(d,r);
504 // TH2D* hclone = static_cast<TH2D*>(h->Clone("hclone"));
505 if (!fUsePoisson) hclone->Reset();
507 for (Int_t i = 0; i <= h->GetNbinsX()+1; i++) {
508 for (Int_t j = 0; j <= h->GetNbinsY()+1; j++) {
509 hclone->SetBinContent(i,j,h->GetBinContent(i,j));
510 hclone->SetBinError(i,j,h->GetBinError(i,j));
516 if (fDoTiming) copyTime += timer.CpuTime();
518 // --- Store Poisson result ------------------------------------
519 if (fDoTiming) timer.Start(true);
520 TH2D* poisson = rh->fPoisson.Result();
521 for (Int_t t=0; t < poisson->GetNbinsX(); t++) {
522 for (Int_t s=0; s < poisson->GetNbinsY(); s++) {
524 Double_t poissonV = poisson->GetBinContent(t+1,s+1);
525 // Use cached eta - since the calls to GetEtaFromStrip and
526 // GetPhiFromStrip are _very_ expensive
527 Double_t phi = phiCache[s*nt+t];
528 Double_t eta = etaCache[s*nt+t];
529 // Double_t phi = fmd.Phi(d,r,s,t) * TMath::DegToRad();
530 // Double_t eta = fmd.Eta(d,r,s,t);
531 // if (fRecalculateEta)
532 // eta = AliForwardUtil::GetEtaFromStrip(d,r,s,t,ip.Z());
533 // if (fRecalculatePhi)
534 // phi = AliForwardUtil::GetPhiFromStrip(r, t, phi, ip.X(), ip.Y());
536 h->Fill(eta,phi,poissonV);
537 rh->fDensity->Fill(eta, phi, poissonV);
540 hclone->Fill(eta,phi,poissonV);
543 if (fDoTiming) poissonTime += timer.CpuTime();
545 // --- Make diagnostics - eloss vs poisson ---------------------
546 if (fDoTiming) timer.Start(true);
547 Int_t nY = h->GetNbinsY();
548 Int_t nIn = 0; // Count non-outliers
549 Int_t nOut = 0; // Count outliers
550 for (Int_t ieta=1; ieta <= h->GetNbinsX(); ieta++) {
551 // Set the overflow bin to contain the phi acceptance
552 Double_t phiAcc = rh->fGood->GetBinContent(ieta);
553 Double_t phiAccE = rh->fGood->GetBinError(ieta);
554 h->SetBinContent(ieta, nY+1, phiAcc);
555 h->SetBinError(ieta, nY+1, phiAccE);
556 Double_t eta = h->GetXaxis()->GetBinCenter(ieta);
557 rh->fPhiAcc->Fill(eta, ip.Z(), phiAcc);
558 for (Int_t iphi=1; iphi<= nY; iphi++) {
560 Double_t poissonV = 0; //h->GetBinContent(,s+1);
563 poissonV = h->GetBinContent(ieta,iphi);
564 eLossV = hclone->GetBinContent(ieta,iphi);
567 poissonV = hclone->GetBinContent(ieta,iphi);
568 eLossV = h->GetBinContent(ieta,iphi);
571 if (poissonV < 1e-12 && eLossV < 1e-12)
572 // we do not care about trivially empty bins
575 Bool_t outlier = CheckOutlier(eLossV, poissonV, fOutlierCut);
576 Double_t rel = eLossV < 1e-12 ? 0 : (poissonV - eLossV) / eLossV;
578 rh->fELossVsPoissonOut->Fill(eLossV, poissonV);
579 rh->fDiffELossPoissonOut->Fill(rel);
583 rh->fELossVsPoisson->Fill(eLossV, poissonV);
584 rh->fDiffELossPoisson->Fill(rel);
589 Double_t outRatio = Double_t(nOut) / (nIn+nOut);
590 rh->fOutliers->Fill(outRatio);
591 if (outRatio < fMaxOutliers) rh->fPoisson.FillDiagnostics();
592 else h->SetBit(AliForwardUtil::kSkipRing);
593 if (fDoTiming) diagTime += timer.CpuTime();
600 fHTiming->Fill(1,reEtaTime);
601 fHTiming->Fill(2,nPartTime);
602 fHTiming->Fill(3,corrTime);
603 fHTiming->Fill(4,rePhiTime);
604 fHTiming->Fill(5,copyTime);
605 fHTiming->Fill(6,poissonTime);
606 fHTiming->Fill(7,diagTime);
607 fHTiming->Fill(8,totalT.CpuTime());
613 //_____________________________________________________________________
615 AliFMDDensityCalculator::CheckOutlier(Double_t eloss,
619 if (eloss < 1e-6) return true;
620 Double_t diff = TMath::Abs(poisson - eloss) / eloss;
623 //_____________________________________________________________________
625 AliFMDDensityCalculator::FindMaxWeight(const AliFMDCorrELossFit* cor,
626 UShort_t d, Char_t r, Int_t iEta) const
629 // Find the max weight to use for FMD<i>dr</i> in eta bin @a iEta
637 DGUARD(fDebug, 10, "Find maximum weight in FMD density calculator");
640 AliFMDCorrELossFit::ELossFit* fit = cor->FindFit(d,r,iEta, -1);
642 // AliWarning(Form("No energy loss fit for FMD%d%c at eta=%f", d, r, eta));
645 return fit->FindMaxWeight(2*AliFMDCorrELossFit::ELossFit::fgMaxRelError,
646 AliFMDCorrELossFit::ELossFit::fgLeastWeight,
650 //_____________________________________________________________________
652 AliFMDDensityCalculator::CacheMaxWeights(const TAxis& axis)
655 // Find the max weights and cache them
657 DGUARD(fDebug, 2, "Cache maximum weights in FMD density calculator");
658 AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
659 const AliFMDCorrELossFit* cor = fcm.GetELossFit();
660 cor->CacheBins(fMinQuality);
662 TAxis eta(axis.GetNbins(),
667 eta.Set(cor->GetEtaAxis().GetNbins(),
668 cor->GetEtaAxis().GetXmin(),
669 cor->GetEtaAxis().GetXmax());
671 Int_t nEta = eta.GetNbins();
678 fMaxWeights->SetBins(nEta, eta.GetXmin(), eta.GetXmax(), 5, .5, 5.5);
679 fMaxWeights->GetYaxis()->SetBinLabel(1, "FMD1i");
680 fMaxWeights->GetYaxis()->SetBinLabel(2, "FMD2i");
681 fMaxWeights->GetYaxis()->SetBinLabel(3, "FMD2o");
682 fMaxWeights->GetYaxis()->SetBinLabel(4, "FMD3i");
683 fMaxWeights->GetYaxis()->SetBinLabel(5, "FMD3o");
685 AliInfo(Form("Get eta axis with %d bins from %f to %f",
686 nEta, eta.GetXmin(), eta.GetXmax()));
687 fLowCuts->SetBins(nEta, eta.GetXmin(), eta.GetXmax(), 5, .5, 5.5);
688 fLowCuts->GetYaxis()->SetBinLabel(1, "FMD1i");
689 fLowCuts->GetYaxis()->SetBinLabel(2, "FMD2i");
690 fLowCuts->GetYaxis()->SetBinLabel(3, "FMD2o");
691 fLowCuts->GetYaxis()->SetBinLabel(4, "FMD3i");
692 fLowCuts->GetYaxis()->SetBinLabel(5, "FMD3o");
694 for (Int_t i = 0; i < nEta; i++) {
696 w[0] = fFMD1iMax[i] = FindMaxWeight(cor, 1, 'I', i+1);
697 w[1] = fFMD2iMax[i] = FindMaxWeight(cor, 2, 'I', i+1);
698 w[2] = fFMD2oMax[i] = FindMaxWeight(cor, 2, 'O', i+1);
699 w[3] = fFMD3iMax[i] = FindMaxWeight(cor, 3, 'I', i+1);
700 w[4] = fFMD3oMax[i] = FindMaxWeight(cor, 3, 'O', i+1);
702 l[0] = GetMultCut(1, 'I', i+1, false);
703 l[1] = GetMultCut(2, 'I', i+1, false);
704 l[2] = GetMultCut(2, 'O', i+1, false);
705 l[3] = GetMultCut(3, 'I', i+1, false);
706 l[4] = GetMultCut(3, 'O', i+1, false);
707 for (Int_t j = 0; j < 5; j++) {
708 if (w[j] > 0) fMaxWeights->SetBinContent(i+1, j+1, w[j]);
709 if (l[j] > 0) fLowCuts->SetBinContent(i+1, j+1, l[j]);
714 //_____________________________________________________________________
716 AliFMDDensityCalculator::GetMaxWeight(UShort_t d, Char_t r, Int_t iEta) const
719 // Find the (cached) maximum weight for FMD<i>dr</i> in
720 // @f$\eta@f$ bin @a iEta
728 // max weight or <= 0 in case of problems
730 if (iEta < 0) return -1;
732 const TArrayI* max = 0;
734 case 1: max = &fFMD1iMax; break;
735 case 2: max = (r == 'I' || r == 'i' ? &fFMD2iMax : &fFMD2oMax); break;
736 case 3: max = (r == 'I' || r == 'i' ? &fFMD3iMax : &fFMD3oMax); break;
739 AliWarning(Form("No array for FMD%d%c", d, r));
743 if (iEta >= max->fN) {
744 AliWarning(Form("Eta bin %3d out of bounds [0,%d]",
749 AliDebug(30,Form("Max weight for FMD%d%c eta bin %3d: %d", d, r, iEta,
751 return max->At(iEta);
754 //_____________________________________________________________________
756 AliFMDDensityCalculator::GetMaxWeight(UShort_t d, Char_t r, Float_t eta) const
759 // Find the (cached) maximum weight for FMD<i>dr</i> iat
768 // max weight or <= 0 in case of problems
770 AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
771 Int_t iEta = fcm.GetELossFit()->FindEtaBin(eta) -1;
773 return GetMaxWeight(d, r, iEta);
776 //_____________________________________________________________________
778 AliFMDDensityCalculator::NParticles(Float_t mult,
782 Bool_t lowFlux) const
785 // Get the number of particles corresponding to the signal mult
792 // t Strip (not used)
794 // eta Pseudo-rapidity
795 // lowFlux Low-flux flag
798 // The number of particles
800 // if (mult <= GetMultCut()) return 0;
801 DGUARD(fDebug, 3, "Calculate Nch in FMD density calculator");
802 if (lowFlux) return 1;
804 AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
805 AliFMDCorrELossFit::ELossFit* fit = fcm.GetELossFit()->FindFit(d,r,eta, -1);
807 AliWarning(Form("No energy loss fit for FMD%d%c at eta=%f qual=%d",
808 d, r, eta, fMinQuality));
812 Int_t m = GetMaxWeight(d,r,eta); // fit->FindMaxWeight();
814 AliWarning(Form("No good fits for FMD%d%c at eta=%f", d, r, eta));
818 UShort_t n = TMath::Min(fMaxParticles, UShort_t(m));
819 Double_t ret = fit->EvaluateWeighted(mult, n);
822 AliInfo(Form("FMD%d%c, eta=%7.4f, %8.5f -> %8.5f", d, r, eta, mult, ret));
825 fWeightedSum->Fill(ret);
826 fSumOfWeights->Fill(ret);
831 //_____________________________________________________________________
833 AliFMDDensityCalculator::Correction(UShort_t d,
837 Bool_t lowFlux) const
840 // Get the inverse correction factor. This consist of
842 // - acceptance correction (corners of sensors)
843 // - double hit correction (for low-flux events)
844 // - dead strip correction
850 // t Strip (not used)
852 // eta Pseudo-rapidity
853 // lowFlux Low-flux flag
858 DGUARD(fDebug, 10, "Apply correction in FMD density calculator");
859 Float_t correction = 1;
860 if (fUsePhiAcceptance == kPhiCorrectNch)
861 correction = AcceptanceCorrection(r,t);
863 AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
866 if (fcm.GetDoubleHit())
867 dblHitCor = fcm.GetDoubleHit()->GetCorrection(d,r);
870 Double_t dblC = dblHitCor->GetBinContent(dblHitCor->FindBin(eta));
871 if (dblC > 0) correction *= dblC;
874 // AliWarning(Form("Missing double hit correction for FMD%d%c",d,r));
880 //_____________________________________________________________________
882 AliFMDDensityCalculator::GenerateAcceptanceCorrection(Char_t r) const
885 // Generate the acceptance corrections
888 // r Ring to generate for
891 // Newly allocated histogram of acceptance corrections
893 DGUARD(fDebug, 3, "Make acceptance correction in FMD density calculator");
894 const Double_t ic1[] = { 4.9895, 15.3560 };
895 const Double_t ic2[] = { 1.8007, 17.2000 };
896 const Double_t oc1[] = { 4.2231, 26.6638 };
897 const Double_t oc2[] = { 1.8357, 27.9500 };
898 const Double_t* c1 = (r == 'I' || r == 'i' ? ic1 : oc1);
899 const Double_t* c2 = (r == 'I' || r == 'i' ? ic2 : oc2);
900 Double_t minR = (r == 'I' || r == 'i' ? 4.5213 : 15.4);
901 Double_t maxR = (r == 'I' || r == 'i' ? 17.2 : 28.0);
902 Int_t nStrips = (r == 'I' || r == 'i' ? 512 : 256);
903 Int_t nSec = (r == 'I' || r == 'i' ? 20 : 40);
904 Float_t basearc = 2 * TMath::Pi() / nSec;
905 Double_t rad = maxR - minR;
906 Float_t segment = rad / nStrips;
907 Float_t cr = TMath::Sqrt(c1[0]*c1[0]+c1[1]*c1[1]);
909 // Numbers used to find end-point of strip.
910 // (See http://mathworld.wolfram.com/Circle-LineIntersection.html)
911 Float_t D = c1[0] * c2[1] - c1[1] * c2[0];
912 Float_t dx = c2[0] - c1[0];
913 Float_t dy = c2[1] - c1[1];
914 Float_t dr = TMath::Sqrt(dx*dx+dy*dy);
916 TH1D* ret = new TH1D(Form("acc%c", r),
917 Form("Acceptance correction for FMDx%c", r),
918 nStrips, -.5, nStrips-.5);
919 ret->SetXTitle("Strip");
920 ret->SetYTitle("#varphi acceptance");
921 ret->SetDirectory(0);
922 ret->SetFillColor(r == 'I' || r == 'i' ? kRed+1 : kBlue+1);
923 ret->SetFillStyle(3001);
925 for (Int_t t = 0; t < nStrips; t++) {
926 Float_t radius = minR + t * segment;
928 // If the radius of the strip is smaller than the radius corresponding
929 // to the first corner we have a full strip length
931 ret->SetBinContent(t+1, 1);
935 // Next, we should find the end-point of the strip - that is,
936 // the coordinates where the line from c1 to c2 intersects a circle
937 // with radius given by the strip.
938 // (See http://mathworld.wolfram.com/Circle-LineIntersection.html)
939 // Calculate the determinant
940 Float_t det = radius * radius * dr * dr - D*D;
943 // <0 means No intersection
944 // =0 means Exactly tangent
945 ret->SetBinContent(t+1, 1);
949 // Calculate end-point and the corresponding opening angle
950 Float_t x = (+D * dy + dx * TMath::Sqrt(det)) / dr / dr;
951 Float_t y = (-D * dx + dy * TMath::Sqrt(det)) / dr / dr;
952 Float_t th = TMath::ATan2(x, y);
954 ret->SetBinContent(t+1, th / basearc);
959 //_____________________________________________________________________
961 AliFMDDensityCalculator::AcceptanceCorrection(Char_t r, UShort_t t) const
964 // Get the acceptance correction for strip @a t in an ring of type @a r
967 // r Ring type ('I' or 'O')
971 // Inverse acceptance correction
973 TH1D* acc = (r == 'I' || r == 'i' ? fAccI : fAccO);
974 return acc->GetBinContent(t+1);
977 //____________________________________________________________________
979 AliFMDDensityCalculator::Terminate(const TList* dir, TList* output,
983 // Scale the histograms to the total number of events
986 // dir where to put the output
987 // nEvents Number of events
989 DGUARD(fDebug, 1, "Scale histograms in FMD density calculator");
990 if (nEvents <= 0) return;
991 TList* d = static_cast<TList*>(dir->FindObject(GetName()));
994 TList* out = new TList;
995 out->SetName(d->GetName());
998 TIter next(&fRingHistos);
1000 THStack* sums = new THStack("sums", "sums of ring signals");
1001 while ((o = static_cast<RingHistos*>(next()))) {
1002 o->Terminate(d, nEvents);
1004 Warning("Terminate", "No density in %s", o->GetName());
1007 TH1D* sum = o->fDensity->ProjectionX(o->GetName(), 1,
1008 o->fDensity->GetNbinsY(),"e");
1009 sum->Scale(1., "width");
1010 sum->SetTitle(o->GetName());
1011 sum->SetDirectory(0);
1012 sum->SetYTitle("#sum N_{ch,incl}");
1019 //____________________________________________________________________
1021 AliFMDDensityCalculator::CreateOutputObjects(TList* dir)
1024 // Output diagnostic histograms to directory
1027 // dir List to write in
1029 DGUARD(fDebug, 1, "Define output FMD density calculator");
1030 TList* d = new TList;
1032 d->SetName(GetName());
1034 d->Add(fWeightedSum);
1035 d->Add(fSumOfWeights);
1036 d->Add(fCorrections);
1039 d->Add(fMaxWeights);
1042 TParameter<int>* nFiles = new TParameter<int>("nFiles", 1);
1043 nFiles->SetMergeMode('+');
1046 d->Add(AliForwardUtil::MakeParameter("maxParticle", fMaxParticles));
1047 d->Add(AliForwardUtil::MakeParameter("method", fUsePoisson));
1048 d->Add(AliForwardUtil::MakeParameter("phiAcceptance",fUsePhiAcceptance));
1049 d->Add(AliForwardUtil::MakeParameter("etaLumping", fEtaLumping));
1050 d->Add(AliForwardUtil::MakeParameter("phiLumping", fPhiLumping));
1051 d->Add(AliForwardUtil::MakeParameter("recalcEta", fRecalculateEta));
1052 d->Add(AliForwardUtil::MakeParameter("recalcPhi", fRecalculatePhi));
1053 d->Add(AliForwardUtil::MakeParameter("maxOutliers", fMaxOutliers));
1054 d->Add(AliForwardUtil::MakeParameter("outlierCut", fOutlierCut));
1057 fCuts.Output(d,"lCuts");
1059 TIter next(&fRingHistos);
1061 while ((o = static_cast<RingHistos*>(next()))) {
1062 o->fPoisson.SetLumping(fEtaLumping, fPhiLumping);
1063 o->CreateOutputObjects(d);
1066 if (!fDoTiming) return;
1068 fHTiming = new TProfile("timing", "#LTt_{part}#GT", 8, .5, 8.5);
1069 fHTiming->SetDirectory(0);
1070 fHTiming->SetYTitle("#LTt_{part}#GT");
1071 fHTiming->SetXTitle("Part");
1072 fHTiming->SetFillColor(kRed+1);
1073 fHTiming->SetFillStyle(3001);
1074 fHTiming->SetMarkerStyle(20);
1075 fHTiming->SetMarkerColor(kBlack);
1076 fHTiming->SetLineColor(kBlack);
1077 fHTiming->SetStats(0);
1078 TAxis* xaxis = fHTiming->GetXaxis();
1079 xaxis->SetBinLabel(1, "Re-calculation of #eta");
1080 xaxis->SetBinLabel(2, "N_{particle}");
1081 xaxis->SetBinLabel(3, "Correction");
1082 xaxis->SetBinLabel(4, "Re-calculation of #phi");
1083 xaxis->SetBinLabel(5, "Copy to cache");
1084 xaxis->SetBinLabel(6, "Poisson calculation");
1085 xaxis->SetBinLabel(7, "Diagnostics");
1086 xaxis->SetBinLabel(8, "Total");
1089 #define PF(N,V,...) \
1090 AliForwardUtil::PrintField(N,V, ## __VA_ARGS__)
1091 #define PFB(N,FLAG) \
1093 AliForwardUtil::PrintName(N); \
1094 std::cout << std::boolalpha << (FLAG) << std::noboolalpha << std::endl; \
1096 #define PFV(N,VALUE) \
1098 AliForwardUtil::PrintName(N); \
1099 std::cout << (VALUE) << std::endl; } while(false)
1101 //____________________________________________________________________
1103 AliFMDDensityCalculator::Print(Option_t* option) const
1106 // Print information
1111 AliForwardUtil::PrintTask(*this);
1112 gROOT->IncreaseDirLevel();
1114 TString phiM("none");
1115 switch (fUsePhiAcceptance) {
1116 case kPhiNoCorrect: phiM = "none"; break;
1117 case kPhiCorrectNch: phiM = "correct Nch"; break;
1118 case kPhiCorrectELoss: phiM = "correct energy loss"; break;
1121 PFV("Max(particles)", fMaxParticles );
1122 PFV("Poisson method", fUsePoisson );
1123 PFV("Eta lumping", fEtaLumping );
1124 PFV("Phi lumping", fPhiLumping );
1125 PFV("Recalculate eta", fRecalculateEta );
1126 PFV("Recalculate phi", fRecalculatePhi );
1127 PFV("Use phi acceptance", phiM);
1128 PFV("Lower cut", "");
1131 TString opt(option);
1133 if (!opt.Contains("nomax")) {
1134 PFV("Max weights", "");
1137 for (Int_t i = 0; i < gROOT->GetDirLevel(); i++) ind[i] = ' ';
1138 ind[gROOT->GetDirLevel()] = '\0';
1139 for (UShort_t d=1; d<=3; d++) {
1140 UShort_t nr = (d == 1 ? 1 : 2);
1141 for (UShort_t q=0; q<nr; q++) {
1142 ind[gROOT->GetDirLevel()] = ' ';
1143 ind[gROOT->GetDirLevel()+1] = '\0';
1144 Char_t r = (q == 0 ? 'I' : 'O');
1145 std::cout << ind << " FMD" << d << r << ":";
1146 ind[gROOT->GetDirLevel()+1] = ' ';
1147 ind[gROOT->GetDirLevel()+2] = '\0';
1149 const TArrayI& a = (d == 1 ? fFMD1iMax :
1150 (d == 2 ? (r == 'I' ? fFMD2iMax : fFMD2oMax) :
1151 (r == 'I' ? fFMD3iMax : fFMD3oMax)));
1153 for (Int_t i = 0; i < a.fN; i++) {
1154 if (a.fArray[i] < 1) continue;
1155 if (j % 6 == 0) std::cout << "\n " << ind;
1157 std::cout << " " << std::setw(3) << i << ": " << a.fArray[i];
1159 std::cout << std::endl;
1163 gROOT->DecreaseDirLevel();
1166 //====================================================================
1167 AliFMDDensityCalculator::RingHistos::RingHistos()
1168 : AliForwardUtil::RingHistos(),
1177 fDiffELossPoisson(0),
1178 fELossVsPoissonOut(0),
1179 fDiffELossPoissonOut(0),
1196 //____________________________________________________________________
1197 AliFMDDensityCalculator::RingHistos::RingHistos(UShort_t d, Char_t r)
1198 : AliForwardUtil::RingHistos(d,r),
1207 fDiffELossPoisson(0),
1208 fELossVsPoissonOut(0),
1209 fDiffELossPoissonOut(0),
1211 fPoisson("ignored"),
1229 fEvsN = new TH2D("elossVsNnocorr",
1230 "#Delta E/#Delta E_{mip} vs uncorrected inclusive N_{ch}",
1231 250, -.5, 24.5, 251, -1.5, 24.5);
1232 fEvsN->SetXTitle("#Delta E/#Delta E_{mip}");
1233 fEvsN->SetYTitle("Inclusive N_{ch} (uncorrected)");
1235 fEvsN->SetDirectory(0);
1237 fEvsM = static_cast<TH2D*>(fEvsN->Clone("elossVsNcorr"));
1238 fEvsM->SetTitle("#Delta E/#Delta E_{mip} vs corrected inclusive N_{ch}");
1239 fEvsM->SetDirectory(0);
1241 fEtaVsN = new TProfile("etaVsNnocorr",
1242 "Average inclusive N_{ch} vs #eta (uncorrected)",
1244 fEtaVsN->SetXTitle("#eta");
1245 fEtaVsN->SetYTitle("#LT N_{ch,incl}#GT (uncorrected)");
1246 fEtaVsN->SetDirectory(0);
1247 fEtaVsN->SetLineColor(Color());
1248 fEtaVsN->SetFillColor(Color());
1250 fEtaVsM = static_cast<TProfile*>(fEtaVsN->Clone("etaVsNcorr"));
1251 fEtaVsM->SetTitle("Average inclusive N_{ch} vs #eta (corrected)");
1252 fEtaVsM->SetYTitle("#LT N_{ch,incl}#GT (corrected)");
1253 fEtaVsM->SetDirectory(0);
1256 fCorr = new TProfile("corr", "Average correction", 200, -4, 6);
1257 fCorr->SetXTitle("#eta");
1258 fCorr->SetYTitle("#LT correction#GT");
1259 fCorr->SetDirectory(0);
1260 fCorr->SetLineColor(Color());
1261 fCorr->SetFillColor(Color());
1263 fDensity = new TH2D("inclDensity", "Inclusive N_{ch} density",
1264 200, -4, 6, (r == 'I' || r == 'i' ? 20 : 40),
1266 fDensity->SetDirectory(0);
1267 fDensity->Sumw2(); fDensity->SetMarkerColor(Color());
1268 fDensity->SetXTitle("#eta");
1269 fDensity->SetYTitle("#phi [radians]");
1270 fDensity->SetZTitle("Inclusive N_{ch} density");
1272 // --- Create increasing sized bins --------------------------------
1274 // bins, lowest order, higest order, return array
1275 const char* nchP = "N_{ch}^{Poisson}";
1276 const char* nchE = "N_{ch}^{#Delta}";
1277 AliForwardUtil::MakeLogScale(300, 0, 2, bins);
1278 fELossVsPoisson = new TH2D("elossVsPoisson",
1279 "N_{ch} from energy loss vs from Poisson",
1280 bins.GetSize()-1, bins.GetArray(),
1281 bins.GetSize()-1, bins.GetArray());
1282 fELossVsPoisson->SetDirectory(0);
1283 fELossVsPoisson->SetXTitle(nchE);
1284 fELossVsPoisson->SetYTitle(nchP);
1285 fELossVsPoisson->SetZTitle("Correlation");
1286 fELossVsPoissonOut =
1287 static_cast<TH2D*>(fELossVsPoisson
1288 ->Clone(Form("%sOutlier",
1289 fELossVsPoisson->GetName())));
1290 fELossVsPoissonOut->SetDirectory(0);
1291 fELossVsPoissonOut->SetMarkerStyle(20);
1292 fELossVsPoissonOut->SetMarkerSize(0.3);
1293 fELossVsPoissonOut->SetMarkerColor(kBlack);
1294 fELossVsPoissonOut->SetTitle(Form("%s for outliers",
1295 fELossVsPoisson->GetTitle()));
1297 fDiffELossPoisson = new TH1D("diffElossPoisson",
1298 Form("(%s-%s)/%s", nchP, nchE, nchE),
1300 fDiffELossPoisson->SetDirectory(0);
1301 fDiffELossPoisson->SetXTitle(fDiffELossPoisson->GetTitle());
1302 fDiffELossPoisson->SetYTitle("Frequency");
1303 fDiffELossPoisson->SetMarkerColor(Color());
1304 fDiffELossPoisson->SetFillColor(Color());
1305 fDiffELossPoisson->SetFillStyle(3001);
1306 fDiffELossPoisson->Sumw2();
1308 fDiffELossPoissonOut =
1309 static_cast<TH1D*>(fDiffELossPoisson
1310 ->Clone(Form("%sOutlier",fDiffELossPoisson->GetName())));
1311 fDiffELossPoissonOut->SetDirectory(0);
1312 fDiffELossPoissonOut->SetTitle(Form("%s for outliers",
1313 fDiffELossPoisson->GetTitle()));
1314 fDiffELossPoissonOut->SetMarkerColor(Color()-2);
1315 fDiffELossPoissonOut->SetFillColor(Color()-2);
1316 fDiffELossPoissonOut->SetFillStyle(3002);
1318 fOutliers = new TH1D("outliers", "Fraction of outliers", 100, 0, 1);
1319 fOutliers->SetDirectory(0);
1320 fOutliers->SetXTitle("N_{outlier}/(N_{outlier}+N_{inside})");
1321 fOutliers->SetYTitle("#sum_{events}#sum_{bins}");
1322 fOutliers->SetFillColor(Color());
1323 fOutliers->SetFillStyle(3001);
1324 fOutliers->SetLineColor(kBlack);
1326 fELoss = new TH1D("eloss", "#Delta/#Delta_{mip} in all strips",
1328 fELoss->SetXTitle("#Delta/#Delta_{mip} (selected)");
1329 fELoss->SetYTitle("P(#Delta/#Delta_{mip})");
1330 fELoss->SetFillColor(Color()-2);
1331 fELoss->SetFillStyle(3003);
1332 fELoss->SetLineColor(kBlack);
1333 fELoss->SetLineStyle(2);
1334 fELoss->SetLineWidth(1);
1335 fELoss->SetDirectory(0);
1337 fELossUsed = static_cast<TH1D*>(fELoss->Clone("elossUsed"));
1338 fELossUsed->SetTitle("#Delta/#Delta_{mip} in used strips");
1339 fELossUsed->SetFillStyle(3002);
1340 fELossUsed->SetLineStyle(1);
1341 fELossUsed->SetDirectory(0);
1343 fPhiBefore = new TH1D("phiBefore", "#phi distribution (before recalc)",
1344 (r == 'I' || r == 'i' ? 20 : 40), 0, 2*TMath::Pi());
1345 fPhiBefore->SetDirectory(0);
1346 fPhiBefore->SetXTitle("#phi");
1347 fPhiBefore->SetYTitle("Events");
1348 fPhiBefore->SetMarkerColor(Color());
1349 fPhiBefore->SetLineColor(Color());
1350 fPhiBefore->SetFillColor(Color());
1351 fPhiBefore->SetFillStyle(3001);
1352 fPhiBefore->SetMarkerStyle(20);
1354 fPhiAfter = static_cast<TH1D*>(fPhiBefore->Clone("phiAfter"));
1355 fPhiAfter->SetTitle("#phi distribution (after re-calc)");
1356 fPhiAfter->SetDirectory(0);
1359 //____________________________________________________________________
1360 AliFMDDensityCalculator::RingHistos::RingHistos(const RingHistos& o)
1361 : AliForwardUtil::RingHistos(o),
1365 // fEtaVsN(o.fEtaVsN),
1366 // fEtaVsM(o.fEtaVsM),
1368 fDensity(o.fDensity),
1369 fELossVsPoisson(o.fELossVsPoisson),
1370 fDiffELossPoisson(o.fDiffELossPoisson),
1371 fELossVsPoissonOut(o.fELossVsPoissonOut),
1372 fDiffELossPoissonOut(o.fDiffELossPoissonOut),
1373 fOutliers(o.fOutliers),
1374 fPoisson(o.fPoisson),
1376 fELossUsed(o.fELossUsed),
1377 fMultCut(o.fMultCut),
1381 fPhiBefore(o.fPhiBefore),
1382 fPhiAfter(o.fPhiAfter)
1388 // o Object to copy from
1392 //____________________________________________________________________
1393 AliFMDDensityCalculator::RingHistos&
1394 AliFMDDensityCalculator::RingHistos::operator=(const RingHistos& o)
1397 // Assignment operator
1400 // o Object to assign from
1403 // Reference to this
1405 if (&o == this) return *this;
1406 AliForwardUtil::RingHistos::operator=(o);
1408 // if (fEvsN) delete fEvsN;
1409 // if (fEvsM) delete fEvsM;
1410 // if (fEtaVsN) delete fEtaVsN;
1411 // if (fEtaVsM) delete fEtaVsM;
1412 if (fCorr) delete fCorr;
1413 if (fDensity) delete fDensity;
1414 if (fELossVsPoisson) delete fELossVsPoisson;
1415 if (fDiffELossPoisson) delete fDiffELossPoisson;
1416 if (fTotal) delete fTotal;
1417 if (fGood) delete fGood;
1418 if (fPhiAcc) delete fPhiAcc;
1419 if (fPhiBefore) delete fPhiBefore;
1420 if (fPhiAfter) delete fPhiAfter;
1422 // fEvsN = static_cast<TH2D*>(o.fEvsN->Clone());
1423 // fEvsM = static_cast<TH2D*>(o.fEvsM->Clone());
1424 // fEtaVsN = static_cast<TProfile*>(o.fEtaVsN->Clone());
1425 // fEtaVsM = static_cast<TProfile*>(o.fEtaVsM->Clone());
1426 fCorr = static_cast<TProfile*>(o.fCorr->Clone());
1427 fDensity = static_cast<TH2D*>(o.fDensity->Clone());
1428 fELossVsPoisson = static_cast<TH2D*>(o.fELossVsPoisson->Clone());
1429 fDiffELossPoisson = static_cast<TH1D*>(o.fDiffELossPoisson->Clone());
1430 fELossVsPoissonOut = static_cast<TH2D*>(o.fELossVsPoisson->Clone());
1431 fDiffELossPoissonOut = static_cast<TH1D*>(o.fDiffELossPoisson->Clone());
1432 fOutliers = static_cast<TH1D*>(o.fOutliers->Clone());
1433 fPoisson = o.fPoisson;
1434 fELoss = static_cast<TH1D*>(o.fELoss->Clone());
1435 fELossUsed = static_cast<TH1D*>(o.fELossUsed->Clone());
1436 fTotal = static_cast<TH1D*>(o.fTotal->Clone());
1437 fGood = static_cast<TH1D*>(o.fGood->Clone());
1438 fPhiAcc = static_cast<TH2D*>(o.fPhiAcc->Clone());
1439 fPhiBefore = static_cast<TH1D*>(o.fPhiBefore->Clone());
1440 fPhiAfter = static_cast<TH1D*>(o.fPhiAfter->Clone());
1443 //____________________________________________________________________
1444 AliFMDDensityCalculator::RingHistos::~RingHistos()
1452 //____________________________________________________________________
1454 AliFMDDensityCalculator::RingHistos::SetupForData(const TAxis& eAxis)
1457 // This is called on first event
1458 fPoisson.Init(-1,-1);
1459 fTotal = new TH1D("total", "Total # of strips per #eta",
1460 eAxis.GetNbins(), eAxis.GetXmin(), eAxis.GetXmax());
1461 fTotal->SetDirectory(0);
1462 fTotal->SetXTitle("#eta");
1463 fTotal->SetYTitle("# of strips");
1464 fGood = static_cast<TH1D*>(fTotal->Clone("good"));
1465 fGood->SetTitle("# of good strips per #eta");
1466 fGood->SetDirectory(0);
1468 fPhiAcc = new TH2D("phiAcc", "#phi acceptance vs Ip_{z}",
1469 eAxis.GetNbins(), eAxis.GetXmin(), eAxis.GetXmax(),
1471 fPhiAcc->SetXTitle("#eta");
1472 fPhiAcc->SetYTitle("v_{z} [cm]");
1473 fPhiAcc->SetZTitle("#phi acceptance");
1474 fPhiAcc->SetDirectory(0);
1476 if (fList) fList->Add(fPhiAcc);
1479 //____________________________________________________________________
1481 AliFMDDensityCalculator::RingHistos::CreateOutputObjects(TList* dir)
1484 // Make output. This is called as part of SlaveBegin
1487 // dir Where to put it
1489 TList* d = DefineOutputList(dir);
1496 d->Add(fELossVsPoisson);
1497 d->Add(fELossVsPoissonOut);
1498 d->Add(fDiffELossPoisson);
1499 d->Add(fDiffELossPoissonOut);
1502 fPoisson.GetOccupancy()->SetFillColor(Color());
1503 fPoisson.GetMean()->SetFillColor(Color());
1504 fPoisson.GetOccupancy()->SetFillColor(Color());
1510 TAxis x(NStrip(), -.5, NStrip()-.5);
1511 TAxis y(NSector(), -.5, NSector()-.5);
1512 x.SetTitle("strip");
1513 y.SetTitle("sector");
1514 fPoisson.Define(x, y);
1516 d->Add(AliForwardUtil::MakeParameter("cut", fMultCut));
1520 //____________________________________________________________________
1522 AliFMDDensityCalculator::RingHistos::Terminate(TList* dir, Int_t nEvents)
1525 // Scale the histograms to the total number of events
1528 // dir Where the output is
1529 // nEvents Number of events
1531 TList* l = GetOutputList(dir);
1534 TH2D* density = static_cast<TH2D*>(GetOutputHist(l,"inclDensity"));
1535 if (density) density->Scale(1./nEvents);
1539 //____________________________________________________________________