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 <AliESDFMD.h>
30 #include "AliForwardCorrectionManager.h"
36 ClassImp(AliFMDSharingFilter)
38 ; // This is for Emacs
42 //____________________________________________________________________
43 AliFMDSharingFilter::AliFMDSharingFilter()
47 fCorrectAngles(kFALSE),
52 // Default Constructor - do not use
56 //____________________________________________________________________
57 AliFMDSharingFilter::AliFMDSharingFilter(const char* title)
58 : TNamed("fmdSharingFilter", title),
61 fCorrectAngles(kFALSE),
69 // title Title of object - not significant
71 fRingHistos.Add(new RingHistos(1, 'I'));
72 fRingHistos.Add(new RingHistos(2, 'I'));
73 fRingHistos.Add(new RingHistos(2, 'O'));
74 fRingHistos.Add(new RingHistos(3, 'I'));
75 fRingHistos.Add(new RingHistos(3, 'O'));
78 //____________________________________________________________________
79 AliFMDSharingFilter::AliFMDSharingFilter(const AliFMDSharingFilter& o)
83 fCorrectAngles(o.fCorrectAngles),
91 // o Object to copy from
93 TIter next(&o.fRingHistos);
95 while ((obj = next())) fRingHistos.Add(obj);
98 //____________________________________________________________________
99 AliFMDSharingFilter::~AliFMDSharingFilter()
104 fRingHistos.Delete();
107 //____________________________________________________________________
109 AliFMDSharingFilter::operator=(const AliFMDSharingFilter& o)
112 // Assignment operator
115 // o Object to assign from
120 TNamed::operator=(o);
123 fCorrectAngles = o.fCorrectAngles;
127 fRingHistos.Delete();
128 TIter next(&o.fRingHistos);
130 while ((obj = next())) fRingHistos.Add(obj);
135 //____________________________________________________________________
136 AliFMDSharingFilter::RingHistos*
137 AliFMDSharingFilter::GetRingHistos(UShort_t d, Char_t r) const
140 // Get the ring histogram container
147 // Ring histogram container
151 case 1: idx = 0; break;
152 case 2: idx = 1 + (r == 'I' || r == 'i' ? 0 : 1); break;
153 case 3: idx = 3 + (r == 'I' || r == 'i' ? 0 : 1); break;
155 if (idx < 0 || idx >= fRingHistos.GetEntries()) return 0;
157 return static_cast<RingHistos*>(fRingHistos.At(idx));
160 //____________________________________________________________________
162 AliFMDSharingFilter::Filter(const AliESDFMD& input,
167 // Filter the input AliESDFMD object
171 // lowFlux If this is a low-flux event
172 // output Output AliESDFMD object
175 // True on success, false otherwise
178 TIter next(&fRingHistos);
180 Double_t lowCut = GetLowCut();
181 while ((o = static_cast<RingHistos*>(next())))
184 // AliFMDAnaParameters* pars = AliFMDAnaParameters::Instance();
186 for(UShort_t d = 1; d <= 3; d++) {
187 Int_t nRings = (d == 1 ? 1 : 2);
188 for (UShort_t q = 0; q < nRings; q++) {
189 Char_t r = (q == 0 ? 'I' : 'O');
190 UShort_t nsec = (q == 0 ? 20 : 40);
191 UShort_t nstr = (q == 0 ? 512 : 256);
193 RingHistos* histos = GetRingHistos(d, r);
195 for(UShort_t s = 0; s < nsec; s++) {
196 Bool_t usedThis = kFALSE;
197 Bool_t usedPrev = kFALSE;
199 for(UShort_t t = 0; t < nstr; t++) {
200 output.SetMultiplicity(d,r,s,t,0.);
201 Float_t mult = SignalInStrip(input,d,r,s,t);
203 // Keep dead-channel information.
204 if(mult == AliESDFMD::kInvalidMult)
205 output.SetMultiplicity(d,r,s,t,AliESDFMD::kInvalidMult);
207 // If no signal or dead strip, go on.
208 if (mult == AliESDFMD::kInvalidMult || mult == 0) continue;
210 // Get the pseudo-rapidity
211 Double_t eta = input.Eta(d,r,s,t);
213 // Fill the diagnostics histogram
214 histos->fBefore->Fill(mult);
216 // Get next and previous signal - if any
220 prevE = SignalInStrip(input,d,r,s,t-1);
221 if (prevE == AliESDFMD::kInvalidMult) prevE = 0;
224 nextE = SignalInStrip(input,d,r,s,t+1);
225 if (nextE == AliESDFMD::kInvalidMult) nextE = 0;
228 Double_t mergedEnergy = MultiplicityOfStrip(mult,eta,prevE,nextE,
231 if (mergedEnergy > lowCut) histos->Incr();
232 histos->fAfter->Fill(mergedEnergy);
234 output.SetMultiplicity(d,r,s,t,mergedEnergy);
235 output.SetEta(d,r,s,t,eta);
242 while ((o = static_cast<RingHistos*>(next())))
248 //_____________________________________________________________________
250 AliFMDSharingFilter::SignalInStrip(const AliESDFMD& input,
257 // Get the signal in a strip
269 Double_t mult = input.Multiplicity(d,r,s,t);
270 if (mult == AliESDFMD::kInvalidMult || mult == 0) return mult;
272 if (fCorrectAngles && !input.IsAngleCorrected())
273 mult = AngleCorrect(mult, input.Eta(d,r,s,t));
274 else if (!fCorrectAngles && input.IsAngleCorrected())
275 mult = DeAngleCorrect(mult, input.Eta(d,r,s,t));
278 //_____________________________________________________________________
280 AliFMDSharingFilter::GetLowCut() const
283 // Get the low cut. Normally, the low cut is taken to be the lower
284 // value of the fit range used when generating the energy loss fits.
285 // However, if fLowCut is set (using SetLowCit) to a value greater
286 // than 0, then that value is used.
288 if (fLowCut > 0) return fLowCut;
289 AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
290 AliFMDCorrELossFit* fits = fcm.GetELossFit();
291 return fits->GetLowCut();
294 //_____________________________________________________________________
296 AliFMDSharingFilter::GetHighCut(UShort_t d, Char_t r, Double_t eta) const
299 // Get the high cut. The high cut is defined as the
300 // most-probably-value peak found from the energy distributions, minus
301 // 2 times the width of the corresponding Landau.
303 AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
306 // Get the high cut. The high cut is defined as the
307 // most-probably-value peak found from the energy distributions, minus
308 // 2 times the width of the corresponding Landau.
309 AliFMDCorrELossFit::ELossFit* fit = fcm.GetELossFit()->FindFit(d,r,eta);
310 Double_t delta = 1024;
313 AliError(Form("No energy loss fit for FMD%d%c at eta=%f", d, r, eta));
321 AliWarning(Form("FMD%d%c, eta=%f, Delta=%f, xi=%f", d, r, eta, delta, xi));
323 Double_t highCut = (delta - fNXi * xi);
327 //_____________________________________________________________________
329 AliFMDSharingFilter::MultiplicityOfStrip(Double_t mult,
342 // The actual algorithm
345 // mult The unfiltered signal in the strip
346 // eta Psuedo rapidity
347 // prevE Previous strip signal (or 0)
348 // nextE Next strip signal (or 0)
349 // lowFlux Whether this is a low flux event
354 // usedPrev Whether the previous strip was used in sharing or not
355 // usedThis Wether this strip was used in sharing or not.
358 // The filtered signal in the strip
361 // IF the multiplicity is very large, or below the cut, reject it, and
362 // flag it as candidate for sharing
363 Double_t lowCut = GetLowCut();
364 if(mult > 12 || mult < lowCut) {
370 // If this was shared with the previous signal, return 0 and mark it as
371 // not a candiate for sharing
378 //analyse and perform sharing on one strip
381 Double_t highCut = GetHighCut(d, r, eta);
383 // If this signal is smaller than the next, and the next signal is smaller
384 // than then the high cut, and it's a low-flux event, then mark this and
385 // the next signal as candidates for sharing
387 // This is the test if the signal is the smaller of two possibly
397 Double_t totalE = mult;
399 // If the previous signal was larger than the low cut, and
400 // the previous was smaller than high cut, and the previous signal
401 // isn't marked as used, then add it's energy to this signal
402 if (prevE > lowCut &&
407 // If the next signal is larger than the low cut, and
408 // the next signal is smaller than the low cut, then add the next signal
409 // to this, and marked the next signal as used
410 if(nextE > lowCut && nextE < highCut ) {
415 // If we're processing on non-angle corrected data, we should do the
416 // angle correction here
418 totalE = AngleCorrect(totalE, eta);
420 // Fill post processing histogram
421 // if(totalE > fLowCut)
422 // GetRingHistos(d,r)->fAfter->Fill(totalE);
425 Double_t mergedEnergy = 0;
428 // If we have a signal, then this is used (sharedPrev=true) and
429 // the signal is set to the result
430 mergedEnergy = totalE;
434 // If we do not have a signal (too low), then this is not shared,
435 // and the next strip is not shared either
442 //____________________________________________________________________
444 AliFMDSharingFilter::AngleCorrect(Double_t mult, Double_t eta) const
447 // Angle correct the signal
450 // mult Angle Un-corrected Signal
451 // eta Pseudo-rapidity
454 // Angle corrected signal
456 Double_t theta = 2 * TMath::ATan(TMath::Exp(-eta));
457 if (eta < 0) theta -= TMath::Pi();
458 return mult * TMath::Cos(theta);
460 //____________________________________________________________________
462 AliFMDSharingFilter::DeAngleCorrect(Double_t mult, Double_t eta) const
465 // Angle de-correct the signal
468 // mult Angle corrected Signal
469 // eta Pseudo-rapidity
472 // Angle un-corrected signal
474 Double_t theta = 2 * TMath::ATan(TMath::Exp(-eta));
475 if (eta < 0) theta -= TMath::Pi();
476 return mult / TMath::Cos(theta);
479 //____________________________________________________________________
481 AliFMDSharingFilter::ScaleHistograms(TList* dir, Int_t nEvents)
484 // Scale the histograms to the total number of events
487 // dir Where the output is
488 // nEvents Number of events
490 if (nEvents <= 0) return;
491 TList* d = static_cast<TList*>(dir->FindObject(GetName()));
494 TIter next(&fRingHistos);
496 while ((o = static_cast<RingHistos*>(next())))
497 o->ScaleHistograms(d, nEvents);
500 //____________________________________________________________________
502 AliFMDSharingFilter::DefineOutput(TList* dir)
505 // Define the output histograms. These are put in a sub list of the
506 // passed list. The histograms are merged before the parent task calls
507 // AliAnalysisTaskSE::Terminate
510 // dir Directory to add to
512 TList* d = new TList;
513 d->SetName(GetName());
515 TIter next(&fRingHistos);
517 while ((o = static_cast<RingHistos*>(next()))) {
521 //____________________________________________________________________
523 AliFMDSharingFilter::Print(Option_t* /*option*/) const
531 char ind[gROOT->GetDirLevel()+1];
532 for (Int_t i = 0; i < gROOT->GetDirLevel(); i++) ind[i] = ' ';
533 ind[gROOT->GetDirLevel()] = '\0';
534 std::cout << ind << "AliFMDSharingFilter: " << GetName() << '\n'
535 << ind << " Low cut: " << fLowCut << '\n'
536 << ind << " N xi factor: " << fNXi << '\n'
537 << ind << " Use corrected angles: "
538 << (fCorrectAngles ? "yes" : "no") << std::endl;
541 //====================================================================
542 AliFMDSharingFilter::RingHistos::RingHistos()
543 : AliForwardUtil::RingHistos(),
555 //____________________________________________________________________
556 AliFMDSharingFilter::RingHistos::RingHistos(UShort_t d, Char_t r)
557 : AliForwardUtil::RingHistos(d,r),
570 fBefore = new TH1D(Form("%s_ESD_Eloss", fName.Data()),
571 Form("Energy loss in %s (reconstruction)", fName.Data()),
573 fAfter = new TH1D(Form("%s_Ana_Eloss", fName.Data()),
574 Form("Energy loss in %s (sharing corrected)",
575 fName.Data()), 1000, 0, 25);
576 fBefore->SetXTitle("#Delta E/#Delta E_{mip}");
577 fBefore->SetYTitle("P(#Delta E/#Delta E_{mip})");
578 fBefore->SetFillColor(kRed+1);
579 fBefore->SetFillStyle(3001);
581 fBefore->SetDirectory(0);
582 fAfter->SetXTitle("#Delta E/#Delta E_{mip}");
583 fAfter->SetYTitle("P(#Delta E/#Delta E_{mip})");
584 fAfter->SetFillColor(kBlue+1);
585 fAfter->SetFillStyle(3001);
587 fAfter->SetDirectory(0);
589 fHits = new TH1D(Form("%s_Hits", fName.Data()),
590 Form("Number of hits in %s", fName.Data()),
592 fHits->SetDirectory(0);
593 fHits->SetXTitle("# of hits");
594 fHits->SetFillColor(kGreen+1);
596 //____________________________________________________________________
597 AliFMDSharingFilter::RingHistos::RingHistos(const RingHistos& o)
598 : AliForwardUtil::RingHistos(o),
608 // o Object to copy from
612 //____________________________________________________________________
613 AliFMDSharingFilter::RingHistos&
614 AliFMDSharingFilter::RingHistos::operator=(const RingHistos& o)
617 // Assignment operator
620 // o Object to assign from
625 AliForwardUtil::RingHistos::operator=(o);
629 if (fBefore) delete fBefore;
630 if (fAfter) delete fAfter;
631 if (fHits) delete fHits;
633 fBefore = static_cast<TH1D*>(o.fBefore->Clone());
634 fAfter = static_cast<TH1D*>(o.fAfter->Clone());
635 fHits = static_cast<TH1D*>(o.fHits->Clone());
639 //____________________________________________________________________
640 AliFMDSharingFilter::RingHistos::~RingHistos()
645 if (fBefore) delete fBefore;
646 if (fAfter) delete fAfter;
647 if (fHits) delete fHits;
649 //____________________________________________________________________
651 AliFMDSharingFilter::RingHistos::Finish()
660 //____________________________________________________________________
662 AliFMDSharingFilter::RingHistos::ScaleHistograms(TList* dir, Int_t nEvents)
665 // Scale the histograms to the total number of events
668 // nEvents Number of events
669 // dir Where the output is
671 TList* l = GetOutputList(dir);
674 TH1D* before = static_cast<TH1D*>(l->FindObject(Form("%s_ESD_ELoss",
676 TH1D* after = static_cast<TH1D*>(l->FindObject(Form("%s_Ana_ELoss",
678 if (before) before->Scale(1./nEvents);
679 if (after) after->Scale(1./nEvents);
682 //____________________________________________________________________
684 AliFMDSharingFilter::RingHistos::Output(TList* dir)
690 // dir where to store
692 TList* d = DefineOutputList(dir);
699 //____________________________________________________________________