]>
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" |
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 | |
71 | ClassImp(AliMUONTrackHitPattern) // Class implementation in ROOT context | |
72 | /// \endcond | |
73 | ||
74 | ||
75 | //______________________________________________________________________________ | |
a0dc65b4 | 76 | AliMUONTrackHitPattern::AliMUONTrackHitPattern(const AliMUONRecoParam* recoParam, |
77 | const AliMUONGeometryTransformer& transformer, | |
d5315275 | 78 | const AliMUONVDigitStore& digitStore, |
79 | const AliMUONTriggerUtilities* triggerUtilities) | |
a0dc65b4 | 80 | : TObject(), |
9b1e069f | 81 | fkRecoParam(recoParam), |
82 | fkTransformer(transformer), | |
64f628e9 | 83 | fkDigitStore(digitStore), |
d5315275 | 84 | fkTriggerUtilities(triggerUtilities), |
0a2dcc83 | 85 | fkMaxDistance(99999.) // obsolete |
7771752e | 86 | { |
d5315275 | 87 | /// Default constructor |
88 | AliMUONTrackExtrap::SetField(); | |
7771752e | 89 | } |
90 | ||
91 | ||
92 | //______________________________________________________________________________ | |
93 | AliMUONTrackHitPattern::~AliMUONTrackHitPattern(void) | |
94 | { | |
7ec3b9cf | 95 | /// Destructor |
7771752e | 96 | } |
97 | ||
683cb6c5 | 98 | |
0a2dcc83 | 99 | //______________________________________________________________________________ |
100 | void | |
101 | AliMUONTrackHitPattern::ApplyMCSCorrections(AliMUONTrackParam& trackParam) const | |
102 | { | |
103 | // | |
104 | /// Returns uncertainties on extrapolated position. | |
105 | /// Takes into account Branson plane corrections in the iron wall. | |
106 | // | |
107 | ||
108 | const Float_t kZFilterOut = AliMUONConstants::MuonFilterZEnd(); | |
109 | const Float_t kFilterThickness = kZFilterOut-AliMUONConstants::MuonFilterZBeg(); // cm | |
110 | ||
111 | AliMUONTrackExtrap::ExtrapToZCov(&trackParam, kZFilterOut); // Extrap to muon filter end | |
112 | AliMUONTrackExtrap::AddMCSEffect(&trackParam, kFilterThickness, AliMUONConstants::MuonFilterX0()); // Add MCS effects | |
113 | return; | |
114 | } | |
115 | ||
116 | ||
683cb6c5 | 117 | //______________________________________________________________________________ |
9b1e069f | 118 | void AliMUONTrackHitPattern::ExecuteValidation(const AliMUONVTrackStore& trackStore, |
683cb6c5 | 119 | const AliMUONVTriggerTrackStore& triggerTrackStore, |
120 | const AliMUONVTriggerStore& triggerStore) const | |
121 | { | |
122 | // | |
123 | /// Main method: | |
124 | /// Loops on reco tracks, extrapolates them to trigger chambers | |
125 | /// and searches for matching trigger tracks and digits | |
126 | // | |
127 | ||
67c201be | 128 | // Get the hit pattern for all trigger tracks |
129 | AliMUONTriggerTrack* triggerTrack; | |
130 | TIter itTriggerTrack(triggerTrackStore.CreateIterator()); | |
131 | while ( ( triggerTrack = static_cast<AliMUONTriggerTrack*>(itTriggerTrack() ) ) ){ | |
0a2dcc83 | 132 | AliMUONTrackParam trackParam; |
133 | trackParam.SetNonBendingCoor(triggerTrack->GetX11()); | |
134 | trackParam.SetBendingCoor(triggerTrack->GetY11()); | |
135 | trackParam.SetZ(triggerTrack->GetZ11()); | |
136 | trackParam.SetNonBendingSlope(triggerTrack->GetSlopeX()); | |
137 | trackParam.SetBendingSlope(triggerTrack->GetSlopeY()); | |
138 | trackParam.SetInverseBendingMomentum(1.); | |
139 | UInt_t pattern = GetHitPattern(trackParam, kTRUE); | |
140 | triggerTrack->SetHitsPatternInTrigCh(pattern); | |
141 | AliDebug(1, Form("Hit pattern (MTR): hits 0x%x slat %2i board %3i effFlag %i", | |
142 | pattern & 0xFF, AliESDMuonTrack::GetSlatOrInfo(pattern),triggerTrack->GetLoTrgNum(), AliESDMuonTrack::GetEffFlag(pattern))); | |
67c201be | 143 | } |
683cb6c5 | 144 | |
67c201be | 145 | // Match tracker tracks with trigger tracks. |
683cb6c5 | 146 | TIter itTrack(trackStore.CreateIterator()); |
147 | AliMUONTrack* track; | |
148 | ||
149 | const Int_t kFirstTrigCh = AliMUONConstants::NTrackingCh(); | |
150 | ||
151 | while ( ( track = static_cast<AliMUONTrack*>(itTrack()) ) ) | |
152 | { | |
153 | AliMUONTrackParam trackParam(*((AliMUONTrackParam*) (track->GetTrackParamAtCluster()->Last()))); | |
154 | ||
155 | ApplyMCSCorrections(trackParam); | |
156 | AliMUONTrackExtrap::ExtrapToZCov(&trackParam, AliMUONConstants::DefaultChamberZ(kFirstTrigCh)); // extrap to 1st trigger chamber | |
157 | ||
158 | AliMUONTriggerTrack *matchedTriggerTrack = MatchTriggerTrack(track, trackParam, triggerTrackStore, triggerStore); | |
0a2dcc83 | 159 | if ( matchedTriggerTrack ) track->SetHitsPatternInTrigCh(matchedTriggerTrack->GetHitsPatternInTrigCh()); |
160 | ||
161 | UInt_t pattern = GetHitPattern(trackParam, kFALSE); | |
162 | track->SetHitsPatternInTrigChTrk(pattern); | |
163 | AliDebug(1, Form("Hit pattern (MTK): hits 0x%x slat %2i board %3i effFlag %i", | |
164 | pattern & 0xFF, AliESDMuonTrack::GetSlatOrInfo(pattern), AliESDMuonTrack::GetCrossedBoard(pattern), AliESDMuonTrack::GetEffFlag(pattern))); | |
165 | } | |
166 | } | |
683cb6c5 | 167 | |
67c201be | 168 | |
0a2dcc83 | 169 | //______________________________________________________________________________ |
170 | Bool_t AliMUONTrackHitPattern::FindMatchingPads(const AliMUONTrackParam* trackParam, | |
171 | TArrayI& matchedDetElemId, TObjArray& pads, | |
172 | const AliMUONVDigitStore& digitStore, | |
173 | Bool_t isTriggerTrack) const | |
174 | { | |
175 | // | |
176 | /// Search for matching digits in trigger chamber | |
177 | // | |
178 | enum {kBending, kNonBending}; | |
179 | ||
180 | Double_t minMatchDist[2]; | |
181 | Int_t padsInCheckArea[2]; | |
182 | ||
183 | AliMUONTrackParam trackParamAtPadZ(*trackParam); | |
184 | ||
185 | Int_t inputDetElemId = matchedDetElemId[0]; | |
186 | ||
187 | for(Int_t cath=0; cath<2; cath++){ | |
188 | minMatchDist[cath] = 99999.; | |
189 | padsInCheckArea[cath] = 0; | |
683cb6c5 | 190 | } |
0a2dcc83 | 191 | |
192 | Int_t iChamber = AliMpDEManager::GetChamberId(inputDetElemId); | |
193 | Int_t iSlat = inputDetElemId%100; | |
194 | ||
195 | TIter next(digitStore.CreateTriggerIterator()); | |
196 | AliMUONVDigit* mDigit; | |
197 | ||
198 | Double_t xPad = 0., yPad = 0., zPad = 0.; | |
199 | Double_t sigmaX = 0., sigmaY = 0.; | |
200 | ||
201 | Double_t nSigmas = ( isTriggerTrack ) ? GetRecoParam()->GetStripCutForTrigger() : GetRecoParam()->GetSigmaCutForTrigger(); | |
202 | Bool_t goodForEff = kTRUE; | |
203 | ||
204 | while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) ) | |
205 | { | |
206 | Int_t currDetElemId = mDigit->DetElemId(); | |
207 | Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId); | |
208 | if ( currCh != iChamber ) continue; | |
209 | Int_t currSlat = currDetElemId%100; | |
210 | Int_t slatDiff = TMath::Abs(currSlat-iSlat); | |
211 | if ( slatDiff>1 && slatDiff<17 ) continue; // Check neighbour slats | |
212 | ||
213 | Int_t cathode = mDigit->Cathode(); | |
214 | Int_t ix = mDigit->PadX(); | |
215 | Int_t iy = mDigit->PadY(); | |
216 | const AliMpVSegmentation* seg = AliMpSegmentation::Instance() | |
217 | ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode)); | |
218 | AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE); | |
219 | ||
220 | // Get local pad coordinates | |
221 | Double_t xPadLocal = pad.GetPositionX(); | |
222 | Double_t yPadLocal = pad.GetPositionY(); | |
223 | Double_t dpx = pad.GetDimensionX(); | |
224 | Double_t dpy = pad.GetDimensionY(); | |
225 | Double_t xWidth = 2. * dpx; | |
226 | Double_t yWidth = 2. * dpy; | |
227 | ||
228 | // Get global pad coordinates | |
229 | fkTransformer.Local2Global(currDetElemId, xPadLocal, yPadLocal, 0., xPad, yPad, zPad); | |
230 | ||
231 | // Get track parameters at pad z | |
232 | if ( trackParamAtPadZ.CovariancesExist() ) AliMUONTrackExtrap::LinearExtrapToZCov(&trackParamAtPadZ, zPad); | |
233 | else AliMUONTrackExtrap::LinearExtrapToZ(&trackParamAtPadZ, zPad); | |
234 | ||
235 | Double_t deltaX = TMath::Abs(xPad-trackParamAtPadZ.GetNonBendingCoor()) - dpx; | |
236 | Double_t deltaY = TMath::Abs(yPad-trackParamAtPadZ.GetBendingCoor()) - dpy; | |
237 | ||
238 | ||
239 | // Get sigmas | |
240 | if ( isTriggerTrack ) { | |
241 | Double_t checkWidth = TMath::Min(xWidth, yWidth); | |
242 | Double_t maxCheckArea = GetRecoParam()->GetMaxStripAreaForTrigger() * checkWidth; | |
243 | Double_t sigma = TMath::Max(checkWidth, 2.); | |
244 | sigmaX = sigma; // in cm | |
245 | sigmaY = sigma; // in cm | |
246 | if ( deltaX <= maxCheckArea && deltaY <= maxCheckArea ) { | |
247 | padsInCheckArea[cathode]++; | |
248 | if ( padsInCheckArea[cathode] > 2 ) { | |
249 | goodForEff = kFALSE; | |
250 | AliDebug(2, Form("padsInCheckArea[%i] = %i\n",cathode,padsInCheckArea[cathode])); | |
251 | } | |
252 | } | |
253 | } | |
254 | else { | |
255 | const TMatrixD& kCovParam = trackParamAtPadZ.GetCovariances(); | |
256 | sigmaX = TMath::Sqrt(kCovParam(0,0)); // in cm | |
257 | sigmaY = TMath::Sqrt(kCovParam(2,2)); // in cm | |
258 | } | |
259 | ||
260 | AliDebug(2, Form("\nDetElemId %i Cath %i Dim = (%.2f,%.2f) Pad (%i,%i) = (%.2f,%.2f) Track = (%.2f,%.2f) Delta (%.2f,%.2f) Sigma (%.2f,%.2f) p %g\n", | |
261 | currDetElemId,cathode,dpx,dpy,ix,iy,xPad,yPad,trackParamAtPadZ.GetNonBendingCoor(),trackParamAtPadZ.GetBendingCoor(),deltaX,deltaY,sigmaX,sigmaY,trackParamAtPadZ.P())); | |
262 | //if ( deltaX <= maxCheckArea && deltaY <= maxCheckArea ) padsInCheckArea[cathode]++; | |
263 | if ( deltaX > nSigmas * sigmaX || deltaY > nSigmas * sigmaY ) continue; | |
264 | Double_t matchDist = TMath::Max(deltaX, deltaY); | |
265 | if ( matchDist > minMatchDist[cathode] ) continue; | |
266 | if ( pads.At(cathode) ) delete pads.RemoveAt(cathode); | |
267 | pads.AddAt((AliMpPad*)pad.Clone(),cathode); | |
268 | minMatchDist[cathode] = matchDist; | |
269 | matchedDetElemId[cathode] = currDetElemId; // Set the input detection element id to the matched one | |
270 | } // loop on digits | |
271 | ||
272 | // // If track matches many pads, it is not good for effciency determination. | |
273 | // // However we still want to calculate the hit pattern. | |
274 | // for ( Int_t cath=0; cath<2; cath++ ){ | |
275 | // if ( padsInCheckArea[cath] > 2 ) { | |
276 | // AliDebug(2, Form("padsInCheckArea[%i] = %i\n",cath,padsInCheckArea[cath])); | |
277 | // return kFALSE; | |
278 | // } | |
279 | // } | |
280 | ||
281 | return goodForEff; | |
282 | } | |
283 | ||
284 | ||
285 | //_____________________________________________________________________________ | |
286 | UInt_t AliMUONTrackHitPattern::GetHitPattern(const AliMUONTrackParam& trackParam, Bool_t isTriggerTrack) const | |
287 | { | |
288 | // | |
289 | /// Searches for matching digits around the track. | |
290 | // | |
291 | ||
292 | AliCodeTimerAuto("",0); | |
293 | ||
294 | TArrayI digitPerTrack(2); | |
295 | digitPerTrack.Reset(); | |
296 | ||
297 | UInt_t pattern = 0; | |
298 | ||
299 | TObjArray trackParamList, matchedPads(2), maskedPads(2), padsFromPos(4), validPads(2); | |
300 | trackParamList.SetOwner(); matchedPads.SetOwner(); maskedPads.SetOwner(); padsFromPos.SetOwner(); | |
301 | ||
302 | Int_t firstSlat = -1, firstBoard = -1; | |
303 | AliESDMuonTrack::EAliTriggerChPatternFlag goodForEff = AliESDMuonTrack::kBoardEff; | |
304 | TArrayI matchedDetElemId(2), maskedDetElemId(2), detElemIdFromTrack(2), validDetElemId(2); | |
305 | ||
306 | for(Int_t ich=0; ich<AliMUONConstants::NTriggerCh(); ich++) { // chamber loop | |
307 | ||
308 | trackParamList.Delete(); matchedPads.Delete(); maskedPads.Delete(); padsFromPos.Delete(); validPads.Clear(); | |
309 | ||
310 | Int_t nFound = GetTrackParamAtChamber(trackParam, 11+ich, trackParamList, detElemIdFromTrack, padsFromPos); | |
311 | if ( nFound == 0 ) { | |
312 | // track is rejected since the extrapolated track | |
313 | // does not match a slat (border effects) | |
314 | AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackOutsideGeometry); | |
315 | goodForEff = AliESDMuonTrack::kNoEff; | |
316 | AliDebug(2, "Warning: trigger track outside trigger chamber\n"); | |
317 | continue; | |
318 | } | |
319 | ||
320 | // Search for masked pads | |
321 | maskedDetElemId.Reset(detElemIdFromTrack[0]); | |
322 | FindMatchingPads((AliMUONTrackParam*)trackParamList.At(0), maskedDetElemId, maskedPads, *(fkTriggerUtilities->GetMaskedDigits()), isTriggerTrack); | |
323 | if ( maskedPads.GetEntries() > 0 ) { | |
324 | AliESDMuonTrack::AddEffInfo(pattern,AliESDMuonTrack::kTrackMatchesMasks); // pad is masked | |
325 | goodForEff = AliESDMuonTrack::kNoEff; | |
326 | for ( Int_t icath=0; icath<2; icath++ ) { | |
327 | AliMpPad* currPad = (AliMpPad*)maskedPads.UncheckedAt(icath); | |
328 | if ( ! currPad ) continue; | |
329 | AliDebug(2,Form("DetElemId %i cath %i board %i strip %i is masked: effFlag 0", matchedDetElemId[icath], icath, currPad->GetLocalBoardId(0), currPad->GetLocalBoardChannel(0))); | |
330 | } | |
331 | // continue; | |
332 | // We want to calculate the hit pattern in any case, so we do not "continue" | |
333 | // However we set the flag in such a way not to use the track for efficiency calculations | |
334 | } | |
335 | ||
336 | // If no masked pads matched, search for active pads | |
337 | matchedDetElemId.Reset(detElemIdFromTrack[0]); | |
338 | if ( ! FindMatchingPads((AliMUONTrackParam*)trackParamList.At(0), matchedDetElemId, matchedPads, fkDigitStore, isTriggerTrack) ) { | |
339 | // if ! FindPadMatchingTrig => too many digits matching pad => | |
340 | // => Event not clear => Do not use for efficiency calculation | |
341 | AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesManyPads); | |
342 | goodForEff = AliESDMuonTrack::kNoEff; | |
343 | AliDebug(2, Form("Warning: track in %i matches many pads. Rejected!\n", matchedDetElemId[0])); | |
344 | } | |
345 | ||
346 | Int_t nMatched = 0; | |
347 | ||
348 | Int_t mostProbDEmatched = detElemIdFromTrack[0]; | |
349 | for ( Int_t icath=0; icath<2; icath++ ) { | |
350 | if ( matchedPads.UncheckedAt(icath) ) { | |
351 | nMatched++; | |
352 | // Fill pattern anyway | |
353 | AliESDMuonTrack::SetFiredChamber(pattern, icath, ich); | |
354 | digitPerTrack[icath]++; | |
355 | mostProbDEmatched = matchedDetElemId[icath]; | |
356 | } | |
357 | } | |
358 | Int_t mostProbDEindex = 0; | |
359 | for ( Int_t ifound=0; ifound<nFound; ifound++ ) { | |
360 | if ( detElemIdFromTrack[ifound] == mostProbDEmatched ) { | |
361 | mostProbDEindex = ifound; | |
362 | break; | |
363 | } | |
364 | } | |
365 | ||
366 | if ( goodForEff == AliESDMuonTrack::kNoEff ) continue; | |
367 | ||
368 | for ( Int_t icath=0; icath<2; icath++ ) { | |
369 | if ( matchedPads.UncheckedAt(icath) ) { | |
370 | validPads.AddAt(matchedPads.UncheckedAt(icath),icath); | |
371 | validDetElemId[icath] = matchedDetElemId[icath]; | |
372 | } | |
373 | else { | |
374 | validPads.AddAt(padsFromPos.UncheckedAt(2*mostProbDEindex + icath),icath); | |
375 | validDetElemId[icath] = detElemIdFromTrack[mostProbDEindex]; | |
376 | } | |
377 | } | |
378 | ||
379 | Int_t currSlat = mostProbDEmatched%100; | |
380 | if ( firstSlat < 0 ) firstSlat = currSlat; | |
381 | ||
382 | if ( currSlat != firstSlat || validDetElemId[0] != validDetElemId[1] ) { | |
383 | goodForEff = AliESDMuonTrack::kChEff; | |
384 | firstSlat = AliESDMuonTrack::kCrossDifferentSlats; | |
385 | } | |
386 | ||
387 | if ( firstBoard < 0 ) firstBoard = ((AliMpPad*)validPads.UncheckedAt(0))->GetLocalBoardId(0); | |
388 | ||
389 | for ( Int_t icath=0; icath<2; icath++ ){ | |
390 | ||
391 | if ( goodForEff == AliESDMuonTrack::kBoardEff) { | |
392 | Bool_t atLeastOneLoc = kFALSE; | |
393 | AliMpPad* currPad = (AliMpPad*)validPads.UncheckedAt(icath); | |
394 | for ( Int_t iloc=0; iloc<currPad->GetNofLocations(); iloc++) { | |
395 | if ( currPad->GetLocalBoardId(iloc) == firstBoard ) { | |
396 | atLeastOneLoc = kTRUE; | |
397 | break; | |
398 | } | |
399 | } // loop on locations | |
400 | if ( ! atLeastOneLoc ) goodForEff = AliESDMuonTrack::kSlatEff; | |
401 | } | |
402 | } // loop on cathodes | |
403 | // } // if track good for efficiency | |
404 | } // end chamber loop | |
405 | ||
406 | if ( goodForEff == AliESDMuonTrack::kNoEff ) return pattern; | |
407 | ||
408 | for(Int_t cath=0; cath<2; cath++){ | |
409 | if(digitPerTrack[cath]<3) { | |
410 | // track is rejected since the number of associated | |
411 | // digits found is less than 3. | |
412 | AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesFewPads); | |
413 | goodForEff = AliESDMuonTrack::kNoEff; | |
414 | AliDebug(2, Form("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath)); | |
415 | } | |
416 | } // loop on cathodes | |
417 | ||
418 | if ( goodForEff == AliESDMuonTrack::kNoEff ) return pattern; | |
419 | ||
420 | AliESDMuonTrack::AddEffInfo(pattern, firstSlat, firstBoard, goodForEff); | |
421 | return pattern; | |
422 | } | |
423 | ||
424 | ||
425 | ||
426 | //_____________________________________________________________________________ | |
427 | Int_t AliMUONTrackHitPattern::GetTrackParamAtChamber(const AliMUONTrackParam& inputTrackParam, Int_t chamber, | |
428 | TObjArray& trackParamList, TArrayI& foundDetElemId, | |
429 | TObjArray& padsFromPos) const | |
430 | { | |
431 | // | |
432 | /// Return the extrapolated the track parameter at the given chamber | |
433 | /// and returns the matching DetElemId | |
434 | /// CAVEAT: at the border the result is not univoque | |
435 | // | |
436 | ||
437 | Int_t nFound = 0; | |
438 | foundDetElemId[0] = foundDetElemId[1] = 0; | |
439 | AliMUONTrackParam trackParamCopy(inputTrackParam); | |
440 | TVector3 globalPoint1(trackParamCopy.GetNonBendingCoor(), trackParamCopy.GetBendingCoor(), trackParamCopy.GetZ()); | |
441 | AliMUONTrackExtrap::LinearExtrapToZ(&trackParamCopy, trackParamCopy.GetZ() + 20.); | |
442 | TVector3 globalPoint2(trackParamCopy.GetNonBendingCoor(), trackParamCopy.GetBendingCoor(), trackParamCopy.GetZ()); | |
443 | TVector3 localCoor; | |
444 | ||
445 | // AliMpArea pointArea(x, y, 2.*AliMpConstants::LengthTolerance(), 2.*AliMpConstants::LengthTolerance()); | |
446 | AliMpDEIterator it; | |
447 | Double_t xGlobal, yGlobal, zGlobal; | |
448 | for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){ | |
449 | Int_t detElemId = it.CurrentDEId(); | |
450 | PosInDetElemIdLocal(localCoor, globalPoint1, globalPoint2, detElemId); | |
451 | fkTransformer.Local2Global(detElemId, localCoor.X(), localCoor.Y(), localCoor.Z(), xGlobal, yGlobal, zGlobal); | |
452 | AliMpArea pointArea(xGlobal, yGlobal, 2.*AliMpConstants::LengthTolerance(), 2.*AliMpConstants::LengthTolerance()); | |
453 | AliMpArea* deArea = fkTransformer.GetDEArea(detElemId); | |
454 | if ( deArea->Contains(pointArea) ) { | |
455 | // Check if track matches valid pads | |
456 | // (this is not trivial for cut RPC) | |
457 | Int_t validPads = 0; | |
458 | for ( Int_t icath=0; icath<2; icath++ ) { | |
459 | const AliMpVSegmentation* seg = | |
460 | AliMpSegmentation::Instance() | |
461 | ->GetMpSegmentation(detElemId,AliMp::GetCathodType(icath)); | |
462 | AliMpPad pad = seg->PadByPosition(localCoor.X(),localCoor.Y(),kFALSE); | |
463 | if ( pad.IsValid() ) { | |
464 | padsFromPos.AddAt(pad.Clone(), 2*nFound + icath); | |
465 | validPads++; | |
466 | } | |
467 | } | |
468 | if ( validPads < 2 ) continue; | |
469 | AliMUONTrackParam* extrapTrackParam = new AliMUONTrackParam(inputTrackParam); | |
470 | if ( extrapTrackParam->CovariancesExist() ) AliMUONTrackExtrap::LinearExtrapToZCov(extrapTrackParam, zGlobal); | |
471 | else AliMUONTrackExtrap::LinearExtrapToZ(extrapTrackParam, zGlobal); | |
472 | trackParamList.AddAt(extrapTrackParam,nFound); | |
473 | foundDetElemId[nFound] = detElemId; | |
474 | nFound++; | |
475 | if ( nFound == 2 ) break; | |
476 | } | |
477 | else if ( nFound > 0 ) break; | |
478 | } // loop on detElemId | |
479 | ||
480 | return nFound; | |
683cb6c5 | 481 | } |
482 | ||
483 | ||
484 | //______________________________________________________________________________ | |
485 | AliMUONTriggerTrack * | |
486 | AliMUONTrackHitPattern::MatchTriggerTrack(AliMUONTrack* track, | |
487 | AliMUONTrackParam& trackParam, | |
488 | const AliMUONVTriggerTrackStore& triggerTrackStore, | |
489 | const AliMUONVTriggerStore& triggerStore) const | |
490 | { | |
491 | // | |
492 | /// Match track with trigger track | |
493 | // | |
494 | ||
495 | Int_t matchTrigger = 0; | |
496 | Int_t loTrgNum(-1); | |
bdfb6eef | 497 | TMatrixD paramDiff(3,1); |
683cb6c5 | 498 | Double_t chi2; |
499 | Double_t chi2MatchTrigger = 0., minChi2MatchTrigger = 999.; | |
500 | Int_t doubleMatch = -1; // Check if track matches 2 trigger tracks | |
501 | Double_t doubleChi2 = -1.; | |
502 | AliMUONTriggerTrack* doubleTriggerTrack = 0x0; | |
503 | AliMUONTriggerTrack* matchedTriggerTrack = 0x0; | |
7ec3b9cf | 504 | |
683cb6c5 | 505 | |
bdfb6eef | 506 | // Covariance matrix 3x3 (X,Y,slopeY) for trigger tracks |
683cb6c5 | 507 | TMatrixD trackCov(3,3); |
fda59e58 | 508 | |
683cb6c5 | 509 | AliMUONTriggerTrack *triggerTrack; |
510 | TIter itTriggerTrack(triggerTrackStore.CreateIterator()); | |
511 | while ( ( triggerTrack = static_cast<AliMUONTriggerTrack*>(itTriggerTrack() ) ) ) | |
512 | { | |
bdfb6eef | 513 | AliMUONTrackExtrap::LinearExtrapToZCov(&trackParam, triggerTrack->GetZ11()); |
514 | const TMatrixD& kParamCov = trackParam.GetCovariances(); | |
515 | ||
516 | Double_t xTrack = trackParam.GetNonBendingCoor(); | |
517 | Double_t yTrack = trackParam.GetBendingCoor(); | |
518 | Double_t ySlopeTrack = trackParam.GetBendingSlope(); | |
519 | ||
520 | paramDiff(0,0) = triggerTrack->GetX11() - xTrack; | |
521 | paramDiff(1,0) = triggerTrack->GetY11() - yTrack; | |
522 | paramDiff(2,0) = triggerTrack->GetSlopeY() - ySlopeTrack; | |
523 | ||
524 | // Covariance matrix 3x3 (X,Y,slopeY) for tracker tracks | |
525 | trackCov.Zero(); | |
526 | trackCov(0,0) = kParamCov(0,0); | |
527 | trackCov(1,1) = kParamCov(2,2); | |
528 | trackCov(2,2) = kParamCov(3,3); | |
529 | trackCov(1,2) = kParamCov(2,3); | |
530 | trackCov(2,1) = kParamCov(3,2); | |
531 | ||
532 | // Covariance matrix 3x3 (X,Y,slopeY) for trigger tracks | |
533 | TMatrixD trigCov(triggerTrack->GetCovariances()); | |
534 | ||
535 | TMatrixD sumCov(trackCov,TMatrixD::kPlus,trigCov); | |
536 | if (sumCov.Determinant() != 0) { | |
537 | sumCov.Invert(); | |
538 | ||
683cb6c5 | 539 | TMatrixD tmp(sumCov,TMatrixD::kMult,paramDiff); |
540 | TMatrixD chi2M(paramDiff,TMatrixD::kTransposeMult,tmp); | |
bdfb6eef | 541 | chi2 = chi2M(0,0); |
542 | } else { | |
543 | AliWarning(" Determinant = 0"); | |
544 | Double_t sigma2 = 0.; | |
683cb6c5 | 545 | chi2 = 0.; |
bdfb6eef | 546 | for (Int_t iVar = 0; iVar < 3; iVar++) { |
547 | sigma2 = trackCov(iVar,iVar) + trigCov(iVar,iVar); | |
548 | chi2 += paramDiff(iVar,0) * paramDiff(iVar,0) / sigma2; | |
549 | } | |
683cb6c5 | 550 | } |
fda59e58 | 551 | |
683cb6c5 | 552 | chi2 /= 3.; // Normalized Chi2: 3 degrees of freedom (X,Y,slopeY) |
a0dc65b4 | 553 | if (chi2 < GetRecoParam()->GetMaxNormChi2MatchTrigger()) |
7ec3b9cf | 554 | { |
683cb6c5 | 555 | Bool_t isDoubleTrack = (TMath::Abs(chi2 - minChi2MatchTrigger)<1.); |
a0dc65b4 | 556 | if (chi2 < minChi2MatchTrigger && chi2 < GetRecoParam()->GetMaxNormChi2MatchTrigger()) |
7ec3b9cf | 557 | { |
683cb6c5 | 558 | if(isDoubleTrack) |
559 | { | |
560 | doubleMatch = loTrgNum; | |
561 | doubleChi2 = chi2MatchTrigger; | |
562 | doubleTriggerTrack = matchedTriggerTrack; | |
fda59e58 | 563 | } |
683cb6c5 | 564 | minChi2MatchTrigger = chi2; |
565 | chi2MatchTrigger = chi2; | |
566 | loTrgNum = triggerTrack->GetLoTrgNum(); | |
567 | matchedTriggerTrack = triggerTrack; | |
568 | AliMUONLocalTrigger* locTrg = triggerStore.FindLocal(loTrgNum); | |
569 | matchTrigger = 1; | |
570 | if(locTrg->LoLpt()>0) matchTrigger = 2; | |
571 | if(locTrg->LoHpt()>0) matchTrigger = 3; | |
572 | } | |
573 | else if(isDoubleTrack) | |
574 | { | |
575 | doubleMatch = triggerTrack->GetLoTrgNum(); | |
576 | doubleChi2 = chi2; | |
7ec3b9cf | 577 | } |
7771752e | 578 | } |
683cb6c5 | 579 | } |
580 | if(doubleMatch>=0) | |
581 | { // If two trigger tracks match, select the one passing more trigger cuts | |
582 | AliDebug(1, Form("Two candidates found: %i and %i",loTrgNum,doubleMatch)); | |
583 | AliMUONLocalTrigger* locTrg1 = triggerStore.FindLocal(doubleMatch); | |
584 | if((locTrg1->LoLpt()>0 && matchTrigger<2) || (locTrg1->LoHpt() && matchTrigger<3)) | |
585 | { | |
586 | if(locTrg1->LoHpt()>0) matchTrigger=3; | |
587 | else matchTrigger = 2; | |
588 | loTrgNum = doubleMatch; | |
589 | chi2MatchTrigger = doubleChi2; | |
590 | matchedTriggerTrack = doubleTriggerTrack; | |
591 | } | |
592 | } | |
593 | ||
594 | track->SetMatchTrigger(matchTrigger); | |
683cb6c5 | 595 | track->SetChi2MatchTrigger(chi2MatchTrigger); |
596 | ||
597 | AliMUONLocalTrigger* locTrg = static_cast<AliMUONLocalTrigger*>(triggerStore.FindLocal(loTrgNum)); | |
598 | ||
599 | if (locTrg) | |
600 | { | |
601 | track->SetLocalTrigger(locTrg->LoCircuit(), | |
602 | locTrg->LoStripX(), | |
603 | locTrg->LoStripY(), | |
00d46f24 | 604 | locTrg->GetDeviation(), |
683cb6c5 | 605 | locTrg->LoLpt(), |
00d46f24 | 606 | locTrg->LoHpt(), |
607 | locTrg->GetTriggerWithoutChamber()); | |
683cb6c5 | 608 | } |
609 | ||
610 | return matchedTriggerTrack; | |
611 | } | |
612 | ||
613 | ||
0a2dcc83 | 614 | //_____________________________________________________________________________ |
615 | Bool_t AliMUONTrackHitPattern::PosInDetElemIdLocal(TVector3& localCoor, const TVector3& globalPoint1, | |
616 | const TVector3& globalPoint2, Int_t detElemId) const | |
617 | { | |
618 | /// Given two points belonging to a line (global coordinates) | |
619 | /// it returns the intersection point with the detElemId (local coordinates) | |
620 | ||
621 | Double_t xloc, yloc, zloc; | |
622 | fkTransformer.Global2Local(detElemId, globalPoint1.X(), globalPoint1.Y(), globalPoint1.Z(), xloc, yloc, zloc); | |
623 | TVector3 localPoint1(xloc, yloc, zloc); | |
624 | fkTransformer.Global2Local(detElemId, globalPoint2.X(), globalPoint2.Y(), globalPoint2.Z(), xloc, yloc, zloc); | |
625 | TVector3 localPoint2(xloc, yloc, zloc); | |
626 | localCoor = localPoint1 - ( localPoint1.Z() / ( localPoint2.Z() - localPoint1.Z() ) ) * ( localPoint2 - localPoint1 ); | |
627 | ||
628 | return kTRUE; | |
629 | } | |
630 | ||
631 | ||
632 | // THE FOLLOWING METHODS ARE OBSOLETE | |
633 | ||
683cb6c5 | 634 | //______________________________________________________________________________ |
0a2dcc83 | 635 | UInt_t AliMUONTrackHitPattern::GetHitPattern(const AliMUONTriggerTrack* matchedTriggerTrack) const |
683cb6c5 | 636 | { |
637 | // | |
67c201be | 638 | /// Get hit pattern on trigger chambers for the current trigger track |
683cb6c5 | 639 | // |
0a2dcc83 | 640 | UInt_t pattern = 0; |
64f628e9 | 641 | PerformTrigTrackMatch(pattern, matchedTriggerTrack); |
67c201be | 642 | return pattern; |
643 | } | |
683cb6c5 | 644 | |
54355f2c | 645 | |
67c201be | 646 | //______________________________________________________________________________ |
0a2dcc83 | 647 | UInt_t AliMUONTrackHitPattern::GetHitPattern(AliMUONTrackParam* trackParam) const |
67c201be | 648 | { |
649 | // | |
650 | /// Get hit pattern on trigger chambers for the current tracker track | |
651 | // | |
0a2dcc83 | 652 | UInt_t pattern = 0; |
67c201be | 653 | Bool_t isMatch[2]; |
654 | const Int_t kNTrackingCh = AliMUONConstants::NTrackingCh(); | |
0a2dcc83 | 655 | |
683cb6c5 | 656 | for(Int_t ch=0; ch<4; ++ch) |
657 | { | |
658 | Int_t iChamber = kNTrackingCh+ch; | |
54355f2c | 659 | AliMUONTrackExtrap::ExtrapToZCov(trackParam, AliMUONConstants::DefaultChamberZ(iChamber)); |
64f628e9 | 660 | FindPadMatchingTrack(*trackParam, isMatch, iChamber); |
683cb6c5 | 661 | for(Int_t cath=0; cath<2; ++cath) |
662 | { | |
67c201be | 663 | if(isMatch[cath]) AliESDMuonTrack::SetFiredChamber(pattern, cath, ch); |
683cb6c5 | 664 | } |
665 | } | |
0a2dcc83 | 666 | |
67c201be | 667 | // pattern obtained by propagation of tracker track |
668 | // when it does not match the trigger. | |
669 | AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackerTrackPattern); | |
0a2dcc83 | 670 | |
67c201be | 671 | return pattern; |
683cb6c5 | 672 | } |
673 | ||
683cb6c5 | 674 | |
7771752e | 675 | //______________________________________________________________________________ |
7ec3b9cf | 676 | void |
64f628e9 | 677 | AliMUONTrackHitPattern::FindPadMatchingTrack(const AliMUONTrackParam& trackParam, |
fda59e58 | 678 | Bool_t isMatch[2], Int_t iChamber) const |
7771752e | 679 | { |
680 | // | |
683cb6c5 | 681 | /// Given the tracker track position, searches for matching digits. |
7771752e | 682 | // |
683 | ||
684 | Float_t minMatchDist[2]; | |
685 | ||
7ec3b9cf | 686 | for(Int_t cath=0; cath<2; ++cath) |
687 | { | |
688 | isMatch[cath]=kFALSE; | |
683cb6c5 | 689 | minMatchDist[cath]=fkMaxDistance/10.; |
7771752e | 690 | } |
691 | ||
64f628e9 | 692 | TIter next(fkDigitStore.CreateTriggerIterator()); |
7ec3b9cf | 693 | AliMUONVDigit* mDigit; |
fda59e58 | 694 | |
7ec3b9cf | 695 | while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) ) |
696 | { | |
697 | Int_t currDetElemId = mDigit->DetElemId(); | |
fda59e58 | 698 | Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId); |
699 | if(currCh!=iChamber) continue; | |
7ec3b9cf | 700 | Int_t cathode = mDigit->Cathode(); |
701 | Int_t ix = mDigit->PadX(); | |
702 | Int_t iy = mDigit->PadY(); | |
703 | Float_t xpad, ypad, zpad; | |
704 | const AliMpVSegmentation* seg = AliMpSegmentation::Instance() | |
705 | ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode)); | |
706 | ||
168e9c4d | 707 | AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE); |
6e97fbb8 | 708 | Float_t xlocal1 = pad.GetPositionX(); |
709 | Float_t ylocal1 = pad.GetPositionY(); | |
710 | Float_t dpx = pad.GetDimensionX(); | |
711 | Float_t dpy = pad.GetDimensionY(); | |
712 | ||
9b1e069f | 713 | fkTransformer.Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad); |
7ec3b9cf | 714 | Float_t matchDist = MinDistanceFromPad(xpad, ypad, zpad, dpx, dpy, trackParam); |
715 | if(matchDist>minMatchDist[cathode])continue; | |
716 | isMatch[cathode] = kTRUE; | |
fda59e58 | 717 | if(isMatch[0] && isMatch[1]) break; |
7ec3b9cf | 718 | minMatchDist[cathode] = matchDist; |
7771752e | 719 | } |
7771752e | 720 | } |
721 | ||
722 | ||
723 | //______________________________________________________________________________ | |
7ec3b9cf | 724 | Float_t |
725 | AliMUONTrackHitPattern::MinDistanceFromPad(Float_t xPad, Float_t yPad, Float_t zPad, | |
726 | Float_t dpx, Float_t dpy, | |
727 | const AliMUONTrackParam& trackParam) const | |
7771752e | 728 | { |
729 | // | |
683cb6c5 | 730 | /// Decides if the digit belongs to the tracker track. |
7771752e | 731 | // |
7771752e | 732 | |
fda59e58 | 733 | AliMUONTrackParam trackParamAtPadZ(trackParam); |
bdfb6eef | 734 | AliMUONTrackExtrap::LinearExtrapToZCov(&trackParamAtPadZ, zPad); |
fda59e58 | 735 | |
736 | Float_t xTrackAtPad = trackParamAtPadZ.GetNonBendingCoor(); | |
737 | Float_t yTrackAtPad = trackParamAtPadZ.GetBendingCoor(); | |
7771752e | 738 | |
a0dc65b4 | 739 | const Float_t kNSigma = GetRecoParam()->GetSigmaCutForTrigger(); |
fda59e58 | 740 | |
741 | const TMatrixD& kCovParam = trackParamAtPadZ.GetCovariances(); | |
742 | ||
743 | Float_t sigmaX = TMath::Sqrt(kCovParam(0,0)); | |
744 | Float_t sigmaY = TMath::Sqrt(kCovParam(2,2)); | |
745 | ||
746 | Float_t maxDistX = kNSigma * sigmaX; // in cm | |
747 | Float_t maxDistY = kNSigma * sigmaY; // in cm | |
7771752e | 748 | |
749 | Float_t deltaX = TMath::Abs(xPad-xTrackAtPad)-dpx; | |
750 | Float_t deltaY = TMath::Abs(yPad-yTrackAtPad)-dpy; | |
751 | ||
683cb6c5 | 752 | Float_t matchDist = fkMaxDistance; |
7771752e | 753 | if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY); |
fda59e58 | 754 | |
7771752e | 755 | return matchDist; |
756 | } | |
757 | ||
758 | ||
683cb6c5 | 759 | //_____________________________________________________________________________ |
d5315275 | 760 | Bool_t AliMUONTrackHitPattern::FindPadMatchingTrig(const TVector3& vec11, const TVector3& vec21, |
761 | Int_t matchedDetElemId[2], TObjArray& pads) const | |
683cb6c5 | 762 | { |
d5315275 | 763 | // |
764 | /// Check slat and board number of digit matching trigger track | |
765 | // | |
766 | ||
767 | enum {kBending, kNonBending}; | |
768 | ||
769 | Float_t minMatchDist[2]; | |
770 | Int_t padsInCheckArea[2]; | |
771 | ||
772 | Int_t inputDetElemId = matchedDetElemId[0]; | |
773 | ||
774 | for(Int_t cath=0; cath<2; cath++){ | |
775 | minMatchDist[cath] = fkMaxDistance/10.; | |
776 | padsInCheckArea[cath] = 0; | |
777 | } | |
778 | ||
779 | Int_t iChamber = AliMpDEManager::GetChamberId(inputDetElemId); | |
780 | Int_t iSlat = inputDetElemId%100; | |
781 | ||
782 | TIter next(fkDigitStore.CreateTriggerIterator()); | |
783 | AliMUONVDigit* mDigit; | |
784 | TVector3 localExtrap; | |
785 | ||
786 | Int_t previousDetElemId = -1; | |
787 | ||
788 | while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) ) | |
789 | { | |
790 | Int_t currDetElemId = mDigit->DetElemId(); | |
791 | Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId); | |
792 | if ( currCh != iChamber ) continue; | |
793 | Int_t currSlat = currDetElemId%100; | |
794 | Int_t slatDiff = TMath::Abs(currSlat-iSlat); | |
795 | if ( slatDiff>1 && slatDiff<17 ) continue; // Check neighbour slats | |
796 | Int_t cathode = mDigit->Cathode(); | |
797 | Int_t ix = mDigit->PadX(); | |
798 | Int_t iy = mDigit->PadY(); | |
799 | const AliMpVSegmentation* seg = AliMpSegmentation::Instance() | |
800 | ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode)); | |
ad30b53f | 801 | |
d5315275 | 802 | AliMpPad pad = seg->PadByIndices(ix,iy,kTRUE); |
683cb6c5 | 803 | |
d5315275 | 804 | if ( currDetElemId != previousDetElemId ) { |
805 | PosInDetElemIdLocal(localExtrap, vec11, vec21, currDetElemId); | |
806 | previousDetElemId = currDetElemId; | |
683cb6c5 | 807 | } |
d5315275 | 808 | |
0a2dcc83 | 809 | AliDebug(11, Form("\nDetElemId = %i Cathode = %i Pad = (%i,%i) = (%.2f,%.2f) Dim = (%.2f,%.2f) Track = (%.2f,%.2f)\n", |
d5315275 | 810 | currDetElemId,cathode,ix,iy,pad.GetPositionX(),pad.GetPositionY(),pad.GetDimensionX(),pad.GetDimensionY(),localExtrap.X(),localExtrap.Y())); |
811 | Float_t matchDist = PadMatchTrack(pad, localExtrap); | |
812 | if ( matchDist < fkMaxDistance/2. ) padsInCheckArea[cathode]++; | |
813 | if ( matchDist > minMatchDist[cathode] ) continue; | |
814 | if ( pads.At(cathode) ) delete pads.RemoveAt(cathode); | |
815 | pads.AddAt((AliMpPad*)pad.Clone(),cathode); | |
816 | minMatchDist[cathode] = matchDist; | |
817 | matchedDetElemId[cathode] = currDetElemId; // Set the input detection element id to the matched one | |
818 | } // loop on digits | |
819 | ||
820 | // If track matches many pads, it is not good for effciency determination. | |
821 | // However we still want to calculate the hit pattern. | |
822 | for ( Int_t cath=0; cath<2; cath++ ){ | |
823 | if ( padsInCheckArea[cath] > 2 ) { | |
0a2dcc83 | 824 | AliDebug(10, Form("padsInCheckArea[%i] = %i\n",cath,padsInCheckArea[cath])); |
d5315275 | 825 | return kFALSE; |
67c201be | 826 | } |
d5315275 | 827 | } |
828 | ||
829 | return kTRUE; | |
683cb6c5 | 830 | } |
831 | ||
832 | //_____________________________________________________________________________ | |
d5315275 | 833 | Float_t AliMUONTrackHitPattern::PadMatchTrack(const AliMpPad& pad, const TVector3& trackPosAtPad) const |
683cb6c5 | 834 | { |
d5315275 | 835 | // |
836 | /// Decides if the digit belongs to the trigger track. | |
837 | // | |
838 | ||
839 | Float_t xPad = pad.GetPositionX(); | |
840 | Float_t yPad = pad.GetPositionY(); | |
841 | Float_t dpx = pad.GetDimensionX(); | |
842 | Float_t dpy = pad.GetDimensionY(); | |
843 | ||
683cb6c5 | 844 | |
a0dc65b4 | 845 | Float_t maxDist = GetRecoParam()->GetStripCutForTrigger() * 2. * TMath::Min(dpx,dpy); // cm |
d5315275 | 846 | if ( maxDist<2. ) maxDist = 2.; |
a0dc65b4 | 847 | Float_t maxDistCheckArea = GetRecoParam()->GetMaxStripAreaForTrigger() * 2. * TMath::Min(dpx,dpy); // cm |
683cb6c5 | 848 | |
d5315275 | 849 | Float_t matchDist = fkMaxDistance; |
683cb6c5 | 850 | |
d5315275 | 851 | Float_t deltaX = TMath::Abs(xPad-trackPosAtPad.X())-dpx; |
852 | Float_t deltaY = TMath::Abs(yPad-trackPosAtPad.Y())-dpy; | |
853 | Float_t maxDistX = maxDist; | |
854 | Float_t maxDistY = maxDist; | |
683cb6c5 | 855 | |
d5315275 | 856 | if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY); |
857 | else if(deltaX<=maxDistCheckArea && deltaY<=maxDistCheckArea) matchDist = fkMaxDistance/5.; | |
858 | return matchDist; | |
683cb6c5 | 859 | } |
860 | ||
861 | ||
862 | //_____________________________________________________________________________ | |
863 | Int_t AliMUONTrackHitPattern::DetElemIdFromPos(Float_t x, Float_t y, | |
d5315275 | 864 | Int_t chamber, Int_t foundDetElemId[2]) const |
683cb6c5 | 865 | { |
d5315275 | 866 | // |
867 | /// Given the (x,y) position in the chamber, | |
868 | /// it returns the corresponding slats | |
869 | /// Caveat: at the border the result is not univoque | |
870 | // | |
871 | ||
872 | Int_t nFound = 0; | |
873 | ||
874 | foundDetElemId[0] = foundDetElemId[1] = 0; | |
875 | AliMpArea pointArea(x, y, 2.*AliMpConstants::LengthTolerance(), 2.*AliMpConstants::LengthTolerance()); | |
876 | AliMpDEIterator it; | |
877 | for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){ | |
878 | Int_t detElemId = it.CurrentDEId(); | |
879 | AliMpArea* deArea = fkTransformer.GetDEArea(detElemId); | |
880 | ||
881 | if ( deArea->Contains(pointArea) ) { | |
882 | foundDetElemId[nFound++] = detElemId; | |
883 | if ( nFound == 2 ) break; | |
884 | } | |
885 | else if ( nFound > 0 ) break; | |
886 | } // loop on detElemId | |
887 | ||
888 | return nFound; | |
889 | } | |
683cb6c5 | 890 | |
683cb6c5 | 891 | |
d5315275 | 892 | |
893 | //_____________________________________________________________________________ | |
894 | Bool_t AliMUONTrackHitPattern::PadsFromPos(const TVector3& vec11, const TVector3& vec21, | |
895 | Int_t detElemId, TObjArray& pads) const | |
896 | { | |
897 | // | |
898 | /// Given the (x,y) position in the chamber, | |
899 | /// it returns the corresponding local board | |
900 | // | |
901 | ||
902 | pads.Delete(); | |
903 | ||
904 | TVector3 localCoor; | |
905 | PosInDetElemIdLocal(localCoor, vec11, vec21, detElemId); | |
906 | for ( Int_t icath=0; icath<2; icath++ ) { | |
907 | const AliMpVSegmentation* seg = | |
908 | AliMpSegmentation::Instance() | |
909 | ->GetMpSegmentation(detElemId,AliMp::GetCathodType(icath)); | |
910 | AliMpPad pad = seg->PadByPosition(localCoor.X(),localCoor.Y(),kFALSE); | |
911 | if ( pad.IsValid() ) { | |
912 | pads.AddAt(pad.Clone(), icath); | |
913 | } | |
914 | } | |
915 | ||
916 | return pads.GetEntries(); | |
683cb6c5 | 917 | } |
918 | ||
919 | ||
d5315275 | 920 | //_____________________________________________________________________________ |
921 | Bool_t AliMUONTrackHitPattern::IsCloseToAccEdge(TObjArray& pads, Int_t detElemId, Float_t coor[2]) const | |
922 | { | |
923 | AliMpArea* deArea = fkTransformer.GetDEArea(detElemId); | |
924 | Float_t dpx = ((AliMpPad*)pads.At(1))->GetDimensionX(); | |
925 | Float_t dpy = ((AliMpPad*)pads.At(0))->GetDimensionY(); | |
926 | Float_t resolution[2] = { 0.75*dpx, 0.75*dpy }; | |
927 | Float_t sign[3] = {0., 1., -1.}; | |
928 | for ( Int_t ineighx=0; ineighx<3; ineighx++ ) { | |
929 | for ( Int_t ineighy=0; ineighy<3; ineighy++ ) { | |
930 | AliMpArea pointArea(coor[0]+sign[ineighx]*resolution[0], | |
931 | coor[1]+sign[ineighy]*resolution[1], | |
932 | 2.*AliMpConstants::LengthTolerance(), | |
933 | 2.*AliMpConstants::LengthTolerance()); | |
934 | if ( ! deArea->Contains(pointArea) ) return kTRUE; | |
935 | } // loop on y neighbours | |
936 | } // loop on x neighbours | |
937 | return kFALSE; | |
938 | } | |
4e116cd5 | 939 | |
d5315275 | 940 | |
941 | //_____________________________________________________________________________ | |
942 | Bool_t AliMUONTrackHitPattern::IsMasked(const AliMpPad& pad, Int_t detElemId, Int_t cathode, const TVector3& vec11, const TVector3& vec21) const | |
943 | { | |
944 | // | |
945 | /// Check if pad or its neighbours are masked | |
946 | // | |
947 | ||
948 | Int_t nMasked = 0; | |
949 | ||
950 | if ( fkTriggerUtilities->IsMasked(pad, detElemId, cathode) ) ++nMasked; | |
951 | ||
952 | // Check closest neighbour | |
953 | ||
954 | TVector3 localCoor; | |
955 | PosInDetElemIdLocal(localCoor, vec11, vec21, detElemId); | |
956 | ||
957 | Float_t padPos[2] = { pad.GetPositionX(), pad.GetPositionY()}; | |
958 | Float_t padDim[2] = { pad.GetDimensionX(), pad.GetDimensionY()}; | |
959 | Float_t inpactPos[2] = { localCoor.X(), localCoor.Y()}; | |
960 | Float_t sign[2] = {-1., 1.}; | |
961 | Int_t icoor = 1-cathode; | |
962 | Int_t addSlatSign[3] = {0,1,-1}; | |
963 | Int_t inputCh = AliMpDEManager::GetChamberId(detElemId)+1; | |
964 | Int_t inputSlat = detElemId%100; | |
965 | ||
966 | Float_t newPos[2]; | |
967 | for ( Int_t ineigh=0; ineigh<2; ineigh++ ) { | |
968 | newPos[1-icoor] = inpactPos[1-icoor]; | |
969 | newPos[icoor] = inpactPos[icoor] + 1.05 * sign[ineigh] * padDim[icoor]; | |
970 | if ( TMath::Abs(newPos[icoor] - padPos[icoor]) < padDim[icoor] ) continue; | |
971 | const AliMpVSegmentation* seg = | |
972 | AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode)); | |
973 | AliMpPad neighPad = seg->PadByPosition(newPos[0],newPos[1],kFALSE); | |
974 | if ( neighPad.IsValid() ) { | |
975 | if ( fkTriggerUtilities->IsMasked(neighPad, detElemId, cathode) ) ++nMasked; | |
683cb6c5 | 976 | } |
d5315275 | 977 | else { |
978 | TVector3 deltaVec(newPos[0]-inpactPos[0],newPos[1]-inpactPos[1],0.); | |
979 | TVector3 transVec11 = vec11+deltaVec; | |
980 | TVector3 transVec21 = vec21+deltaVec; | |
981 | TObjArray padsFromPos; | |
982 | padsFromPos.SetOwner(); | |
983 | for ( Int_t iAddSlat=0; iAddSlat<2; iAddSlat++ ) { | |
984 | Int_t currSlat = (inputSlat + addSlatSign[iAddSlat])%18; | |
985 | Int_t currDetElemId = 100 * inputCh + currSlat; | |
986 | PadsFromPos(transVec11,transVec21,currDetElemId,padsFromPos); | |
987 | AliMpPad* currPad = (AliMpPad*)padsFromPos.UncheckedAt(cathode); | |
988 | Bool_t isMasked = ( currPad ) ? fkTriggerUtilities->IsMasked(*currPad, currDetElemId, cathode) : kFALSE; | |
989 | padsFromPos.Delete(); | |
990 | if ( isMasked ) ++nMasked; | |
991 | } | |
992 | } // loop on slats | |
993 | } // loop on neigbours | |
994 | ||
995 | Double_t maskedProb = ((Double_t)nMasked)/3.; | |
996 | if ( gRandom->Rndm() < maskedProb ) return kTRUE; | |
997 | ||
998 | return kFALSE; | |
683cb6c5 | 999 | } |
1000 | ||
1001 | ||
1002 | //_____________________________________________________________________________ | |
0a2dcc83 | 1003 | Bool_t AliMUONTrackHitPattern::PerformTrigTrackMatch(UInt_t &pattern, |
64f628e9 | 1004 | const AliMUONTriggerTrack* matchedTrigTrack) const |
7771752e | 1005 | { |
fda59e58 | 1006 | // |
683cb6c5 | 1007 | /// It searches for matching digits around the trigger track. |
fda59e58 | 1008 | // |
d5315275 | 1009 | |
1010 | AliCodeTimerAuto("",0); | |
7771752e | 1011 | |
683cb6c5 | 1012 | enum {kBending, kNonBending}; |
7771752e | 1013 | |
d5315275 | 1014 | TArrayF zMeanChamber(AliMUONConstants::NTriggerCh()); |
bdfb6eef | 1015 | zMeanChamber[0] = matchedTrigTrack->GetZ11(); |
1016 | zMeanChamber[1] = matchedTrigTrack->GetZ11() + AliMUONConstants::DefaultChamberZ(11) - AliMUONConstants::DefaultChamberZ(10); | |
1017 | zMeanChamber[2] = matchedTrigTrack->GetZ21(); | |
1018 | zMeanChamber[3] = matchedTrigTrack->GetZ21() + AliMUONConstants::DefaultChamberZ(13) - AliMUONConstants::DefaultChamberZ(12); | |
683cb6c5 | 1019 | |
d5315275 | 1020 | TArrayI digitPerTrack(2); |
683cb6c5 | 1021 | digitPerTrack.Reset(); |
683cb6c5 | 1022 | |
d5315275 | 1023 | Float_t trackIntersectCh[2]; |
683cb6c5 | 1024 | |
bdfb6eef | 1025 | Float_t slopeX = matchedTrigTrack->GetSlopeX(); |
1026 | Float_t slopeY = matchedTrigTrack->GetSlopeY(); | |
d5315275 | 1027 | |
1028 | Float_t z11 = matchedTrigTrack->GetZ11(); | |
1029 | Float_t x11 = slopeX * z11; | |
1030 | Float_t y11 = matchedTrigTrack->GetY11(); | |
1031 | Float_t z21 = matchedTrigTrack->GetZ21(); | |
1032 | Float_t x21 = slopeX * z21; | |
1033 | Float_t y21 = y11 + slopeY * (z21-z11); | |
1034 | TVector3 vec11(x11, y11, z11), vec21(x21, y21, z21); | |
1035 | ||
d5315275 | 1036 | Int_t firstSlat = -1, firstBoard = -1; |
1037 | AliESDMuonTrack::EAliTriggerChPatternFlag goodForEff = AliESDMuonTrack::kBoardEff; | |
1038 | TObjArray matchedPads(2), padsFromPos(2), validPads(2); | |
1039 | matchedPads.SetOwner(); padsFromPos.SetOwner(); | |
1040 | Int_t matchedDetElemId[2], detElemIdFromTrack[2]; | |
1041 | ||
1042 | for(Int_t ich=0; ich<AliMUONConstants::NTriggerCh(); ich++) { // chamber loop | |
1043 | ||
683cb6c5 | 1044 | // searching track intersection with chambers (first approximation) |
d5315275 | 1045 | Float_t deltaZ = zMeanChamber[ich] - zMeanChamber[0]; |
1046 | trackIntersectCh[0] = zMeanChamber[ich] * slopeX; | |
1047 | trackIntersectCh[1] = y11 + deltaZ * slopeY; | |
1048 | Int_t nFound = DetElemIdFromPos(trackIntersectCh[0], trackIntersectCh[1], 11+ich, detElemIdFromTrack); | |
1049 | if ( nFound == 0 ) { | |
67c201be | 1050 | // track is rejected since the extrapolated track |
1051 | // does not match a slat (border effects) | |
1052 | AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackOutsideGeometry); | |
d5315275 | 1053 | goodForEff = AliESDMuonTrack::kNoEff; |
0a2dcc83 | 1054 | AliDebug(10, "Warning: trigger track outside trigger chamber\n"); |
683cb6c5 | 1055 | continue; |
1056 | } | |
d5315275 | 1057 | |
1058 | matchedDetElemId[0] = matchedDetElemId[1] = detElemIdFromTrack[0]; | |
1059 | ||
1060 | if ( ! FindPadMatchingTrig(vec11, vec21, matchedDetElemId, matchedPads) ) { | |
1061 | // if ! FindPadMatchingTrig => too many digits matching pad => | |
1062 | // => Event not clear => Do not use for efficiency calculation | |
67c201be | 1063 | AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesManyPads); |
d5315275 | 1064 | goodForEff = AliESDMuonTrack::kNoEff; |
0a2dcc83 | 1065 | AliDebug(10, Form("Warning: track = %p (%i) matches many pads. Rejected!\n",(void *)matchedTrigTrack, matchedDetElemId[0])); |
683cb6c5 | 1066 | } |
d5315275 | 1067 | |
1068 | Int_t nMatched = 0; | |
1069 | ||
1070 | Int_t mostProbDEmatched = detElemIdFromTrack[0]; | |
1071 | for ( Int_t icath=0; icath<2; icath++ ) { | |
1072 | if ( matchedPads.UncheckedAt(icath) ) { | |
1073 | nMatched++; | |
1074 | // Fill pattern anyway | |
1075 | AliESDMuonTrack::SetFiredChamber(pattern, icath, ich); | |
1076 | digitPerTrack[icath]++; | |
1077 | mostProbDEmatched = matchedDetElemId[icath]; | |
683cb6c5 | 1078 | } |
1079 | } | |
d5315275 | 1080 | Int_t mostProbDEfromTrack = detElemIdFromTrack[0]; |
1081 | for ( Int_t ifound=0; ifound<nFound; ifound++ ) { | |
1082 | if ( detElemIdFromTrack[ifound] == mostProbDEmatched ) { | |
1083 | mostProbDEfromTrack = mostProbDEmatched; | |
1084 | break; | |
1085 | } | |
1086 | } | |
1087 | ||
1088 | if ( goodForEff == AliESDMuonTrack::kNoEff ) continue; | |
1089 | ||
1090 | if ( nMatched < 2 ) PadsFromPos(vec11, vec21, mostProbDEfromTrack, padsFromPos); | |
1091 | ||
1092 | for ( Int_t cath=0; cath<2; cath++ ) { | |
1093 | if ( matchedPads.UncheckedAt(cath) ) validPads.AddAt(matchedPads.UncheckedAt(cath),cath); | |
1094 | else if ( padsFromPos.UncheckedAt(cath) ) { | |
1095 | AliMpPad* currPad = (AliMpPad*)padsFromPos.UncheckedAt(cath); | |
1096 | validPads.AddAt(currPad,cath); | |
1097 | if ( IsMasked(*currPad, mostProbDEfromTrack, cath, vec11, vec21) ) { | |
1098 | // Check if strip was masked (if inefficient strip is found) | |
0a2dcc83 | 1099 | AliESDMuonTrack::AddEffInfo(pattern,AliESDMuonTrack::kTrackMatchesMasks); // pad is masked |
1100 | AliDebug(10,Form("DetElemId %i cath %i board %i strip %i is masked: effFlag 0", mostProbDEfromTrack, cath, currPad->GetLocalBoardId(0), currPad->GetLocalBoardChannel(0))); | |
d5315275 | 1101 | goodForEff = AliESDMuonTrack::kNoEff; |
1102 | } | |
1103 | } | |
1104 | else goodForEff = AliESDMuonTrack::kNoEff; | |
1105 | } // loop on cathodes | |
1106 | ||
1107 | if ( goodForEff != AliESDMuonTrack::kNoEff ) { | |
1108 | ||
1109 | if ( nMatched == 0 && IsCloseToAccEdge(padsFromPos, mostProbDEfromTrack, trackIntersectCh) ) { | |
1110 | // Non of cathodes is fired. | |
1111 | // If we are close to the edge of the RPC | |
1112 | // it could be a problem of acceptance | |
1113 | AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackOutsideGeometry); | |
1114 | goodForEff = AliESDMuonTrack::kNoEff; | |
0a2dcc83 | 1115 | AliDebug(10, "Warning: trigger track at the edge of the chamber\n"); |
d5315275 | 1116 | } |
1117 | ||
1118 | Int_t currSlat = mostProbDEmatched%100; | |
1119 | if ( firstSlat < 0 ) firstSlat = currSlat; | |
1120 | else if ( currSlat != firstSlat ) { | |
1121 | goodForEff = AliESDMuonTrack::kChEff; | |
1122 | firstSlat = AliESDMuonTrack::kCrossDifferentSlats; | |
1123 | } | |
1124 | ||
1125 | if ( firstBoard < 0 ) firstBoard = ((AliMpPad*)validPads[kBending])->GetLocalBoardId(0); | |
1126 | ||
1127 | for ( Int_t cath=0; cath<2; cath++ ){ | |
1128 | ||
1129 | if ( goodForEff == AliESDMuonTrack::kBoardEff) { | |
1130 | Bool_t atLeastOneLoc = kFALSE; | |
1131 | AliMpPad* currPad = (AliMpPad*)validPads.UncheckedAt(cath); | |
1132 | for ( Int_t iloc=0; iloc<currPad->GetNofLocations(); iloc++) { | |
1133 | if ( currPad->GetLocalBoardId(iloc) == firstBoard ) { | |
1134 | atLeastOneLoc = kTRUE; | |
1135 | break; | |
1136 | } | |
1137 | } // loop on locations | |
1138 | if ( ! atLeastOneLoc ) goodForEff = AliESDMuonTrack::kSlatEff; | |
1139 | } | |
1140 | } // loop on cathodes | |
1141 | } // if track good for efficiency | |
1142 | matchedPads.Delete(); | |
1143 | padsFromPos.Delete(); | |
683cb6c5 | 1144 | } // end chamber loop |
d5315275 | 1145 | |
1146 | if ( goodForEff == AliESDMuonTrack::kNoEff ) return kFALSE; | |
683cb6c5 | 1147 | |
d5315275 | 1148 | for(Int_t cath=0; cath<2; cath++){ |
67c201be | 1149 | if(digitPerTrack[cath]<3) { |
67c201be | 1150 | // track is rejected since the number of associated |
1151 | // digits found is less than 3. | |
1152 | AliESDMuonTrack::AddEffInfo(pattern, AliESDMuonTrack::kTrackMatchesFewPads); | |
d5315275 | 1153 | goodForEff = AliESDMuonTrack::kNoEff; |
0a2dcc83 | 1154 | AliDebug(10, Form("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath)); |
67c201be | 1155 | } |
d5315275 | 1156 | } // loop on cathodes |
683cb6c5 | 1157 | |
d5315275 | 1158 | if ( goodForEff == AliESDMuonTrack::kNoEff ) return kFALSE; |
683cb6c5 | 1159 | |
0a2dcc83 | 1160 | AliESDMuonTrack::AddEffInfo(pattern, firstSlat, firstBoard, goodForEff); |
683cb6c5 | 1161 | return kTRUE; |
7771752e | 1162 | } |