]>
Commit | Line | Data |
---|---|---|
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" |
7771752e | 41 | #include "AliMUONLocalTriggerBoard.h" |
a0dc65b4 | 42 | #include "AliMUONRecoParam.h" |
7ec3b9cf | 43 | #include "AliMUONTrack.h" |
44 | #include "AliMUONTrackExtrap.h" | |
45 | #include "AliMUONTrackParam.h" | |
46 | #include "AliMUONVTrackStore.h" | |
47 | #include "AliMUONVTriggerStore.h" | |
7771752e | 48 | #include "AliMpPad.h" |
7771752e | 49 | #include "AliMpSegmentation.h" |
7ec3b9cf | 50 | #include "AliMpVSegmentation.h" |
fda59e58 | 51 | #include "AliMpDEManager.h" |
52 | #include "AliMUONReconstructor.h" | |
683cb6c5 | 53 | #include "AliMUONTriggerTrack.h" |
54 | #include "AliMUONVTriggerTrackStore.h" | |
55 | ||
56 | #include "AliMpConstants.h" | |
ea94c18b | 57 | |
ea94c18b | 58 | #include "AliLog.h" |
7771752e | 59 | #include "AliTracker.h" |
67c201be | 60 | #include "AliESDMuonTrack.h" |
ea94c18b | 61 | |
7771752e | 62 | #include <Riostream.h> |
7ec3b9cf | 63 | #include <TArrayS.h> |
7771752e | 64 | #include <TClonesArray.h> |
65 | #include <TMath.h> | |
66 | #include <TMatrixD.h> | |
683cb6c5 | 67 | #include <TROOT.h> |
68 | #include <TDirectory.h> | |
69 | #include <TFile.h> | |
70 | #include <TSystem.h> | |
6e97fbb8 | 71 | #include <TVector2.h> |
683cb6c5 | 72 | |
73 | #include <cassert> | |
7771752e | 74 | |
75 | /// \cond CLASSIMP | |
76 | ClassImp(AliMUONTrackHitPattern) // Class implementation in ROOT context | |
77 | /// \endcond | |
78 | ||
79 | ||
80 | //______________________________________________________________________________ | |
a0dc65b4 | 81 | AliMUONTrackHitPattern::AliMUONTrackHitPattern(const AliMUONRecoParam* recoParam, |
82 | const AliMUONGeometryTransformer& transformer, | |
64f628e9 | 83 | const AliMUONVDigitStore& digitStore) |
a0dc65b4 | 84 | : TObject(), |
9b1e069f | 85 | fkRecoParam(recoParam), |
86 | fkTransformer(transformer), | |
64f628e9 | 87 | fkDigitStore(digitStore), |
a0dc65b4 | 88 | fkMaxDistance(99999.) |
7771752e | 89 | { |
90 | /// Default constructor | |
f7a1cc68 | 91 | AliMUONTrackExtrap::SetField(); |
7771752e | 92 | } |
93 | ||
94 | ||
95 | //______________________________________________________________________________ | |
96 | AliMUONTrackHitPattern::~AliMUONTrackHitPattern(void) | |
97 | { | |
7ec3b9cf | 98 | /// Destructor |
7771752e | 99 | } |
100 | ||
683cb6c5 | 101 | //_____________________________________________________________________________ |
102 | void AliMUONTrackHitPattern::CheckConstants() const | |
103 | { | |
104 | /// Check consistence of redefined constants | |
105 | ||
106 | assert(fgkNcathodes == AliMpConstants::NofCathodes()); | |
107 | assert(fgkNchambers == AliMpConstants::NofTriggerChambers()); | |
108 | assert(fgkNplanes == AliMpConstants::NofTriggerChambers() * fgkNcathodes); | |
109 | } | |
110 | ||
111 | ||
112 | //______________________________________________________________________________ | |
9b1e069f | 113 | void AliMUONTrackHitPattern::ExecuteValidation(const AliMUONVTrackStore& trackStore, |
683cb6c5 | 114 | const AliMUONVTriggerTrackStore& triggerTrackStore, |
115 | const AliMUONVTriggerStore& triggerStore) const | |
116 | { | |
117 | // | |
118 | /// Main method: | |
119 | /// Loops on reco tracks, extrapolates them to trigger chambers | |
120 | /// and searches for matching trigger tracks and digits | |
121 | // | |
122 | ||
67c201be | 123 | // Get the hit pattern for all trigger tracks |
124 | AliMUONTriggerTrack* triggerTrack; | |
125 | TIter itTriggerTrack(triggerTrackStore.CreateIterator()); | |
126 | while ( ( triggerTrack = static_cast<AliMUONTriggerTrack*>(itTriggerTrack() ) ) ){ | |
64f628e9 | 127 | UShort_t pattern = GetHitPattern(triggerTrack); |
67c201be | 128 | triggerTrack->SetHitsPatternInTrigCh(pattern); |
129 | AliDebug(1, Form("Hit pattern: hits 0x%x slat %2i board %3i effFlag %i", | |
130 | pattern & 0xFF, AliESDMuonTrack::GetSlatOrInfo(pattern), | |
131 | triggerTrack->GetLoTrgNum(), AliESDMuonTrack::GetEffFlag(pattern))); | |
132 | } | |
683cb6c5 | 133 | |
67c201be | 134 | // Match tracker tracks with trigger tracks. |
683cb6c5 | 135 | TIter itTrack(trackStore.CreateIterator()); |
136 | AliMUONTrack* track; | |
137 | ||
138 | const Int_t kFirstTrigCh = AliMUONConstants::NTrackingCh(); | |
139 | ||
140 | while ( ( track = static_cast<AliMUONTrack*>(itTrack()) ) ) | |
141 | { | |
142 | AliMUONTrackParam trackParam(*((AliMUONTrackParam*) (track->GetTrackParamAtCluster()->Last()))); | |
143 | ||
144 | ApplyMCSCorrections(trackParam); | |
145 | AliMUONTrackExtrap::ExtrapToZCov(&trackParam, AliMUONConstants::DefaultChamberZ(kFirstTrigCh)); // extrap to 1st trigger chamber | |
146 | ||
147 | AliMUONTriggerTrack *matchedTriggerTrack = MatchTriggerTrack(track, trackParam, triggerTrackStore, triggerStore); | |
148 | ||
67c201be | 149 | // Copy trigger tracks hit pattern if there is matching, |
150 | // otherwise calculate the hit pattern directly from tracker track: | |
151 | // the obtained pattern is good for check, but not good for efficiency determination. | |
152 | UShort_t pattern = matchedTriggerTrack ? | |
153 | matchedTriggerTrack->GetHitsPatternInTrigCh() : | |
64f628e9 | 154 | GetHitPattern(&trackParam); |
67c201be | 155 | |
683cb6c5 | 156 | track->SetHitsPatternInTrigCh(pattern); |
157 | } | |
158 | } | |
159 | ||
160 | ||
161 | //______________________________________________________________________________ | |
162 | AliMUONTriggerTrack * | |
163 | AliMUONTrackHitPattern::MatchTriggerTrack(AliMUONTrack* track, | |
164 | AliMUONTrackParam& trackParam, | |
165 | const AliMUONVTriggerTrackStore& triggerTrackStore, | |
166 | const AliMUONVTriggerStore& triggerStore) const | |
167 | { | |
168 | // | |
169 | /// Match track with trigger track | |
170 | // | |
171 | ||
172 | Int_t matchTrigger = 0; | |
173 | Int_t loTrgNum(-1); | |
bdfb6eef | 174 | TMatrixD paramDiff(3,1); |
683cb6c5 | 175 | Double_t chi2; |
176 | Double_t chi2MatchTrigger = 0., minChi2MatchTrigger = 999.; | |
177 | Int_t doubleMatch = -1; // Check if track matches 2 trigger tracks | |
178 | Double_t doubleChi2 = -1.; | |
179 | AliMUONTriggerTrack* doubleTriggerTrack = 0x0; | |
180 | AliMUONTriggerTrack* matchedTriggerTrack = 0x0; | |
7ec3b9cf | 181 | |
683cb6c5 | 182 | |
bdfb6eef | 183 | // Covariance matrix 3x3 (X,Y,slopeY) for trigger tracks |
683cb6c5 | 184 | TMatrixD trackCov(3,3); |
fda59e58 | 185 | |
683cb6c5 | 186 | AliMUONTriggerTrack *triggerTrack; |
187 | TIter itTriggerTrack(triggerTrackStore.CreateIterator()); | |
188 | while ( ( triggerTrack = static_cast<AliMUONTriggerTrack*>(itTriggerTrack() ) ) ) | |
189 | { | |
bdfb6eef | 190 | AliMUONTrackExtrap::LinearExtrapToZCov(&trackParam, triggerTrack->GetZ11()); |
191 | const TMatrixD& kParamCov = trackParam.GetCovariances(); | |
192 | ||
193 | Double_t xTrack = trackParam.GetNonBendingCoor(); | |
194 | Double_t yTrack = trackParam.GetBendingCoor(); | |
195 | Double_t ySlopeTrack = trackParam.GetBendingSlope(); | |
196 | ||
197 | paramDiff(0,0) = triggerTrack->GetX11() - xTrack; | |
198 | paramDiff(1,0) = triggerTrack->GetY11() - yTrack; | |
199 | paramDiff(2,0) = triggerTrack->GetSlopeY() - ySlopeTrack; | |
200 | ||
201 | // Covariance matrix 3x3 (X,Y,slopeY) for tracker tracks | |
202 | trackCov.Zero(); | |
203 | trackCov(0,0) = kParamCov(0,0); | |
204 | trackCov(1,1) = kParamCov(2,2); | |
205 | trackCov(2,2) = kParamCov(3,3); | |
206 | trackCov(1,2) = kParamCov(2,3); | |
207 | trackCov(2,1) = kParamCov(3,2); | |
208 | ||
209 | // Covariance matrix 3x3 (X,Y,slopeY) for trigger tracks | |
210 | TMatrixD trigCov(triggerTrack->GetCovariances()); | |
211 | ||
212 | TMatrixD sumCov(trackCov,TMatrixD::kPlus,trigCov); | |
213 | if (sumCov.Determinant() != 0) { | |
214 | sumCov.Invert(); | |
215 | ||
683cb6c5 | 216 | TMatrixD tmp(sumCov,TMatrixD::kMult,paramDiff); |
217 | TMatrixD chi2M(paramDiff,TMatrixD::kTransposeMult,tmp); | |
bdfb6eef | 218 | chi2 = chi2M(0,0); |
219 | } else { | |
220 | AliWarning(" Determinant = 0"); | |
221 | Double_t sigma2 = 0.; | |
683cb6c5 | 222 | chi2 = 0.; |
bdfb6eef | 223 | for (Int_t iVar = 0; iVar < 3; iVar++) { |
224 | sigma2 = trackCov(iVar,iVar) + trigCov(iVar,iVar); | |
225 | chi2 += paramDiff(iVar,0) * paramDiff(iVar,0) / sigma2; | |
226 | } | |
683cb6c5 | 227 | } |
fda59e58 | 228 | |
683cb6c5 | 229 | chi2 /= 3.; // Normalized Chi2: 3 degrees of freedom (X,Y,slopeY) |
a0dc65b4 | 230 | if (chi2 < GetRecoParam()->GetMaxNormChi2MatchTrigger()) |
7ec3b9cf | 231 | { |
683cb6c5 | 232 | Bool_t isDoubleTrack = (TMath::Abs(chi2 - minChi2MatchTrigger)<1.); |
a0dc65b4 | 233 | if (chi2 < minChi2MatchTrigger && chi2 < GetRecoParam()->GetMaxNormChi2MatchTrigger()) |
7ec3b9cf | 234 | { |
683cb6c5 | 235 | if(isDoubleTrack) |
236 | { | |
237 | doubleMatch = loTrgNum; | |
238 | doubleChi2 = chi2MatchTrigger; | |
239 | doubleTriggerTrack = matchedTriggerTrack; | |
fda59e58 | 240 | } |
683cb6c5 | 241 | minChi2MatchTrigger = chi2; |
242 | chi2MatchTrigger = chi2; | |
243 | loTrgNum = triggerTrack->GetLoTrgNum(); | |
244 | matchedTriggerTrack = triggerTrack; | |
245 | AliMUONLocalTrigger* locTrg = triggerStore.FindLocal(loTrgNum); | |
246 | matchTrigger = 1; | |
247 | if(locTrg->LoLpt()>0) matchTrigger = 2; | |
248 | if(locTrg->LoHpt()>0) matchTrigger = 3; | |
249 | } | |
250 | else if(isDoubleTrack) | |
251 | { | |
252 | doubleMatch = triggerTrack->GetLoTrgNum(); | |
253 | doubleChi2 = chi2; | |
7ec3b9cf | 254 | } |
7771752e | 255 | } |
683cb6c5 | 256 | } |
257 | if(doubleMatch>=0) | |
258 | { // If two trigger tracks match, select the one passing more trigger cuts | |
259 | AliDebug(1, Form("Two candidates found: %i and %i",loTrgNum,doubleMatch)); | |
260 | AliMUONLocalTrigger* locTrg1 = triggerStore.FindLocal(doubleMatch); | |
261 | if((locTrg1->LoLpt()>0 && matchTrigger<2) || (locTrg1->LoHpt() && matchTrigger<3)) | |
262 | { | |
263 | if(locTrg1->LoHpt()>0) matchTrigger=3; | |
264 | else matchTrigger = 2; | |
265 | loTrgNum = doubleMatch; | |
266 | chi2MatchTrigger = doubleChi2; | |
267 | matchedTriggerTrack = doubleTriggerTrack; | |
268 | } | |
269 | } | |
270 | ||
271 | track->SetMatchTrigger(matchTrigger); | |
683cb6c5 | 272 | track->SetChi2MatchTrigger(chi2MatchTrigger); |
273 | ||
274 | AliMUONLocalTrigger* locTrg = static_cast<AliMUONLocalTrigger*>(triggerStore.FindLocal(loTrgNum)); | |
275 | ||
276 | if (locTrg) | |
277 | { | |
278 | track->SetLocalTrigger(locTrg->LoCircuit(), | |
279 | locTrg->LoStripX(), | |
280 | locTrg->LoStripY(), | |
00d46f24 | 281 | locTrg->GetDeviation(), |
683cb6c5 | 282 | locTrg->LoLpt(), |
00d46f24 | 283 | locTrg->LoHpt(), |
284 | locTrg->GetTriggerWithoutChamber()); | |
683cb6c5 | 285 | } |
286 | ||
287 | return matchedTriggerTrack; | |
288 | } | |
289 | ||
290 | ||
291 | //______________________________________________________________________________ | |
64f628e9 | 292 | UShort_t AliMUONTrackHitPattern::GetHitPattern(AliMUONTriggerTrack* matchedTriggerTrack) const |
683cb6c5 | 293 | { |
294 | // | |
67c201be | 295 | /// Get hit pattern on trigger chambers for the current trigger track |
683cb6c5 | 296 | // |
297 | UShort_t pattern = 0; | |
64f628e9 | 298 | PerformTrigTrackMatch(pattern, matchedTriggerTrack); |
67c201be | 299 | return pattern; |
300 | } | |
683cb6c5 | 301 | |
54355f2c | 302 | |
67c201be | 303 | //______________________________________________________________________________ |
64f628e9 | 304 | UShort_t AliMUONTrackHitPattern::GetHitPattern(AliMUONTrackParam* trackParam) const |
67c201be | 305 | { |
306 | // | |
307 | /// Get hit pattern on trigger chambers for the current tracker track | |
308 | // | |
309 | UShort_t pattern = 0; | |
310 | Bool_t isMatch[2]; | |
311 | const Int_t kNTrackingCh = AliMUONConstants::NTrackingCh(); | |
683cb6c5 | 312 | |
313 | for(Int_t ch=0; ch<4; ++ch) | |
314 | { | |
315 | Int_t iChamber = kNTrackingCh+ch; | |
54355f2c | 316 | AliMUONTrackExtrap::ExtrapToZCov(trackParam, AliMUONConstants::DefaultChamberZ(iChamber)); |
64f628e9 | 317 | FindPadMatchingTrack(*trackParam, isMatch, iChamber); |
683cb6c5 | 318 | for(Int_t cath=0; cath<2; ++cath) |
319 | { | |
67c201be | 320 | if(isMatch[cath]) AliESDMuonTrack::SetFiredChamber(pattern, cath, ch); |
683cb6c5 | 321 | } |
322 | } | |
683cb6c5 | 323 | |
67c201be | 324 | // pattern obtained by propagation of tracker track |
325 | // when it does not match the trigger. | |
326 | AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackerTrackPattern); | |
683cb6c5 | 327 | |
67c201be | 328 | return pattern; |
683cb6c5 | 329 | } |
330 | ||
683cb6c5 | 331 | //______________________________________________________________________________ |
332 | void | |
333 | AliMUONTrackHitPattern::ApplyMCSCorrections(AliMUONTrackParam& trackParam) const | |
334 | { | |
335 | // | |
336 | /// Returns uncertainties on extrapolated position. | |
337 | /// Takes into account Branson plane corrections in the iron wall. | |
338 | // | |
339 | ||
340 | const Float_t kZFilterOut = AliMUONConstants::MuonFilterZEnd(); | |
37a615ac | 341 | const Float_t kFilterThickness = kZFilterOut-AliMUONConstants::MuonFilterZBeg(); // cm |
683cb6c5 | 342 | |
343 | AliMUONTrackExtrap::ExtrapToZCov(&trackParam, kZFilterOut); // Extrap to muon filter end | |
344 | AliMUONTrackExtrap::AddMCSEffect(&trackParam, kFilterThickness, AliMUONConstants::MuonFilterX0()); // Add MCS effects | |
345 | return; | |
346 | } | |
347 | ||
348 | ||
7771752e | 349 | //______________________________________________________________________________ |
7ec3b9cf | 350 | void |
64f628e9 | 351 | AliMUONTrackHitPattern::FindPadMatchingTrack(const AliMUONTrackParam& trackParam, |
fda59e58 | 352 | Bool_t isMatch[2], Int_t iChamber) const |
7771752e | 353 | { |
354 | // | |
683cb6c5 | 355 | /// Given the tracker track position, searches for matching digits. |
7771752e | 356 | // |
357 | ||
358 | Float_t minMatchDist[2]; | |
359 | ||
7ec3b9cf | 360 | for(Int_t cath=0; cath<2; ++cath) |
361 | { | |
362 | isMatch[cath]=kFALSE; | |
683cb6c5 | 363 | minMatchDist[cath]=fkMaxDistance/10.; |
7771752e | 364 | } |
365 | ||
64f628e9 | 366 | TIter next(fkDigitStore.CreateTriggerIterator()); |
7ec3b9cf | 367 | AliMUONVDigit* mDigit; |
fda59e58 | 368 | |
7ec3b9cf | 369 | while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) ) |
370 | { | |
371 | Int_t currDetElemId = mDigit->DetElemId(); | |
fda59e58 | 372 | Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId); |
373 | if(currCh!=iChamber) continue; | |
7ec3b9cf | 374 | Int_t cathode = mDigit->Cathode(); |
375 | Int_t ix = mDigit->PadX(); | |
376 | Int_t iy = mDigit->PadY(); | |
377 | Float_t xpad, ypad, zpad; | |
378 | const AliMpVSegmentation* seg = AliMpSegmentation::Instance() | |
379 | ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode)); | |
380 | ||
168e9c4d | 381 | AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE); |
6e97fbb8 | 382 | Float_t xlocal1 = pad.GetPositionX(); |
383 | Float_t ylocal1 = pad.GetPositionY(); | |
384 | Float_t dpx = pad.GetDimensionX(); | |
385 | Float_t dpy = pad.GetDimensionY(); | |
386 | ||
9b1e069f | 387 | fkTransformer.Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad); |
7ec3b9cf | 388 | Float_t matchDist = MinDistanceFromPad(xpad, ypad, zpad, dpx, dpy, trackParam); |
389 | if(matchDist>minMatchDist[cathode])continue; | |
390 | isMatch[cathode] = kTRUE; | |
fda59e58 | 391 | if(isMatch[0] && isMatch[1]) break; |
7ec3b9cf | 392 | minMatchDist[cathode] = matchDist; |
7771752e | 393 | } |
7771752e | 394 | } |
395 | ||
396 | ||
397 | //______________________________________________________________________________ | |
7ec3b9cf | 398 | Float_t |
399 | AliMUONTrackHitPattern::MinDistanceFromPad(Float_t xPad, Float_t yPad, Float_t zPad, | |
400 | Float_t dpx, Float_t dpy, | |
401 | const AliMUONTrackParam& trackParam) const | |
7771752e | 402 | { |
403 | // | |
683cb6c5 | 404 | /// Decides if the digit belongs to the tracker track. |
7771752e | 405 | // |
7771752e | 406 | |
fda59e58 | 407 | AliMUONTrackParam trackParamAtPadZ(trackParam); |
bdfb6eef | 408 | AliMUONTrackExtrap::LinearExtrapToZCov(&trackParamAtPadZ, zPad); |
fda59e58 | 409 | |
410 | Float_t xTrackAtPad = trackParamAtPadZ.GetNonBendingCoor(); | |
411 | Float_t yTrackAtPad = trackParamAtPadZ.GetBendingCoor(); | |
7771752e | 412 | |
a0dc65b4 | 413 | const Float_t kNSigma = GetRecoParam()->GetSigmaCutForTrigger(); |
fda59e58 | 414 | |
415 | const TMatrixD& kCovParam = trackParamAtPadZ.GetCovariances(); | |
416 | ||
417 | Float_t sigmaX = TMath::Sqrt(kCovParam(0,0)); | |
418 | Float_t sigmaY = TMath::Sqrt(kCovParam(2,2)); | |
419 | ||
420 | Float_t maxDistX = kNSigma * sigmaX; // in cm | |
421 | Float_t maxDistY = kNSigma * sigmaY; // in cm | |
7771752e | 422 | |
423 | Float_t deltaX = TMath::Abs(xPad-xTrackAtPad)-dpx; | |
424 | Float_t deltaY = TMath::Abs(yPad-yTrackAtPad)-dpy; | |
425 | ||
683cb6c5 | 426 | Float_t matchDist = fkMaxDistance; |
7771752e | 427 | if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY); |
fda59e58 | 428 | |
7771752e | 429 | return matchDist; |
430 | } | |
431 | ||
432 | ||
683cb6c5 | 433 | //_____________________________________________________________________________ |
64f628e9 | 434 | Int_t AliMUONTrackHitPattern::FindPadMatchingTrig(Int_t &detElemId, |
683cb6c5 | 435 | Float_t coor[2], Bool_t isMatch[2], |
436 | TArrayI nboard[2], TArrayF &zRealMatch, Float_t y11) const | |
437 | { | |
438 | // | |
439 | /// Check slat and board number of digit matching trigger track | |
440 | // | |
441 | ||
442 | enum {kBending, kNonBending}; | |
443 | ||
444 | Float_t minMatchDist[fgkNcathodes]; | |
445 | Int_t padsInCheckArea[fgkNcathodes]; | |
446 | ||
447 | for(Int_t cath=0; cath<fgkNcathodes; cath++){ | |
448 | isMatch[cath] = kFALSE; | |
449 | minMatchDist[cath] = fkMaxDistance/10.; | |
450 | padsInCheckArea[cath] = 0; | |
451 | } | |
ad30b53f | 452 | |
453 | Int_t iChamber = AliMpDEManager::GetChamberId(detElemId); | |
454 | if ( iChamber < 0 ) { | |
455 | AliErrorStream() << "Cannot get chamberId from detElemId=" << detElemId << endl; | |
456 | return -1; | |
457 | } | |
458 | ||
683cb6c5 | 459 | Int_t ch = iChamber-10; |
460 | Float_t oldDeltaZ = AliMUONConstants::DefaultChamberZ(iChamber) - AliMUONConstants::DefaultChamberZ(10); | |
461 | Float_t y = coor[1]; | |
462 | Int_t iSlat = detElemId%100; | |
463 | Int_t trigDigitBendPlane = -1; | |
464 | Int_t foundDetElemId = detElemId; | |
465 | Float_t foundZmatch=999.; | |
466 | Float_t yCoorAtPadZ=999.; | |
467 | ||
64f628e9 | 468 | TIter next(fkDigitStore.CreateTriggerIterator()); |
683cb6c5 | 469 | AliMUONVDigit* mDigit; |
470 | Int_t idigit=0; | |
471 | ||
472 | while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) ) | |
473 | { | |
474 | idigit++; | |
475 | Int_t currDetElemId = mDigit->DetElemId(); | |
476 | Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId); | |
477 | if(currCh!=iChamber) continue; | |
478 | Int_t currSlat = currDetElemId%100; | |
479 | Int_t slatDiff = TMath::Abs(currSlat-iSlat); | |
480 | if(slatDiff>1 && slatDiff<17) continue; // Check neighbour slats | |
481 | Int_t cathode = mDigit->Cathode(); | |
482 | Int_t ix = mDigit->PadX(); | |
483 | Int_t iy = mDigit->PadY(); | |
484 | Float_t xpad, ypad, zpad; | |
485 | const AliMpVSegmentation* seg = AliMpSegmentation::Instance() | |
486 | ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode)); | |
487 | ||
168e9c4d | 488 | AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE); |
6e97fbb8 | 489 | Float_t xlocal1 = pad.GetPositionX(); |
490 | Float_t ylocal1 = pad.GetPositionY(); | |
491 | Float_t dpx = pad.GetDimensionX(); | |
492 | Float_t dpy = pad.GetDimensionY(); | |
493 | ||
9b1e069f | 494 | fkTransformer.Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad); |
b5270f21 | 495 | AliDebug(2, Form("\nDetElemId = %i Cathode = %i Pad = (%i,%i) = (%.2f,%.2f) Dim = (%.2f,%.2f) Track = (%.2f,%.2f)\n",currDetElemId,cathode,ix,iy,xpad,ypad,dpx,dpy,coor[0],coor[1])); |
683cb6c5 | 496 | // searching track intersection with chambers (second approximation) |
497 | if(ch%2==1){ | |
498 | //if(iChamber%2==1){ | |
499 | Float_t deltaZ = zpad - zRealMatch[0]; | |
500 | y = (coor[1]-y11)*deltaZ/oldDeltaZ + y11; | |
501 | if(TMath::Abs(y-coor[1])>0.1) AliDebug(3, Form("oldDeltaZ = %7.2f newDeltaZ = %7.2f\toldY = %7.2f new y = %7.2f\n",oldDeltaZ,deltaZ,coor[1],y)); | |
502 | } | |
503 | Float_t matchDist = PadMatchTrack(xpad, ypad, dpx, dpy, coor[0], y); | |
504 | if(matchDist<fkMaxDistance/2.) padsInCheckArea[cathode]++; | |
505 | if(matchDist>minMatchDist[cathode])continue; | |
506 | isMatch[cathode] = kTRUE; | |
507 | minMatchDist[cathode] = matchDist; | |
508 | foundDetElemId = currDetElemId; | |
509 | foundZmatch=zpad; | |
510 | yCoorAtPadZ=y; | |
511 | if(cathode==kBending) trigDigitBendPlane = idigit; | |
512 | for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){ | |
168e9c4d | 513 | nboard[cathode][loc] = pad.GetLocalBoardId(loc); |
683cb6c5 | 514 | } |
515 | for(Int_t loc=pad.GetNofLocations(); loc<fgkNlocations; loc++){ | |
516 | nboard[cathode][loc]=-1; | |
517 | } | |
683cb6c5 | 518 | } |
519 | ||
683cb6c5 | 520 | if(isMatch[kBending] || isMatch[kNonBending]){ |
521 | detElemId = foundDetElemId; | |
522 | zRealMatch[ch] = foundZmatch; | |
523 | coor[1] = yCoorAtPadZ; | |
524 | } | |
67c201be | 525 | |
526 | // If track matches many pads, it is not good for effciency determination. | |
527 | // However we still want to calculate the hit pattern. | |
528 | for(Int_t cath=0; cath<fgkNcathodes; cath++){ | |
529 | if(padsInCheckArea[cath]>2) { | |
530 | AliDebug(1, Form("padsInCheckArea[%i] = %i\n",cath,padsInCheckArea[cath])); | |
531 | return -500; | |
532 | } | |
533 | } | |
534 | ||
683cb6c5 | 535 | return trigDigitBendPlane; |
536 | } | |
537 | ||
538 | //_____________________________________________________________________________ | |
539 | Float_t AliMUONTrackHitPattern::PadMatchTrack(Float_t xPad, Float_t yPad, | |
540 | Float_t dpx, Float_t dpy, | |
541 | Float_t xTrackAtPad, Float_t yTrackAtPad) const | |
542 | { | |
543 | // | |
544 | /// Decides if the digit belongs to the trigger track. | |
545 | // | |
546 | ||
a0dc65b4 | 547 | Float_t maxDist = GetRecoParam()->GetStripCutForTrigger() * 2. * TMath::Min(dpx,dpy); // cm |
b5270f21 | 548 | if(maxDist<2.) maxDist = 2.; |
a0dc65b4 | 549 | Float_t maxDistCheckArea = GetRecoParam()->GetMaxStripAreaForTrigger() * 2. * TMath::Min(dpx,dpy); // cm |
683cb6c5 | 550 | |
551 | Float_t matchDist = fkMaxDistance; | |
552 | ||
553 | Float_t deltaX = TMath::Abs(xPad-xTrackAtPad)-dpx; | |
554 | Float_t deltaY = TMath::Abs(yPad-yTrackAtPad)-dpy; | |
555 | Float_t maxDistX = maxDist; | |
556 | Float_t maxDistY = maxDist; | |
557 | ||
558 | if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY); | |
559 | else if(deltaX<=maxDistCheckArea && deltaY<=maxDistCheckArea) matchDist = fkMaxDistance/5.; | |
560 | return matchDist; | |
561 | } | |
562 | ||
563 | ||
564 | //_____________________________________________________________________________ | |
565 | Int_t AliMUONTrackHitPattern::DetElemIdFromPos(Float_t x, Float_t y, | |
566 | Int_t chamber, Int_t cathode) const | |
567 | { | |
568 | // | |
569 | /// Given the (x,y) position in the chamber, | |
570 | /// it returns the corresponding slat | |
571 | // | |
572 | ||
573 | Int_t resultingDetElemId = -1; | |
574 | AliMpDEIterator it; | |
575 | Float_t minDist = 999.; | |
576 | for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){ | |
577 | Int_t detElemId = it.CurrentDEId(); | |
578 | Int_t ich = detElemId/100-10; | |
579 | Float_t tolerance=0.2*((Float_t)ich); | |
580 | Float_t currDist=9999.; | |
581 | ||
582 | const AliMpVSegmentation* seg = | |
583 | AliMpSegmentation::Instance() | |
584 | ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode)); | |
585 | if (!seg) continue; | |
586 | ||
6e97fbb8 | 587 | Float_t deltax = seg->GetDimensionX(); |
588 | Float_t deltay = seg->GetDimensionY(); | |
683cb6c5 | 589 | Float_t xlocal1 = -deltax; |
590 | Float_t ylocal1 = -deltay; | |
591 | Float_t xlocal2 = +deltax; | |
592 | Float_t ylocal2 = +deltay; | |
593 | Float_t xg01, yg01, zg1, xg02, yg02, zg2; | |
9b1e069f | 594 | fkTransformer.Local2Global(detElemId, xlocal1, ylocal1, 0, xg01, yg01, zg1); |
595 | fkTransformer.Local2Global(detElemId, xlocal2, ylocal2, 0, xg02, yg02, zg2); | |
683cb6c5 | 596 | |
597 | Float_t xg1 = xg01, xg2 = xg02, yg1 = yg01, yg2 = yg02; | |
598 | ||
599 | if(xg01>xg02){ | |
600 | xg1 = xg02; | |
601 | xg2 = xg01; | |
602 | } | |
603 | if(yg01>yg02){ | |
604 | yg1 = yg02; | |
605 | yg2 = yg01; | |
606 | } | |
607 | ||
608 | if(x>=xg1-tolerance && x<=xg2+tolerance && y>=yg1-tolerance && y<=yg2+tolerance){ // takes into account errors in extrapolation | |
609 | if(y<yg1) currDist = yg1-y; | |
610 | else if(y>yg2) currDist = y-yg2; | |
611 | if(currDist<minDist) { | |
612 | resultingDetElemId = detElemId; | |
613 | minDist=currDist; | |
614 | continue; | |
615 | } | |
616 | resultingDetElemId = detElemId; | |
617 | break; | |
618 | } | |
619 | } // loop on detElemId | |
620 | return resultingDetElemId; | |
621 | } | |
622 | ||
623 | ||
624 | //_____________________________________________________________________________ | |
625 | void AliMUONTrackHitPattern::LocalBoardFromPos(Float_t x, Float_t y, | |
626 | Int_t detElemId, Int_t cathode, | |
627 | Int_t localBoard[4]) const | |
628 | { | |
629 | // | |
630 | /// Given the (x,y) position in the chamber, | |
631 | /// it returns the corresponding local board | |
632 | // | |
633 | ||
634 | for(Int_t loc=0; loc<fgkNlocations; loc++){ | |
635 | localBoard[loc]=-1; | |
636 | } | |
4e116cd5 | 637 | Float_t xg, yg, zg; |
638 | fkTransformer.Local2Global(detElemId, 0., 0., 0., xg, yg, zg); | |
639 | Float_t z = zg - (y-yg)*TMath::Tan(TMath::DegToRad()*AliMUONConstants::St345Inclination()); | |
683cb6c5 | 640 | Float_t xl, yl, zl; |
4e116cd5 | 641 | fkTransformer.Global2Local(detElemId, x, y, z, xl, yl, zl); |
683cb6c5 | 642 | const AliMpVSegmentation* seg = |
643 | AliMpSegmentation::Instance() | |
644 | ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode)); | |
4e116cd5 | 645 | if ( ! seg ) return; |
646 | AliMpPad pad = seg->PadByPosition(xl,yl,kFALSE); | |
647 | if ( ! pad.IsValid() ){ | |
648 | AliWarning(Form("Pad not found! DetElemId %i position global (%f, %f, %f) local (%f, %f, %f)\n", detElemId, x, y, z, xl, yl, zl)); | |
649 | return; | |
650 | } | |
651 | ||
652 | AliDebug(2, Form("\nWould match: DetElemId = %i Pad = (%i,%i) = (%.2f,%.2f,%.2f) Board %3i\n",detElemId,pad.GetIx(),pad.GetIy(),xl,yl,zl,pad.GetLocalBoardId(0))); | |
653 | ||
654 | for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){ | |
655 | localBoard[loc] = pad.GetLocalBoardId(loc); | |
683cb6c5 | 656 | } |
657 | } | |
658 | ||
659 | ||
660 | //_____________________________________________________________________________ | |
661 | Bool_t AliMUONTrackHitPattern::PerformTrigTrackMatch(UShort_t &pattern, | |
64f628e9 | 662 | const AliMUONTriggerTrack* matchedTrigTrack) const |
7771752e | 663 | { |
fda59e58 | 664 | // |
683cb6c5 | 665 | /// It searches for matching digits around the trigger track. |
fda59e58 | 666 | // |
7771752e | 667 | |
683cb6c5 | 668 | enum {kBending, kNonBending}; |
7771752e | 669 | |
683cb6c5 | 670 | Int_t chOrder[fgkNchambers] = {0,2,1,3}; |
671 | ||
672 | TArrayF zRealMatch(fgkNchambers); | |
683cb6c5 | 673 | |
674 | Bool_t isMatch[fgkNcathodes]; | |
675 | for(Int_t cath=0; cath<fgkNcathodes; cath++){ | |
676 | isMatch[cath] = kFALSE; | |
677 | } | |
678 | ||
679 | TArrayF zMeanChamber(fgkNchambers); | |
bdfb6eef | 680 | zMeanChamber[0] = matchedTrigTrack->GetZ11(); |
681 | zMeanChamber[1] = matchedTrigTrack->GetZ11() + AliMUONConstants::DefaultChamberZ(11) - AliMUONConstants::DefaultChamberZ(10); | |
682 | zMeanChamber[2] = matchedTrigTrack->GetZ21(); | |
683 | zMeanChamber[3] = matchedTrigTrack->GetZ21() + AliMUONConstants::DefaultChamberZ(13) - AliMUONConstants::DefaultChamberZ(12); | |
683cb6c5 | 684 | |
685 | TArrayI digitPerTrack(fgkNcathodes); | |
686 | ||
687 | Float_t trackIntersectCh[fgkNchambers][fgkNcathodes]; | |
688 | ||
689 | TArrayI triggeredDigits; | |
690 | triggeredDigits.Set(fgkNchambers); | |
691 | triggeredDigits.Reset(-1); | |
692 | ||
693 | TArrayI trigScheme[fgkNcathodes]; | |
694 | TArrayI slatThatTriggered[fgkNcathodes]; | |
695 | for(Int_t cath=0; cath<fgkNcathodes; cath++){ | |
696 | trigScheme[cath].Set(fgkNchambers); | |
697 | slatThatTriggered[cath].Set(fgkNchambers); | |
698 | } | |
699 | ||
700 | Int_t boardThatTriggered[fgkNchambers][fgkNcathodes][fgkNlocations]; | |
701 | TArrayI nboard[fgkNcathodes]; | |
702 | for(Int_t cath=0; cath<fgkNcathodes; cath++){ | |
703 | nboard[cath].Set(fgkNlocations); | |
704 | } | |
705 | Int_t ineffBoard[fgkNlocations]; | |
706 | for(Int_t loc=0; loc<fgkNlocations; loc++){ | |
707 | ineffBoard[loc] = -1; | |
708 | } | |
709 | ||
710 | digitPerTrack.Reset(); | |
711 | for(Int_t ch=0; ch<fgkNchambers; ch++){ | |
712 | zRealMatch[ch] = zMeanChamber[ch]; | |
713 | for(Int_t cath=0; cath<fgkNcathodes; cath++){ | |
714 | for(Int_t loc=0; loc<fgkNlocations; loc++){ | |
715 | boardThatTriggered[ch][cath][loc]=-1; | |
716 | } | |
717 | } | |
718 | } | |
719 | ||
720 | for(Int_t cath=0; cath<fgkNcathodes; cath++){ | |
721 | slatThatTriggered[cath].Reset(-1); | |
722 | trigScheme[cath].Reset(); | |
723 | } | |
724 | ||
725 | Bool_t isClearEvent = kTRUE; | |
726 | ||
683cb6c5 | 727 | Float_t y11 = matchedTrigTrack->GetY11();// y position (info from bending plane) |
bdfb6eef | 728 | Float_t slopeX = matchedTrigTrack->GetSlopeX(); |
729 | Float_t slopeY = matchedTrigTrack->GetSlopeY(); | |
683cb6c5 | 730 | |
731 | for(Int_t ch=0; ch<fgkNchambers; ch++) { // chamber loop | |
732 | Int_t currCh = chOrder[ch]; | |
b5270f21 | 733 | AliDebug(3, Form("zMeanChamber[%i] = %.2f\tzRealMatch[0] = %.2f\n",currCh,zMeanChamber[currCh],zRealMatch[0])); |
683cb6c5 | 734 | |
683cb6c5 | 735 | // searching track intersection with chambers (first approximation) |
736 | Float_t deltaZ = zMeanChamber[currCh] - zMeanChamber[0]; | |
bdfb6eef | 737 | trackIntersectCh[currCh][0] = zMeanChamber[currCh] * slopeX; |
738 | trackIntersectCh[currCh][1] = y11 + deltaZ * slopeY; | |
683cb6c5 | 739 | Int_t detElemIdFromTrack = DetElemIdFromPos(trackIntersectCh[currCh][0], trackIntersectCh[currCh][1], 11+currCh, 0); |
740 | if(detElemIdFromTrack<0) { | |
741 | AliDebug(1, "Warning: trigger track outside trigger chamber\n"); | |
67c201be | 742 | isClearEvent = kFALSE; |
743 | ||
744 | // track is rejected since the extrapolated track | |
745 | // does not match a slat (border effects) | |
746 | AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackOutsideGeometry); | |
683cb6c5 | 747 | continue; |
748 | } | |
749 | ||
64f628e9 | 750 | triggeredDigits[currCh] = FindPadMatchingTrig(detElemIdFromTrack, trackIntersectCh[currCh], isMatch, nboard, zRealMatch, y11); |
683cb6c5 | 751 | |
752 | // if FindPadMatchingTrig = -500 => too many digits matching pad => | |
67c201be | 753 | // => Event not clear => Do not use for efficiency calculation |
683cb6c5 | 754 | if(triggeredDigits[currCh]<-100){ |
755 | isClearEvent = kFALSE; | |
67c201be | 756 | // track is rejected since it matches many pads |
757 | AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesManyPads); | |
683cb6c5 | 758 | AliDebug(1, Form("Warning: track = %p (%i) matches many pads. Rejected!\n",(void *)matchedTrigTrack, detElemIdFromTrack)); |
683cb6c5 | 759 | } |
760 | ||
761 | for(Int_t cath=0; cath<fgkNcathodes; cath++){ | |
762 | if(!isMatch[cath]) continue; | |
67c201be | 763 | AliESDMuonTrack::SetFiredChamber(pattern, cath, currCh); |
683cb6c5 | 764 | digitPerTrack[cath]++; |
765 | trigScheme[cath][currCh]++; | |
766 | slatThatTriggered[cath][currCh] = detElemIdFromTrack; | |
767 | for(Int_t loc=0; loc<fgkNlocations; loc++){ | |
768 | boardThatTriggered[currCh][cath][loc] = nboard[cath][loc]; | |
769 | } | |
770 | } | |
771 | } // end chamber loop | |
772 | ||
773 | for(Int_t cath=0; cath<fgkNcathodes; cath++){ | |
67c201be | 774 | if(digitPerTrack[cath]<3) { |
775 | isClearEvent = kFALSE; | |
776 | // track is rejected since the number of associated | |
777 | // digits found is less than 3. | |
778 | AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesFewPads); | |
779 | AliDebug(1, Form("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath)); | |
780 | } | |
683cb6c5 | 781 | } |
782 | ||
783 | if(!isClearEvent) return kFALSE; | |
784 | ||
67c201be | 785 | AliESDMuonTrack::EAliTriggerChPatternFlag goodForEff = AliESDMuonTrack::kBoardEff; |
683cb6c5 | 786 | |
787 | Int_t ineffSlat = -1; | |
788 | Int_t ineffDetElId = -1; | |
789 | Int_t firstSlat = slatThatTriggered[kBending][0]%100; | |
790 | if(firstSlat<0) firstSlat = slatThatTriggered[kBending][1]%100; | |
791 | Int_t firstBoard = boardThatTriggered[0][kBending][0]; | |
792 | if(firstBoard<0) firstBoard = boardThatTriggered[1][kBending][0]; | |
793 | for(Int_t ch=0; ch<fgkNchambers; ch++){ | |
794 | Bool_t isCurrChIneff = kFALSE; | |
795 | Int_t currSlat = slatThatTriggered[kBending][ch]%100; | |
796 | if(currSlat<0){ | |
797 | ineffDetElId = DetElemIdFromPos(trackIntersectCh[ch][0], trackIntersectCh[ch][1], 11+ch, kBending); | |
798 | currSlat = ineffDetElId%100; | |
799 | ineffSlat = currSlat; | |
800 | isCurrChIneff = kTRUE; | |
801 | } | |
802 | if(currSlat!=firstSlat) { | |
67c201be | 803 | AliESDMuonTrack::AddEffInfo(pattern, |
804 | AliESDMuonTrack::kCrossDifferentSlats, | |
805 | AliESDMuonTrack::kChEff); // track crosses different slats | |
683cb6c5 | 806 | return kTRUE; |
807 | } | |
808 | Bool_t atLeastOneLoc=kFALSE; | |
809 | if(isCurrChIneff) LocalBoardFromPos(trackIntersectCh[ch][0], trackIntersectCh[ch][1], ineffDetElId, kBending, ineffBoard); | |
810 | for(Int_t loc=0; loc<fgkNlocations; loc++){ | |
811 | Int_t currBoard = boardThatTriggered[ch][kBending][loc]; | |
812 | if(isCurrChIneff) currBoard = ineffBoard[loc]; | |
813 | if(currBoard==firstBoard){ | |
814 | atLeastOneLoc=kTRUE; | |
815 | break; | |
816 | } | |
817 | } | |
67c201be | 818 | if(!atLeastOneLoc) goodForEff = AliESDMuonTrack::kSlatEff; |
683cb6c5 | 819 | } // end chamber loop |
820 | ||
67c201be | 821 | AliESDMuonTrack::AddEffInfo(pattern, firstSlat, goodForEff); |
683cb6c5 | 822 | return kTRUE; |
7771752e | 823 | } |