]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONEventReconstructor.cxx
Unique material names (R.Grosso)
[u/mrichter/AliRoot.git] / MUON / AliMUONEventReconstructor.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 //
20 // MUON event reconstructor in ALICE
21 //
22 // This class contains as data:
23 // * the parameters for the event reconstruction
24 // * a pointer to the array of hits to be reconstructed (the event)
25 // * a pointer to the array of segments made with these hits inside each station
26 // * a pointer to the array of reconstructed tracks
27 //
28 // It contains as methods, among others:
29 // * MakeEventToBeReconstructed to build the array of hits to be reconstructed
30 // * MakeSegments to build the segments
31 // * MakeTracks to build the tracks
32 //
33 ////////////////////////////////////
34
35 #include <stdlib.h>
36 #include <Riostream.h>
37 #include <TDirectory.h>
38 #include <TFile.h>
39 #include <TMatrixD.h> //AZ
40
41 #include "AliMUONEventReconstructor.h"
42 #include "AliMUON.h"
43 #include "AliMUONConstants.h"
44 #include "AliMUONHitForRec.h"
45 #include "AliMUONTriggerTrack.h"
46 #include "AliMUONTriggerCircuit.h"
47 #include "AliMUONRawCluster.h"
48 #include "AliMUONLocalTrigger.h"
49 #include "AliMUONGlobalTrigger.h"
50 #include "AliMUONRecoEvent.h"
51 #include "AliMUONSegment.h"
52 #include "AliMUONTrack.h"
53 #include "AliMUONTrackHit.h"
54 #include "AliMagF.h"
55 #include "AliRun.h" // for gAlice
56 #include "AliRunLoader.h"
57 #include "AliLoader.h"
58 #include "AliMUONTrackK.h" //AZ
59 #include "AliMC.h"
60 #include "AliLog.h"
61 #include "AliTrackReference.h"
62
63 //************* Defaults parameters for reconstruction
64 const Double_t AliMUONEventReconstructor::fgkDefaultMinBendingMomentum = 3.0;
65 const Double_t AliMUONEventReconstructor::fgkDefaultMaxBendingMomentum = 2000.0;
66 const Double_t AliMUONEventReconstructor::fgkDefaultMaxChi2 = 100.0;
67 const Double_t AliMUONEventReconstructor::fgkDefaultMaxSigma2Distance = 16.0;
68 const Double_t AliMUONEventReconstructor::fgkDefaultBendingResolution = 0.01;
69 const Double_t AliMUONEventReconstructor::fgkDefaultNonBendingResolution = 0.144;
70 const Double_t AliMUONEventReconstructor::fgkDefaultChamberThicknessInX0 = 0.03;
71 // Simple magnetic field:
72 // Value taken from macro MUONtracking.C: 0.7 T, hence 7 kG
73 // Length and Position from reco_muon.F, with opposite sign:
74 // Length = ZMAGEND-ZCOIL
75 // Position = (ZMAGEND+ZCOIL)/2
76 // to be ajusted differently from real magnetic field ????
77 const Double_t AliMUONEventReconstructor::fgkDefaultSimpleBValue = 7.0;
78 const Double_t AliMUONEventReconstructor::fgkDefaultSimpleBLength = 428.0;
79 const Double_t AliMUONEventReconstructor::fgkDefaultSimpleBPosition = 1019.0;
80 const Int_t    AliMUONEventReconstructor::fgkDefaultRecTrackRefHits = 0;
81 const Double_t AliMUONEventReconstructor::fgkDefaultEfficiency = 0.95;
82
83 const Int_t    AliMUONEventReconstructor::fgkDefaultPrintLevel = -1;
84
85 ClassImp(AliMUONEventReconstructor) // Class implementation in ROOT context
86
87   //__________________________________________________________________________
88 AliMUONEventReconstructor::AliMUONEventReconstructor(AliLoader* loader)
89   : TObject()
90 {
91   // Constructor for class AliMUONEventReconstructor
92   SetReconstructionParametersToDefaults();
93   fTrackMethod = 1; //AZ - tracking method (1-default, 2-Kalman)
94   // Memory allocation for the TClonesArray of hits for reconstruction
95   // Is 10000 the right size ????
96   fHitsForRecPtr = new TClonesArray("AliMUONHitForRec", 10000);
97   fNHitsForRec = 0; // really needed or GetEntriesFast sufficient ????
98   // Memory allocation for the TClonesArray's of segments in stations
99   // Is 2000 the right size ????
100   for (Int_t st = 0; st < fgkMaxMuonTrackingStations; st++) {
101     fSegmentsPtr[st] = new TClonesArray("AliMUONSegment", 2000);
102     fNSegments[st] = 0; // really needed or GetEntriesFast sufficient ????
103   }
104   // Memory allocation for the TClonesArray of reconstructed tracks
105   // Is 10 the right size ????
106   fRecTracksPtr = new TClonesArray("AliMUONTrack", 10);
107   fNRecTracks = 0; // really needed or GetEntriesFast sufficient ????
108 // trigger tracks
109   fRecTriggerTracksPtr = new TClonesArray("AliMUONTriggerTrack", 10);
110   fNRecTriggerTracks = 0; // really needed or GetEntriesFast sufficient ????
111   // Memory allocation for the TClonesArray of hits on reconstructed tracks
112   // Is 100 the right size ????
113   //AZ fRecTrackHitsPtr = new TClonesArray("AliMUONTrack", 100);
114   fRecTrackHitsPtr = new TClonesArray("AliMUONTrackHit", 100);
115   fNRecTrackHits = 0; // really needed or GetEntriesFast sufficient ????
116
117   // Sign of fSimpleBValue according to sign of Bx value at (50,50,-950).
118   Float_t b[3], x[3];
119   x[0] = 50.; x[1] = 50.; x[2] = -950.;
120   gAlice->Field()->Field(x, b);
121   fSimpleBValue = TMath::Sign(fSimpleBValue,(Double_t) b[0]);
122   fSimpleBPosition = TMath::Sign(fSimpleBPosition,(Double_t) x[2]);
123   // See how to get fSimple(BValue, BLength, BPosition)
124   // automatically calculated from the actual magnetic field ????
125
126   if (fPrintLevel >= 0) {
127     cout << "AliMUONEventReconstructor constructed with defaults" << endl; Dump();
128     cout << endl << "Magnetic field from root file:" << endl;
129     gAlice->Field()->Dump();
130     cout << endl;
131   }
132   
133   // Initializions for track ref. background events
134   fBkgTrackRefFile = 0;
135   fBkgTrackRefTK = 0;
136   fBkgTrackRefParticles = 0;
137   fBkgTrackRefTTR = 0;
138   fBkgTrackRefEventNumber = -1;
139   
140   // Initialize to 0 pointers to RecoEvent, tree and tree file
141   fRecoEvent = 0;
142   fEventTree = 0;
143   fTreeFile  = 0;
144  
145   // initialize loader's
146   fLoader = loader;
147
148   // initialize container
149   fMUONData  = new AliMUONData(fLoader,"MUON","MUON");
150
151   return;
152 }
153   //__________________________________________________________________________
154 AliMUONEventReconstructor::AliMUONEventReconstructor (const AliMUONEventReconstructor& rhs)
155   : TObject(rhs)
156 {
157 // Protected copy constructor
158
159   AliFatal("Not implemented.");
160 }
161
162 AliMUONEventReconstructor & 
163 AliMUONEventReconstructor::operator=(const AliMUONEventReconstructor& rhs)
164 {
165 // Protected assignement operator
166
167   if (this == &rhs) return *this;
168
169   AliFatal("Not implemented.");
170     
171   return *this;  
172 }
173
174   //__________________________________________________________________________
175 AliMUONEventReconstructor::~AliMUONEventReconstructor(void)
176 {
177   // Destructor for class AliMUONEventReconstructor
178   if (fTreeFile) {
179      fTreeFile->Close();
180      delete fTreeFile;
181   }
182 //  if (fEventTree) delete fEventTree;
183   if (fRecoEvent) delete fRecoEvent;
184   delete fHitsForRecPtr; // Correct destruction of everything ???? or delete [] ????
185   for (Int_t st = 0; st < fgkMaxMuonTrackingStations; st++)
186     delete fSegmentsPtr[st]; // Correct destruction of everything ????
187   return;
188 }
189
190   //__________________________________________________________________________
191 void AliMUONEventReconstructor::SetReconstructionParametersToDefaults(void)
192 {
193   // Set reconstruction parameters to default values
194   // Would be much more convenient with a structure (or class) ????
195   fMinBendingMomentum = fgkDefaultMinBendingMomentum;
196   fMaxBendingMomentum = fgkDefaultMaxBendingMomentum;
197   fMaxChi2 = fgkDefaultMaxChi2;
198   fMaxSigma2Distance = fgkDefaultMaxSigma2Distance;
199
200   AliMUON *pMUON = (AliMUON*) gAlice->GetModule("MUON");
201   // ******** Parameters for making HitsForRec
202   // minimum radius,
203   // like in TRACKF_STAT:
204   // 2 degrees for stations 1 and 2, or ch(0...) from 0 to 3;
205   // 30 cm for stations 3 to 5, or ch(0...) from 4 to 9
206   for (Int_t ch = 0; ch < fgkMaxMuonTrackingChambers; ch++) {
207     if (ch < 4) fRMin[ch] = TMath::Abs((&(pMUON->Chamber(ch)))->Z()) *
208                   2.0 * TMath::Pi() / 180.0;
209     else fRMin[ch] = 30.0;
210     // maximum radius at 10 degrees and Z of chamber
211     fRMax[ch] = TMath::Abs((&(pMUON->Chamber(ch)))->Z()) *
212                   10.0 * TMath::Pi() / 180.0;
213   }
214
215   // ******** Parameters for making segments
216   // should be parametrized ????
217   // according to interval between chambers in a station ????
218   // Maximum distance in non bending plane
219   // 5 * 0.22 just to remember the way it was made in TRACKF_STAT
220   // SIGCUT*DYMAX(IZ)
221   for (Int_t st = 0; st < fgkMaxMuonTrackingStations; st++)
222     fSegmentMaxDistNonBending[st] = 5. * 0.22;
223   // Maximum distance in bending plane:
224   // values from TRACKF_STAT, corresponding to (J psi 20cm),
225   // scaled to the real distance between chambers in a station
226   fSegmentMaxDistBending[0] = TMath::Abs( 1.5 *
227     ((&(pMUON->Chamber(1)))->Z() - (&(pMUON->Chamber(0)))->Z()) / 20.0);
228   fSegmentMaxDistBending[1] = TMath::Abs( 1.5 *
229     ((&(pMUON->Chamber(3)))->Z() - (&(pMUON->Chamber(2)))->Z()) / 20.0);
230   fSegmentMaxDistBending[2] = TMath::Abs( 3.0 *
231     ((&(pMUON->Chamber(5)))->Z() - (&(pMUON->Chamber(4)))->Z()) / 20.0);
232   fSegmentMaxDistBending[3] = TMath::Abs( 6.0 *
233     ((&(pMUON->Chamber(7)))->Z() - (&(pMUON->Chamber(6)))->Z()) / 20.0);
234   fSegmentMaxDistBending[4] = TMath::Abs( 6.0 *
235     ((&(pMUON->Chamber(9)))->Z() - (&(pMUON->Chamber(8)))->Z()) / 20.0);
236   
237   fBendingResolution = fgkDefaultBendingResolution;
238   fNonBendingResolution = fgkDefaultNonBendingResolution;
239   fChamberThicknessInX0 = fgkDefaultChamberThicknessInX0;
240   fSimpleBValue = fgkDefaultSimpleBValue;
241   fSimpleBLength = fgkDefaultSimpleBLength;
242   fSimpleBPosition = fgkDefaultSimpleBPosition;
243   fRecTrackRefHits = fgkDefaultRecTrackRefHits;
244   fEfficiency = fgkDefaultEfficiency;
245   fPrintLevel = fgkDefaultPrintLevel;
246   return;
247 }
248
249 //__________________________________________________________________________
250 Double_t AliMUONEventReconstructor::GetImpactParamFromBendingMomentum(Double_t BendingMomentum) const
251 {
252   // Returns impact parameter at vertex in bending plane (cm),
253   // from the signed bending momentum "BendingMomentum" in bending plane (GeV/c),
254   // using simple values for dipole magnetic field.
255   // The sign of "BendingMomentum" is the sign of the charge.
256   return (-0.0003 * fSimpleBValue * fSimpleBLength * fSimpleBPosition /
257           BendingMomentum);
258 }
259
260 //__________________________________________________________________________
261 Double_t AliMUONEventReconstructor::GetBendingMomentumFromImpactParam(Double_t ImpactParam) const
262 {
263   // Returns signed bending momentum in bending plane (GeV/c),
264   // the sign being the sign of the charge for particles moving forward in Z,
265   // from the impact parameter "ImpactParam" at vertex in bending plane (cm),
266   // using simple values for dipole magnetic field.
267   return (-0.0003 * fSimpleBValue * fSimpleBLength * fSimpleBPosition /
268           ImpactParam);
269 }
270
271 //__________________________________________________________________________
272 void AliMUONEventReconstructor::SetBkgTrackRefFile(Text_t *BkgTrackRefFileName)
273 {
274   // Set background file ... for track ref. hits
275   // Must be called after having loaded the firts signal event
276   if (fPrintLevel >= 0) {
277     cout << "Enter SetBkgTrackRefFile with BkgTrackRefFileName ``"
278          << BkgTrackRefFileName << "''" << endl;}
279   if (strlen(BkgTrackRefFileName)) {
280     // BkgTrackRefFileName not empty: try to open the file
281     if (fPrintLevel >= 2) {cout << "Before File(Bkg)" << endl; gDirectory->Dump();}
282     fBkgTrackRefFile = new TFile(BkgTrackRefFileName);
283     if (fPrintLevel >= 2) {cout << "After File(Bkg)" << endl; gDirectory->Dump();}
284     if (fBkgTrackRefFile-> IsOpen()) {
285       if (fPrintLevel >= 0) {
286         cout << "Background for Track ref. hits in file: ``" << BkgTrackRefFileName
287              << "'' successfully opened" << endl;}
288     }
289     else {
290       cout << "Background for Track Ref. hits in file: " << BkgTrackRefFileName << endl;
291       cout << "NOT FOUND: EXIT" << endl;
292       exit(0); // right instruction for exit ????
293     }
294     // Arrays for "particles" and "hits"
295     fBkgTrackRefParticles = new TClonesArray("TParticle", 200);
296     // Event number to -1 for initialization
297     fBkgTrackRefEventNumber = -1;
298     // Back to the signal file:
299     // first signal event must have been loaded previously,
300     // otherwise, Segmentation violation at the next instruction
301     // How is it possible to do smething better ????
302     ((gAlice->TreeK())->GetCurrentFile())->cd();
303     if (fPrintLevel >= 2) {cout << "After cd(gAlice)" << endl; gDirectory->Dump();}
304   }
305   return;
306 }
307
308 //__________________________________________________________________________
309 void AliMUONEventReconstructor::NextBkgTrackRefEvent(void)
310 {
311   // Get next event in background file for track ref. hits
312   // Goes back to event number 0 when end of file is reached
313   char treeName[20];
314   if (fPrintLevel >= 0) {
315     cout << "Enter NextBkgTrackRefEvent" << endl;}
316   // Clean previous event
317   if(fBkgTrackRefTK) delete fBkgTrackRefTK;
318   fBkgTrackRefTK = NULL;
319   if(fBkgTrackRefParticles) fBkgTrackRefParticles->Clear();
320   if(fBkgTrackRefTTR) delete fBkgTrackRefTTR;
321   fBkgTrackRefTTR = NULL;
322   // Increment event number
323   fBkgTrackRefEventNumber++;
324   // Get access to Particles and Hits for event from background file
325   if (fPrintLevel >= 2) {cout << "Before cd(Bkg)" << endl; gDirectory->Dump();}
326   fBkgTrackRefFile->cd();
327   if (fPrintLevel >= 2) {cout << "After cd(Bkg)" << endl; gDirectory->Dump();}
328   // Particles: TreeK for event and branch "Particles"
329   sprintf(treeName, "TreeK%d", fBkgTrackRefEventNumber);
330   fBkgTrackRefTK = (TTree*)gDirectory->Get(treeName);
331   if (!fBkgTrackRefTK) {
332     if (fPrintLevel >= 0) {
333       cout << "Cannot find Kine Tree for background event: " <<
334         fBkgTrackRefEventNumber << endl;
335       cout << "Goes back to event 0" << endl;
336     }
337     fBkgTrackRefEventNumber = 0;
338     sprintf(treeName, "TreeK%d", fBkgTrackRefEventNumber);
339     fBkgTrackRefTK = (TTree*)gDirectory->Get(treeName);
340     if (!fBkgTrackRefTK) {
341                 AliError(Form("cannot find Kine Tree for background event: %d",fBkgTrackRefEventNumber));
342         exit(0);
343     }
344   }
345   if (fBkgTrackRefTK) 
346     fBkgTrackRefTK->SetBranchAddress("Particles", &fBkgTrackRefParticles);
347   fBkgTrackRefTK->GetEvent(0); // why event 0 ???? necessary ????
348   // Hits: TreeH for event and branch "MUON"
349   sprintf(treeName, "TreeTR%d", fBkgTrackRefEventNumber);
350   fBkgTrackRefTTR = (TTree*)gDirectory->Get(treeName);
351   if (!fBkgTrackRefTTR) {
352           AliError(Form("cannot find Hits Tree for background event: %d",fBkgTrackRefEventNumber));
353       exit(0);
354   }
355   fBkgTrackRefTTR->GetEntries(); // necessary ????
356   // Back to the signal file
357   ((gAlice->TreeK())->GetCurrentFile())->cd();
358   if (fPrintLevel >= 2) {cout << "After cd(gAlice)" << endl; gDirectory->Dump();}
359   return;
360 }
361
362 //__________________________________________________________________________
363 void AliMUONEventReconstructor::EventReconstruct(void)
364 {
365   // To reconstruct one event
366   if (fPrintLevel >= 1) cout << "enter EventReconstruct" << endl;
367   MakeEventToBeReconstructed();
368   MakeSegments();
369   MakeTracks();
370   if (fMUONData->IsTriggerTrackBranchesInTree()) 
371     ValidateTracksWithTrigger(); 
372
373   // Add tracks to MUON data container 
374   for(Int_t i=0; i<GetNRecTracks(); i++) {
375     AliMUONTrack * track = (AliMUONTrack*) GetRecTracksPtr()->At(i);
376     fMUONData->AddRecTrack(*track);
377   }
378
379   return;
380 }
381
382 //__________________________________________________________________________
383 void AliMUONEventReconstructor::EventReconstructTrigger(void)
384 {
385   // To reconstruct one event
386   if (fPrintLevel >= 1) cout << "enter EventReconstructTrigger" << endl;
387   MakeTriggerTracks();  
388   return;
389 }
390
391   //__________________________________________________________________________
392 void AliMUONEventReconstructor::ResetHitsForRec(void)
393 {
394   // To reset the array and the number of HitsForRec,
395   // and also the number of HitsForRec
396   // and the index of the first HitForRec per chamber
397   if (fHitsForRecPtr) fHitsForRecPtr->Clear();
398   fNHitsForRec = 0;
399   for (Int_t ch = 0; ch < fgkMaxMuonTrackingChambers; ch++)
400     fNHitsForRecPerChamber[ch] = fIndexOfFirstHitForRecPerChamber[ch] = 0;
401   return;
402 }
403
404   //__________________________________________________________________________
405 void AliMUONEventReconstructor::ResetSegments(void)
406 {
407   // To reset the TClonesArray of segments and the number of Segments
408   // for all stations
409   for (Int_t st = 0; st < fgkMaxMuonTrackingStations; st++) {
410     if (fSegmentsPtr[st]) fSegmentsPtr[st]->Clear();
411     fNSegments[st] = 0;
412   }
413   return;
414 }
415
416   //__________________________________________________________________________
417 void AliMUONEventReconstructor::ResetTracks(void)
418 {
419   // To reset the TClonesArray of reconstructed tracks
420   if (fRecTracksPtr) fRecTracksPtr->Delete();
421   // Delete in order that the Track destructors are called,
422   // hence the space for the TClonesArray of pointers to TrackHit's is freed
423   fNRecTracks = 0;
424   return;
425 }
426
427   //__________________________________________________________________________
428 void AliMUONEventReconstructor::ResetTriggerTracks(void)
429 {
430   // To reset the TClonesArray of reconstructed trigger tracks
431     if (fRecTriggerTracksPtr) fRecTriggerTracksPtr->Delete();
432   // Delete in order that the Track destructors are called,
433   // hence the space for the TClonesArray of pointers to TrackHit's is freed
434     fNRecTriggerTracks = 0;
435   return;
436 }
437
438   //__________________________________________________________________________
439 void AliMUONEventReconstructor::ResetTrackHits(void)
440 {
441   // To reset the TClonesArray of hits on reconstructed tracks
442   if (fRecTrackHitsPtr) fRecTrackHitsPtr->Clear();
443   fNRecTrackHits = 0;
444   return;
445 }
446
447   //__________________________________________________________________________
448 void AliMUONEventReconstructor::MakeEventToBeReconstructed(void)
449 {
450   // To make the list of hits to be reconstructed,
451   // either from the track ref. hits or from the raw clusters
452   // according to the parameter set for the reconstructor
453 //   TString evfoldname = AliConfig::GetDefaultEventFolderName();//to be interfaced properly
454   
455 //   AliRunLoader* rl = AliRunLoader::GetRunLoader(evfoldname);
456 //   if (rl == 0x0)
457 //    {
458 //      Error("MakeEventToBeReconstructed",
459 //            "Can not find Run Loader in Event Folder named %s.",
460 //            evfoldname.Data());
461 //      return;
462 //    }
463 //   AliLoader* gime = rl->GetLoader("MUONLoader");
464 //   if (gime == 0x0)
465 //    {
466 //      Error("MakeEventToBeReconstructed","Can not get MUON Loader from Run Loader.");
467 //      return;
468 //    }
469   AliRunLoader *runLoader = fLoader->GetRunLoader();
470
471   if (fPrintLevel >= 1) cout << "enter MakeEventToBeReconstructed" << endl;
472   ResetHitsForRec();
473   if (fRecTrackRefHits == 1) {
474     // Reconstruction from track ref. hits
475     // Back to the signal file
476     TTree* treeTR = runLoader->TreeTR();
477     if (treeTR == 0x0)
478       {
479         Int_t retval = runLoader->LoadTrackRefs("READ");
480         if ( retval)
481           {
482             AliError("Error occured while loading hits.");
483             return;
484           }
485         treeTR = runLoader->TreeTR();
486         if (treeTR == 0x0)
487           {
488             AliError("Can not get TreeTR");
489             return;
490           }
491       }
492     
493     AddHitsForRecFromTrackRef(treeTR,1);
494     
495     // Background hits
496     AddHitsForRecFromTrackRef(fBkgTrackRefTTR,0);
497     // Sort HitsForRec in increasing order with respect to chamber number
498     SortHitsForRecWithIncreasingChamber();
499   }
500   else {
501     // Reconstruction from raw clusters
502     // AliMUON *MUON  = (AliMUON*) gAlice->GetModule("MUON"); // necessary ????
503     // Security on MUON ????
504     // TreeR assumed to be be "prepared" in calling function
505     // by "MUON->GetTreeR(nev)" ????
506     TTree *treeR = fLoader->TreeR();
507     fMUONData->SetTreeAddress("RC");
508     AddHitsForRecFromRawClusters(treeR);
509     // No sorting: it is done automatically in the previous function
510   }
511   if (fPrintLevel >= 10) {
512     cout << "end of MakeEventToBeReconstructed" << endl;
513     cout << "NHitsForRec: " << fNHitsForRec << endl;
514     for (Int_t ch = 0; ch < fgkMaxMuonTrackingChambers; ch++) {
515       cout << "chamber(0...): " << ch
516            << "  NHitsForRec: " << fNHitsForRecPerChamber[ch]
517            << "  index(first HitForRec): " << fIndexOfFirstHitForRecPerChamber[ch]
518            << endl;
519       for (Int_t hit = fIndexOfFirstHitForRecPerChamber[ch];
520            hit < fIndexOfFirstHitForRecPerChamber[ch] + fNHitsForRecPerChamber[ch];
521            hit++) {
522         cout << "HitForRec index(0...): " << hit << endl;
523         ((*fHitsForRecPtr)[hit])->Dump();
524       }
525     }
526   }
527   return;
528 }
529
530   //__________________________________________________________________________
531 void AliMUONEventReconstructor::AddHitsForRecFromTrackRef(TTree *TTR, Int_t signal)
532 {
533   // To add to the list of hits for reconstruction
534   // the signal hits from a track reference tree TreeTR.
535   TClonesArray *listOfTrackRefs = NULL;
536   AliTrackReference *trackRef;
537   
538   Int_t track = 0;
539   if (fPrintLevel >= 2)
540     cout << "enter AddHitsForRecFromTrackRef with TTR: " << TTR << endl;
541   if (TTR == NULL) return;
542   
543   listOfTrackRefs = CleanTrackRefs(TTR);
544
545   Int_t ntracks = listOfTrackRefs->GetEntriesFast();
546
547   if (fPrintLevel >= 2)
548     cout << "ntracks: " << ntracks << endl;
549
550   for (Int_t index = 0; index < ntracks; index++) {
551     trackRef = (AliTrackReference*) listOfTrackRefs->At(index);
552     track =  trackRef->GetTrack();
553     
554     NewHitForRecFromTrackRef(trackRef,track,signal);
555   } // end of track ref.
556   
557   listOfTrackRefs->Delete();
558   delete listOfTrackRefs;
559   return;
560 }
561
562
563   //__________________________________________________________________________
564 AliMUONHitForRec* AliMUONEventReconstructor::NewHitForRecFromTrackRef(AliTrackReference* Hit, Int_t TrackNumber, Int_t Signal)
565 {
566   // To make a new hit for reconstruction from a track ref. hit pointed to by "Hit",
567   // with  the track numbered "TrackNumber",
568   // either from signal ("Signal" = 1) or background ("Signal" = 0) event.
569   // Selects hits in tracking (not trigger) chambers.
570   // Takes into account the efficiency (fEfficiency)
571   // and the smearing from resolution (fBendingResolution and fNonBendingResolution).
572   // Adds a condition on the radius between RMin and RMax
573   // to better simulate the real chambers.
574   // Returns the pointer to the new hit for reconstruction,
575   // or NULL in case of inefficiency or non tracking chamber or bad radius.
576   // No condition on at most 20 cm from a muon from a resonance
577   // like in Fortran TRACKF_STAT.
578   AliMUONHitForRec* hitForRec;
579   Double_t bendCoor, nonBendCoor, radius;
580   Int_t chamber = AliMUONConstants::ChamberNumber(Hit->Z()); // chamber(0...)
581   if (chamber < 0) return NULL;
582   // only in tracking chambers (fChamber starts at 1)
583   if (chamber >= fgkMaxMuonTrackingChambers) return NULL;
584   // only if hit is efficient (keep track for checking ????)
585   if (gRandom->Rndm() > fEfficiency) return NULL;
586   // only if radius between RMin and RMax
587   bendCoor = Hit->Y();
588   nonBendCoor = Hit->X();
589   radius = TMath::Sqrt((bendCoor * bendCoor) + (nonBendCoor * nonBendCoor));
590   // This cut is not needed with a realistic chamber geometry !!!!
591 //   if ((radius < fRMin[chamber]) || (radius > fRMax[chamber])) return NULL;
592   // new AliMUONHitForRec from track ref. hit and increment number of AliMUONHitForRec's
593   hitForRec = new ((*fHitsForRecPtr)[fNHitsForRec]) AliMUONHitForRec(Hit);
594   fNHitsForRec++;
595   // add smearing from resolution
596   hitForRec->SetBendingCoor(bendCoor + gRandom->Gaus(0., fBendingResolution));
597   hitForRec->SetNonBendingCoor(nonBendCoor
598                                + gRandom->Gaus(0., fNonBendingResolution));
599 //   // !!!! without smearing
600 //   hitForRec->SetBendingCoor(bendCoor);
601 //   hitForRec->SetNonBendingCoor(nonBendCoor);
602   // more information into HitForRec
603   //  resolution: angular effect to be added here ????
604   hitForRec->SetBendingReso2(fBendingResolution * fBendingResolution);
605   hitForRec->SetNonBendingReso2(fNonBendingResolution * fNonBendingResolution);
606   //   track ref. info
607   hitForRec->SetTTRTrack(TrackNumber);
608   hitForRec->SetTrackRefSignal(Signal);
609   if (fPrintLevel >= 10) {
610     cout << "track: " << TrackNumber << endl;
611     Hit->Dump();
612     cout << "AliMUONHitForRec number (1...): " << fNHitsForRec << endl;
613     hitForRec->Dump();}
614   return hitForRec;
615 }
616   //__________________________________________________________________________
617 TClonesArray* AliMUONEventReconstructor::CleanTrackRefs(TTree *treeTR)
618 {
619   // Make hits from track ref..  
620   // Re-calculate hits parameters because two AliTrackReferences are recorded for
621   // each chamber (one when particle is entering + one when particle is leaving 
622   // the sensitive volume) 
623  
624   AliTrackReference *trackReference;
625   Float_t x1, y1, z1, pX1, pY1, pZ1;
626   Float_t x2, y2, z2, pX2, pY2, pZ2;
627   Int_t track1, track2;
628   Int_t nRec = 0;
629   Float_t maxGasGap = 1.; // cm 
630   Int_t iHit1 = 0;
631   Int_t iHitMin = 0;
632  
633   AliTrackReference *trackReferenceNew = new AliTrackReference();
634   
635   TClonesArray* trackRefs = new TClonesArray("AliTrackReference", 10);
636   TClonesArray* cleanTrackRefs = new TClonesArray("AliTrackReference", 10);
637
638   if (treeTR == NULL) return NULL;
639   TBranch* branch = treeTR->GetBranch("MUON");
640   if (branch == NULL) return NULL;
641   branch->SetAddress(&trackRefs);
642
643   Int_t nTrack = (Int_t)treeTR->GetEntries();
644   for (Int_t iTrack  = 0; iTrack < nTrack; iTrack++) {
645     treeTR->GetEntry(iTrack);
646     iHitMin = 0;
647     iHit1 = 0;
648     while (iHit1 < trackRefs->GetEntries()) {
649       trackReference = (AliTrackReference*)trackRefs->At(iHit1);
650       x1 = trackReference->X();
651       y1 = trackReference->Y();
652       z1 = trackReference->Z();
653       pX1 = trackReference->Px();
654       pY1 = trackReference->Py();
655       pZ1 = trackReference->Pz();
656       track1 = trackReference->GetTrack();
657       nRec = 1;
658       iHitMin = iHit1+1;
659       for (Int_t iHit2 = iHit1+1; iHit2 < trackRefs->GetEntries(); iHit2++) {
660         trackReference = (AliTrackReference*)trackRefs->At(iHit2);
661         x2 = trackReference->X();
662         y2 = trackReference->Y();
663         z2 = trackReference->Z();
664         pX2 = trackReference->Px();
665         pY2 = trackReference->Py();
666         pZ2 = trackReference->Pz();
667         track2 = trackReference->GetTrack();
668         if (track2 == track1 && TMath::Abs(z2-z1) < maxGasGap ) {
669           nRec++;
670           x1 += x2;
671           y1 += y2;
672           z1 += z2;                             
673           pX1 += pX2;
674           pY1 += pY2;
675           pZ1 += pZ2;
676           iHitMin = iHit2+1;
677         }
678         
679       } // for iHit2
680       x1 /= (Float_t)nRec;
681       y1 /= (Float_t)nRec;
682       z1 /= (Float_t)nRec;
683       pX1 /= (Float_t)nRec;
684       pY1 /= (Float_t)nRec;
685       pZ1 /= (Float_t)nRec;
686       trackReferenceNew->SetPosition(x1,y1,z1);
687       trackReferenceNew->SetMomentum(pX1,pY1,pZ1);
688       trackReferenceNew->SetTrack(track1);
689       {new ((*cleanTrackRefs)[cleanTrackRefs->GetEntriesFast()]) AliTrackReference(*trackReferenceNew);}       
690       iHit1 = iHitMin;
691     } // while iHit1
692   } // for track
693
694   trackRefs->Delete();
695   delete trackRefs;
696   delete trackReferenceNew;
697   return cleanTrackRefs;
698  
699 }
700   //__________________________________________________________________________
701 void AliMUONEventReconstructor::SortHitsForRecWithIncreasingChamber()
702 {
703   // Sort HitsForRec's in increasing order with respect to chamber number.
704   // Uses the function "Compare".
705   // Update the information for HitsForRec per chamber too.
706   Int_t ch, nhits, prevch;
707   fHitsForRecPtr->Sort();
708   for (ch = 0; ch < fgkMaxMuonTrackingChambers; ch++) {
709     fNHitsForRecPerChamber[ch] = 0;
710     fIndexOfFirstHitForRecPerChamber[ch] = 0;
711   }
712   prevch = 0; // previous chamber
713   nhits = 0; // number of hits in current chamber
714   // Loop over HitsForRec
715   for (Int_t hit = 0; hit < fNHitsForRec; hit++) {
716     // chamber number (0...)
717     ch = ((AliMUONHitForRec*)  ((*fHitsForRecPtr)[hit]))->GetChamberNumber();
718     // increment number of hits in current chamber
719     (fNHitsForRecPerChamber[ch])++;
720     // update index of first HitForRec in current chamber
721     // if chamber number different from previous one
722     if (ch != prevch) {
723       fIndexOfFirstHitForRecPerChamber[ch] = hit;
724       prevch = ch;
725     }
726   }
727   return;
728 }
729
730 //   //__________________________________________________________________________
731 // void AliMUONEventReconstructor::AddHitsForRecFromCathodeCorrelations(TTree* TC)
732 // {
733 //   // OLD VERSION WHEN ONE ONE WAS USING SO CALLED CATHODE CORRELATIONS
734 //   // To add to the list of hits for reconstruction
735 //   // the (cathode correlated) raw clusters
736 //   // No condition added, like in Fortran TRACKF_STAT,
737 //   // on the radius between RMin and RMax.
738 //   AliMUONHitForRec *hitForRec;
739 //   if (fPrintLevel >= 1) cout << "enter AddHitsForRecFromCathodeCorrelations" << endl;
740 //   AliMUON *MUON  = (AliMUON*) gAlice->GetModule("MUON"); // necessary ????
741 //   // Security on MUON ????
742 //   // Loop over tracking chambers
743 //   for (Int_t ch = 0; ch < fgkMaxMuonTrackingChambers; ch++) {
744 //     // number of HitsForRec to 0 for the chamber
745 //     fNHitsForRecPerChamber[ch] = 0;
746 //     // index of first HitForRec for the chamber
747 //     if (ch == 0) fIndexOfFirstHitForRecPerChamber[ch] = 0;
748 //     else fIndexOfFirstHitForRecPerChamber[ch] = fNHitsForRec;
749 //     TClonesArray *reconst_hits  = MUON->ReconstHitsAddress(ch);
750 //     MUON->ResetReconstHits();
751 //     TC->GetEvent();
752 //     Int_t ncor = (Int_t)reconst_hits->GetEntries();
753 //     // Loop over (cathode correlated) raw clusters
754 //     for (Int_t cor = 0; cor < ncor; cor++) {
755 //       AliMUONReconstHit * mCor = 
756 //      (AliMUONReconstHit*) reconst_hits->UncheckedAt(cor);
757 //       // new AliMUONHitForRec from (cathode correlated) raw cluster
758 //       // and increment number of AliMUONHitForRec's (total and in chamber)
759 //       hitForRec = new ((*fHitsForRecPtr)[fNHitsForRec]) AliMUONHitForRec(mCor);
760 //       fNHitsForRec++;
761 //       (fNHitsForRecPerChamber[ch])++;
762 //       // more information into HitForRec
763 //       hitForRec->SetChamberNumber(ch);
764 //       hitForRec->SetHitNumber(cor);
765 //       // Z coordinate of the chamber (cm) with sign opposite to TRACKREF sign
766 //       // could (should) be more exact from chamber geometry ???? 
767 //       hitForRec->SetZ(-(&(MUON->Chamber(ch)))->Z());
768 //       if (fPrintLevel >= 10) {
769 //      cout << "chamber (0...): " << ch <<
770 //        " cathcorrel (0...): " << cor << endl;
771 //      mCor->Dump();
772 //      cout << "AliMUONHitForRec number (1...): " << fNHitsForRec << endl;
773 //      hitForRec->Dump();}
774 //     } // end of cluster loop
775 //   } // end of chamber loop
776 //   return;
777 // }
778
779   //__________________________________________________________________________
780 void AliMUONEventReconstructor::AddHitsForRecFromRawClusters(TTree* TR)
781 {
782   // To add to the list of hits for reconstruction all the raw clusters
783   // No condition added, like in Fortran TRACKF_STAT,
784   // on the radius between RMin and RMax.
785   AliMUONHitForRec *hitForRec;
786   AliMUONRawCluster *clus;
787   Int_t iclus, nclus, nTRentries;
788   TClonesArray *rawclusters;
789   if (fPrintLevel >= 1) cout << "enter AddHitsForRecFromRawClusters" << endl;
790
791 //   TString evfoldname = AliConfig::GetDefaultEventFolderName();//to be interfaced properly
792 //   AliRunLoader* rl = AliRunLoader::GetRunLoader(evfoldname);
793 //   if (rl == 0x0)
794 //    {
795 //      Error("MakeEventToBeReconstructed",
796 //            "Can not find Run Loader in Event Folder named %s.",
797 //            evfoldname.Data());
798 //      return;
799 //    }
800 //   AliLoader* gime = rl->GetLoader("MUONLoader");
801 //   if (gime == 0x0)
802 //    {
803 //      Error("MakeEventToBeReconstructed","Can not get MUON Loader from Run Loader.");
804 //      return;
805 //    }
806 //    // Loading AliRun master
807 //   rl->LoadgAlice();
808 //   gAlice = rl->GetAliRun();
809
810   // Loading MUON subsystem
811   //  AliMUON * pMUON = (AliMUON *) gAlice->GetDetector("MUON");
812
813   nTRentries = Int_t(TR->GetEntries());
814   if (nTRentries != 1) {
815     AliError(Form("nTRentries = %d not equal to 1 ",nTRentries));
816     exit(0);
817   }
818   fLoader->TreeR()->GetEvent(0); // only one entry  
819
820   // Loop over tracking chambers
821   for (Int_t ch = 0; ch < fgkMaxMuonTrackingChambers; ch++) {
822     // number of HitsForRec to 0 for the chamber
823     fNHitsForRecPerChamber[ch] = 0;
824     // index of first HitForRec for the chamber
825     if (ch == 0) fIndexOfFirstHitForRecPerChamber[ch] = 0;
826     else fIndexOfFirstHitForRecPerChamber[ch] = fNHitsForRec;
827     rawclusters =fMUONData->RawClusters(ch);
828 //     pMUON->ResetRawClusters();
829 //     TR->GetEvent((Int_t) (TR->GetEntries()) - 1); // to be checked ????
830     nclus = (Int_t) (rawclusters->GetEntries());
831     // Loop over (cathode correlated) raw clusters
832     for (iclus = 0; iclus < nclus; iclus++) {
833       clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(iclus);
834       // new AliMUONHitForRec from raw cluster
835       // and increment number of AliMUONHitForRec's (total and in chamber)
836       hitForRec = new ((*fHitsForRecPtr)[fNHitsForRec]) AliMUONHitForRec(clus);
837       fNHitsForRec++;
838       (fNHitsForRecPerChamber[ch])++;
839       // more information into HitForRec
840       //  resolution: info should be already in raw cluster and taken from it ????
841       hitForRec->SetBendingReso2(fBendingResolution * fBendingResolution);
842       hitForRec->SetNonBendingReso2(fNonBendingResolution * fNonBendingResolution);
843       //  original raw cluster
844       hitForRec->SetChamberNumber(ch);
845       hitForRec->SetHitNumber(iclus);
846       // Z coordinate of the raw cluster (cm)
847       hitForRec->SetZ(clus->GetZ(0));
848       if (fPrintLevel >= 10) {
849         cout << "chamber (0...): " << ch <<
850           " raw cluster (0...): " << iclus << endl;
851         clus->Dump();
852         cout << "AliMUONHitForRec number (1...): " << fNHitsForRec << endl;
853         hitForRec->Dump();}
854     } // end of cluster loop
855   } // end of chamber loop
856   SortHitsForRecWithIncreasingChamber(); //AZ 
857   return;
858 }
859
860   //__________________________________________________________________________
861 void AliMUONEventReconstructor::MakeSegments(void)
862 {
863   // To make the list of segments in all stations,
864   // from the list of hits to be reconstructed
865   if (fPrintLevel >= 1) cout << "enter MakeSegments" << endl;
866   ResetSegments();
867   // Loop over stations
868   Int_t nb = (fTrackMethod == 2) ? 3 : 0; //AZ
869   //AZ for (Int_t st = 0; st < fgkMaxMuonTrackingStations; st++)
870   for (Int_t st = nb; st < fgkMaxMuonTrackingStations; st++) //AZ
871     MakeSegmentsPerStation(st); 
872   if (fPrintLevel >= 10) {
873     cout << "end of MakeSegments" << endl;
874     for (Int_t st = 0; st < fgkMaxMuonTrackingStations; st++) {
875       cout << "station(0...): " << st
876            << "  Segments: " << fNSegments[st]
877            << endl;
878       for (Int_t seg = 0;
879            seg < fNSegments[st];
880            seg++) {
881         cout << "Segment index(0...): " << seg << endl;
882         ((*fSegmentsPtr[st])[seg])->Dump();
883       }
884     }
885   }
886   return;
887 }
888
889   //__________________________________________________________________________
890 void AliMUONEventReconstructor::MakeSegmentsPerStation(Int_t Station)
891 {
892   // To make the list of segments in station number "Station" (0...)
893   // from the list of hits to be reconstructed.
894   // Updates "fNSegments"[Station].
895   // Segments in stations 4 and 5 are sorted
896   // according to increasing absolute value of "impact parameter"
897   AliMUONHitForRec *hit1Ptr, *hit2Ptr;
898   AliMUONSegment *segment;
899   Bool_t last2st;
900   Double_t bendingSlope, distBend, distNonBend, extBendCoor, extNonBendCoor,
901       impactParam = 0., maxImpactParam = 0., minImpactParam = 0.; // =0 to avoid compilation warnings.
902   if (fPrintLevel >= 1)
903     cout << "enter MakeSegmentsPerStation (0...) " << Station << endl;
904   // first and second chambers (0...) in the station
905   Int_t ch1 = 2 * Station;
906   Int_t ch2 = ch1 + 1;
907   // variable true for stations downstream of the dipole:
908   // Station(0..4) equal to 3 or 4
909   if ((Station == 3) || (Station == 4)) {
910     last2st = kTRUE;
911     // maximum impact parameter (cm) according to fMinBendingMomentum...
912     maxImpactParam =
913       TMath::Abs(GetImpactParamFromBendingMomentum(fMinBendingMomentum));
914     // minimum impact parameter (cm) according to fMaxBendingMomentum...
915     minImpactParam =
916       TMath::Abs(GetImpactParamFromBendingMomentum(fMaxBendingMomentum));
917   }
918   else last2st = kFALSE;
919   // extrapolation factor from Z of first chamber to Z of second chamber
920   // dZ to be changed to take into account fine structure of chambers ????
921   Double_t extrapFact;
922   // index for current segment
923   Int_t segmentIndex = 0;
924   // Loop over HitsForRec in the first chamber of the station
925   for (Int_t hit1 = fIndexOfFirstHitForRecPerChamber[ch1];
926        hit1 < fIndexOfFirstHitForRecPerChamber[ch1] + fNHitsForRecPerChamber[ch1];
927        hit1++) {
928     // pointer to the HitForRec
929     hit1Ptr = (AliMUONHitForRec*) ((*fHitsForRecPtr)[hit1]);
930     // extrapolation,
931     // on the straight line joining the HitForRec to the vertex (0,0,0),
932     // to the Z of the second chamber of the station
933     // Loop over HitsForRec in the second chamber of the station
934     for (Int_t hit2 = fIndexOfFirstHitForRecPerChamber[ch2];
935          hit2 < fIndexOfFirstHitForRecPerChamber[ch2] + fNHitsForRecPerChamber[ch2];
936          hit2++) {
937       // pointer to the HitForRec
938       hit2Ptr = (AliMUONHitForRec*) ((*fHitsForRecPtr)[hit2]);
939       // absolute values of distances, in bending and non bending planes,
940       // between the HitForRec in the second chamber
941       // and the previous extrapolation
942       extrapFact = hit2Ptr->GetZ()/ hit1Ptr->GetZ();
943       extBendCoor = extrapFact * hit1Ptr->GetBendingCoor();
944       extNonBendCoor = extrapFact * hit1Ptr->GetNonBendingCoor();
945       distBend = TMath::Abs(hit2Ptr->GetBendingCoor() - extBendCoor);
946       distNonBend = TMath::Abs(hit2Ptr->GetNonBendingCoor() - extNonBendCoor);
947       if (last2st) {
948         // bending slope
949         bendingSlope = (hit1Ptr->GetBendingCoor() - hit2Ptr->GetBendingCoor()) /
950           (hit1Ptr->GetZ() - hit2Ptr->GetZ());
951         // absolute value of impact parameter
952         impactParam =
953           TMath::Abs(hit1Ptr->GetBendingCoor() - hit1Ptr->GetZ() * bendingSlope);
954       }
955       // check for distances not too large,
956       // and impact parameter not too big if stations downstream of the dipole.
957       // Conditions "distBend" and "impactParam" correlated for these stations ????
958       if ((distBend < fSegmentMaxDistBending[Station]) &&
959           (distNonBend < fSegmentMaxDistNonBending[Station]) &&
960           (!last2st || (impactParam < maxImpactParam)) &&
961           (!last2st || (impactParam > minImpactParam))) {
962         // make new segment
963         segment = new ((*fSegmentsPtr[Station])[segmentIndex])
964           AliMUONSegment(hit1Ptr, hit2Ptr);
965         // update "link" to this segment from the hit in the first chamber
966         if (hit1Ptr->GetNSegments() == 0)
967           hit1Ptr->SetIndexOfFirstSegment(segmentIndex);
968         hit1Ptr->SetNSegments(hit1Ptr->GetNSegments() + 1);
969         if (fPrintLevel >= 10) {
970           cout << "segmentIndex(0...): " << segmentIndex
971                << "  distBend: " << distBend
972                << "  distNonBend: " << distNonBend
973                << endl;
974           segment->Dump();
975           cout << "HitForRec in first chamber" << endl;
976           hit1Ptr->Dump();
977           cout << "HitForRec in second chamber" << endl;
978           hit2Ptr->Dump();
979         };
980         // increment index for current segment
981         segmentIndex++;
982       }
983     } //for (Int_t hit2
984   } // for (Int_t hit1...
985   fNSegments[Station] = segmentIndex;
986   // Sorting according to "impact parameter" if station(1..5) 4 or 5,
987   // i.e. Station(0..4) 3 or 4, using the function "Compare".
988   // After this sorting, it is impossible to use
989   // the "fNSegments" and "fIndexOfFirstSegment"
990   // of the HitForRec in the first chamber to explore all segments formed with it.
991   // Is this sorting really needed ????
992   if ((Station == 3) || (Station == 4)) (fSegmentsPtr[Station])->Sort();
993   if (fPrintLevel >= 1) cout << "Station: " << Station << "  NSegments: "
994                              << fNSegments[Station] << endl;
995   return;
996 }
997
998   //__________________________________________________________________________
999 void AliMUONEventReconstructor::MakeTracks(void)
1000 {
1001   // To make the tracks,
1002   // from the list of segments and points in all stations
1003   if (fPrintLevel >= 1) cout << "enter MakeTracks" << endl;
1004   // The order may be important for the following Reset's
1005   ResetTracks();
1006   ResetTrackHits();
1007   if (fTrackMethod == 2) { //AZ - Kalman filter
1008     MakeTrackCandidatesK();
1009     if (fRecTracksPtr->GetEntriesFast() == 0) return;
1010     // Follow tracks in stations(1..) 3, 2 and 1
1011     FollowTracksK();
1012     // Remove double tracks
1013     RemoveDoubleTracksK();
1014     // Propagate tracks to the vertex thru absorber
1015     GoToVertex();
1016     // Fill AliMUONTrack data members
1017     FillMUONTrack();
1018   } else { 
1019     // Look for candidates from at least 3 aligned points in stations(1..) 4 and 5
1020     MakeTrackCandidates();
1021     // Follow tracks in stations(1..) 3, 2 and 1
1022     FollowTracks();
1023     // Remove double tracks
1024     RemoveDoubleTracks();
1025     UpdateTrackParamAtHit();
1026     UpdateHitForRecAtHit();
1027   }
1028   return;
1029 }
1030
1031   //__________________________________________________________________________
1032 void AliMUONEventReconstructor::ValidateTracksWithTrigger(void)
1033 {
1034   // Try to match track from tracking system with trigger track
1035   AliMUONTrack *track;
1036   TClonesArray *recTriggerTracks;
1037   
1038   fMUONData->ResetRecTriggerTracks();
1039   fMUONData->SetTreeAddress("RL");
1040   fMUONData->GetRecTriggerTracks();
1041   recTriggerTracks = fMUONData->RecTriggerTracks();
1042
1043   track = (AliMUONTrack*) fRecTracksPtr->First();
1044   while (track) {
1045     track->MatchTriggerTrack(recTriggerTracks);
1046     track = (AliMUONTrack*) fRecTracksPtr->After(track);
1047   }
1048
1049 }
1050
1051   //__________________________________________________________________________
1052 Bool_t AliMUONEventReconstructor::MakeTriggerTracks(void)
1053 {
1054     // To make the trigger tracks from Local Trigger
1055     if (fPrintLevel >= 1) cout << "enter MakeTriggerTracks" << endl;
1056     //    ResetTriggerTracks();
1057     
1058     Int_t nTRentries;
1059     Long_t gloTrigPat;
1060     TClonesArray *localTrigger;
1061     TClonesArray *globalTrigger;
1062     AliMUONLocalTrigger *locTrg;
1063     AliMUONGlobalTrigger *gloTrg;
1064     AliMUONTriggerCircuit *circuit;
1065     AliMUONTriggerTrack *recTriggerTrack = 0;
1066
1067     TTree* treeR = fLoader->TreeR();
1068     
1069     // Loading MUON subsystem
1070     AliMUON * pMUON = (AliMUON *) gAlice->GetDetector("MUON");
1071     
1072     nTRentries = Int_t(treeR->GetEntries());
1073      
1074     treeR->GetEvent(0); // only one entry  
1075
1076     if (!(fMUONData->IsTriggerBranchesInTree())) {
1077       AliWarning(Form("Trigger information is not avalaible, nTRentries = %d not equal to 1",nTRentries));
1078       return kFALSE;
1079     }
1080
1081     fMUONData->SetTreeAddress("TC");
1082     fMUONData->GetTrigger();
1083
1084     // global trigger for trigger pattern
1085     gloTrigPat = 0;
1086     globalTrigger = fMUONData->GlobalTrigger(); 
1087     gloTrg = (AliMUONGlobalTrigger*)globalTrigger->UncheckedAt(0);      
1088     if (gloTrg) {
1089       if (gloTrg->SinglePlusLpt())  gloTrigPat|= 0x1;
1090       if (gloTrg->SinglePlusHpt())  gloTrigPat|= 0x2;
1091       if (gloTrg->SinglePlusApt())  gloTrigPat|= 0x4;
1092       
1093       if (gloTrg->SingleMinusLpt()) gloTrigPat|= 0x8;
1094       if (gloTrg->SingleMinusHpt()) gloTrigPat|= 0x10;
1095       if (gloTrg->SingleMinusApt()) gloTrigPat|= 0x20;
1096       
1097       if (gloTrg->SingleUndefLpt()) gloTrigPat|= 0x40;
1098       if (gloTrg->SingleUndefHpt()) gloTrigPat|= 0x80;
1099       if (gloTrg->SingleUndefApt()) gloTrigPat|= 0x100;
1100       
1101       if (gloTrg->PairUnlikeLpt())  gloTrigPat|= 0x200;
1102       if (gloTrg->PairUnlikeHpt())  gloTrigPat|= 0x400;
1103       if (gloTrg->PairUnlikeApt())  gloTrigPat|= 0x800;
1104       
1105       if (gloTrg->PairLikeLpt())    gloTrigPat|= 0x1000;
1106       if (gloTrg->PairLikeHpt())    gloTrigPat|= 0x2000;
1107       if (gloTrg->PairLikeApt())    gloTrigPat|= 0x4000;
1108     }
1109
1110  
1111
1112     // local trigger for tracking 
1113     localTrigger = fMUONData->LocalTrigger();    
1114     Int_t nlocals = (Int_t) (localTrigger->GetEntries());
1115     Float_t z11 = ( &(pMUON->Chamber(10)) )->Z();
1116     Float_t z21 = ( &(pMUON->Chamber(12)) )->Z();
1117
1118     for (Int_t i=0; i<nlocals; i++) { // loop on Local Trigger
1119       locTrg = (AliMUONLocalTrigger*)localTrigger->UncheckedAt(i);      
1120       circuit = &(pMUON->TriggerCircuit(locTrg->LoCircuit()));
1121       Float_t y11 = circuit->GetY11Pos(locTrg->LoStripX()); 
1122       Int_t stripX21 = locTrg->LoStripX()+locTrg->LoDev()+1;
1123       Float_t y21 = circuit->GetY21Pos(stripX21);       
1124       Float_t x11 = circuit->GetX11Pos(locTrg->LoStripY());
1125       Float_t thetax = TMath::ATan2( x11 , z11 );
1126       Float_t thetay = TMath::ATan2( (y21-y11) , (z21-z11) );
1127
1128       recTriggerTrack = new AliMUONTriggerTrack(x11,y11,thetax,thetay,gloTrigPat,this);
1129       // since static statement does not work, set gloTrigPat for each track
1130
1131       //        fNRecTriggerTracks++;
1132       fMUONData->AddRecTriggerTrack(*recTriggerTrack);
1133     } // end of loop on Local Trigger
1134     return kTRUE;    
1135 }
1136
1137   //__________________________________________________________________________
1138 Int_t AliMUONEventReconstructor::MakeTrackCandidatesWithTwoSegments(AliMUONSegment *BegSegment)
1139 {
1140   // To make track candidates with two segments in stations(1..) 4 and 5,
1141   // the first segment being pointed to by "BegSegment".
1142   // Returns the number of such track candidates.
1143   Int_t endStation, iEndSegment, nbCan2Seg;
1144   AliMUONSegment *endSegment;
1145   AliMUONSegment *extrapSegment = NULL;
1146   AliMUONTrack *recTrack;
1147   Double_t mcsFactor;
1148   if (fPrintLevel >= 1) cout << "enter MakeTrackCandidatesWithTwoSegments" << endl;
1149   // Station for the end segment
1150   endStation = 7 - (BegSegment->GetHitForRec1())->GetChamberNumber() / 2;
1151   // multiple scattering factor corresponding to one chamber
1152   mcsFactor = 0.0136 /
1153     GetBendingMomentumFromImpactParam(BegSegment->GetBendingImpact());
1154   mcsFactor     = fChamberThicknessInX0 * mcsFactor * mcsFactor;
1155   // linear extrapolation to end station
1156   // number of candidates with 2 segments to 0
1157   nbCan2Seg = 0;
1158   // Loop over segments in the end station
1159   for (iEndSegment = 0; iEndSegment < fNSegments[endStation]; iEndSegment++) {
1160     // pointer to segment
1161     endSegment = (AliMUONSegment*) ((*fSegmentsPtr[endStation])[iEndSegment]);
1162     // test compatibility between current segment and "extrapSegment"
1163     // 4 because 4 quantities in chi2
1164     extrapSegment =
1165       BegSegment->CreateSegmentFromLinearExtrapToStation(endSegment->GetZ(), mcsFactor);
1166     if ((endSegment->
1167          NormalizedChi2WithSegment(extrapSegment,
1168                                    fMaxSigma2Distance)) <= 4.0) {
1169       // both segments compatible:
1170       // make track candidate from "begSegment" and "endSegment"
1171       if (fPrintLevel >= 2)
1172         cout << "TrackCandidate with Segment " << iEndSegment <<
1173           " in Station(0..) " << endStation << endl;
1174       // flag for both segments in one track:
1175       // to be done in track constructor ????
1176       BegSegment->SetInTrack(kTRUE);
1177       endSegment->SetInTrack(kTRUE);
1178       recTrack = new ((*fRecTracksPtr)[fNRecTracks])
1179         AliMUONTrack(BegSegment, endSegment, this);
1180       fNRecTracks++;
1181       if (fPrintLevel >= 10) recTrack->RecursiveDump();
1182       // increment number of track candidates with 2 segments
1183       nbCan2Seg++;
1184     }
1185     delete extrapSegment; // should not delete HitForRec's it points to !!!!
1186   } // for (iEndSegment = 0;...
1187   return nbCan2Seg;
1188 }
1189
1190   //__________________________________________________________________________
1191 Int_t AliMUONEventReconstructor::MakeTrackCandidatesWithOneSegmentAndOnePoint(AliMUONSegment *BegSegment)
1192 {
1193   // To make track candidates with one segment and one point
1194   // in stations(1..) 4 and 5,
1195   // the segment being pointed to by "BegSegment".
1196   Int_t ch, ch1, ch2, endStation, iHit, iHitMax, iHitMin, nbCan1Seg1Hit;
1197   AliMUONHitForRec *extrapHitForRec= NULL;
1198   AliMUONHitForRec *hit;
1199   AliMUONTrack *recTrack;
1200   Double_t mcsFactor;
1201   if (fPrintLevel >= 1)
1202     cout << "enter MakeTrackCandidatesWithOneSegmentAndOnePoint" << endl;
1203   // station for the end point
1204   endStation = 7 - (BegSegment->GetHitForRec1())->GetChamberNumber() / 2;
1205   // multiple scattering factor corresponding to one chamber
1206   mcsFactor = 0.0136 /
1207     GetBendingMomentumFromImpactParam(BegSegment->GetBendingImpact());
1208   mcsFactor     = fChamberThicknessInX0 * mcsFactor * mcsFactor;
1209   // first and second chambers(0..) in the end station
1210   ch1 = 2 * endStation;
1211   ch2 = ch1 + 1;
1212   // number of candidates to 0
1213   nbCan1Seg1Hit = 0;
1214   // Loop over chambers of the end station
1215   for (ch = ch2; ch >= ch1; ch--) {
1216     // limits for the hit index in the loop
1217     iHitMin = fIndexOfFirstHitForRecPerChamber[ch];
1218     iHitMax = iHitMin + fNHitsForRecPerChamber[ch];
1219     // Loop over HitForRec's in the chamber
1220     for (iHit = iHitMin; iHit < iHitMax; iHit++) {
1221       // pointer to HitForRec
1222       hit = (AliMUONHitForRec*) ((*fHitsForRecPtr)[iHit]);
1223       // test compatibility between current HitForRec and "extrapHitForRec"
1224       // 2 because 2 quantities in chi2
1225       // linear extrapolation to chamber
1226       extrapHitForRec =
1227         BegSegment->CreateHitForRecFromLinearExtrapToChamber( hit->GetZ(), mcsFactor);
1228       if ((hit->
1229            NormalizedChi2WithHitForRec(extrapHitForRec,
1230                                        fMaxSigma2Distance)) <= 2.0) {
1231         // both HitForRec's compatible:
1232         // make track candidate from begSegment and current HitForRec
1233         if (fPrintLevel >= 2)
1234           cout << "TrackCandidate with HitForRec " << iHit <<
1235             " in Chamber(0..) " << ch << endl;
1236         // flag for beginning segments in one track:
1237         // to be done in track constructor ????
1238         BegSegment->SetInTrack(kTRUE);
1239         recTrack = new ((*fRecTracksPtr)[fNRecTracks])
1240           AliMUONTrack(BegSegment, hit, this);
1241         // the right place to eliminate "double counting" ???? how ????
1242         fNRecTracks++;
1243         if (fPrintLevel >= 10) recTrack->RecursiveDump();
1244         // increment number of track candidates
1245         nbCan1Seg1Hit++;
1246       }
1247       delete extrapHitForRec;
1248     } // for (iHit = iHitMin;...
1249   } // for (ch = ch2;...
1250   return nbCan1Seg1Hit;
1251 }
1252
1253   //__________________________________________________________________________
1254 void AliMUONEventReconstructor::MakeTrackCandidates(void)
1255 {
1256   // To make track candidates
1257   // with at least 3 aligned points in stations(1..) 4 and 5
1258   // (two Segment's or one Segment and one HitForRec)
1259   Int_t begStation, iBegSegment, nbCan1Seg1Hit, nbCan2Seg;
1260   AliMUONSegment *begSegment;
1261   if (fPrintLevel >= 1) cout << "enter MakeTrackCandidates" << endl;
1262   // Loop over stations(1..) 5 and 4 for the beginning segment
1263   for (begStation = 4; begStation > 2; begStation--) {
1264     // Loop over segments in the beginning station
1265     for (iBegSegment = 0; iBegSegment < fNSegments[begStation]; iBegSegment++) {
1266       // pointer to segment
1267       begSegment = (AliMUONSegment*) ((*fSegmentsPtr[begStation])[iBegSegment]);
1268       if (fPrintLevel >= 2)
1269         cout << "look for TrackCandidate's with Segment " << iBegSegment <<
1270           " in Station(0..) " << begStation << endl;
1271       // Look for track candidates with two segments,
1272       // "begSegment" and all compatible segments in other station.
1273       // Only for beginning station(1..) 5
1274       // because candidates with 2 segments have to looked for only once.
1275       if (begStation == 4)
1276         nbCan2Seg = MakeTrackCandidatesWithTwoSegments(begSegment);
1277       // Look for track candidates with one segment and one point,
1278       // "begSegment" and all compatible HitForRec's in other station.
1279       // Only if "begSegment" does not belong already to a track candidate.
1280       // Is that a too strong condition ????
1281       if (!(begSegment->GetInTrack()))
1282         nbCan1Seg1Hit = MakeTrackCandidatesWithOneSegmentAndOnePoint(begSegment);
1283     } // for (iBegSegment = 0;...
1284   } // for (begStation = 4;...
1285   return;
1286 }
1287
1288   //__________________________________________________________________________
1289 void AliMUONEventReconstructor::FollowTracks(void)
1290 {
1291   // Follow tracks in stations(1..) 3, 2 and 1
1292   // too long: should be made more modular !!!!
1293   AliMUONHitForRec *bestHit, *extrapHit, *hit;
1294   AliMUONSegment *bestSegment, *extrapSegment, *segment;
1295   AliMUONTrack *track, *nextTrack;
1296   AliMUONTrackParam *trackParam1, trackParam[2], trackParamVertex;
1297   // -1 to avoid compilation warnings
1298   Int_t ch = -1, chInStation, chBestHit = -1, iHit, iSegment, station, trackIndex; 
1299   Double_t bestChi2, chi2, dZ1, dZ2, dZ3, maxSigma2Distance, mcsFactor;
1300   Double_t bendingMomentum, chi2Norm = 0.;
1301   AliMUON *pMUON = (AliMUON*) gAlice->GetModule("MUON"); // necessary ????
1302   // local maxSigma2Distance, for easy increase in testing
1303   maxSigma2Distance = fMaxSigma2Distance;
1304   if (fPrintLevel >= 2)
1305     cout << "enter FollowTracks" << endl;
1306   // Loop over track candidates
1307   track = (AliMUONTrack*) fRecTracksPtr->First();
1308   trackIndex = -1;
1309   while (track) {
1310     // Follow function for each track candidate ????
1311     trackIndex++;
1312     nextTrack = (AliMUONTrack*) fRecTracksPtr->After(track); // prepare next track
1313     if (fPrintLevel >= 2)
1314       cout << "FollowTracks: track candidate(0..): " << trackIndex << endl;
1315     // Fit track candidate
1316     track->SetFitMCS(0); // without multiple Coulomb scattering
1317     track->SetFitNParam(3); // with 3 parameters (X = Y = 0)
1318     track->SetFitStart(0); // from parameters at vertex
1319     track->Fit();
1320     if (fPrintLevel >= 10) {
1321       cout << "FollowTracks: track candidate(0..): " << trackIndex
1322            << " after fit in stations(0..) 3 and 4" << endl;
1323       track->RecursiveDump();
1324     }
1325     // Loop over stations(1..) 3, 2 and 1
1326     // something SPECIAL for stations 2 and 1 for majority 3 coincidence ????
1327     // otherwise: majority coincidence 2 !!!!
1328     for (station = 2; station >= 0; station--) {
1329       // Track parameters at first track hit (smallest Z)
1330       trackParam1 = ((AliMUONTrackHit*)
1331                      (track->GetTrackHitsPtr()->First()))->GetTrackParam();
1332       // extrapolation to station
1333       trackParam1->ExtrapToStation(station, trackParam);
1334       extrapSegment = new AliMUONSegment(); //  empty segment
1335       // multiple scattering factor corresponding to one chamber
1336       // and momentum in bending plane (not total)
1337       mcsFactor = 0.0136 * trackParam1->GetInverseBendingMomentum();
1338       mcsFactor = fChamberThicknessInX0 * mcsFactor * mcsFactor;
1339       // Z difference from previous station
1340       dZ1 = (&(pMUON->Chamber(2 * station)))->Z() -
1341         (&(pMUON->Chamber(2 * station + 2)))->Z();
1342       // Z difference between the two previous stations
1343       dZ2 = (&(pMUON->Chamber(2 * station + 2)))->Z() -
1344         (&(pMUON->Chamber(2 * station + 4)))->Z();
1345       // Z difference between the two chambers in the previous station
1346       dZ3 = (&(pMUON->Chamber(2 * station)))->Z() -
1347         (&(pMUON->Chamber(2 * station + 1)))->Z();
1348       extrapSegment->SetBendingCoorReso2(fBendingResolution * fBendingResolution);
1349       extrapSegment->
1350         SetNonBendingCoorReso2(fNonBendingResolution * fNonBendingResolution);
1351       extrapSegment->UpdateFromStationTrackParam
1352         (trackParam, mcsFactor, dZ1, dZ2, dZ3, station,
1353          trackParam1->GetInverseBendingMomentum());
1354       bestChi2 = 5.0;
1355       bestSegment = NULL;
1356       if (fPrintLevel >= 10) {
1357         cout << "FollowTracks: track candidate(0..): " << trackIndex
1358              << " Look for segment in station(0..): " << station << endl;
1359       }
1360       // Loop over segments in station
1361       for (iSegment = 0; iSegment < fNSegments[station]; iSegment++) {
1362         // Look for best compatible Segment in station
1363         // should consider all possibilities ????
1364         // multiple scattering ????
1365         // separation in 2 functions: Segment and HitForRec ????
1366         segment = (AliMUONSegment*) ((*fSegmentsPtr[station])[iSegment]);
1367         // correction of corrected segment (fBendingCoor and fNonBendingCoor)
1368         // according to real Z value of "segment" and slopes of "extrapSegment"
1369         (&(trackParam[0]))->ExtrapToZ(segment->GetZ());
1370         (&(trackParam[1]))->ExtrapToZ(segment->GetZ());
1371         extrapSegment->SetBendingCoor((&(trackParam[0]))->GetBendingCoor());
1372         extrapSegment->SetNonBendingCoor((&(trackParam[0]))->GetNonBendingCoor());
1373         extrapSegment->SetBendingSlope((&(trackParam[0]))->GetBendingSlope());
1374         extrapSegment->SetNonBendingSlope((&(trackParam[0]))->GetNonBendingSlope());
1375         chi2 = segment->
1376           NormalizedChi2WithSegment(extrapSegment, maxSigma2Distance);
1377         if (chi2 < bestChi2) {
1378           // update best Chi2 and Segment if better found
1379           bestSegment = segment;
1380           bestChi2 = chi2;
1381         }
1382       }
1383       if (bestSegment) {
1384         // best segment found: add it to track candidate
1385         (&(trackParam[0]))->ExtrapToZ(bestSegment->GetZ());
1386         (&(trackParam[1]))->ExtrapToZ(bestSegment->GetZ());
1387         track->AddSegment(bestSegment);
1388         // set track parameters at these two TrakHit's
1389         track->SetTrackParamAtHit(track->GetNTrackHits() - 2, &(trackParam[0]));
1390         track->SetTrackParamAtHit(track->GetNTrackHits() - 1, &(trackParam[1]));
1391         if (fPrintLevel >= 10) {
1392           cout << "FollowTracks: track candidate(0..): " << trackIndex
1393                << " Added segment in station(0..): " << station << endl;
1394           track->RecursiveDump();
1395         }
1396       }
1397       else {
1398         // No best segment found:
1399         // Look for best compatible HitForRec in station:
1400         // should consider all possibilities ????
1401         // multiple scattering ???? do about like for extrapSegment !!!!
1402         extrapHit = new AliMUONHitForRec(); //  empty hit
1403         bestChi2 = 3.0;
1404         bestHit = NULL;
1405         if (fPrintLevel >= 10) {
1406           cout << "FollowTracks: track candidate(0..): " << trackIndex
1407                << " Segment not found, look for hit in station(0..): " << station
1408                << endl;
1409         }
1410         // Loop over chambers of the station
1411         for (chInStation = 0; chInStation < 2; chInStation++) {
1412           ch = 2 * station + chInStation;
1413           for (iHit = fIndexOfFirstHitForRecPerChamber[ch];
1414                iHit < fIndexOfFirstHitForRecPerChamber[ch] +
1415                  fNHitsForRecPerChamber[ch];
1416                iHit++) {
1417             hit = (AliMUONHitForRec*) ((*fHitsForRecPtr)[iHit]);
1418             // coordinates of extrapolated hit
1419             (&(trackParam[chInStation]))->ExtrapToZ(hit->GetZ());
1420             extrapHit->
1421               SetBendingCoor((&(trackParam[chInStation]))->GetBendingCoor());
1422             extrapHit->
1423               SetNonBendingCoor((&(trackParam[chInStation]))->GetNonBendingCoor());
1424             // resolutions from "extrapSegment"
1425             extrapHit->SetBendingReso2(extrapSegment->GetBendingCoorReso2());
1426             extrapHit->SetNonBendingReso2(extrapSegment->GetNonBendingCoorReso2());
1427             // Loop over hits in the chamber
1428             // condition for hit not already in segment ????
1429             chi2 = hit->NormalizedChi2WithHitForRec(extrapHit, maxSigma2Distance);
1430             if (chi2 < bestChi2) {
1431               // update best Chi2 and HitForRec if better found
1432               bestHit = hit;
1433               bestChi2 = chi2;
1434               chBestHit = chInStation;
1435             }
1436           }
1437         }
1438         if (bestHit) {
1439           // best hit found: add it to track candidate
1440           (&(trackParam[chBestHit]))->ExtrapToZ(bestHit->GetZ());
1441           track->AddHitForRec(bestHit);
1442           // set track parameters at this TrackHit
1443           track->SetTrackParamAtHit(track->GetNTrackHits() - 1,
1444                                     &(trackParam[chBestHit]));
1445           if (fPrintLevel >= 10) {
1446             cout << "FollowTracks: track candidate(0..): " << trackIndex
1447                  << " Added hit in station(0..): " << station << endl;
1448             track->RecursiveDump();
1449           }
1450         }
1451         else {
1452           // Remove current track candidate
1453           // and corresponding TrackHit's, ...
1454           track->Remove();
1455           delete extrapSegment;
1456           delete extrapHit;
1457           break; // stop the search for this candidate:
1458           // exit from the loop over station
1459         }
1460         delete extrapHit;
1461       }
1462       delete extrapSegment;
1463       // Sort track hits according to increasing Z
1464       track->GetTrackHitsPtr()->Sort();
1465       // Update track parameters at first track hit (smallest Z)
1466       trackParam1 = ((AliMUONTrackHit*)
1467                      (track->GetTrackHitsPtr()->First()))->GetTrackParam();
1468       bendingMomentum = 0.;
1469       if (TMath::Abs(trackParam1->GetInverseBendingMomentum()) > 0.)
1470         bendingMomentum = TMath::Abs(1/(trackParam1->GetInverseBendingMomentum()));
1471       // Track removed if bendingMomentum not in window [min, max]
1472       if ((bendingMomentum < fMinBendingMomentum) || (bendingMomentum > fMaxBendingMomentum)) {
1473         track->Remove();
1474         break; // stop the search for this candidate:
1475         // exit from the loop over station 
1476       }
1477       // Track fit
1478       // with multiple Coulomb scattering if all stations
1479       if (station == 0) track->SetFitMCS(1);
1480       // without multiple Coulomb scattering if not all stations
1481       else track->SetFitMCS(0);
1482       track->SetFitNParam(5);  // with 5 parameters (momentum and position)
1483       track->SetFitStart(1);  // from parameters at first hit
1484       track->Fit();
1485       Double_t numberOfDegFree = (2.0 * track->GetNTrackHits() - 5);
1486       if (numberOfDegFree > 0) {
1487         chi2Norm =  track->GetFitFMin() / numberOfDegFree;
1488       } else {
1489         chi2Norm = 1.e10;
1490       }
1491       // Track removed if normalized chi2 too high
1492       if (chi2Norm > fMaxChi2) {
1493         track->Remove();
1494         break; // stop the search for this candidate:
1495         // exit from the loop over station 
1496       }
1497       if (fPrintLevel >= 10) {
1498         cout << "FollowTracks: track candidate(0..): " << trackIndex
1499              << " after fit from station(0..): " << station << " to 4" << endl;
1500         track->RecursiveDump();
1501       }
1502       // Track extrapolation to the vertex through the absorber (Branson)
1503       // after going through the first station
1504       if (station == 0) {
1505         trackParamVertex = *trackParam1;
1506         (&trackParamVertex)->ExtrapToVertex(0.,0.,0.);
1507         track->SetTrackParamAtVertex(&trackParamVertex);
1508         if (fPrintLevel >= 1) {
1509           cout << "FollowTracks: track candidate(0..): " << trackIndex
1510                << " after extrapolation to vertex" << endl;
1511           track->RecursiveDump();
1512         }
1513       }
1514     } // for (station = 2;...
1515     // go really to next track
1516     track = nextTrack;
1517   } // while (track)
1518   // Compression of track array (necessary after Remove ????)
1519   fRecTracksPtr->Compress();
1520   return;
1521 }
1522
1523   //__________________________________________________________________________
1524 void AliMUONEventReconstructor::RemoveDoubleTracks(void)
1525 {
1526   // To remove double tracks.
1527   // Tracks are considered identical
1528   // if they have at least half of their hits in common.
1529   // Among two identical tracks, one keeps the track with the larger number of hits
1530   // or, if these numbers are equal, the track with the minimum Chi2.
1531   AliMUONTrack *track1, *track2, *trackToRemove;
1532   Bool_t identicalTracks;
1533   Int_t hitsInCommon, nHits1, nHits2;
1534   identicalTracks = kTRUE;
1535   while (identicalTracks) {
1536     identicalTracks = kFALSE;
1537     // Loop over first track of the pair
1538     track1 = (AliMUONTrack*) fRecTracksPtr->First();
1539     while (track1 && (!identicalTracks)) {
1540       nHits1 = track1->GetNTrackHits();
1541       // Loop over second track of the pair
1542       track2 = (AliMUONTrack*) fRecTracksPtr->After(track1);
1543       while (track2 && (!identicalTracks)) {
1544         nHits2 = track2->GetNTrackHits();
1545         // number of hits in common between two tracks
1546         hitsInCommon = track1->HitsInCommon(track2);
1547         // check for identical tracks
1548         if ((4 * hitsInCommon) >= (nHits1 + nHits2)) {
1549           identicalTracks = kTRUE;
1550           // decide which track to remove
1551           if (nHits1 > nHits2) trackToRemove = track2;
1552           else if (nHits1 < nHits2) trackToRemove = track1;
1553           else if ((track1->GetFitFMin()) < (track2->GetFitFMin()))
1554             trackToRemove = track2;
1555           else trackToRemove = track1;
1556           // remove it
1557           trackToRemove->Remove();
1558         }
1559         track2 = (AliMUONTrack*) fRecTracksPtr->After(track2);
1560       } // track2
1561       track1 = (AliMUONTrack*) fRecTracksPtr->After(track1);
1562     } // track1
1563   }
1564   return;
1565 }
1566
1567   //__________________________________________________________________________
1568 void AliMUONEventReconstructor::UpdateTrackParamAtHit()
1569 {
1570   // Set track parameters after track fitting. Fill fTrackParamAtHit of AliMUONTrack's
1571   AliMUONTrack *track;
1572   AliMUONTrackHit *trackHit;
1573   AliMUONTrackParam *trackParam;
1574   track = (AliMUONTrack*) fRecTracksPtr->First();
1575   while (track) {
1576     trackHit = (AliMUONTrackHit*) (track->GetTrackHitsPtr())->First();
1577     while (trackHit) {
1578       trackParam = trackHit->GetTrackParam();
1579       track->AddTrackParamAtHit(trackParam);
1580       trackHit = (AliMUONTrackHit*) (track->GetTrackHitsPtr())->After(trackHit); 
1581     } // trackHit    
1582     track = (AliMUONTrack*) fRecTracksPtr->After(track);
1583   } // track
1584   return;
1585 }
1586
1587   //__________________________________________________________________________
1588 void AliMUONEventReconstructor::UpdateHitForRecAtHit()
1589 {
1590   // Set cluster parameterss after track fitting. Fill fHitForRecAtHit of AliMUONTrack's
1591   AliMUONTrack *track;
1592   AliMUONTrackHit *trackHit;
1593   AliMUONHitForRec *hitForRec;
1594   track = (AliMUONTrack*) fRecTracksPtr->First();
1595   while (track) {
1596     trackHit = (AliMUONTrackHit*) (track->GetTrackHitsPtr())->First();
1597     while (trackHit) {
1598       hitForRec = trackHit->GetHitForRecPtr();
1599       track->AddHitForRecAtHit(hitForRec);
1600       trackHit = (AliMUONTrackHit*) (track->GetTrackHitsPtr())->After(trackHit); 
1601     } // trackHit    
1602     track = (AliMUONTrack*) fRecTracksPtr->After(track);
1603   } // track
1604   return;
1605 }
1606
1607   //__________________________________________________________________________
1608 void AliMUONEventReconstructor::FillMUONTrack()
1609 {
1610   // Set track parameters at hits for Kalman track. Fill fTrackParamAtHit of AliMUONTrack's
1611   AliMUONTrackK *track;
1612   track = (AliMUONTrackK*) fRecTracksPtr->First();
1613   while (track) {
1614     track->FillMUONTrack();
1615     track = (AliMUONTrackK*) fRecTracksPtr->After(track);
1616   } 
1617   return;
1618 }
1619
1620   //__________________________________________________________________________
1621 void AliMUONEventReconstructor::EventDump(void)
1622 {
1623   // Dump reconstructed event (track parameters at vertex and at first hit),
1624   // and the particle parameters
1625
1626   AliMUONTrack *track;
1627   AliMUONTrackParam *trackParam, *trackParam1;
1628   Double_t bendingSlope, nonBendingSlope, pYZ;
1629   Double_t pX, pY, pZ, x, y, z, c;
1630   Int_t np, trackIndex, nTrackHits;
1631  
1632   if (fPrintLevel >= 1) cout << "****** enter EventDump ******" << endl;
1633   if (fPrintLevel >= 1) {
1634     cout << " Number of Reconstructed tracks :" <<  fNRecTracks << endl; 
1635   }
1636   fRecTracksPtr->Compress(); // for simple loop without "Next" since no hole
1637   // Loop over reconstructed tracks
1638   for (trackIndex = 0; trackIndex < fNRecTracks; trackIndex++) {
1639     if (fTrackMethod != 1) continue; //AZ - skip the rest for now
1640     if (fPrintLevel >= 1)
1641       cout << " track number: " << trackIndex << endl;
1642     // function for each track for modularity ????
1643     track = (AliMUONTrack*) ((*fRecTracksPtr)[trackIndex]);
1644     nTrackHits = track->GetNTrackHits();
1645     if (fPrintLevel >= 1)
1646       cout << " number of track hits: " << nTrackHits << endl;
1647     // track parameters at Vertex
1648     trackParam = track->GetTrackParamAtVertex();
1649     x = trackParam->GetNonBendingCoor();
1650     y = trackParam->GetBendingCoor();
1651     z = trackParam->GetZ();
1652     bendingSlope = trackParam->GetBendingSlope();
1653     nonBendingSlope = trackParam->GetNonBendingSlope();
1654     pYZ = 1/TMath::Abs(trackParam->GetInverseBendingMomentum());
1655     pZ = pYZ/TMath::Sqrt(1+bendingSlope*bendingSlope);
1656     pX = pZ * nonBendingSlope;
1657     pY = pZ * bendingSlope;
1658     c = TMath::Sign(1.0, trackParam->GetInverseBendingMomentum());
1659     if (fPrintLevel >= 1)
1660       printf(" track parameters at Vertex z= %f: X= %f Y= %f pX= %f pY= %f pZ= %f c= %f\n",
1661              z, x, y, pX, pY, pZ, c);
1662
1663     // track parameters at first hit
1664     trackParam1 = ((AliMUONTrackHit*)
1665                    (track->GetTrackHitsPtr()->First()))->GetTrackParam();
1666     x = trackParam1->GetNonBendingCoor();
1667     y = trackParam1->GetBendingCoor();
1668     z = trackParam1->GetZ();
1669     bendingSlope = trackParam1->GetBendingSlope();
1670     nonBendingSlope = trackParam1->GetNonBendingSlope();
1671     pYZ = 1/TMath::Abs(trackParam1->GetInverseBendingMomentum());
1672     pZ = pYZ/TMath::Sqrt(1.0 + bendingSlope * bendingSlope);
1673     pX = pZ * nonBendingSlope;
1674     pY = pZ * bendingSlope;
1675     c = TMath::Sign(1.0, trackParam1->GetInverseBendingMomentum());
1676     if (fPrintLevel >= 1)
1677       printf(" track parameters at z= %f: X= %f Y= %f pX= %f pY= %f pZ= %f c= %f\n",
1678              z, x, y, pX, pY, pZ, c);
1679   }
1680   // informations about generated particles
1681   np = gAlice->GetMCApp()->GetNtrack();
1682   printf(" **** number of generated particles: %d  \n", np);
1683   
1684 //    for (Int_t iPart = 0; iPart < np; iPart++) {
1685 //      p = gAlice->Particle(iPart);
1686 //      printf(" particle %d: type= %d px= %f py= %f pz= %f pdg= %d\n",
1687 //         iPart, p->GetPdgCode(), p->Px(), p->Py(), p->Pz(), p->GetPdgCode());    
1688 //    }
1689   return;
1690 }
1691
1692
1693 //__________________________________________________________________________
1694 void AliMUONEventReconstructor::EventDumpTrigger(void)
1695 {
1696   // Dump reconstructed trigger event 
1697   // and the particle parameters
1698     
1699   AliMUONTriggerTrack *triggertrack ;
1700   Int_t nTriggerTracks = fMUONData->RecTriggerTracks()->GetEntriesFast();
1701  
1702   if (fPrintLevel >= 1) {
1703     cout << "****** enter EventDumpTrigger ******" << endl;
1704     cout << " Number of Reconstructed tracks :" <<  nTriggerTracks << endl;
1705   }
1706   // Loop over reconstructed tracks
1707   for (Int_t trackIndex = 0; trackIndex < nTriggerTracks; trackIndex++) {
1708     triggertrack = (AliMUONTriggerTrack*)fMUONData->RecTriggerTracks()->At(trackIndex);
1709       printf(" trigger track number %i x11=%f y11=%f thetax=%f thetay=%f \n",
1710              trackIndex,
1711              triggertrack->GetX11(),triggertrack->GetY11(),
1712              triggertrack->GetThetax(),triggertrack->GetThetay());      
1713   } 
1714 }
1715
1716 //__________________________________________________________________________
1717 void AliMUONEventReconstructor::FillEvent()
1718 {
1719 // Create a new AliMUONRecoEvent, fill its track list, then add it as a
1720 // leaf in the Event branch of TreeRecoEvent tree
1721    cout << "Enter FillEvent() ...\n";
1722
1723    if (!fRecoEvent) {
1724       fRecoEvent = new AliMUONRecoEvent();
1725    } else {
1726       fRecoEvent->Clear();
1727    }
1728    //save current directory
1729    TDirectory *current =  gDirectory;
1730    if (!fTreeFile)  fTreeFile  = new TFile("tree_reco.root", "RECREATE");
1731    if (!fEventTree) fEventTree = new TTree("TreeRecoEvent", "MUON reconstructed events");
1732    //AZif (fRecoEvent->MakeDumpTracks(fRecTracksPtr)) {
1733    if (fRecoEvent->MakeDumpTracks(fMuons, fRecTracksPtr, this)) { //AZ
1734       if (fPrintLevel > 1) fRecoEvent->EventInfo();
1735       TBranch *branch = fEventTree->GetBranch("Event");
1736       if (!branch) branch = fEventTree->Branch("Event", "AliMUONRecoEvent", &fRecoEvent, 64000);
1737       branch->SetAutoDelete();
1738       fTreeFile->cd();
1739       fEventTree->Fill();
1740       fTreeFile->Write();
1741    }
1742    // restore directory
1743    current->cd();
1744 }
1745
1746 //__________________________________________________________________________
1747 void AliMUONEventReconstructor::MakeTrackCandidatesK(void)
1748 {
1749   // To make initial tracks for Kalman filter from the list of segments
1750   Int_t istat, iseg;
1751   AliMUONSegment *segment;
1752   AliMUONTrackK *trackK;
1753
1754   if (fPrintLevel >= 1) cout << "enter MakeTrackCandidatesK" << endl;
1755   // Reset the TClonesArray of reconstructed tracks
1756   if (fRecTracksPtr) fRecTracksPtr->Delete();
1757   // Delete in order that the Track destructors are called,
1758   // hence the space for the TClonesArray of pointers to TrackHit's is freed
1759   fNRecTracks = 0;
1760
1761   AliMUONTrackK a(this, fHitsForRecPtr); // bad idea ???
1762   // Loop over stations(1...) 5 and 4
1763   for (istat=4; istat>=3; istat--) {
1764     // Loop over segments in the station
1765     for (iseg=0; iseg<fNSegments[istat]; iseg++) {
1766       // Transform segments to tracks and evaluate covariance matrix
1767       segment = (AliMUONSegment*) ((*fSegmentsPtr[istat])[iseg]);
1768       trackK = new ((*fRecTracksPtr)[fNRecTracks]) AliMUONTrackK(segment);
1769       fNRecTracks++;
1770     } // for (iseg=0;...)
1771   } // for (istat=4;...)
1772   return;
1773 }
1774
1775 //__________________________________________________________________________
1776 void AliMUONEventReconstructor::FollowTracksK(void)
1777 {
1778   // Follow tracks using Kalman filter
1779   Bool_t ok;
1780   Int_t icand, ichamBeg = 0, ichamEnd, chamBits;
1781   Double_t zDipole1, zDipole2;
1782   AliMUONTrackK *trackK;
1783   AliMUONHitForRec *hit;
1784   AliMUONRawCluster *clus;
1785   TClonesArray *rawclusters;
1786   clus = 0; rawclusters = 0;
1787
1788   //AZ(z->-z) zDipole1 = GetSimpleBPosition() - GetSimpleBLength()/2;
1789   //AZ(z->-z) zDipole2 = zDipole1 + GetSimpleBLength();
1790   zDipole1 = GetSimpleBPosition() + GetSimpleBLength()/2;
1791   zDipole2 = zDipole1 - GetSimpleBLength();
1792
1793   // Print hits
1794   trackK = (AliMUONTrackK*) ((*fRecTracksPtr)[0]);
1795   if (trackK->DebugLevel() > 0) {
1796     for (Int_t i1=0; i1<fNHitsForRec; i1++) {
1797       hit = (AliMUONHitForRec*) ((*fHitsForRecPtr)[i1]);
1798       //if (hit->GetTTRTrack() > 1 || hit->GetTrackRefSignal() == 0) continue;
1799       printf(" Hit # %d %10.4f %10.4f %10.4f",
1800              hit->GetChamberNumber(), hit->GetBendingCoor(),
1801              hit->GetNonBendingCoor(), hit->GetZ());
1802       if (fRecTrackRefHits) {
1803         // from track ref hits
1804         printf(" %3d %3d \n", hit->GetTrackRefSignal(), hit->GetTTRTrack());
1805       } else {
1806         // from raw clusters
1807         rawclusters = fMUONData->RawClusters(hit->GetChamberNumber());
1808         clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->
1809                                                  GetHitNumber());
1810         printf("%3d", clus->GetTrack(1)-1);
1811         if (clus->GetTrack(2) != 0) printf("%3d \n", clus->GetTrack(2)-1);
1812         else printf("\n");
1813       } // if (fRecTrackRefHits)
1814     }
1815   } // if (trackK->DebugLevel() > 0)
1816
1817   icand = -1;
1818   Int_t nSeeds;
1819   nSeeds = fNRecTracks; // starting number of seeds
1820   // Loop over track candidates
1821   while (icand < fNRecTracks-1) {
1822     icand ++;
1823     if (trackK->DebugLevel()>0) cout << " *** Kalman track candidate No. " << icand << endl;
1824     trackK = (AliMUONTrackK*) ((*fRecTracksPtr)[icand]);
1825     if (trackK->GetRecover() < 0) continue; // failed track
1826
1827     // Discard candidate which will produce the double track
1828     /*
1829     if (icand > 0) {
1830       ok = CheckCandidateK(icand,nSeeds);
1831       if (!ok) {
1832         trackK->SetRecover(-1); // mark candidate to be removed
1833         continue;
1834       }
1835     }
1836     */
1837
1838     ok = kTRUE;
1839     if (trackK->GetRecover() == 0) hit = (AliMUONHitForRec*) 
1840                                    trackK->GetHitOnTrack()->Last(); // last hit
1841     //else hit = (AliMUONHitForRec*) (*trackK->GetHitOnTrack())[1]; // 2'nd hit
1842     else hit = trackK->GetHitLastOk(); // hit where track stopped
1843     if (hit) ichamBeg = hit->GetChamberNumber();
1844     ichamEnd = 0;
1845     // Check propagation direction
1846     if (hit == NULL) ichamBeg = ichamEnd;
1847     //AZ(z->-z) else if (trackK->GetTrackDir() > 0) {
1848     else if (trackK->GetTrackDir() < 0) {
1849       ichamEnd = 9; // forward propagation
1850       ok = trackK->KalmanFilter(ichamBeg,ichamEnd,kFALSE,zDipole1,zDipole2);
1851       if (ok) {
1852         ichamBeg = ichamEnd;
1853         ichamEnd = 6; // backward propagation
1854         // Change weight matrix and zero fChi2 for backpropagation
1855         trackK->StartBack();
1856         //AZ trackK->SetTrackDir(-1);
1857         trackK->SetTrackDir(1);
1858         ok = trackK->KalmanFilter(ichamBeg,ichamEnd,kTRUE,zDipole1,zDipole2);
1859         ichamBeg = ichamEnd;
1860         ichamEnd = 0;
1861       }
1862     } else {
1863       if (trackK->GetBPFlag()) {
1864         // backpropagation
1865         ichamEnd = 6; // backward propagation
1866         // Change weight matrix and zero fChi2 for backpropagation
1867         trackK->StartBack();
1868         ok = trackK->KalmanFilter(ichamBeg,ichamEnd,kTRUE,zDipole1,zDipole2);
1869         ichamBeg = ichamEnd;
1870         ichamEnd = 0;
1871       }
1872     }
1873
1874     if (ok) {
1875       //AZ trackK->SetTrackDir(-1);
1876       trackK->SetTrackDir(1);
1877       trackK->SetBPFlag(kFALSE);
1878       ok = trackK->KalmanFilter(ichamBeg,ichamEnd,kFALSE,zDipole1,zDipole2);
1879     }
1880     if (!ok) { trackK->SetRecover(-1); continue; } // mark candidate to be removed
1881
1882     // Apply smoother
1883     if (trackK->GetRecover() >= 0) {
1884       ok = trackK->Smooth();
1885       if (!ok) trackK->SetRecover(-1); // mark candidate to be removed
1886     }
1887
1888     // Majority 3 of 4 in first 2 stations
1889     if (!ok) continue;
1890     chamBits = 0;
1891     Double_t chi2_max = 0;
1892     for (Int_t i=0; i<trackK->GetNTrackHits(); i++) {
1893       hit = (AliMUONHitForRec*) (*trackK->GetHitOnTrack())[i];
1894       chamBits |= BIT(hit->GetChamberNumber());
1895       if (trackK->GetChi2PerPoint(i) > chi2_max) chi2_max = trackK->GetChi2PerPoint(i);
1896     }
1897     if (!((chamBits&3)==3 || (chamBits>>2&3)==3) && chi2_max > 25) {
1898       //trackK->Recover();
1899       trackK->SetRecover(-1); //mark candidate to be removed
1900       continue;
1901     }
1902     if (ok) trackK->SetTrackQuality(0); // compute "track quality"
1903   } // while
1904
1905   for (Int_t i=0; i<fNRecTracks; i++) {
1906     trackK = (AliMUONTrackK*) ((*fRecTracksPtr)[i]);
1907     if (trackK->GetRecover() < 0) fRecTracksPtr->RemoveAt(i);
1908   }
1909
1910   // Compress TClonesArray
1911   fRecTracksPtr->Compress();
1912   fNRecTracks = fRecTracksPtr->GetEntriesFast();
1913   return;
1914 }
1915
1916 //__________________________________________________________________________
1917 Bool_t AliMUONEventReconstructor::CheckCandidateK(Int_t icand, Int_t nSeeds) const
1918 {
1919   // Discards track candidate if it will produce the double track (having
1920   // the same seed segment hits as hits of a good track found before)
1921   AliMUONTrackK *track1, *track2;
1922   AliMUONHitForRec *hit1, *hit2, *hit;
1923
1924   track1 = (AliMUONTrackK*) ((*fRecTracksPtr)[icand]);
1925   hit1 = (AliMUONHitForRec*) (*track1->GetHitOnTrack())[0]; // 1'st hit
1926   hit2 = (AliMUONHitForRec*) (*track1->GetHitOnTrack())[1]; // 2'nd hit
1927
1928   for (Int_t i=0; i<icand; i++) {
1929     track2 = (AliMUONTrackK*) ((*fRecTracksPtr)[i]);
1930     //if (track2->GetRecover() < 0) continue;
1931     if (track2->GetRecover() < 0 && icand >= nSeeds) continue;
1932
1933     if (track1->GetStartSegment() == track2->GetStartSegment()) {
1934       return kFALSE;
1935     } else {
1936       Int_t nSame = 0;
1937       for (Int_t j=0; j<track2->GetNTrackHits(); j++) {
1938         hit = (AliMUONHitForRec*) (*track2->GetHitOnTrack())[j];
1939         if (hit == hit1 || hit == hit2) {
1940           nSame++;
1941           if (nSame == 2) return kFALSE;
1942         }
1943       } // for (Int_t j=0;
1944     }
1945   } // for (Int_t i=0;
1946   return kTRUE;
1947 }
1948
1949 //__________________________________________________________________________
1950 void AliMUONEventReconstructor::RemoveDoubleTracksK(void)
1951 {
1952   // Removes double tracks (sharing more than half of their hits). Keeps
1953   // the track with higher quality
1954   AliMUONTrackK *track1, *track2, *trackToKill;
1955
1956   // Sort tracks according to their quality
1957   fRecTracksPtr->Sort();
1958
1959   // Loop over first track of the pair
1960   track1 = (AliMUONTrackK*) fRecTracksPtr->First();
1961   Int_t debug = track1->DebugLevel();
1962   while (track1) {
1963     // Loop over second track of the pair
1964     track2 = (AliMUONTrackK*) fRecTracksPtr->After(track1);
1965     while (track2) {
1966       // Check whether or not to keep track2
1967       if (!track2->KeepTrack(track1)) {
1968         if (debug >= 0) cout << " Killed track: " << 1/(*track2->GetTrackParameters())(4,0) <<
1969           " " << track2->GetTrackQuality() << endl;
1970         trackToKill = track2;
1971         track2 = (AliMUONTrackK*) fRecTracksPtr->After(track2);
1972         trackToKill->Kill();
1973         fRecTracksPtr->Compress();
1974       } else track2 = (AliMUONTrackK*) fRecTracksPtr->After(track2);
1975     } // track2
1976     track1 = (AliMUONTrackK*) fRecTracksPtr->After(track1);
1977   } // track1
1978
1979   fNRecTracks = fRecTracksPtr->GetEntriesFast();
1980   if (debug >= 0) cout << " Number of Kalman tracks: " << fNRecTracks << endl;
1981 }
1982
1983 //__________________________________________________________________________
1984 void AliMUONEventReconstructor::GoToVertex(void)
1985 {
1986   // Propagates track to the vertex thru absorber
1987   // (using Branson correction for now)
1988
1989   Double_t zVertex;
1990   zVertex = 0;
1991   for (Int_t i=0; i<fNRecTracks; i++) {
1992     //((AliMUONTrackK*)(*fRecTracksPtr)[i])->Branson();
1993     ((AliMUONTrackK*)(*fRecTracksPtr)[i])->SetTrackQuality(1); // compute Chi2
1994     //((AliMUONTrackK*)(*fRecTracksPtr)[i])->GoToZ(zVertex); // w/out absorber
1995     ((AliMUONTrackK*)(*fRecTracksPtr)[i])->GoToVertex(1); // with absorber
1996   }
1997 }
1998
1999 //__________________________________________________________________________
2000 void AliMUONEventReconstructor::SetTrackMethod(Int_t iTrackMethod)
2001 {
2002   // Set track method and recreate track container if necessary
2003   
2004   fTrackMethod = iTrackMethod == 2 ? 2 : 1;
2005   if (fTrackMethod == 2) {
2006     if (fRecTracksPtr) delete fRecTracksPtr;
2007     fRecTracksPtr = new TClonesArray("AliMUONTrackK", 10);
2008     cout << " *** Tracking with the Kalman filter *** " << endl;
2009   } else cout << " *** Traditional tracking *** " << endl;
2010
2011 }