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