1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
19 //-----------------------------------------------------------------------------
20 /// \class AliMUONTrackHitPattern
22 /// This class propagates tracks to trigger chambers
23 /// searching for matching trigger tracks and fired strips.
25 /// To each track, a hit pattern for trigger chambers is set.
27 /// The main method is:
28 /// * ExecuteValidation
30 /// \author Diego Stocco
31 //-----------------------------------------------------------------------------
34 #include "AliMUONTrackHitPattern.h"
36 #include "AliMUONConstants.h"
37 #include "AliMUONVDigit.h"
38 #include "AliMUONVDigitStore.h"
39 #include "AliMUONGeometryTransformer.h"
40 #include "AliMUONLocalTrigger.h"
41 #include "AliMUONRecoParam.h"
42 #include "AliMUONTrack.h"
43 #include "AliMUONTrackExtrap.h"
44 #include "AliMUONTrackParam.h"
45 #include "AliMUONVTrackStore.h"
46 #include "AliMUONVTriggerStore.h"
47 #include "AliMUONTriggerTrack.h"
48 #include "AliMUONVTriggerTrackStore.h"
49 #include "AliMUONTriggerUtilities.h"
52 #include "AliMpSegmentation.h"
53 #include "AliMpVSegmentation.h"
54 #include "AliMpDEManager.h"
55 #include "AliMpArea.h"
56 #include "AliMpConstants.h"
59 #include "AliESDMuonTrack.h"
60 #include "AliCodeTimer.h"
62 #include <Riostream.h>
71 ClassImp(AliMUONTrackHitPattern) // Class implementation in ROOT context
75 //______________________________________________________________________________
76 AliMUONTrackHitPattern::AliMUONTrackHitPattern(const AliMUONRecoParam* recoParam,
77 const AliMUONGeometryTransformer& transformer,
78 const AliMUONVDigitStore& digitStore,
79 const AliMUONTriggerUtilities* triggerUtilities)
81 fkRecoParam(recoParam),
82 fkTransformer(transformer),
83 fkDigitStore(digitStore),
84 fkTriggerUtilities(triggerUtilities),
87 /// Default constructor
88 AliMUONTrackExtrap::SetField();
92 //______________________________________________________________________________
93 AliMUONTrackHitPattern::~AliMUONTrackHitPattern(void)
99 //______________________________________________________________________________
100 void AliMUONTrackHitPattern::ExecuteValidation(const AliMUONVTrackStore& trackStore,
101 const AliMUONVTriggerTrackStore& triggerTrackStore,
102 const AliMUONVTriggerStore& triggerStore) const
106 /// Loops on reco tracks, extrapolates them to trigger chambers
107 /// and searches for matching trigger tracks and digits
110 // Get the hit pattern for all trigger tracks
111 AliMUONTriggerTrack* triggerTrack;
112 TIter itTriggerTrack(triggerTrackStore.CreateIterator());
113 while ( ( triggerTrack = static_cast<AliMUONTriggerTrack*>(itTriggerTrack() ) ) ){
114 UShort_t pattern = GetHitPattern(triggerTrack);
115 triggerTrack->SetHitsPatternInTrigCh(pattern);
116 AliDebug(1, Form("Hit pattern: hits 0x%x slat %2i board %3i effFlag %i",
117 pattern & 0xFF, AliESDMuonTrack::GetSlatOrInfo(pattern),
118 triggerTrack->GetLoTrgNum(), AliESDMuonTrack::GetEffFlag(pattern)));
121 // Match tracker tracks with trigger tracks.
122 TIter itTrack(trackStore.CreateIterator());
125 const Int_t kFirstTrigCh = AliMUONConstants::NTrackingCh();
127 while ( ( track = static_cast<AliMUONTrack*>(itTrack()) ) )
129 AliMUONTrackParam trackParam(*((AliMUONTrackParam*) (track->GetTrackParamAtCluster()->Last())));
131 ApplyMCSCorrections(trackParam);
132 AliMUONTrackExtrap::ExtrapToZCov(&trackParam, AliMUONConstants::DefaultChamberZ(kFirstTrigCh)); // extrap to 1st trigger chamber
134 AliMUONTriggerTrack *matchedTriggerTrack = MatchTriggerTrack(track, trackParam, triggerTrackStore, triggerStore);
136 // Copy trigger tracks hit pattern if there is matching,
137 // otherwise calculate the hit pattern directly from tracker track:
138 // the obtained pattern is good for check, but not good for efficiency determination.
139 UShort_t pattern = matchedTriggerTrack ?
140 matchedTriggerTrack->GetHitsPatternInTrigCh() :
141 GetHitPattern(&trackParam);
143 track->SetHitsPatternInTrigCh(pattern);
148 //______________________________________________________________________________
149 AliMUONTriggerTrack *
150 AliMUONTrackHitPattern::MatchTriggerTrack(AliMUONTrack* track,
151 AliMUONTrackParam& trackParam,
152 const AliMUONVTriggerTrackStore& triggerTrackStore,
153 const AliMUONVTriggerStore& triggerStore) const
156 /// Match track with trigger track
159 Int_t matchTrigger = 0;
161 TMatrixD paramDiff(3,1);
163 Double_t chi2MatchTrigger = 0., minChi2MatchTrigger = 999.;
164 Int_t doubleMatch = -1; // Check if track matches 2 trigger tracks
165 Double_t doubleChi2 = -1.;
166 AliMUONTriggerTrack* doubleTriggerTrack = 0x0;
167 AliMUONTriggerTrack* matchedTriggerTrack = 0x0;
170 // Covariance matrix 3x3 (X,Y,slopeY) for trigger tracks
171 TMatrixD trackCov(3,3);
173 AliMUONTriggerTrack *triggerTrack;
174 TIter itTriggerTrack(triggerTrackStore.CreateIterator());
175 while ( ( triggerTrack = static_cast<AliMUONTriggerTrack*>(itTriggerTrack() ) ) )
177 AliMUONTrackExtrap::LinearExtrapToZCov(&trackParam, triggerTrack->GetZ11());
178 const TMatrixD& kParamCov = trackParam.GetCovariances();
180 Double_t xTrack = trackParam.GetNonBendingCoor();
181 Double_t yTrack = trackParam.GetBendingCoor();
182 Double_t ySlopeTrack = trackParam.GetBendingSlope();
184 paramDiff(0,0) = triggerTrack->GetX11() - xTrack;
185 paramDiff(1,0) = triggerTrack->GetY11() - yTrack;
186 paramDiff(2,0) = triggerTrack->GetSlopeY() - ySlopeTrack;
188 // Covariance matrix 3x3 (X,Y,slopeY) for tracker tracks
190 trackCov(0,0) = kParamCov(0,0);
191 trackCov(1,1) = kParamCov(2,2);
192 trackCov(2,2) = kParamCov(3,3);
193 trackCov(1,2) = kParamCov(2,3);
194 trackCov(2,1) = kParamCov(3,2);
196 // Covariance matrix 3x3 (X,Y,slopeY) for trigger tracks
197 TMatrixD trigCov(triggerTrack->GetCovariances());
199 TMatrixD sumCov(trackCov,TMatrixD::kPlus,trigCov);
200 if (sumCov.Determinant() != 0) {
203 TMatrixD tmp(sumCov,TMatrixD::kMult,paramDiff);
204 TMatrixD chi2M(paramDiff,TMatrixD::kTransposeMult,tmp);
207 AliWarning(" Determinant = 0");
208 Double_t sigma2 = 0.;
210 for (Int_t iVar = 0; iVar < 3; iVar++) {
211 sigma2 = trackCov(iVar,iVar) + trigCov(iVar,iVar);
212 chi2 += paramDiff(iVar,0) * paramDiff(iVar,0) / sigma2;
216 chi2 /= 3.; // Normalized Chi2: 3 degrees of freedom (X,Y,slopeY)
217 if (chi2 < GetRecoParam()->GetMaxNormChi2MatchTrigger())
219 Bool_t isDoubleTrack = (TMath::Abs(chi2 - minChi2MatchTrigger)<1.);
220 if (chi2 < minChi2MatchTrigger && chi2 < GetRecoParam()->GetMaxNormChi2MatchTrigger())
224 doubleMatch = loTrgNum;
225 doubleChi2 = chi2MatchTrigger;
226 doubleTriggerTrack = matchedTriggerTrack;
228 minChi2MatchTrigger = chi2;
229 chi2MatchTrigger = chi2;
230 loTrgNum = triggerTrack->GetLoTrgNum();
231 matchedTriggerTrack = triggerTrack;
232 AliMUONLocalTrigger* locTrg = triggerStore.FindLocal(loTrgNum);
234 if(locTrg->LoLpt()>0) matchTrigger = 2;
235 if(locTrg->LoHpt()>0) matchTrigger = 3;
237 else if(isDoubleTrack)
239 doubleMatch = triggerTrack->GetLoTrgNum();
245 { // If two trigger tracks match, select the one passing more trigger cuts
246 AliDebug(1, Form("Two candidates found: %i and %i",loTrgNum,doubleMatch));
247 AliMUONLocalTrigger* locTrg1 = triggerStore.FindLocal(doubleMatch);
248 if((locTrg1->LoLpt()>0 && matchTrigger<2) || (locTrg1->LoHpt() && matchTrigger<3))
250 if(locTrg1->LoHpt()>0) matchTrigger=3;
251 else matchTrigger = 2;
252 loTrgNum = doubleMatch;
253 chi2MatchTrigger = doubleChi2;
254 matchedTriggerTrack = doubleTriggerTrack;
258 track->SetMatchTrigger(matchTrigger);
259 track->SetChi2MatchTrigger(chi2MatchTrigger);
261 AliMUONLocalTrigger* locTrg = static_cast<AliMUONLocalTrigger*>(triggerStore.FindLocal(loTrgNum));
265 track->SetLocalTrigger(locTrg->LoCircuit(),
268 locTrg->GetDeviation(),
271 locTrg->GetTriggerWithoutChamber());
274 return matchedTriggerTrack;
278 //______________________________________________________________________________
279 UShort_t AliMUONTrackHitPattern::GetHitPattern(const AliMUONTriggerTrack* matchedTriggerTrack) const
282 /// Get hit pattern on trigger chambers for the current trigger track
284 UShort_t pattern = 0;
285 PerformTrigTrackMatch(pattern, matchedTriggerTrack);
290 //______________________________________________________________________________
291 UShort_t AliMUONTrackHitPattern::GetHitPattern(AliMUONTrackParam* trackParam) const
294 /// Get hit pattern on trigger chambers for the current tracker track
296 UShort_t pattern = 0;
298 const Int_t kNTrackingCh = AliMUONConstants::NTrackingCh();
300 for(Int_t ch=0; ch<4; ++ch)
302 Int_t iChamber = kNTrackingCh+ch;
303 AliMUONTrackExtrap::ExtrapToZCov(trackParam, AliMUONConstants::DefaultChamberZ(iChamber));
304 FindPadMatchingTrack(*trackParam, isMatch, iChamber);
305 for(Int_t cath=0; cath<2; ++cath)
307 if(isMatch[cath]) AliESDMuonTrack::SetFiredChamber(pattern, cath, ch);
311 // pattern obtained by propagation of tracker track
312 // when it does not match the trigger.
313 AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackerTrackPattern);
318 //______________________________________________________________________________
320 AliMUONTrackHitPattern::ApplyMCSCorrections(AliMUONTrackParam& trackParam) const
323 /// Returns uncertainties on extrapolated position.
324 /// Takes into account Branson plane corrections in the iron wall.
327 const Float_t kZFilterOut = AliMUONConstants::MuonFilterZEnd();
328 const Float_t kFilterThickness = kZFilterOut-AliMUONConstants::MuonFilterZBeg(); // cm
330 AliMUONTrackExtrap::ExtrapToZCov(&trackParam, kZFilterOut); // Extrap to muon filter end
331 AliMUONTrackExtrap::AddMCSEffect(&trackParam, kFilterThickness, AliMUONConstants::MuonFilterX0()); // Add MCS effects
336 //______________________________________________________________________________
338 AliMUONTrackHitPattern::FindPadMatchingTrack(const AliMUONTrackParam& trackParam,
339 Bool_t isMatch[2], Int_t iChamber) const
342 /// Given the tracker track position, searches for matching digits.
345 Float_t minMatchDist[2];
347 for(Int_t cath=0; cath<2; ++cath)
349 isMatch[cath]=kFALSE;
350 minMatchDist[cath]=fkMaxDistance/10.;
353 TIter next(fkDigitStore.CreateTriggerIterator());
354 AliMUONVDigit* mDigit;
356 while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
358 Int_t currDetElemId = mDigit->DetElemId();
359 Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId);
360 if(currCh!=iChamber) continue;
361 Int_t cathode = mDigit->Cathode();
362 Int_t ix = mDigit->PadX();
363 Int_t iy = mDigit->PadY();
364 Float_t xpad, ypad, zpad;
365 const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
366 ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode));
368 AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE);
369 Float_t xlocal1 = pad.GetPositionX();
370 Float_t ylocal1 = pad.GetPositionY();
371 Float_t dpx = pad.GetDimensionX();
372 Float_t dpy = pad.GetDimensionY();
374 fkTransformer.Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad);
375 Float_t matchDist = MinDistanceFromPad(xpad, ypad, zpad, dpx, dpy, trackParam);
376 if(matchDist>minMatchDist[cathode])continue;
377 isMatch[cathode] = kTRUE;
378 if(isMatch[0] && isMatch[1]) break;
379 minMatchDist[cathode] = matchDist;
384 //______________________________________________________________________________
386 AliMUONTrackHitPattern::MinDistanceFromPad(Float_t xPad, Float_t yPad, Float_t zPad,
387 Float_t dpx, Float_t dpy,
388 const AliMUONTrackParam& trackParam) const
391 /// Decides if the digit belongs to the tracker track.
394 AliMUONTrackParam trackParamAtPadZ(trackParam);
395 AliMUONTrackExtrap::LinearExtrapToZCov(&trackParamAtPadZ, zPad);
397 Float_t xTrackAtPad = trackParamAtPadZ.GetNonBendingCoor();
398 Float_t yTrackAtPad = trackParamAtPadZ.GetBendingCoor();
400 const Float_t kNSigma = GetRecoParam()->GetSigmaCutForTrigger();
402 const TMatrixD& kCovParam = trackParamAtPadZ.GetCovariances();
404 Float_t sigmaX = TMath::Sqrt(kCovParam(0,0));
405 Float_t sigmaY = TMath::Sqrt(kCovParam(2,2));
407 Float_t maxDistX = kNSigma * sigmaX; // in cm
408 Float_t maxDistY = kNSigma * sigmaY; // in cm
410 Float_t deltaX = TMath::Abs(xPad-xTrackAtPad)-dpx;
411 Float_t deltaY = TMath::Abs(yPad-yTrackAtPad)-dpy;
413 Float_t matchDist = fkMaxDistance;
414 if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY);
420 //_____________________________________________________________________________
421 Bool_t AliMUONTrackHitPattern::FindPadMatchingTrig(const TVector3& vec11, const TVector3& vec21,
422 Int_t matchedDetElemId[2], TObjArray& pads) const
425 /// Check slat and board number of digit matching trigger track
428 enum {kBending, kNonBending};
430 Float_t minMatchDist[2];
431 Int_t padsInCheckArea[2];
433 Int_t inputDetElemId = matchedDetElemId[0];
435 for(Int_t cath=0; cath<2; cath++){
436 minMatchDist[cath] = fkMaxDistance/10.;
437 padsInCheckArea[cath] = 0;
440 Int_t iChamber = AliMpDEManager::GetChamberId(inputDetElemId);
441 Int_t iSlat = inputDetElemId%100;
443 TIter next(fkDigitStore.CreateTriggerIterator());
444 AliMUONVDigit* mDigit;
445 TVector3 localExtrap;
447 Int_t previousDetElemId = -1;
449 while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
451 Int_t currDetElemId = mDigit->DetElemId();
452 Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId);
453 if ( currCh != iChamber ) continue;
454 Int_t currSlat = currDetElemId%100;
455 Int_t slatDiff = TMath::Abs(currSlat-iSlat);
456 if ( slatDiff>1 && slatDiff<17 ) continue; // Check neighbour slats
457 Int_t cathode = mDigit->Cathode();
458 Int_t ix = mDigit->PadX();
459 Int_t iy = mDigit->PadY();
460 const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
461 ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode));
463 AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE);
465 if ( currDetElemId != previousDetElemId ) {
466 PosInDetElemIdLocal(localExtrap, vec11, vec21, currDetElemId);
467 previousDetElemId = currDetElemId;
470 AliDebug(2, Form("\nDetElemId = %i Cathode = %i Pad = (%i,%i) = (%.2f,%.2f) Dim = (%.2f,%.2f) Track = (%.2f,%.2f)\n",
471 currDetElemId,cathode,ix,iy,pad.GetPositionX(),pad.GetPositionY(),pad.GetDimensionX(),pad.GetDimensionY(),localExtrap.X(),localExtrap.Y()));
472 Float_t matchDist = PadMatchTrack(pad, localExtrap);
473 if ( matchDist < fkMaxDistance/2. ) padsInCheckArea[cathode]++;
474 if ( matchDist > minMatchDist[cathode] ) continue;
475 if ( pads.At(cathode) ) delete pads.RemoveAt(cathode);
476 pads.AddAt((AliMpPad*)pad.Clone(),cathode);
477 minMatchDist[cathode] = matchDist;
478 matchedDetElemId[cathode] = currDetElemId; // Set the input detection element id to the matched one
481 // If track matches many pads, it is not good for effciency determination.
482 // However we still want to calculate the hit pattern.
483 for ( Int_t cath=0; cath<2; cath++ ){
484 if ( padsInCheckArea[cath] > 2 ) {
485 AliDebug(1, Form("padsInCheckArea[%i] = %i\n",cath,padsInCheckArea[cath]));
493 //_____________________________________________________________________________
494 Float_t AliMUONTrackHitPattern::PadMatchTrack(const AliMpPad& pad, const TVector3& trackPosAtPad) const
497 /// Decides if the digit belongs to the trigger track.
500 Float_t xPad = pad.GetPositionX();
501 Float_t yPad = pad.GetPositionY();
502 Float_t dpx = pad.GetDimensionX();
503 Float_t dpy = pad.GetDimensionY();
506 Float_t maxDist = GetRecoParam()->GetStripCutForTrigger() * 2. * TMath::Min(dpx,dpy); // cm
507 if ( maxDist<2. ) maxDist = 2.;
508 Float_t maxDistCheckArea = GetRecoParam()->GetMaxStripAreaForTrigger() * 2. * TMath::Min(dpx,dpy); // cm
510 Float_t matchDist = fkMaxDistance;
512 Float_t deltaX = TMath::Abs(xPad-trackPosAtPad.X())-dpx;
513 Float_t deltaY = TMath::Abs(yPad-trackPosAtPad.Y())-dpy;
514 Float_t maxDistX = maxDist;
515 Float_t maxDistY = maxDist;
517 if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY);
518 else if(deltaX<=maxDistCheckArea && deltaY<=maxDistCheckArea) matchDist = fkMaxDistance/5.;
523 //_____________________________________________________________________________
524 Int_t AliMUONTrackHitPattern::DetElemIdFromPos(Float_t x, Float_t y,
525 Int_t chamber, Int_t foundDetElemId[2]) const
528 /// Given the (x,y) position in the chamber,
529 /// it returns the corresponding slats
530 /// Caveat: at the border the result is not univoque
535 foundDetElemId[0] = foundDetElemId[1] = 0;
536 AliMpArea pointArea(x, y, 2.*AliMpConstants::LengthTolerance(), 2.*AliMpConstants::LengthTolerance());
538 for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){
539 Int_t detElemId = it.CurrentDEId();
540 AliMpArea* deArea = fkTransformer.GetDEArea(detElemId);
542 if ( deArea->Contains(pointArea) ) {
543 foundDetElemId[nFound++] = detElemId;
544 if ( nFound == 2 ) break;
546 else if ( nFound > 0 ) break;
547 } // loop on detElemId
554 //_____________________________________________________________________________
555 Bool_t AliMUONTrackHitPattern::PadsFromPos(const TVector3& vec11, const TVector3& vec21,
556 Int_t detElemId, TObjArray& pads) const
559 /// Given the (x,y) position in the chamber,
560 /// it returns the corresponding local board
566 PosInDetElemIdLocal(localCoor, vec11, vec21, detElemId);
567 for ( Int_t icath=0; icath<2; icath++ ) {
568 const AliMpVSegmentation* seg =
569 AliMpSegmentation::Instance()
570 ->GetMpSegmentation(detElemId,AliMp::GetCathodType(icath));
571 AliMpPad pad = seg->PadByPosition(localCoor.X(),localCoor.Y(),kFALSE);
572 if ( pad.IsValid() ) {
573 pads.AddAt(pad.Clone(), icath);
577 return pads.GetEntries();
581 //_____________________________________________________________________________
582 Bool_t AliMUONTrackHitPattern::PosInDetElemIdLocal(TVector3& localCoor, const TVector3& globalPoint1,
583 const TVector3& globalPoint2, Int_t detElemId) const
585 /// Given two points belonging to a line (global coordinates)
586 /// it returns the intersection point with the detElemId (local coordinates)
588 Double_t xloc, yloc, zloc;
589 fkTransformer.Global2Local(detElemId, globalPoint1.X(), globalPoint1.Y(), globalPoint1.Z(), xloc, yloc, zloc);
590 TVector3 localPoint1(xloc, yloc, zloc);
591 fkTransformer.Global2Local(detElemId, globalPoint2.X(), globalPoint2.Y(), globalPoint2.Z(), xloc, yloc, zloc);
592 TVector3 localPoint2(xloc, yloc, zloc);
593 localCoor = localPoint1 - ( localPoint1.Z() / ( localPoint2.Z() - localPoint1.Z() ) ) * ( localPoint2 - localPoint1 );
599 //_____________________________________________________________________________
600 Bool_t AliMUONTrackHitPattern::IsCloseToAccEdge(TObjArray& pads, Int_t detElemId, Float_t coor[2]) const
602 AliMpArea* deArea = fkTransformer.GetDEArea(detElemId);
603 Float_t dpx = ((AliMpPad*)pads.At(1))->GetDimensionX();
604 Float_t dpy = ((AliMpPad*)pads.At(0))->GetDimensionY();
605 Float_t resolution[2] = { 0.75*dpx, 0.75*dpy };
606 Float_t sign[3] = {0., 1., -1.};
607 for ( Int_t ineighx=0; ineighx<3; ineighx++ ) {
608 for ( Int_t ineighy=0; ineighy<3; ineighy++ ) {
609 AliMpArea pointArea(coor[0]+sign[ineighx]*resolution[0],
610 coor[1]+sign[ineighy]*resolution[1],
611 2.*AliMpConstants::LengthTolerance(),
612 2.*AliMpConstants::LengthTolerance());
613 if ( ! deArea->Contains(pointArea) ) return kTRUE;
614 } // loop on y neighbours
615 } // loop on x neighbours
620 //_____________________________________________________________________________
621 Bool_t AliMUONTrackHitPattern::IsMasked(const AliMpPad& pad, Int_t detElemId, Int_t cathode, const TVector3& vec11, const TVector3& vec21) const
624 /// Check if pad or its neighbours are masked
629 if ( fkTriggerUtilities->IsMasked(pad, detElemId, cathode) ) ++nMasked;
631 // Check closest neighbour
634 PosInDetElemIdLocal(localCoor, vec11, vec21, detElemId);
636 Float_t padPos[2] = { pad.GetPositionX(), pad.GetPositionY()};
637 Float_t padDim[2] = { pad.GetDimensionX(), pad.GetDimensionY()};
638 Float_t inpactPos[2] = { localCoor.X(), localCoor.Y()};
639 Float_t sign[2] = {-1., 1.};
640 Int_t icoor = 1-cathode;
641 Int_t addSlatSign[3] = {0,1,-1};
642 Int_t inputCh = AliMpDEManager::GetChamberId(detElemId)+1;
643 Int_t inputSlat = detElemId%100;
646 for ( Int_t ineigh=0; ineigh<2; ineigh++ ) {
647 newPos[1-icoor] = inpactPos[1-icoor];
648 newPos[icoor] = inpactPos[icoor] + 1.05 * sign[ineigh] * padDim[icoor];
649 if ( TMath::Abs(newPos[icoor] - padPos[icoor]) < padDim[icoor] ) continue;
650 const AliMpVSegmentation* seg =
651 AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
652 AliMpPad neighPad = seg->PadByPosition(newPos[0],newPos[1],kFALSE);
653 if ( neighPad.IsValid() ) {
654 if ( fkTriggerUtilities->IsMasked(neighPad, detElemId, cathode) ) ++nMasked;
657 TVector3 deltaVec(newPos[0]-inpactPos[0],newPos[1]-inpactPos[1],0.);
658 TVector3 transVec11 = vec11+deltaVec;
659 TVector3 transVec21 = vec21+deltaVec;
660 TObjArray padsFromPos;
661 padsFromPos.SetOwner();
662 for ( Int_t iAddSlat=0; iAddSlat<2; iAddSlat++ ) {
663 Int_t currSlat = (inputSlat + addSlatSign[iAddSlat])%18;
664 Int_t currDetElemId = 100 * inputCh + currSlat;
665 PadsFromPos(transVec11,transVec21,currDetElemId,padsFromPos);
666 AliMpPad* currPad = (AliMpPad*)padsFromPos.UncheckedAt(cathode);
667 Bool_t isMasked = ( currPad ) ? fkTriggerUtilities->IsMasked(*currPad, currDetElemId, cathode) : kFALSE;
668 padsFromPos.Delete();
669 if ( isMasked ) ++nMasked;
672 } // loop on neigbours
674 Double_t maskedProb = ((Double_t)nMasked)/3.;
675 if ( gRandom->Rndm() < maskedProb ) return kTRUE;
681 //_____________________________________________________________________________
682 Bool_t AliMUONTrackHitPattern::PerformTrigTrackMatch(UShort_t &pattern,
683 const AliMUONTriggerTrack* matchedTrigTrack) const
686 /// It searches for matching digits around the trigger track.
689 AliCodeTimerAuto("",0);
691 enum {kBending, kNonBending};
693 TArrayF zMeanChamber(AliMUONConstants::NTriggerCh());
694 zMeanChamber[0] = matchedTrigTrack->GetZ11();
695 zMeanChamber[1] = matchedTrigTrack->GetZ11() + AliMUONConstants::DefaultChamberZ(11) - AliMUONConstants::DefaultChamberZ(10);
696 zMeanChamber[2] = matchedTrigTrack->GetZ21();
697 zMeanChamber[3] = matchedTrigTrack->GetZ21() + AliMUONConstants::DefaultChamberZ(13) - AliMUONConstants::DefaultChamberZ(12);
699 TArrayI digitPerTrack(2);
700 digitPerTrack.Reset();
702 Float_t trackIntersectCh[2];
704 Float_t slopeX = matchedTrigTrack->GetSlopeX();
705 Float_t slopeY = matchedTrigTrack->GetSlopeY();
707 Float_t z11 = matchedTrigTrack->GetZ11();
708 Float_t x11 = slopeX * z11;
709 Float_t y11 = matchedTrigTrack->GetY11();
710 Float_t z21 = matchedTrigTrack->GetZ21();
711 Float_t x21 = slopeX * z21;
712 Float_t y21 = y11 + slopeY * (z21-z11);
713 TVector3 vec11(x11, y11, z11), vec21(x21, y21, z21);
716 Int_t firstSlat = -1, firstBoard = -1;
717 AliESDMuonTrack::EAliTriggerChPatternFlag goodForEff = AliESDMuonTrack::kBoardEff;
718 TObjArray matchedPads(2), padsFromPos(2), validPads(2);
719 matchedPads.SetOwner(); padsFromPos.SetOwner();
720 Int_t matchedDetElemId[2], detElemIdFromTrack[2];
722 for(Int_t ich=0; ich<AliMUONConstants::NTriggerCh(); ich++) { // chamber loop
724 // searching track intersection with chambers (first approximation)
725 Float_t deltaZ = zMeanChamber[ich] - zMeanChamber[0];
726 trackIntersectCh[0] = zMeanChamber[ich] * slopeX;
727 trackIntersectCh[1] = y11 + deltaZ * slopeY;
728 Int_t nFound = DetElemIdFromPos(trackIntersectCh[0], trackIntersectCh[1], 11+ich, detElemIdFromTrack);
730 // track is rejected since the extrapolated track
731 // does not match a slat (border effects)
732 AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackOutsideGeometry);
733 goodForEff = AliESDMuonTrack::kNoEff;
734 AliDebug(1, "Warning: trigger track outside trigger chamber\n");
738 matchedDetElemId[0] = matchedDetElemId[1] = detElemIdFromTrack[0];
740 if ( ! FindPadMatchingTrig(vec11, vec21, matchedDetElemId, matchedPads) ) {
741 // if ! FindPadMatchingTrig => too many digits matching pad =>
742 // => Event not clear => Do not use for efficiency calculation
743 AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesManyPads);
744 goodForEff = AliESDMuonTrack::kNoEff;
745 AliDebug(1, Form("Warning: track = %p (%i) matches many pads. Rejected!\n",(void *)matchedTrigTrack, matchedDetElemId[0]));
750 Int_t mostProbDEmatched = detElemIdFromTrack[0];
751 for ( Int_t icath=0; icath<2; icath++ ) {
752 if ( matchedPads.UncheckedAt(icath) ) {
754 // Fill pattern anyway
755 AliESDMuonTrack::SetFiredChamber(pattern, icath, ich);
756 digitPerTrack[icath]++;
757 mostProbDEmatched = matchedDetElemId[icath];
760 Int_t mostProbDEfromTrack = detElemIdFromTrack[0];
761 for ( Int_t ifound=0; ifound<nFound; ifound++ ) {
762 if ( detElemIdFromTrack[ifound] == mostProbDEmatched ) {
763 mostProbDEfromTrack = mostProbDEmatched;
768 if ( goodForEff == AliESDMuonTrack::kNoEff ) continue;
770 if ( nMatched < 2 ) PadsFromPos(vec11, vec21, mostProbDEfromTrack, padsFromPos);
772 for ( Int_t cath=0; cath<2; cath++ ) {
773 if ( matchedPads.UncheckedAt(cath) ) validPads.AddAt(matchedPads.UncheckedAt(cath),cath);
774 else if ( padsFromPos.UncheckedAt(cath) ) {
775 AliMpPad* currPad = (AliMpPad*)padsFromPos.UncheckedAt(cath);
776 validPads.AddAt(currPad,cath);
777 if ( IsMasked(*currPad, mostProbDEfromTrack, cath, vec11, vec21) ) {
778 // Check if strip was masked (if inefficient strip is found)
779 AliESDMuonTrack::AddEffInfo(pattern,25,AliESDMuonTrack::kNoEff); // pad is masked
780 AliDebug(1,Form("DetElemId %i cath %i strip %i is masked: effFlag 0", mostProbDEfromTrack, cath, currPad->GetLocalBoardId(0)));
781 goodForEff = AliESDMuonTrack::kNoEff;
784 else goodForEff = AliESDMuonTrack::kNoEff;
785 } // loop on cathodes
787 if ( goodForEff != AliESDMuonTrack::kNoEff ) {
789 if ( nMatched == 0 && IsCloseToAccEdge(padsFromPos, mostProbDEfromTrack, trackIntersectCh) ) {
790 // Non of cathodes is fired.
791 // If we are close to the edge of the RPC
792 // it could be a problem of acceptance
793 AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackOutsideGeometry);
794 goodForEff = AliESDMuonTrack::kNoEff;
795 AliDebug(1, "Warning: trigger track at the edge of the chamber\n");
798 Int_t currSlat = mostProbDEmatched%100;
799 if ( firstSlat < 0 ) firstSlat = currSlat;
800 else if ( currSlat != firstSlat ) {
801 goodForEff = AliESDMuonTrack::kChEff;
802 firstSlat = AliESDMuonTrack::kCrossDifferentSlats;
805 if ( firstBoard < 0 ) firstBoard = ((AliMpPad*)validPads[kBending])->GetLocalBoardId(0);
807 for ( Int_t cath=0; cath<2; cath++ ){
809 if ( goodForEff == AliESDMuonTrack::kBoardEff) {
810 Bool_t atLeastOneLoc = kFALSE;
811 AliMpPad* currPad = (AliMpPad*)validPads.UncheckedAt(cath);
812 for ( Int_t iloc=0; iloc<currPad->GetNofLocations(); iloc++) {
813 if ( currPad->GetLocalBoardId(iloc) == firstBoard ) {
814 atLeastOneLoc = kTRUE;
817 } // loop on locations
818 if ( ! atLeastOneLoc ) goodForEff = AliESDMuonTrack::kSlatEff;
820 } // loop on cathodes
821 } // if track good for efficiency
822 matchedPads.Delete();
823 padsFromPos.Delete();
824 } // end chamber loop
826 if ( goodForEff == AliESDMuonTrack::kNoEff ) return kFALSE;
828 for(Int_t cath=0; cath<2; cath++){
829 if(digitPerTrack[cath]<3) {
830 // track is rejected since the number of associated
831 // digits found is less than 3.
832 AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesFewPads);
833 goodForEff = AliESDMuonTrack::kNoEff;
834 AliDebug(1, Form("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath));
836 } // loop on cathodes
838 if ( goodForEff == AliESDMuonTrack::kNoEff ) return kFALSE;
840 AliESDMuonTrack::AddEffInfo(pattern, firstSlat, goodForEff);