2 // Class to do the sharing correction. That is, a filter that merges
3 // adjacent strip signals presumably originating from a single particle
4 // that impinges on the detector in such a way that it deposite energy
5 // into two or more strips.
8 // - AliESDFMD object - from reconstruction
11 // - AliESDFMD object - copy of input, but with signals merged
14 // - AliFMDCorrELossFit
17 // - For each ring (FMD1i, FMD2i, FMD2o, FMD3i, FMD3o) the distribution of
18 // signals before and after the filter.
19 // - For each ring (see above), an array of distributions of number of
20 // hit strips for each vertex bin (if enabled - see Init method)
24 #include "AliFMDSharingFilter.h"
25 #include "AliFMDStripIndex.h"
26 #include <AliESDFMD.h>
31 #include "AliForwardCorrectionManager.h"
32 #include "AliFMDCorrELossFit.h"
36 #include <TParameter.h>
40 ClassImp(AliFMDSharingFilter)
42 ; // This is for Emacs
46 do { if (L>fDebug)break; std::cout << (M) << std::flush;} while(false)
48 do { if (L>fDebug)break; std::cout << (M) << std::endl;} while(false)
52 //____________________________________________________________________
53 AliFMDSharingFilter::AliFMDSharingFilter()
56 fCorrectAngles(kFALSE),
62 fZeroSharedHitsBelowThreshold(false),
65 fUseSimpleMerging(false),
66 fThreeStripSharing(true),
67 fRecalculateEta(false),
71 // Default Constructor - do not use
73 DGUARD(fDebug,1, "Default CTOR for AliFMDSharingFilter");
76 //____________________________________________________________________
77 AliFMDSharingFilter::AliFMDSharingFilter(const char* title)
78 : TNamed("fmdSharingFilter", title),
80 fCorrectAngles(kFALSE),
86 fZeroSharedHitsBelowThreshold(false),
89 fUseSimpleMerging(false),
90 fThreeStripSharing(true),
91 fRecalculateEta(false),
98 // title Title of object - not significant
100 DGUARD(fDebug,1, "Named CTOR for AliFMDSharingFilter: %s", title);
101 fRingHistos.SetName(GetName());
102 fRingHistos.SetOwner();
104 fRingHistos.Add(new RingHistos(1, 'I'));
105 fRingHistos.Add(new RingHistos(2, 'I'));
106 fRingHistos.Add(new RingHistos(2, 'O'));
107 fRingHistos.Add(new RingHistos(3, 'I'));
108 fRingHistos.Add(new RingHistos(3, 'O'));
111 fHCuts.SetIncludeSigma(1);
112 fLCuts.SetMultCuts(.15);
114 fExtraDead.Reset(-1);
117 //____________________________________________________________________
118 AliFMDSharingFilter::AliFMDSharingFilter(const AliFMDSharingFilter& o)
121 fCorrectAngles(o.fCorrectAngles),
123 fHighCuts(o.fHighCuts),
124 fLowCuts(o.fLowCuts),
127 fZeroSharedHitsBelowThreshold(o.fZeroSharedHitsBelowThreshold),
130 fUseSimpleMerging(o.fUseSimpleMerging),
131 fThreeStripSharing(o.fThreeStripSharing),
132 fRecalculateEta(o.fRecalculateEta),
133 fExtraDead(o.fExtraDead)
139 // o Object to copy from
141 DGUARD(fDebug,1, "Copy CTOR for AliFMDSharingFilter");
142 TIter next(&o.fRingHistos);
144 while ((obj = next())) fRingHistos.Add(obj);
147 //____________________________________________________________________
148 AliFMDSharingFilter::~AliFMDSharingFilter()
153 DGUARD(fDebug,3, "DTOR for AliFMDSharingFilter");
154 // fRingHistos.Delete();
157 //____________________________________________________________________
159 AliFMDSharingFilter::operator=(const AliFMDSharingFilter& o)
162 // Assignment operator
165 // o Object to assign from
170 DGUARD(fDebug,3, "Assigment for AliFMDSharingFilter");
171 if (&o == this) return *this;
172 TNamed::operator=(o);
174 fCorrectAngles = o.fCorrectAngles;
178 fHighCuts = o.fHighCuts;
179 fLowCuts = o.fLowCuts;
180 fZeroSharedHitsBelowThreshold = o.fZeroSharedHitsBelowThreshold;
183 fUseSimpleMerging = o.fUseSimpleMerging;
184 fThreeStripSharing = o.fThreeStripSharing;
185 fRecalculateEta = o.fRecalculateEta;
187 fRingHistos.Delete();
188 TIter next(&o.fRingHistos);
190 while ((obj = next())) fRingHistos.Add(obj);
195 //____________________________________________________________________
196 AliFMDSharingFilter::RingHistos*
197 AliFMDSharingFilter::GetRingHistos(UShort_t d, Char_t r) const
200 // Get the ring histogram container
207 // Ring histogram container
211 case 1: idx = 0; break;
212 case 2: idx = 1 + (r == 'I' || r == 'i' ? 0 : 1); break;
213 case 3: idx = 3 + (r == 'I' || r == 'i' ? 0 : 1); break;
215 if (idx < 0 || idx >= fRingHistos.GetEntries()) return 0;
217 return static_cast<RingHistos*>(fRingHistos.At(idx));
220 //____________________________________________________________________
222 AliFMDSharingFilter::AddDead(UShort_t d, Char_t r, UShort_t s, UShort_t t)
224 if (d < 1 || d > 3) {
225 Warning("AddDead", "Invalid detector FMD%d", d);
228 Bool_t inner = (r == 'I' || r == 'i');
229 if (d == 1 && !inner) {
230 Warning("AddDead", "Invalid ring FMD%d%c", d, r);
233 if ((inner && s >= 20) || (!inner && s >= 40)) {
234 Warning("AddDead", "Invalid sector FMD%d%c[%02d]", d, r, s);
237 if ((inner && t >= 512) || (!inner && t >= 256)) {
238 Warning("AddDead", "Invalid strip FMD%d%c[%02d,%03d]", d, r, s, t);
242 Int_t id = AliFMDStripIndex::Pack(d, r, s, t);
244 for (i = 0; i < fExtraDead.GetSize(); i++) {
245 Int_t j = fExtraDead.At(i);
246 if (j == id) return; // Already there
247 if (j < 0) break; // Free slot
249 if (i >= fExtraDead.GetSize()) {
250 Warning("AddDead", "No free slot to add FMD%d%c[%02d,%03d] at",
256 //____________________________________________________________________
258 AliFMDSharingFilter::AddDeadRegion(UShort_t d, Char_t r,
259 UShort_t s1, UShort_t s2,
260 UShort_t t1, UShort_t t2)
262 // Add a dead region spanning from FMD<d><r>[<s1>,<t1>] to
263 // FMD<d><r>[<s2>,<t2>] (both inclusive)
264 for (Int_t s = s1; s <= s2; s++)
265 for (Int_t t = t1; t <= t2; t++)
268 //____________________________________________________________________
270 AliFMDSharingFilter::IsDead(UShort_t d, Char_t r, UShort_t s, UShort_t t) const
272 Int_t id = AliFMDStripIndex::Pack(d, r, s, t);
273 for (Int_t i = 0; i < fExtraDead.GetSize(); i++) {
274 Int_t j = fExtraDead.At(i);
276 //Info("IsDead", "FMD%d%c[%02d,%03d] marked as dead here", d, r, s, t);
279 if (j < 0) break; // High water mark
283 //____________________________________________________________________
285 AliFMDSharingFilter::SetupForData(const TAxis& axis)
287 // Initialise - called on first event
288 DGUARD(fDebug,1, "Initialize for AliFMDSharingFilter");
289 AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
290 AliFMDCorrELossFit* fits = fcm.GetELossFit();
292 // Get the high cut. The high cut is defined as the
293 // most-probably-value peak found from the energy distributions, minus
294 // 2 times the width of the corresponding Landau.
296 TAxis eAxis(axis.GetNbins(),
300 eAxis.Set(fits->GetEtaAxis().GetNbins(),
301 fits->GetEtaAxis().GetXmin(),
302 fits->GetEtaAxis().GetXmax());
304 UShort_t nEta = eAxis.GetNbins();
306 fHighCuts->SetBins(nEta, eAxis.GetXmin(), eAxis.GetXmax(), 5, .5, 5.5);
307 fHighCuts->GetYaxis()->SetBinLabel(1, "FMD1i");
308 fHighCuts->GetYaxis()->SetBinLabel(2, "FMD2i");
309 fHighCuts->GetYaxis()->SetBinLabel(3, "FMD2o");
310 fHighCuts->GetYaxis()->SetBinLabel(4, "FMD3i");
311 fHighCuts->GetYaxis()->SetBinLabel(5, "FMD3o");
313 fLowCuts->SetBins(nEta, eAxis.GetXmin(), eAxis.GetXmax(), 5, .5, 5.5);
314 fLowCuts->GetYaxis()->SetBinLabel(1, "FMD1i");
315 fLowCuts->GetYaxis()->SetBinLabel(2, "FMD2i");
316 fLowCuts->GetYaxis()->SetBinLabel(3, "FMD2o");
317 fLowCuts->GetYaxis()->SetBinLabel(4, "FMD3i");
318 fLowCuts->GetYaxis()->SetBinLabel(5, "FMD3o");
321 for (UShort_t d = 1; d <= 3; d++) {
322 UShort_t nr = (d == 1 ? 1 : 2);
323 for (UShort_t q = 0; q < nr; q++) {
324 Char_t r = (q == 0 ? 'I' : 'O');
326 for (UShort_t e = 1; e <= nEta; e++) {
327 Double_t eta = eAxis.GetBinCenter(e);
329 if (fDebug > 3) fHCuts.Print();
331 Double_t hcut = GetHighCut(d, r, eta, false);
332 Double_t lcut = GetLowCut(d, r, eta);
334 if (hcut > 0) fHighCuts->SetBinContent(e, ybin, hcut);
335 if (lcut > 0) fLowCuts ->SetBinContent(e, ybin, lcut);
341 //____________________________________________________________________
342 #define ETA2COS(ETA) \
343 TMath::Cos(2*TMath::ATan(TMath::Exp(-TMath::Abs(ETA))))
346 AliFMDSharingFilter::Filter(const AliESDFMD& input,
352 // Filter the input AliESDFMD object
356 // lowFlux If this is a low-flux event
357 // output Output AliESDFMD object
360 // True on success, false otherwise
362 DGUARD(fDebug,1, "Filter event in AliFMDSharingFilter");
364 TIter next(&fRingHistos);
366 while ((o = static_cast<RingHistos*>(next())))
369 if (fOper) fOper->Reset(0);
371 Int_t nCandidate = 0;
380 for(UShort_t d = 1; d <= 3; d++) {
381 Int_t nRings = (d == 1 ? 1 : 2);
382 for (UShort_t q = 0; q < nRings; q++) {
383 Char_t r = (q == 0 ? 'I' : 'O');
384 UShort_t nsec = (q == 0 ? 20 : 40);
385 UShort_t nstr = (q == 0 ? 512 : 256);
386 RingHistos* histos = GetRingHistos(d, r);
388 for(UShort_t s = 0; s < nsec; s++) {
390 for (UShort_t t = 0; t < nstr; t++) status[t] = kCandidate;
393 Bool_t used = kFALSE;
394 Double_t eTotal = -1;
395 Int_t nDistanceBefore = -1;
396 Int_t nDistanceAfter = -1;
397 Bool_t twoLow = kFALSE;
398 for(UShort_t t = 0; t < nstr; t++) {
402 output.SetMultiplicity(d,r,s,t,0.);
403 Float_t mult = SignalInStrip(input,d,r,s,t);
404 Float_t multNext = (t<nstr-1) ? SignalInStrip(input,d,r,s,t+1) :0;
405 Float_t multNextNext = (t<nstr-2) ? SignalInStrip(input,d,r,s,t+2) :0;
406 if (multNext == AliESDFMD::kInvalidMult) multNext = 0;
407 if (multNextNext == AliESDFMD::kInvalidMult) multNextNext = 0;
408 if(!fThreeStripSharing) multNextNext = 0;
410 // Get the pseudo-rapidity
411 Double_t eta = input.Eta(d,r,s,t);
412 Double_t phi = input.Phi(d,r,s,t) * TMath::Pi() / 180.;
413 if (s == 0) output.SetEta(d,r,s,t,eta);
415 if(fRecalculateEta) {
416 Double_t etaOld = eta;
417 Double_t etaCalc = AliForwardUtil::GetEtaFromStrip(d,r,s,t,zvtx);
420 if (mult > 0 && mult != AliESDFMD::kInvalidMult ) {
421 Double_t cosOld = ETA2COS(etaOld);
422 Double_t cosNew = ETA2COS(etaCalc);
423 Double_t corr = cosNew / cosOld;
426 multNextNext *= corr;
430 // Keep dead-channel information.
431 if(mult == AliESDFMD::kInvalidMult || IsDead(d,r,s,t)) {
432 output.SetMultiplicity(d,r,s,t,AliESDFMD::kInvalidMult);
433 mult = AliESDFMD::kInvalidMult;
436 // If no signal or dead strip, go on.
437 if (mult == AliESDFMD::kInvalidMult || mult == 0) {
438 if (mult == 0) histos->fSum->Fill(eta,phi,mult);
443 // Fill the diagnostics histogram
444 histos->fBefore->Fill(mult);
446 Double_t mergedEnergy = 0;
448 if(fUseSimpleMerging) {
450 if (t < nstr-1) histos->fNeighborsBefore->Fill(mult,multNext);
451 if(mult > GetHighCut(d, r, eta ,false)) {
452 histos->fDistanceBefore->Fill(nDistanceBefore);
453 nDistanceBefore = -1;
457 if(fThreeStripSharing && multNext > GetLowCut(d, r, eta) &&
458 (multNext < GetHighCut(d, r, eta ,false) || twoLow)) {
459 eTotal = eTotal + multNext;
461 histos->fTriple->Fill(eTotal);
467 histos->fDouble->Fill(eTotal);
474 if(used) {used = kFALSE; continue; }
475 if(mult > GetLowCut(d, r, eta)) etot = mult;
477 if(mult > GetLowCut(d, r, eta) &&
478 multNext > GetLowCut(d, r, eta) &&
479 (mult < GetHighCut(d, r, eta ,false) ||
480 multNext < GetHighCut(d, r, eta ,false))) {
482 if(mult < GetHighCut(d, r, eta ,false) &&
483 multNext < GetHighCut(d, r, eta ,false) )
486 if(mult>multNext && multNextNext < GetLowCut(d, r, eta))
488 etot = mult + multNext;
490 histos->fDouble->Fill(etot);
495 eTotal = mult + multNext;
500 histos->fSingle->Fill(etot);
501 histos->fSinglePerStrip->Fill(etot,t);
508 if(mergedEnergy > GetHighCut(d, r, eta ,false) ) {
509 histos->fDistanceAfter->Fill(nDistanceAfter);
512 //if(mult>0 && multNext >0)
513 // std::cout<<mult<<" "<<multNext<<" "<<mergedEnergy<<std::endl;
514 } // End of simple merge
516 // Get next and previous signal - if any
519 Status prevStatus = (t == 0 ? kNone : status[t-1]);
520 Status thisStatus = status[t];
521 Status nextStatus = (t == nstr-1 ? kNone : status[t+1]);
523 prevE = SignalInStrip(input,d,r,s,t-1);
524 if (prevE == AliESDFMD::kInvalidMult) prevE = 0;
527 nextE = SignalInStrip(input,d,r,s,t+1);
528 if (nextE == AliESDFMD::kInvalidMult) nextE = 0;
530 if (t != 0) histos->fNeighborsBefore->Fill(prevE, mult);
532 mergedEnergy = MultiplicityOfStrip(mult, prevE, nextE,
538 if (t != 0) status[t-1] = prevStatus;
539 if (t != nstr-1) status[t+1] = nextStatus;
540 status[t] = thisStatus;
541 // If we're processing on non-angle corrected data, we
542 // should do the angle correction here
543 } // End of non-simple
545 mergedEnergy = AngleCorrect(mergedEnergy, eta);
546 if (mergedEnergy > 0) histos->Incr();
549 histos->fNeighborsAfter->Fill(output.Multiplicity(d,r,s,t-1),
551 histos->fBeforeAfter->Fill(mult, mergedEnergy);
553 histos->fAfter->Fill(mergedEnergy);
554 histos->fSum->Fill(eta,phi,mergedEnergy);
556 output.SetMultiplicity(d,r,s,t,mergedEnergy);
558 for (UShort_t t = 0; t < nstr; t++) {
559 if (fOper) fOper->operator()(d, r, s, t) = status[t];
561 case kNone: nNone++; break;
562 case kCandidate: nCandidate++; break;
563 case kMergedWithOther: nMerged++; break;
564 case kMergedInto: nSummed++; break;
570 fSummed->Fill(kNone, nNone);
571 fSummed->Fill(kCandidate, nCandidate);
572 fSummed->Fill(kMergedWithOther, nMerged);
573 fSummed->Fill(kMergedInto, nSummed);
575 DMSG(fDebug, 3,"single=%9d, double=%9d, triple=%9d",
576 nSingle, nDouble, nTriple);
578 while ((o = static_cast<RingHistos*>(next())))
584 //_____________________________________________________________________
586 AliFMDSharingFilter::SignalInStrip(const AliESDFMD& input,
593 // Get the signal in a strip
605 Double_t mult = input.Multiplicity(d,r,s,t);
607 // - bad value (invalid or 0)
608 // - we want angle corrected and data is
609 // - we don't want angle corrected and data isn't
610 // just return read value
611 if (mult == AliESDFMD::kInvalidMult ||
613 (fCorrectAngles && input.IsAngleCorrected()) ||
614 (!fCorrectAngles && !input.IsAngleCorrected()))
617 // If we want angle corrected data, correct it,
618 // otherwise de-correct it
619 if (fCorrectAngles) mult = AngleCorrect(mult, input.Eta(d,r,s,t));
620 else mult = DeAngleCorrect(mult, input.Eta(d,r,s,t));
623 //_____________________________________________________________________
625 AliFMDSharingFilter::GetLowCut(UShort_t d, Char_t r, Double_t eta) const
628 // Get the low cut. Normally, the low cut is taken to be the lower
629 // value of the fit range used when generating the energy loss fits.
630 // However, if fLowCut is set (using SetLowCit) to a value greater
631 // than 0, then that value is used.
633 return fLCuts.GetMultCut(d,r,eta,false);
635 if (!fCutAtFractionOfMPV && fLowCut > 0) return fLowCut;
637 AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
638 AliFMDCorrELossFit* fits = fcm.GetELossFit();
640 if (fCutAtFractionOfMPV) {
641 AliFMDCorrELossFit::ELossFit* func = fits->GetFit(d,r,eta);
642 return fFractionOfMPV*func->GetDelta() ;
644 return fits->GetLowCut();
648 //_____________________________________________________________________
650 AliFMDSharingFilter::GetHighCut(UShort_t d, Char_t r,
651 Double_t eta, Bool_t errors) const
654 // Get the high cut. The high cut is defined as the
655 // most-probably-value peak found from the energy distributions, minus
656 // 2 times the width of the corresponding Landau.
658 return fHCuts.GetMultCut(d,r,eta,errors);
661 //_____________________________________________________________________
663 const char* status2String(AliFMDSharingFilter::Status s)
666 case AliFMDSharingFilter::kNone: return "none ";
667 case AliFMDSharingFilter::kCandidate: return "candidate";
668 case AliFMDSharingFilter::kMergedWithOther: return "merged ";
669 case AliFMDSharingFilter::kMergedInto: return "summed ";
675 //_____________________________________________________________________
677 AliFMDSharingFilter::MultiplicityOfStrip(Double_t thisE,
688 Status& nextStatus) const
690 Double_t lowCut = GetLowCut(d, r, eta);
692 DBG(3,Form("FMD%d%c[%2d,%3d]: this=%9f(%s), prev=%9f(%s), next=%9f(%s)",
694 thisE, status2String(thisStatus),
695 prevE, status2String(prevStatus),
696 nextE, status2String(nextStatus)));
698 // If below cut, then modify zero signal and make sure the next
699 // strip is considered a candidate.
700 if (thisE < lowCut || thisE > 20) {
702 DBGL(5,Form(" %9f<%9f || %9f>20, 0'ed", thisE, lowCut, thisE));
703 if (prevStatus == kCandidate) prevStatus = kNone;
706 // It this strip was merged with the previous strip, then
707 // make the next strip a candidate and zero the value in this strip.
708 if (thisStatus == kMergedWithOther) {
709 DBGL(5,Form(" Merged with other, 0'ed"));
713 // Get the upper cut on the sharing
714 Double_t highCut = GetHighCut(d, r, eta ,false);
720 // Only for low-flux events
722 // If this is smaller than the next, and the next is larger
723 // then the cut, mark both as candidates for sharing.
724 // They should be be merged on the next iteration
725 if (thisE < nextE && nextE > highCut) {
726 thisStatus = kCandidate;
727 nextStatus = kCandidate;
732 // Variable to sum signal in
733 Double_t totalE = thisE;
735 // If the previous signal was between the two cuts, and is still
736 // marked as a candidate , then merge it in here.
737 if (prevStatus == kCandidate && prevE > lowCut && prevE < highCut) {
739 prevStatus = kMergedWithOther;
740 DBG(3, Form(" Prev candidate %9f<%9f<%9f->%9f",
741 lowCut, prevE, highCut, totalE));
744 // If the next signal is between the two cuts, then merge it here
745 if (nextE > lowCut && nextE < highCut) {
747 nextStatus = kMergedWithOther;
748 DBG(3, Form(" Next %9f<%9f<%9f->%9f", lowCut, nextE, highCut,totalE));
751 // If the signal is bigger than the high-cut, then return the value
752 if (totalE > highCut) {
754 thisStatus = kMergedInto;
757 DBGL(5, Form(" %9f>%f9 (was %9f) -> %9f %s",
758 totalE, highCut, thisE, totalE,status2String(thisStatus)));
762 // This is below cut, so flag next as a candidate
763 DBG(3, Form(" %9f<=%9f, next candidate", totalE, highCut));
764 nextStatus = kCandidate;
767 // If the total signal is smaller than low cut then zero this and kill this
768 if (totalE < lowCut) {
769 DBGL(5, Form(" %9f<%9f (was %9f), zeroed", totalE, lowCut, thisE));
774 // If total signal not above high cut or lower than low cut,
775 // mark this as a candidate for merging into the next, and zero signal
776 DBGL(5, Form(" %9f<%9f<%9f (was %9f), zeroed, candidate",
777 lowCut, totalE, highCut, thisE));
778 thisStatus = kCandidate;
779 return (fZeroSharedHitsBelowThreshold ? 0 : totalE);
782 //_____________________________________________________________________
784 AliFMDSharingFilter::MultiplicityOfStrip(Double_t mult,
794 Bool_t& usedThis) const
797 // The actual algorithm
800 // mult The unfiltered signal in the strip
801 // eta Psuedo rapidity
802 // prevE Previous strip signal (or 0)
803 // nextE Next strip signal (or 0)
804 // lowFlux Whether this is a low flux event
809 // usedPrev Whether the previous strip was used in sharing or not
810 // usedThis Wether this strip was used in sharing or not.
813 // The filtered signal in the strip
816 // IF the multiplicity is very large, or below the cut, reject it, and
817 // flag it as candidate for sharing
818 Double_t lowCut = GetLowCut(d,r,eta);
819 if(mult > 12 || mult < lowCut) {
825 // If this was shared with the previous signal, return 0 and mark it as
826 // not a candiate for sharing
833 //analyse and perform sharing on one strip
836 Double_t highCut = GetHighCut(d, r, eta, false);
843 // If this signal is smaller than the next, and the next signal is smaller
844 // than then the high cut, and it's a low-flux event, then mark this and
845 // the next signal as candidates for sharing
847 // This is the test if the signal is the smaller of two possibly
857 Double_t totalE = mult;
859 // If the previous signal was larger than the low cut, and
860 // the previous was smaller than high cut, and the previous signal
861 // isn't marked as used, then add it's energy to this signal
862 if (prevE > lowCut &&
867 // If the next signal is larger than the low cut, and
868 // the next signal is smaller than the high cut, then add the next signal
869 // to this, and marked the next signal as used
870 if(nextE > lowCut && nextE < highCut ) {
875 // If we're processing on non-angle corrected data, we should do the
876 // angle correction here
877 // if (!fCorrectAngles)
878 // totalE = AngleCorrect(totalE, eta);
880 // Fill post processing histogram
881 // if(totalE > fLowCut)
882 // GetRingHistos(d,r)->fAfter->Fill(totalE);
885 Double_t mergedEnergy = 0;
888 // If we have a signal, then this is used (sharedPrev=true) and
889 // the signal is set to the result
890 mergedEnergy = totalE;
894 // If we do not have a signal (too low), then this is not shared,
895 // and the next strip is not shared either
902 //____________________________________________________________________
904 AliFMDSharingFilter::AngleCorrect(Double_t mult, Double_t eta) const
907 // Angle correct the signal
910 // mult Angle Un-corrected Signal
911 // eta Pseudo-rapidity
914 // Angle corrected signal
916 Double_t theta = 2 * TMath::ATan(TMath::Exp(-eta));
917 if (eta < 0) theta -= TMath::Pi();
918 return mult * TMath::Cos(theta);
920 //____________________________________________________________________
922 AliFMDSharingFilter::DeAngleCorrect(Double_t mult, Double_t eta) const
925 // Angle de-correct the signal
928 // mult Angle corrected Signal
929 // eta Pseudo-rapidity
932 // Angle un-corrected signal
934 Double_t theta = 2 * TMath::ATan(TMath::Exp(-eta));
935 if (eta < 0) theta -= TMath::Pi();
936 return mult / TMath::Cos(theta);
939 //____________________________________________________________________
941 AliFMDSharingFilter::Terminate(const TList* dir, TList* output, Int_t nEvents)
944 // Scale the histograms to the total number of events
947 // dir Where the output is
948 // nEvents Number of events
950 DGUARD(fDebug,1, "Scale histograms in AliFMDSharingFilter");
951 if (nEvents <= 0) return;
952 TList* d = static_cast<TList*>(dir->FindObject(GetName()));
955 TList* out = new TList;
956 out->SetName(d->GetName());
959 TIter next(&fRingHistos);
961 THStack* sums = new THStack("sums", "Sum of ring signals");
962 while ((o = static_cast<RingHistos*>(next()))) {
963 o->Terminate(d, nEvents);
965 Warning("Terminate", "No sum histogram found for ring %s", o->GetName());
968 TH1D* sum = o->fSum->ProjectionX(o->GetName(), 1, o->fSum->GetNbinsY(),"e");
969 sum->Scale(1., "width");
970 sum->SetTitle(o->GetName());
971 sum->SetDirectory(0);
972 sum->SetYTitle("#sum #Delta/#Delta_{mip}");
979 //____________________________________________________________________
981 AliFMDSharingFilter::CreateOutputObjects(TList* dir)
984 // Define the output histograms. These are put in a sub list of the
985 // passed list. The histograms are merged before the parent task calls
986 // AliAnalysisTaskSE::Terminate
989 // dir Directory to add to
991 DGUARD(fDebug,1, "Define output in AliFMDSharingFilter");
992 TList* d = new TList;
993 d->SetName(GetName());
996 fSummed = new TH2I("operations", "Strip operations",
997 kMergedInto, kNone-.5, kMergedInto+.5,
998 51201, -.5, 51200.5);
999 fSummed->SetXTitle("Operation");
1000 fSummed->SetYTitle("# of strips");
1001 fSummed->SetZTitle("Events");
1002 fSummed->GetXaxis()->SetBinLabel(kNone, "None");
1003 fSummed->GetXaxis()->SetBinLabel(kCandidate, "Candidate");
1004 fSummed->GetXaxis()->SetBinLabel(kMergedWithOther, "Merged w/other");
1005 fSummed->GetXaxis()->SetBinLabel(kMergedInto, "Merged into");
1006 fSummed->SetDirectory(0);
1009 fHighCuts = new TH2D("highCuts", "High cuts used", 1,0,1, 1,0,1);
1010 fHighCuts->SetXTitle("#eta");
1011 fHighCuts->SetDirectory(0);
1014 fLowCuts = new TH2D("lowCuts", "Low cuts used", 1,0,1, 1,0,1);
1015 fLowCuts->SetXTitle("#eta");
1016 fLowCuts->SetDirectory(0);
1022 d->Add(AliForwardUtil::MakeParameter("angle", fCorrectAngles));
1023 d->Add(AliForwardUtil::MakeParameter("lowSignal",
1024 fZeroSharedHitsBelowThreshold));
1025 d->Add(AliForwardUtil::MakeParameter("simple", fUseSimpleMerging));
1027 TObjArray* extraDead = new TObjArray;
1028 extraDead->SetOwner();
1029 extraDead->SetName("extraDead");
1030 for (Int_t i = 0; i < fExtraDead.GetSize(); i++) {
1031 if (fExtraDead.At(i) < 0) break;
1034 Int_t id = fExtraDead.At(i);
1035 AliFMDStripIndex::Unpack(id, dd, r, s, t);
1036 extraDead->Add(AliForwardUtil::MakeParameter(Form("FMD%d%c[%02d,%03d]",
1040 fLCuts.Output(d,"lCuts");
1041 fHCuts.Output(d,"hCuts");
1043 TIter next(&fRingHistos);
1045 while ((o = static_cast<RingHistos*>(next()))) {
1046 o->CreateOutputObjects(d);
1049 //____________________________________________________________________
1051 AliFMDSharingFilter::Print(Option_t* /*option*/) const
1054 // Print information
1059 char ind[gROOT->GetDirLevel()+1];
1060 for (Int_t i = 0; i < gROOT->GetDirLevel(); i++) ind[i] = ' ';
1061 ind[gROOT->GetDirLevel()] = '\0';
1062 std::cout << ind << ClassName() << ": " << GetName() << '\n'
1064 << ind << " Debug: " << fDebug << "\n"
1065 << ind << " Use corrected angles: " << fCorrectAngles << '\n'
1066 << ind << " Zero below threshold: "
1067 << fZeroSharedHitsBelowThreshold << '\n'
1068 << ind << " Use simple sharing: " << fUseSimpleMerging << '\n'
1069 << std::noboolalpha << std::endl;
1070 std::cout << ind << " Low cuts: " << std::endl;
1072 std::cout << ind << " High cuts: " << std::endl;
1076 //====================================================================
1077 AliFMDSharingFilter::RingHistos::RingHistos()
1078 : AliForwardUtil::RingHistos(),
1088 fNeighborsBefore(0),
1100 //____________________________________________________________________
1101 AliFMDSharingFilter::RingHistos::RingHistos(UShort_t d, Char_t r)
1102 : AliForwardUtil::RingHistos(d,r),
1112 fNeighborsBefore(0),
1125 fBefore = new TH1D("esdEloss", Form("Energy loss in %s (reconstruction)",
1126 GetName()), 600, 0, 15);
1127 fBefore->SetXTitle("#Delta E/#Delta E_{mip}");
1128 fBefore->SetYTitle("P(#Delta E/#Delta E_{mip})");
1129 fBefore->SetFillColor(Color());
1130 fBefore->SetFillStyle(3001);
1131 fBefore->SetLineColor(kBlack);
1132 fBefore->SetLineStyle(2);
1133 fBefore->SetDirectory(0);
1135 fAfter = static_cast<TH1D*>(fBefore->Clone("anaEloss"));
1136 fAfter->SetTitle(Form("Energy loss in %s (sharing corrected)", GetName()));
1137 fAfter->SetFillColor(Color()+2);
1138 fAfter->SetLineStyle(1);
1139 fAfter->SetDirectory(0);
1141 fSingle = new TH1D("singleEloss", "Energy loss (single strips)",
1143 fSingle->SetXTitle("#Delta/#Delta_{mip}");
1144 fSingle->SetYTitle("P(#Delta/#Delta_{mip})");
1145 fSingle->SetFillColor(Color());
1146 fSingle->SetFillStyle(3001);
1147 fSingle->SetLineColor(kBlack);
1148 fSingle->SetLineStyle(2);
1149 fSingle->SetDirectory(0);
1151 fDouble = static_cast<TH1D*>(fSingle->Clone("doubleEloss"));
1152 fDouble->SetTitle("Energy loss (two strips)");
1153 fDouble->SetFillColor(Color()+1);
1154 fDouble->SetDirectory(0);
1156 fTriple = static_cast<TH1D*>(fSingle->Clone("tripleEloss"));
1157 fTriple->SetTitle("Energy loss (three strips)");
1158 fTriple->SetFillColor(Color()+2);
1159 fTriple->SetDirectory(0);
1161 //Int_t nBinsForInner = (r == 'I' ? 32 : 16);
1162 Int_t nBinsForInner = (r == 'I' ? 512 : 256);
1163 Int_t nStrips = (r == 'I' ? 512 : 256);
1165 fSinglePerStrip = new TH2D("singlePerStrip", "SinglePerStrip",
1166 600,0,15, nBinsForInner,0,nStrips);
1167 fSinglePerStrip->SetXTitle("#Delta/#Delta_{mip}");
1168 fSinglePerStrip->SetYTitle("Strip #");
1169 fSinglePerStrip->SetZTitle("Counts");
1170 fSinglePerStrip->SetDirectory(0);
1172 fDistanceBefore = new TH1D("distanceBefore", "Distance before sharing",
1173 nStrips , 0,nStrips );
1174 fDistanceBefore->SetXTitle("Distance");
1175 fDistanceBefore->SetYTitle("Counts");
1176 fDistanceBefore->SetFillColor(kGreen+2);
1177 fDistanceBefore->SetFillStyle(3001);
1178 fDistanceBefore->SetLineColor(kBlack);
1179 fDistanceBefore->SetLineStyle(2);
1180 fDistanceBefore->SetDirectory(0);
1182 fDistanceAfter = static_cast<TH1D*>(fDistanceBefore->Clone("distanceAfter"));
1183 fDistanceAfter->SetTitle("Distance after sharing");
1184 fDistanceAfter->SetFillColor(kGreen+1);
1185 fDistanceAfter->SetDirectory(0);
1190 Int_t n = int((max-min) / (max / 300));
1191 fBeforeAfter = new TH2D("beforeAfter", "Before and after correlation",
1192 n, min, max, n, min, max);
1193 fBeforeAfter->SetXTitle("#Delta E/#Delta E_{mip} before");
1194 fBeforeAfter->SetYTitle("#Delta E/#Delta E_{mip} after");
1195 fBeforeAfter->SetZTitle("Correlation");
1196 fBeforeAfter->SetDirectory(0);
1198 fNeighborsBefore = static_cast<TH2D*>(fBeforeAfter->Clone("neighborsBefore"));
1199 fNeighborsBefore->SetTitle("Correlation of neighbors before");
1200 fNeighborsBefore->SetXTitle("#Delta E_{i}/#Delta E_{mip}");
1201 fNeighborsBefore->SetYTitle("#Delta E_{i+1}/#Delta E_{mip}");
1202 fNeighborsBefore->SetDirectory(0);
1205 static_cast<TH2D*>(fNeighborsBefore->Clone("neighborsAfter"));
1206 fNeighborsAfter->SetTitle("Correlation of neighbors after");
1207 fNeighborsAfter->SetDirectory(0);
1209 fSum = new TH2D("summed", "Summed signal", 200, -4, 6,
1210 (fRing == 'I' || fRing == 'i' ? 20 : 40), 0, 2*TMath::Pi());
1211 fSum->SetDirectory(0);
1213 fSum->SetMarkerColor(Color());
1214 // fSum->SetFillColor(Color());
1215 fSum->SetXTitle("#eta");
1216 fSum->SetYTitle("#varphi [radians]");
1217 fSum->SetZTitle("#sum #Delta/#Delta_{mip}(#eta,#varphi) ");
1219 fHits = new TH1D("hits", "Number of hits", 200, 0, 200000);
1220 fHits->SetDirectory(0);
1221 fHits->SetXTitle("# of hits");
1222 fHits->SetFillColor(kGreen+1);
1224 //____________________________________________________________________
1225 AliFMDSharingFilter::RingHistos::RingHistos(const RingHistos& o)
1226 : AliForwardUtil::RingHistos(o),
1232 fSinglePerStrip(o.fSinglePerStrip),
1233 fDistanceBefore(o.fDistanceBefore),
1234 fDistanceAfter(o.fDistanceAfter),
1235 fBeforeAfter(o.fBeforeAfter),
1236 fNeighborsBefore(o.fNeighborsBefore),
1237 fNeighborsAfter(o.fNeighborsAfter),
1246 // o Object to copy from
1250 //____________________________________________________________________
1251 AliFMDSharingFilter::RingHistos&
1252 AliFMDSharingFilter::RingHistos::operator=(const RingHistos& o)
1255 // Assignment operator
1258 // o Object to assign from
1261 // Reference to this
1263 if (&o == this) return *this;
1264 AliForwardUtil::RingHistos::operator=(o);
1268 if (fBefore) delete fBefore;
1269 if (fAfter) delete fAfter;
1270 if (fSingle) delete fSingle;
1271 if (fDouble) delete fDouble;
1272 if (fTriple) delete fTriple;
1273 if (fSinglePerStrip) delete fSinglePerStrip;
1274 if (fDistanceBefore) delete fDistanceBefore;
1275 if (fDistanceAfter) delete fDistanceAfter;
1276 if (fHits) delete fHits;
1279 fBefore = static_cast<TH1D*>(o.fBefore->Clone());
1280 fAfter = static_cast<TH1D*>(o.fAfter->Clone());
1281 fSingle = static_cast<TH1D*>(o.fSingle->Clone());
1282 fDouble = static_cast<TH1D*>(o.fDouble->Clone());
1283 fTriple = static_cast<TH1D*>(o.fTriple->Clone());
1284 fSinglePerStrip = static_cast<TH2D*>(o.fSinglePerStrip->Clone());
1285 fDistanceBefore = static_cast<TH1D*>(o.fDistanceBefore->Clone());
1286 fDistanceAfter = static_cast<TH1D*>(o.fDistanceAfter->Clone());
1287 fBeforeAfter = static_cast<TH2D*>(o.fBeforeAfter->Clone());
1288 fNeighborsBefore = static_cast<TH2D*>(o.fNeighborsBefore->Clone());
1289 fNeighborsAfter = static_cast<TH2D*>(o.fNeighborsAfter->Clone());
1290 fHits = static_cast<TH1D*>(o.fHits->Clone());
1291 fSum = static_cast<TH2D*>(o.fSum->Clone());
1295 //____________________________________________________________________
1296 AliFMDSharingFilter::RingHistos::~RingHistos()
1302 //____________________________________________________________________
1304 AliFMDSharingFilter::RingHistos::Finish()
1310 fHits->Fill(fNHits);
1313 //____________________________________________________________________
1315 AliFMDSharingFilter::RingHistos::Terminate(const TList* dir, Int_t nEvents)
1318 // Scale the histograms to the total number of events
1321 // nEvents Number of events
1322 // dir Where the output is
1324 TList* l = GetOutputList(dir);
1328 TH1D* before = static_cast<TH1D*>(l->FindObject("esdEloss"));
1329 TH1D* after = static_cast<TH1D*>(l->FindObject("anaEloss"));
1330 if (before) before->Scale(1./nEvents);
1331 if (after) after->Scale(1./nEvents);
1334 TH2D* summed = static_cast<TH2D*>(l->FindObject("summed"));
1335 if (summed) summed->Scale(1./nEvents);
1339 //____________________________________________________________________
1341 AliFMDSharingFilter::RingHistos::CreateOutputObjects(TList* dir)
1347 // dir where to store
1349 TList* d = DefineOutputList(dir);
1356 d->Add(fSinglePerStrip);
1357 d->Add(fDistanceBefore);
1358 d->Add(fDistanceAfter);
1359 d->Add(fBeforeAfter);
1360 d->Add(fNeighborsBefore);
1361 d->Add(fNeighborsAfter);
1365 // Removed to avoid doubly adding the list which destroys
1370 //____________________________________________________________________