]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MFT/AliMuonForwardTrackFinder.cxx
ffa44e7683367a7ab6a19410b1a673c991228d6a
[u/mrichter/AliRoot.git] / MFT / AliMuonForwardTrackFinder.cxx
1 // ROOT includes
2 #include "TObject.h"
3 #include "TClonesArray.h"
4 #include "TObjArray.h"
5 #include "TH2D.h"
6 #include "TH1D.h"
7 #include "TFile.h"
8 #include "TGeoManager.h"
9 #include "TMatrixD.h"
10 #include "TParticle.h"
11 #include "TMath.h"
12 #include "TGraph.h"
13 #include "TEllipse.h"
14 #include "TCanvas.h"
15 #include "TString.h"
16 #include "TLatex.h"
17 #include "TMarker.h"
18 #include "TNtuple.h"
19 #include "TRandom.h"
20 #include "TIterator.h"
21
22 // STEER includes
23 #include "AliLog.h"
24 #include "AliRun.h"
25 #include "AliRunLoader.h"
26 #include "AliLoader.h"
27 #include "AliHeader.h"
28 #include "AliMC.h"
29 #include "AliStack.h"
30 #include "AliMagF.h"
31 #include "AliTracker.h"
32 #include "AliGRPObject.h"
33 #include "AliCDBEntry.h"
34 #include "AliCDBManager.h"
35
36 // MUON includes
37 #include "AliMUONConstants.h"
38 #include "AliMUONTrack.h"
39 #include "AliMUONRecoCheck.h"
40 #include "AliMUONTrackParam.h"
41 #include "AliMUONTrackExtrap.h"
42 #include "AliMUONVTrackStore.h"
43 #include "AliMUONVCluster.h"
44
45 // MFT includes
46 #include "AliMuonForwardTrack.h"
47 #include "AliMFTCluster.h"
48 #include "AliMFT.h"
49 #include "AliMFTSegmentation.h"
50 #include "AliMFTConstants.h"
51
52 #include "AliMuonForwardTrackFinder.h"
53
54 //====================================================================================================================================================
55 //
56 // Class for the creation of the "global muon tracks" built from the clusters in the 
57 // muon spectrometer and the clusters of the Muon Forward Tracker. QA histograms are also created
58 //
59 // Contact author: antonio.uras@cern.ch
60 //
61 //====================================================================================================================================================
62
63 const Double_t AliMuonForwardTrackFinder::fRadLengthSi = AliMFTConstants::fRadLengthSi;
64
65 ClassImp(AliMuonForwardTrackFinder)
66
67 //=====================================================================================================
68
69 AliMuonForwardTrackFinder::AliMuonForwardTrackFinder():
70   TObject(),
71   fRun(0),
72   fNEventsToAnalyze(0),
73   fSigmaClusterCut(0),
74   fChi2GlobalCut(0),
75   fSigmaSpectrometerCut(0),
76   fExtrapOriginTransvError(0),
77   fGaussianBlurZVert(0),
78   fNFinalCandidatesCut(0),
79   fReadDir(0),
80   fOutDir(0),
81   fDrawOption(0),
82
83   fDistanceFromGoodClusterAndTrackAtLastPlane(-1),
84   fDistanceFromBestClusterAndTrackAtLastPlane(-1),
85   
86   fRAbsorberCut(0),
87   fLowPtCut(0),
88   fNPlanesMFT(0),
89   fNPlanesMFTAnalyzed(0),
90   fNMaxMissingMFTClusters(0),
91
92   fEv(0),
93   fLabelMC(0),
94
95   fHistPtSpectrometer(0), 
96   fHistPtMuonTrackWithGoodMatch(0),
97   fHistPtMuonTrackWithBadMatch(0),
98   fHistRadiusEndOfAbsorber(0), 
99   fHistNGoodClustersForFinalTracks(0),
100   fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane(0),
101   fHistDistanceGoodClusterFromTrackAtLastPlane(0),
102
103   fNtuFinalCandidates(0),
104   fNtuFinalBestCandidates(0),
105
106   fCanvas(0),
107
108   fTxtMuonHistory(0), 
109   fTxtTrackGoodClusters(0), 
110   fTxtTrackFinalChi2(0),
111   fTxtTrackMomentum(0),
112   fTxtFinalCandidates(0), 
113   fTxtDummy(0),
114   fTxtAllClust(0), 
115   fTxtClustGoodChi2(0), 
116   fTxtClustMC(0), 
117   fTxtClustOfTrack(0), 
118   fMrkAllClust(0), 
119   fMrkClustGoodChi2(0), 
120   fMrkClustMC(0), 
121   fMrkClustOfTrack(0),
122
123   fCountRealTracksAnalyzed(0),
124   fMaxNTracksToBeAnalyzed(99999999),
125   fCountRealTracksWithRefMC(0), 
126   fCountRealTracksWithRefMC_andTrigger(0),
127   fCountRealTracksWithRefMC_andTrigger_andGoodPt(0),
128   fCountRealTracksWithRefMC_andTrigger_andGoodPt_andGoodTheta(0),
129   fCountRealTracksAnalyzedOfEvent(0),
130   fCountRealTracksAnalyzedWithFinalCandidates(0),
131
132   fFileCluster(0),
133   fFileESD(0),
134   fFile_gAlice(0),
135
136   fRunLoader(0),
137   fMFTLoader(0),
138   fMuonRecoCheck(0),
139   fMFTClusterTree(0),
140   fMuonTrackReco(0),
141   fCurrentTrack(0),
142   fFinalBestCandidate(0),
143   fIsCurrentMuonTrackable(0),
144   fCandidateTracks(0),
145   fTrackStore(0),
146   fTrackRefStore(0),
147   fNextTrack(0),
148   fStack(0),
149   fMFT(0),
150   fSegmentation(0),
151   fOutputTreeFile(0),
152   fOutputQAFile(0),
153   fOutputEventTree(0),
154   fMuonForwardTracks(0),
155   fMatchingMode(-1),
156   fMinResearchRadiusAtLastPlane(0),
157   fGRPData(0),
158   fRunInfo(0)
159
160 {
161
162   // Default constructor
163
164   for (Int_t iPlane=0; iPlane<AliMFTConstants::fNMaxPlanes; iPlane++) {
165
166     fHistNTracksAfterExtrapolation[iPlane] = 0;
167     fHistChi2Cluster_GoodCluster[iPlane] = 0;
168     fHistChi2Cluster_BadCluster[iPlane] = 0;
169     fHistResearchRadius[iPlane] = 0;      
170     
171     fIsGoodClusterInPlane[iPlane] = kFALSE;
172     
173     fHistChi2Cluster_GoodCluster[iPlane] = 0;
174     fHistChi2Cluster_BadCluster[iPlane]  = 0;
175     
176     fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[iPlane] = 0;
177     fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[iPlane] = 0;
178     
179     fZPlane[iPlane] = 0.;
180     fRPlaneMax[iPlane] = 0.;
181     fRPlaneMin[iPlane] = 0.;
182     
183     for (Int_t i=0; i<4; i++) fGrMFTPlane[i][iPlane] = 0;
184     fCircleExt[iPlane] = 0;
185     fCircleInt[iPlane] = 0;
186     
187     fTxtTrackChi2[iPlane] = 0;
188     
189     fIsClusterCompatible[iPlane] = 0;
190     
191     fMFTClusterArray[iPlane]      = 0;
192     fMFTClusterArrayFront[iPlane] = new TClonesArray("AliMFTCluster");
193     fMFTClusterArrayBack[iPlane]  = new TClonesArray("AliMFTCluster");
194
195     fIsPlaneMandatory[iPlane] = kFALSE;
196     
197   }
198
199   //  fNextTrack = 0;
200
201   fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane = 0;
202   fHistDistanceGoodClusterFromTrackAtLastPlane = 0;
203
204   fMFTClusterTree = 0;
205   fCandidateTracks = 0;
206
207   fOutputTreeFile    = new TFile("MuonGlobalTracks.root", "recreate");
208   fOutputEventTree   = new TTree("AliMuonForwardTracks", "Tree of AliMuonForwardTracks");
209   fMuonForwardTracks = new TClonesArray("AliMuonForwardTrack");
210   fOutputEventTree   -> Branch("tracks", &fMuonForwardTracks);
211
212 }
213
214 //=====================================================================================================
215
216 AliMuonForwardTrackFinder::~AliMuonForwardTrackFinder() {
217
218   for (Int_t iPlane=0; iPlane<AliMFTConstants::fNMaxPlanes; iPlane++) {
219
220     delete fHistNTracksAfterExtrapolation[iPlane];
221     delete fHistChi2Cluster_GoodCluster[iPlane];
222     delete fHistChi2Cluster_BadCluster[iPlane];
223     delete fHistResearchRadius[iPlane];
224     
225     delete fHistChi2Cluster_GoodCluster[iPlane];
226     delete fHistChi2Cluster_BadCluster[iPlane];
227     
228     delete fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[iPlane];
229     delete fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[iPlane];
230     
231     for (Int_t i=0; i<4; i++) delete fGrMFTPlane[i][iPlane];
232     delete fCircleExt[iPlane];
233     delete fCircleInt[iPlane];
234     
235     delete fTxtTrackChi2[iPlane];
236     
237     delete fMFTClusterArray[iPlane];
238     delete fMFTClusterArrayFront[iPlane];
239     delete fMFTClusterArrayBack[iPlane];
240
241   }
242
243   delete fNtuFinalCandidates;
244   delete fNtuFinalBestCandidates;
245
246   delete fHistPtSpectrometer;
247   delete fHistPtMuonTrackWithGoodMatch;
248   delete fHistPtMuonTrackWithBadMatch;
249   delete fHistRadiusEndOfAbsorber;
250
251   delete fHistNGoodClustersForFinalTracks; 
252   delete fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane;         //
253   delete fHistDistanceGoodClusterFromTrackAtLastPlane;                                          //
254
255   delete fCanvas;
256
257   delete fTxtMuonHistory;
258   delete fTxtTrackGoodClusters;
259   delete fTxtTrackFinalChi2;
260   delete fTxtTrackMomentum;
261   delete fTxtFinalCandidates;
262   delete fTxtDummy;
263   delete fTxtAllClust;
264   delete fTxtClustGoodChi2;
265   delete fTxtClustMC;
266   delete fTxtClustOfTrack;
267   delete fMrkAllClust;
268   delete fMrkClustGoodChi2;
269   delete fMrkClustMC;
270   delete fMrkClustOfTrack;
271  
272   delete fFileCluster;
273   delete fFileESD;
274   delete fFile_gAlice;
275
276   delete fRunLoader;
277   delete fMFTLoader;
278   delete fMuonRecoCheck;
279
280   delete fMFTClusterTree;
281
282   delete fMuonTrackReco;
283   delete fCurrentTrack;
284   delete fFinalBestCandidate;
285
286   delete fCandidateTracks;
287
288   delete fTrackStore;
289   delete fTrackRefStore;
290   
291   delete fNextTrack;
292   
293   delete fStack;
294
295   delete fMFT;
296   delete fSegmentation;
297
298   delete fOutputTreeFile; 
299   delete fOutputQAFile;
300   delete fOutputEventTree;
301
302   delete fMuonForwardTracks;
303
304   delete fGRPData;
305   delete fRunInfo;       
306
307 }
308
309 //=====================================================================================================
310
311 void AliMuonForwardTrackFinder::Init(Int_t nRun, 
312                                      Char_t *readDir,
313                                      Char_t *outDir,
314                                      Int_t nEventsToAnalyze) {
315   
316   if (fRunLoader) {
317     AliInfo("WARNING: run already initialized!!\n");
318   }
319
320   SetRun(nRun);
321   SetReadDir(readDir);
322   SetOutDir(outDir);
323
324   AliInfo(Form("input  dir = %s\n", fReadDir.Data()));
325   AliInfo(Form("output dir = %s\n", fOutDir.Data()));
326
327   // -------------------------- initializing files...
328
329   AliInfo(Form("initializing files for run %d...\n", fRun));
330
331   Char_t geoFileName[300];
332   Char_t esdFileName[300];
333   Char_t gAliceName[300];
334   Char_t clusterName[300];
335   
336   sprintf(geoFileName , "%s/geometry.root",      fReadDir.Data());
337   sprintf(esdFileName , "%s/AliESDs.root" ,      fReadDir.Data());
338   sprintf(gAliceName  , "%s/galice.root"  ,      fReadDir.Data());
339   sprintf(clusterName , "%s/MFT.RecPoints.root", fReadDir.Data());
340   
341   // Import TGeo geometry (needed by AliMUONTrackExtrap::ExtrapToVertex)
342   if (!gGeoManager) {
343     TGeoManager::Import(geoFileName);
344     if (!gGeoManager) {
345       AliError(Form("getting geometry from file %s failed", geoFileName));
346       return;
347     }
348   }
349   
350   fFileESD = new TFile(esdFileName);
351   if (!fFileESD || !fFileESD->IsOpen()) return;
352   else AliInfo(Form("file %s successfully opened\n", fFileESD->GetName()));
353   
354   fMuonRecoCheck = new AliMUONRecoCheck(esdFileName, Form("%s/generated/", fReadDir.Data()));       // Utility class to check reconstruction
355   fFile_gAlice = new TFile(gAliceName);
356   if (!fFile_gAlice || !fFile_gAlice->IsOpen()) return;
357   else AliInfo(Form("file %s successfully opened\n", fFile_gAlice->GetName()));
358   
359   fRunLoader = AliRunLoader::Open(gAliceName);
360   gAlice = fRunLoader->GetAliRun();
361   if (!gAlice) fRunLoader->LoadgAlice();
362   fMFT = (AliMFT*) gAlice->GetDetector("MFT"); 
363   fSegmentation = fMFT->GetSegmentation();
364   SetNPlanesMFT(fSegmentation->GetNPlanes());
365
366   if (!SetRunNumber()) return;
367   if (!InitGRP()) return;
368   AliMUONTrackExtrap::SetField();        // set the magnetic field for track extrapolations
369
370   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
371     fZPlane[iPlane]    = fSegmentation->GetPlane(iPlane)->GetZCenter();
372     fRPlaneMax[iPlane] = fSegmentation->GetPlane(iPlane)->GetRMaxSupport();
373     fRPlaneMin[iPlane] = fSegmentation->GetPlane(iPlane)->GetRMinSupport();
374   }
375   
376   // Loading MFT clusters
377   fMFTLoader = fRunLoader->GetDetectorLoader("MFT");
378   fMFTLoader->LoadRecPoints("READ");
379   
380   fMFTClusterTree = fMFTLoader->TreeR();
381
382   Int_t nEventsInFile = fMuonRecoCheck->NumberOfEvents();
383   if (!nEventsInFile) {
384     AliError("no events available!!!\n");
385     return;
386   }
387   if (nEventsInFile<nEventsToAnalyze || nEventsToAnalyze<0) fNEventsToAnalyze = nEventsInFile;
388   else fNEventsToAnalyze = nEventsToAnalyze;
389
390   fCandidateTracks = new TClonesArray("AliMuonForwardTrack",50000);
391
392   // -------------------------- initializing histograms...
393
394   AliInfo("\ninitializing histograms...\n");
395   BookHistos();
396   SetTitleHistos();
397   AliInfo("... done!\n\n");
398
399   // -------------------------- initializing graphics...
400
401   AliInfo("initializing graphics...\n");
402   BookPlanes();
403   AliInfo("... done!\n\n");
404
405   SetSigmaSpectrometerCut(4.0);
406   SetSigmaClusterCut(4.5);
407   SetChi2GlobalCut(2.0);
408   SetNFinalCandidatesCut(10);
409   SetRAbsorberCut(26.4);
410   SetLowPtCut(0.5);
411   SetExtrapOriginTransvError(1.0);
412
413 }
414
415 //======================================================================================================================================
416
417 Bool_t AliMuonForwardTrackFinder::LoadNextEvent() {
418
419   // load next reconstructed event from the tree
420
421   if (fEv) FillOutputTree();
422
423   if (fEv>=fNEventsToAnalyze) return kFALSE;
424
425   fCountRealTracksAnalyzedOfEvent = 0;
426   
427   AliInfo(Form(" **** analyzing event # %d  \n", fEv));
428   
429   fTrackStore    = fMuonRecoCheck->ReconstructedTracks(fEv);
430   fTrackRefStore = fMuonRecoCheck->ReconstructibleTracks(fEv);
431   
432   fRunLoader->GetEvent(fEv);
433   if (!fMFTLoader->TreeR()->GetEvent()) return kFALSE;
434   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
435     AliDebug(1, Form("plane %02d: nClusters = %d\n", iPlane, (fMFT->GetRecPointsList(iPlane))->GetEntries()));
436     fMFTClusterArray[iPlane] = fMFT->GetRecPointsList(iPlane);
437   }
438   SeparateFrontBackClusters();
439
440   fRunLoader -> LoadKinematics();
441   fStack = fRunLoader->Stack();
442   fNextTrack = fTrackStore->CreateIterator();
443   fMuonForwardTracks->Clear();
444
445   fEv++;
446   
447   return kTRUE;
448
449 }
450
451 //======================================================================================================================================
452
453 Int_t AliMuonForwardTrackFinder::LoadNextTrack() {
454
455   fNPlanesMFTAnalyzed = 0;
456
457   // load next muon track from the reconstructed event
458
459   if (fCountRealTracksAnalyzed>fMaxNTracksToBeAnalyzed) return kFALSE;
460
461   if (!fCountRealTracksAnalyzed) if (!LoadNextEvent()) return kFALSE;
462   if (fCountRealTracksAnalyzed==fMaxNTracksToBeAnalyzed) {
463     fCountRealTracksAnalyzed++;
464     if (!LoadNextEvent()) return kFALSE;
465   }
466
467   while ( !(fMuonTrackReco = static_cast<AliMUONTrack*>(fNextTrack->Next())) ) if (!LoadNextEvent()) return kFALSE;
468
469   AliDebug(1, "**************************************************************************************\n");
470   AliDebug(1, Form("***************************   MUON TRACK %3d   ***************************************\n", fCountRealTracksAnalyzedOfEvent));
471   AliDebug(1, "**************************************************************************************\n");
472
473   fCountRealTracksAnalyzed++;
474
475   fCandidateTracks -> Clear();
476
477   fLabelMC = -1;
478   fDistanceFromGoodClusterAndTrackAtLastPlane = -1.;
479   fDistanceFromBestClusterAndTrackAtLastPlane = -1.;
480   ResetPlanes();
481
482   TIter nextTrackRef(fTrackRefStore->CreateIterator());
483   AliMUONTrack *trackRef=0;
484   
485   // --------------------------------------- loop on MC generated tracks to find the MC reference...
486   
487   while ( (trackRef = static_cast<AliMUONTrack*>(nextTrackRef())) ) {
488     // number of compatible clusters between trackReco and trackRef
489     Int_t nMatchCluster = fMuonTrackReco->FindCompatibleClusters(*trackRef, fSigmaSpectrometerCut, fIsClusterCompatible);  
490     if ( (fIsClusterCompatible[0] || fIsClusterCompatible[1] || fIsClusterCompatible[2] || fIsClusterCompatible[3]) &&   // before the dipole
491          (fIsClusterCompatible[6] || fIsClusterCompatible[7] || fIsClusterCompatible[8] || fIsClusterCompatible[9]) &&   // after the dipole
492          2*nMatchCluster>fMuonTrackReco->GetNClusters() ) {
493       fMuonTrackReco->SetMCLabel(trackRef->GetUniqueID());   // MC reference has been found for trackReco!
494       break;
495     }
496   }
497   
498   // ------------------------------------- ...done!
499
500   if (fMuonTrackReco->GetMCLabel()>=0) fCountRealTracksWithRefMC++;
501   
502   fLabelMC = fMuonTrackReco->GetMCLabel();
503
504   CheckCurrentMuonTrackable();
505
506   if (fMuonTrackReco->GetMatchTrigger()) fCountRealTracksWithRefMC_andTrigger++;
507   
508   // the track we are going to build, starting from fMuonTrackReco and adding the MFT clusters
509   AliMuonForwardTrack *track = new ((*fCandidateTracks)[0]) AliMuonForwardTrack();
510   track -> SetMUONTrack(fMuonTrackReco);
511   if (fLabelMC>=0 && fStack->Particle(fLabelMC)) track -> SetMCTrackRef(fStack->Particle(fLabelMC));
512   track -> SetMCLabel(fMuonTrackReco->GetMCLabel());
513   track -> SetMatchTrigger(fMuonTrackReco->GetMatchTrigger());
514   
515   // track parameters at the first tracking station in the Muon Spectrometer
516   AliMUONTrackParam *param = (AliMUONTrackParam*) (fMuonTrackReco->GetTrackParamAtCluster()->First());
517   Double_t ptSpectrometer = TMath::Sqrt(param->Px()*param->Px() + param->Py()*param->Py());
518   Double_t thetaSpectrometer = TMath::ATan(ptSpectrometer/param->Pz());
519   if (thetaSpectrometer<0.) thetaSpectrometer += TMath::Pi();
520   Double_t etaSpectrometer = -1.*TMath::Log(TMath::Tan(0.5*thetaSpectrometer));
521   //  fOutputQAFile->cd();
522   fHistPtSpectrometer -> Fill(ptSpectrometer);
523   
524   // if the transverse momentum in the Muon Spectrometer is smaller than the threshold, skip to the next track
525   if (ptSpectrometer < fLowPtCut) return 3;
526   
527   // track parameters linearly extrapolated from the first tracking station to the end of the absorber
528   AliMUONTrackParam trackParamEndOfAbsorber(*((AliMUONTrackParam*)(fMuonTrackReco->GetTrackParamAtCluster()->First())));
529   AliMUONTrackExtrap::ExtrapToZCov(&trackParamEndOfAbsorber, -503.);   // absorber extends from -90 to -503 cm
530   Double_t xEndOfAbsorber = trackParamEndOfAbsorber.GetNonBendingCoor();
531   Double_t yEndOfAbsorber = trackParamEndOfAbsorber.GetBendingCoor();
532   Double_t rAbsorber      = TMath::Sqrt(xEndOfAbsorber*xEndOfAbsorber + yEndOfAbsorber*yEndOfAbsorber);
533   //  fOutputQAFile->cd();
534   fHistRadiusEndOfAbsorber -> Fill(rAbsorber);
535   
536   // if the radial distance of the track at the end of the absorber is smaller than a radius corresponding to 
537   // 3 degrees as seen from the interaction point, skip to the next track
538   if (rAbsorber < fRAbsorberCut) return 4;
539   
540   //------------------------- NOW THE CYCLE OVER THE MFT PLANES STARTS ---------------------------------------
541   
542   for (Int_t iPlane=fNPlanesMFT-1; iPlane>=0; iPlane--) {          // *** do not reverse the order of this cycle!!! 
543                                                                    // *** this reflects the fact that the extrapolation is performed 
544                                                                    // *** starting from the last MFT plane back to the origin
545     
546     // --------- updating the array of tracks according to the clusters available in the i-th plane ---------
547     
548     fNPlanesMFTAnalyzed++;
549
550     if (fMatchingMode==kRealMatching) {
551       Int_t nTracksToBeAnalyzed = fCandidateTracks->GetEntriesFast();
552       for (Int_t iTrack=0; iTrack<nTracksToBeAnalyzed; iTrack++) {
553         fCurrentTrack = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(iTrack);
554         // if the old track is compatible with the new cluster, the track is updated and inserted as new track in the array 
555         // (several new tracks can be created for one old track)
556         FindClusterInPlane(iPlane);   
557         if ((fNPlanesMFTAnalyzed-fCurrentTrack->GetNMFTClusters())>fNMaxMissingMFTClusters || fIsPlaneMandatory[iPlane]) {
558           fCandidateTracks->Remove(fCurrentTrack);     // the old track is removed after the check;
559         }
560       }
561       fCandidateTracks->Compress();
562       if (fIsCurrentMuonTrackable) {
563         //      fOutputQAFile->cd();
564         fHistNTracksAfterExtrapolation[iPlane] -> Fill(fCandidateTracks->GetEntriesFast());
565       }
566     }
567
568     else if (fMatchingMode==kIdealMatching && fIsCurrentMuonTrackable) {
569       fCurrentTrack = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(0);
570       AliDebug(2, Form("plane %02d: fCandidateTracks->GetEntriesFast() = %d   fCandidateTracks->UncheckedAt(0) = %p   fCurrentTrack = %p\n", 
571                        iPlane, fCandidateTracks->GetEntriesFast(), fCandidateTracks->UncheckedAt(0), fCurrentTrack));
572       AttachGoodClusterInPlane(iPlane);
573     }
574
575   }      
576   
577   // -------------------------- END OF THE CYCLE OVER THE MFT PLANES --------------------------------------------
578   
579   AliDebug(1, "Finished cycle over planes");
580
581   Double_t momentum = ptSpectrometer * TMath::CosH(etaSpectrometer);
582   fTxtTrackMomentum = new TLatex(0.10, 0.70, Form("P_{spectro} = %3.1f GeV/c", momentum));
583
584   if (fMatchingMode==kIdealMatching) {
585     AliDebug(1, "Adding track to output tree...\n");
586     fFinalBestCandidate = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(0);
587     AliMuonForwardTrack *newTrack = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(0);
588     new ((*fMuonForwardTracks)[fMuonForwardTracks->GetEntries()]) AliMuonForwardTrack(*newTrack);
589     AliDebug(1, "...track added!\n");
590     fCandidateTracks->Clear();
591     fCountRealTracksAnalyzedOfEvent++;
592     fCountRealTracksAnalyzedWithFinalCandidates++;
593     PrintParticleHistory();
594     FillPlanesWithTrackHistory();
595
596     Double_t chi2AtPlane[fNMaxPlanes] = {0};
597     Int_t nGoodClusters = 0;
598     Int_t nMFTClusters  = fFinalBestCandidate->GetNMFTClusters();
599 //     Int_t nMUONClusters = fFinalBestCandidate->GetNMUONClusters();
600     Int_t plane = 0;
601     for (Int_t iCluster=0; iCluster<nMFTClusters; iCluster++) {
602       while (!fFinalBestCandidate->PlaneExists(plane)) plane++;
603       AliMFTCluster *localCluster = fFinalBestCandidate->GetMFTCluster(iCluster);
604       chi2AtPlane[plane] = localCluster->GetLocalChi2();
605       if (IsCorrectMatch(localCluster)) nGoodClusters++;
606 //       Int_t nClustersGlobalTrack = nMUONClusters + (nMFTClusters-iCluster);        // Muon Spectrometer clusters + clusters in the Vertex Telescope
607 //       Int_t ndfGlobalTrack = GetNDF(nClustersGlobalTrack);
608 //       chi2AtPlane[plane] /= Double_t(ndfGlobalTrack);
609       plane++;
610     }
611     for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
612       fTxtTrackChi2[iPlane] = new TLatex(0.55*fRPlaneMax[fNPlanesMFT-1], 
613                                          0.90*fRPlaneMax[fNPlanesMFT-1], 
614                                          Form("#chi^{2} = %3.1f", chi2AtPlane[iPlane]));
615     }
616     fTxtTrackFinalChi2 = new TLatex(0.20, 0.44, Form("#chi^{2}_{final} = %3.1f", chi2AtPlane[0]));
617
618     if (fDrawOption) DrawPlanes();
619     return 5;
620   }
621   
622   // If we have several final tracks, we must find the best candidate:
623
624   Int_t nFinalTracks = fCandidateTracks->GetEntriesFast();
625   AliDebug(1, Form("nFinalTracks = %d", nFinalTracks));
626
627   if (nFinalTracks) fCountRealTracksAnalyzedWithFinalCandidates++;
628   
629   Double_t theVariable_Best        = -1.;                    // variable defining the best candidate
630   Bool_t bestCandidateExists       = kFALSE;
631   Int_t nGoodClustersBestCandidate = 0;
632   Int_t idBestCandidate            = 0;
633   Double_t chi2HistoryForBestCandidate[fNMaxPlanes] = {0};  // chi2 on each plane, for the best candidate
634   Double_t nClustersPerPlane[fNMaxPlanes] = {0};
635   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
636     chi2HistoryForBestCandidate[iPlane] = -1.;
637     nClustersPerPlane[iPlane] = fMFTClusterArray[iPlane] -> GetEntries();
638   }
639   
640   fTxtFinalCandidates = new TLatex(0.10, 0.78, Form("N_{FinalCandidates} = %d", nFinalTracks));
641   
642   Int_t nClustersMC = 0;
643   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) nClustersMC += fIsGoodClusterInPlane[iPlane];
644
645   for (Int_t iTrack=0; iTrack<nFinalTracks; iTrack++) {
646     
647     AliMuonForwardTrack *finalTrack = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(iTrack);
648     
649     Double_t chi2AtPlane[fNMaxPlanes] = {0};
650     Int_t nGoodClusters = 0;
651     Int_t nMFTClusters  = finalTrack->GetNMFTClusters();
652 //     Int_t nMUONClusters = finalTrack->GetNMUONClusters();
653
654     Int_t plane = 0;
655     for (Int_t iCluster=0; iCluster<nMFTClusters; iCluster++) {
656       while (!finalTrack->PlaneExists(plane)) plane++;
657       AliMFTCluster *localCluster = finalTrack->GetMFTCluster(iCluster);
658       chi2AtPlane[plane] = localCluster->GetLocalChi2();
659       if (IsCorrectMatch(localCluster)) nGoodClusters++;
660 //       Int_t nClustersGlobalTrack = nMUONClusters + (nMFTClusters-iCluster);        // Muon Spectrometer clusters + clusters in the Vertex Telescope
661 //       Int_t ndfGlobalTrack = GetNDF(nClustersGlobalTrack);
662 //       chi2AtPlane[plane] /= Double_t(ndfGlobalTrack);
663       plane++;
664     }
665     
666     if (fIsCurrentMuonTrackable) {
667       //      fOutputQAFile->cd();
668       fHistNGoodClustersForFinalTracks -> Fill(nGoodClusters);
669     }
670
671     //    fOutputQAFile->cd();
672
673     Float_t finalCandidatesInfo[] = {Double_t(fRun),
674                                      Double_t(fEv),
675                                      Double_t(fCountRealTracksAnalyzedOfEvent),
676                                      Double_t(nFinalTracks),
677                                      Double_t(nClustersMC),
678                                      Double_t(nGoodClusters),
679                                      ptSpectrometer,
680                                      thetaSpectrometer,
681                                      etaSpectrometer, 
682                                      chi2AtPlane[0],
683                                      chi2AtPlane[1],
684                                      chi2AtPlane[2],
685                                      chi2AtPlane[3],
686                                      chi2AtPlane[4],
687                                      chi2AtPlane[5],
688                                      chi2AtPlane[6],
689                                      chi2AtPlane[7],
690                                      chi2AtPlane[8]};
691     
692     fNtuFinalCandidates -> Fill(finalCandidatesInfo);
693
694     // now comparing the tracks with various criteria, in order to find the best one
695     
696     Double_t theVariable = 0.;
697 //     theVariable = chi2AtPlane[0];
698     for (Int_t iCluster=0; iCluster<nMFTClusters; iCluster++) theVariable += chi2AtPlane[iCluster];
699     theVariable /= Double_t(nMFTClusters);
700     
701       
702     if (theVariable<theVariable_Best || theVariable_Best<0.) {
703       nGoodClustersBestCandidate = nGoodClusters;
704       for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) chi2HistoryForBestCandidate[iPlane] = chi2AtPlane[iPlane];
705       theVariable_Best = theVariable;
706       fTxtTrackFinalChi2 = new TLatex(0.20, 0.44, Form("#chi^{2}_{final} = %3.1f", chi2HistoryForBestCandidate[0]));
707       for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
708         fTxtTrackChi2[iPlane] = new TLatex(0.55*fRPlaneMax[fNPlanesMFT-1], 
709                                            0.90*fRPlaneMax[fNPlanesMFT-1], 
710                                            Form("#chi^{2} = %3.1f", chi2AtPlane[iPlane]));
711       }
712       idBestCandidate = iTrack;
713       bestCandidateExists=kTRUE;
714     }
715
716     // ----------------------------------------------------------
717
718   }
719
720   if (nFinalTracks) {
721     fFinalBestCandidate = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(idBestCandidate);
722     AliInfo(Form("fFinalBestCandidate->GetNMFTClusters() = %d\n",  fFinalBestCandidate->GetNMFTClusters()));
723     PrintParticleHistory();
724     FillPlanesWithTrackHistory();
725     AliMuonForwardTrack *newTrack = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(idBestCandidate);
726     newTrack -> SetNWrongClustersMC(newTrack->GetNMFTClusters() - nGoodClustersBestCandidate);
727     new ((*fMuonForwardTracks)[fMuonForwardTracks->GetEntries()]) AliMuonForwardTrack(*newTrack);
728   }
729
730   //  fOutputQAFile->cd();
731   
732   Float_t finalBestCandidatesInfo[] = {Double_t(fRun),
733                                        Double_t(fEv),
734                                        Double_t(fCountRealTracksAnalyzedOfEvent),
735                                        Double_t(nFinalTracks),
736                                        Double_t(nClustersMC),
737                                        Double_t(nGoodClustersBestCandidate),
738                                        ptSpectrometer,
739                                        thetaSpectrometer,
740                                        etaSpectrometer,
741                                        chi2HistoryForBestCandidate[0],
742                                        chi2HistoryForBestCandidate[1],
743                                        chi2HistoryForBestCandidate[2],
744                                        chi2HistoryForBestCandidate[3],
745                                        chi2HistoryForBestCandidate[4],
746                                        chi2HistoryForBestCandidate[5],
747                                        chi2HistoryForBestCandidate[6],
748                                        chi2HistoryForBestCandidate[7],
749                                        chi2HistoryForBestCandidate[8],
750                                        nClustersPerPlane[0],
751                                        nClustersPerPlane[1],
752                                        nClustersPerPlane[2],
753                                        nClustersPerPlane[3],
754                                        nClustersPerPlane[4],
755                                        nClustersPerPlane[5],
756                                        nClustersPerPlane[6],
757                                        nClustersPerPlane[7],
758                                        nClustersPerPlane[8]};
759   
760   fNtuFinalBestCandidates -> Fill(finalBestCandidatesInfo);
761   
762   if (fDrawOption && bestCandidateExists) {
763     fTxtTrackGoodClusters = new TLatex(0.20, 0.51, Form("N_{GoodClusters} = %d", nGoodClustersBestCandidate));
764     DrawPlanes();
765   }
766
767   if (fIsCurrentMuonTrackable) {
768     //    fOutputQAFile->cd();
769     if (nGoodClustersBestCandidate==5) fHistPtMuonTrackWithGoodMatch -> Fill(ptSpectrometer);
770     else                               fHistPtMuonTrackWithBadMatch  -> Fill(ptSpectrometer);
771   }
772
773   // -------------------------------------------------------------------------------------------
774
775   fCandidateTracks->Clear();
776   fFinalBestCandidate = NULL;
777   
778   fCountRealTracksAnalyzedOfEvent++;
779
780   return 5;
781   
782 }
783
784 //===========================================================================================================================================
785
786 void AliMuonForwardTrackFinder::FindClusterInPlane(Int_t planeId) { 
787   
788   AliDebug(2, Form(">>>> executing AliMuonForwardTrackFinder::FindClusterInPlane(%d)\n", planeId));
789
790   // !!!!!!!!! coordinates and errors on the interaction vertex should be taken from the event itself (ITS) if available
791
792   // propagate track to plane #planeId (both to front and back active sensors)
793   // look for compatible clusters
794   // update TrackParam at found cluster (if any) using Kalman Filter
795
796   AliMUONTrackParam currentParamFront, currentParamBack, currentParamForResearchFront, currentParamForResearchBack;
797
798   if (planeId == fNPlanesMFT-1) {      // last plane of the telecope
799     currentParamFront = (*((AliMUONTrackParam*)(fMuonTrackReco->GetTrackParamAtCluster()->First())));
800     currentParamBack  = (*((AliMUONTrackParam*)(fMuonTrackReco->GetTrackParamAtCluster()->First())));
801     currentParamForResearchFront = currentParamFront;
802     currentParamForResearchBack  = currentParamBack;
803     AliMUONTrackExtrap::ExtrapToVertexWithoutBranson(&currentParamFront, 0.); 
804     AliMUONTrackExtrap::ExtrapToVertexWithoutBranson(&currentParamBack,  0.); 
805     AliMUONTrackExtrap::ExtrapToVertex(&currentParamForResearchFront, 0., 0., gRandom->Gaus(0,fGaussianBlurZVert), fExtrapOriginTransvError, fExtrapOriginTransvError); 
806     AliMUONTrackExtrap::ExtrapToVertex(&currentParamForResearchBack,  0., 0., gRandom->Gaus(0,fGaussianBlurZVert), fExtrapOriginTransvError, fExtrapOriginTransvError); 
807   }
808   else {          // MFT planes others than the last one: mult. scattering correction because of the upstream MFT planes is performed
809     currentParamFront = (*((AliMUONTrackParam*)(fCurrentTrack->GetTrackParamAtCluster()->First())));
810     currentParamBack  = (*((AliMUONTrackParam*)(fCurrentTrack->GetTrackParamAtCluster()->First())));
811     currentParamForResearchFront = currentParamFront;
812     currentParamForResearchBack  = currentParamBack;
813     AliMUONTrackExtrap::AddMCSEffect(&currentParamFront,           (fSegmentation->GetPlane(planeId+1)->GetEquivalentSilicon()+
814                                                                     fSegmentation->GetPlane(planeId)->GetEquivalentSiliconBeforeFront())/fRadLengthSi,-1.);
815     AliMUONTrackExtrap::AddMCSEffect(&currentParamForResearchFront,(fSegmentation->GetPlane(planeId+1)->GetEquivalentSilicon()+
816                                                                     fSegmentation->GetPlane(planeId)->GetEquivalentSiliconBeforeFront())/fRadLengthSi,-1.);
817     AliMUONTrackExtrap::AddMCSEffect(&currentParamBack,            (fSegmentation->GetPlane(planeId+1)->GetEquivalentSilicon()+
818                                                                     fSegmentation->GetPlane(planeId)->GetEquivalentSiliconBeforeBack())/fRadLengthSi,-1.);
819     AliMUONTrackExtrap::AddMCSEffect(&currentParamForResearchBack, (fSegmentation->GetPlane(planeId+1)->GetEquivalentSilicon()+
820                                                                     fSegmentation->GetPlane(planeId)->GetEquivalentSiliconBeforeBack())/fRadLengthSi,-1.);
821   }
822   // for all planes: extrapolation to the Z of the plane
823   AliMUONTrackExtrap::ExtrapToZCov(&currentParamFront,            -1.*fSegmentation->GetPlane(planeId)->GetZCenterActiveFront());   
824   AliMUONTrackExtrap::ExtrapToZCov(&currentParamForResearchFront, -1.*fSegmentation->GetPlane(planeId)->GetZCenterActiveFront());
825   AliMUONTrackExtrap::ExtrapToZCov(&currentParamBack,             -1.*fSegmentation->GetPlane(planeId)->GetZCenterActiveBack());   
826   AliMUONTrackExtrap::ExtrapToZCov(&currentParamForResearchBack,  -1.*fSegmentation->GetPlane(planeId)->GetZCenterActiveBack());
827
828   //---------------------------------------------------------------------------------------
829
830   TMatrixD covFront(5,5); covFront = currentParamForResearchFront.GetCovariances();
831   TMatrixD covBack(5,5);  covBack  = currentParamForResearchBack.GetCovariances();
832   
833   Double_t squaredError_X_Front = covFront(0,0);
834   Double_t squaredError_Y_Front = covFront(2,2);
835   Double_t squaredError_X_Back  = covBack(0,0);
836   Double_t squaredError_Y_Back  = covBack(2,2);
837
838   Double_t corrFact = 1.0;
839
840   Double_t researchRadiusFront = TMath::Sqrt(squaredError_X_Front + squaredError_Y_Front);
841   Double_t researchRadiusBack  = TMath::Sqrt(squaredError_X_Back  + squaredError_Y_Back);
842   if (planeId==fNPlanesMFT-1 && 0.5*(researchRadiusFront+researchRadiusBack)<fMinResearchRadiusAtLastPlane) {
843     corrFact = fMinResearchRadiusAtLastPlane/(0.5*(researchRadiusFront+researchRadiusBack));
844   }
845   if (fIsCurrentMuonTrackable) {
846     //    fOutputQAFile->cd();
847     fHistResearchRadius[planeId] -> Fill(0.5*(researchRadiusFront+researchRadiusBack));
848   }
849
850   Double_t position_X_Front = currentParamForResearchFront.GetNonBendingCoor();
851   Double_t position_Y_Front = currentParamForResearchFront.GetBendingCoor();
852   Double_t position_X_Back = currentParamForResearchBack.GetNonBendingCoor();
853   Double_t position_Y_Back = currentParamForResearchBack.GetBendingCoor();
854   Double_t radialPositionOfTrackFront = TMath::Sqrt(position_X_Front*position_X_Front + position_Y_Front*position_Y_Front);
855   Double_t radialPositionOfTrackBack  = TMath::Sqrt(position_X_Back*position_X_Back   + position_Y_Back*position_Y_Back);
856
857   //---------------------------------------------------------------------------------------
858
859   Double_t chi2cut = 2.*fSigmaClusterCut*fSigmaClusterCut;     // depends on the number of variables (here, 2)
860   
861   // Analyizing the clusters: FRONT ACTIVE ELEMENTS
862   
863   Int_t nClustersFront = fMFTClusterArrayFront[planeId]->GetEntries();
864   AliDebug(2, Form("There are %3d clusters in plane %02d FRONT\n", nClustersFront, planeId));
865   
866   for (Int_t iCluster=0; iCluster<nClustersFront; iCluster++) {
867
868     Bool_t isGoodChi2 = kFALSE;
869
870     AliMFTCluster *cluster = (AliMFTCluster*) fMFTClusterArrayFront[planeId]->At(iCluster); 
871     Double_t chi2 = (1./(corrFact*corrFact)) * TryOneCluster(currentParamForResearchFront, cluster);     // describes the compatibility between the track and the cluster
872     if (chi2<chi2cut) isGoodChi2 = kTRUE;
873
874     Double_t radialPositionOfClusterFront = TMath::Sqrt(cluster->GetX()*cluster->GetX() + cluster->GetY()*cluster->GetY());    
875     if (planeId == fNPlanesMFT-1) {
876       if (TMath::Abs(radialPositionOfTrackFront-radialPositionOfClusterFront)<fDistanceFromBestClusterAndTrackAtLastPlane ||
877           fDistanceFromBestClusterAndTrackAtLastPlane<0.) {
878         fDistanceFromBestClusterAndTrackAtLastPlane = TMath::Abs(radialPositionOfTrackFront-radialPositionOfClusterFront);
879       }
880       if (IsCorrectMatch(cluster)) {
881         fDistanceFromGoodClusterAndTrackAtLastPlane = TMath::Abs(radialPositionOfTrackFront-radialPositionOfClusterFront);
882       }
883     }
884
885     if (fIsCurrentMuonTrackable) {
886       //      fOutputQAFile->cd();
887       if (IsCorrectMatch(cluster)) fHistChi2Cluster_GoodCluster[planeId]->Fill(chi2/2.);     //  chi2/ndf
888       else                         fHistChi2Cluster_BadCluster[planeId] ->Fill(chi2/2.);     //  chi2/ndf
889     }
890
891     if (isGoodChi2) {
892       AliDebug(3, Form("accepting cluster: chi2=%f (cut = %f)\n", chi2, chi2cut));
893       AliMuonForwardTrack *newTrack = new ((*fCandidateTracks)[fCandidateTracks->GetEntriesFast()]) AliMuonForwardTrack(*fCurrentTrack);
894       newTrack->AddTrackParamAtMFTCluster(currentParamFront, *cluster);    // creating new track param and attaching the cluster
895       AliDebug(1, Form("After plane %02d: newTrack->GetNMFTClusters() = %d (fCurrentTrack->GetNMFTClusters() = %d)", 
896                        planeId, newTrack->GetNMFTClusters(), fCurrentTrack->GetNMFTClusters()));
897       newTrack->SetPlaneExists(planeId);
898       AliDebug(2, Form("current muon is trackable: %d\n", fIsCurrentMuonTrackable));
899       if (fIsCurrentMuonTrackable) {
900         Double_t newGlobalChi2 = ((AliMUONTrackParam*) newTrack->GetTrackParamAtCluster()->First())->GetTrackChi2();
901         AliDebug(2, Form("new chi2 = %f (= %f)\n", newGlobalChi2, newTrack->GetMFTCluster(0)->GetTrackChi2()));
902         Int_t nClustersGlobalTrack = newTrack->GetNMUONClusters() + newTrack->GetNMFTClusters();        // Muon Spectrometer clusters + clusters in the Vertex Telescope
903         Int_t ndfGlobalTrack = GetNDF(nClustersGlobalTrack);
904         //      fOutputQAFile->cd();
905         if (IsCorrectMatch(cluster)) fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[planeId]->Fill(newGlobalChi2/Double_t(ndfGlobalTrack));
906         else                         fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[planeId] ->Fill(newGlobalChi2/Double_t(ndfGlobalTrack));
907       }
908       fGrMFTPlane[kClustersGoodChi2][planeId] -> SetPoint(fGrMFTPlane[kClustersGoodChi2][planeId]->GetN(), cluster->GetX(), cluster->GetY());
909     }
910     else AliDebug(3, Form("discarding cluster: chi2=%f (cut = %f)\n", chi2, chi2cut));
911
912   }
913
914   // Analyizing the clusters: BACK ACTIVE ELEMENTS
915   
916   Int_t nClustersBack = fMFTClusterArrayBack[planeId]->GetEntries();
917   AliDebug(2, Form("There are %3d clusters in plane %02d BACK\n", nClustersBack, planeId));
918   
919   for (Int_t iCluster=0; iCluster<nClustersBack; iCluster++) {
920
921     Bool_t isGoodChi2 = kFALSE;
922
923     AliMFTCluster *cluster = (AliMFTCluster*) fMFTClusterArrayBack[planeId]->At(iCluster); 
924     Double_t chi2 = (1./(corrFact*corrFact)) * TryOneCluster(currentParamForResearchBack, cluster);     // describes the compatibility between the track and the cluster
925     if (chi2<chi2cut) isGoodChi2 = kTRUE;
926
927     Double_t radialPositionOfClusterBack = TMath::Sqrt(cluster->GetX()*cluster->GetX() + cluster->GetY()*cluster->GetY());    
928     if (planeId == fNPlanesMFT-1) {
929       if (TMath::Abs(radialPositionOfTrackBack-radialPositionOfClusterBack)<fDistanceFromBestClusterAndTrackAtLastPlane ||
930           fDistanceFromBestClusterAndTrackAtLastPlane<0.) {
931         fDistanceFromBestClusterAndTrackAtLastPlane = TMath::Abs(radialPositionOfTrackBack-radialPositionOfClusterBack);
932       }
933       if (IsCorrectMatch(cluster)) {
934         fDistanceFromGoodClusterAndTrackAtLastPlane = TMath::Abs(radialPositionOfTrackBack-radialPositionOfClusterBack);
935       }
936     }
937
938     if (fIsCurrentMuonTrackable) {
939       //      fOutputQAFile->cd();
940       if (IsCorrectMatch(cluster)) fHistChi2Cluster_GoodCluster[planeId]->Fill(chi2/2.);     //  chi2/ndf
941       else                         fHistChi2Cluster_BadCluster[planeId] ->Fill(chi2/2.);     //  chi2/ndf
942     }
943
944     if (isGoodChi2) {
945       AliDebug(3,Form("accepting cluster: chi2=%f (cut = %f)\n", chi2, chi2cut));
946       AliMuonForwardTrack *newTrack = new ((*fCandidateTracks)[fCandidateTracks->GetEntriesFast()]) AliMuonForwardTrack(*fCurrentTrack);
947       newTrack->AddTrackParamAtMFTCluster(currentParamBack, *cluster);    // creating new track param and attaching the cluster
948       AliDebug(1, Form("After plane %02d: newTrack->GetNMFTClusters() = %d (fCurrentTrack->GetNMFTClusters() = %d)", 
949                        planeId, newTrack->GetNMFTClusters(), fCurrentTrack->GetNMFTClusters()));
950       newTrack->SetPlaneExists(planeId);
951       AliDebug(2, Form("current muon is trackable: %d\n", fIsCurrentMuonTrackable));
952       if (fIsCurrentMuonTrackable) {
953         Double_t newGlobalChi2 = ((AliMUONTrackParam*) newTrack->GetTrackParamAtCluster()->First())->GetTrackChi2();
954         AliDebug(2, Form("new chi2 = %f (= %f)\n", newGlobalChi2, newTrack->GetMFTCluster(0)->GetTrackChi2()));
955         Int_t nClustersGlobalTrack = newTrack->GetNMUONClusters() + newTrack->GetNMFTClusters();        // Muon Spectrometer clusters + clusters in the Vertex Telescope
956         Int_t ndfGlobalTrack = GetNDF(nClustersGlobalTrack);
957         //      fOutputQAFile->cd();
958         if (IsCorrectMatch(cluster)) fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[planeId]->Fill(newGlobalChi2/Double_t(ndfGlobalTrack));
959         else                         fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[planeId] ->Fill(newGlobalChi2/Double_t(ndfGlobalTrack));
960       }
961       fGrMFTPlane[kClustersGoodChi2][planeId] -> SetPoint(fGrMFTPlane[kClustersGoodChi2][planeId]->GetN(), cluster->GetX(), cluster->GetY());
962     }
963     else AliDebug(3,Form("discarding cluster: chi2=%f (cut = %f)\n", chi2, chi2cut));
964
965   }
966
967   //---------------------------------------------------------------------------------------------
968
969   if (planeId == fNPlanesMFT-1) {
970     if (fIsCurrentMuonTrackable && fDistanceFromGoodClusterAndTrackAtLastPlane>0.) {
971       //      fOutputQAFile->cd();
972       fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane -> Fill(TMath::Abs(fDistanceFromBestClusterAndTrackAtLastPlane-
973                                                                                                        fDistanceFromGoodClusterAndTrackAtLastPlane));
974       fHistDistanceGoodClusterFromTrackAtLastPlane -> Fill(fDistanceFromGoodClusterAndTrackAtLastPlane);
975     }
976   }
977   
978 }
979
980 //==========================================================================================================================================
981
982 void AliMuonForwardTrackFinder::AttachGoodClusterInPlane(Int_t planeId) { 
983   
984   AliDebug(1, Form(">>>> executing AliMuonForwardTrackFinder::AttachGoodClusterInPlane(%d)\n", planeId));
985
986   AliMUONTrackParam currentParamFront, currentParamBack;
987
988   if (planeId == fNPlanesMFT-1) {      // last plane of the telecope
989     currentParamFront = (*((AliMUONTrackParam*)(fMuonTrackReco->GetTrackParamAtCluster()->First())));
990     currentParamBack  = (*((AliMUONTrackParam*)(fMuonTrackReco->GetTrackParamAtCluster()->First())));
991     AliMUONTrackExtrap::ExtrapToVertexWithoutBranson(&currentParamFront, 0.); 
992     AliMUONTrackExtrap::ExtrapToVertexWithoutBranson(&currentParamBack,  0.); 
993   }
994   else {          // MFT planes others than the last one: mult. scattering correction because of the upstream MFT planes is performed
995     AliDebug(2, Form("fCurrentTrack = %p\n", fCurrentTrack));
996     currentParamFront = (*((AliMUONTrackParam*)(fCurrentTrack->GetTrackParamAtCluster()->First())));
997     currentParamBack  = (*((AliMUONTrackParam*)(fCurrentTrack->GetTrackParamAtCluster()->First())));
998     AliMUONTrackExtrap::AddMCSEffect(&currentParamFront, (fSegmentation->GetPlane(planeId+1)->GetEquivalentSilicon()+
999                                                           fSegmentation->GetPlane(planeId)->GetEquivalentSiliconBeforeFront())/fRadLengthSi,-1.);
1000     AliMUONTrackExtrap::AddMCSEffect(&currentParamBack,  (fSegmentation->GetPlane(planeId+1)->GetEquivalentSilicon()+
1001                                                           fSegmentation->GetPlane(planeId)->GetEquivalentSiliconBeforeBack())/fRadLengthSi,-1.);
1002   }
1003   // for all planes: linear extrapolation to the Z of the plane
1004   AliMUONTrackExtrap::ExtrapToZCov(&currentParamFront, -1.*fSegmentation->GetPlane(planeId)->GetZCenterActiveFront());   
1005   AliMUONTrackExtrap::ExtrapToZCov(&currentParamBack,  -1.*fSegmentation->GetPlane(planeId)->GetZCenterActiveBack());   
1006
1007   Bool_t goodClusterFound = kFALSE;
1008   
1009   // Analyizing the clusters: FRONT ACTIVE ELEMENTS
1010
1011   Int_t nClustersFront = fMFTClusterArrayFront[planeId]->GetEntries();
1012   
1013   AliDebug(1, Form("nClustersFront = %d\n", nClustersFront));
1014   for (Int_t iCluster=0; iCluster<nClustersFront; iCluster++) {
1015     AliMFTCluster *cluster = (AliMFTCluster*) fMFTClusterArrayFront[planeId]->UncheckedAt(iCluster);
1016     AliDebug(2, Form("checking cluster %02d of %02d: cluter=%p, fCurrentTrack=%p\n", iCluster, nClustersFront, cluster, fCurrentTrack));
1017     if (IsCorrectMatch(cluster)) {
1018       fCurrentTrack->AddTrackParamAtMFTCluster(currentParamFront, *cluster);  // creating new track param and attaching the cluster
1019       fCurrentTrack->SetPlaneExists(planeId);
1020       goodClusterFound = kTRUE;
1021       break;
1022     }
1023   }
1024
1025   if (goodClusterFound) return;
1026
1027   // Analyizing the clusters: BACK ACTIVE ELEMENTS
1028
1029   Int_t nClustersBack = fMFTClusterArrayBack[planeId]->GetEntries();
1030   
1031   AliDebug(1, Form("nClustersBack = %d\n", nClustersBack));
1032   for (Int_t iCluster=0; iCluster<nClustersBack; iCluster++) {
1033     AliMFTCluster *cluster = (AliMFTCluster*) fMFTClusterArrayBack[planeId]->UncheckedAt(iCluster);
1034     AliDebug(2,Form("checking cluster %02d of %02d: cluter=%p, fCurrentTrack=%p\n", iCluster, nClustersBack, cluster, fCurrentTrack));
1035     if (IsCorrectMatch(cluster)) {
1036       fCurrentTrack->AddTrackParamAtMFTCluster(currentParamBack, *cluster);  // creating new track param and attaching the cluster
1037       fCurrentTrack->SetPlaneExists(planeId);
1038       goodClusterFound = kTRUE;
1039       break;
1040     }
1041   }
1042
1043 }
1044
1045 //==========================================================================================================================================
1046
1047 void AliMuonForwardTrackFinder::CheckCurrentMuonTrackable() {
1048
1049   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1050     fIsGoodClusterInPlane[iPlane] = kFALSE;
1051     Int_t nClusters = fMFTClusterArray[iPlane]->GetEntriesFast();
1052     for (Int_t iCluster=0; iCluster<nClusters; iCluster++) {
1053       AliMFTCluster *cluster = (AliMFTCluster*) fMFTClusterArray[iPlane]->At(iCluster); 
1054       for (Int_t iTrack=0; iTrack<cluster->GetNMCTracks(); iTrack++) {
1055         if (cluster->GetMCLabel(iTrack)==fLabelMC) {
1056           fIsGoodClusterInPlane[iPlane] = kTRUE;
1057           break;
1058         }
1059       }
1060     }
1061   }
1062
1063   fIsCurrentMuonTrackable = kTRUE;
1064   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) fIsCurrentMuonTrackable = (fIsCurrentMuonTrackable&&fIsGoodClusterInPlane[iPlane]);
1065
1066 }
1067
1068 //==========================================================================================================================================
1069
1070 void AliMuonForwardTrackFinder::FillPlanesWithTrackHistory() { 
1071   
1072   // Fill planes with the clusters
1073
1074   Int_t cluster = 0;
1075   AliDebug(2, Form("fFinalBestCandidate->GetNMFTClusters() = %d\n",  fFinalBestCandidate->GetNMFTClusters()));
1076   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1077     if (fFinalBestCandidate->PlaneExists(iPlane)) {
1078       AliMFTCluster *trackCluster = fFinalBestCandidate->GetMFTCluster(cluster++);
1079       fGrMFTPlane[kClusterOfTrack][iPlane] -> SetPoint(fGrMFTPlane[kClusterOfTrack][iPlane]->GetN(), trackCluster->GetX(), trackCluster->GetY());
1080     }
1081     Int_t nClusters = fMFTClusterArray[iPlane]->GetEntriesFast();
1082     for (Int_t iCluster=0; iCluster<nClusters; iCluster++) {
1083       AliMFTCluster *myCluster = (AliMFTCluster*) fMFTClusterArray[iPlane]->UncheckedAt(iCluster); 
1084       fGrMFTPlane[kAllClusters][iPlane] -> SetPoint(fGrMFTPlane[kAllClusters][iPlane]->GetN(), myCluster->GetX(), myCluster->GetY());
1085       if (IsCorrectMatch(myCluster)) {
1086         fGrMFTPlane[kClusterCorrectMC][iPlane] -> SetPoint(fGrMFTPlane[kClusterCorrectMC][iPlane]->GetN(), myCluster->GetX(), myCluster->GetY());
1087       }
1088     }
1089   }
1090
1091 }
1092
1093 //======================================================================================================================================
1094
1095 Bool_t AliMuonForwardTrackFinder::IsCorrectMatch(AliMFTCluster *cluster) {
1096
1097   Bool_t result = kFALSE;
1098
1099   // check if the cluster belongs to the correct MC track
1100
1101   for (Int_t iTrack=0; iTrack<cluster->GetNMCTracks(); iTrack++) {
1102     if (cluster->GetMCLabel(iTrack)==fLabelMC) {
1103       result = kTRUE;
1104       break;
1105     }
1106   }
1107
1108   AliDebug(2,Form("returning %d\n", result));
1109
1110   return result;
1111
1112 }
1113
1114 //======================================================================================================================================
1115
1116 Double_t AliMuonForwardTrackFinder::TryOneCluster(const AliMUONTrackParam &trackParam, AliMFTCluster *cluster) {
1117
1118   // Test the compatibility between the track and the cluster (using trackParam's covariance matrix):
1119   // return the corresponding Chi2
1120   // assume the track parameters are given at the Z of the cluster
1121   
1122   // Set differences between trackParam and cluster in the bending and non bending directions
1123   Double_t dX = cluster->GetX() - trackParam.GetNonBendingCoor();
1124   Double_t dY = cluster->GetY() - trackParam.GetBendingCoor();
1125   AliDebug(3,Form("dX = %f, dY = %f\n", dX, dY));
1126   
1127   // Calculate errors and covariances
1128   const TMatrixD& kParamCov = trackParam.GetCovariances();
1129   Double_t sigmaX2 = kParamCov(0,0) + cluster->GetErrX2();
1130   Double_t sigmaY2 = kParamCov(2,2) + cluster->GetErrY2();
1131   AliDebug(3, Form("dX2 = %f, dY2 = %f\n", sigmaX2, sigmaY2));
1132   Double_t covXY   = kParamCov(0,2);
1133   Double_t det     = sigmaX2 * sigmaY2 - covXY * covXY;
1134   
1135   // Compute chi2
1136   if (det==0.) return 1.e10;
1137   return (dX*dX*sigmaY2 + dY*dY*sigmaX2 - 2.*dX*dY*covXY) / det;
1138   
1139 }
1140
1141 //=========================================================================================================================================
1142
1143 void AliMuonForwardTrackFinder::SeparateFrontBackClusters() {
1144
1145   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1146     fMFTClusterArrayFront[iPlane]->Clear();
1147     fMFTClusterArrayBack[iPlane] ->Clear();
1148     for (Int_t iCluster=0; iCluster<fMFTClusterArray[iPlane]->GetEntries(); iCluster++) {
1149       AliMFTCluster *cluster = (AliMFTCluster*) fMFTClusterArray[iPlane]->At(iCluster);
1150       if (TMath::Abs(cluster->GetZ())<TMath::Abs(fSegmentation->GetPlane(iPlane)->GetZCenter())) {
1151         new ((*fMFTClusterArrayFront[iPlane])[fMFTClusterArrayFront[iPlane]->GetEntries()]) AliMFTCluster(*cluster);
1152       }
1153       else {
1154         new ((*fMFTClusterArrayBack[iPlane])[fMFTClusterArrayBack[iPlane]->GetEntries()]) AliMFTCluster(*cluster);
1155       }
1156     }
1157   }
1158
1159 }
1160
1161 //=========================================================================================================================================
1162
1163 Int_t AliMuonForwardTrackFinder::GetNDF(Int_t nClusters) {
1164
1165   // the same definition as in AliMUONTrack is implemented, since here we just add more clusters to the Muon track
1166   
1167   Int_t ndf = 2 * nClusters - 5;
1168   return (ndf > 0) ? ndf : 0;
1169
1170 }
1171
1172 //============================================================================================================================================
1173
1174 void AliMuonForwardTrackFinder::BookHistos() {
1175
1176   const Int_t nMaxNewTracks[]  = {150,     200,   250, 600, 1000};
1177   const Double_t radiusPlane[] = {0.010, 0.010, 0.050, 0.5,  1.5};
1178
1179   fHistPtSpectrometer = new TH1D("hPtSpectrometer", "p_{T} as given by the Muon Spectrometer", 200, 0, 20.); 
1180
1181   fHistPtMuonTrackWithGoodMatch = new TH1D("fHistPtMuonTrackWithGoodMatch", "p_{T} of muon track with good match", 200, 0, 20.); 
1182   fHistPtMuonTrackWithBadMatch  = new TH1D("fHistPtMuonTrackWithBadMatch",  "p_{T} of muon track with bad match",  200, 0, 20.); 
1183
1184   fHistRadiusEndOfAbsorber = new TH1D("hRadiusEndOfAbsorber", "Track radial distance at the end of the absorber",  1000, 0, 100.); 
1185
1186   fHistNGoodClustersForFinalTracks = new TH1D("hNGoodClustersForFinalTracks", "Number of Good Clusters per Final Track", 20, -0.25, 9.75);
1187
1188   fHistDistanceGoodClusterFromTrackAtLastPlane = new TH1D("hDistanceGoodClusterFromTrackAtLastPlane",
1189                                                           "Distance of MC Good Cluster from Track in last MFT plane", 200, 0., 2.);
1190   
1191   fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane = 
1192     new TH1D("hDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane",
1193              "Good Cluster distance from track - Best Cluster distance from track in last MFT plane", 200, 0., 2.);
1194   
1195   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1196     
1197     fHistNTracksAfterExtrapolation[iPlane] = new TH1D(Form("hNTracksAfterExtrapolation_pl%02d", iPlane),
1198                                                       Form("Number of Candidates after analysis of MFT plane %02d", iPlane),
1199                                                       nMaxNewTracks[iPlane], -0.5, nMaxNewTracks[iPlane]-0.5);
1200     
1201     fHistResearchRadius[iPlane] = new TH1D(Form("hResearchRadius_pl%02d", iPlane),
1202                                            Form("Research Radius for candidate clusters in MFT plane %02d", iPlane),
1203                                            1000, 0., radiusPlane[iPlane]);
1204     
1205     fHistChi2Cluster_GoodCluster[iPlane] = new TH1D(Form("hChi2Cluster_GoodCluster_pl%02d", iPlane),
1206                                                     Form("#chi^{2}_{clust} for Good clusters in MFT plane %02d", iPlane),
1207                                                     100, 0., 15.);
1208     
1209     fHistChi2Cluster_BadCluster[iPlane] = new TH1D(Form("hChi2Cluster_BadCluster_pl%02d", iPlane),
1210                                                    Form("#chi^{2}_{clust} for Bad clusters in MFT plane %02d", iPlane),
1211                                                    100, 0., 15.);
1212
1213     fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[iPlane] = new TH1D(Form("fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons_pl%02d", iPlane),
1214                                                                                  Form("#chi^{2}/ndf at plane %d for GOOD candidates of trackable muons",iPlane),
1215                                                                                  100, 0., 15.);
1216     
1217     fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[iPlane] = new TH1D(Form("fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons_pl%02d", iPlane),
1218                                                                                 Form("#chi^{2}/ndf at plane %d for BAD candidates of trackable muons",iPlane),
1219                                                                                 100, 0., 15.);
1220     
1221   }
1222   
1223   //------------------------------------------
1224   
1225   fHistPtSpectrometer               -> Sumw2();
1226   fHistPtMuonTrackWithGoodMatch     -> Sumw2();
1227   fHistPtMuonTrackWithBadMatch      -> Sumw2();
1228   fHistRadiusEndOfAbsorber          -> Sumw2();
1229   fHistNGoodClustersForFinalTracks  -> Sumw2();
1230
1231   fHistDistanceGoodClusterFromTrackAtLastPlane                                  -> Sumw2();  
1232   fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane -> Sumw2();  
1233
1234   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1235     
1236     fHistNTracksAfterExtrapolation[iPlane] -> Sumw2();
1237     fHistResearchRadius[iPlane]            -> Sumw2();
1238     
1239     fHistChi2Cluster_GoodCluster[iPlane]        -> Sumw2();
1240     fHistChi2Cluster_BadCluster[iPlane]         -> Sumw2();
1241
1242     fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[iPlane] -> Sumw2();
1243     fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[iPlane]  -> Sumw2();
1244     
1245   }
1246
1247   fNtuFinalCandidates     = new TNtuple("ntuFinalCandidates",     "Final Candidates (ALL)", "run:event:muonTrack:nFinalCandidates:nClustersMC:nGoodClusters:ptSpectrometer:thetaSpectrometer:etaSpectrometer:chi2AtPlane0:chi2AtPlane1:chi2AtPlane2:chi2AtPlane3:chi2AtPlane4:chi2AtPlane5:chi2AtPlane6:chi2AtPlane7:chi2AtPlane8");
1248
1249   fNtuFinalBestCandidates = new TNtuple("ntuFinalBestCandidates", "Final Best Candidates",  "run:event:muonTrack:nFinalCandidates:nClustersMC:nGoodClusters:ptSpectrometer:thetaSpectrometer:etaSpectrometer:chi2AtPlane0:chi2AtPlane1:chi2AtPlane2:chi2AtPlane3:chi2AtPlane4:chi2AtPlane5:chi2AtPlane6:chi2AtPlane7:chi2AtPlane8:nClustersAtPlane0:nClustersAtPlane1:nClustersAtPlane2:nClustersAtPlane3:nClustersAtPlane4:nClustersAtPlane5:nClustersAtPlane6:nClustersAtPlane7:nClustersAtPlane8");
1250
1251 }
1252
1253 //============================================================================================================================================
1254
1255 void AliMuonForwardTrackFinder::SetTitleHistos() {
1256
1257   fHistPtSpectrometer              -> SetXTitle("p_{T}  [GeV/c]");
1258   fHistPtMuonTrackWithGoodMatch    -> SetXTitle("p_{T}  [GeV/c]");
1259   fHistPtMuonTrackWithBadMatch     -> SetXTitle("p_{T}  [GeV/c]");
1260   fHistRadiusEndOfAbsorber         -> SetXTitle("R_{abs}  [cm]");
1261   fHistNGoodClustersForFinalTracks -> SetXTitle("N_{GoodClusters}");
1262
1263   fHistDistanceGoodClusterFromTrackAtLastPlane                                  -> SetXTitle("Distance  [cm]");  
1264   fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane -> SetXTitle("Distance  [cm]");  
1265
1266
1267   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1268     
1269     fHistNTracksAfterExtrapolation[iPlane] -> SetXTitle("N_{tracks}");
1270     fHistResearchRadius[iPlane]            -> SetXTitle("Research Radius  [cm]");
1271     
1272     fHistChi2Cluster_GoodCluster[iPlane]         -> SetXTitle("#chi^{2}/ndf");
1273     fHistChi2Cluster_BadCluster[iPlane]          -> SetXTitle("#chi^{2}/ndf");
1274
1275     fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[iPlane] -> SetXTitle("#chi^{2}/ndf");
1276     fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[iPlane]  -> SetXTitle("#chi^{2}/ndf");
1277     
1278   }
1279
1280 }
1281
1282 //===========================================================================================================================================
1283
1284 void AliMuonForwardTrackFinder::BookPlanes() {
1285
1286   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1287     fGrMFTPlane[kAllClusters][iPlane] = new TGraph();
1288     fGrMFTPlane[kAllClusters][iPlane] -> SetName(Form("fGrMFTPlane_%02d_AllClusters",iPlane));
1289     fGrMFTPlane[kAllClusters][iPlane] -> SetMarkerStyle(20);
1290     //    fGrMFTPlane[kAllClusters][iPlane] -> SetMarkerSize(0.5);
1291     //    fGrMFTPlane[kAllClusters][iPlane] -> SetMarkerSize(0.3);
1292     fGrMFTPlane[kAllClusters][iPlane] -> SetMarkerSize(0.2);
1293   }
1294
1295   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1296     fGrMFTPlane[kClustersGoodChi2][iPlane] = new TGraph();
1297     fGrMFTPlane[kClustersGoodChi2][iPlane] -> SetName(Form("fGrMFTPlane_%02d_ClustersGoodChi2",iPlane));
1298     fGrMFTPlane[kClustersGoodChi2][iPlane] -> SetMarkerStyle(20);
1299     //    fGrMFTPlane[kClustersGoodChi2][iPlane] -> SetMarkerSize(0.8);
1300     //    fGrMFTPlane[kClustersGoodChi2][iPlane] -> SetMarkerSize(0.4);
1301     fGrMFTPlane[kClustersGoodChi2][iPlane] -> SetMarkerSize(0.3);
1302     fGrMFTPlane[kClustersGoodChi2][iPlane] -> SetMarkerColor(kBlue);
1303   }
1304
1305   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1306     fGrMFTPlane[kClusterOfTrack][iPlane] = new TGraph();
1307     fGrMFTPlane[kClusterOfTrack][iPlane] -> SetName(Form("fGrMFTPlane_%02d_ClustersOfTrack",iPlane));
1308     fGrMFTPlane[kClusterOfTrack][iPlane] -> SetMarkerStyle(25);
1309     //    fGrMFTPlane[kClusterOfTrack][iPlane] -> SetMarkerSize(1.2);
1310     fGrMFTPlane[kClusterOfTrack][iPlane] -> SetMarkerSize(0.9);
1311     fGrMFTPlane[kClusterOfTrack][iPlane] -> SetMarkerColor(kRed);
1312     fGrMFTPlane[kClusterOfTrack][iPlane] -> SetTitle(Form("Plane %d (%3.1f cm)", iPlane, fZPlane[iPlane]));
1313   }
1314
1315   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1316     fGrMFTPlane[kClusterCorrectMC][iPlane] = new TGraph();
1317     fGrMFTPlane[kClusterCorrectMC][iPlane] -> SetName(Form("fGrMFTPlane_%02d_ClustersCorrectMC",iPlane));
1318     fGrMFTPlane[kClusterCorrectMC][iPlane] -> SetMarkerStyle(20);
1319     //    fGrMFTPlane[kClusterCorrectMC][iPlane] -> SetMarkerSize(0.8);
1320     fGrMFTPlane[kClusterCorrectMC][iPlane] -> SetMarkerSize(0.5);
1321     fGrMFTPlane[kClusterCorrectMC][iPlane] -> SetMarkerColor(kGreen);
1322   }
1323
1324   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1325     fCircleExt[iPlane] = new TEllipse(0., 0., fRPlaneMax[iPlane], fRPlaneMax[iPlane]);
1326     fCircleInt[iPlane] = new TEllipse(0., 0., fRPlaneMin[iPlane], fRPlaneMin[iPlane]);
1327   }
1328   
1329   fTxtDummy = new TLatex(0.10, 0.59, "Best Candidate:");
1330
1331   //---------------------------------------------------
1332
1333   fMrkAllClust = new TMarker(0.10, 0.32, 20);
1334   fMrkAllClust -> SetMarkerSize(0.5);
1335
1336   fMrkClustGoodChi2 = new TMarker(0.10, 0.26, 20);
1337   fMrkClustGoodChi2 -> SetMarkerSize(0.8);
1338   fMrkClustGoodChi2 -> SetMarkerColor(kBlue);
1339
1340   fMrkClustMC = new TMarker(0.10, 0.20, 20);
1341   fMrkClustMC -> SetMarkerSize(0.8);
1342   fMrkClustMC -> SetMarkerColor(kGreen);
1343
1344   fMrkClustOfTrack = new TMarker(0.10, 0.14, 25);
1345   fMrkClustOfTrack -> SetMarkerSize(1.2);
1346   fMrkClustOfTrack -> SetMarkerColor(kRed);
1347
1348   fTxtAllClust = new TLatex(0.15, 0.30, "All Clusters");
1349   fTxtAllClust -> SetTextSize(0.040);
1350
1351   fTxtClustGoodChi2 = new TLatex(0.15, 0.24, "Clusters involved in the research");
1352   fTxtClustGoodChi2 -> SetTextSize(0.040);
1353
1354   fTxtClustMC = new TLatex(0.15, 0.18, "MC good clusters");
1355   fTxtClustMC -> SetTextSize(0.040);
1356
1357   fTxtClustOfTrack = new TLatex(0.15, 0.12, "Clusters of the best candidate");
1358   fTxtClustOfTrack -> SetTextSize(0.040);
1359
1360 }
1361
1362 //===========================================================================================================================================
1363
1364 void AliMuonForwardTrackFinder::ResetPlanes() {
1365
1366   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1367     for (Int_t iGr=0; iGr<4; iGr++) {
1368       Int_t nOldClusters = fGrMFTPlane[iGr][iPlane]->GetN();
1369       for (Int_t iPoint=nOldClusters-1; iPoint>=0; iPoint--) fGrMFTPlane[iGr][iPlane]->RemovePoint(iPoint);
1370     }
1371   }
1372
1373 }
1374
1375 //===========================================================================================================================================
1376
1377 void AliMuonForwardTrackFinder::PrintParticleHistory() {
1378
1379   AliDebug(1, "Entering");
1380
1381   TString history = "";
1382   
1383   TParticle *part = 0;
1384   if (fLabelMC>=0) part = fStack->Particle(fLabelMC);
1385
1386   AliDebug(1, Form("fStack->Particle(fLabelMC) = %p", part));
1387
1388   if (part) {
1389     if (part->GetFirstMother() != -1) {
1390       TParticle *partMother = fStack->Particle(part->GetFirstMother());
1391       AliDebug(1, Form("fStack->Particle(part->GetFirstMother() = %p", partMother));
1392       if (partMother) {
1393         Char_t newName[100];
1394         if (partMother->GetFirstMother() != -1) history += "...  #rightarrow ";
1395         PDGNameConverter(partMother->GetName(), newName);
1396         history += Form("%s #rightarrow ", newName);
1397       }
1398     }
1399     Char_t newName[100];
1400     PDGNameConverter(part->GetName(), newName);
1401     history += Form("%s  at  z = %5.1f cm", newName, part->Vz());
1402     //  printf("%s", history.Data());
1403   }
1404   else history += "NO AVAILABLE HISTORY";
1405
1406   fTxtMuonHistory = new TLatex(0.10, 0.86, history.Data());
1407
1408   // Filling particle history in the fFinalBestCandidate
1409
1410   if (part) {
1411     for (Int_t iParent=0; iParent<AliMuonForwardTrack::fgkNParentsMax; iParent++) {
1412       if (part->GetFirstMother() == -1) break;
1413       if (!(fStack->Particle(part->GetFirstMother()))) break;
1414       AliDebug(1, Form("fStack->Particle(part->GetFirstMother() = %p", fStack->Particle(part->GetFirstMother())));
1415       fFinalBestCandidate->SetParentMCLabel(iParent, part->GetFirstMother());
1416       fFinalBestCandidate->SetParentPDGCode(iParent, fStack->Particle(part->GetFirstMother())->GetPdgCode());
1417       part = fStack->Particle(part->GetFirstMother());
1418     }
1419   }
1420   
1421 }
1422
1423 //===========================================================================================================================================
1424
1425 Bool_t AliMuonForwardTrackFinder::IsMother(Char_t *nameMother) {
1426   
1427   Bool_t result = kFALSE;
1428   
1429   TParticle *part = 0;
1430   if (fLabelMC>=0) part = fStack->Particle(fLabelMC);
1431   
1432   if (part) {
1433     if (part->GetFirstMother() != -1) {
1434       TParticle *partMother = fStack->Particle(part->GetFirstMother());
1435       if (partMother) {
1436         if (!strcmp(partMother->GetName(), nameMother)) result=kTRUE;
1437       }
1438     }
1439   }
1440
1441   return result;
1442
1443 }
1444
1445 //===========================================================================================================================================
1446
1447 void AliMuonForwardTrackFinder::DrawPlanes() {
1448
1449   fCanvas -> Clear();
1450   if (fNPlanesMFT <= 5)       fCanvas -> Divide(3,2);
1451   else if (fNPlanesMFT <= 11) fCanvas -> Divide(4,3);
1452   else if (fNPlanesMFT <= 19) fCanvas -> Divide(5,4);
1453
1454   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1455     
1456     fCanvas->cd(fNPlanesMFT-iPlane+1);
1457     
1458     fGrMFTPlane[kClusterOfTrack][iPlane] -> GetXaxis() -> SetLimits(-1.1*fRPlaneMax[fNPlanesMFT-1], +1.1*fRPlaneMax[fNPlanesMFT-1]);
1459     fGrMFTPlane[kClusterOfTrack][iPlane] -> GetYaxis() -> SetRangeUser(-1.1*fRPlaneMax[fNPlanesMFT-1], +1.1*fRPlaneMax[fNPlanesMFT-1]);
1460     fGrMFTPlane[kClusterOfTrack][iPlane] -> GetXaxis() -> SetTitle("X  [cm]");
1461     fGrMFTPlane[kClusterOfTrack][iPlane] -> GetYaxis() -> SetTitle("Y  [cm]");
1462     fGrMFTPlane[kClusterOfTrack][iPlane] -> Draw("ap");
1463
1464     fCircleExt[iPlane] -> Draw("same");
1465     fCircleInt[iPlane] -> Draw("same");
1466     
1467     if (fGrMFTPlane[kAllClusters][iPlane]->GetN())       fGrMFTPlane[kAllClusters][iPlane]      -> Draw("psame");
1468     if (fGrMFTPlane[kClustersGoodChi2][iPlane]->GetN())  fGrMFTPlane[kClustersGoodChi2][iPlane] -> Draw("psame");
1469     if (fGrMFTPlane[kClusterOfTrack][iPlane]->GetN())    fGrMFTPlane[kClusterOfTrack][iPlane]   -> Draw("psame");
1470     if (fGrMFTPlane[kClusterCorrectMC][iPlane]->GetN())  fGrMFTPlane[kClusterCorrectMC][iPlane] -> Draw("psame");
1471
1472     fTxtTrackChi2[iPlane] -> Draw("same");
1473
1474   }
1475
1476   fCanvas -> cd(1);
1477   fTxtMuonHistory       -> Draw();
1478   fTxtDummy             -> Draw("same");
1479   if (fMatchingMode==kRealMatching) fTxtTrackGoodClusters -> Draw("same");
1480   fTxtTrackFinalChi2    -> Draw("same");
1481   fTxtTrackMomentum     -> Draw("same");
1482   if (fMatchingMode==kRealMatching) fTxtFinalCandidates   -> Draw("same");
1483
1484   fMrkAllClust      -> Draw("same");
1485   fMrkClustGoodChi2 -> Draw("same");
1486   fMrkClustMC       -> Draw("same");
1487   fMrkClustOfTrack  -> Draw("same");
1488
1489   fTxtAllClust      -> Draw("same");
1490   fTxtClustGoodChi2 -> Draw("same");
1491   fTxtClustMC       -> Draw("same");
1492   fTxtClustOfTrack  -> Draw("same");
1493
1494   //  fCanvas -> SaveAs(Form("%s/figures/eventDisplay/run%d_event%d_track%d.eps", fOutDir.Data(), fRun, fEv, fCountRealTracksAnalyzedOfEvent));
1495   fCanvas -> SaveAs(Form("%s/figures/eventDisplay/run%d_event%d_track%d.gif", fOutDir.Data(), fRun, fEv, fCountRealTracksAnalyzedOfEvent));
1496   if (IsMother("phi")) {
1497     fCanvas -> SaveAs(Form("%s/figures/eventDisplay/run%d_event%d_track%d.phi.gif", fOutDir.Data(), fRun, fEv, fCountRealTracksAnalyzedOfEvent));
1498     fCanvas -> SaveAs(Form("%s/figures/eventDisplay/run%d_event%d_track%d.phi.eps", fOutDir.Data(), fRun, fEv, fCountRealTracksAnalyzedOfEvent));
1499   }
1500   if (IsMother("J/psi")) {
1501     fCanvas -> SaveAs(Form("%s/figures/eventDisplay/run%d_event%d_track%d.jPsi.gif", fOutDir.Data(), fRun, fEv, fCountRealTracksAnalyzedOfEvent));
1502     fCanvas -> SaveAs(Form("%s/figures/eventDisplay/run%d_event%d_track%d.jPsi.eps", fOutDir.Data(), fRun, fEv, fCountRealTracksAnalyzedOfEvent));
1503   }
1504     
1505 }
1506
1507 //===========================================================================================================================================
1508
1509 void AliMuonForwardTrackFinder::Terminate() {
1510   
1511   AliInfo("");
1512   AliInfo("---------------------------------------------------------------------------------------------------------------");
1513   AliInfo(Form("%8d  tracks analyzed",                                                     fCountRealTracksAnalyzed));
1514   AliInfo(Form("%8d  tracks with MC ref",                                                  fCountRealTracksWithRefMC));
1515   AliInfo(Form("%8d  tracks with MC ref & trigger match",                                  fCountRealTracksWithRefMC_andTrigger));
1516   if (fMatchingMode==kRealMatching) {
1517     AliInfo(Form("%8d  tracks analyzed with final candidates",                             fCountRealTracksAnalyzedWithFinalCandidates));
1518   }
1519   else {
1520     AliInfo(Form("%8d  tracks matched with their MC clusters",                             fCountRealTracksAnalyzedWithFinalCandidates));
1521   }
1522 //   printf("%8d  tracks with MC ref & trigger match & pt>%3.1f GeV/c",                 fCountRealTracksWithRefMC_andTrigger_andGoodPt, fLowPtCut);
1523 //   printf("%8d  tracks with MC ref & trigger match & pt>%3.1f GeV/c & correct R_abs", fCountRealTracksWithRefMC_andTrigger_andGoodPt_andGoodTheta, fLowPtCut);
1524   AliInfo("---------------------------------------------------------------------------------------------------------------");
1525
1526   WriteOutputTree();
1527   WriteHistos();
1528
1529 }
1530
1531 //==========================================================================================================================================
1532
1533 void AliMuonForwardTrackFinder::FillOutputTree() {
1534
1535   if (!fMuonForwardTracks || !fOutputEventTree) return;
1536
1537   AliDebug(1, Form("Filling output tree %p with %p having %d entries whose 1st entry is %p", 
1538                    fOutputEventTree, fMuonForwardTracks, fMuonForwardTracks->GetEntries(), fMuonForwardTracks->At(0)));
1539   
1540   //  fOutputTreeFile->cd();
1541   fOutputEventTree->Fill();
1542   AliDebug(1, Form("\nFilled Tree: nEvents = %d!!!!\n", Int_t(fOutputEventTree->GetEntries())));
1543
1544 }
1545
1546 //==========================================================================================================================================
1547
1548 void AliMuonForwardTrackFinder::WriteOutputTree() {
1549
1550   if (!fOutputEventTree || !fOutputTreeFile) return;
1551
1552   fOutputTreeFile -> cd();
1553
1554   fOutputEventTree -> Write();
1555   fOutputTreeFile -> Close();
1556
1557 }
1558
1559 //==========================================================================================================================================
1560
1561 void AliMuonForwardTrackFinder::WriteHistos() {
1562
1563   fOutputQAFile = new TFile(Form("MuonGlobalTracking.QA.run%d.root", fRun), "recreate");
1564   fOutputQAFile -> cd();
1565
1566   fHistPtSpectrometer              -> Write();
1567   fHistPtMuonTrackWithGoodMatch    -> Write();
1568   fHistPtMuonTrackWithBadMatch     -> Write();
1569   fHistRadiusEndOfAbsorber         -> Write();
1570   fHistNGoodClustersForFinalTracks -> Write();
1571
1572   fHistDistanceGoodClusterFromTrackAtLastPlane                                  -> Write();  
1573   fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane -> Write();  
1574
1575   for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1576     
1577     fHistNTracksAfterExtrapolation[iPlane] -> Write();
1578     fHistResearchRadius[iPlane]            -> Write();
1579     
1580     fHistChi2Cluster_GoodCluster[iPlane]   -> Write();
1581     fHistChi2Cluster_BadCluster[iPlane]    -> Write();
1582     
1583     fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[iPlane] -> Write();
1584     fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[iPlane]  -> Write();
1585
1586   }
1587
1588   fNtuFinalCandidates     -> Write();
1589   fNtuFinalBestCandidates -> Write();
1590
1591   fOutputQAFile -> Close();
1592
1593 }
1594
1595 //===========================================================================================================================================
1596
1597 void AliMuonForwardTrackFinder::PDGNameConverter(const Char_t *nameIn, Char_t *nameOut) {
1598
1599   if      (!strcmp(nameIn, "mu+"))     sprintf(nameOut, "#mu^{+}");
1600   else if (!strcmp(nameIn, "mu-"))     sprintf(nameOut, "#mu^{-}");
1601   else if (!strcmp(nameIn, "pi+"))     sprintf(nameOut, "#pi^{+}");
1602   else if (!strcmp(nameIn, "pi-"))     sprintf(nameOut, "#pi^{-}");
1603   else if (!strcmp(nameIn, "K+"))      sprintf(nameOut, "K^{+}");
1604   else if (!strcmp(nameIn, "K-"))      sprintf(nameOut, "K^{-}");
1605   else if (!strcmp(nameIn, "K*+"))     sprintf(nameOut, "K^{*+}");
1606   else if (!strcmp(nameIn, "K*-"))     sprintf(nameOut, "K^{*-}");
1607   else if (!strcmp(nameIn, "K_S0"))    sprintf(nameOut, "K_{S}^{0}");
1608   else if (!strcmp(nameIn, "K_L0"))    sprintf(nameOut, "K_{L}^{0}");
1609   else if (!strcmp(nameIn, "K0"))      sprintf(nameOut, "K^{0}");
1610   else if (!strcmp(nameIn, "K0_bar"))  sprintf(nameOut, "#bar{K}^{0}");
1611   else if (!strcmp(nameIn, "K*0"))     sprintf(nameOut, "K^{*0}");
1612   else if (!strcmp(nameIn, "K*0_bar")) sprintf(nameOut, "#bar{K}^{*0}");
1613   else if (!strcmp(nameIn, "rho0"))    sprintf(nameOut, "#rho^{0}");
1614   else if (!strcmp(nameIn, "rho+"))    sprintf(nameOut, "#rho^{+}");
1615   else if (!strcmp(nameIn, "rho-"))    sprintf(nameOut, "#rho^{-}");
1616   else if (!strcmp(nameIn, "omega"))   sprintf(nameOut, "#omega");
1617   else if (!strcmp(nameIn, "eta'"))    sprintf(nameOut, "#eta'");
1618   else if (!strcmp(nameIn, "phi"))     sprintf(nameOut, "#phi");
1619
1620   else if (!strcmp(nameIn, "D-"))     sprintf(nameOut, "D^{-}");
1621   else if (!strcmp(nameIn, "D+"))     sprintf(nameOut, "D^{+}");
1622   else if (!strcmp(nameIn, "D0"))     sprintf(nameOut, "D^{0}");
1623   else if (!strcmp(nameIn, "D0_bar")) sprintf(nameOut, "#bar{D}^{0}");
1624   else if (!strcmp(nameIn, "D*-"))    sprintf(nameOut, "D^{*-}");
1625   else if (!strcmp(nameIn, "D*+"))    sprintf(nameOut, "D^{*+}");
1626   else if (!strcmp(nameIn, "D_s+"))   sprintf(nameOut, "D_{s}^{+}");
1627   else if (!strcmp(nameIn, "D*_s+"))  sprintf(nameOut, "D_{s}^{*+}");
1628
1629   else if (!strcmp(nameIn, "B-"))       sprintf(nameOut, "B^{-}");
1630   else if (!strcmp(nameIn, "B+"))       sprintf(nameOut, "B^{+}");
1631   else if (!strcmp(nameIn, "B_s0_bar")) sprintf(nameOut, "#bar{B}_{s}^{0}");
1632
1633   else if (!strcmp(nameIn, "antiproton"))  sprintf(nameOut, "#bar{p}");
1634   else if (!strcmp(nameIn, "proton"))      sprintf(nameOut, "p");
1635   else if (!strcmp(nameIn, "neutron"))     sprintf(nameOut, "n");
1636   else if (!strcmp(nameIn, "Sigma+"))      sprintf(nameOut, "#Sigma^{+}");
1637   else if (!strcmp(nameIn, "Delta+"))      sprintf(nameOut, "#Delta{+}");
1638   else if (!strcmp(nameIn, "Delta--"))     sprintf(nameOut, "#Delta{--}");
1639   else if (!strcmp(nameIn, "Lambda0"))     sprintf(nameOut, "#Lambda_0");
1640   else if (!strcmp(nameIn, "Lambda0_bar")) sprintf(nameOut, "#bar{Lambda}_0");
1641
1642   else sprintf(nameOut, "%s", nameIn);
1643
1644 }
1645
1646 //===========================================================================================================================================
1647
1648 void AliMuonForwardTrackFinder::SetDraw(Bool_t drawOption) { 
1649
1650   fDrawOption = drawOption;
1651
1652   if (!fCanvas) {
1653     fCanvas = new TCanvas("tracking", "tracking", 1200, 800);
1654     fCanvas -> Divide(3,2);
1655   }
1656
1657 }
1658
1659 //===========================================================================================================================================
1660
1661 Bool_t AliMuonForwardTrackFinder::InitGRP() {
1662
1663   //------------------------------------
1664   // Initialization of the GRP entry 
1665   //------------------------------------
1666
1667   AliCDBEntry* entry = AliCDBManager::Instance()->Get("GRP/GRP/Data");
1668
1669   if (entry) {
1670
1671     TMap* m = dynamic_cast<TMap*>(entry->GetObject());  // old GRP entry
1672
1673     if (m) {
1674        AliInfo("Found a TMap in GRP/GRP/Data, converting it into an AliGRPObject");
1675        m->Print();
1676        fGRPData = new AliGRPObject();
1677        fGRPData->ReadValuesFromMap(m);
1678     }
1679
1680     else {
1681        AliInfo("Found an AliGRPObject in GRP/GRP/Data, reading it");
1682        fGRPData = dynamic_cast<AliGRPObject*>(entry->GetObject());  // new GRP entry
1683        entry->SetOwner(0);
1684     }
1685
1686     //    FIX ME: The unloading of GRP entry is temporarily disabled
1687     //    because ZDC and VZERO are using it in order to initialize
1688     //    their reconstructor objects. In the future one has to think
1689     //    of propagating AliRunInfo to the reconstructors.
1690     //    AliCDBManager::Instance()->UnloadFromCache("GRP/GRP/Data");
1691   }
1692
1693   if (!fGRPData) {
1694      AliError("No GRP entry found in OCDB!");
1695      return kFALSE;
1696   }
1697
1698   TString lhcState = fGRPData->GetLHCState();
1699   if (lhcState==AliGRPObject::GetInvalidString()) {
1700     AliError("GRP/GRP/Data entry:  missing value for the LHC state ! Using UNKNOWN");
1701     lhcState = "UNKNOWN";
1702   }
1703
1704   TString beamType = fGRPData->GetBeamType();
1705   if (beamType==AliGRPObject::GetInvalidString()) {
1706     AliError("GRP/GRP/Data entry:  missing value for the beam type ! Using UNKNOWN");
1707     beamType = "UNKNOWN";
1708   }
1709
1710   Float_t beamEnergy = fGRPData->GetBeamEnergy();
1711   if (beamEnergy==AliGRPObject::GetInvalidFloat()) {
1712     AliError("GRP/GRP/Data entry:  missing value for the beam energy ! Using 0");
1713     beamEnergy = 0;
1714   }
1715
1716   TString runType = fGRPData->GetRunType();
1717   if (runType==AliGRPObject::GetInvalidString()) {
1718     AliError("GRP/GRP/Data entry:  missing value for the run type ! Using UNKNOWN");
1719     runType = "UNKNOWN";
1720   }
1721
1722   Int_t activeDetectors = fGRPData->GetDetectorMask();
1723   if (activeDetectors==AliGRPObject::GetInvalidUInt()) {
1724     AliError("GRP/GRP/Data entry:  missing value for the detector mask ! Using 1074790399");
1725     activeDetectors = 1074790399;
1726   }
1727   AliDebug(1, Form("activeDetectors = %d", activeDetectors));
1728
1729   fRunInfo = new AliRunInfo(lhcState, beamType, beamEnergy, runType, activeDetectors);
1730   fRunInfo->Dump();
1731
1732   // *** Dealing with the magnetic field map
1733
1734   if ( TGeoGlobalMagField::Instance()->IsLocked() ) {
1735     if (TGeoGlobalMagField::Instance()->GetField()->TestBit(AliMagF::kOverrideGRP)) {
1736       AliInfo("ExpertMode!!! GRP information will be ignored !");
1737       AliInfo("ExpertMode!!! Running with the externally locked B field !");
1738     }
1739     else {
1740       AliInfo("Destroying existing B field instance!");
1741       delete TGeoGlobalMagField::Instance();
1742     }    
1743   }
1744   if ( !TGeoGlobalMagField::Instance()->IsLocked() ) {
1745     // Construct the field map out of the information retrieved from GRP.
1746     Bool_t ok = kTRUE;
1747     // L3
1748     Float_t l3Current = fGRPData->GetL3Current((AliGRPObject::Stats)0);
1749     if (l3Current == AliGRPObject::GetInvalidFloat()) {
1750       AliError("GRP/GRP/Data entry:  missing value for the L3 current !");
1751       ok = kFALSE;
1752     }
1753     
1754     Char_t l3Polarity = fGRPData->GetL3Polarity();
1755     if (l3Polarity == AliGRPObject::GetInvalidChar()) {
1756       AliError("GRP/GRP/Data entry:  missing value for the L3 polarity !");
1757       ok = kFALSE;
1758     }
1759
1760     // Dipole
1761     Float_t diCurrent = fGRPData->GetDipoleCurrent((AliGRPObject::Stats)0);
1762     if (diCurrent == AliGRPObject::GetInvalidFloat()) {
1763       AliError("GRP/GRP/Data entry:  missing value for the dipole current !");
1764       ok = kFALSE;
1765     }
1766
1767     Char_t diPolarity = fGRPData->GetDipolePolarity();
1768     if (diPolarity == AliGRPObject::GetInvalidChar()) {
1769       AliError("GRP/GRP/Data entry:  missing value for the dipole polarity !");
1770       ok = kFALSE;
1771     }
1772
1773     // read special bits for the polarity convention and map type
1774     Int_t  polConvention = fGRPData->IsPolarityConventionLHC() ? AliMagF::kConvLHC : AliMagF::kConvDCS2008;
1775     Bool_t uniformB = fGRPData->IsUniformBMap();
1776
1777     if (ok) { 
1778       AliMagF* fld = AliMagF::CreateFieldMap(TMath::Abs(l3Current) * (l3Polarity ? -1:1), 
1779                                              TMath::Abs(diCurrent) * (diPolarity ? -1:1), 
1780                                              polConvention,uniformB,beamEnergy, beamType.Data());
1781       if (fld) {
1782         TGeoGlobalMagField::Instance()->SetField( fld );
1783         TGeoGlobalMagField::Instance()->Lock();
1784         AliInfo("Running with the B field constructed out of GRP !");
1785       }
1786       else AliFatal("Failed to create a B field map !");
1787     }
1788     else AliFatal("B field is neither set nor constructed from GRP ! Exitig...");
1789   }
1790   
1791   return kTRUE;
1792
1793
1794 //====================================================================================================================================================
1795
1796 Bool_t AliMuonForwardTrackFinder::SetRunNumber() {
1797
1798   AliCDBManager *man = AliCDBManager::Instance();
1799
1800   if (!fRunLoader) {
1801     AliError("No run loader found!");
1802     return kFALSE;
1803   }
1804   else {
1805     fRunLoader->LoadHeader();
1806     // read run number from gAlice
1807     if (fRunLoader->GetHeader()) {
1808       man->SetRun(fRunLoader->GetHeader()->GetRun());
1809       fRunLoader->UnloadHeader();
1810     }
1811     else {
1812       AliError("No run-loader header found!");
1813       return kFALSE;
1814     }
1815   }
1816
1817   return kTRUE;
1818
1819 }
1820
1821 //====================================================================================================================================================
1822