2 // This class collects the event histograms into single histograms,
3 // one for each ring in each vertex bin.
6 // - AliESDFMD object possibly corrected for sharing
9 // - 5 RingHistos objects - each with a number of vertex dependent
10 // 2D histograms of the inclusive charge particle density
12 // HistCollector used:
13 // - AliFMDCorrSecondaryMap
15 #include "AliFMDHistCollector.h"
16 #include <AliESDFMD.h>
20 #include "AliForwardCorrectionManager.h"
25 #include <TProfile2D.h>
31 ClassImp(AliFMDHistCollector)
36 //____________________________________________________________________
37 AliFMDHistCollector::AliFMDHistCollector()
46 fMergeMethod(kStraightMean),
47 fFiducialMethod(kByCut),
52 //____________________________________________________________________
53 AliFMDHistCollector::AliFMDHistCollector(const char* title)
54 : TNamed("fmdHistCollector", title),
63 fMergeMethod(kStraightMean),
64 fFiducialMethod(kByCut),
69 //____________________________________________________________________
70 AliFMDHistCollector::AliFMDHistCollector(const AliFMDHistCollector& o)
72 fNCutBins(o.fNCutBins),
73 fCorrectionCut(o.fCorrectionCut),
74 fFirstBins(o.fFirstBins),
75 fLastBins(o.fLastBins),
78 fSumRings(o.fSumRings),
79 fCoverage(o.fCoverage),
80 fMergeMethod(o.fMergeMethod),
81 fFiducialMethod(o.fFiducialMethod),
82 fSkipFMDRings(o.fSkipFMDRings),
83 fBgAndHitMaps(o.fBgAndHitMaps)
86 //____________________________________________________________________
87 AliFMDHistCollector::~AliFMDHistCollector()
89 if (fList) delete fList;
91 //____________________________________________________________________
93 AliFMDHistCollector::operator=(const AliFMDHistCollector& o)
96 // Assignement operator
99 // o Object to assign from
102 // Reference to this object
104 if (&o == this) return *this;
105 TNamed::operator=(o);
107 fNCutBins = o.fNCutBins;
108 fCorrectionCut = o.fCorrectionCut;
109 fFirstBins = o.fFirstBins;
110 fLastBins = o.fLastBins;
113 fSumRings = o.fSumRings;
114 fCoverage = o.fCoverage;
115 fMergeMethod = o.fMergeMethod;
116 fFiducialMethod = o.fFiducialMethod;
117 fSkipFMDRings = o.fSkipFMDRings;
118 fBgAndHitMaps = o.fBgAndHitMaps;
123 //____________________________________________________________________
125 AliFMDHistCollector::Init(const TAxis& vtxAxis,
126 const TAxis& etaAxis)
132 // vtxAxis Vertex axis
135 AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
137 fSumRings = new TH2D("sumRings", "Sum in individual rings",
138 etaAxis.GetNbins(), etaAxis.GetXmin(), etaAxis.GetXmax(),
141 fSumRings->SetDirectory(0);
142 fSumRings->SetXTitle("#eta");
143 fSumRings->GetYaxis()->SetBinLabel(1,"FMD1i");
144 fSumRings->GetYaxis()->SetBinLabel(2,"FMD2i");
145 fSumRings->GetYaxis()->SetBinLabel(3,"FMD2o");
146 fSumRings->GetYaxis()->SetBinLabel(4,"FMD3i");
147 fSumRings->GetYaxis()->SetBinLabel(5,"FMD3o");
148 fList->Add(fSumRings);
150 fCoverage = new TH2D("coverage", "#eta coverage per v_{z}",
151 etaAxis.GetNbins(),etaAxis.GetXmin(),etaAxis.GetXmax(),
152 vtxAxis.GetNbins(),vtxAxis.GetXmin(),vtxAxis.GetXmax());
153 fCoverage->SetDirectory(0);
154 fCoverage->SetXTitle("#eta");
155 fCoverage->SetYTitle("v_{z} [cm]");
156 fCoverage->SetZTitle("n_{bins}");
157 fList->Add(fCoverage);
159 UShort_t nVz = vtxAxis.GetNbins();
160 fFirstBins.Set(5*nVz);
161 fLastBins.Set(5*nVz);
163 // Find the eta bin ranges
164 for (UShort_t iVz = 1; iVz <= nVz; iVz++) {
166 Double_t vMin = vtxAxis.GetBinLowEdge(iVz);
167 Double_t vMax = vtxAxis.GetBinUpEdge(iVz);
171 vtxList->SetName(Form("%c%02d_%c%02d",
172 vMin < 0 ? 'm' : 'p', int(TMath::Abs(vMin)),
173 vMax < 0 ? 'm' : 'p', int(TMath::Abs(vMax))));
176 // Find the first and last eta bin to use for each ring for
177 // each vertex bin. This is instead of using the methods
178 // provided by AliFMDAnaParameters
179 for (Int_t iIdx = 0; iIdx < 5; iIdx++) {
182 GetDetRing(iIdx, d, r);
184 // Skipping selected FMD rings
185 if(d==1 && r=='I' && (fSkipFMDRings & kFMD1I)) continue;
186 if(d==2 && r=='I' && (fSkipFMDRings & kFMD2I)) continue;
187 if(d==2 && r=='O' && (fSkipFMDRings & kFMD2O)) continue;
188 if(d==3 && r=='I' && (fSkipFMDRings & kFMD3I)) continue;
189 if(d==3 && r=='O' && (fSkipFMDRings & kFMD3O)) continue;
191 // Get the background object
192 // TH2F* bg = pars->GetBackgroundCorrection(d,r,iVz);
193 TH2D* bg = fcm.GetSecondaryMap()->GetCorrection(d,r,iVz);
194 Int_t nEta = bg->GetNbinsX();
195 Int_t first = nEta+1;
198 // Loop over the eta bins
199 for (Int_t ie = 1; ie <= nEta; ie++) {
200 // Loop over the phi bins to make sure that we
201 // do not have holes in the coverage
203 for (Int_t ip = 1; ip <= bg->GetNbinsY(); ip++) {
204 if (!CheckCorrection(bg, ie, ip)) {
211 first = TMath::Min(ie, first);
212 last = TMath::Max(ie, last);
215 // Store the result for later use
216 fFirstBins[(iVz-1)*5+iIdx] = first;
217 fLastBins[(iVz-1)*5+iIdx] = last;
220 obg = static_cast<TH2D*>(bg->Clone(Form("secMapFMD%d%c", d, r)));
221 obg->SetDirectory(0);
225 TH2D* hitmap = static_cast<TH2D*>(bg->Clone(Form("hitMapFMD%d%c", d, r)));
226 if(r == 'O') hitmap->RebinY(2);
227 hitmap->SetDirectory(0);
228 hitmap->GetZaxis()->SetTitle("");
230 vtxList->Add(hitmap);
232 // Fill diagnostics histograms
233 for (Int_t ie = first+fNCutBins; ie <= last-fNCutBins; ie++) {
234 Double_t old = fCoverage->GetBinContent(ie, iVz);
235 fCoverage->SetBinContent(ie, iVz, old+1);
237 for (Int_t ip = 1; ip <= bg->GetNbinsY(); ip++) {
238 obg->SetBinContent(ie, ip, bg->GetBinContent(ie, ip));
239 obg->SetBinError(ie, ip, bg->GetBinError(ie, ip));
247 //____________________________________________________________________
249 AliFMDHistCollector::CheckCorrection(const TH2D* bg, Int_t ie, Int_t ip) const
252 // Check if we should include the bin in the data range
255 // bg Secondary map histogram
260 // True if to be used
262 Double_t c = bg->GetBinContent(ie,ip);
263 switch (fFiducialMethod) {
265 return c >= fCorrectionCut;
267 if (2 * c < bg->GetBinContent(ie+1,ip) ||
268 2 * c < bg->GetBinContent(ie-1,ip)) return false;
271 AliError("No fiducal cut method defined");
276 //____________________________________________________________________
278 AliFMDHistCollector::DefineOutput(TList* dir)
281 // Output diagnostic histograms to directory
284 // dir List to write in
288 fList->SetName(GetName());
294 //____________________________________________________________________
296 AliFMDHistCollector::GetIdx(UShort_t d, Char_t r) const
299 // Get the ring index from detector number and ring identifier
306 // ring index or -1 in case of problems
310 case 1: idx = 0; break;
311 case 2: idx = 1 + (r == 'I' || r == 'i' ? 0 : 1); break;
312 case 3: idx = 3 + (r == 'I' || r == 'i' ? 0 : 1); break;
316 //____________________________________________________________________
318 AliFMDHistCollector::GetDetRing(Int_t idx, UShort_t& d, Char_t& r) const
321 // Get the detector and ring from the ring index
325 // d On return, the detector or 0 in case of errors
326 // r On return, the ring id or '0' in case of errors
331 case 0: d = 1; r = 'I'; break;
332 case 1: d = 2; r = 'I'; break;
333 case 2: d = 2; r = 'O'; break;
334 case 3: d = 3; r = 'I'; break;
335 case 4: d = 3; r = 'O'; break;
339 //____________________________________________________________________
341 AliFMDHistCollector::GetFirstAndLast(Int_t idx, UShort_t vtxbin,
342 Int_t& first, Int_t& last) const
345 // Get the first and last eta bin to use for a given ring and vertex
348 // idx Ring index as given by GetIdx
349 // vtxBin Vertex bin (1 based)
350 // first On return, the first eta bin to use
351 // last On return, the last eta bin to use
357 if (vtxbin <= 0) return;
358 idx += (vtxbin-1) * 5;
360 if (idx < 0 || idx >= fFirstBins.GetSize()) return;
362 first = fFirstBins.At(idx)+fNCutBins;
363 last = fLastBins.At(idx)-fNCutBins;
366 //____________________________________________________________________
368 AliFMDHistCollector::GetFirst(Int_t idx, UShort_t v) const
371 // Get the first eta bin to use for a given ring and vertex
374 // idx Ring index as given by GetIdx
375 // v vertex bin (1 based)
378 // First eta bin to use, or -1 in case of problems
381 GetFirstAndLast(idx,v,f,l);
386 //____________________________________________________________________
388 AliFMDHistCollector::GetLast(Int_t idx, UShort_t v) const
391 // Get the last eta bin to use for a given ring and vertex
394 // idx Ring index as given by GetIdx
395 // v vertex bin (1 based)
398 // Last eta bin to use, or -1 in case of problems
401 GetFirstAndLast(idx,v,f,l);
405 //____________________________________________________________________
407 AliFMDHistCollector::GetOverlap(UShort_t d, Char_t r,
408 Int_t bin, UShort_t vtxbin) const
411 // Get the possibly overlapping histogram of eta bin @a e in
418 // v Vertex bin (1 based)
421 // Overlapping histogram index or -1
426 if (bin <= GetLast(2,'I',vtxbin)) other = GetIdx(2,'I');
428 else if (d == 2 && r == 'I') {
429 if (bin <= GetLast(2, 'O', vtxbin)) other = GetIdx(2, 'O');
430 else if (bin >= GetFirst(1, 'I', vtxbin)) other = GetIdx(1, 'I');
432 else if (d == 2 && r == 'O') {
433 if (bin >= GetFirst(2, 'I', vtxbin)) other = GetIdx(2,'I');
435 else if (d == 3 && r == 'O') {
436 if (bin <= GetLast(3, 'I', vtxbin)) other = GetIdx(3, 'I');
438 else if (d == 3 && r == 'I') {
439 if (bin >= GetFirst(3, 'O', vtxbin)) other = GetIdx(3, 'O');
441 // AliInfo(Form("FMD%d%c (%d) -> %d", d, r, GetIdx(d,r), other));
444 //____________________________________________________________________
446 AliFMDHistCollector::GetOverlap(Int_t idx, Int_t bin, UShort_t vtxbin) const
449 // Get the possibly overlapping histogram of eta bin @a e in
455 // v Vertex bin (1 based)
458 // Overlapping histogram index or -1
462 GetDetRing(idx, d, r);
463 if (d == 0 || r == '\0') return 0;
465 return GetOverlap(d, r, bin, vtxbin);
469 //____________________________________________________________________
471 AliFMDHistCollector::MergeBins(Double_t c, Double_t e,
472 Double_t oc, Double_t oe,
473 Double_t& rc, Double_t& re) const
476 // Merge bins accoring to set method
483 // rc On return, the new content
484 // re On return, tne new error
487 switch (fMergeMethod) {
489 // calculate the average of old value (half the original),
490 // and this value, as well as the summed squared errors
491 // of the existing content (sqrt((e_1/2)^2=sqrt(e_1^2/4)=e_1/2)
492 // and half the error of this.
494 // So, on the first overlapping histogram we get
497 // e = sqrt((e_1 / 2)^2) = e_1/2
499 // On the second we get
501 // c' = c_2 / 2 + c = c_2 / 2 + c_1 / 2 = (c_1+c_2)/2
502 // e' = sqrt(e^2 + (e_2/2)^2)
503 // = sqrt(e_1^2/4 + e_2^2/4)
504 // = sqrt(1/4 * (e_1^2+e_2^2))
505 // = 1/2 * sqrt(e_1^2 + e_2^2)
507 re = TMath::Sqrt(oe*oe+(e*e)/4);
509 case kStraightMeanNoZero:
510 // If there's data in the overlapping histogram,
511 // calculate the average and add the errors in
514 // If there's no data in the overlapping histogram,
515 // then just fill in the data
518 re = TMath::Sqrt(oe*oe + e*e)/2;
525 case kWeightedMean: {
526 // Calculate the weighted mean
527 Double_t w = 1/(e*e);
531 Double_t ow = 1/(oe*oe);
536 re = TMath::Sqrt(1 / sw);
550 AliError("No method for defining content of overlapping bins defined");
555 //____________________________________________________________________
557 AliFMDHistCollector::Collect(const AliForwardUtil::Histos& hists,
558 AliForwardUtil::Histos& sums,
563 // Do the calculations
566 // hists Cache of histograms
567 // vtxBin Vertex bin (1 based)
568 // out Output histogram
573 AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
574 const TAxis* vtxAxis = fcm.GetVertexAxis();
575 Double_t vMin = vtxAxis->GetBinLowEdge(vtxbin);
576 Double_t vMax = vtxAxis->GetBinUpEdge(vtxbin);
578 = static_cast<TList*>(fList->FindObject(Form("%c%02d_%c%02d",
579 vMin < 0 ? 'm' : 'p',
580 int(TMath::Abs(vMin)),
581 vMax < 0 ? 'm' : 'p',
582 int(TMath::Abs(vMax)))));
585 for (UShort_t d=1; d<=3; d++) {
586 UShort_t nr = (d == 1 ? 1 : 2);
587 for (UShort_t q=0; q<nr; q++) {
588 Char_t r = (q == 0 ? 'I' : 'O');
589 TH2D* h = hists.Get(d,r);
590 TH2D* t = static_cast<TH2D*>(h->Clone(Form("FMD%d%c_tmp",d,r)));
591 Int_t i = (d == 1 ? 1 : 2*d + (q == 0 ? -2 : -1));
592 TH2D* o = sums.Get(d, r);
594 // Skipping selected FMD rings
595 if(d==1 && r=='I' && (fSkipFMDRings & kFMD1I)) { delete t; continue; }
596 if(d==2 && r=='I' && (fSkipFMDRings & kFMD2I)) { delete t; continue; }
597 if(d==2 && r=='O' && (fSkipFMDRings & kFMD2O)) { delete t; continue; }
598 if(d==3 && r=='I' && (fSkipFMDRings & kFMD3I)) { delete t; continue; }
599 if(d==3 && r=='O' && (fSkipFMDRings & kFMD3O)) { delete t; continue; }
604 GetFirstAndLast(d, r, vtxbin, first, last);
606 // Zero outside valid range
607 for (Int_t iPhi = 0; iPhi <= t->GetNbinsY()+1; iPhi++) {
609 for (Int_t iEta = 1; iEta < first; iEta++) {
610 t->SetBinContent(iEta,iPhi,0);
611 t->SetBinError(iEta,iPhi,0);
613 for (Int_t iEta = last+1; iEta <= t->GetNbinsX(); iEta++) {
614 t->SetBinContent(iEta,iPhi,0);
615 t->SetBinError(iEta,iPhi,0);
618 for (Int_t iEta = first; iEta <= last; iEta++)
619 t->SetBinContent(iEta,0,1);
620 // Add to our per-ring sum
623 // Outer rings have better phi segmentation - rebin to same as inner.
624 if (q == 1) t->RebinY(2);
626 // Now update profile output
627 for (Int_t iEta = first; iEta <= last; iEta++) {
629 // Get the possibly overlapping histogram
630 Int_t overlap = GetOverlap(d,r,iEta,vtxbin);
632 // Fill eta acceptance for this event into the phi underlow bin
633 Float_t ooc = out.GetBinContent(iEta,0);
634 Float_t noc = overlap >= 0? 0.5 : 1;
635 out.SetBinContent(iEta, 0, ooc + noc);
637 // Should we loop over h or t Y bins - I think it's t
638 for (Int_t iPhi = 1; iPhi <= t->GetNbinsY(); iPhi++) {
639 Double_t c = t->GetBinContent(iEta,iPhi);
640 Double_t e = t->GetBinError(iEta,iPhi);
641 Double_t ee = t->GetXaxis()->GetBinCenter(iEta);
642 fSumRings->Fill(ee, i, c);
644 // If there's no signal, continue
645 // if (e <= 0) continue;
646 if (c <= 0 || e <= 0) continue;
648 // If there's no overlapping histogram (ring), then
649 // fill in data and continue to the next phi bin
651 out.SetBinContent(iEta,iPhi,c);
652 out.SetBinError(iEta,iPhi,e);
656 // Get the current bin content and error
657 Double_t oc = out.GetBinContent(iEta,iPhi);
658 Double_t oe = out.GetBinError(iEta,iPhi);
661 MergeBins(c, e, oc, oe, rc, re);
662 out.SetBinContent(iEta,iPhi, rc);
663 out.SetBinError(iEta,iPhi, re);
666 // Remove temporary histogram
669 = static_cast<TH2D*>(vtxList->FindObject(Form("hitMapFMD%d%c", d, r)));
678 //____________________________________________________________________
680 AliFMDHistCollector::Print(Option_t* /* option */) const
688 char ind[gROOT->GetDirLevel()+1];
689 for (Int_t i = 0; i < gROOT->GetDirLevel(); i++) ind[i] = ' ';
690 ind[gROOT->GetDirLevel()] = '\0';
691 std::cout << ind << ClassName() << ": " << GetName() << '\n'
692 << ind << " # of cut bins: " << fNCutBins << '\n'
693 << ind << " Correction cut: " << fCorrectionCut << '\n'
694 << ind << " Merge method: ";
695 switch (fMergeMethod) {
696 case kStraightMean: std::cout << "straight mean\n"; break;
697 case kStraightMeanNoZero: std::cout << "straight mean (no zeros)\n"; break;
698 case kWeightedMean: std::cout << "weighted mean\n"; break;
699 case kLeastError: std::cout << "least error\n"; break;
702 std::cout << ind << " Bin ranges:\n" << ind << " rings ";
703 Int_t nVz = fFirstBins.fN / 5;
704 for (Int_t iIdx = 0; iIdx < 5; iIdx++) {
707 GetDetRing(iIdx, d, r);
708 std::cout << ind << " | FMD" << d << r << " ";
710 std::cout << '\n' << ind << " /vz_bin ";
711 for (Int_t iIdx = 0; iIdx < 5; iIdx++)
712 std::cout << "-+--------";
713 std::cout << std::endl;
715 for (UShort_t iVz = 1; iVz <= nVz; iVz++) {
716 std::cout << " " << std::setw(7) << iVz << " ";
717 for (Int_t iIdx = 0; iIdx < 5; iIdx++) {
720 GetDetRing(iIdx, d, r);
723 GetFirstAndLast(iIdx, iVz, first, last);
724 std::cout << " | " << std::setw(3) << first << "-"
725 << std::setw(3) << last;
727 std::cout << std::endl;
731 //____________________________________________________________________