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