3 #include "TClonesArray.h"
8 #include "TGeoManager.h"
10 #include "TParticle.h"
20 #include "TIterator.h"
25 #include "AliRunLoader.h"
26 #include "AliLoader.h"
27 #include "AliHeader.h"
31 #include "AliTracker.h"
32 #include "AliGRPObject.h"
33 #include "AliCDBEntry.h"
34 #include "AliCDBManager.h"
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"
46 #include "AliMuonForwardTrack.h"
47 #include "AliMFTCluster.h"
49 #include "AliMFTSegmentation.h"
50 #include "AliMFTConstants.h"
52 #include "AliMuonForwardTrackFinder.h"
54 //====================================================================================================================================================
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
59 // Contact author: antonio.uras@cern.ch
61 //====================================================================================================================================================
63 const Double_t AliMuonForwardTrackFinder::fRadLengthSi = AliMFTConstants::fRadLengthSi;
65 ClassImp(AliMuonForwardTrackFinder)
67 //=====================================================================================================
69 AliMuonForwardTrackFinder::AliMuonForwardTrackFinder():
75 fSigmaSpectrometerCut(0),
79 fNFinalCandidatesCut(0),
84 fDistanceFromGoodClusterAndTrackAtLastPlane(-1),
85 fDistanceFromBestClusterAndTrackAtLastPlane(-1),
90 fNPlanesMFTAnalyzed(0),
91 fNMaxMissingMFTClusters(0),
96 fHistRadiusEndOfAbsorber(0),
97 fHistNGoodClustersForFinalTracks(0),
98 fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane(0),
99 fHistDistanceGoodClusterFromTrackAtLastPlane(0),
101 fNtuFinalCandidates(0),
102 fNtuFinalBestCandidates(0),
107 fTxtTrackGoodClusters(0),
108 fTxtTrackFinalChi2(0),
109 fTxtTrackMomentum(0),
110 fTxtFinalCandidates(0),
113 fTxtClustGoodChi2(0),
117 fMrkClustGoodChi2(0),
121 fCountRealTracksAnalyzed(0),
122 fMaxNTracksToBeAnalyzed(99999999),
123 fCountRealTracksWithRefMC(0),
124 fCountRealTracksWithRefMC_andTrigger(0),
125 fCountRealTracksWithRefMC_andTrigger_andGoodPt(0),
126 fCountRealTracksWithRefMC_andTrigger_andGoodPt_andGoodTheta(0),
127 fCountRealTracksAnalyzedOfEvent(0),
128 fCountRealTracksAnalyzedWithFinalCandidates(0),
140 fFinalBestCandidate(0),
141 fIsCurrentMuonTrackable(0),
152 fMuonForwardTracks(0),
154 fMinResearchRadiusAtLastPlane(0),
160 // Default constructor
162 for (Int_t iPlane=0; iPlane<AliMFTConstants::fNMaxPlanes; iPlane++) {
164 fHistNTracksAfterExtrapolation[iPlane] = 0;
165 fHistChi2Cluster_GoodCluster[iPlane] = 0;
166 fHistChi2Cluster_BadCluster[iPlane] = 0;
167 fHistResearchRadius[iPlane] = 0;
169 fIsGoodClusterInPlane[iPlane] = kFALSE;
171 fHistChi2Cluster_GoodCluster[iPlane] = 0;
172 fHistChi2Cluster_BadCluster[iPlane] = 0;
174 fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[iPlane] = 0;
175 fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[iPlane] = 0;
177 fZPlane[iPlane] = 0.;
178 fRPlaneMax[iPlane] = 0.;
179 fRPlaneMin[iPlane] = 0.;
181 for (Int_t i=0; i<4; i++) fGrMFTPlane[i][iPlane] = 0;
182 fCircleExt[iPlane] = 0;
183 fCircleInt[iPlane] = 0;
185 fTxtTrackChi2[iPlane] = 0;
187 fIsClusterCompatible[iPlane] = 0;
189 fMFTClusterArray[iPlane] = 0;
190 fMFTClusterArrayFront[iPlane] = new TClonesArray("AliMFTCluster");
191 fMFTClusterArrayBack[iPlane] = new TClonesArray("AliMFTCluster");
193 fIsPlaneMandatory[iPlane] = kFALSE;
199 fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane = 0;
200 fHistDistanceGoodClusterFromTrackAtLastPlane = 0;
203 fCandidateTracks = 0;
205 fOutputTreeFile = new TFile("MuonGlobalTracks.root", "recreate");
206 fOutputEventTree = new TTree("AliMuonForwardTracks", "Tree of AliMuonForwardTracks");
207 fMuonForwardTracks = new TClonesArray("AliMuonForwardTrack");
208 fOutputEventTree -> Branch("tracks", &fMuonForwardTracks);
212 //=====================================================================================================
214 AliMuonForwardTrackFinder::~AliMuonForwardTrackFinder() {
216 for (Int_t iPlane=0; iPlane<AliMFTConstants::fNMaxPlanes; iPlane++) {
218 delete fHistNTracksAfterExtrapolation[iPlane];
219 delete fHistChi2Cluster_GoodCluster[iPlane];
220 delete fHistChi2Cluster_BadCluster[iPlane];
221 delete fHistResearchRadius[iPlane];
223 delete fHistChi2Cluster_GoodCluster[iPlane];
224 delete fHistChi2Cluster_BadCluster[iPlane];
226 delete fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[iPlane];
227 delete fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[iPlane];
229 for (Int_t i=0; i<4; i++) delete fGrMFTPlane[i][iPlane];
230 delete fCircleExt[iPlane];
231 delete fCircleInt[iPlane];
233 delete fTxtTrackChi2[iPlane];
235 delete fMFTClusterArray[iPlane];
236 delete fMFTClusterArrayFront[iPlane];
237 delete fMFTClusterArrayBack[iPlane];
241 delete fNtuFinalCandidates;
242 delete fNtuFinalBestCandidates;
244 delete fHistRadiusEndOfAbsorber;
246 delete fHistNGoodClustersForFinalTracks;
247 delete fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane; //
248 delete fHistDistanceGoodClusterFromTrackAtLastPlane; //
252 delete fTxtMuonHistory;
253 delete fTxtTrackGoodClusters;
254 delete fTxtTrackFinalChi2;
255 delete fTxtTrackMomentum;
256 delete fTxtFinalCandidates;
259 delete fTxtClustGoodChi2;
261 delete fTxtClustOfTrack;
263 delete fMrkClustGoodChi2;
265 delete fMrkClustOfTrack;
273 delete fMuonRecoCheck;
275 delete fMFTClusterTree;
277 delete fMuonTrackReco;
278 delete fCurrentTrack;
279 delete fFinalBestCandidate;
281 delete fCandidateTracks;
284 delete fTrackRefStore;
291 delete fSegmentation;
293 delete fOutputTreeFile;
294 delete fOutputQAFile;
295 delete fOutputEventTree;
297 delete fMuonForwardTracks;
304 //=====================================================================================================
306 void AliMuonForwardTrackFinder::Init(Int_t nRun,
309 Int_t nEventsToAnalyze) {
312 AliInfo("WARNING: run already initialized!!\n");
319 AliInfo(Form("input dir = %s\n", fReadDir.Data()));
320 AliInfo(Form("output dir = %s\n", fOutDir.Data()));
322 // -------------------------- initializing files...
324 AliInfo(Form("initializing files for run %d...\n", fRun));
326 Char_t geoFileName[300];
327 Char_t esdFileName[300];
328 Char_t gAliceName[300];
329 Char_t clusterName[300];
331 sprintf(geoFileName , "%s/geometry.root", fReadDir.Data());
332 sprintf(esdFileName , "%s/AliESDs.root" , fReadDir.Data());
333 sprintf(gAliceName , "%s/galice.root" , fReadDir.Data());
334 sprintf(clusterName , "%s/MFT.RecPoints.root", fReadDir.Data());
336 // Import TGeo geometry (needed by AliMUONTrackExtrap::ExtrapToVertex)
338 TGeoManager::Import(geoFileName);
340 AliError(Form("getting geometry from file %s failed", geoFileName));
345 fFileESD = new TFile(esdFileName);
346 if (!fFileESD || !fFileESD->IsOpen()) return;
347 else AliInfo(Form("file %s successfully opened\n", fFileESD->GetName()));
349 fMuonRecoCheck = new AliMUONRecoCheck(esdFileName, Form("%s/generated/", fReadDir.Data())); // Utility class to check reconstruction
350 fFile_gAlice = new TFile(gAliceName);
351 if (!fFile_gAlice || !fFile_gAlice->IsOpen()) return;
352 else AliInfo(Form("file %s successfully opened\n", fFile_gAlice->GetName()));
354 fRunLoader = AliRunLoader::Open(gAliceName);
355 gAlice = fRunLoader->GetAliRun();
356 if (!gAlice) fRunLoader->LoadgAlice();
357 fMFT = (AliMFT*) gAlice->GetDetector("MFT");
358 fSegmentation = fMFT->GetSegmentation();
359 SetNPlanesMFT(fSegmentation->GetNPlanes());
361 if (!SetRunNumber()) return;
362 if (!InitGRP()) return;
363 AliMUONTrackExtrap::SetField(); // set the magnetic field for track extrapolations
365 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
366 fZPlane[iPlane] = fSegmentation->GetPlane(iPlane)->GetZCenter();
367 fRPlaneMax[iPlane] = fSegmentation->GetPlane(iPlane)->GetRMaxSupport();
368 fRPlaneMin[iPlane] = fSegmentation->GetPlane(iPlane)->GetRMinSupport();
371 // Loading MFT clusters
372 fMFTLoader = fRunLoader->GetDetectorLoader("MFT");
373 fMFTLoader->LoadRecPoints("READ");
375 fMFTClusterTree = fMFTLoader->TreeR();
377 Int_t nEventsInFile = fMuonRecoCheck->NumberOfEvents();
378 if (!nEventsInFile) {
379 AliError("no events available!!!\n");
382 if (nEventsInFile<nEventsToAnalyze || nEventsToAnalyze<0) fNEventsToAnalyze = nEventsInFile;
383 else fNEventsToAnalyze = nEventsToAnalyze;
385 fCandidateTracks = new TClonesArray("AliMuonForwardTrack",50000);
387 // -------------------------- initializing histograms...
389 AliInfo("\ninitializing histograms...\n");
392 AliInfo("... done!\n\n");
394 // -------------------------- initializing graphics...
396 AliInfo("initializing graphics...\n");
398 AliInfo("... done!\n\n");
400 SetSigmaSpectrometerCut(4.0);
401 SetSigmaClusterCut(4.5);
402 SetChi2GlobalCut(2.0);
403 SetNFinalCandidatesCut(10);
404 SetRAbsorberCut(26.4);
409 //======================================================================================================================================
411 Bool_t AliMuonForwardTrackFinder::LoadNextEvent() {
413 // load next reconstructed event from the tree
415 if (fEv) FillOutputTree();
417 if (fEv>=fNEventsToAnalyze) return kFALSE;
419 fCountRealTracksAnalyzedOfEvent = 0;
421 AliInfo(Form(" **** analyzing event # %d \n", fEv));
423 fTrackStore = fMuonRecoCheck->ReconstructedTracks(fEv);
424 fTrackRefStore = fMuonRecoCheck->ReconstructibleTracks(fEv);
426 fRunLoader->GetEvent(fEv);
427 if (!fMFTLoader->TreeR()->GetEvent()) return kFALSE;
428 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
429 AliDebug(1, Form("plane %02d: nClusters = %d\n", iPlane, (fMFT->GetRecPointsList(iPlane))->GetEntries()));
430 fMFTClusterArray[iPlane] = fMFT->GetRecPointsList(iPlane);
432 SeparateFrontBackClusters();
434 fRunLoader -> LoadKinematics();
435 fStack = fRunLoader->Stack();
436 fNextTrack = fTrackStore->CreateIterator();
437 fMuonForwardTracks->Clear();
445 //======================================================================================================================================
447 Int_t AliMuonForwardTrackFinder::LoadNextTrack() {
449 fNPlanesMFTAnalyzed = 0;
451 // load next muon track from the reconstructed event
453 if (fCountRealTracksAnalyzed>fMaxNTracksToBeAnalyzed) return kFALSE;
455 if (!fCountRealTracksAnalyzed) if (!LoadNextEvent()) return kFALSE;
456 if (fCountRealTracksAnalyzed==fMaxNTracksToBeAnalyzed) {
457 fCountRealTracksAnalyzed++;
458 if (!LoadNextEvent()) return kFALSE;
461 while ( !(fMuonTrackReco = static_cast<AliMUONTrack*>(fNextTrack->Next())) ) if (!LoadNextEvent()) return kFALSE;
463 AliDebug(1, "**************************************************************************************\n");
464 AliDebug(1, Form("*************************** MUON TRACK %3d ***************************************\n", fCountRealTracksAnalyzedOfEvent));
465 AliDebug(1, "**************************************************************************************\n");
467 fCountRealTracksAnalyzed++;
469 fCandidateTracks -> Clear();
472 fDistanceFromGoodClusterAndTrackAtLastPlane = -1.;
473 fDistanceFromBestClusterAndTrackAtLastPlane = -1.;
476 TIter nextTrackRef(fTrackRefStore->CreateIterator());
477 AliMUONTrack *trackRef=0;
479 // --------------------------------------- loop on MC generated tracks to find the MC reference...
481 while ( (trackRef = static_cast<AliMUONTrack*>(nextTrackRef())) ) {
482 // number of compatible clusters between trackReco and trackRef
483 Int_t nMatchCluster = fMuonTrackReco->FindCompatibleClusters(*trackRef, fSigmaSpectrometerCut, fIsClusterCompatible);
484 if ( (fIsClusterCompatible[0] || fIsClusterCompatible[1] || fIsClusterCompatible[2] || fIsClusterCompatible[3]) && // before the dipole
485 (fIsClusterCompatible[6] || fIsClusterCompatible[7] || fIsClusterCompatible[8] || fIsClusterCompatible[9]) && // after the dipole
486 2*nMatchCluster>fMuonTrackReco->GetNClusters() ) {
487 fMuonTrackReco->SetMCLabel(trackRef->GetUniqueID()); // MC reference has been found for trackReco!
492 // ------------------------------------- ...done!
494 if (fMuonTrackReco->GetMCLabel()>=0) fCountRealTracksWithRefMC++;
496 fLabelMC = fMuonTrackReco->GetMCLabel();
498 CheckCurrentMuonTrackable();
500 if (fMuonTrackReco->GetMatchTrigger()) fCountRealTracksWithRefMC_andTrigger++;
502 // the track we are going to build, starting from fMuonTrackReco and adding the MFT clusters
503 AliMuonForwardTrack *track = new ((*fCandidateTracks)[0]) AliMuonForwardTrack();
504 track -> SetMUONTrack(fMuonTrackReco);
505 if (fLabelMC>=0 && fStack->Particle(fLabelMC)) track->SetMCTrackRef(fStack->Particle(fLabelMC));
506 track -> SetMCLabel(fMuonTrackReco->GetMCLabel());
507 track -> SetMatchTrigger(fMuonTrackReco->GetMatchTrigger());
510 Double_t xVtx=-999., yVtx=-999., zVtx=-999999.;
511 if (track->GetMCTrackRef()) {
512 xVtx = track->GetMCTrackRef()->Vx();
513 yVtx = track->GetMCTrackRef()->Vy();
514 zVtx = track->GetMCTrackRef()->Vz();
518 Double_t pt=-999., theta=-999., eta=-999.;
519 if (track->GetMCTrackRef()) {
520 pt = track->GetMCTrackRef()->Pt();
521 theta = track->GetMCTrackRef()->Theta();
522 if (theta<0.) theta += TMath::Pi();
523 eta = track->GetMCTrackRef()->Eta();
526 AliMUONTrackParam *param = (AliMUONTrackParam*) (fMuonTrackReco->GetTrackParamAtCluster()->First());
527 pt = TMath::Sqrt(param->Px()*param->Px() + param->Py()*param->Py());
528 theta = TMath::ATan(pt/param->Pz());
529 if (theta<0.) theta += TMath::Pi();
530 eta = -1.*TMath::Log(TMath::Tan(0.5*theta));
532 // if the transverse momentum is smaller than the threshold, skip to the next track
533 if (pt < fLowPtCut) return 3;
535 // track parameters linearly extrapolated from the first tracking station to the end of the absorber
536 AliMUONTrackParam trackParamEndOfAbsorber(*((AliMUONTrackParam*)(fMuonTrackReco->GetTrackParamAtCluster()->First())));
537 AliMUONTrackExtrap::ExtrapToZCov(&trackParamEndOfAbsorber, -503.); // absorber extends from -90 to -503 cm
538 Double_t xEndOfAbsorber = trackParamEndOfAbsorber.GetNonBendingCoor();
539 Double_t yEndOfAbsorber = trackParamEndOfAbsorber.GetBendingCoor();
540 Double_t rAbsorber = TMath::Sqrt(xEndOfAbsorber*xEndOfAbsorber + yEndOfAbsorber*yEndOfAbsorber);
541 fHistRadiusEndOfAbsorber -> Fill(rAbsorber);
543 // if the radial distance of the track at the end of the absorber is smaller than a given radius, skip to the next track
544 if (rAbsorber < fRAbsorberCut) return 4;
546 //------------------------- NOW THE CYCLE OVER THE MFT PLANES STARTS ---------------------------------------
548 for (Int_t iPlane=fNPlanesMFT-1; iPlane>=0; iPlane--) { // *** do not reverse the order of this cycle!!!
549 // *** this reflects the fact that the extrapolation is performed
550 // *** starting from the last MFT plane back to the origin
552 // --------- updating the array of tracks according to the clusters available in the i-th plane ---------
554 fNPlanesMFTAnalyzed++;
556 if (fMatchingMode==kRealMatching) {
557 Int_t nTracksToBeAnalyzed = fCandidateTracks->GetEntriesFast();
558 for (Int_t iTrack=0; iTrack<nTracksToBeAnalyzed; iTrack++) {
559 fCurrentTrack = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(iTrack);
560 // if the old track is compatible with the new cluster, the track is updated and inserted as new track in the array
561 // (several new tracks can be created for one old track)
562 FindClusterInPlane(iPlane);
563 if ((fNPlanesMFTAnalyzed-fCurrentTrack->GetNMFTClusters())>fNMaxMissingMFTClusters || fIsPlaneMandatory[iPlane]) {
564 fCandidateTracks->Remove(fCurrentTrack); // the old track is removed after the check;
567 fCandidateTracks->Compress();
568 if (fIsCurrentMuonTrackable) {
569 // fOutputQAFile->cd();
570 fHistNTracksAfterExtrapolation[iPlane] -> Fill(fCandidateTracks->GetEntriesFast());
574 else if (fMatchingMode==kIdealMatching && fIsCurrentMuonTrackable) {
575 fCurrentTrack = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(0);
576 AliDebug(2, Form("plane %02d: fCandidateTracks->GetEntriesFast() = %d fCandidateTracks->UncheckedAt(0) = %p fCurrentTrack = %p\n",
577 iPlane, fCandidateTracks->GetEntriesFast(), fCandidateTracks->UncheckedAt(0), fCurrentTrack));
578 AttachGoodClusterInPlane(iPlane);
583 // -------------------------- END OF THE CYCLE OVER THE MFT PLANES --------------------------------------------
585 AliDebug(1, "Finished cycle over planes");
587 Double_t momentum = pt * TMath::CosH(eta);
588 fTxtTrackMomentum = new TLatex(0.10, 0.70, Form("P_{spectro} = %3.1f GeV/c", momentum));
590 if (fMatchingMode==kIdealMatching) {
591 AliDebug(1, "Adding track to output tree...\n");
592 fFinalBestCandidate = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(0);
593 AliMuonForwardTrack *newTrack = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(0);
594 new ((*fMuonForwardTracks)[fMuonForwardTracks->GetEntries()]) AliMuonForwardTrack(*newTrack);
595 AliDebug(1, "...track added!\n");
596 fCandidateTracks->Clear();
597 fCountRealTracksAnalyzedOfEvent++;
598 fCountRealTracksAnalyzedWithFinalCandidates++;
599 PrintParticleHistory();
600 FillPlanesWithTrackHistory();
602 Double_t chi2AtPlane[fNMaxPlanes] = {0};
603 Int_t nGoodClusters = 0;
604 Int_t nMFTClusters = fFinalBestCandidate->GetNMFTClusters();
605 // Int_t nMUONClusters = fFinalBestCandidate->GetNMUONClusters();
607 for (Int_t iCluster=0; iCluster<nMFTClusters; iCluster++) {
608 while (!fFinalBestCandidate->PlaneExists(plane)) plane++;
609 AliMFTCluster *localCluster = fFinalBestCandidate->GetMFTCluster(iCluster);
610 chi2AtPlane[plane] = localCluster->GetLocalChi2();
611 if (IsCorrectMatch(localCluster)) nGoodClusters++;
612 // Int_t nClustersGlobalTrack = nMUONClusters + (nMFTClusters-iCluster); // Muon Spectrometer clusters + clusters in the Vertex Telescope
613 // Int_t ndfGlobalTrack = GetNDF(nClustersGlobalTrack);
614 // chi2AtPlane[plane] /= Double_t(ndfGlobalTrack);
617 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
618 fTxtTrackChi2[iPlane] = new TLatex(0.55*fRPlaneMax[fNPlanesMFT-1],
619 0.90*fRPlaneMax[fNPlanesMFT-1],
620 Form("#chi^{2} = %3.1f", chi2AtPlane[iPlane]));
622 fTxtTrackFinalChi2 = new TLatex(0.20, 0.44, Form("#chi^{2}_{final} = %3.1f", chi2AtPlane[0]));
624 if (fDrawOption) DrawPlanes();
628 // If we have several final tracks, we must find the best candidate:
630 Int_t nFinalTracks = fCandidateTracks->GetEntriesFast();
631 AliDebug(1, Form("nFinalTracks = %d", nFinalTracks));
633 if (nFinalTracks) fCountRealTracksAnalyzedWithFinalCandidates++;
635 Double_t theVariable_Best = -1.; // variable defining the best candidate
636 Bool_t bestCandidateExists = kFALSE;
637 Int_t nGoodClustersBestCandidate = 0;
638 Int_t idBestCandidate = 0;
639 Double_t chi2HistoryForBestCandidate[fNMaxPlanes] = {0}; // chi2 on each plane, for the best candidate
640 Double_t nClustersPerPlane[fNMaxPlanes] = {0};
641 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
642 chi2HistoryForBestCandidate[iPlane] = -1.;
643 nClustersPerPlane[iPlane] = fMFTClusterArray[iPlane] -> GetEntries();
646 fTxtFinalCandidates = new TLatex(0.10, 0.78, Form("N_{FinalCandidates} = %d", nFinalTracks));
648 Int_t nClustersMC = 0;
649 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) nClustersMC += fIsGoodClusterInPlane[iPlane];
651 for (Int_t iTrack=0; iTrack<nFinalTracks; iTrack++) {
653 AliMuonForwardTrack *finalTrack = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(iTrack);
655 Double_t chi2AtPlane[fNMaxPlanes] = {0};
656 Int_t nGoodClusters = 0;
657 Int_t nMFTClusters = finalTrack->GetNMFTClusters();
658 // Int_t nMUONClusters = finalTrack->GetNMUONClusters();
661 for (Int_t iCluster=0; iCluster<nMFTClusters; iCluster++) {
662 while (!finalTrack->PlaneExists(plane)) plane++;
663 AliMFTCluster *localCluster = finalTrack->GetMFTCluster(iCluster);
664 chi2AtPlane[plane] = localCluster->GetLocalChi2();
665 if (IsCorrectMatch(localCluster)) nGoodClusters++;
666 // Int_t nClustersGlobalTrack = nMUONClusters + (nMFTClusters-iCluster); // Muon Spectrometer clusters + clusters in the Vertex Telescope
667 // Int_t ndfGlobalTrack = GetNDF(nClustersGlobalTrack);
668 // chi2AtPlane[plane] /= Double_t(ndfGlobalTrack);
672 if (fIsCurrentMuonTrackable) {
673 // fOutputQAFile->cd();
674 fHistNGoodClustersForFinalTracks -> Fill(nGoodClusters);
677 // fOutputQAFile->cd();
679 Float_t finalCandidatesInfo[] = {Double_t(fRun),
681 Double_t(fCountRealTracksAnalyzedOfEvent),
682 Double_t(nFinalTracks),
683 Double_t(fLabelMC>=0),
685 Double_t(fMuonTrackReco->GetMatchTrigger()),
686 Double_t(nClustersMC),
687 Double_t(nGoodClusters),
699 fNtuFinalCandidates -> Fill(finalCandidatesInfo);
701 // now comparing the tracks with various criteria, in order to find the best one
703 Double_t theVariable = 0.;
704 // theVariable = chi2AtPlane[0];
705 for (Int_t iCluster=0; iCluster<nMFTClusters; iCluster++) theVariable += chi2AtPlane[iCluster];
706 theVariable /= Double_t(nMFTClusters);
709 if (theVariable<theVariable_Best || theVariable_Best<0.) {
710 nGoodClustersBestCandidate = nGoodClusters;
711 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) chi2HistoryForBestCandidate[iPlane] = chi2AtPlane[iPlane];
712 theVariable_Best = theVariable;
713 fTxtTrackFinalChi2 = new TLatex(0.20, 0.44, Form("#chi^{2}_{final} = %3.1f", chi2HistoryForBestCandidate[0]));
714 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
715 fTxtTrackChi2[iPlane] = new TLatex(0.55*fRPlaneMax[fNPlanesMFT-1],
716 0.90*fRPlaneMax[fNPlanesMFT-1],
717 Form("#chi^{2} = %3.1f", chi2AtPlane[iPlane]));
719 idBestCandidate = iTrack;
720 bestCandidateExists=kTRUE;
723 // ----------------------------------------------------------
728 fFinalBestCandidate = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(idBestCandidate);
729 AliInfo(Form("fFinalBestCandidate->GetNMFTClusters() = %d\n", fFinalBestCandidate->GetNMFTClusters()));
730 PrintParticleHistory();
731 FillPlanesWithTrackHistory();
732 AliMuonForwardTrack *newTrack = (AliMuonForwardTrack*) fCandidateTracks->UncheckedAt(idBestCandidate);
733 newTrack -> SetNWrongClustersMC(newTrack->GetNMFTClusters() - nGoodClustersBestCandidate);
734 new ((*fMuonForwardTracks)[fMuonForwardTracks->GetEntries()]) AliMuonForwardTrack(*newTrack);
737 // fOutputQAFile->cd();
739 Float_t finalBestCandidatesInfo[] = {Double_t(fRun),
741 Double_t(fCountRealTracksAnalyzedOfEvent),
742 Double_t(nFinalTracks),
743 Double_t(fLabelMC>=0),
745 Double_t(fMuonTrackReco->GetMatchTrigger()),
746 Double_t(nClustersMC),
747 Double_t(nGoodClustersBestCandidate),
749 chi2HistoryForBestCandidate[0],
750 chi2HistoryForBestCandidate[1],
751 chi2HistoryForBestCandidate[2],
752 chi2HistoryForBestCandidate[3],
753 chi2HistoryForBestCandidate[4],
754 chi2HistoryForBestCandidate[5],
755 chi2HistoryForBestCandidate[6],
756 chi2HistoryForBestCandidate[7],
757 chi2HistoryForBestCandidate[8],
758 nClustersPerPlane[0],
759 nClustersPerPlane[1],
760 nClustersPerPlane[2],
761 nClustersPerPlane[3],
762 nClustersPerPlane[4],
763 nClustersPerPlane[5],
764 nClustersPerPlane[6],
765 nClustersPerPlane[7],
766 nClustersPerPlane[8]};
768 fNtuFinalBestCandidates -> Fill(finalBestCandidatesInfo);
770 if (fDrawOption && bestCandidateExists) {
771 fTxtTrackGoodClusters = new TLatex(0.20, 0.51, Form("N_{GoodClusters} = %d", nGoodClustersBestCandidate));
775 // -------------------------------------------------------------------------------------------
777 fCandidateTracks->Clear();
778 fFinalBestCandidate = NULL;
780 fCountRealTracksAnalyzedOfEvent++;
786 //===========================================================================================================================================
788 void AliMuonForwardTrackFinder::FindClusterInPlane(Int_t planeId) {
790 AliDebug(2, Form(">>>> executing AliMuonForwardTrackFinder::FindClusterInPlane(%d)\n", planeId));
792 // !!!!!!!!! coordinates and errors on the interaction vertex should be taken from the event itself (ITS) if available
794 // propagate track to plane #planeId (both to front and back active sensors)
795 // look for compatible clusters
796 // update TrackParam at found cluster (if any) using Kalman Filter
798 AliMUONTrackParam currentParamFront, currentParamBack, currentParamForResearchFront, currentParamForResearchBack;
800 if (planeId == fNPlanesMFT-1) { // last plane of the telecope
801 currentParamFront = (*((AliMUONTrackParam*)(fMuonTrackReco->GetTrackParamAtCluster()->First())));
802 currentParamBack = (*((AliMUONTrackParam*)(fMuonTrackReco->GetTrackParamAtCluster()->First())));
803 currentParamForResearchFront = currentParamFront;
804 currentParamForResearchBack = currentParamBack;
805 Double_t xExtrap = gRandom->Gaus(0,fVertexErrorX);
806 Double_t yExtrap = gRandom->Gaus(0,fVertexErrorY);
807 Double_t zExtrap = gRandom->Gaus(0,fVertexErrorZ);
808 AliMUONTrackExtrap::ExtrapToVertex(¤tParamFront, xExtrap, yExtrap, zExtrap, fVertexErrorX, fVertexErrorY);
809 AliMUONTrackExtrap::ExtrapToVertex(¤tParamBack, xExtrap, yExtrap, zExtrap, fVertexErrorX, fVertexErrorY);
810 AliMUONTrackExtrap::ExtrapToVertex(¤tParamForResearchFront, xExtrap, yExtrap, zExtrap, fVertexErrorX, fVertexErrorY);
811 AliMUONTrackExtrap::ExtrapToVertex(¤tParamForResearchBack, xExtrap, yExtrap, zExtrap, fVertexErrorX, fVertexErrorY);
813 else { // MFT planes others than the last one: mult. scattering correction because of the upstream MFT planes is performed
814 currentParamFront = (*((AliMUONTrackParam*)(fCurrentTrack->GetTrackParamAtCluster()->First())));
815 currentParamBack = (*((AliMUONTrackParam*)(fCurrentTrack->GetTrackParamAtCluster()->First())));
816 currentParamForResearchFront = currentParamFront;
817 currentParamForResearchBack = currentParamBack;
818 AliMUONTrackExtrap::AddMCSEffect(¤tParamFront, (fSegmentation->GetPlane(planeId+1)->GetEquivalentSilicon()+
819 fSegmentation->GetPlane(planeId)->GetEquivalentSiliconBeforeFront())/fRadLengthSi,-1.);
820 AliMUONTrackExtrap::AddMCSEffect(¤tParamForResearchFront,(fSegmentation->GetPlane(planeId+1)->GetEquivalentSilicon()+
821 fSegmentation->GetPlane(planeId)->GetEquivalentSiliconBeforeFront())/fRadLengthSi,-1.);
822 AliMUONTrackExtrap::AddMCSEffect(¤tParamBack, (fSegmentation->GetPlane(planeId+1)->GetEquivalentSilicon()+
823 fSegmentation->GetPlane(planeId)->GetEquivalentSiliconBeforeBack())/fRadLengthSi,-1.);
824 AliMUONTrackExtrap::AddMCSEffect(¤tParamForResearchBack, (fSegmentation->GetPlane(planeId+1)->GetEquivalentSilicon()+
825 fSegmentation->GetPlane(planeId)->GetEquivalentSiliconBeforeBack())/fRadLengthSi,-1.);
827 // for all planes: extrapolation to the Z of the plane
828 AliMUONTrackExtrap::ExtrapToZCov(¤tParamFront, -1.*fSegmentation->GetPlane(planeId)->GetZCenterActiveFront());
829 AliMUONTrackExtrap::ExtrapToZCov(¤tParamForResearchFront, -1.*fSegmentation->GetPlane(planeId)->GetZCenterActiveFront());
830 AliMUONTrackExtrap::ExtrapToZCov(¤tParamBack, -1.*fSegmentation->GetPlane(planeId)->GetZCenterActiveBack());
831 AliMUONTrackExtrap::ExtrapToZCov(¤tParamForResearchBack, -1.*fSegmentation->GetPlane(planeId)->GetZCenterActiveBack());
833 //---------------------------------------------------------------------------------------
835 TMatrixD covFront(5,5); covFront = currentParamForResearchFront.GetCovariances();
836 TMatrixD covBack(5,5); covBack = currentParamForResearchBack.GetCovariances();
838 Double_t squaredError_X_Front = covFront(0,0);
839 Double_t squaredError_Y_Front = covFront(2,2);
840 Double_t squaredError_X_Back = covBack(0,0);
841 Double_t squaredError_Y_Back = covBack(2,2);
843 Double_t corrFact = 1.0;
845 Double_t researchRadiusFront = TMath::Sqrt(squaredError_X_Front + squaredError_Y_Front);
846 Double_t researchRadiusBack = TMath::Sqrt(squaredError_X_Back + squaredError_Y_Back);
847 if (planeId==fNPlanesMFT-1 && 0.5*(researchRadiusFront+researchRadiusBack)<fMinResearchRadiusAtLastPlane) {
848 corrFact = fMinResearchRadiusAtLastPlane/(0.5*(researchRadiusFront+researchRadiusBack));
850 if (fIsCurrentMuonTrackable) {
851 // fOutputQAFile->cd();
852 fHistResearchRadius[planeId] -> Fill(0.5*(researchRadiusFront+researchRadiusBack));
855 Double_t position_X_Front = currentParamForResearchFront.GetNonBendingCoor();
856 Double_t position_Y_Front = currentParamForResearchFront.GetBendingCoor();
857 Double_t position_X_Back = currentParamForResearchBack.GetNonBendingCoor();
858 Double_t position_Y_Back = currentParamForResearchBack.GetBendingCoor();
859 Double_t radialPositionOfTrackFront = TMath::Sqrt(position_X_Front*position_X_Front + position_Y_Front*position_Y_Front);
860 Double_t radialPositionOfTrackBack = TMath::Sqrt(position_X_Back*position_X_Back + position_Y_Back*position_Y_Back);
862 //---------------------------------------------------------------------------------------
864 Double_t chi2cut = 2.*fSigmaClusterCut*fSigmaClusterCut; // depends on the number of variables (here, 2)
866 // Analyizing the clusters: FRONT ACTIVE ELEMENTS
868 Int_t nClustersFront = fMFTClusterArrayFront[planeId]->GetEntries();
869 AliDebug(2, Form("There are %3d clusters in plane %02d FRONT\n", nClustersFront, planeId));
871 for (Int_t iCluster=0; iCluster<nClustersFront; iCluster++) {
873 Bool_t isGoodChi2 = kFALSE;
875 AliMFTCluster *cluster = (AliMFTCluster*) fMFTClusterArrayFront[planeId]->At(iCluster);
876 Double_t chi2 = (1./(corrFact*corrFact)) * TryOneCluster(currentParamForResearchFront, cluster); // describes the compatibility between the track and the cluster
877 if (chi2<chi2cut) isGoodChi2 = kTRUE;
879 Double_t radialPositionOfClusterFront = TMath::Sqrt(cluster->GetX()*cluster->GetX() + cluster->GetY()*cluster->GetY());
880 if (planeId == fNPlanesMFT-1) {
881 if (TMath::Abs(radialPositionOfTrackFront-radialPositionOfClusterFront)<fDistanceFromBestClusterAndTrackAtLastPlane ||
882 fDistanceFromBestClusterAndTrackAtLastPlane<0.) {
883 fDistanceFromBestClusterAndTrackAtLastPlane = TMath::Abs(radialPositionOfTrackFront-radialPositionOfClusterFront);
885 if (IsCorrectMatch(cluster)) {
886 fDistanceFromGoodClusterAndTrackAtLastPlane = TMath::Abs(radialPositionOfTrackFront-radialPositionOfClusterFront);
890 if (fIsCurrentMuonTrackable) {
891 // fOutputQAFile->cd();
892 if (IsCorrectMatch(cluster)) fHistChi2Cluster_GoodCluster[planeId]->Fill(chi2/2.); // chi2/ndf
893 else fHistChi2Cluster_BadCluster[planeId] ->Fill(chi2/2.); // chi2/ndf
897 AliDebug(3, Form("accepting cluster: chi2=%f (cut = %f)\n", chi2, chi2cut));
898 AliMuonForwardTrack *newTrack = new ((*fCandidateTracks)[fCandidateTracks->GetEntriesFast()]) AliMuonForwardTrack(*fCurrentTrack);
899 newTrack->AddTrackParamAtMFTCluster(currentParamFront, *cluster); // creating new track param and attaching the cluster
900 AliDebug(1, Form("After plane %02d: newTrack->GetNMFTClusters() = %d (fCurrentTrack->GetNMFTClusters() = %d)",
901 planeId, newTrack->GetNMFTClusters(), fCurrentTrack->GetNMFTClusters()));
902 newTrack->SetPlaneExists(planeId);
903 AliDebug(2, Form("current muon is trackable: %d\n", fIsCurrentMuonTrackable));
904 if (fIsCurrentMuonTrackable) {
905 Double_t newGlobalChi2 = ((AliMUONTrackParam*) newTrack->GetTrackParamAtCluster()->First())->GetTrackChi2();
906 AliDebug(2, Form("new chi2 = %f (= %f)\n", newGlobalChi2, newTrack->GetMFTCluster(0)->GetTrackChi2()));
907 Int_t nClustersGlobalTrack = newTrack->GetNMUONClusters() + newTrack->GetNMFTClusters(); // Muon Spectrometer clusters + clusters in the Vertex Telescope
908 Int_t ndfGlobalTrack = GetNDF(nClustersGlobalTrack);
909 // fOutputQAFile->cd();
910 if (IsCorrectMatch(cluster)) fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[planeId]->Fill(newGlobalChi2/Double_t(ndfGlobalTrack));
911 else fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[planeId] ->Fill(newGlobalChi2/Double_t(ndfGlobalTrack));
913 fGrMFTPlane[kClustersGoodChi2][planeId] -> SetPoint(fGrMFTPlane[kClustersGoodChi2][planeId]->GetN(), cluster->GetX(), cluster->GetY());
915 else AliDebug(3, Form("discarding cluster: chi2=%f (cut = %f)\n", chi2, chi2cut));
919 // Analyizing the clusters: BACK ACTIVE ELEMENTS
921 Int_t nClustersBack = fMFTClusterArrayBack[planeId]->GetEntries();
922 AliDebug(2, Form("There are %3d clusters in plane %02d BACK\n", nClustersBack, planeId));
924 for (Int_t iCluster=0; iCluster<nClustersBack; iCluster++) {
926 Bool_t isGoodChi2 = kFALSE;
928 AliMFTCluster *cluster = (AliMFTCluster*) fMFTClusterArrayBack[planeId]->At(iCluster);
929 Double_t chi2 = (1./(corrFact*corrFact)) * TryOneCluster(currentParamForResearchBack, cluster); // describes the compatibility between the track and the cluster
930 if (chi2<chi2cut) isGoodChi2 = kTRUE;
932 Double_t radialPositionOfClusterBack = TMath::Sqrt(cluster->GetX()*cluster->GetX() + cluster->GetY()*cluster->GetY());
933 if (planeId == fNPlanesMFT-1) {
934 if (TMath::Abs(radialPositionOfTrackBack-radialPositionOfClusterBack)<fDistanceFromBestClusterAndTrackAtLastPlane ||
935 fDistanceFromBestClusterAndTrackAtLastPlane<0.) {
936 fDistanceFromBestClusterAndTrackAtLastPlane = TMath::Abs(radialPositionOfTrackBack-radialPositionOfClusterBack);
938 if (IsCorrectMatch(cluster)) {
939 fDistanceFromGoodClusterAndTrackAtLastPlane = TMath::Abs(radialPositionOfTrackBack-radialPositionOfClusterBack);
943 if (fIsCurrentMuonTrackable) {
944 // fOutputQAFile->cd();
945 if (IsCorrectMatch(cluster)) fHistChi2Cluster_GoodCluster[planeId]->Fill(chi2/2.); // chi2/ndf
946 else fHistChi2Cluster_BadCluster[planeId] ->Fill(chi2/2.); // chi2/ndf
950 AliDebug(3,Form("accepting cluster: chi2=%f (cut = %f)\n", chi2, chi2cut));
951 AliMuonForwardTrack *newTrack = new ((*fCandidateTracks)[fCandidateTracks->GetEntriesFast()]) AliMuonForwardTrack(*fCurrentTrack);
952 newTrack->AddTrackParamAtMFTCluster(currentParamBack, *cluster); // creating new track param and attaching the cluster
953 AliDebug(1, Form("After plane %02d: newTrack->GetNMFTClusters() = %d (fCurrentTrack->GetNMFTClusters() = %d)",
954 planeId, newTrack->GetNMFTClusters(), fCurrentTrack->GetNMFTClusters()));
955 newTrack->SetPlaneExists(planeId);
956 AliDebug(2, Form("current muon is trackable: %d\n", fIsCurrentMuonTrackable));
957 if (fIsCurrentMuonTrackable) {
958 Double_t newGlobalChi2 = ((AliMUONTrackParam*) newTrack->GetTrackParamAtCluster()->First())->GetTrackChi2();
959 AliDebug(2, Form("new chi2 = %f (= %f)\n", newGlobalChi2, newTrack->GetMFTCluster(0)->GetTrackChi2()));
960 Int_t nClustersGlobalTrack = newTrack->GetNMUONClusters() + newTrack->GetNMFTClusters(); // Muon Spectrometer clusters + clusters in the Vertex Telescope
961 Int_t ndfGlobalTrack = GetNDF(nClustersGlobalTrack);
962 // fOutputQAFile->cd();
963 if (IsCorrectMatch(cluster)) fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[planeId]->Fill(newGlobalChi2/Double_t(ndfGlobalTrack));
964 else fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[planeId] ->Fill(newGlobalChi2/Double_t(ndfGlobalTrack));
966 fGrMFTPlane[kClustersGoodChi2][planeId] -> SetPoint(fGrMFTPlane[kClustersGoodChi2][planeId]->GetN(), cluster->GetX(), cluster->GetY());
968 else AliDebug(3,Form("discarding cluster: chi2=%f (cut = %f)\n", chi2, chi2cut));
972 //---------------------------------------------------------------------------------------------
974 if (planeId == fNPlanesMFT-1) {
975 if (fIsCurrentMuonTrackable && fDistanceFromGoodClusterAndTrackAtLastPlane>0.) {
976 // fOutputQAFile->cd();
977 fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane -> Fill(TMath::Abs(fDistanceFromBestClusterAndTrackAtLastPlane-
978 fDistanceFromGoodClusterAndTrackAtLastPlane));
979 fHistDistanceGoodClusterFromTrackAtLastPlane -> Fill(fDistanceFromGoodClusterAndTrackAtLastPlane);
985 //==========================================================================================================================================
987 void AliMuonForwardTrackFinder::AttachGoodClusterInPlane(Int_t planeId) {
989 AliDebug(1, Form(">>>> executing AliMuonForwardTrackFinder::AttachGoodClusterInPlane(%d)\n", planeId));
991 AliMUONTrackParam currentParamFront, currentParamBack;
993 if (planeId == fNPlanesMFT-1) { // last plane of the telecope
994 currentParamFront = (*((AliMUONTrackParam*)(fMuonTrackReco->GetTrackParamAtCluster()->First())));
995 currentParamBack = (*((AliMUONTrackParam*)(fMuonTrackReco->GetTrackParamAtCluster()->First())));
996 AliMUONTrackExtrap::ExtrapToVertexWithoutBranson(¤tParamFront, 0.);
997 AliMUONTrackExtrap::ExtrapToVertexWithoutBranson(¤tParamBack, 0.);
999 else { // MFT planes others than the last one: mult. scattering correction because of the upstream MFT planes is performed
1000 AliDebug(2, Form("fCurrentTrack = %p\n", fCurrentTrack));
1001 currentParamFront = (*((AliMUONTrackParam*)(fCurrentTrack->GetTrackParamAtCluster()->First())));
1002 currentParamBack = (*((AliMUONTrackParam*)(fCurrentTrack->GetTrackParamAtCluster()->First())));
1003 AliMUONTrackExtrap::AddMCSEffect(¤tParamFront, (fSegmentation->GetPlane(planeId+1)->GetEquivalentSilicon()+
1004 fSegmentation->GetPlane(planeId)->GetEquivalentSiliconBeforeFront())/fRadLengthSi,-1.);
1005 AliMUONTrackExtrap::AddMCSEffect(¤tParamBack, (fSegmentation->GetPlane(planeId+1)->GetEquivalentSilicon()+
1006 fSegmentation->GetPlane(planeId)->GetEquivalentSiliconBeforeBack())/fRadLengthSi,-1.);
1008 // for all planes: linear extrapolation to the Z of the plane
1009 AliMUONTrackExtrap::ExtrapToZCov(¤tParamFront, -1.*fSegmentation->GetPlane(planeId)->GetZCenterActiveFront());
1010 AliMUONTrackExtrap::ExtrapToZCov(¤tParamBack, -1.*fSegmentation->GetPlane(planeId)->GetZCenterActiveBack());
1012 Bool_t goodClusterFound = kFALSE;
1014 // Analyizing the clusters: FRONT ACTIVE ELEMENTS
1016 Int_t nClustersFront = fMFTClusterArrayFront[planeId]->GetEntries();
1018 AliDebug(1, Form("nClustersFront = %d\n", nClustersFront));
1019 for (Int_t iCluster=0; iCluster<nClustersFront; iCluster++) {
1020 AliMFTCluster *cluster = (AliMFTCluster*) fMFTClusterArrayFront[planeId]->UncheckedAt(iCluster);
1021 AliDebug(2, Form("checking cluster %02d of %02d: cluter=%p, fCurrentTrack=%p\n", iCluster, nClustersFront, cluster, fCurrentTrack));
1022 if (IsCorrectMatch(cluster)) {
1023 fCurrentTrack->AddTrackParamAtMFTCluster(currentParamFront, *cluster); // creating new track param and attaching the cluster
1024 fCurrentTrack->SetPlaneExists(planeId);
1025 goodClusterFound = kTRUE;
1030 if (goodClusterFound) return;
1032 // Analyizing the clusters: BACK ACTIVE ELEMENTS
1034 Int_t nClustersBack = fMFTClusterArrayBack[planeId]->GetEntries();
1036 AliDebug(1, Form("nClustersBack = %d\n", nClustersBack));
1037 for (Int_t iCluster=0; iCluster<nClustersBack; iCluster++) {
1038 AliMFTCluster *cluster = (AliMFTCluster*) fMFTClusterArrayBack[planeId]->UncheckedAt(iCluster);
1039 AliDebug(2,Form("checking cluster %02d of %02d: cluter=%p, fCurrentTrack=%p\n", iCluster, nClustersBack, cluster, fCurrentTrack));
1040 if (IsCorrectMatch(cluster)) {
1041 fCurrentTrack->AddTrackParamAtMFTCluster(currentParamBack, *cluster); // creating new track param and attaching the cluster
1042 fCurrentTrack->SetPlaneExists(planeId);
1043 goodClusterFound = kTRUE;
1050 //==========================================================================================================================================
1052 void AliMuonForwardTrackFinder::CheckCurrentMuonTrackable() {
1054 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1055 fIsGoodClusterInPlane[iPlane] = kFALSE;
1056 Int_t nClusters = fMFTClusterArray[iPlane]->GetEntriesFast();
1057 for (Int_t iCluster=0; iCluster<nClusters; iCluster++) {
1058 AliMFTCluster *cluster = (AliMFTCluster*) fMFTClusterArray[iPlane]->At(iCluster);
1059 for (Int_t iTrack=0; iTrack<cluster->GetNMCTracks(); iTrack++) {
1060 if (cluster->GetMCLabel(iTrack)==fLabelMC) {
1061 fIsGoodClusterInPlane[iPlane] = kTRUE;
1068 fIsCurrentMuonTrackable = kTRUE;
1069 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) fIsCurrentMuonTrackable = (fIsCurrentMuonTrackable&&fIsGoodClusterInPlane[iPlane]);
1073 //==========================================================================================================================================
1075 void AliMuonForwardTrackFinder::FillPlanesWithTrackHistory() {
1077 // Fill planes with the clusters
1080 AliDebug(2, Form("fFinalBestCandidate->GetNMFTClusters() = %d\n", fFinalBestCandidate->GetNMFTClusters()));
1081 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1082 if (fFinalBestCandidate->PlaneExists(iPlane)) {
1083 AliMFTCluster *trackCluster = fFinalBestCandidate->GetMFTCluster(cluster++);
1084 fGrMFTPlane[kClusterOfTrack][iPlane] -> SetPoint(fGrMFTPlane[kClusterOfTrack][iPlane]->GetN(), trackCluster->GetX(), trackCluster->GetY());
1086 Int_t nClusters = fMFTClusterArray[iPlane]->GetEntriesFast();
1087 for (Int_t iCluster=0; iCluster<nClusters; iCluster++) {
1088 AliMFTCluster *myCluster = (AliMFTCluster*) fMFTClusterArray[iPlane]->UncheckedAt(iCluster);
1089 fGrMFTPlane[kAllClusters][iPlane] -> SetPoint(fGrMFTPlane[kAllClusters][iPlane]->GetN(), myCluster->GetX(), myCluster->GetY());
1090 if (IsCorrectMatch(myCluster)) {
1091 fGrMFTPlane[kClusterCorrectMC][iPlane] -> SetPoint(fGrMFTPlane[kClusterCorrectMC][iPlane]->GetN(), myCluster->GetX(), myCluster->GetY());
1098 //======================================================================================================================================
1100 Bool_t AliMuonForwardTrackFinder::IsCorrectMatch(AliMFTCluster *cluster) {
1102 Bool_t result = kFALSE;
1104 // check if the cluster belongs to the correct MC track
1106 for (Int_t iTrack=0; iTrack<cluster->GetNMCTracks(); iTrack++) {
1107 if (cluster->GetMCLabel(iTrack)==fLabelMC) {
1113 AliDebug(2,Form("returning %d\n", result));
1119 //======================================================================================================================================
1121 Double_t AliMuonForwardTrackFinder::TryOneCluster(const AliMUONTrackParam &trackParam, AliMFTCluster *cluster) {
1123 // Test the compatibility between the track and the cluster (using trackParam's covariance matrix):
1124 // return the corresponding Chi2
1125 // assume the track parameters are given at the Z of the cluster
1127 // Set differences between trackParam and cluster in the bending and non bending directions
1128 Double_t dX = cluster->GetX() - trackParam.GetNonBendingCoor();
1129 Double_t dY = cluster->GetY() - trackParam.GetBendingCoor();
1130 AliDebug(3,Form("dX = %f, dY = %f\n", dX, dY));
1132 // Calculate errors and covariances
1133 const TMatrixD& kParamCov = trackParam.GetCovariances();
1134 Double_t sigmaX2 = kParamCov(0,0) + cluster->GetErrX2();
1135 Double_t sigmaY2 = kParamCov(2,2) + cluster->GetErrY2();
1136 AliDebug(3, Form("dX2 = %f, dY2 = %f\n", sigmaX2, sigmaY2));
1137 Double_t covXY = kParamCov(0,2);
1138 Double_t det = sigmaX2 * sigmaY2 - covXY * covXY;
1141 if (det==0.) return 1.e10;
1142 return (dX*dX*sigmaY2 + dY*dY*sigmaX2 - 2.*dX*dY*covXY) / det;
1146 //=========================================================================================================================================
1148 void AliMuonForwardTrackFinder::SeparateFrontBackClusters() {
1150 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1151 fMFTClusterArrayFront[iPlane]->Clear();
1152 fMFTClusterArrayBack[iPlane] ->Clear();
1153 for (Int_t iCluster=0; iCluster<fMFTClusterArray[iPlane]->GetEntries(); iCluster++) {
1154 AliMFTCluster *cluster = (AliMFTCluster*) fMFTClusterArray[iPlane]->At(iCluster);
1155 if (TMath::Abs(cluster->GetZ())<TMath::Abs(fSegmentation->GetPlane(iPlane)->GetZCenter())) {
1156 new ((*fMFTClusterArrayFront[iPlane])[fMFTClusterArrayFront[iPlane]->GetEntries()]) AliMFTCluster(*cluster);
1159 new ((*fMFTClusterArrayBack[iPlane])[fMFTClusterArrayBack[iPlane]->GetEntries()]) AliMFTCluster(*cluster);
1166 //=========================================================================================================================================
1168 Int_t AliMuonForwardTrackFinder::GetNDF(Int_t nClusters) {
1170 // the same definition as in AliMUONTrack is implemented, since here we just add more clusters to the Muon track
1172 Int_t ndf = 2 * nClusters - 5;
1173 return (ndf > 0) ? ndf : 0;
1177 //============================================================================================================================================
1179 void AliMuonForwardTrackFinder::BookHistos() {
1181 const Int_t nMaxNewTracks[] = {150, 200, 250, 600, 1000};
1182 const Double_t radiusPlane[] = {0.010, 0.010, 0.050, 0.5, 1.5};
1184 fHistRadiusEndOfAbsorber = new TH1D("hRadiusEndOfAbsorber", "Track radial distance at the end of the absorber", 1000, 0, 100.);
1186 fHistNGoodClustersForFinalTracks = new TH1D("hNGoodClustersForFinalTracks", "Number of Good Clusters per Final Track", 20, -0.25, 9.75);
1188 fHistDistanceGoodClusterFromTrackAtLastPlane = new TH1D("hDistanceGoodClusterFromTrackAtLastPlane",
1189 "Distance of MC Good Cluster from Track in last MFT plane", 200, 0., 2.);
1191 fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane =
1192 new TH1D("hDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane",
1193 "Good Cluster distance from track - Best Cluster distance from track in last MFT plane", 200, 0., 2.);
1195 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
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);
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]);
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),
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),
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),
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),
1223 //------------------------------------------
1225 fHistRadiusEndOfAbsorber -> Sumw2();
1226 fHistNGoodClustersForFinalTracks -> Sumw2();
1228 fHistDistanceGoodClusterFromTrackAtLastPlane -> Sumw2();
1229 fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane -> Sumw2();
1231 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1233 fHistNTracksAfterExtrapolation[iPlane] -> Sumw2();
1234 fHistResearchRadius[iPlane] -> Sumw2();
1236 fHistChi2Cluster_GoodCluster[iPlane] -> Sumw2();
1237 fHistChi2Cluster_BadCluster[iPlane] -> Sumw2();
1239 fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[iPlane] -> Sumw2();
1240 fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[iPlane] -> Sumw2();
1244 fNtuFinalCandidates = new TNtuple("ntuFinalCandidates", "Final Candidates (ALL)", "run:event:muonTrack:nFinalCandidates:MCTrackRefExists:xVtx:yVtx:zVtx:triggerMatch:nClustersMC:nGoodClusters:pt:theta:eta:chi2AtPlane0:chi2AtPlane1:chi2AtPlane2:chi2AtPlane3:chi2AtPlane4:chi2AtPlane5:chi2AtPlane6:chi2AtPlane7:chi2AtPlane8");
1246 fNtuFinalBestCandidates = new TNtuple("ntuFinalBestCandidates", "Final Best Candidates", "run:event:muonTrack:nFinalCandidates:MCTrackRefExists:xVtx:yVtx:zVtx:triggerMatch:nClustersMC:nGoodClusters:pt:theta:eta:chi2AtPlane0:chi2AtPlane1:chi2AtPlane2:chi2AtPlane3:chi2AtPlane4:chi2AtPlane5:chi2AtPlane6:chi2AtPlane7:chi2AtPlane8:nClustersAtPlane0:nClustersAtPlane1:nClustersAtPlane2:nClustersAtPlane3:nClustersAtPlane4:nClustersAtPlane5:nClustersAtPlane6:nClustersAtPlane7:nClustersAtPlane8");
1250 //============================================================================================================================================
1252 void AliMuonForwardTrackFinder::SetTitleHistos() {
1254 fHistRadiusEndOfAbsorber -> SetXTitle("R_{abs} [cm]");
1255 fHistNGoodClustersForFinalTracks -> SetXTitle("N_{GoodClusters}");
1257 fHistDistanceGoodClusterFromTrackAtLastPlane -> SetXTitle("Distance [cm]");
1258 fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane -> SetXTitle("Distance [cm]");
1261 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1263 fHistNTracksAfterExtrapolation[iPlane] -> SetXTitle("N_{tracks}");
1264 fHistResearchRadius[iPlane] -> SetXTitle("Research Radius [cm]");
1266 fHistChi2Cluster_GoodCluster[iPlane] -> SetXTitle("#chi^{2}/ndf");
1267 fHistChi2Cluster_BadCluster[iPlane] -> SetXTitle("#chi^{2}/ndf");
1269 fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[iPlane] -> SetXTitle("#chi^{2}/ndf");
1270 fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[iPlane] -> SetXTitle("#chi^{2}/ndf");
1276 //===========================================================================================================================================
1278 void AliMuonForwardTrackFinder::BookPlanes() {
1280 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1281 fGrMFTPlane[kAllClusters][iPlane] = new TGraph();
1282 fGrMFTPlane[kAllClusters][iPlane] -> SetName(Form("fGrMFTPlane_%02d_AllClusters",iPlane));
1283 fGrMFTPlane[kAllClusters][iPlane] -> SetMarkerStyle(20);
1284 // fGrMFTPlane[kAllClusters][iPlane] -> SetMarkerSize(0.5);
1285 // fGrMFTPlane[kAllClusters][iPlane] -> SetMarkerSize(0.3);
1286 fGrMFTPlane[kAllClusters][iPlane] -> SetMarkerSize(0.2);
1289 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1290 fGrMFTPlane[kClustersGoodChi2][iPlane] = new TGraph();
1291 fGrMFTPlane[kClustersGoodChi2][iPlane] -> SetName(Form("fGrMFTPlane_%02d_ClustersGoodChi2",iPlane));
1292 fGrMFTPlane[kClustersGoodChi2][iPlane] -> SetMarkerStyle(20);
1293 // fGrMFTPlane[kClustersGoodChi2][iPlane] -> SetMarkerSize(0.8);
1294 // fGrMFTPlane[kClustersGoodChi2][iPlane] -> SetMarkerSize(0.4);
1295 fGrMFTPlane[kClustersGoodChi2][iPlane] -> SetMarkerSize(0.3);
1296 fGrMFTPlane[kClustersGoodChi2][iPlane] -> SetMarkerColor(kBlue);
1299 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1300 fGrMFTPlane[kClusterOfTrack][iPlane] = new TGraph();
1301 fGrMFTPlane[kClusterOfTrack][iPlane] -> SetName(Form("fGrMFTPlane_%02d_ClustersOfTrack",iPlane));
1302 fGrMFTPlane[kClusterOfTrack][iPlane] -> SetMarkerStyle(25);
1303 // fGrMFTPlane[kClusterOfTrack][iPlane] -> SetMarkerSize(1.2);
1304 fGrMFTPlane[kClusterOfTrack][iPlane] -> SetMarkerSize(0.9);
1305 fGrMFTPlane[kClusterOfTrack][iPlane] -> SetMarkerColor(kRed);
1306 fGrMFTPlane[kClusterOfTrack][iPlane] -> SetTitle(Form("Plane %d (%3.1f cm)", iPlane, fZPlane[iPlane]));
1309 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1310 fGrMFTPlane[kClusterCorrectMC][iPlane] = new TGraph();
1311 fGrMFTPlane[kClusterCorrectMC][iPlane] -> SetName(Form("fGrMFTPlane_%02d_ClustersCorrectMC",iPlane));
1312 fGrMFTPlane[kClusterCorrectMC][iPlane] -> SetMarkerStyle(20);
1313 // fGrMFTPlane[kClusterCorrectMC][iPlane] -> SetMarkerSize(0.8);
1314 fGrMFTPlane[kClusterCorrectMC][iPlane] -> SetMarkerSize(0.5);
1315 fGrMFTPlane[kClusterCorrectMC][iPlane] -> SetMarkerColor(kGreen);
1318 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1319 fCircleExt[iPlane] = new TEllipse(0., 0., fRPlaneMax[iPlane], fRPlaneMax[iPlane]);
1320 fCircleInt[iPlane] = new TEllipse(0., 0., fRPlaneMin[iPlane], fRPlaneMin[iPlane]);
1323 fTxtDummy = new TLatex(0.10, 0.59, "Best Candidate:");
1325 //---------------------------------------------------
1327 fMrkAllClust = new TMarker(0.10, 0.32, 20);
1328 fMrkAllClust -> SetMarkerSize(0.5);
1330 fMrkClustGoodChi2 = new TMarker(0.10, 0.26, 20);
1331 fMrkClustGoodChi2 -> SetMarkerSize(0.8);
1332 fMrkClustGoodChi2 -> SetMarkerColor(kBlue);
1334 fMrkClustMC = new TMarker(0.10, 0.20, 20);
1335 fMrkClustMC -> SetMarkerSize(0.8);
1336 fMrkClustMC -> SetMarkerColor(kGreen);
1338 fMrkClustOfTrack = new TMarker(0.10, 0.14, 25);
1339 fMrkClustOfTrack -> SetMarkerSize(1.2);
1340 fMrkClustOfTrack -> SetMarkerColor(kRed);
1342 fTxtAllClust = new TLatex(0.15, 0.30, "All Clusters");
1343 fTxtAllClust -> SetTextSize(0.040);
1345 fTxtClustGoodChi2 = new TLatex(0.15, 0.24, "Clusters involved in the research");
1346 fTxtClustGoodChi2 -> SetTextSize(0.040);
1348 fTxtClustMC = new TLatex(0.15, 0.18, "MC good clusters");
1349 fTxtClustMC -> SetTextSize(0.040);
1351 fTxtClustOfTrack = new TLatex(0.15, 0.12, "Clusters of the best candidate");
1352 fTxtClustOfTrack -> SetTextSize(0.040);
1356 //===========================================================================================================================================
1358 void AliMuonForwardTrackFinder::ResetPlanes() {
1360 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1361 for (Int_t iGr=0; iGr<4; iGr++) {
1362 Int_t nOldClusters = fGrMFTPlane[iGr][iPlane]->GetN();
1363 for (Int_t iPoint=nOldClusters-1; iPoint>=0; iPoint--) fGrMFTPlane[iGr][iPlane]->RemovePoint(iPoint);
1369 //===========================================================================================================================================
1371 void AliMuonForwardTrackFinder::PrintParticleHistory() {
1373 AliDebug(1, "Entering");
1375 TString history = "";
1377 TParticle *part = 0;
1378 if (fLabelMC>=0) part = fStack->Particle(fLabelMC);
1380 AliDebug(1, Form("fStack->Particle(fLabelMC) = %p", part));
1383 if (part->GetFirstMother() != -1) {
1384 TParticle *partMother = fStack->Particle(part->GetFirstMother());
1385 AliDebug(1, Form("fStack->Particle(part->GetFirstMother() = %p", partMother));
1387 Char_t newName[100];
1388 if (partMother->GetFirstMother() != -1) history += "... #rightarrow ";
1389 PDGNameConverter(partMother->GetName(), newName);
1390 history += Form("%s #rightarrow ", newName);
1393 Char_t newName[100];
1394 PDGNameConverter(part->GetName(), newName);
1395 history += Form("%s at z = %5.1f cm", newName, part->Vz());
1396 // printf("%s", history.Data());
1398 else history += "NO AVAILABLE HISTORY";
1400 fTxtMuonHistory = new TLatex(0.10, 0.86, history.Data());
1402 // Filling particle history in the fFinalBestCandidate
1405 for (Int_t iParent=0; iParent<AliMuonForwardTrack::fgkNParentsMax; iParent++) {
1406 if (part->GetFirstMother() == -1) break;
1407 if (!(fStack->Particle(part->GetFirstMother()))) break;
1408 AliDebug(1, Form("fStack->Particle(part->GetFirstMother() = %p", fStack->Particle(part->GetFirstMother())));
1409 fFinalBestCandidate->SetParentMCLabel(iParent, part->GetFirstMother());
1410 fFinalBestCandidate->SetParentPDGCode(iParent, fStack->Particle(part->GetFirstMother())->GetPdgCode());
1411 part = fStack->Particle(part->GetFirstMother());
1417 //===========================================================================================================================================
1419 Bool_t AliMuonForwardTrackFinder::IsMother(Char_t *nameMother) {
1421 Bool_t result = kFALSE;
1423 TParticle *part = 0;
1424 if (fLabelMC>=0) part = fStack->Particle(fLabelMC);
1427 if (part->GetFirstMother() != -1) {
1428 TParticle *partMother = fStack->Particle(part->GetFirstMother());
1430 if (!strcmp(partMother->GetName(), nameMother)) result=kTRUE;
1439 //===========================================================================================================================================
1441 void AliMuonForwardTrackFinder::DrawPlanes() {
1444 if (fNPlanesMFT <= 5) fCanvas -> Divide(3,2);
1445 else if (fNPlanesMFT <= 11) fCanvas -> Divide(4,3);
1446 else if (fNPlanesMFT <= 19) fCanvas -> Divide(5,4);
1448 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1450 fCanvas->cd(fNPlanesMFT-iPlane+1);
1452 fGrMFTPlane[kClusterOfTrack][iPlane] -> GetXaxis() -> SetLimits(-1.1*fRPlaneMax[fNPlanesMFT-1], +1.1*fRPlaneMax[fNPlanesMFT-1]);
1453 fGrMFTPlane[kClusterOfTrack][iPlane] -> GetYaxis() -> SetRangeUser(-1.1*fRPlaneMax[fNPlanesMFT-1], +1.1*fRPlaneMax[fNPlanesMFT-1]);
1454 fGrMFTPlane[kClusterOfTrack][iPlane] -> GetXaxis() -> SetTitle("X [cm]");
1455 fGrMFTPlane[kClusterOfTrack][iPlane] -> GetYaxis() -> SetTitle("Y [cm]");
1456 fGrMFTPlane[kClusterOfTrack][iPlane] -> Draw("ap");
1458 fCircleExt[iPlane] -> Draw("same");
1459 fCircleInt[iPlane] -> Draw("same");
1461 if (fGrMFTPlane[kAllClusters][iPlane]->GetN()) fGrMFTPlane[kAllClusters][iPlane] -> Draw("psame");
1462 if (fGrMFTPlane[kClustersGoodChi2][iPlane]->GetN()) fGrMFTPlane[kClustersGoodChi2][iPlane] -> Draw("psame");
1463 if (fGrMFTPlane[kClusterOfTrack][iPlane]->GetN()) fGrMFTPlane[kClusterOfTrack][iPlane] -> Draw("psame");
1464 if (fGrMFTPlane[kClusterCorrectMC][iPlane]->GetN()) fGrMFTPlane[kClusterCorrectMC][iPlane] -> Draw("psame");
1466 fTxtTrackChi2[iPlane] -> Draw("same");
1471 fTxtMuonHistory -> Draw();
1472 fTxtDummy -> Draw("same");
1473 if (fMatchingMode==kRealMatching) fTxtTrackGoodClusters -> Draw("same");
1474 fTxtTrackFinalChi2 -> Draw("same");
1475 fTxtTrackMomentum -> Draw("same");
1476 if (fMatchingMode==kRealMatching) fTxtFinalCandidates -> Draw("same");
1478 fMrkAllClust -> Draw("same");
1479 fMrkClustGoodChi2 -> Draw("same");
1480 fMrkClustMC -> Draw("same");
1481 fMrkClustOfTrack -> Draw("same");
1483 fTxtAllClust -> Draw("same");
1484 fTxtClustGoodChi2 -> Draw("same");
1485 fTxtClustMC -> Draw("same");
1486 fTxtClustOfTrack -> Draw("same");
1488 // fCanvas -> SaveAs(Form("%s/figures/eventDisplay/run%d_event%d_track%d.eps", fOutDir.Data(), fRun, fEv, fCountRealTracksAnalyzedOfEvent));
1489 fCanvas -> SaveAs(Form("%s/figures/eventDisplay/run%d_event%d_track%d.gif", fOutDir.Data(), fRun, fEv, fCountRealTracksAnalyzedOfEvent));
1490 if (IsMother("phi")) {
1491 fCanvas -> SaveAs(Form("%s/figures/eventDisplay/run%d_event%d_track%d.phi.gif", fOutDir.Data(), fRun, fEv, fCountRealTracksAnalyzedOfEvent));
1492 fCanvas -> SaveAs(Form("%s/figures/eventDisplay/run%d_event%d_track%d.phi.eps", fOutDir.Data(), fRun, fEv, fCountRealTracksAnalyzedOfEvent));
1494 if (IsMother("J/psi")) {
1495 fCanvas -> SaveAs(Form("%s/figures/eventDisplay/run%d_event%d_track%d.jPsi.gif", fOutDir.Data(), fRun, fEv, fCountRealTracksAnalyzedOfEvent));
1496 fCanvas -> SaveAs(Form("%s/figures/eventDisplay/run%d_event%d_track%d.jPsi.eps", fOutDir.Data(), fRun, fEv, fCountRealTracksAnalyzedOfEvent));
1501 //===========================================================================================================================================
1503 void AliMuonForwardTrackFinder::Terminate() {
1506 AliInfo("---------------------------------------------------------------------------------------------------------------");
1507 AliInfo(Form("%8d tracks analyzed", fCountRealTracksAnalyzed));
1508 AliInfo(Form("%8d tracks with MC ref", fCountRealTracksWithRefMC));
1509 AliInfo(Form("%8d tracks with MC ref & trigger match", fCountRealTracksWithRefMC_andTrigger));
1510 if (fMatchingMode==kRealMatching) {
1511 AliInfo(Form("%8d tracks analyzed with final candidates", fCountRealTracksAnalyzedWithFinalCandidates));
1514 AliInfo(Form("%8d tracks matched with their MC clusters", fCountRealTracksAnalyzedWithFinalCandidates));
1516 // printf("%8d tracks with MC ref & trigger match & pt>%3.1f GeV/c", fCountRealTracksWithRefMC_andTrigger_andGoodPt, fLowPtCut);
1517 // printf("%8d tracks with MC ref & trigger match & pt>%3.1f GeV/c & correct R_abs", fCountRealTracksWithRefMC_andTrigger_andGoodPt_andGoodTheta, fLowPtCut);
1518 AliInfo("---------------------------------------------------------------------------------------------------------------");
1525 //==========================================================================================================================================
1527 void AliMuonForwardTrackFinder::FillOutputTree() {
1529 if (!fMuonForwardTracks || !fOutputEventTree) return;
1531 AliDebug(1, Form("Filling output tree %p with %p having %d entries whose 1st entry is %p",
1532 fOutputEventTree, fMuonForwardTracks, fMuonForwardTracks->GetEntries(), fMuonForwardTracks->At(0)));
1534 // fOutputTreeFile->cd();
1535 fOutputEventTree->Fill();
1536 AliDebug(1, Form("\nFilled Tree: nEvents = %d!!!!\n", Int_t(fOutputEventTree->GetEntries())));
1540 //==========================================================================================================================================
1542 void AliMuonForwardTrackFinder::WriteOutputTree() {
1544 if (!fOutputEventTree || !fOutputTreeFile) return;
1546 fOutputTreeFile -> cd();
1548 fOutputEventTree -> Write();
1549 fOutputTreeFile -> Close();
1553 //==========================================================================================================================================
1555 void AliMuonForwardTrackFinder::WriteHistos() {
1557 fOutputQAFile = new TFile(Form("MuonGlobalTracking.QA.run%d.root", fRun), "recreate");
1558 fOutputQAFile -> cd();
1560 fHistRadiusEndOfAbsorber -> Write();
1561 fHistNGoodClustersForFinalTracks -> Write();
1563 fHistDistanceGoodClusterFromTrackAtLastPlane -> Write();
1564 fHistDistanceGoodClusterFromTrackMinusDistanceBestClusterFromTrackAtLastPlane -> Write();
1566 for (Int_t iPlane=0; iPlane<fNPlanesMFT; iPlane++) {
1568 fHistNTracksAfterExtrapolation[iPlane] -> Write();
1569 fHistResearchRadius[iPlane] -> Write();
1571 fHistChi2Cluster_GoodCluster[iPlane] -> Write();
1572 fHistChi2Cluster_BadCluster[iPlane] -> Write();
1574 fHistGlobalChi2AtPlaneFor_GOOD_CandidatesOfTrackableMuons[iPlane] -> Write();
1575 fHistGlobalChi2AtPlaneFor_BAD_CandidatesOfTrackableMuons[iPlane] -> Write();
1579 fNtuFinalCandidates -> Write();
1580 fNtuFinalBestCandidates -> Write();
1582 fOutputQAFile -> Close();
1586 //===========================================================================================================================================
1588 void AliMuonForwardTrackFinder::PDGNameConverter(const Char_t *nameIn, Char_t *nameOut) {
1590 if (!strcmp(nameIn, "mu+")) sprintf(nameOut, "#mu^{+}");
1591 else if (!strcmp(nameIn, "mu-")) sprintf(nameOut, "#mu^{-}");
1592 else if (!strcmp(nameIn, "pi+")) sprintf(nameOut, "#pi^{+}");
1593 else if (!strcmp(nameIn, "pi-")) sprintf(nameOut, "#pi^{-}");
1594 else if (!strcmp(nameIn, "K+")) sprintf(nameOut, "K^{+}");
1595 else if (!strcmp(nameIn, "K-")) sprintf(nameOut, "K^{-}");
1596 else if (!strcmp(nameIn, "K*+")) sprintf(nameOut, "K^{*+}");
1597 else if (!strcmp(nameIn, "K*-")) sprintf(nameOut, "K^{*-}");
1598 else if (!strcmp(nameIn, "K_S0")) sprintf(nameOut, "K_{S}^{0}");
1599 else if (!strcmp(nameIn, "K_L0")) sprintf(nameOut, "K_{L}^{0}");
1600 else if (!strcmp(nameIn, "K0")) sprintf(nameOut, "K^{0}");
1601 else if (!strcmp(nameIn, "K0_bar")) sprintf(nameOut, "#bar{K}^{0}");
1602 else if (!strcmp(nameIn, "K*0")) sprintf(nameOut, "K^{*0}");
1603 else if (!strcmp(nameIn, "K*0_bar")) sprintf(nameOut, "#bar{K}^{*0}");
1604 else if (!strcmp(nameIn, "rho0")) sprintf(nameOut, "#rho^{0}");
1605 else if (!strcmp(nameIn, "rho+")) sprintf(nameOut, "#rho^{+}");
1606 else if (!strcmp(nameIn, "rho-")) sprintf(nameOut, "#rho^{-}");
1607 else if (!strcmp(nameIn, "omega")) sprintf(nameOut, "#omega");
1608 else if (!strcmp(nameIn, "eta'")) sprintf(nameOut, "#eta'");
1609 else if (!strcmp(nameIn, "phi")) sprintf(nameOut, "#phi");
1611 else if (!strcmp(nameIn, "D-")) sprintf(nameOut, "D^{-}");
1612 else if (!strcmp(nameIn, "D+")) sprintf(nameOut, "D^{+}");
1613 else if (!strcmp(nameIn, "D0")) sprintf(nameOut, "D^{0}");
1614 else if (!strcmp(nameIn, "D0_bar")) sprintf(nameOut, "#bar{D}^{0}");
1615 else if (!strcmp(nameIn, "D*-")) sprintf(nameOut, "D^{*-}");
1616 else if (!strcmp(nameIn, "D*+")) sprintf(nameOut, "D^{*+}");
1617 else if (!strcmp(nameIn, "D_s+")) sprintf(nameOut, "D_{s}^{+}");
1618 else if (!strcmp(nameIn, "D*_s+")) sprintf(nameOut, "D_{s}^{*+}");
1620 else if (!strcmp(nameIn, "B-")) sprintf(nameOut, "B^{-}");
1621 else if (!strcmp(nameIn, "B+")) sprintf(nameOut, "B^{+}");
1622 else if (!strcmp(nameIn, "B_s0_bar")) sprintf(nameOut, "#bar{B}_{s}^{0}");
1624 else if (!strcmp(nameIn, "antiproton")) sprintf(nameOut, "#bar{p}");
1625 else if (!strcmp(nameIn, "proton")) sprintf(nameOut, "p");
1626 else if (!strcmp(nameIn, "neutron")) sprintf(nameOut, "n");
1627 else if (!strcmp(nameIn, "Sigma+")) sprintf(nameOut, "#Sigma^{+}");
1628 else if (!strcmp(nameIn, "Delta+")) sprintf(nameOut, "#Delta{+}");
1629 else if (!strcmp(nameIn, "Delta--")) sprintf(nameOut, "#Delta{--}");
1630 else if (!strcmp(nameIn, "Lambda0")) sprintf(nameOut, "#Lambda_0");
1631 else if (!strcmp(nameIn, "Lambda0_bar")) sprintf(nameOut, "#bar{Lambda}_0");
1633 else sprintf(nameOut, "%s", nameIn);
1637 //===========================================================================================================================================
1639 void AliMuonForwardTrackFinder::SetDraw(Bool_t drawOption) {
1641 fDrawOption = drawOption;
1644 fCanvas = new TCanvas("tracking", "tracking", 1200, 800);
1645 fCanvas -> Divide(3,2);
1650 //===========================================================================================================================================
1652 Bool_t AliMuonForwardTrackFinder::InitGRP() {
1654 //------------------------------------
1655 // Initialization of the GRP entry
1656 //------------------------------------
1658 AliCDBEntry* entry = AliCDBManager::Instance()->Get("GRP/GRP/Data");
1662 TMap* m = dynamic_cast<TMap*>(entry->GetObject()); // old GRP entry
1665 AliInfo("Found a TMap in GRP/GRP/Data, converting it into an AliGRPObject");
1667 fGRPData = new AliGRPObject();
1668 fGRPData->ReadValuesFromMap(m);
1672 AliInfo("Found an AliGRPObject in GRP/GRP/Data, reading it");
1673 fGRPData = dynamic_cast<AliGRPObject*>(entry->GetObject()); // new GRP entry
1677 // FIX ME: The unloading of GRP entry is temporarily disabled
1678 // because ZDC and VZERO are using it in order to initialize
1679 // their reconstructor objects. In the future one has to think
1680 // of propagating AliRunInfo to the reconstructors.
1681 // AliCDBManager::Instance()->UnloadFromCache("GRP/GRP/Data");
1685 AliError("No GRP entry found in OCDB!");
1689 TString lhcState = fGRPData->GetLHCState();
1690 if (lhcState==AliGRPObject::GetInvalidString()) {
1691 AliError("GRP/GRP/Data entry: missing value for the LHC state ! Using UNKNOWN");
1692 lhcState = "UNKNOWN";
1695 TString beamType = fGRPData->GetBeamType();
1696 if (beamType==AliGRPObject::GetInvalidString()) {
1697 AliError("GRP/GRP/Data entry: missing value for the beam type ! Using UNKNOWN");
1698 beamType = "UNKNOWN";
1701 Float_t beamEnergy = fGRPData->GetBeamEnergy();
1702 if (beamEnergy==AliGRPObject::GetInvalidFloat()) {
1703 AliError("GRP/GRP/Data entry: missing value for the beam energy ! Using 0");
1707 TString runType = fGRPData->GetRunType();
1708 if (runType==AliGRPObject::GetInvalidString()) {
1709 AliError("GRP/GRP/Data entry: missing value for the run type ! Using UNKNOWN");
1710 runType = "UNKNOWN";
1713 Int_t activeDetectors = fGRPData->GetDetectorMask();
1714 if (activeDetectors==AliGRPObject::GetInvalidUInt()) {
1715 AliError("GRP/GRP/Data entry: missing value for the detector mask ! Using 1074790399");
1716 activeDetectors = 1074790399;
1718 AliDebug(1, Form("activeDetectors = %d", activeDetectors));
1720 fRunInfo = new AliRunInfo(lhcState, beamType, beamEnergy, runType, activeDetectors);
1723 // *** Dealing with the magnetic field map
1725 if ( TGeoGlobalMagField::Instance()->IsLocked() ) {
1726 if (TGeoGlobalMagField::Instance()->GetField()->TestBit(AliMagF::kOverrideGRP)) {
1727 AliInfo("ExpertMode!!! GRP information will be ignored !");
1728 AliInfo("ExpertMode!!! Running with the externally locked B field !");
1731 AliInfo("Destroying existing B field instance!");
1732 delete TGeoGlobalMagField::Instance();
1735 if ( !TGeoGlobalMagField::Instance()->IsLocked() ) {
1736 // Construct the field map out of the information retrieved from GRP.
1739 Float_t l3Current = fGRPData->GetL3Current((AliGRPObject::Stats)0);
1740 if (l3Current == AliGRPObject::GetInvalidFloat()) {
1741 AliError("GRP/GRP/Data entry: missing value for the L3 current !");
1745 Char_t l3Polarity = fGRPData->GetL3Polarity();
1746 if (l3Polarity == AliGRPObject::GetInvalidChar()) {
1747 AliError("GRP/GRP/Data entry: missing value for the L3 polarity !");
1752 Float_t diCurrent = fGRPData->GetDipoleCurrent((AliGRPObject::Stats)0);
1753 if (diCurrent == AliGRPObject::GetInvalidFloat()) {
1754 AliError("GRP/GRP/Data entry: missing value for the dipole current !");
1758 Char_t diPolarity = fGRPData->GetDipolePolarity();
1759 if (diPolarity == AliGRPObject::GetInvalidChar()) {
1760 AliError("GRP/GRP/Data entry: missing value for the dipole polarity !");
1764 // read special bits for the polarity convention and map type
1765 Int_t polConvention = fGRPData->IsPolarityConventionLHC() ? AliMagF::kConvLHC : AliMagF::kConvDCS2008;
1766 Bool_t uniformB = fGRPData->IsUniformBMap();
1769 AliMagF* fld = AliMagF::CreateFieldMap(TMath::Abs(l3Current) * (l3Polarity ? -1:1),
1770 TMath::Abs(diCurrent) * (diPolarity ? -1:1),
1771 polConvention,uniformB,beamEnergy, beamType.Data());
1773 TGeoGlobalMagField::Instance()->SetField( fld );
1774 TGeoGlobalMagField::Instance()->Lock();
1775 AliInfo("Running with the B field constructed out of GRP !");
1777 else AliFatal("Failed to create a B field map !");
1779 else AliFatal("B field is neither set nor constructed from GRP ! Exitig...");
1785 //====================================================================================================================================================
1787 Bool_t AliMuonForwardTrackFinder::SetRunNumber() {
1789 AliCDBManager *man = AliCDBManager::Instance();
1792 AliError("No run loader found!");
1796 fRunLoader->LoadHeader();
1797 // read run number from gAlice
1798 if (fRunLoader->GetHeader()) {
1799 man->SetRun(fRunLoader->GetHeader()->GetRun());
1800 fRunLoader->UnloadHeader();
1803 AliError("No run-loader header found!");
1812 //====================================================================================================================================================