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