Validation fail only in case the merging part of job failed
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackHitPattern.cxx
CommitLineData
7771752e 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
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 **************************************************************************/
15
ea94c18b 16/* $Id$ */
17
18
3d1463c8 19//-----------------------------------------------------------------------------
7771752e 20/// \class AliMUONTrackHitPattern
21///
22/// This class propagates tracks to trigger chambers
683cb6c5 23/// searching for matching trigger tracks and fired strips.
7771752e 24///
25/// To each track, a hit pattern for trigger chambers is set.
67c201be 26///
7771752e 27/// The main method is:
683cb6c5 28/// * ExecuteValidation
7771752e 29///
30/// \author Diego Stocco
3d1463c8 31//-----------------------------------------------------------------------------
7771752e 32
33
34#include "AliMUONTrackHitPattern.h"
7ec3b9cf 35
7771752e 36#include "AliMUONConstants.h"
7ec3b9cf 37#include "AliMUONVDigit.h"
64f628e9 38#include "AliMUONVDigitStore.h"
7771752e 39#include "AliMUONGeometryTransformer.h"
7771752e 40#include "AliMUONLocalTrigger.h"
a0dc65b4 41#include "AliMUONRecoParam.h"
7ec3b9cf 42#include "AliMUONTrack.h"
43#include "AliMUONTrackExtrap.h"
44#include "AliMUONTrackParam.h"
45#include "AliMUONVTrackStore.h"
46#include "AliMUONVTriggerStore.h"
d5315275 47#include "AliMUONTriggerTrack.h"
48#include "AliMUONVTriggerTrackStore.h"
49#include "AliMUONTriggerUtilities.h"
50
7771752e 51#include "AliMpPad.h"
7771752e 52#include "AliMpSegmentation.h"
7ec3b9cf 53#include "AliMpVSegmentation.h"
fda59e58 54#include "AliMpDEManager.h"
d5315275 55#include "AliMpArea.h"
683cb6c5 56#include "AliMpConstants.h"
ea94c18b 57
ea94c18b 58#include "AliLog.h"
67c201be 59#include "AliESDMuonTrack.h"
d5315275 60#include "AliCodeTimer.h"
ea94c18b 61
7771752e 62#include <Riostream.h>
d5315275 63#include <TArrayI.h>
7771752e 64#include <TMath.h>
65#include <TMatrixD.h>
d5315275 66#include <TVector3.h>
67#include <TArrayF.h>
68#include <TRandom.h>
7771752e 69
70/// \cond CLASSIMP
71ClassImp(AliMUONTrackHitPattern) // Class implementation in ROOT context
72/// \endcond
73
74
75//______________________________________________________________________________
a0dc65b4 76AliMUONTrackHitPattern::AliMUONTrackHitPattern(const AliMUONRecoParam* recoParam,
77 const AliMUONGeometryTransformer& transformer,
d5315275 78 const AliMUONVDigitStore& digitStore,
79 const AliMUONTriggerUtilities* triggerUtilities)
a0dc65b4 80: TObject(),
9b1e069f 81fkRecoParam(recoParam),
82fkTransformer(transformer),
64f628e9 83fkDigitStore(digitStore),
d5315275 84fkTriggerUtilities(triggerUtilities),
a0dc65b4 85fkMaxDistance(99999.)
7771752e 86{
d5315275 87 /// Default constructor
88 AliMUONTrackExtrap::SetField();
7771752e 89}
90
91
92//______________________________________________________________________________
93AliMUONTrackHitPattern::~AliMUONTrackHitPattern(void)
94{
7ec3b9cf 95 /// Destructor
7771752e 96}
97
683cb6c5 98
99//______________________________________________________________________________
9b1e069f 100void AliMUONTrackHitPattern::ExecuteValidation(const AliMUONVTrackStore& trackStore,
683cb6c5 101 const AliMUONVTriggerTrackStore& triggerTrackStore,
102 const AliMUONVTriggerStore& triggerStore) const
103{
104 //
105 /// Main method:
106 /// Loops on reco tracks, extrapolates them to trigger chambers
107 /// and searches for matching trigger tracks and digits
108 //
109
67c201be 110 // Get the hit pattern for all trigger tracks
111 AliMUONTriggerTrack* triggerTrack;
112 TIter itTriggerTrack(triggerTrackStore.CreateIterator());
113 while ( ( triggerTrack = static_cast<AliMUONTriggerTrack*>(itTriggerTrack() ) ) ){
64f628e9 114 UShort_t pattern = GetHitPattern(triggerTrack);
67c201be 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)));
119 }
683cb6c5 120
67c201be 121 // Match tracker tracks with trigger tracks.
683cb6c5 122 TIter itTrack(trackStore.CreateIterator());
123 AliMUONTrack* track;
124
125 const Int_t kFirstTrigCh = AliMUONConstants::NTrackingCh();
126
127 while ( ( track = static_cast<AliMUONTrack*>(itTrack()) ) )
128 {
129 AliMUONTrackParam trackParam(*((AliMUONTrackParam*) (track->GetTrackParamAtCluster()->Last())));
130
131 ApplyMCSCorrections(trackParam);
132 AliMUONTrackExtrap::ExtrapToZCov(&trackParam, AliMUONConstants::DefaultChamberZ(kFirstTrigCh)); // extrap to 1st trigger chamber
133
134 AliMUONTriggerTrack *matchedTriggerTrack = MatchTriggerTrack(track, trackParam, triggerTrackStore, triggerStore);
135
67c201be 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() :
64f628e9 141 GetHitPattern(&trackParam);
67c201be 142
683cb6c5 143 track->SetHitsPatternInTrigCh(pattern);
144 }
145}
146
147
148//______________________________________________________________________________
149AliMUONTriggerTrack *
150AliMUONTrackHitPattern::MatchTriggerTrack(AliMUONTrack* track,
151 AliMUONTrackParam& trackParam,
152 const AliMUONVTriggerTrackStore& triggerTrackStore,
153 const AliMUONVTriggerStore& triggerStore) const
154{
155 //
156 /// Match track with trigger track
157 //
158
159 Int_t matchTrigger = 0;
160 Int_t loTrgNum(-1);
bdfb6eef 161 TMatrixD paramDiff(3,1);
683cb6c5 162 Double_t chi2;
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;
7ec3b9cf 168
683cb6c5 169
bdfb6eef 170 // Covariance matrix 3x3 (X,Y,slopeY) for trigger tracks
683cb6c5 171 TMatrixD trackCov(3,3);
fda59e58 172
683cb6c5 173 AliMUONTriggerTrack *triggerTrack;
174 TIter itTriggerTrack(triggerTrackStore.CreateIterator());
175 while ( ( triggerTrack = static_cast<AliMUONTriggerTrack*>(itTriggerTrack() ) ) )
176 {
bdfb6eef 177 AliMUONTrackExtrap::LinearExtrapToZCov(&trackParam, triggerTrack->GetZ11());
178 const TMatrixD& kParamCov = trackParam.GetCovariances();
179
180 Double_t xTrack = trackParam.GetNonBendingCoor();
181 Double_t yTrack = trackParam.GetBendingCoor();
182 Double_t ySlopeTrack = trackParam.GetBendingSlope();
183
184 paramDiff(0,0) = triggerTrack->GetX11() - xTrack;
185 paramDiff(1,0) = triggerTrack->GetY11() - yTrack;
186 paramDiff(2,0) = triggerTrack->GetSlopeY() - ySlopeTrack;
187
188 // Covariance matrix 3x3 (X,Y,slopeY) for tracker tracks
189 trackCov.Zero();
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);
195
196 // Covariance matrix 3x3 (X,Y,slopeY) for trigger tracks
197 TMatrixD trigCov(triggerTrack->GetCovariances());
198
199 TMatrixD sumCov(trackCov,TMatrixD::kPlus,trigCov);
200 if (sumCov.Determinant() != 0) {
201 sumCov.Invert();
202
683cb6c5 203 TMatrixD tmp(sumCov,TMatrixD::kMult,paramDiff);
204 TMatrixD chi2M(paramDiff,TMatrixD::kTransposeMult,tmp);
bdfb6eef 205 chi2 = chi2M(0,0);
206 } else {
207 AliWarning(" Determinant = 0");
208 Double_t sigma2 = 0.;
683cb6c5 209 chi2 = 0.;
bdfb6eef 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;
213 }
683cb6c5 214 }
fda59e58 215
683cb6c5 216 chi2 /= 3.; // Normalized Chi2: 3 degrees of freedom (X,Y,slopeY)
a0dc65b4 217 if (chi2 < GetRecoParam()->GetMaxNormChi2MatchTrigger())
7ec3b9cf 218 {
683cb6c5 219 Bool_t isDoubleTrack = (TMath::Abs(chi2 - minChi2MatchTrigger)<1.);
a0dc65b4 220 if (chi2 < minChi2MatchTrigger && chi2 < GetRecoParam()->GetMaxNormChi2MatchTrigger())
7ec3b9cf 221 {
683cb6c5 222 if(isDoubleTrack)
223 {
224 doubleMatch = loTrgNum;
225 doubleChi2 = chi2MatchTrigger;
226 doubleTriggerTrack = matchedTriggerTrack;
fda59e58 227 }
683cb6c5 228 minChi2MatchTrigger = chi2;
229 chi2MatchTrigger = chi2;
230 loTrgNum = triggerTrack->GetLoTrgNum();
231 matchedTriggerTrack = triggerTrack;
232 AliMUONLocalTrigger* locTrg = triggerStore.FindLocal(loTrgNum);
233 matchTrigger = 1;
234 if(locTrg->LoLpt()>0) matchTrigger = 2;
235 if(locTrg->LoHpt()>0) matchTrigger = 3;
236 }
237 else if(isDoubleTrack)
238 {
239 doubleMatch = triggerTrack->GetLoTrgNum();
240 doubleChi2 = chi2;
7ec3b9cf 241 }
7771752e 242 }
683cb6c5 243 }
244 if(doubleMatch>=0)
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))
249 {
250 if(locTrg1->LoHpt()>0) matchTrigger=3;
251 else matchTrigger = 2;
252 loTrgNum = doubleMatch;
253 chi2MatchTrigger = doubleChi2;
254 matchedTriggerTrack = doubleTriggerTrack;
255 }
256 }
257
258 track->SetMatchTrigger(matchTrigger);
683cb6c5 259 track->SetChi2MatchTrigger(chi2MatchTrigger);
260
261 AliMUONLocalTrigger* locTrg = static_cast<AliMUONLocalTrigger*>(triggerStore.FindLocal(loTrgNum));
262
263 if (locTrg)
264 {
265 track->SetLocalTrigger(locTrg->LoCircuit(),
266 locTrg->LoStripX(),
267 locTrg->LoStripY(),
00d46f24 268 locTrg->GetDeviation(),
683cb6c5 269 locTrg->LoLpt(),
00d46f24 270 locTrg->LoHpt(),
271 locTrg->GetTriggerWithoutChamber());
683cb6c5 272 }
273
274 return matchedTriggerTrack;
275}
276
277
278//______________________________________________________________________________
d5315275 279UShort_t AliMUONTrackHitPattern::GetHitPattern(const AliMUONTriggerTrack* matchedTriggerTrack) const
683cb6c5 280{
281 //
67c201be 282 /// Get hit pattern on trigger chambers for the current trigger track
683cb6c5 283 //
284 UShort_t pattern = 0;
64f628e9 285 PerformTrigTrackMatch(pattern, matchedTriggerTrack);
67c201be 286 return pattern;
287}
683cb6c5 288
54355f2c 289
67c201be 290//______________________________________________________________________________
64f628e9 291UShort_t AliMUONTrackHitPattern::GetHitPattern(AliMUONTrackParam* trackParam) const
67c201be 292{
293 //
294 /// Get hit pattern on trigger chambers for the current tracker track
295 //
296 UShort_t pattern = 0;
297 Bool_t isMatch[2];
298 const Int_t kNTrackingCh = AliMUONConstants::NTrackingCh();
683cb6c5 299
300 for(Int_t ch=0; ch<4; ++ch)
301 {
302 Int_t iChamber = kNTrackingCh+ch;
54355f2c 303 AliMUONTrackExtrap::ExtrapToZCov(trackParam, AliMUONConstants::DefaultChamberZ(iChamber));
64f628e9 304 FindPadMatchingTrack(*trackParam, isMatch, iChamber);
683cb6c5 305 for(Int_t cath=0; cath<2; ++cath)
306 {
67c201be 307 if(isMatch[cath]) AliESDMuonTrack::SetFiredChamber(pattern, cath, ch);
683cb6c5 308 }
309 }
683cb6c5 310
67c201be 311 // pattern obtained by propagation of tracker track
312 // when it does not match the trigger.
313 AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackerTrackPattern);
683cb6c5 314
67c201be 315 return pattern;
683cb6c5 316}
317
683cb6c5 318//______________________________________________________________________________
319void
320AliMUONTrackHitPattern::ApplyMCSCorrections(AliMUONTrackParam& trackParam) const
321{
322 //
323 /// Returns uncertainties on extrapolated position.
324 /// Takes into account Branson plane corrections in the iron wall.
325 //
326
327 const Float_t kZFilterOut = AliMUONConstants::MuonFilterZEnd();
37a615ac 328 const Float_t kFilterThickness = kZFilterOut-AliMUONConstants::MuonFilterZBeg(); // cm
683cb6c5 329
330 AliMUONTrackExtrap::ExtrapToZCov(&trackParam, kZFilterOut); // Extrap to muon filter end
331 AliMUONTrackExtrap::AddMCSEffect(&trackParam, kFilterThickness, AliMUONConstants::MuonFilterX0()); // Add MCS effects
332 return;
333}
334
335
336//______________________________________________________________________________
7ec3b9cf 337void
64f628e9 338AliMUONTrackHitPattern::FindPadMatchingTrack(const AliMUONTrackParam& trackParam,
fda59e58 339 Bool_t isMatch[2], Int_t iChamber) const
7771752e 340{
341 //
683cb6c5 342 /// Given the tracker track position, searches for matching digits.
7771752e 343 //
344
345 Float_t minMatchDist[2];
346
7ec3b9cf 347 for(Int_t cath=0; cath<2; ++cath)
348 {
349 isMatch[cath]=kFALSE;
683cb6c5 350 minMatchDist[cath]=fkMaxDistance/10.;
7771752e 351 }
352
64f628e9 353 TIter next(fkDigitStore.CreateTriggerIterator());
7ec3b9cf 354 AliMUONVDigit* mDigit;
fda59e58 355
7ec3b9cf 356 while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
357 {
358 Int_t currDetElemId = mDigit->DetElemId();
fda59e58 359 Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId);
360 if(currCh!=iChamber) continue;
7ec3b9cf 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));
367
168e9c4d 368 AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE);
6e97fbb8 369 Float_t xlocal1 = pad.GetPositionX();
370 Float_t ylocal1 = pad.GetPositionY();
371 Float_t dpx = pad.GetDimensionX();
372 Float_t dpy = pad.GetDimensionY();
373
9b1e069f 374 fkTransformer.Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad);
7ec3b9cf 375 Float_t matchDist = MinDistanceFromPad(xpad, ypad, zpad, dpx, dpy, trackParam);
376 if(matchDist>minMatchDist[cathode])continue;
377 isMatch[cathode] = kTRUE;
fda59e58 378 if(isMatch[0] && isMatch[1]) break;
7ec3b9cf 379 minMatchDist[cathode] = matchDist;
7771752e 380 }
7771752e 381}
382
383
384//______________________________________________________________________________
7ec3b9cf 385Float_t
386AliMUONTrackHitPattern::MinDistanceFromPad(Float_t xPad, Float_t yPad, Float_t zPad,
387 Float_t dpx, Float_t dpy,
388 const AliMUONTrackParam& trackParam) const
7771752e 389{
390 //
683cb6c5 391 /// Decides if the digit belongs to the tracker track.
7771752e 392 //
7771752e 393
fda59e58 394 AliMUONTrackParam trackParamAtPadZ(trackParam);
bdfb6eef 395 AliMUONTrackExtrap::LinearExtrapToZCov(&trackParamAtPadZ, zPad);
fda59e58 396
397 Float_t xTrackAtPad = trackParamAtPadZ.GetNonBendingCoor();
398 Float_t yTrackAtPad = trackParamAtPadZ.GetBendingCoor();
7771752e 399
a0dc65b4 400 const Float_t kNSigma = GetRecoParam()->GetSigmaCutForTrigger();
fda59e58 401
402 const TMatrixD& kCovParam = trackParamAtPadZ.GetCovariances();
403
404 Float_t sigmaX = TMath::Sqrt(kCovParam(0,0));
405 Float_t sigmaY = TMath::Sqrt(kCovParam(2,2));
406
407 Float_t maxDistX = kNSigma * sigmaX; // in cm
408 Float_t maxDistY = kNSigma * sigmaY; // in cm
7771752e 409
410 Float_t deltaX = TMath::Abs(xPad-xTrackAtPad)-dpx;
411 Float_t deltaY = TMath::Abs(yPad-yTrackAtPad)-dpy;
412
683cb6c5 413 Float_t matchDist = fkMaxDistance;
7771752e 414 if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY);
fda59e58 415
7771752e 416 return matchDist;
417}
418
419
683cb6c5 420//_____________________________________________________________________________
d5315275 421Bool_t AliMUONTrackHitPattern::FindPadMatchingTrig(const TVector3& vec11, const TVector3& vec21,
422 Int_t matchedDetElemId[2], TObjArray& pads) const
683cb6c5 423{
d5315275 424 //
425 /// Check slat and board number of digit matching trigger track
426 //
427
428 enum {kBending, kNonBending};
429
430 Float_t minMatchDist[2];
431 Int_t padsInCheckArea[2];
432
433 Int_t inputDetElemId = matchedDetElemId[0];
434
435 for(Int_t cath=0; cath<2; cath++){
436 minMatchDist[cath] = fkMaxDistance/10.;
437 padsInCheckArea[cath] = 0;
438 }
439
440 Int_t iChamber = AliMpDEManager::GetChamberId(inputDetElemId);
441 Int_t iSlat = inputDetElemId%100;
442
443 TIter next(fkDigitStore.CreateTriggerIterator());
444 AliMUONVDigit* mDigit;
445 TVector3 localExtrap;
446
447 Int_t previousDetElemId = -1;
448
449 while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
450 {
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));
ad30b53f 462
d5315275 463 AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE);
683cb6c5 464
d5315275 465 if ( currDetElemId != previousDetElemId ) {
466 PosInDetElemIdLocal(localExtrap, vec11, vec21, currDetElemId);
467 previousDetElemId = currDetElemId;
683cb6c5 468 }
d5315275 469
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
479 } // loop on digits
480
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]));
486 return kFALSE;
67c201be 487 }
d5315275 488 }
489
490 return kTRUE;
683cb6c5 491}
492
493//_____________________________________________________________________________
d5315275 494Float_t AliMUONTrackHitPattern::PadMatchTrack(const AliMpPad& pad, const TVector3& trackPosAtPad) const
683cb6c5 495{
d5315275 496 //
497 /// Decides if the digit belongs to the trigger track.
498 //
499
500 Float_t xPad = pad.GetPositionX();
501 Float_t yPad = pad.GetPositionY();
502 Float_t dpx = pad.GetDimensionX();
503 Float_t dpy = pad.GetDimensionY();
504
683cb6c5 505
a0dc65b4 506 Float_t maxDist = GetRecoParam()->GetStripCutForTrigger() * 2. * TMath::Min(dpx,dpy); // cm
d5315275 507 if ( maxDist<2. ) maxDist = 2.;
a0dc65b4 508 Float_t maxDistCheckArea = GetRecoParam()->GetMaxStripAreaForTrigger() * 2. * TMath::Min(dpx,dpy); // cm
683cb6c5 509
d5315275 510 Float_t matchDist = fkMaxDistance;
683cb6c5 511
d5315275 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;
683cb6c5 516
d5315275 517 if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY);
518 else if(deltaX<=maxDistCheckArea && deltaY<=maxDistCheckArea) matchDist = fkMaxDistance/5.;
519 return matchDist;
683cb6c5 520}
521
522
523//_____________________________________________________________________________
524Int_t AliMUONTrackHitPattern::DetElemIdFromPos(Float_t x, Float_t y,
d5315275 525 Int_t chamber, Int_t foundDetElemId[2]) const
683cb6c5 526{
d5315275 527 //
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
531 //
532
533 Int_t nFound = 0;
534
535 foundDetElemId[0] = foundDetElemId[1] = 0;
536 AliMpArea pointArea(x, y, 2.*AliMpConstants::LengthTolerance(), 2.*AliMpConstants::LengthTolerance());
537 AliMpDEIterator it;
538 for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){
539 Int_t detElemId = it.CurrentDEId();
540 AliMpArea* deArea = fkTransformer.GetDEArea(detElemId);
541
542 if ( deArea->Contains(pointArea) ) {
543 foundDetElemId[nFound++] = detElemId;
544 if ( nFound == 2 ) break;
545 }
546 else if ( nFound > 0 ) break;
547 } // loop on detElemId
548
549 return nFound;
550}
683cb6c5 551
683cb6c5 552
d5315275 553
554//_____________________________________________________________________________
555Bool_t AliMUONTrackHitPattern::PadsFromPos(const TVector3& vec11, const TVector3& vec21,
556 Int_t detElemId, TObjArray& pads) const
557{
558 //
559 /// Given the (x,y) position in the chamber,
560 /// it returns the corresponding local board
561 //
562
563 pads.Delete();
564
565 TVector3 localCoor;
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);
574 }
575 }
576
577 return pads.GetEntries();
683cb6c5 578}
579
580
581//_____________________________________________________________________________
d5315275 582Bool_t AliMUONTrackHitPattern::PosInDetElemIdLocal(TVector3& localCoor, const TVector3& globalPoint1,
583 const TVector3& globalPoint2, Int_t detElemId) const
683cb6c5 584{
d5315275 585 /// Given two points belonging to a line (global coordinates)
586 /// it returns the intersection point with the detElemId (local coordinates)
587
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 );
594
595 return kTRUE;
596}
683cb6c5 597
4e116cd5 598
d5315275 599//_____________________________________________________________________________
600Bool_t AliMUONTrackHitPattern::IsCloseToAccEdge(TObjArray& pads, Int_t detElemId, Float_t coor[2]) const
601{
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
616 return kFALSE;
617}
4e116cd5 618
d5315275 619
620//_____________________________________________________________________________
621Bool_t AliMUONTrackHitPattern::IsMasked(const AliMpPad& pad, Int_t detElemId, Int_t cathode, const TVector3& vec11, const TVector3& vec21) const
622{
623 //
624 /// Check if pad or its neighbours are masked
625 //
626
627 Int_t nMasked = 0;
628
629 if ( fkTriggerUtilities->IsMasked(pad, detElemId, cathode) ) ++nMasked;
630
631 // Check closest neighbour
632
633 TVector3 localCoor;
634 PosInDetElemIdLocal(localCoor, vec11, vec21, detElemId);
635
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;
644
645 Float_t newPos[2];
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;
683cb6c5 655 }
d5315275 656 else {
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;
670 }
671 } // loop on slats
672 } // loop on neigbours
673
674 Double_t maskedProb = ((Double_t)nMasked)/3.;
675 if ( gRandom->Rndm() < maskedProb ) return kTRUE;
676
677 return kFALSE;
683cb6c5 678}
679
680
681//_____________________________________________________________________________
682Bool_t AliMUONTrackHitPattern::PerformTrigTrackMatch(UShort_t &pattern,
64f628e9 683 const AliMUONTriggerTrack* matchedTrigTrack) const
7771752e 684{
fda59e58 685 //
683cb6c5 686 /// It searches for matching digits around the trigger track.
fda59e58 687 //
d5315275 688
689 AliCodeTimerAuto("",0);
7771752e 690
683cb6c5 691 enum {kBending, kNonBending};
7771752e 692
d5315275 693 TArrayF zMeanChamber(AliMUONConstants::NTriggerCh());
bdfb6eef 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);
683cb6c5 698
d5315275 699 TArrayI digitPerTrack(2);
683cb6c5 700 digitPerTrack.Reset();
683cb6c5 701
d5315275 702 Float_t trackIntersectCh[2];
683cb6c5 703
bdfb6eef 704 Float_t slopeX = matchedTrigTrack->GetSlopeX();
705 Float_t slopeY = matchedTrigTrack->GetSlopeY();
d5315275 706
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);
714
715
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];
721
722 for(Int_t ich=0; ich<AliMUONConstants::NTriggerCh(); ich++) { // chamber loop
723
683cb6c5 724 // searching track intersection with chambers (first approximation)
d5315275 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);
729 if ( nFound == 0 ) {
67c201be 730 // track is rejected since the extrapolated track
731 // does not match a slat (border effects)
732 AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackOutsideGeometry);
d5315275 733 goodForEff = AliESDMuonTrack::kNoEff;
734 AliDebug(1, "Warning: trigger track outside trigger chamber\n");
683cb6c5 735 continue;
736 }
d5315275 737
738 matchedDetElemId[0] = matchedDetElemId[1] = detElemIdFromTrack[0];
739
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
67c201be 743 AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesManyPads);
d5315275 744 goodForEff = AliESDMuonTrack::kNoEff;
745 AliDebug(1, Form("Warning: track = %p (%i) matches many pads. Rejected!\n",(void *)matchedTrigTrack, matchedDetElemId[0]));
683cb6c5 746 }
d5315275 747
748 Int_t nMatched = 0;
749
750 Int_t mostProbDEmatched = detElemIdFromTrack[0];
751 for ( Int_t icath=0; icath<2; icath++ ) {
752 if ( matchedPads.UncheckedAt(icath) ) {
753 nMatched++;
754 // Fill pattern anyway
755 AliESDMuonTrack::SetFiredChamber(pattern, icath, ich);
756 digitPerTrack[icath]++;
757 mostProbDEmatched = matchedDetElemId[icath];
683cb6c5 758 }
759 }
d5315275 760 Int_t mostProbDEfromTrack = detElemIdFromTrack[0];
761 for ( Int_t ifound=0; ifound<nFound; ifound++ ) {
762 if ( detElemIdFromTrack[ifound] == mostProbDEmatched ) {
763 mostProbDEfromTrack = mostProbDEmatched;
764 break;
765 }
766 }
767
768 if ( goodForEff == AliESDMuonTrack::kNoEff ) continue;
769
770 if ( nMatched < 2 ) PadsFromPos(vec11, vec21, mostProbDEfromTrack, padsFromPos);
771
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;
782 }
783 }
784 else goodForEff = AliESDMuonTrack::kNoEff;
785 } // loop on cathodes
786
787 if ( goodForEff != AliESDMuonTrack::kNoEff ) {
788
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");
796 }
797
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;
803 }
804
805 if ( firstBoard < 0 ) firstBoard = ((AliMpPad*)validPads[kBending])->GetLocalBoardId(0);
806
807 for ( Int_t cath=0; cath<2; cath++ ){
808
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;
815 break;
816 }
817 } // loop on locations
818 if ( ! atLeastOneLoc ) goodForEff = AliESDMuonTrack::kSlatEff;
819 }
820 } // loop on cathodes
821 } // if track good for efficiency
822 matchedPads.Delete();
823 padsFromPos.Delete();
683cb6c5 824 } // end chamber loop
d5315275 825
826 if ( goodForEff == AliESDMuonTrack::kNoEff ) return kFALSE;
683cb6c5 827
d5315275 828 for(Int_t cath=0; cath<2; cath++){
67c201be 829 if(digitPerTrack[cath]<3) {
67c201be 830 // track is rejected since the number of associated
831 // digits found is less than 3.
832 AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesFewPads);
d5315275 833 goodForEff = AliESDMuonTrack::kNoEff;
67c201be 834 AliDebug(1, Form("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath));
835 }
d5315275 836 } // loop on cathodes
683cb6c5 837
d5315275 838 if ( goodForEff == AliESDMuonTrack::kNoEff ) return kFALSE;
683cb6c5 839
67c201be 840 AliESDMuonTrack::AddEffInfo(pattern, firstSlat, goodForEff);
683cb6c5 841 return kTRUE;
7771752e 842}