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