Line data Source code
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 :
16 : /* $Id$ */
17 :
18 : //-----------------------------------------------------------------------------
19 : /// \class AliMUONRecoCheck
20 : /// Utility class to check reconstruction
21 : /// Reconstructed tracks are compared to reference tracks.
22 : /// The reference tracks are built from AliTrackReference for the
23 : /// hit in chamber (0..9) and from kinematics for the vertex parameters.
24 : //-----------------------------------------------------------------------------
25 :
26 : // 13 Nov 2007:
27 : // Added a method to create a list of reconstructed AliMUONTrack objects from
28 : // ESD data. This is necessary since the track objects that are actually created
29 : // during offline reconstruction are no longer stored to disk.
30 : // - Artur Szostak <artursz@iafrica.com>
31 : // 25 Jan 2008:
32 : // Use the new ESDInterface to create MUON objects from ESD data
33 : // - Philippe Pillot
34 : //
35 :
36 : #include "AliMUONRecoCheck.h"
37 : #include "AliMUONTrack.h"
38 : #include "AliMUONVTrackStore.h"
39 : #include "AliMUONVCluster.h"
40 : #include "AliMUONVClusterStore.h"
41 : #include "AliMUONConstants.h"
42 : #include "AliMUONESDInterface.h"
43 : #include "AliMUONTrackParam.h"
44 : #include "AliMUONTriggerTrack.h"
45 : #include "AliMUONVTriggerTrackStore.h"
46 : #include "AliMUONTriggerStoreV1.h"
47 : #include "AliMUONLocalTrigger.h"
48 : #include "AliMCEventHandler.h"
49 : #include "AliMCEvent.h"
50 : #include "AliStack.h"
51 : #include "AliTrackReference.h"
52 : #include "AliLog.h"
53 : #include "AliESDEvent.h"
54 : #include "AliESDMuonTrack.h"
55 : #include "AliMUONDigitStoreV2S.h"
56 : #include "AliMUONVDigit.h"
57 : #include "AliMpVSegmentation.h"
58 : #include "AliMpSegmentation.h"
59 : #include "AliMpPad.h"
60 :
61 : #include "AliGeomManager.h"
62 : #include "AliCDBManager.h"
63 : #include "AliMpCDB.h"
64 : #include "AliMpDDLStore.h"
65 : #include "AliMUONCDB.h"
66 : #include "AliMUONGeometryTransformer.h"
67 : #include "AliMUONTriggerCircuit.h"
68 : #include "AliMUONVTrackReconstructor.h"
69 : #include "AliMUONVTriggerStore.h"
70 : #include "AliMUONCalibrationData.h"
71 : #include "AliMUONTriggerElectronics.h"
72 :
73 :
74 : #include "TGeoManager.h"
75 :
76 : #include <TFile.h>
77 : #include <TTree.h>
78 : #include <TParticle.h>
79 : #include <TParticlePDG.h>
80 : #include <Riostream.h>
81 :
82 : #include "AliMUONRecoCheck.h"
83 :
84 : /// \cond CLASSIMP
85 16 : ClassImp(AliMUONRecoCheck)
86 : /// \endcond
87 :
88 : //_____________________________________________________________________________
89 : AliMUONRecoCheck::AliMUONRecoCheck(const Char_t *esdFileName, const Char_t *pathSim)
90 0 : : TObject(),
91 0 : fMCEventHandler(new AliMCEventHandler()),
92 0 : fESDEvent(new AliESDEvent()),
93 0 : fESDTree (0x0),
94 0 : fESDFile (0x0),
95 0 : fCurrentEvent(0),
96 0 : fTrackRefStore(0x0),
97 0 : fRecoTrackRefStore(0x0),
98 0 : fRecoTriggerRefStore(0x0),
99 0 : fRecoTrackStore(0x0),
100 0 : fRecoTriggerTrackStore(0x0),
101 0 : fGeometryTransformer(0x0),
102 0 : fTriggerCircuit(0x0),
103 0 : fCalibrationData(0x0),
104 0 : fTriggerElectronics(0x0),
105 0 : fESDEventOwner(kTRUE)
106 0 : {
107 : /// Normal ctor
108 :
109 : // TrackRefs and Particules
110 0 : fMCEventHandler->SetInputPath(pathSim);
111 0 : fMCEventHandler->InitIO("");
112 :
113 : // ESD MUON Tracks
114 0 : fESDFile = TFile::Open(esdFileName); // open the file
115 0 : if (!fESDFile || !fESDFile->IsOpen()) {
116 0 : AliError(Form("opening ESD file %s failed", esdFileName));
117 0 : fESDFile = 0x0;
118 0 : return;
119 : }
120 0 : fESDTree = (TTree*) fESDFile->Get("esdTree"); // get the tree
121 0 : if (!fESDTree) {
122 0 : AliError("no ESD tree found");
123 0 : fESDFile->Close();
124 0 : fESDFile = 0x0;
125 0 : return;
126 : }
127 0 : fESDEvent->ReadFromTree(fESDTree); // link fESDEvent to the tree
128 0 : }
129 :
130 : //_____________________________________________________________________________
131 : AliMUONRecoCheck::AliMUONRecoCheck(AliESDEvent *esdEvent, AliMCEventHandler *mcEventHandler)
132 0 : : TObject(),
133 0 : fMCEventHandler(0),
134 0 : fESDEvent(0),
135 0 : fESDTree (0x0),
136 0 : fESDFile (0x0),
137 0 : fCurrentEvent(0),
138 0 : fTrackRefStore(0x0),
139 0 : fRecoTrackRefStore(0x0),
140 0 : fRecoTriggerRefStore(0x0),
141 0 : fRecoTrackStore(0x0),
142 0 : fRecoTriggerTrackStore(0x0),
143 0 : fGeometryTransformer(0x0),
144 0 : fTriggerCircuit(0x0),
145 0 : fCalibrationData(0x0),
146 0 : fTriggerElectronics(0x0),
147 0 : fESDEventOwner(kFALSE)
148 0 : {
149 : /// Normal ctor
150 :
151 : // TrackRefs and Particules
152 0 : fMCEventHandler = mcEventHandler;
153 :
154 : // ESD MUON Tracks
155 0 : fESDEvent = esdEvent;
156 0 : }
157 :
158 : //_____________________________________________________________________________
159 : AliMUONRecoCheck::~AliMUONRecoCheck()
160 0 : {
161 : /// Destructor
162 0 : if (fESDEventOwner) {
163 0 : delete fMCEventHandler;
164 0 : delete fESDEvent;
165 0 : if (fESDFile) fESDFile->Close();
166 : }
167 0 : ResetStores();
168 0 : delete fGeometryTransformer;
169 0 : delete fTriggerCircuit;
170 0 : delete fTriggerElectronics;
171 0 : delete fCalibrationData;
172 0 : }
173 :
174 : //_____________________________________________________________________________
175 : void AliMUONRecoCheck::ResetStores()
176 : {
177 : /// Deletes all the store objects that have been created and resets the pointers to 0x0
178 0 : delete fTrackRefStore; fTrackRefStore = 0x0;
179 0 : delete fRecoTrackRefStore; fRecoTrackRefStore = 0x0;
180 0 : delete fRecoTriggerRefStore; fRecoTriggerRefStore = 0x0;
181 0 : delete fRecoTrackStore; fRecoTrackStore = 0x0;
182 0 : delete fRecoTriggerTrackStore; fRecoTriggerTrackStore = 0x0;
183 0 : }
184 :
185 : //_____________________________________________________________________________
186 : Bool_t AliMUONRecoCheck::InitCircuit()
187 : {
188 :
189 0 : if ( fTriggerCircuit ) return kTRUE;
190 :
191 0 : if ( ! InitGeometryTransformer() ) return kFALSE;
192 :
193 : // reset tracker for local trigger to trigger track conversion
194 0 : if ( ! AliMUONESDInterface::GetTracker() ) AliMUONESDInterface::ResetTracker();
195 :
196 0 : fTriggerCircuit = new AliMUONTriggerCircuit(fGeometryTransformer);
197 :
198 0 : return kTRUE;
199 0 : }
200 :
201 :
202 : //_____________________________________________________________________________
203 : Int_t AliMUONRecoCheck::GetRunNumber()
204 : {
205 : /// Return the run number of the current ESD event
206 :
207 0 : if (fESDEventOwner && fRecoTrackStore == 0x0 && fRecoTriggerTrackStore == 0x0) {
208 0 : if (!fESDTree || fESDTree->GetEvent(fCurrentEvent) <= 0) {
209 0 : AliError(Form("fails to read ESD object for event %d: cannot get the run number",fCurrentEvent));
210 0 : return -1;
211 : }
212 : }
213 :
214 0 : return fESDEvent->GetRunNumber();
215 0 : }
216 :
217 : //_____________________________________________________________________________
218 : Int_t AliMUONRecoCheck::NumberOfEvents() const
219 : {
220 : /// Return the number of events
221 0 : if (fESDEventOwner && fESDTree) return fESDTree->GetEntries();
222 0 : return 0;
223 0 : }
224 :
225 : //_____________________________________________________________________________
226 : AliMUONVTrackStore* AliMUONRecoCheck::ReconstructedTracks(Int_t event, Bool_t refit)
227 : {
228 : /// Return a track store containing the reconstructed tracks (converted into
229 : /// MUONTrack objects) for a given event.
230 : /// Track parameters at each clusters are computed or not depending on the flag "refit".
231 : /// If not, only the track parameters at first cluster are valid.
232 :
233 0 : if (!fESDEventOwner) {
234 0 : if (fRecoTrackStore == 0x0) MakeReconstructedTracks(refit);
235 0 : return fRecoTrackStore;
236 : }
237 :
238 0 : if (event != fCurrentEvent) {
239 0 : ResetStores();
240 0 : fCurrentEvent = event;
241 0 : }
242 :
243 0 : if (fRecoTrackStore != 0x0) return fRecoTrackStore;
244 : else {
245 0 : if (!fESDTree) return 0x0;
246 0 : if (fESDTree->GetEvent(event) <= 0) {
247 0 : AliError(Form("fails to read ESD object for event %d", event));
248 0 : return 0x0;
249 : }
250 0 : MakeReconstructedTracks(refit);
251 0 : return fRecoTrackStore;
252 : }
253 0 : }
254 :
255 :
256 : //_____________________________________________________________________________
257 : AliMUONVTriggerTrackStore* AliMUONRecoCheck::TriggeredTracks(Int_t event)
258 : {
259 : /// Return a track store containing the reconstructed trigger tracks (converted into
260 : /// MUONTriggerTrack objects) for a given event.
261 :
262 0 : if (!fESDEventOwner) {
263 0 : if (fRecoTriggerTrackStore == 0x0) MakeTriggeredTracks();
264 0 : return fRecoTriggerTrackStore;
265 : }
266 :
267 0 : if (event != fCurrentEvent) {
268 0 : ResetStores();
269 0 : fCurrentEvent = event;
270 0 : }
271 :
272 0 : if (fRecoTriggerTrackStore != 0x0) return fRecoTriggerTrackStore;
273 : else {
274 0 : if (!fESDTree) return 0x0;
275 0 : if (fESDTree->GetEvent(event) <= 0) {
276 0 : AliError(Form("fails to read ESD object for event %d", event));
277 0 : return 0x0;
278 : }
279 0 : MakeTriggeredTracks();
280 0 : return fRecoTriggerTrackStore;
281 : }
282 0 : }
283 :
284 :
285 : //_____________________________________________________________________________
286 : AliMUONVTrackStore* AliMUONRecoCheck::TrackRefs(Int_t event)
287 : {
288 : /// Return a track store containing the track references (converted into
289 : /// MUONTrack objects) for a given event
290 :
291 0 : if (!fESDEventOwner) {
292 0 : if (fTrackRefStore == 0x0) MakeTrackRefs();
293 0 : return fTrackRefStore;
294 : }
295 :
296 0 : if (event != fCurrentEvent) {
297 0 : ResetStores();
298 0 : fCurrentEvent = event;
299 0 : }
300 :
301 0 : if (fTrackRefStore != 0x0) return fTrackRefStore;
302 : else {
303 0 : if (!fMCEventHandler->BeginEvent(event)) {
304 0 : AliError(Form("fails to read MC objects for event %d", event));
305 0 : return 0x0;
306 : }
307 0 : MakeTrackRefs();
308 0 : fMCEventHandler->FinishEvent();
309 0 : return fTrackRefStore;
310 : }
311 0 : }
312 :
313 : //_____________________________________________________________________________
314 : AliMUONVTriggerTrackStore* AliMUONRecoCheck::TriggerableTracks(Int_t event)
315 : {
316 : /// Return a trigger track store containing the triggerable track references (converted into
317 : /// AliMUONTriggerTrack objects) for a given event
318 :
319 0 : if (!fESDEventOwner) {
320 0 : if (fRecoTriggerRefStore == 0x0) MakeTriggerableTracks();
321 0 : return fRecoTriggerRefStore;
322 : }
323 :
324 0 : if (event != fCurrentEvent) {
325 0 : ResetStores();
326 0 : fCurrentEvent = event;
327 0 : }
328 :
329 0 : if (fRecoTriggerRefStore != 0x0) return fRecoTriggerRefStore;
330 : else {
331 0 : if (!fMCEventHandler->BeginEvent(event)) {
332 0 : AliError(Form("fails to read MC objects for event %d", event));
333 0 : return 0x0;
334 : }
335 0 : MakeTriggerableTracks();
336 0 : fMCEventHandler->FinishEvent();
337 0 : return fRecoTriggerRefStore;
338 : }
339 0 : }
340 :
341 :
342 : //_____________________________________________________________________________
343 : AliMUONVTrackStore* AliMUONRecoCheck::ReconstructibleTracks(Int_t event, UInt_t requestedStationMask,
344 : Bool_t request2ChInSameSt45, Bool_t hitInFrontOfPad)
345 : {
346 : /// Return a track store containing the reconstructible tracks for a given event,
347 : /// according to the mask of requested stations and the minimum number of chambers hit in stations 4 & 5.
348 :
349 0 : if (!fESDEventOwner) {
350 0 : if (fRecoTrackRefStore == 0x0) {
351 0 : if (TrackRefs(event) == 0x0) return 0x0;
352 0 : MakeReconstructibleTracks(requestedStationMask, request2ChInSameSt45, hitInFrontOfPad);
353 0 : }
354 0 : return fRecoTrackRefStore;
355 : }
356 :
357 0 : if (event != fCurrentEvent) {
358 0 : ResetStores();
359 0 : fCurrentEvent = event;
360 0 : }
361 :
362 0 : if (fRecoTrackRefStore != 0x0) return fRecoTrackRefStore;
363 : else {
364 0 : if (TrackRefs(event) == 0x0) return 0x0;
365 0 : MakeReconstructibleTracks(requestedStationMask, request2ChInSameSt45, hitInFrontOfPad);
366 0 : return fRecoTrackRefStore;
367 : }
368 0 : }
369 :
370 :
371 : //_____________________________________________________________________________
372 : void AliMUONRecoCheck::MakeReconstructedTracks(Bool_t refit)
373 : {
374 : /// Make reconstructed tracks
375 0 : if (!(fRecoTrackStore = AliMUONESDInterface::NewTrackStore())) return;
376 :
377 : // loop over all reconstructed tracks and add them to the store (skip ghosts)
378 0 : Int_t nTracks = (Int_t) fESDEvent->GetNumberOfMuonTracks();
379 0 : for (Int_t iTrack = 0; iTrack < nTracks; iTrack++) {
380 0 : AliESDMuonTrack* esdTrack = fESDEvent->GetMuonTrack(iTrack);
381 0 : if (esdTrack->ContainTrackerData()) AliMUONESDInterface::Add(*esdTrack, *fRecoTrackStore, refit);
382 : }
383 :
384 0 : }
385 :
386 :
387 : //_____________________________________________________________________________
388 : void AliMUONRecoCheck::MakeTriggeredTracks()
389 : {
390 : /// Make reconstructed trigger tracks
391 0 : if (!(fRecoTriggerTrackStore = AliMUONESDInterface::NewTriggerTrackStore())) return;
392 :
393 0 : AliMUONVTriggerStore* tmpTriggerStore = AliMUONESDInterface::NewTriggerStore();
394 0 : if ( ! tmpTriggerStore ) return;
395 :
396 : // loop over all reconstructed tracks and add them to the store (include ghosts)
397 0 : Int_t nTracks = (Int_t) fESDEvent->GetNumberOfMuonTracks();
398 0 : for (Int_t iTrack = 0; iTrack < nTracks; iTrack++) {
399 0 : AliESDMuonTrack* esdTrack = fESDEvent->GetMuonTrack(iTrack);
400 0 : if (esdTrack->ContainTriggerData()) AliMUONESDInterface::Add(*esdTrack, *tmpTriggerStore);
401 : }
402 :
403 0 : if ( InitCircuit() ) {
404 :
405 0 : AliMUONVTrackReconstructor* tracker = AliMUONESDInterface::GetTracker();
406 0 : tracker->EventReconstructTrigger(*fTriggerCircuit, *tmpTriggerStore, *fRecoTriggerTrackStore);
407 0 : }
408 :
409 0 : delete tmpTriggerStore;
410 0 : }
411 :
412 : //_____________________________________________________________________________
413 : Bool_t AliMUONRecoCheck::TriggerToTrack(const AliMUONLocalTrigger& locTrg, AliMUONTriggerTrack& triggerTrack)
414 : {
415 : /// Make trigger track from local trigger info
416 0 : if ( ! InitCircuit() ) return kFALSE;
417 0 : AliMUONVTrackReconstructor* tracker = AliMUONESDInterface::GetTracker();
418 0 : return tracker->TriggerToTrack(*fTriggerCircuit, locTrg, triggerTrack);
419 0 : }
420 :
421 :
422 : //_____________________________________________________________________________
423 : void AliMUONRecoCheck::MakeTrackRefs()
424 : {
425 : /// Make reconstructible tracks
426 0 : AliMUONVTrackStore *tmpTrackRefStore = AliMUONESDInterface::NewTrackStore();
427 0 : if (!tmpTrackRefStore) return;
428 :
429 : Double_t x, y, z, pX, pY, pZ, bendingSlope, nonBendingSlope, inverseBendingMomentum;
430 0 : TParticle* particle;
431 0 : TClonesArray* trackRefs;
432 0 : Int_t nTrackRef = fMCEventHandler->MCEvent()->GetNumberOfTracks();
433 0 : AliMUONVCluster* hit = AliMUONESDInterface::NewCluster();
434 :
435 : // loop over simulated tracks
436 0 : for (Int_t iTrackRef = 0; iTrackRef < nTrackRef; ++iTrackRef) {
437 0 : Int_t nHits = fMCEventHandler->GetParticleAndTR(iTrackRef, particle, trackRefs);
438 :
439 : // skip empty trackRefs
440 0 : if (nHits < 1) continue;
441 :
442 : // get the particle charge for further calculation
443 0 : TParticlePDG* ppdg = particle->GetPDG();
444 0 : Int_t charge = ppdg != NULL ? (Int_t)(ppdg->Charge()/3.0) : 0;
445 :
446 0 : AliMUONTrack track;
447 :
448 : // loop over simulated track hits
449 0 : for (Int_t iHit = 0; iHit < nHits; ++iHit) {
450 0 : AliTrackReference* trackReference = static_cast<AliTrackReference*>(trackRefs->UncheckedAt(iHit));
451 :
452 : // skip trackRefs not in MUON
453 0 : if (trackReference->DetectorId() != AliTrackReference::kMUON) continue;
454 :
455 : // Get track parameters of current hit
456 0 : x = trackReference->X();
457 0 : y = trackReference->Y();
458 0 : z = trackReference->Z();
459 0 : pX = trackReference->Px();
460 0 : pY = trackReference->Py();
461 0 : pZ = trackReference->Pz();
462 :
463 : // check chamberId of current trackReference
464 0 : Int_t detElemId = trackReference->UserId();
465 0 : Int_t chamberId = detElemId / 100 - 1;
466 0 : if (chamberId < 0 || chamberId >= AliMUONConstants::NTrackingCh()) continue;
467 :
468 : // set hit parameters
469 0 : hit->SetUniqueID(AliMUONVCluster::BuildUniqueID(chamberId, detElemId, iHit));
470 0 : hit->SetXYZ(x,y,z);
471 0 : hit->SetErrXY(0.,0.);
472 :
473 : // compute track parameters at hit
474 : bendingSlope = 0;
475 : nonBendingSlope = 0;
476 : inverseBendingMomentum = 0;
477 0 : if (TMath::Abs(pZ) > 0) {
478 0 : bendingSlope = pY/pZ;
479 0 : nonBendingSlope = pX/pZ;
480 0 : }
481 0 : Double_t pYZ = TMath::Sqrt(pY*pY+pZ*pZ);
482 0 : if (pYZ >0) inverseBendingMomentum = 1/pYZ;
483 0 : inverseBendingMomentum *= charge;
484 :
485 : // set track parameters at hit
486 0 : AliMUONTrackParam trackParam;
487 0 : trackParam.SetNonBendingCoor(x);
488 0 : trackParam.SetBendingCoor(y);
489 0 : trackParam.SetZ(z);
490 0 : trackParam.SetBendingSlope(bendingSlope);
491 0 : trackParam.SetNonBendingSlope(nonBendingSlope);
492 0 : trackParam.SetInverseBendingMomentum(inverseBendingMomentum);
493 :
494 : // add track parameters at current hit to the track
495 0 : track.AddTrackParamAtCluster(trackParam, *hit, kTRUE);
496 0 : }
497 :
498 : // if none of the track hits was in MUON, goto the next track
499 0 : if (track.GetNClusters() < 1) continue;
500 :
501 : // get track parameters at particle's vertex
502 0 : x = particle->Vx();
503 0 : y = particle->Vy();
504 0 : z = particle->Vz();
505 0 : pX = particle->Px();
506 0 : pY = particle->Py();
507 0 : pZ = particle->Pz();
508 :
509 : // compute rest of track parameters at particle's vertex
510 : bendingSlope = 0;
511 : nonBendingSlope = 0;
512 : inverseBendingMomentum = 0;
513 0 : if (TMath::Abs(pZ) > 0) {
514 0 : bendingSlope = pY/pZ;
515 0 : nonBendingSlope = pX/pZ;
516 0 : }
517 0 : Double_t pYZ = TMath::Sqrt(pY*pY+pZ*pZ);
518 0 : if (pYZ >0) inverseBendingMomentum = 1/pYZ;
519 0 : inverseBendingMomentum *= charge;
520 :
521 : // set track parameters at particle's vertex
522 0 : AliMUONTrackParam trackParamAtVertex;
523 0 : trackParamAtVertex.SetNonBendingCoor(x);
524 0 : trackParamAtVertex.SetBendingCoor(y);
525 0 : trackParamAtVertex.SetZ(z);
526 0 : trackParamAtVertex.SetBendingSlope(bendingSlope);
527 0 : trackParamAtVertex.SetNonBendingSlope(nonBendingSlope);
528 0 : trackParamAtVertex.SetInverseBendingMomentum(inverseBendingMomentum);
529 :
530 : // add track parameters at vertex
531 0 : track.SetTrackParamAtVertex(&trackParamAtVertex);
532 :
533 : // store the track
534 0 : track.SetUniqueID(iTrackRef);
535 0 : tmpTrackRefStore->Add(track);
536 0 : }
537 :
538 0 : CleanMuonTrackRef(tmpTrackRefStore);
539 :
540 0 : delete hit;
541 0 : delete tmpTrackRefStore;
542 0 : }
543 :
544 : //_____________________________________________________________________________
545 : void AliMUONRecoCheck::MakeTriggerableTracks()
546 : {
547 : /// Make triggerable tracks
548 0 : if (!(fRecoTriggerRefStore = AliMUONESDInterface::NewTriggerTrackStore()))
549 : return;
550 :
551 0 : Double_t x, y, z, slopeX, slopeY, pZ, xLoc, yLoc, zLoc;
552 0 : TParticle* particle;
553 0 : TClonesArray* trackRefs;
554 0 : Int_t nTrackRef = fMCEventHandler->MCEvent()->GetNumberOfTracks();
555 :
556 : // loop over simulated tracks
557 0 : for (Int_t iTrackRef = 0; iTrackRef < nTrackRef; ++iTrackRef) {
558 0 : Int_t nHits = fMCEventHandler->GetParticleAndTR(iTrackRef, particle, trackRefs);
559 :
560 : // skip empty trackRefs
561 0 : if (nHits < 1) continue;
562 :
563 0 : AliMUONTriggerTrack track;
564 0 : AliMUONDigitStoreV2S digitStore;
565 : Int_t hitsOnTrigger = 0;
566 : Int_t currCh = -1;
567 :
568 : // loop over simulated track hits
569 0 : for (Int_t iHit = 0; iHit < nHits; ++iHit) {
570 0 : AliTrackReference* trackReference = static_cast<AliTrackReference*>(trackRefs->UncheckedAt(iHit));
571 :
572 : // skip trackRefs not in MUON
573 0 : if (trackReference->DetectorId() != AliTrackReference::kMUON) continue;
574 :
575 : // check chamberId of current trackReference
576 0 : Int_t detElemId = trackReference->UserId();
577 0 : Int_t chamberId = detElemId / 100 - 1;
578 0 : if (chamberId < AliMUONConstants::NTrackingCh() || chamberId >= AliMUONConstants::NCh() ) continue;
579 :
580 : // Get track parameters of current hit
581 0 : x = trackReference->X();
582 0 : y = trackReference->Y();
583 0 : z = trackReference->Z();
584 :
585 0 : if ( InitTriggerResponse() ) {
586 0 : fGeometryTransformer->Global2Local(detElemId, x, y, z, xLoc, yLoc, zLoc);
587 :
588 : Int_t nboard = 0;
589 0 : for ( Int_t cath = AliMp::kCath0; cath <= AliMp::kCath1; ++cath )
590 : {
591 : const AliMpVSegmentation* seg
592 0 : = AliMpSegmentation::Instance()
593 0 : ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cath));
594 :
595 0 : AliMpPad pad = seg->PadByPosition(xLoc,yLoc,kFALSE);
596 0 : Int_t ix = pad.GetIx();
597 0 : Int_t iy = pad.GetIy();
598 :
599 0 : if ( !pad.IsValid() ) continue;
600 :
601 0 : if ( cath == AliMp::kCath0 ) nboard = pad.GetLocalBoardId(0);
602 :
603 0 : AliMUONVDigit* digit = digitStore.Add(detElemId, nboard, pad.GetLocalBoardChannel(0),
604 : cath, AliMUONVDigitStore::kDeny);
605 0 : if (digit) {
606 0 : digit->SetPadXY(ix,iy);
607 0 : digit->SetCharge(1.);
608 : }
609 0 : }
610 0 : }
611 :
612 0 : if ( hitsOnTrigger == 0 ) {
613 0 : pZ = trackReference->Pz();
614 0 : slopeX = ( pZ == 0. ) ? 99999. : trackReference->Px() / pZ;
615 0 : slopeY = ( pZ == 0. ) ? 99999. : trackReference->Py() / pZ;
616 :
617 0 : track.SetX11(x);
618 0 : track.SetY11(y);
619 0 : track.SetZ11(z);
620 0 : track.SetSlopeX(slopeX);
621 0 : track.SetSlopeY(slopeY);
622 0 : }
623 :
624 0 : if ( currCh != chamberId ) {
625 0 : hitsOnTrigger++;
626 : currCh = chamberId;
627 0 : }
628 :
629 0 : } // loop on hits
630 :
631 0 : if ( hitsOnTrigger < 3 ) continue;
632 :
633 : // Check if the track passes the trigger algorithm
634 0 : if ( InitTriggerResponse() ) {
635 0 : AliMUONTriggerStoreV1 triggerStore;
636 0 : fTriggerElectronics->Digits2Trigger(digitStore,triggerStore);
637 :
638 0 : TIter next(triggerStore.CreateIterator());
639 : AliMUONLocalTrigger* locTrg(0x0);
640 :
641 : Int_t ptCutLevel = 0;
642 :
643 0 : while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(next()) ) )
644 : {
645 0 : if ( locTrg->IsTrigX() && locTrg->IsTrigY() )
646 : {
647 0 : ptCutLevel = TMath::Max(ptCutLevel, 1);
648 0 : if ( locTrg->LoHpt() ) ptCutLevel = TMath::Max(ptCutLevel, 3);
649 0 : else if ( locTrg->LoLpt() ) ptCutLevel = TMath::Max(ptCutLevel, 2);
650 : } // board is fired
651 : } // end of loop on Local Trigger
652 0 : track.SetPtCutLevel(ptCutLevel);
653 0 : }
654 0 : track.SetUniqueID(iTrackRef);
655 0 : fRecoTriggerRefStore->Add(track);
656 0 : }
657 0 : }
658 :
659 :
660 : //_____________________________________________________________________________
661 : void AliMUONRecoCheck::CleanMuonTrackRef(const AliMUONVTrackStore *tmpTrackRefStore)
662 : {
663 : /// Re-calculate hits parameters because two AliTrackReferences are recorded for
664 : /// each chamber (one when particle is entering + one when particle is leaving
665 : /// the sensitive volume)
666 0 : if (!(fTrackRefStore = AliMUONESDInterface::NewTrackStore())) return;
667 :
668 : Double_t maxGasGap = 1.; // cm
669 : Double_t x, y, z, pX, pY, pZ, x1, y1, z1, pX1, pY1, pZ1, z2;
670 : Double_t bendingSlope,nonBendingSlope,inverseBendingMomentum;
671 0 : AliMUONVCluster* hit = AliMUONESDInterface::NewCluster();
672 :
673 : // create iterator
674 0 : TIter next(tmpTrackRefStore->CreateIterator());
675 :
676 : // loop over tmpTrackRef
677 : AliMUONTrack* track;
678 0 : while ( ( track = static_cast<AliMUONTrack*>(next()) ) ) {
679 :
680 0 : AliMUONTrack newTrack;
681 :
682 : // loop over tmpTrackRef's hits
683 : Int_t iHit1 = 0;
684 0 : Int_t nTrackHits = track->GetNClusters();
685 0 : while (iHit1 < nTrackHits) {
686 0 : AliMUONTrackParam *trackParam1 = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->UncheckedAt(iHit1);
687 :
688 : // get track parameters at hit1
689 0 : x1 = trackParam1->GetNonBendingCoor();
690 0 : y1 = trackParam1->GetBendingCoor();
691 0 : z1 = trackParam1->GetZ();
692 0 : pX1 = trackParam1->Px();
693 0 : pY1 = trackParam1->Py();
694 0 : pZ1 = trackParam1->Pz();
695 :
696 : // prepare new track parameters
697 : x = x1;
698 : y = y1;
699 : z = z1;
700 : pX = pX1;
701 : pY = pY1;
702 : pZ = pZ1;
703 :
704 : // loop over next tmpTrackRef's hits
705 : Int_t nCombinedHits = 1;
706 0 : for (Int_t iHit2 = iHit1+1; iHit2 < nTrackHits; iHit2++) {
707 0 : AliMUONTrackParam *trackParam2 = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->UncheckedAt(iHit2);
708 :
709 : // get z position of hit2
710 0 : z2 = trackParam2->GetZ();
711 :
712 : // complete new track parameters if hit2 is on the same detection element
713 0 : if ( TMath::Abs(z2-z1) < maxGasGap ) {
714 0 : x += trackParam2->GetNonBendingCoor();
715 0 : y += trackParam2->GetBendingCoor();
716 0 : z += z2;
717 0 : pX += trackParam2->Px();
718 0 : pY += trackParam2->Py();
719 0 : pZ += trackParam2->Pz();
720 0 : nCombinedHits++;
721 : iHit1 = iHit2;
722 0 : }
723 :
724 : }
725 :
726 : // finalize new track parameters
727 0 : x /= (Double_t)nCombinedHits;
728 0 : y /= (Double_t)nCombinedHits;
729 0 : z /= (Double_t)nCombinedHits;
730 0 : pX /= (Double_t)nCombinedHits;
731 0 : pY /= (Double_t)nCombinedHits;
732 0 : pZ /= (Double_t)nCombinedHits;
733 : bendingSlope = 0;
734 : nonBendingSlope = 0;
735 : inverseBendingMomentum = 0;
736 0 : if (TMath::Abs(pZ) > 0) {
737 0 : bendingSlope = pY/pZ;
738 0 : nonBendingSlope = pX/pZ;
739 0 : }
740 0 : Double_t pYZ = TMath::Sqrt(pY*pY+pZ*pZ);
741 0 : if (pYZ >0) inverseBendingMomentum = 1/pYZ;
742 0 : inverseBendingMomentum *= trackParam1->GetCharge();
743 :
744 : // set hit parameters
745 0 : hit->SetUniqueID(trackParam1->GetClusterPtr()->GetUniqueID());
746 0 : hit->SetXYZ(x,y,z);
747 0 : hit->SetErrXY(0.,0.);
748 :
749 : // set new track parameters at new hit
750 0 : AliMUONTrackParam trackParam;
751 0 : trackParam.SetNonBendingCoor(x);
752 0 : trackParam.SetBendingCoor(y);
753 0 : trackParam.SetZ(z);
754 0 : trackParam.SetBendingSlope(bendingSlope);
755 0 : trackParam.SetNonBendingSlope(nonBendingSlope);
756 0 : trackParam.SetInverseBendingMomentum(inverseBendingMomentum);
757 :
758 : // add track parameters at current hit to the track
759 0 : newTrack.AddTrackParamAtCluster(trackParam, *hit, kTRUE);
760 :
761 0 : iHit1++;
762 0 : }
763 :
764 0 : newTrack.SetUniqueID(track->GetUniqueID());
765 0 : newTrack.SetTrackParamAtVertex(track->GetTrackParamAtVertex());
766 0 : fTrackRefStore->Add(newTrack);
767 :
768 0 : }
769 :
770 0 : delete hit;
771 0 : }
772 :
773 : //_____________________________________________________________________________
774 : void AliMUONRecoCheck::MakeReconstructibleTracks(UInt_t requestedStationMask, Bool_t request2ChInSameSt45,
775 : Bool_t hitInFrontOfPad)
776 : {
777 : /// Isolate the reconstructible tracks
778 0 : if (!(fRecoTrackRefStore = AliMUONESDInterface::NewTrackStore())) return;
779 :
780 : // need geometry transformer and segmentation to check if trackrefs are located in front of pad(s)
781 0 : if (hitInFrontOfPad) {
782 0 : if (!InitGeometryTransformer()) return;
783 0 : if (!AliMpSegmentation::Instance(kFALSE) && !AliMUONCDB::LoadMapping(kTRUE)) return;
784 : }
785 :
786 : // create iterator on trackRef
787 0 : TIter next(fTrackRefStore->CreateIterator());
788 :
789 : // loop over trackRef and add reconstructible tracks to fRecoTrackRefStore
790 : AliMUONTrack* track;
791 0 : while ( ( track = static_cast<AliMUONTrack*>(next()) ) ) {
792 :
793 : // check if the track is valid as it is
794 0 : if (track->IsValid(requestedStationMask, request2ChInSameSt45)) {
795 :
796 0 : if (hitInFrontOfPad) {
797 :
798 0 : AliMUONTrack trackTmp(*track);
799 :
800 : // loop over clusters and remove those which are not in front of pad(s)
801 0 : AliMUONTrackParam *param = static_cast<AliMUONTrackParam*>(trackTmp.GetTrackParamAtCluster()->First());
802 0 : while (param) {
803 0 : AliMUONTrackParam *nextParam = static_cast<AliMUONTrackParam*>(trackTmp.GetTrackParamAtCluster()->After(param));
804 0 : if (!IsHitInFrontOfPad(param)) trackTmp.RemoveTrackParamAtCluster(param);
805 : param = nextParam;
806 : }
807 :
808 : // add the track if it is still valid
809 0 : if (trackTmp.IsValid(requestedStationMask, request2ChInSameSt45)) fRecoTrackRefStore->Add(trackTmp);
810 :
811 0 : } else {
812 :
813 : // add the track
814 0 : fRecoTrackRefStore->Add(*track);
815 :
816 : }
817 :
818 : }
819 :
820 : }
821 :
822 0 : }
823 :
824 : //_____________________________________________________________________________
825 : AliMUONTrack* AliMUONRecoCheck::FindCompatibleTrack(AliMUONTrack &track, AliMUONVTrackStore &trackStore,
826 : Int_t &nMatchClusters, Bool_t useLabel, Double_t sigmaCut)
827 : {
828 : /// Return the track from the store matched with the given track (or 0x0) and the number of matched clusters.
829 : /// Matching is done by using the MC label of by comparing cluster/TrackRef positions according to the flag "useLabel".
830 : /// WARNING: Who match who matters since the matching algorithm uses the *fraction* of matched clusters of the given track
831 :
832 : AliMUONTrack *matchedTrack = 0x0;
833 0 : nMatchClusters = 0;
834 :
835 0 : if (useLabel) { // by using the MC label
836 :
837 : // get the corresponding simulated track if any
838 0 : Int_t label = track.GetMCLabel();
839 0 : matchedTrack = (AliMUONTrack*) trackStore.FindObject(label);
840 :
841 : // get the fraction of matched clusters
842 0 : if (matchedTrack) {
843 0 : Int_t nClusters = track.GetNClusters();
844 0 : for (Int_t iCl = 0; iCl < nClusters; iCl++)
845 0 : if (((AliMUONTrackParam*) track.GetTrackParamAtCluster()->UncheckedAt(iCl))->GetClusterPtr()->GetMCLabel() == label)
846 0 : nMatchClusters++;
847 0 : }
848 :
849 0 : } else { // by comparing cluster/TrackRef positions
850 :
851 : // look for the corresponding simulated track if any
852 0 : TIter next(trackStore.CreateIterator());
853 : AliMUONTrack* track2;
854 0 : while ( ( track2 = static_cast<AliMUONTrack*>(next()) ) ) {
855 :
856 : // check compatibility
857 0 : Int_t n = 0;
858 0 : if (track.Match(*track2, sigmaCut, n)) {
859 : matchedTrack = track2;
860 0 : nMatchClusters = n;
861 0 : break;
862 : }
863 :
864 0 : }
865 :
866 0 : }
867 :
868 0 : return matchedTrack;
869 :
870 0 : }
871 :
872 :
873 : //_____________________________________________________________________________
874 : AliMUONTriggerTrack* AliMUONRecoCheck::FindCompatibleTrack(AliMUONTriggerTrack &track, const AliMUONVTriggerTrackStore &triggerTrackStore,
875 : Double_t sigmaCut)
876 : {
877 : /// Return the trigger track from the store matched with the given track (or 0x0).
878 : /// Matching is done by comparing cluster/TrackRef positions.
879 :
880 : AliMUONTriggerTrack *matchedTrack = 0x0;
881 :
882 : // look for the corresponding simulated track if any
883 0 : TIter next(triggerTrackStore.CreateIterator());
884 : AliMUONTriggerTrack* track2;
885 0 : while ( ( track2 = static_cast<AliMUONTriggerTrack*>(next()) ) ) {
886 : // check compatibility
887 0 : if (track.Match(*track2, sigmaCut)) {
888 : matchedTrack = track2;
889 0 : break;
890 : }
891 : }
892 :
893 : return matchedTrack;
894 :
895 0 : }
896 :
897 :
898 : //____________________________________________________________________________
899 : Bool_t AliMUONRecoCheck::InitTriggerResponse()
900 : {
901 : /// Initialize trigger electronics
902 : /// for building of triggerable tracks from MC
903 :
904 0 : if ( fTriggerElectronics ) return kTRUE;
905 :
906 0 : if ( ! InitGeometryTransformer() ) return kFALSE;
907 :
908 0 : if ( ! AliMpDDLStore::Instance(false) && ! AliMpCDB::LoadDDLStore()) return kFALSE;
909 :
910 0 : if ( ! InitCalibrationData() ) return kFALSE;
911 :
912 0 : fTriggerElectronics = new AliMUONTriggerElectronics(fCalibrationData);
913 :
914 0 : return kTRUE;
915 0 : }
916 :
917 :
918 : //____________________________________________________________________________
919 : Bool_t AliMUONRecoCheck::InitCalibrationData()
920 : {
921 : /// Initialize calibration data
922 0 : if ( ! fCalibrationData ) {
923 0 : if ( !AliMUONCDB::CheckOCDB() ) return kFALSE;
924 0 : fCalibrationData = new AliMUONCalibrationData(AliCDBManager::Instance()->GetRun());
925 0 : }
926 0 : return kTRUE;
927 0 : }
928 :
929 :
930 : //____________________________________________________________________________
931 : Bool_t AliMUONRecoCheck::InitGeometryTransformer()
932 : {
933 : /// Return geometry transformer
934 : /// (create it if necessary)
935 0 : if ( ! fGeometryTransformer ) {
936 :
937 0 : if ( !AliMUONCDB::CheckOCDB() ) return kFALSE;
938 :
939 0 : if (!AliGeomManager::GetGeometry()) {
940 0 : AliGeomManager::LoadGeometry();
941 0 : if (!AliGeomManager::GetGeometry()) return kFALSE;
942 0 : if (!AliGeomManager::ApplyAlignObjsFromCDB("MUON")) return kFALSE;
943 : }
944 :
945 0 : fGeometryTransformer = new AliMUONGeometryTransformer();
946 0 : fGeometryTransformer->LoadGeometryData();
947 0 : }
948 :
949 0 : return kTRUE;
950 0 : }
951 :
952 : //________________________________________________________________________
953 : Bool_t AliMUONRecoCheck::IsHitInFrontOfPad(AliMUONTrackParam *param) const
954 : {
955 : /// Return kTRUE if the hit is located in front of at least 1 pad
956 :
957 0 : Int_t deId = param->GetClusterPtr()->GetDetElemId();
958 :
959 0 : Double_t xL, yL, zL;
960 0 : fGeometryTransformer->Global2Local(deId, param->GetNonBendingCoor(), param->GetBendingCoor(), param->GetZ(), xL, yL, zL);
961 :
962 0 : const AliMpVSegmentation* seg1 = AliMpSegmentation::Instance()->GetMpSegmentation(deId, AliMp::kCath0);
963 0 : const AliMpVSegmentation* seg2 = AliMpSegmentation::Instance()->GetMpSegmentation(deId, AliMp::kCath1);
964 0 : if (!seg1 || !seg2) return kFALSE;
965 :
966 0 : AliMpPad pad1 = seg1->PadByPosition(xL, yL, kFALSE);
967 0 : AliMpPad pad2 = seg2->PadByPosition(xL, yL, kFALSE);
968 :
969 0 : return (pad1.IsValid() || pad2.IsValid());
970 0 : }
971 :
|