60ff78f119b5d35cd820480eeda2860317d98ef7
[u/mrichter/AliRoot.git] / MUON / MUONFakes.C
1 #if !defined(__CINT__) || defined(__MAKECINT__)
2 // ROOT includes
3 #include <TFile.h>
4 #include <TH1.h>
5 #include <TCanvas.h>
6 #include <Riostream.h>
7 #include <TROOT.h>
8 #include <TClonesArray.h>
9 #include <TArrayI.h>
10
11 // STEER includes
12 #include "AliLog.h"
13 #include "AliESDEvent.h"
14 #include "AliESDMuonTrack.h"
15 #include "AliCDBManager.h"
16   
17 // MUON includes
18 #include "AliMUONCDB.h"
19 #include "AliMUONTrack.h"
20 #include "AliMUONVTrackStore.h"
21 #include "AliMUONTrackParam.h"
22 #include "AliMUONESDInterface.h"
23 #include "AliMUONRecoCheck.h"
24 #include "AliMUONVCluster.h"
25 #include "AliMUONRecoParam.h"
26 #endif
27
28 /// \ingroup macros
29 /// \file MUONFakes.C
30 ///
31 /// \author Ph. Pillot, Subatech, March. 2009
32 ///
33 /// Macro to study fake tracks by comparing reconstructed tracks with TrackRefs
34 /// Results are saved in the root file Fakes.root
35 /// Results are relevent provided that you use the same recoParams as for the reconstruction
36
37 Bool_t TrackMatched(AliMUONTrack &track, AliMUONTrack &trackRef, Float_t &fractionOfMatchCluster, Double_t sigmaCut);
38 Bool_t IsRecontructible(AliMUONTrack &track, AliMUONRecoParam &recoParam);
39 AliMUONTrack* MatchWithTrackRef(AliMUONTrack &muonTrack, AliMUONVTrackStore &trackRefStore,
40                                 Float_t &fractionOfMatchCluster, Bool_t useLabel, Double_t sigmaCut);
41 Int_t RemoveConnectedFakes(AliMUONVTrackStore &fakeTrackStore, AliMUONVTrackStore &trackRefStore, AliMUONRecoParam &recoParam,
42                            Bool_t useLabel, Double_t sigmaCut, TH1F &hFractionOfConnectedClusters);
43
44 //-----------------------------------------------------------------------
45 void MUONFakes(Bool_t useLabel = kFALSE, Int_t FirstEvent = 0, Int_t LastEvent = -1,
46                const TString esdFileName = "AliESDs.root", const TString SimDir = "./generated/",
47                const TString ocdbPath = "local://$ALICE_ROOT/OCDB")
48 {
49   
50   //Reset ROOT and connect tree file
51   gROOT->Reset();
52   
53   // File for histograms and histogram booking
54   TFile *histoFile = new TFile("Fakes.root", "RECREATE");
55   
56   TH1F *hNumberOfTracks = new TH1F("hNumberOfTracks","nb of tracks /evt",20,0.,20.);
57   TH1F *hNumberOfAdditionalTracks = new TH1F("hNumberOfAdditionalTracks","nb of fake - nb of missing track",20,0.,20.);
58   
59   TH1F *hNumberOfClusters = new TH1F("hNumberOfClusters","nb of clusters /track",20,0.,20.);
60   TH1F *hNumberOfClustersM = new TH1F("hNumberOfClustersM","nb of clusters /matched track",20,0.,20.);
61   TH1F *hNumberOfClustersF = new TH1F("hNumberOfClustersF","nb of clusters /fake track",20,0.,20.);
62   TH1F *hNumberOfClustersMC = new TH1F("hNumberOfClustersMC","nb of clusters /MC track",20,0.,20.);
63   TH1F *hFractionOfMatchedClusters = new TH1F("hFractionOfMatchedClusters","nb of matched clusters / nb of clusters",110,0.,1.1);
64   TH1F *hFractionOfConnectedClusters = new TH1F("hFractionOfConnectedClusters","nb of connected clusters / nb of clusters in fake tracks",110,0.,1.1);
65   
66   TH1F *hChi2PerDof = new TH1F("hChi2PerDof", "track chi2/d.o.f.", 100, 0., 20.);
67   TH1F *hChi2PerDofM = new TH1F("hChi2PerDofM", "matched track chi2/d.o.f.", 100, 0., 20.);
68   TH1F *hChi2PerDofF = new TH1F("hChi2PerDofF", "fake track chi2/d.o.f.", 100, 0., 20.);
69   TH1F *hP = new TH1F("hP", "Muon P distribution (GeV/c)", 100, 0., 200.);
70   TH1F *hPM = new TH1F("hPM", "matched track P distribution (GeV/c)", 100, 0., 200.);
71   TH1F *hPF = new TH1F("hPF", "fake track P distribution (GeV/c)", 100, 0., 200.);
72   TH1F *hPt = new TH1F("hPt", "Muon Pt distribution (GeV/c)", 100, 0., 20.);
73   TH1F *hPtM = new TH1F("hPtM", "matched track Pt distribution (GeV/c)", 100, 0., 20.);
74   TH1F *hPtF = new TH1F("hPtF", "fake track Pt distribution (GeV/c)", 100, 0., 20.);
75   TH1F *hEta = new TH1F("hEta"," Muon pseudo-rapidity distribution",100,-10,0);
76   TH1F *hEtaM = new TH1F("hEtaM"," matched track pseudo-rapidity distribution",100,-10,0);
77   TH1F *hEtaF = new TH1F("hEtaF"," fake track pseudo-rapidity distribution",100,-10,0);
78   TH1F *hPhi = new TH1F("hPhi"," Muon phi distribution",100,-1.,9.);
79   TH1F *hPhiM = new TH1F("hPhiM"," matched track phi distribution",100,-1.,9.);
80   TH1F *hPhiF = new TH1F("hPhiF"," fake track phi distribution",100,-1.,9.);
81   
82   // link to reconstructed and simulated tracks
83   AliMUONRecoCheck rc(esdFileName, SimDir);
84   
85   // load necessary data from OCDB
86   AliCDBManager::Instance()->SetDefaultStorage(ocdbPath);
87   AliCDBManager::Instance()->SetRun(rc.GetRunNumber());
88   AliMUONRecoParam* recoParam = AliMUONCDB::LoadRecoParam();
89   if (!recoParam) return;
90   
91   // get sigma cut from recoParam to associate clusters with TrackRefs in case the label are not used
92   Double_t sigmaCut = (recoParam->ImproveTracks()) ? recoParam->GetSigmaCutForImprovement() : recoParam->GetSigmaCutForTracking();
93   
94   // initialize global counters
95   Int_t nReconstructibleTracks = 0;
96   Int_t nReconstructedTracks = 0;
97   Int_t nEventsWithTrackReconstructedYet = 0;
98   Int_t nEventsWithFake = 0;
99   Int_t nEventsWithAdditionalFake = 0;
100   Int_t nTotMatchedTracks = 0;
101   Int_t nTotTracksReconstructedYet = 0;
102   Int_t nTotFakeTracks = 0;
103   Int_t nTotConnectedTracks = 0;
104   Int_t nTotAdditionalTracks = 0;
105   Bool_t trackReconstructedYet;
106   TArrayI eventsWithTrackReconstructedYet(10);
107   TArrayI eventsWithFake(10);
108   TArrayI eventsWithAdditionalFake(10);
109   
110   // Loop over ESD events
111   FirstEvent = TMath::Max(0, FirstEvent);
112   LastEvent = (LastEvent>=0) ? TMath::Min(rc.NumberOfEvents() - 1, LastEvent) : rc.NumberOfEvents() - 1;
113   for (Int_t iEvent = FirstEvent; iEvent <= LastEvent; iEvent++) {
114     
115     // get reconstructed and simulated tracks
116     AliMUONVTrackStore* muonTrackStore = rc.ReconstructedTracks(iEvent, kFALSE);
117     AliMUONVTrackStore* trackRefStore = rc.TrackRefs(iEvent);
118     if (!muonTrackStore || !trackRefStore) continue;
119     
120     // count the number of reconstructible tracks
121     TIter next(trackRefStore->CreateIterator());
122     AliMUONTrack* trackRef;
123     while ( ( trackRef = static_cast<AliMUONTrack*>(next()) ) ) {
124       if (IsRecontructible(*trackRef,*recoParam)) nReconstructibleTracks++;
125     }
126     
127     // loop over ESD tracks
128     Int_t nTrackerTracks = 0;
129     trackReconstructedYet = kFALSE;
130     AliMUONVTrackStore *fakeTrackStore = AliMUONESDInterface::NewTrackStore();
131     const AliESDEvent* esd = rc.GetESDEvent();
132     Int_t nTracks = (Int_t)esd->GetNumberOfMuonTracks() ;
133     for (Int_t iTrack = 0; iTrack <  nTracks;  iTrack++) {
134       
135       AliESDMuonTrack* esdTrack = esd->GetMuonTrack(iTrack);
136       
137       // skip ghosts
138       if (!esdTrack->ContainTrackerData()) continue;
139       nTrackerTracks++;
140       
141       // find the corresponding MUON track
142       AliMUONTrack* muonTrack = (AliMUONTrack*) muonTrackStore->FindObject(esdTrack->GetUniqueID());
143       
144       // get track info
145       Int_t nClusters = esdTrack->GetNClusters();
146       Double_t normalizedChi2 = esdTrack->GetChi2() / (2. * esdTrack->GetNHit() - 5);
147       Double_t p = esdTrack->P();
148       Double_t pT = esdTrack->Pt();
149       Double_t eta = esdTrack->Eta();
150       Double_t phi = esdTrack->Phi();
151       
152       // fill global histograms
153       hNumberOfClusters->Fill(nClusters);
154       hChi2PerDof->Fill(normalizedChi2);
155       hP->Fill(p);
156       hPt->Fill(pT);
157       hEta->Fill(eta);
158       hPhi->Fill(phi);
159       
160       // try to match the reconstructed track with a simulated one
161       Float_t fractionOfMatchCluster = 0.;
162       AliMUONTrack* matchedTrackRef = MatchWithTrackRef(*muonTrack, *trackRefStore, fractionOfMatchCluster, useLabel, sigmaCut);
163       
164       // take actions according to matching result
165       if (matchedTrackRef) {
166         
167         // global counter
168         nTotMatchedTracks++;
169         if (!IsRecontructible(*matchedTrackRef,*recoParam)) {
170           trackReconstructedYet = kTRUE;
171           nTotTracksReconstructedYet++;
172         }
173         
174         // fill histograms
175         hFractionOfMatchedClusters->Fill(fractionOfMatchCluster);
176         hNumberOfClustersMC->Fill(matchedTrackRef->GetNClusters());
177         hNumberOfClustersM->Fill(nClusters);
178         hChi2PerDofM->Fill(normalizedChi2);
179         hPM->Fill(p);
180         hPtM->Fill(pT);
181         hEtaM->Fill(eta);
182         hPhiM->Fill(phi);
183         
184         // remove already matched trackRefs
185         trackRefStore->Remove(*matchedTrackRef);
186         
187       } else {
188         
189         // global counter
190         nTotFakeTracks++;
191         
192         // fill histograms
193         hNumberOfClustersF->Fill(nClusters);
194         hChi2PerDofF->Fill(normalizedChi2);
195         hPF->Fill(p);
196         hPtF->Fill(pT);
197         hEtaF->Fill(eta);
198         hPhiF->Fill(phi);
199         
200         // store fake tracks
201         fakeTrackStore->Add(*muonTrack);
202         
203       }
204       
205     } // end of loop over ESD tracks
206     
207     // fill histograms
208     hNumberOfTracks->Fill(nTrackerTracks);
209     nReconstructedTracks += nTrackerTracks;
210     if (trackReconstructedYet) eventsWithTrackReconstructedYet[nEventsWithTrackReconstructedYet++] = iEvent;
211     
212     // count the number the additional fake tracks
213     if (fakeTrackStore->GetSize() > 0) {
214       
215       // remove the most connected fake tracks
216       Int_t nFreeMissingTracks = RemoveConnectedFakes(*fakeTrackStore, *trackRefStore, *recoParam,
217                                                       useLabel, sigmaCut, *hFractionOfConnectedClusters);
218       
219       // remove the remaining free reconstructible tracks
220       Int_t nAdditionalTracks = fakeTrackStore->GetSize() - nFreeMissingTracks;
221       
222       // fill histograms
223       eventsWithFake[nEventsWithFake] = iEvent;
224       nEventsWithFake++;
225       if (nAdditionalTracks > 0) {
226         eventsWithAdditionalFake[nEventsWithAdditionalFake] = iEvent;
227         nEventsWithAdditionalFake++;
228         nTotAdditionalTracks += nAdditionalTracks;
229         hNumberOfAdditionalTracks->Fill(nAdditionalTracks);
230       }
231       
232     }
233     
234     delete fakeTrackStore;
235     
236   } // end of loop over events
237
238   // total number of connected tracks
239   nTotConnectedTracks = hFractionOfConnectedClusters->GetEntries();
240   
241   // plot results
242   TCanvas cFakesSummary("cFakesSummary","cFakesSummary",900,600);
243   cFakesSummary.Divide(3,2);
244   cFakesSummary.cd(1);
245   cFakesSummary.GetPad(1)->SetLogy();
246   hNumberOfClusters->Draw();
247   hNumberOfClusters->SetMinimum(0.5);
248   hNumberOfClustersM->Draw("same");
249   hNumberOfClustersM->SetLineColor(4);
250   hNumberOfClustersF->Draw("same");
251   hNumberOfClustersF->SetLineColor(2);
252   hNumberOfClustersF->SetFillColor(2);
253   hNumberOfClustersF->SetFillStyle(3017);
254   cFakesSummary.cd(2);
255   cFakesSummary.GetPad(2)->SetLogy();
256   hChi2PerDof->Draw();
257   hChi2PerDof->SetMinimum(0.5);
258   hChi2PerDofM->Draw("same");
259   hChi2PerDofM->SetLineColor(4);
260   hChi2PerDofF->Draw("same");
261   hChi2PerDofF->SetLineColor(2);
262   hChi2PerDofF->SetFillColor(2);
263   hChi2PerDofF->SetFillStyle(3017);
264   cFakesSummary.cd(3);
265   cFakesSummary.GetPad(3)->SetLogy();
266   hP->Draw();
267   hP->SetMinimum(0.5);
268   hPM->Draw("same");
269   hPM->SetLineColor(4);
270   hPF->Draw("same");
271   hPF->SetLineColor(2);
272   hPF->SetFillColor(2);
273   hPF->SetFillStyle(3017);
274   cFakesSummary.cd(4);
275   cFakesSummary.GetPad(4)->SetLogy();
276   hPt->Draw();
277   hPt->SetMinimum(0.5);
278   hPtM->Draw("same");
279   hPtM->SetLineColor(4);
280   hPtF->Draw("same");
281   hPtF->SetLineColor(2);
282   hPtF->SetFillColor(2);
283   hPtF->SetFillStyle(3017);
284   cFakesSummary.cd(5);
285   cFakesSummary.GetPad(5)->SetLogy();
286   hEta->Draw();
287   hEta->SetMinimum(0.5);
288   hEtaM->Draw("same");
289   hEtaM->SetLineColor(4);
290   hEtaF->Draw("same");
291   hEtaF->SetLineColor(2);
292   hEtaF->SetFillColor(2);
293   hEtaF->SetFillStyle(3017);
294   cFakesSummary.cd(6);
295   cFakesSummary.GetPad(6)->SetLogy();
296   hPhi->Draw();
297   hPhi->SetMinimum(0.5);
298   hPhiM->Draw("same");
299   hPhiM->SetLineColor(4);
300   hPhiF->Draw("same");
301   hPhiF->SetLineColor(2);
302   hPhiF->SetFillColor(2);
303   hPhiF->SetFillStyle(3017);
304   
305   // save results
306   histoFile->cd();
307   histoFile->Write();
308   cFakesSummary.Write();
309   histoFile->Close();
310   
311   // print results
312   cout << endl;
313   cout << "- Number of reconstructible tracks: " << nReconstructibleTracks << endl;
314   cout << "- Number of reconstructed tracks: " << nReconstructedTracks << endl;
315   cout << "- Number of matched tracks: " << nTotMatchedTracks << endl;
316   cout << "  (including " << nTotTracksReconstructedYet << " track(s) matched with a TrackRef that is not reconstructible";
317   if (nTotTracksReconstructedYet > 0) {
318     for(Int_t i=0; i<nEventsWithTrackReconstructedYet; i++){
319       if (i==0) cout << " (eventID = " << eventsWithTrackReconstructedYet[i];
320       else cout << ", " << eventsWithTrackReconstructedYet[i];
321     }
322     cout << "))" << endl;
323   } else cout << ")" << endl;
324   cout << "- Number of fake tracks: " << nTotFakeTracks << endl;
325   cout << "  (including " << nTotConnectedTracks << " track(s) still connected to a reconstructible one)" << endl;
326   cout << "  (including " << nTotAdditionalTracks << " additional track(s) (compared to the number of expected ones))" << endl;
327   cout << "- Number of events with fake track(s): " << nEventsWithFake;
328   if (nEventsWithFake > 0) {
329     for(Int_t i=0; i<nEventsWithFake; i++){
330       if (i==0) cout << " (eventID = " << eventsWithFake[i];
331       else cout << ", " << eventsWithFake[i];
332     }
333     cout << ")" << endl;
334   } else cout << endl;
335   cout << "  (including " << nEventsWithAdditionalFake << " events with additional track(s)";
336   if (nEventsWithAdditionalFake > 0) {
337     for(Int_t i=0; i<nEventsWithAdditionalFake; i++){
338       if (i==0) cout << " (eventID = " << eventsWithAdditionalFake[i];
339       else cout << ", " << eventsWithAdditionalFake[i];
340     }
341     cout << "))" << endl;
342   } else cout << ")" << endl;
343   cout << endl;
344   cout << "REMINDER: results are relevent provided that you use the same recoParams as for the reconstruction" << endl;
345   cout << endl;
346   
347 }
348
349 //-----------------------------------------------------------------------
350 Bool_t TrackMatched(AliMUONTrack &track, AliMUONTrack &trackRef, Float_t &fractionOfMatchCluster, Double_t sigmaCut)
351 {
352   /// Try to match 2 tracks
353   
354   Bool_t compTrack[10];
355   Int_t nMatchClusters = track.CompatibleTrack(&trackRef, sigmaCut, compTrack);
356   fractionOfMatchCluster = ((Float_t)nMatchClusters) / ((Float_t)track.GetNClusters());
357   
358   if ((compTrack[0] || compTrack[1] || compTrack[2] || compTrack[3]) && // at least 1 cluster matched in st 1 & 2
359       (compTrack[6] || compTrack[7] || compTrack[8] || compTrack[9]) && // at least 1 cluster matched in st 4 & 5
360       fractionOfMatchCluster > 0.5) return kTRUE;                       // more than 50% of clusters matched
361   else return kFALSE;
362   
363 }
364
365 //-----------------------------------------------------------------------
366 Bool_t IsRecontructible(AliMUONTrack &track, AliMUONRecoParam &recoParam)
367 {
368   /// Check il the track is reconstructible
369   Int_t nMinChHitInSt45 = (recoParam.MakeMoreTrackCandidates()) ? 2 : 3;
370   Int_t currentCh, previousCh = -1, nChHitInSt45 = 0;
371   Bool_t clusterInSt[5];
372   for (Int_t iSt = 0; iSt < 5; iSt++) clusterInSt[iSt] = !recoParam.RequestStation(iSt);
373   
374   AliMUONTrackParam* trackParam = static_cast<AliMUONTrackParam*>(track.GetTrackParamAtCluster()->First());
375   while (trackParam) {
376     
377     currentCh = trackParam->GetClusterPtr()->GetChamberId();
378     
379     clusterInSt[currentCh/2] = kTRUE;
380     
381     if (currentCh > 5 && currentCh != previousCh) {
382       nChHitInSt45++;
383       previousCh = currentCh;
384     }
385     
386     trackParam = static_cast<AliMUONTrackParam*>(track.GetTrackParamAtCluster()->After(trackParam));
387   }
388   
389   return (clusterInSt[0] && clusterInSt[1] && clusterInSt[2] &&
390           clusterInSt[3] && clusterInSt[4] && nChHitInSt45 >= nMinChHitInSt45);
391   
392 }
393
394 //-----------------------------------------------------------------------
395 AliMUONTrack* MatchWithTrackRef(AliMUONTrack &muonTrack, AliMUONVTrackStore &trackRefStore,
396                                 Float_t &fractionOfMatchCluster, Bool_t useLabel, Double_t sigmaCut)
397 {
398   /// Return if the trackRef matched with the reconstructed track and the fraction of matched clusters
399   
400   AliMUONTrack *matchedTrackRef = 0x0;
401   fractionOfMatchCluster = 0.;
402   
403   if (useLabel) { // by using the MC label
404     
405     // get the corresponding simulated track if any
406     Int_t label = muonTrack.GetMCLabel();
407     matchedTrackRef = (AliMUONTrack*) trackRefStore.FindObject(label);
408     
409     // get the fraction of matched clusters
410     if (matchedTrackRef) {
411       Int_t nMatchClusters = 0;
412       Int_t nClusters = muonTrack.GetNClusters();
413       for (Int_t iCl = 0; iCl < nClusters; iCl++)
414         if (((AliMUONTrackParam*) muonTrack.GetTrackParamAtCluster()->UncheckedAt(iCl))->GetClusterPtr()->GetMCLabel() == label)
415           nMatchClusters++;
416       fractionOfMatchCluster = ((Float_t)nMatchClusters) / ((Float_t)nClusters);
417     }
418     
419   } else { // by comparing cluster/TrackRef positions
420     
421     // look for the corresponding simulated track if any
422     TIter next(trackRefStore.CreateIterator());
423     AliMUONTrack* trackRef;
424     while ( ( trackRef = static_cast<AliMUONTrack*>(next()) ) ) {
425       
426       // check compatibility
427       Float_t f = 0.;
428       if (TrackMatched(muonTrack, *trackRef, f, sigmaCut)) {
429         matchedTrackRef = trackRef;
430         fractionOfMatchCluster = f;
431         break;
432       }
433       
434     }
435     
436   }
437   
438   return matchedTrackRef;
439   
440 }
441
442 //-----------------------------------------------------------------------
443 Int_t RemoveConnectedFakes(AliMUONVTrackStore &fakeTrackStore, AliMUONVTrackStore &trackRefStore, AliMUONRecoParam &recoParam,
444                           Bool_t useLabel, Double_t sigmaCut, TH1F &hFractionOfConnectedClusters)
445 {
446   /// loop over reconstructible TrackRef not associated with reconstructed track:
447   /// for each of them, find and remove the most connected the fake track, if any,
448   /// and fill the histograms with the fraction of connected clusters.
449   /// Return the number of reconstructible track not connected to any fake
450   
451   Int_t nFreeMissingTracks = 0;
452   
453   // loop over trackRefs
454   TIter next(trackRefStore.CreateIterator());
455   AliMUONTrack* trackRef;
456   while ( ( trackRef = static_cast<AliMUONTrack*>(next()) ) ) {
457     
458     // skip not reconstructible trackRefs
459     if (!IsRecontructible(*trackRef,recoParam)) continue;
460     
461     Int_t label = trackRef->GetUniqueID();
462     
463     // look for the most connected fake track
464     AliMUONTrack *connectedFake = 0x0;
465     Double_t fractionOfConnectedClusters = 0.;
466     TIter next2(fakeTrackStore.CreateIterator());
467     AliMUONTrack* fakeTrack;
468     while ( ( fakeTrack = static_cast<AliMUONTrack*>(next2()) ) ) {
469       
470       // get the number of connected clusters
471       Int_t nConnectedClusters = 0;
472       if (useLabel) { // by using the MC label
473         for (Int_t iCl = 0; iCl < fakeTrack->GetNClusters(); iCl++)
474           if (((AliMUONTrackParam*) fakeTrack->GetTrackParamAtCluster()->UncheckedAt(iCl))->GetClusterPtr()->GetMCLabel() == label)
475             nConnectedClusters++;
476       } else { // by comparing cluster/TrackRef positions
477         Bool_t compTrack[10];
478         nConnectedClusters = fakeTrack->CompatibleTrack(trackRef, sigmaCut, compTrack);
479       }
480       
481       // skip non-connected fake tracks
482       if (nConnectedClusters == 0) continue;
483       
484       // check if it is the most connected fake track
485       Double_t f = ((Double_t)nConnectedClusters) / ((Double_t)fakeTrack->GetNClusters());
486       if (f > fractionOfConnectedClusters) {
487         connectedFake = fakeTrack;
488         fractionOfConnectedClusters = f;
489       }
490       
491     }
492     
493     // remove the most connected fake track
494     if (connectedFake) {
495       hFractionOfConnectedClusters.Fill(fractionOfConnectedClusters);
496       fakeTrackStore.Remove(*connectedFake);
497     } else nFreeMissingTracks++;
498     
499   }
500   
501   return nFreeMissingTracks;
502   
503 }
504