Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

AlgTrackCamList.cxx

Go to the documentation of this file.
00001 
00002 // Package: CandTrackCam
00003 //
00004 // AlgTrackCamList.cxx
00005 //
00006 // marshall@hep.phy.cam.ac.uk
00007 //
00008 // chapman@hep.phy.cam.ac.uk
00009 // blake@hep.phy.cam.ac.uk
00011 
00012 #include <cassert>
00013 #include <cmath>
00014 
00015 #include "Conventions/Munits.h"
00016 #include "MessageService/MsgService.h"
00017 #include "MinosObjectMap/MomNavigator.h"
00018 #include "Navigation/NavKey.h"
00019 #include "Navigation/NavSet.h"
00020 #include "Validity/VldContext.h"
00021 
00022 #include "Algorithm/AlgFactory.h"
00023 #include "Algorithm/AlgHandle.h"
00024 #include "Algorithm/AlgConfig.h"
00025 #include "Candidate/CandContext.h"
00026 
00027 #include "RecoBase/CandTrackHandle.h"
00028 #include "RecoBase/CandTrackListHandle.h"
00029 #include "RecoBase/CandSliceHandle.h"
00030 #include "RecoBase/CandSliceListHandle.h"
00031 #include "RecoBase/CandStripHandle.h"
00032 #include "RecoBase/CandStripListHandle.h"
00033 #include "CandDigit/CandDeMuxDigitHandle.h"
00034 #include "CandDigit/CandDeMuxDigitListHandle.h"
00035 
00036 #include "CandTrackCam/AlgTrackCamList.h"
00037 #include "CandTrackCam/CandTrackCamListHandle.h"
00038 #include "CandTrackCam/CandTrackCamHandle.h"
00039 
00040 #include "HitCam.h"
00041 #include "ClusterCam.h"
00042 #include "TrackSegmentCam.h"
00043 #include "TrackCam.h"
00044 
00045 #include "TObjArray.h"
00046 
00047 ClassImp(AlgTrackCamList)
00048 
00049   CVSID("$Id: AlgTrackCamList.cxx,v 1.14 2007/11/11 08:48:25 rhatcher Exp $");
00050 
00052 AlgTrackCamList::AlgTrackCamList() :
00053   StripWidth(4.108e-2)
00054 {
00055 }
00057 
00058 
00060 AlgTrackCamList::~AlgTrackCamList()
00061 {
00062 }
00064 
00065 
00067 void AlgTrackCamList::RunAlg(AlgConfig &ac,CandHandle &ch, CandContext &cx)
00068 {
00069   assert(cx.GetDataIn());
00070 
00071   // Check for CandSliceListHandle input
00072   if (cx.GetDataIn()->InheritsFrom("CandSliceListHandle")) {
00073     const CandSliceListHandle *cslh = dynamic_cast<const CandSliceListHandle*>(cx.GetDataIn());
00074     const MomNavigator *mom = cx.GetMom();
00075     
00076     CandRecord* candrec = (CandRecord*)(cx.GetCandRecord());
00077     assert(candrec);
00078     
00079     vldc = (VldContext*)(candrec->GetVldContext());
00080     
00081     
00082     // Create the new tracklist
00083     CandTrackCamListHandle& tracklist = dynamic_cast<CandTrackCamListHandle&>(ch);
00084     
00085     if( !cslh || cslh->GetNDaughters()<1 ) {
00086       // Require number of CandSlices to be non-zero to do anything more
00087       MSG("AlgTrackCamList", Msg::kWarning) << " !cslh || cslh->GetNDaughters()<1 " << endl;
00088       return;
00089     }
00090  
00091     // Configure for correct detector
00092     switch(vldc->GetDetector()){
00093     case Detector::kFar:
00094       ModuleType=1; NumModules=2; PlanesInModule=248; break;
00095     case Detector::kNear:
00096       ModuleType=2; NumModules=1; PlanesInModule=120; break;
00097     case Detector::kCalDet:
00098       ModuleType=3; NumModules=1; PlanesInModule=60; break;
00099     default:
00100       ModuleType=-1; NumModules=0; PlanesInModule=0; break;
00101     }
00102      
00103  
00104     // Unpack AlgConfig
00105     CambridgeAnalysis=false;
00106     if( ac.KeyExists("CambridgeAnalysis") ) {CambridgeAnalysis = ac.GetInt("CambridgeAnalysis");}
00107   
00108  
00109     // Iterate over the slices
00110     TIter sliceItr(cslh->GetDaughterIterator());
00111      
00112     while (CandSliceHandle *slice = dynamic_cast<CandSliceHandle*>(sliceItr())) {
00113 
00114       // Find tracks in slice
00116       if(ModuleType==1 || ModuleType==3) {PECut=1.8; PECut2=1.8;}
00117       else if(ModuleType==2) {PECut=2.; PECut2=0.5;}
00118       RunTheFinder(slice);
00119 
00120         
00121       // Setup AlgTrackCam
00123       AlgFactory &af = AlgFactory::GetInstance();
00124       TString algtrackconfig = "default";
00125       if( ac.KeyExists("AlgTrackCamConfig") ) {
00126         const char* tmps;
00127         if( ac.Get("AlgTrackCamConfig",tmps)) { algtrackconfig = tmps; }
00128       }
00129       AlgHandle ah_trk = af.GetAlgHandle("AlgTrackCam", algtrackconfig.Data());
00130 
00131         
00132       // Create the CandContext
00134       CandContext cx0(this, mom);
00135       cx0.SetCandRecord(candrec);
00136         
00137       unsigned int NTracksFound = FinalTrackBank[0].size();
00138 
00139       // Run the finder again with different PECut settings
00140       if(CambridgeAnalysis==false && NTracksFound==0) {
00141         ClearUp(); PECut=0.5; PECut2=0.5;
00142         RunTheFinder(slice); 
00143         NTracksFound = FinalTrackBank[0].size();
00144       }
00145   
00146       // Sanity Check
00147       if(NTracksFound!= FinalTrackBank[1].size()) {
00148         MSG("AlgTrackCamList", Msg::kError) <<"Different Number of U and V Tracks Found!"<<endl;
00149         if( NTracksFound>=FinalTrackBank[1].size()) {NTracksFound = FinalTrackBank[1].size();}
00150       }
00151 
00152       //Loop over the U and V track found
00154       for(unsigned int i=0; i<NTracksFound; ++i) {
00155         TrackCam* tracku = FinalTrackBank[0][i];
00156         TrackCam* trackv = FinalTrackBank[1][i];
00157         
00158         //Fill the CandContext for this track
00160         TObjArray trackin;
00161         trackin.Add(tracku);
00162         trackin.Add(trackv);
00163         trackin.Add(slice);
00164         cx0.SetDataIn(&trackin);
00165           
00166         //Create the CandTrack
00167         CandTrackCamHandle cth = CandTrackCam::MakeCandidate(ah_trk, cx0);
00168         cth.SetName(TString("CandTrackCamHandle"));
00169         cth.SetTitle(TString("Created by AlgTrackCamList"));
00170           
00171         // Add CandTrack to CandTrackList
00173         if(cth.GetNDaughters()>0) {tracklist.AddDaughterLink(cth);}
00174       }
00175       
00176       ClearUp();
00177 
00178     } // End loop over slices
00179       
00180   } // End if inherits from CandSliceListHandle
00181   
00182 }
00184 
00185 
00186 
00187 
00189 void AlgTrackCamList::RunTheFinder(CandSliceHandle* slice)
00190 {
00191   // Configure algorithm for the relevant detector
00192   // For ND, initial algorithm is applied only to calorimeter,
00193   // spectrometer is treated separately
00194   MSG("AlgTrackCamList", Msg::kVerbose) << "FINDING TRACKS IN SLICE" << endl;
00195 
00196   // Run the methods
00197   FormTheHits(slice);
00198   FormTheClusters(); 
00199   IDTrkAndShwClusters();
00200   FormTriplets();
00201   FindAllAssociations();
00202   FindPreferredJoins();
00203   FindMatchedJoins();
00204   FirstUVComparison();
00205   if(ModuleType==2) {NearDetectorTriplets();}
00206   Form2DTracks();
00207   Join2DTracks();
00208   SecondUVComparison();
00209   Form3DTracks(slice);
00210 
00211   return;
00212 }
00214 
00215 
00216 
00217 
00219 void AlgTrackCamList::FormTheHits(CandSliceHandle* slice)
00220 {
00221   // Create and (store pointers to) HitCam objects for all strips in slice
00222   // meeting PH and XTalk requirements. HitCam class is essentially a wrapper
00223   // for CandStripHandles
00224 
00225   bool IsXTalk[2];
00226   int Counter; double StripCharge;
00227   
00228   // Loop over all strips in the slice
00229   TIter SliceItr(slice->GetDaughterIterator());
00230   while(CandStripHandle* SlcStrip = dynamic_cast<CandStripHandle*>(SliceItr())) {
00231     
00232     // Default Xtalk flag to false, as cannot identify ND XTalk
00233     IsXTalk[0]=false; IsXTalk[1]=false;
00234   
00235     // Identify XTalk strips for FD
00236     if(ModuleType==1) {
00237       IsXTalk[0]=true; IsXTalk[1]=true; Counter=0;
00238       
00239       TIter DigItr(SlcStrip->GetDaughterIterator());
00240       while(CandDeMuxDigitHandle* Digit = (CandDeMuxDigitHandle*)(DigItr())) {
00241         if( !((Digit->GetDeMuxDigitFlagWord()<8)
00242               && (Digit->GetDeMuxDigitFlagWord() & CandDeMuxDigit::kXTalk)==(CandDeMuxDigit::kXTalk)) ) {
00243           IsXTalk[Counter]=false;
00244         }
00245         if(Counter==0) {Counter=1;}
00246       }
00247     }
00248     
00249     // Add the hits to the bank, where they are stored in plane order
00250     if(IsXTalk[0]==false || IsXTalk[1]==false) {
00251       StripCharge=SlcStrip->GetCharge();
00252 
00253       if(StripCharge>PECut2 || StripCharge>PECut) {
00254         HitCam* hit = new HitCam(SlcStrip);
00255 
00256         if(StripCharge>PECut) {HitBank[SlcStrip->GetPlane()].push_back(hit);}
00257         if(StripCharge>PECut2) {AllHitBank[SlcStrip->GetPlane()].push_back(hit);}
00258       }
00259     }
00260   }
00261   
00262 
00263   // Print out the list of hits
00264   MSG("AlgTrackCamList", Msg::kVerbose) << " *** LIST OF HITS *** " << endl;
00265   for(int i=0; i<500; ++i){
00266     for(unsigned int j=0; j<HitBank[i].size(); ++j) {
00267       MSG("AlgTrackCamList", Msg::kVerbose)
00268         << " pln="  << HitBank[i][j]->GetPlane() 
00269         << " strp=" << HitBank[i][j]->GetStrip() 
00270         << " chg="  << HitBank[i][j]->GetCharge()
00271         << " time=" << HitBank[i][j]->GetTime() << endl;
00272     }
00273   }
00274 
00275   return;
00276 }
00278 
00279 
00280 
00281 
00283 void AlgTrackCamList::FormTheClusters()
00284 {
00285   // For each plane where we stored hits, we look to form 1D clusters 
00286   // of these hits. This is controlled by the IsHitAssoc method in ClusterCam.
00287   // Pointers to the ClusterCam objects are stored in plane order in a 
00288   // clusterbank
00289   
00290 
00291   bool AddingHits;
00292   int i;
00293 
00294   for(int Module=0; Module<NumModules; ++Module) {
00295     for(int Plane=0; Plane<PlanesInModule+1; ++Plane) {
00296       i=Plane + Module*(PlanesInModule+1);
00297       
00298       // Loop over the hits on plane i
00299       for(unsigned int j=0; j<HitBank[i].size(); ++j) {
00300         
00301         // Make a cluster for the first hit on the plane
00302         if(HitBank[i][j]->GetUID()==0) {
00303           ClusterCam* Clust = new ClusterCam(HitBank[i][j]);
00304           ClusterBank[HitBank[i][j]->GetPlane()].push_back(Clust);
00305 
00306           // Change UID from 0 to 1 to show that hit has been added       
00307           HitBank[i][j]->SetUID(1); 
00308           AddingHits=true;
00309           
00310           // Loop over other hits on plane to form clusters
00311           while(AddingHits==true) {
00312             AddingHits=false;
00313             
00314             for(unsigned int k=0; k<HitBank[i].size(); ++k) {
00315               if(HitBank[i][k]->GetUID()==0 && Clust->IsHitAssoc(HitBank[i][k])) {
00316                 Clust->AddHit(HitBank[i][k]); 
00317                 HitBank[i][k]->SetUID(1);
00318                 AddingHits=true;
00319               }
00320             }
00321           }
00322 
00323         }
00324       } // End loop over hits on plane
00325     } // End loop over planes in module
00326   } // End loop over modules
00327 
00328   return;
00329 }
00331 
00332 
00333 
00334 
00336 void AlgTrackCamList::IDTrkAndShwClusters()
00337 {
00338   // Look at the 1D clusters formed and use simple techniques to get an idea
00339   // of how track-like or shower-like each cluster is.
00340   // Then look at all clusters on the plane and see how track-like or shower-like
00341   // the plane is.
00342 
00343   //  Detector::Detector_t Detector = vldc->GetDetector();
00344 
00345   int i, k0;
00346   int nclust0, nclust1, nhits0, nhits1, ShwAssocNum;
00347   vector<ClusterCam*> TempClust0;
00348   vector<ClusterCam*> TempClust1;
00349 
00350 
00351   // Simple checks to set initial track flags
00353   for(int Module=0; Module<NumModules; ++Module) {
00354     for(int Plane=0; Plane<PlanesInModule+1; ++Plane) {
00355       i=Plane + Module*(PlanesInModule+1);
00356       
00357       for(unsigned int j=0; j<ClusterBank[i].size(); ++j) {
00358         if(ClusterBank[i][j]->GetCharge()>PECut || ClusterBank[i][j]->GetDigits()>1 ) {
00359           ClusterBank[i][j]->SetTrkFlag(1);
00360         }
00361       }
00362     }
00363   }
00365 
00366 
00367   
00368   // Identify the shower-like clusters
00370   for(int Module=0; Module<NumModules; ++Module) {
00371     for(int Plane=1; Plane<PlanesInModule+1; ++Plane) {
00372       i=Plane + Module*(PlanesInModule+1);
00373       
00374       for(unsigned int j=0; j<ClusterBank[i].size(); ++j) {
00375         ClusterCam* Clust0 = ClusterBank[i][j];
00376 
00377         nhits0=0; nhits1=0; nclust0=0; nclust1=0;
00378         TempClust0.clear(); TempClust1.clear(); 
00379         
00380         
00381         // Look for shower associations in nearby planes
00383         // Loop over nearby planes
00384         for(int k=-1; k<2; ++k) {
00385           k0=i+(2*k);
00386           
00387           // Check k0 is a valid nearby plane
00388           if(k0>Module*(PlanesInModule+1) && k0<(Module+1)*(PlanesInModule+1)) {
00389 
00390             // Loop over clusters on plane k0
00391             for(unsigned int k1=0; k1<ClusterBank[k0].size(); ++k1) {
00392               ClusterCam* Clust1 = ClusterBank[k0][k1];
00393 
00394               // Check shower-like associations
00395               if(Clust0->GetCharge()>1. && Clust1->GetCharge()>1.) {
00396                 ShwAssocNum=Clust0->IsShwAssoc(Clust1);
00397                 
00398                 // Store the association data and the clusters
00399                 if(ShwAssocNum>0) {
00400                   nhits0+=Clust1->GetEntries(); 
00401                   nclust0+=1;
00402                   TempClust0.push_back(Clust1);
00403                 }
00404                 
00405                 if(ShwAssocNum>1) {
00406                   nhits1+=Clust1->GetEntries(); 
00407                   nclust1+=1;
00408                   TempClust1.push_back(Clust1);
00409                 }
00410               }
00411             } // End loop over clusters on nearby plane
00412           }
00413         } // End loop over nearby planes
00415 
00416 
00417         // Use the above results to set the shower flags
00418         // Has important implications for finding tracks embedded in showers
00420         if(nclust1>1 && nhits1>4) {
00421           for(unsigned int k=0; k<TempClust1.size(); ++k) {
00422             TempClust1[k]->SetShwFlag(1);
00423           }
00424         }
00425 
00426         if(nclust0>4 && nhits0>5) {
00427           for(unsigned int k=0; k<TempClust0.size(); ++k) {
00428             TempClust0[k]->SetShwFlag(1);
00429           }
00430         }
00432 
00433       }
00434     }
00435   }
00437 
00438 
00439 
00440   // Identify track-like and shower-like planes
00442   double Charge;
00443 
00444   for(int Module=0; Module<NumModules; ++Module) {
00445     for(int Plane=0; Plane<PlanesInModule+1; ++Plane) {
00446       i=Plane + Module*(PlanesInModule+1);
00447       Charge=0.;
00448 
00449       // Get total charge in clusters on plane
00450       for(unsigned int j=0; j<ClusterBank[i].size(); ++j) {
00451         Charge+=ClusterBank[i][j]->GetCharge();
00452       }
00453 
00454       if(Charge>0.) {
00455         for(unsigned int j=0; j<ClusterBank[i].size(); ++j) {
00456           ClusterCam* Clust = ClusterBank[i][j];
00457 
00458           // Set the plane flags for the clusters // should be <3
00459           if(Clust->GetEntries()<7 && (Clust->GetCharge()/Charge)>0.5) {Clust->SetTrkPlnFlag(1);}
00460           if(Clust->GetEntries()>1 && (Clust->GetCharge()/Charge)>0.5) {Clust->SetShwPlnFlag(1);}
00461         }
00462       }
00463     }
00464   }
00466   
00467 
00468 
00469   // Print out list of hits and 1D clusters
00470   MSG("AlgTrackCamList", Msg::kVerbose) << " *** LIST OF CLUSTERS *** " << endl;
00471   for(int i=0; i<500; ++i){
00472     for(unsigned int j=0; j<ClusterBank[i].size(); ++j) {
00473       MSG("AlgTrackCamList", Msg::kVerbose)
00474         << " plane="    << ClusterBank[i][j]->GetPlane() 
00475         << " begtpos="  << ClusterBank[i][j]->GetBegTPos() 
00476         << " endtpos="  << ClusterBank[i][j]->GetEndTPos() 
00477         << " trkflag="  << ClusterBank[i][j]->GetTrkFlag()
00478         << " shwpln="   << ClusterBank[i][j]->GetShwPlnFlag() 
00479         << " trkpln="   << ClusterBank[i][j]->GetTrkPlnFlag()
00480         << " shwflag="  << ClusterBank[i][j]->GetShwFlag() << endl;
00481     }
00482   }
00483 
00484   return;
00485 }
00487 
00488 
00489 
00490 
00492 void AlgTrackCamList::FormTriplets()
00493 {
00494   // Treating U and V views separately, we consider associations between clusters
00495   // on nearby planes. We look for groups of three clusters, each on different 
00496   // planes, that can be joined together in a small track segment, or triplet. 
00497 
00498   // All possible triplets of the following form are created:
00499   
00500   // If we sit on plane 0, and there are no possible hits on a plane marked X, m 
00501   // means a lower plane number than our origin plane, and p means a higher plane 
00502   // number.
00503    
00504   // m 0 p         The simplest triplet
00505   
00506   // m X 0 p       One gap
00507   // m 0 X p
00508   
00509   // m X X 0 p     Two gaps
00510   // m X 0 X p
00511   // m 0 X X p
00512 
00513 
00514   int TripAssocNum;
00515   bool AlternateTriplets;
00516   bool JoinFlag;
00517   int i;
00518   
00519   // Begin loop to make the triplets
00520   for(int Module=0; Module<NumModules; ++Module) {
00521 
00522     for(int Plane=2; Plane<PlanesInModule-1; ++Plane) {
00523       i=Plane + Module*(PlanesInModule+1);
00524 
00525       // Loop over clusters on plane. This is our plane 0, the origin.
00526       for(unsigned int k0=0; k0<ClusterBank[i].size(); ++k0) {
00527 
00528         if(ClusterBank[i][k0]->GetTrkFlag()>0) {
00529           JoinFlag=false;
00530 
00531 
00532           // Look for triplets of form m 0 p
00534           if((i-2)>=0 && ClusterBank[i-2].size()>0 && (i+2)<500 && ClusterBank[i+2].size()>0) {
00535           
00536             // Look at the clusters on plane i-2...
00537             for(unsigned int km=0; km<ClusterBank[i-2].size(); ++km) {
00538             
00539               // ...and the clusters on plane i+2
00540               for(unsigned int kp=0; kp<ClusterBank[i+2].size(); ++kp) {
00541               
00542                 if(ClusterBank[i-2][km]->GetTrkFlag()>0 && ClusterBank[i+2][kp]->GetTrkFlag()>0) {
00543 
00544                   // Check the track-like association of the three clusters
00545                   TripAssocNum=ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-2][km],ClusterBank[i+2][kp]);
00546 
00547                   // If the association is good, make the triplet
00548                   if(TripAssocNum>0) {
00549                     TrackSegmentCam* seg0 = new TrackSegmentCam(ClusterBank[i-2][km], ClusterBank[i][k0], ClusterBank[i+2][kp]);
00550 
00551                     SegmentBank[i].push_back(seg0);
00552                     JoinFlag=true;
00553 
00554                     // Indicate that triplet is exceptionally track-like, by setting flag to 2.
00555                     if(TripAssocNum>1) {ClusterBank[i][k0]->SetTrkFlag(2);}
00556                   }
00557                 }
00558               }
00559             }
00560           }
00562         
00563 
00564         
00565           // Look for triplets of form m <-> 0 p
00567           if((i+2)<500 && ClusterBank[i+2].size()>0) {
00568 
00569         
00570             // Look for triplets of form m X 0 p  
00572             if( Plane>3 && (i-4)>=0 && ClusterBank[i-4].size()>0) {
00573 
00574               // Look at the clusters on plane i+2...
00575               for(unsigned int kp=0; kp<ClusterBank[i+2].size(); ++kp) {
00576               
00577                 // ...and the clusters on plane i-4
00578                 for(unsigned int km=0; km<ClusterBank[i-4].size(); ++km) {
00579 
00580                   if(ClusterBank[i-4][km]->GetTrkFlag()>0 && ClusterBank[i+2][kp]->GetTrkFlag()>0) {
00581 
00582                     // Check the track-like association of the three clusters
00583                     TripAssocNum=ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-4][km],ClusterBank[i+2][kp]);
00584                   
00585                     // If the association is good, check whether we can make the triplet
00586                     if(TripAssocNum>0) {
00587                       AlternateTriplets=false;
00588                       
00589                       // Check to see if there is also an alternate triplet possibility with clusters on plane i-2
00590                       // i.e. Want to make sure that the X in "m X 0 p" is correct.
00591 
00592                       if(AlternateTriplets==false && ClusterBank[i-2].size()>0) {
00593                         // Look at the clusters on plane i-2
00594                         for(unsigned int ktmp=0; ktmp<ClusterBank[i-2].size(); ++ktmp) {
00595                           if(AlternateTriplets==false && ClusterBank[i-2][ktmp]->GetTrkFlag()>0
00596                              && ClusterBank[i-2][ktmp]->IsTrkAssoc(ClusterBank[i-4][km],ClusterBank[i][k0])>0 
00597                              && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-2][ktmp],ClusterBank[i+2][kp])>0) 
00598                             {AlternateTriplets=true;}
00599                         }
00600                       }
00601                       
00602                       
00603                       // If everything is good, make the triplet
00604                       if(AlternateTriplets==false) {
00605                         TrackSegmentCam* seg0 = new TrackSegmentCam(ClusterBank[i-4][km],ClusterBank[i][k0],ClusterBank[i+2][kp]);
00606                         
00607                         SegmentBank[i].push_back(seg0);
00608                         JoinFlag=true;
00609         
00610                         // Indicate that triplet is exceptionally track-like, by setting flag to 2.
00611                         if(TripAssocNum>1) {ClusterBank[i][k0]->SetTrkFlag(2);}
00612                       }
00613                     }
00614                   }
00615                 }
00616               }
00617             }
00619 
00620 
00621             // Look for triplets of form m X X 0 p  
00623             if( Plane>5 && (i-6)>=0 && ClusterBank[i-6].size()>0) {
00624 
00625               // Look at the clusters on plane i+2...
00626               for(unsigned int kp=0; kp<ClusterBank[i+2].size(); ++kp) {
00627               
00628                 // ...and look at the clusters on plane i-6
00629                 for(unsigned int km=0; km<ClusterBank[i-6].size(); ++km) {
00630                   
00631                   if(ClusterBank[i-6][km]->GetTrkFlag()>0 && ClusterBank[i+2][kp]->GetTrkFlag()>0) {
00632 
00633                     // Check the track-like association of the three clusters
00634                     TripAssocNum=ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-6][km],ClusterBank[i+2][kp]);
00635         
00636                     // If the association is good, check whether we can make the triplet
00637                     if(TripAssocNum>0) {
00638                       AlternateTriplets=false;
00639                       
00640                       // Check to see if there are alternate triplet possibilities with clusters on plane i-2 or i-4
00641                       // i.e. Want to make sure that the Xs in "m X X 0 p" are correct.
00642 
00643                       // Check first X
00644                       if(AlternateTriplets==false && ClusterBank[i-2].size()>0) {
00645                         // Look at any clusters on plane i-2
00646                         for(unsigned int ktmp=0; ktmp<ClusterBank[i-2].size(); ++ktmp) {
00647                           if(AlternateTriplets==false && ClusterBank[i-2][ktmp]->GetTrkFlag()>0
00648                              && ClusterBank[i-2][ktmp]->IsTrkAssoc(ClusterBank[i-6][km],ClusterBank[i][k0])>0 
00649                              && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-2][ktmp],ClusterBank[i+2][kp])>0) 
00650                             {AlternateTriplets=true;}
00651                         }
00652                       }
00653                       
00654                       // Check second X, plane i-4
00655                       if(AlternateTriplets==false && ClusterBank[i-4].size()>0) {
00656                         // Look at any clusters on plane i-4
00657                         for(unsigned int ktmp=0; ktmp<ClusterBank[i-4].size(); ++ktmp) {
00658                           if(AlternateTriplets==false && ClusterBank[i-4][ktmp]->GetTrkFlag()>0
00659                              && ClusterBank[i-4][ktmp]->IsTrkAssoc(ClusterBank[i-6][km],ClusterBank[i][k0])>0 
00660                              && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-4][ktmp],ClusterBank[i+2][kp])>0) 
00661                             {AlternateTriplets=true;}
00662                         }
00663                       }
00664                       
00665                       // Check both Xs together, planes i-2 and i-4
00666                       if(AlternateTriplets==false && ClusterBank[i-2].size()>0 && ClusterBank[i-4].size()>0) {
00667                         // Look again at any clusters on plane i-4...
00668                         for(unsigned int ktmp=0; ktmp<ClusterBank[i-4].size(); ++ktmp) {
00669                           
00670                           // ...and look again any clusters on plane i-2
00671                           for(unsigned int ktmp1=0; ktmp1<ClusterBank[i-2].size(); ++ktmp1) {
00672                             if(AlternateTriplets==false 
00673                                && ClusterBank[i-4][ktmp]->GetTrkFlag()>0 && ClusterBank[i-2][ktmp1]->GetTrkFlag()>0
00674                                && ClusterBank[i-4][ktmp]->IsTrkAssoc(ClusterBank[i-6][km],ClusterBank[i-2][ktmp1])>0
00675                                && ClusterBank[i-2][ktmp1]->IsTrkAssoc(ClusterBank[i-4][ktmp],ClusterBank[i][k0])>0
00676                                && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-2][ktmp1],ClusterBank[i+2][kp])>0)
00677                               {AlternateTriplets=true;}
00678                           }
00679                           
00680                         }
00681                       }
00682                       
00683                       // If everything is good, make the triplet
00684                       if(AlternateTriplets==false) {
00685                         TrackSegmentCam* seg0 = new TrackSegmentCam(ClusterBank[i-6][km],ClusterBank[i][k0],ClusterBank[i+2][kp]);
00686                         
00687                         SegmentBank[i].push_back(seg0);
00688                         JoinFlag=true;
00689 
00690                         // Indicate that triplet is exceptionally track-like, by setting flag to 2.
00691                         if(TripAssocNum>1) {ClusterBank[i][k0]->SetTrkFlag(2);}
00692                       }
00693                     }
00694                   }
00695                 }
00696               }
00697             }
00699 
00700           }
00702 
00703 
00704 
00705           // Look for triplets of form m 0 <-> p
00707           if((i-2)>0 && ClusterBank[i-2].size()>0) {
00708 
00709         
00710             // Look for triplets of form m 0 X p  
00712             if( Plane<PlanesInModule-3 && (i+4)<500 && ClusterBank[i+4].size()>0) {
00713 
00714               // Look at the clusters on plane i-2...
00715               for(unsigned int km=0; km<ClusterBank[i-2].size(); ++km) {
00716               
00717                 // ... and the clusters on plane i+4
00718                 for(unsigned int kp=0; kp<ClusterBank[i+4].size(); ++kp) {
00719 
00720                   if(ClusterBank[i-2][km]->GetTrkFlag()>0 && ClusterBank[i+4][kp]->GetTrkFlag()>0) {
00721 
00722                     // Check the track-like association of the three clusters
00723                     TripAssocNum=ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-2][km],ClusterBank[i+4][kp]);
00724                    
00725                     // If the association is good, check whether we can make the triplet
00726                     if(TripAssocNum>0) {
00727                       AlternateTriplets=false;
00728                       
00729                       // Check to see if there is also an alternate triplet possibility with clusters on plane i+2
00730                       // i.e. Want to make sure that the X in "m 0 X p" is correct.
00731 
00732                       if(AlternateTriplets==false && ClusterBank[i+2].size()>0) {
00733                         // Look at the clusters on plane i+2
00734                         for(unsigned int ktmp=0; ktmp<ClusterBank[i+2].size(); ++ktmp) {
00735                           if(AlternateTriplets==false && ClusterBank[i+2][ktmp]->GetTrkFlag()>0
00736                              && ClusterBank[i+2][ktmp]->IsTrkAssoc(ClusterBank[i][k0],ClusterBank[i+4][kp])>0 
00737                              && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-2][km],ClusterBank[i+2][ktmp])>0) 
00738                             {AlternateTriplets=true;}
00739                         }
00740                       }
00741                       
00742                       
00743                       // If everything is good, make the triplet
00744                       if(AlternateTriplets==false) {
00745                         // Store segment on empty plane too
00746                         for(int j=0; j<2; ++j) {
00747                           TrackSegmentCam* seg0 = new TrackSegmentCam(ClusterBank[i-2][km],ClusterBank[i][k0],ClusterBank[i+4][kp]);
00748                           
00749                           SegmentBank[i+2*j].push_back(seg0);
00750                           JoinFlag=true;
00751                         }
00752                         
00753                         // Indicate that triplet is exceptionally track-like, by setting flag to 2.
00754                         if(TripAssocNum>1) {ClusterBank[i][k0]->SetTrkFlag(2);}
00755                       }
00756                     }
00757                   }
00758                 }
00759               }
00760             }
00762 
00763 
00764             // Look for triplets of form m 0 X X p  
00766             if(Plane<PlanesInModule-5 && (i+6)<500 && ClusterBank[i+6].size()>0) {
00767 
00768               // Look at the clusters on plane i-2...
00769               for(unsigned int km=0; km<ClusterBank[i-2].size(); ++km) {
00770               
00771                 // ...and look at the clusters on plane i+6
00772                 for(unsigned int kp=0; kp<ClusterBank[i+6].size(); ++kp) {
00773 
00774                   if(ClusterBank[i-2][km]->GetTrkFlag()>0 && ClusterBank[i+6][kp]->GetTrkFlag()>0) {
00775                     // Check the track-like association of the three clusters
00776                     TripAssocNum=ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-2][km],ClusterBank[i+6][kp]);
00777                     
00778                     // If the association is good, check whether we can make the triplet
00779                     if(TripAssocNum>0) {
00780                       AlternateTriplets=false;
00781         
00782                       // Check to see if there are alternate triplet possibilities with clusters on plane i+2 or i+4
00783                       // i.e. Want to make sure that the Xs in "m 0 X X p" are correct.
00784               
00785                       // Check first X, plane i+2
00786                       if(AlternateTriplets==false && ClusterBank[i+2].size()>0) {
00787                         // Look at any clusters on plane i+2
00788                         for(unsigned int ktmp=0; ktmp<ClusterBank[i+2].size(); ++ktmp) {
00789                           if(AlternateTriplets==false && ClusterBank[i+2][ktmp]->GetTrkFlag()>0
00790                              && ClusterBank[i+2][ktmp]->IsTrkAssoc(ClusterBank[i][k0],ClusterBank[i+6][kp])>0 
00791                              && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-2][km],ClusterBank[i+2][ktmp])>0) 
00792                             {AlternateTriplets=true;}
00793                         }
00794                       }
00795                       
00796                       // Check second X, plane i+4
00797                       if(AlternateTriplets==false && ClusterBank[i+4].size()>0) {
00798                         // Look at any clusters on plane i+4
00799                         for(unsigned int ktmp=0; ktmp<ClusterBank[i+4].size(); ++ktmp) {
00800                           if(AlternateTriplets==false && ClusterBank[i+4][ktmp]->GetTrkFlag()>0
00801                              && ClusterBank[i+4][ktmp]->IsTrkAssoc(ClusterBank[i][k0],ClusterBank[i+6][kp])>0 
00802                              && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-2][km],ClusterBank[i+4][ktmp])>0) 
00803                             {AlternateTriplets=true;}
00804                         }
00805                       }
00806                       
00807                       // Check both Xs together, planes i+2 and i+4
00808                       if(AlternateTriplets==false && ClusterBank[i+2].size()>0 && ClusterBank[i+4].size()>0) {
00809                         // Look again at any clusters on plane i+2...
00810                         for(unsigned int ktmp=0; ktmp<ClusterBank[i+2].size(); ++ktmp) {
00811                           
00812                           // ...and look again at any clusters on plane i+4
00813                           for(unsigned int ktmp1=0; ktmp1<ClusterBank[i+4].size(); ++ktmp1) {
00814                             if(AlternateTriplets==false 
00815                                && ClusterBank[i+2][ktmp]->GetTrkFlag()>0 &&ClusterBank[i+4][ktmp1]->GetTrkFlag()>0
00816                                && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-2][km],ClusterBank[i+2][ktmp])>0
00817                                && ClusterBank[i+2][ktmp]->IsTrkAssoc(ClusterBank[i][k0],ClusterBank[i+4][ktmp1])>0
00818                                && ClusterBank[i+4][ktmp1]->IsTrkAssoc(ClusterBank[i+2][ktmp],ClusterBank[i+6][kp])>0)
00819                               {AlternateTriplets=true;}
00820                           }
00821                           
00822                         }
00823                       }
00824                       
00825                       // If everything is good, make the triplet
00826                       if(AlternateTriplets==false) {
00827                         // Store segment on empty planes too
00828                         for(int j=0; j<3; ++j) {
00829                           TrackSegmentCam* seg0 = new TrackSegmentCam(ClusterBank[i-2][km],ClusterBank[i][k0],ClusterBank[i+6][kp]);
00830                           
00831                           SegmentBank[i+2*j].push_back(seg0);
00832                           JoinFlag=true;
00833                         }
00834                         // Indicate that triplet is exceptionally track-like, by setting flag to 2.
00835                         if(TripAssocNum>1) {ClusterBank[i][k0]->SetTrkFlag(2);}
00836                       }
00837                     }
00838                   }
00839                 }
00840               }
00841             }
00843 
00844           }
00846 
00847 
00848 
00849           // Look for triplets of form m X 0 X p
00851           if(Plane>3 && Plane<PlanesInModule-3 && (i-4)>=0 && ClusterBank[i-4].size()>0 && (i+4)<500 && ClusterBank[i+4].size()>0) {
00852 
00853             // Look at clusters on planes i-4 and i+4
00854             for(unsigned int km=0; km<ClusterBank[i-4].size(); ++km) {
00855               for(unsigned int kp=0; kp<ClusterBank[i+4].size(); ++kp) {
00856 
00857                 if(ClusterBank[i-4][km]->GetTrkFlag()>0 && ClusterBank[i+4][kp]->GetTrkFlag()>0) {
00858                   // Check the track-like association of the three clusters
00859                   TripAssocNum=ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-4][km],ClusterBank[i+4][kp]);
00860                   
00861                   // If the association is good, check whether we can make the triplet
00862                   if(TripAssocNum>0) {
00863                     AlternateTriplets=false;
00864                     
00865                     // Check to see if there are alternate triplet possibilities with clusters on plane i-2 or i+2
00866                     // i.e. Want to make sure that the Xs in "m X 0 X p" are correct.
00867                     
00868                     // Check first X, plane i-2
00869                     if(AlternateTriplets==false && ClusterBank[i-2].size()>0) {
00870                       // Look at any clusters on plane i-2
00871                       for(unsigned int ktmp=0; ktmp<ClusterBank[i-2].size(); ++ktmp) {
00872                         if(AlternateTriplets==false && ClusterBank[i-2][ktmp]->GetTrkFlag()>0
00873                            && ClusterBank[i-2][ktmp]->IsTrkAssoc(ClusterBank[i-4][km],ClusterBank[i][k0])>0 
00874                            && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-2][ktmp],ClusterBank[i+4][kp])>0) 
00875                           {AlternateTriplets=true;}
00876                       }
00877                     }
00878                     
00879                     // Check second X, plane i+2
00880                     if(AlternateTriplets==false && ClusterBank[i+2].size()>0) {
00881                       // Look at any clusters on plane i+2
00882                       for(unsigned int ktmp=0; ktmp<ClusterBank[i+2].size(); ++ktmp) {
00883                         if(AlternateTriplets==false  && ClusterBank[i+2][ktmp]->GetTrkFlag()>0
00884                            && ClusterBank[i+2][ktmp]->IsTrkAssoc(ClusterBank[i][k0],ClusterBank[i+4][kp])>0 
00885                            && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-4][km],ClusterBank[i+2][ktmp])>0) 
00886                           {AlternateTriplets=true;}
00887                       }
00888                     }
00889                     
00890                     // Check both Xs together, planes i-2 and i+2
00891                     if(AlternateTriplets==false && ClusterBank[i-2].size()>0 && ClusterBank[i+2].size()>0) {
00892                       
00893                       // Loop again at any clusters on plane i-2
00894                       for(unsigned int ktmp=0; ktmp<ClusterBank[i-2].size(); ++ktmp) {
00895                         
00896                         // Look again at any clusters on plane i+2
00897                         for(unsigned int ktmp1=0; ktmp1<ClusterBank[i+2].size(); ++ktmp1) {
00898                           if(AlternateTriplets==false 
00899                              && ClusterBank[i-2][ktmp]->GetTrkFlag()>0 && ClusterBank[i+2][ktmp1]->GetTrkFlag()>0
00900                              && ClusterBank[i-2][ktmp]->IsTrkAssoc(ClusterBank[i-4][km],ClusterBank[i][k0])>0 
00901                              && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-2][ktmp],ClusterBank[i+2][ktmp1])>0 
00902                              && ClusterBank[i+2][ktmp1]->IsTrkAssoc(ClusterBank[i][k0],ClusterBank[i+4][kp])>0)
00903                             {AlternateTriplets=true;}
00904                         }
00905                       }
00906                     }
00907 
00908                     // If everything is good, make the triplet
00909                     if(AlternateTriplets==false) {
00910                       // Store segment on empty planes too
00911                       for(int j=0; j<2; ++j) {
00912                         TrackSegmentCam* seg0 = new TrackSegmentCam(ClusterBank[i-4][km],ClusterBank[i][k0],ClusterBank[i+4][kp]);
00913                         
00914                         SegmentBank[i+2*j].push_back(seg0);
00915                         JoinFlag=true;
00916                       }
00917                       // Indicate that triplet is exceptionally track-like, by setting flag to 2.
00918                       if(TripAssocNum>1) {ClusterBank[i][k0]->SetTrkFlag(2);}
00919                     }               
00920                   }
00921                 }
00922               }
00923             }
00924           }
00926 
00927 
00928           // Set the exceptionally track-like flag for lone hits that form part of a triplet
00929           if(JoinFlag==true && (ClusterBank[i][k0]->GetEndTPos()==ClusterBank[i][k0]->GetBegTPos())) {
00930             ClusterBank[i][k0]->SetTrkFlag(2);
00931           }
00932 
00933           
00934         }
00935 
00936       } // End loop over clusters on plane
00937     
00938     } // End loop over planes in module
00939 
00940   } // End loop over modules
00941 
00942 
00943   // Print out list of hits and 1D clusters
00944   MSG("AlgTrackCamList", Msg::kVerbose) << " *** 2ND LIST OF CLUSTERS *** " << endl;
00945   for(int i=0; i<500; ++i){
00946     for(unsigned int j=0; j<ClusterBank[i].size(); ++j) {
00947       MSG("AlgTrackCamList", Msg::kVerbose)
00948         << " plane="    << ClusterBank[i][j]->GetPlane() 
00949         << " begtpos="  << ClusterBank[i][j]->GetBegTPos() 
00950         << " endtpos="  << ClusterBank[i][j]->GetEndTPos() 
00951         << " trkflag="  << ClusterBank[i][j]->GetTrkFlag()
00952         << " shwpln="   << ClusterBank[i][j]->GetShwPlnFlag() 
00953         << " trkpln="   << ClusterBank[i][j]->GetTrkPlnFlag()
00954         << " shwflag="  << ClusterBank[i][j]->GetShwFlag() << endl;
00955     }
00956   }
00957 
00958 
00959   // Print out list of triplets
00960   MSG("AlgTrackCamList", Msg::kVerbose) << " *** LIST OF TRIPLETS *** " << endl;
00961   for(int i=0; i<500; ++i) {
00962     for(unsigned int j=0;j<SegmentBank[i].size(); ++j) {
00963       MSG("AlgTrackCamList", Msg::kVerbose) << " Segment Num " << j << ", Plane " << i <<endl;
00964  
00965       ClusterCam* clr0 = SegmentBank[i][j]->GetCluster(0);
00966       ClusterCam* clr1 = SegmentBank[i][j]->GetCluster(1);
00967       ClusterCam* clr2 = SegmentBank[i][j]->GetCluster(2);
00968 
00969       MSG("AlgTrackCamList", Msg::kVerbose) 
00970         << " (" << clr0->GetPlane() << "," << clr0->GetBegTPos() << "->" << clr0->GetEndTPos() << ") "
00971         << " (" << clr1->GetPlane() << "," << clr1->GetBegTPos() << "->" << clr1->GetEndTPos() << ") "
00972         << " (" << clr2->GetPlane() << "," << clr2->GetBegTPos() << "->" << clr2->GetEndTPos() << ") " << endl;
00973     }
00974   }
00975   
00976   return;
00977 }
00979 
00980 
00981 
00982 
00984 void AlgTrackCamList::FindAllAssociations()
00985 {
00986   // For each triplet formed, we consider nearby triplets and see whether
00987   // the triplets are associated. 
00988 
00989   // For each triplet, we simply find the nearby other triplets that have 
00990   // a compatible beginning/end position/direction.
00991 
00992   // Later we look more that one triplet away, to find strings of 
00993   // "preferred associations" that might indicate a track.
00994 
00995 
00996   int i=0;
00997 
00998 
00999   // Loop over the planes
01001   for(int Module=0; Module<NumModules; ++Module) {
01002 
01003     for(int Plane=3; Plane<PlanesInModule-1; ++Plane) {
01004       i=Plane + Module*(PlanesInModule+1);
01005         
01006       if((i+2)<500 && SegmentBank[i].size()>0 && SegmentBank[i+2].size()>0) {
01007         
01008         // Look at the segments on plane i
01009         for(unsigned int k0=0; k0<SegmentBank[i].size(); ++k0) {
01010           
01011           // For each of these, look at the segments on plane i+2
01012           for(unsigned int kp=0; kp<SegmentBank[i+2].size(); ++kp) {
01013             
01014             // Check associations. 
01015             if(SegmentBank[i][k0]->IsAssoc(SegmentBank[i+2][kp])) {
01016               
01017               // If segments are associated, we add to list of ALL possible joins
01018               SegmentBank[i][k0]->AddAssocSegToEnd(SegmentBank[i+2][kp]);
01019               SegmentBank[i+2][kp]->AddAssocSegToBeg(SegmentBank[i][k0]);
01020             }
01021           }
01022         }
01023       }
01024     } // End loop over planes in module
01025   } // End loop over modules
01027 
01028 
01029 
01030 
01031   // Print out list of all associations
01033   MSG("AlgTrackCamList", Msg::kVerbose) << " *** LIST OF ALL SEG ASSOCIATIONS *** " << endl;
01034 
01035   // Print out list of triplets
01036   for(int i=0; i<500; ++i) {
01037     for(unsigned int j=0;j<SegmentBank[i].size(); ++j) {
01038       TrackSegmentCam* segment = SegmentBank[i][j];
01039 
01040       MSG("AlgTrackCamList", Msg::kVerbose) << "--- Plane " << i << ", Seg Number " << j 
01041                                             << ", BegPlane " << segment->GetBegPlane() 
01042                                             << ", EndPlane " << segment->GetEndPlane() 
01043                                             << ", BegTPos " << segment->GetBegTPos() 
01044                                             << ", EndTPos " << segment->GetEndTPos() 
01045                                             <<endl;
01046  
01047       MSG("AlgTrackCamList", Msg::kVerbose) << " Beg: " <<endl;
01048       for(unsigned int k=0; k<segment->GetNAssocSegBeg(); ++k) {
01049         TrackSegmentCam* segtmp = segment->GetAssocSegBeg(k);
01050         MSG("AlgTrackCamList", Msg::kVerbose) << "  Assoc number=" << k
01051                                               << "  begpln: " << segtmp->GetBegPlane()
01052                                               << "  begtpos: " << segtmp->GetBegTPos()
01053                                               << "  endpln: " << segtmp->GetEndPlane()
01054                                               << "  endtpos: " << segtmp->GetEndTPos() << endl;
01055       }
01056       
01057       MSG("AlgTrackCamList", Msg::kVerbose) << " End: " <<endl;
01058       for(unsigned int k=0; k<segment->GetNAssocSegEnd(); ++k) {
01059         TrackSegmentCam* segtmp = segment->GetAssocSegEnd(k);
01060         MSG("AlgTrackCamList", Msg::kVerbose) << "  Assoc number=" << k
01061                                               << "  begpln: " << segtmp->GetBegPlane()
01062                                               << "  begtpos: " << segtmp->GetBegTPos()
01063                                               << "  endpln: " << segtmp->GetEndPlane()
01064                                               << "  endtpos: " << segtmp->GetEndTPos() << endl;           
01065       }
01066     }
01067   }
01069 
01070   return;
01071 }
01073 
01074 
01075 
01076 
01078 void AlgTrackCamList::FindPreferredJoins()
01079 {
01080   // Having made all possible associations between triplets above, we 
01081   // select those associations that are most track-like and so are preferred.
01082   
01083   // For a given triplet, we know which triplets are associated with the
01084   // beginning and which are associated at the end. If there are associations
01085   // between these beginning and end triplets too, then we are quite likely 
01086   // to be considering track-like segments.
01087 
01088 
01089 
01090   int i;
01091 
01092   vector<TrackSegmentCam*> mTempSeg;
01093   vector<TrackSegmentCam*> pTempSeg;
01094   
01095   bool JoinFlag; bool mJnFlag; bool pJnFlag; 
01096 
01097   double GradientTolerance=8.;
01098   if(ModuleType==2) {GradientTolerance=5.;}
01099 
01100 
01101   // Loop over the planes
01103   for(int Module=0; Module<NumModules; ++Module) {
01104 
01105     for(int Plane=3; Plane<PlanesInModule-1; ++Plane) {
01106       i=Plane + Module*(PlanesInModule+1);
01107       
01108 
01109       // SET THE TEMPORARY TRACK FLAGS
01110      
01111       // Consider previous adjacent triplets   ( i-2 <-> ) i <-> i+2
01112       //                                                  Seg
01113       // If there are associations at both ends of triplet, set triplet's 
01114       // temporary track flag to 1. 
01115 
01116       // If one of beginning associated triplets also starts at lower plane 
01117       // than current triplet, set the triplet's temporary track flag to 2
01119       mTempSeg.clear();
01120 
01121       // Loop over the triplets centered on plane i
01122       for(unsigned int j=0; j<SegmentBank[i].size(); ++j) {
01123         TrackSegmentCam* Seg = SegmentBank[i][j];
01124 
01125         // Check to see if there are associations at end
01126         if(Seg->GetNAssocSegEnd()>0) {
01127           mTempSeg.push_back(Seg);
01128           
01129           // Check to see if there are associations at beginning
01130           if(Seg->GetNAssocSegBeg()>0) {
01131             
01132             // We now know that triplet has possible associations at both ends
01133             Seg->SetTmpTrkFlag(1);
01134 
01135             // Loop over the associations at beginning and set temp track flags
01136             // for segments on plane i
01137             for(unsigned int k=0; k<Seg->GetNAssocSegBeg(); ++k) {
01138               if(Seg->GetTmpTrkFlag()<2
01139                  && (Seg->GetAssocSegBeg(k)->GetBegPlane() < Seg->GetBegPlane()) ) 
01140                 {Seg->SetTmpTrkFlag(2); break;}
01141             }
01142           }
01143         }
01144       }
01146 
01147 
01148 
01149       // Subsequent adjacent triplets   i <-> i+2 ( <-> i+4 )
01150       //                                      Segp
01151       // If there are associations at both ends of triplet centered on 
01152       // plane i+2, set triplet's temporary track flag to 1.
01153 
01154       // If one of the end associated triplets also ends at higher plane
01155       // than i+2 triplet, set i+2 triplet's temporary track flag to 2
01157       pTempSeg.clear();
01158 
01159       // Loop over the triplets centered on plane i+2
01160       for(unsigned int j=0; j<SegmentBank[i+2].size(); ++j) {
01161         TrackSegmentCam* Segp = SegmentBank[i+2][j];
01162 
01163         // Check to see if there are associations at beginning
01164         if(Segp->GetNAssocSegBeg()>0) {
01165           pTempSeg.push_back(Segp);
01166           
01167           // Check to see if there are associations at end
01168           if(Segp->GetNAssocSegEnd()>0) {
01169             
01170             // We now know that triplet has possible associations at both ends
01171             Segp->SetTmpTrkFlag(1);
01172             
01173             // Loop over associations at end and set temp track flags
01174             // for segments on plane i+2
01175             for(unsigned int k=0; k<Segp->GetNAssocSegEnd(); ++k) {
01176               if(Segp->GetTmpTrkFlag()<2
01177                  && (Segp->GetAssocSegEnd(k)->GetEndPlane() > Segp->GetEndPlane()) ) 
01178                 {Segp->SetTmpTrkFlag(2); break;}
01179             }
01180           }
01181         }
01182       }
01184       
01185   
01186 
01187       // Look for preferred joins   ( i-2 <-> ) i <-> i+2
01189       // Loop the over segments on plane i+2, which we know have possible beginning associations
01190       for(unsigned int j=0; j<pTempSeg.size(); ++j) {
01191         JoinFlag=false;
01192 
01193         // Loop over these beginning associations. If one beginning associated
01194         // triplet already has temp track flag 2, set JoinFlag to true.
01195         for(unsigned int k=0; k<pTempSeg[j]->GetNAssocSegBeg(); ++k) {
01196           if(pTempSeg[j]->GetAssocSegBeg(k)->GetTmpTrkFlag()>1) {JoinFlag=true; break;}   
01197         }
01198 
01199         // If JoinFlag is true, and a beginning assoc segment has temp track flag 1 (i.e. possible 
01200         // beginning and end associations), set the temp track flag to 2 for this beg assoc segment
01201         if(JoinFlag==true) {
01202           // Loop over beginning associations again and set temp track flags
01203           // for segments on plane i
01204           for(unsigned int k=0; k<pTempSeg[j]->GetNAssocSegBeg(); ++k) {
01205             if(pTempSeg[j]->GetAssocSegBeg(k)->GetTmpTrkFlag()==1) {
01206               pTempSeg[j]->GetAssocSegBeg(k)->SetTmpTrkFlag(2); 
01207             }
01208           }
01209         }
01210       }
01212 
01213 
01214 
01215       // Look for preferred joins    i <-> i+2 ( <-> i+4 )
01217       // Loop over segments on plane i, which we know have possible end associations
01218       for(unsigned int j=0; j<mTempSeg.size(); ++j) {
01219         JoinFlag=false;
01220 
01221         // Loop over these end associations. If one end associated triplet already
01222         // has temp track flag 2, set JoinFlag to true.
01223         for(unsigned int k=0; k<mTempSeg[j]->GetNAssocSegEnd(); ++k) {
01224           if(mTempSeg[j]->GetAssocSegEnd(k)->GetTmpTrkFlag()>1) {JoinFlag=true; break;}   
01225         }
01226         
01227         // If JoinFlag is true, and an end assoc segment has temp track flag 1 (i.e. possible 
01228         // beginning and end associations), set the temp track flag to 2 for this end assoc segment
01229         if(JoinFlag==true) {
01230           // Loop over end associations again and set temp track flags
01231           // for segments on plane i+2
01232           for(unsigned int k=0; k<mTempSeg[j]->GetNAssocSegEnd(); ++k) {
01233             if(mTempSeg[j]->GetAssocSegEnd(k)->GetTmpTrkFlag()==1) {
01234               mTempSeg[j]->GetAssocSegEnd(k)->SetTmpTrkFlag(2); 
01235             }
01236           }
01237         }
01238       }
01240 
01241 
01242       // Now have temporary track flags set to 2 for all segments on planes i and i+2
01243       // which look like very promising track segments      
01245 
01246 
01247 
01248 
01249       // MAKE THE PREFERRED JOINS BETWEEN TRIPLETS ON PLANE i AND PLANE i+2
01251       if(mTempSeg.size()>0 && pTempSeg.size()>0) {
01252       
01253         // Look for doubly preferred joins    ( i-2 <-> ) i <-> i+2 ( <-> i+4 )
01255 
01256         // Loop over segments on plane i, which we know have possible end associations
01257         for(unsigned int j=0; j<mTempSeg.size(); ++j) {
01258           TrackSegmentCam* Seg = mTempSeg[j];
01259 
01260           // For these, loop over possible end associations
01261           for(unsigned int k=0; k<Seg->GetNAssocSegEnd(); ++k) {
01262             TrackSegmentCam* Segp = Seg->GetAssocSegEnd(k);
01263  
01264             // If both segments given temp track flag 2 above check assocations 
01265             // between triplets on either side
01266             if(Seg->GetTmpTrkFlag()>1 && Segp->GetTmpTrkFlag()>1) {
01267 
01268               // For each Segp, see if there is a Segm association
01269               mJnFlag=false;
01270               for(unsigned int l=0; l<Seg->GetNAssocSegBeg(); ++l) {
01271                 TrackSegmentCam* Segm = Seg->GetAssocSegBeg(l);
01272                 if(Segm->IsAssoc(Segp) ) {mJnFlag=true; break;}
01273               }
01274 
01275               // For each end assoc of Segp, see if it is assoc with Seg
01276               pJnFlag=false;
01277               for(unsigned int l=0; l<Segp->GetNAssocSegEnd(); ++l) {
01278                 TrackSegmentCam* Segp2 = Segp->GetAssocSegEnd(l);
01279                 if(Seg->IsAssoc(Segp2) ) {pJnFlag=true; break;}
01280               }
01281 
01282               // Make the preferred assocations
01283               if(mJnFlag==true && pJnFlag==true){
01284                 if(fabs((Seg->GetBegTPos()-Seg->GetEndTPos())-
01285                         (Segp->GetBegTPos()-Segp->GetEndTPos()))<GradientTolerance*StripWidth
01286                    && Seg->GetBegPlane()<=Segp->GetBegPlane()
01287                    && Seg->GetEndPlane()<=Segp->GetEndPlane() ) {
01288                   Seg->AddPrefSegToEnd(Segp); Segp->AddPrefSegToBeg(Seg);}
01289 
01290                 else {MSG("AlgTrackCamList", Msg::kVerbose) << "Seg " << Seg->GetBegPlane() << " " << Seg->GetEndPlane() << " "
01291                                                             << Seg->GetBegTPos() << " " << Seg->GetEndTPos() << " Segp " 
01292                                                             << Segp->GetBegPlane() << " " << Segp->GetEndPlane() << " "
01293                                                             << Segp->GetBegTPos() << " " << Segp->GetEndTPos() << endl;}
01294               }
01295             }
01296           }
01297         }
01299      
01300 
01301 
01302         // Look for singly preferred joins (1)    ( i-2 <-> ) i <-> i+2 
01304 
01305         // Loop over segments on plane i, which we know have possible end associations
01306         for(unsigned int j=0; j<mTempSeg.size(); ++j) {
01307           TrackSegmentCam* Seg = mTempSeg[j];
01308           
01309           // If segment given temp track flag 2 above 
01310           if(Seg->GetTmpTrkFlag()>1) {
01311             JoinFlag=false;
01312 
01313             // Check to see if we will already have made the preferred association above
01314             for(unsigned int k=0; k<Seg->GetNAssocSegEnd(); ++k) {
01315               TrackSegmentCam* Segp = Seg->GetAssocSegEnd(k);
01316               
01317               if(Segp->GetTmpTrkFlag()>1) {JoinFlag=true; break;}
01318             }
01319 
01320             // If have not made the association, can check assocations 
01321             // between triplets on either side
01322             if(JoinFlag==false) {
01323               for(unsigned int k=0; k<Seg->GetNAssocSegEnd(); ++k) {
01324                 TrackSegmentCam* Segp = Seg->GetAssocSegEnd(k);
01325 
01326                 // For each Segp, see if there is a Segm associated
01327                 mJnFlag=false;
01328                 for(unsigned int l=0; l<Seg->GetNAssocSegBeg(); ++l) {
01329                   TrackSegmentCam* Segm = Seg->GetAssocSegBeg(l);
01330                   if(mJnFlag==false && Segm->IsAssoc(Segp) ) {mJnFlag=true; break;}
01331                 }
01332                
01333                 // Make the preferred assocations
01334                 if(mJnFlag==true){
01335                   if(fabs((Seg->GetBegTPos()-Seg->GetEndTPos())-
01336                           (Segp->GetBegTPos()-Segp->GetEndTPos()))<GradientTolerance*StripWidth
01337                      && Seg->GetBegPlane()<=Segp->GetBegPlane()
01338                      && Seg->GetEndPlane()<=Segp->GetEndPlane() ) {
01339                     Seg->AddPrefSegToEnd(Segp); Segp->AddPrefSegToBeg(Seg);}
01340 
01341                   else {MSG("AlgTrackCamList", Msg::kVerbose) << "Seg " << Seg->GetBegPlane() << " " << Seg->GetEndPlane() << " "
01342                                                               << Seg->GetBegTPos() << " " << Seg->GetEndTPos() << " Segp " 
01343                                                               << Segp->GetBegPlane() << " " << Segp->GetEndPlane() << " "
01344                                                               << Segp->GetBegTPos() << " " << Segp->GetEndTPos() << endl;}
01345                 }
01346               }
01347             }
01348           }
01349         }
01351 
01352 
01353 
01354         // Look for singly preferred joins (2)    i <-> i+2 ( <-> i+4 )
01356 
01357         // Loop the over segments on plane i+2, which we know have possible beginning associations
01358         for(unsigned int j=0; j<pTempSeg.size(); ++j) {
01359           TrackSegmentCam* Segp = pTempSeg[j];
01360 
01361           // If segment given temp track flag 2 above
01362           if(Segp->GetTmpTrkFlag()>1) {
01363             JoinFlag=false;
01364 
01365             // Check to see if we will already have made the preferred association above
01366             for(unsigned int k=0; k<Segp->GetNAssocSegBeg(); ++k) {
01367               TrackSegmentCam* Seg = Segp->GetAssocSegBeg(k);
01368               
01369               if(Seg->GetTmpTrkFlag()>1) {JoinFlag=true; break;}
01370             }
01371 
01372             // If have not made the association, can check assocations 
01373             // between triplets on either side
01374             if(JoinFlag==false) {
01375               for(unsigned int k=0; k<Segp->GetNAssocSegBeg(); ++k) {
01376                 TrackSegmentCam* Seg = Segp->GetAssocSegBeg(k);
01377 
01378                 // For each Seg, see if there is a Segp2 associated
01379                 pJnFlag=false;
01380                 for(unsigned int l=0; l<Segp->GetNAssocSegEnd(); ++l) {
01381                   TrackSegmentCam* Segp2 = Segp->GetAssocSegEnd(l);
01382                   if(pJnFlag==false && Seg->IsAssoc(Segp2) ) {pJnFlag=true; break;}
01383                 }
01384                
01385                 // Make the preferred assocations
01386                 if(pJnFlag==true){
01387                   if(fabs((Seg->GetBegTPos()-Seg->GetEndTPos())-
01388                           (Segp->GetBegTPos()-Segp->GetEndTPos()))<GradientTolerance*StripWidth
01389                      && Seg->GetBegPlane()<=Segp->GetBegPlane()
01390                      && Seg->GetEndPlane()<=Segp->GetEndPlane() ) {
01391                   Seg->AddPrefSegToEnd(Segp); Segp->AddPrefSegToBeg(Seg);}
01392 
01393                   else {MSG("AlgTrackCamList", Msg::kVerbose) << "Seg " << Seg->GetBegPlane() << " " << Seg->GetEndPlane() << " "
01394                                                               << Seg->GetBegTPos() << " " << Seg->GetEndTPos() << " Segp " 
01395                                                               << Segp->GetBegPlane() << " " << Segp->GetEndPlane() << " "
01396                                                               << Segp->GetBegTPos() << " " << Segp->GetEndTPos() << endl;}
01397                 }
01398               }
01399             }
01400           }
01401         }
01403 
01404 
01405 
01406         // Look for other joins we have missed    i <-> i+2 
01408 
01409         // Loop over segments on plane i, which we know have possible end associations
01410         for(unsigned int j=0; j<mTempSeg.size(); ++j) {
01411           TrackSegmentCam* Seg = mTempSeg[j];
01412           
01413           // For these, loop over the end assocations
01414           for(unsigned int k=0; k<Seg->GetNAssocSegEnd(); ++k) {
01415             TrackSegmentCam* Segp = Seg->GetAssocSegEnd(k);
01416             
01417             // If segments and its end assoc segment were given temp track flag 2 above
01418             if(Seg->GetTmpTrkFlag()<2 && Segp->GetTmpTrkFlag()<2) {
01419               
01420               // Look at each possible end assoc for Seg to see if we've already
01421               // made the assocation
01422               mJnFlag=false;
01423               for(unsigned int l=0; l<Seg->GetNAssocSegEnd(); ++l) {
01424                 if(Seg->GetAssocSegEnd(l)->GetTmpTrkFlag()>1) {mJnFlag=true; break;}
01425               }
01426 
01427               // Look at each possible beginning assoc for Segp to see if we've already
01428               // made the assocation
01429               pJnFlag=false;
01430               for(unsigned int l=0; l<Segp->GetNAssocSegBeg(); ++l) {
01431                 if(Segp->GetAssocSegBeg(l)->GetTmpTrkFlag()>1) {pJnFlag=true; break;}
01432               }
01433                       
01434               // Make the preferred associations if it hasn't been done by one of the loops above
01435               if(mJnFlag==false && pJnFlag==false) {
01436                 if(fabs((Seg->GetBegTPos()-Seg->GetEndTPos())-
01437                         (Segp->GetBegTPos()-Segp->GetEndTPos()))<GradientTolerance*StripWidth
01438                    && Seg->GetBegPlane()<=Segp->GetBegPlane()
01439                    && Seg->GetEndPlane()<=Segp->GetEndPlane() ) {
01440                 Seg->AddPrefSegToEnd(Segp); Segp->AddPrefSegToBeg(Seg);}
01441 
01442                 else {MSG("AlgTrackCamList", Msg::kVerbose) << "Seg " << Seg->GetBegPlane() << " " << Seg->GetEndPlane() << " "
01443                                                             << Seg->GetBegTPos() << " " << Seg->GetEndTPos() << " Segp " 
01444                                                             << Segp->GetBegPlane() << " " << Segp->GetEndPlane() << " "
01445                                                             << Segp->GetBegTPos() << " " << Segp->GetEndTPos() << endl;}
01446               }
01447             }       
01448           }
01449         }
01450         
01452 
01453 
01454       }
01456 
01457 
01458 
01459       // Clear flags ready to consider next planes
01461       for(unsigned int j=0; j<mTempSeg.size(); ++j) {
01462         mTempSeg[j]->SetTmpTrkFlag(0);
01463       }
01464       
01465       for(unsigned int j=0; j<pTempSeg.size(); ++j) {
01466         pTempSeg[j]->SetTmpTrkFlag(0);
01467       }
01469 
01470 
01471     } // End loop over planes in module
01472 
01473   } // End loop over modules
01475 
01476   
01477   
01478   
01479   // Look for any other preferred associations we may have missed.
01480   // Find segments with no preferred end association and look a bit
01481   // further to find preferred associations.
01482 
01483   // Not for ND
01484   if(ModuleType==1 || ModuleType==3) {
01485 
01486     int NewPlane; int Increment;
01487     double SegTPos, NearbySegTPos; 
01488     bool AssocsStopHere;
01489     bool ConsiderSegment;
01490 
01491     for(int Module=0; Module<NumModules; ++Module) {
01492       for(int Plane=3; Plane<PlanesInModule-1; ++Plane) {
01493         i=Plane + Module*(PlanesInModule+1);
01494           
01495         // Loop over all segments
01496         for(unsigned int j=0; j<SegmentBank[i].size(); ++j) {
01497           TrackSegmentCam* Seg0 = SegmentBank[i][j];
01498         
01499           // Loop over the segments with no preferred end association
01501           if(Seg0->GetNPrefSegEnd()==0 && Seg0->GetNPrefSegBeg()>0) {
01502           
01503             // Look at nearby segments to see if these already continue the associations.
01505             AssocsStopHere=true;
01506             SegTPos=0.5*(Seg0->GetBegTPos()+Seg0->GetEndTPos());
01507 
01508             for(unsigned int k=0; k<SegmentBank[i].size(); ++k) {
01509               TrackSegmentCam* NearbySeg = SegmentBank[i][k];
01510             
01511               if(NearbySeg==Seg0) {continue;}
01512             
01513               NearbySegTPos=0.5*(NearbySeg->GetBegTPos()+NearbySeg->GetEndTPos());
01514 
01515               if(fabs(NearbySegTPos-SegTPos)<1 && 
01516                  NearbySeg->GetNPrefSegEnd()>0 && NearbySeg->GetNPrefSegBeg()>0) {AssocsStopHere=false; break;}
01517             }
01518 
01519             if(AssocsStopHere==false) {break;}
01521 
01522 
01523             JoinFlag=false;
01524 
01525             // Consider the segment, plus all the segments, SegBeg, with which 
01526             // it has a preferred beginning association.
01528             for(int k=-1; k<int(Seg0->GetNPrefSegBeg()); ++k) {
01529               // First time, consider Seg0, rather than one of its preferred beginning associations.
01530               TrackSegmentCam* SegBeg = 0;
01531               if(k<0) {SegBeg=Seg0;}
01532               else{SegBeg = Seg0->GetPrefSegBeg(k);}
01533               Increment=4;
01534 
01535               // Look up to 12 planes ahead within the same module.
01536               while(Increment<=14) {
01537                 NewPlane=SegBeg->GetEndPlane()+Increment;
01538               
01539                 if(NewPlane>=(Module+1)*(PlanesInModule+1)) {break;}
01540 
01541                 // See if SegBeg is associated with a segment on this plane, NextSeg.
01542                 // If so, also see if SegBeg is associated with one of NextSeg's 
01543                 // preferred end associated segments.
01544 
01545                 // If so, make the preferred associations between SegBeg and NextSeg.
01546                 for(unsigned int l=0; l<SegmentBank[NewPlane].size(); ++l) {
01547                   TrackSegmentCam* NextSeg = SegmentBank[NewPlane][l];
01548 
01549 
01550                   // Check segments are not now linked in a chain of preferred associations.
01552                   ConsiderSegment=true;
01553                   for(unsigned int m=0; m<NextSeg->GetNPrefSegBeg(); ++m) {
01554                     TrackSegmentCam* PrefSeg = NextSeg->GetPrefSegBeg(m);
01555 
01556                     if(PrefSeg->GetTmpTrkFlag()==1) {NextSeg->SetTmpTrkFlag(1); ConsiderSegment=false; break;}
01557                   }
01558                   if(ConsiderSegment==false) {continue;}
01560 
01561 
01563                   if( SegBeg->IsAssoc(NextSeg) ) {
01564                   
01565                     for(unsigned int m=0; m<NextSeg->GetNPrefSegEnd(); ++m) {
01566                       TrackSegmentCam* SegEnd = NextSeg->GetPrefSegEnd(m);
01567                     
01568                       if( SegBeg->IsAssoc(SegEnd) ) {
01569                         JoinFlag=true;
01570                       
01571                         SegBeg->AddPrefSegToEnd(NextSeg);
01572                         NextSeg->AddPrefSegToBeg(SegBeg);
01573 
01574                         SegBeg->SetTmpTrkFlag(1); NextSeg->SetTmpTrkFlag(1);
01575 
01576                         MSG("AlgTrackCamList", Msg::kVerbose) << "Made missing Pref assoc, SegBeg "
01577                                                               << SegBeg->GetBegPlane() << ", " << SegBeg->GetEndPlane() << ", "
01578                                                               << SegBeg->GetBegTPos() << ", " << SegBeg->GetEndTPos()
01579                                                               << " NextSeg " << NextSeg->GetBegPlane() << ", " 
01580                                                               << NextSeg->GetEndPlane() << ", " << NextSeg->GetBegTPos() 
01581                                                               << ", " << NextSeg->GetEndTPos() << endl;
01582                         break;
01583                       }
01584                     }
01585                   }
01587                 }
01588                 Increment+=2;
01589               }
01590 
01591               // Reset TmpTrkFlags
01592               for(int p=i; p<(1+Module)*PlanesInModule; ++p) {
01593                 for(unsigned int q=0; q<SegmentBank[p].size(); ++q) {SegmentBank[p][q]->SetTmpTrkFlag(0);}
01594               }
01595 
01596               if(JoinFlag==true) {break;}
01597             }
01598           }
01600         
01601 
01602         
01603           // Now loop over the segments with no preferred beginning association
01605           if(Seg0->GetNPrefSegBeg()==0 && Seg0->GetNPrefSegEnd()>0) {
01606           
01607             // Look at nearby segments to see if these already continue the associations.
01609             AssocsStopHere=true;
01610             SegTPos=0.5*(Seg0->GetBegTPos()+Seg0->GetEndTPos());
01611 
01612             for(unsigned int k=0; k<SegmentBank[i].size(); ++k) {
01613               TrackSegmentCam* NearbySeg = SegmentBank[i][k];
01614             
01615               if(NearbySeg==Seg0) {continue;}
01616             
01617               NearbySegTPos=0.5*(NearbySeg->GetBegTPos()+NearbySeg->GetEndTPos());
01618 
01619               if(fabs(NearbySegTPos-SegTPos)<1 && 
01620                  NearbySeg->GetNPrefSegEnd()>0 && NearbySeg->GetNPrefSegBeg()>0) {AssocsStopHere=false; break;}
01621             }
01622 
01623             if(AssocsStopHere==false) {break;}
01625 
01626 
01627             JoinFlag=false;
01628 
01629             // Consider the segment, plus all the segments, SegEnd, with which 
01630             // it has a preferred end association.
01632             for(int k=-1; k<int(Seg0->GetNPrefSegEnd()); ++k) {
01633               // First time, consider Seg0, rather than one of its preferred end associations.
01634               TrackSegmentCam* SegEnd = 0;
01635               if(k<0) {SegEnd=Seg0;}
01636               else{SegEnd = Seg0->GetPrefSegEnd(k);}
01637               Increment=4;
01638 
01639               // Look up to 12 planes behind within the same module.
01640               while(Increment<=14) {
01641                 NewPlane=SegEnd->GetBegPlane()-Increment;
01642               
01643                 if(NewPlane<=(Module)*(PlanesInModule+1)) {break;}
01644 
01645                 // See if SegEnd is associated with a segment on this plane, PrevSeg.
01646                 // If so, also see if SegEnd is associated with one of PrevSeg's 
01647                 // preferred beginning associated segments.
01648 
01649                 // If so, make the preferred associations between SegEnd and PrevSeg.
01650                 for(unsigned int l=0; l<SegmentBank[NewPlane].size(); ++l) {
01651                   TrackSegmentCam* PrevSeg = SegmentBank[NewPlane][l];
01652 
01653 
01654                   // Check segments are not now linked in a chain of preferred associations.
01656                   ConsiderSegment=true;
01657                   for(unsigned int m=0; m<PrevSeg->GetNPrefSegEnd(); ++m) {
01658                     TrackSegmentCam* PrefSeg = PrevSeg->GetPrefSegEnd(m);
01659 
01660                     if(PrefSeg->GetTmpTrkFlag()==1) {PrevSeg->SetTmpTrkFlag(1); ConsiderSegment=false; break;}
01661                   }
01662                   if(ConsiderSegment==false) {continue;}
01664         
01665 
01667                   if( PrevSeg->IsAssoc(SegEnd) ) {
01668                   
01669                     for(unsigned int m=0; m<PrevSeg->GetNPrefSegBeg(); ++m) {
01670                       TrackSegmentCam* SegBeg = PrevSeg->GetPrefSegBeg(m);
01671                             
01672                       if( SegBeg->IsAssoc(SegEnd) ) {
01673                         JoinFlag=true;
01674                       
01675                         SegEnd->AddPrefSegToBeg(PrevSeg);
01676                         PrevSeg->AddPrefSegToEnd(SegEnd);
01677 
01678                         SegEnd->SetTmpTrkFlag(1); PrevSeg->SetTmpTrkFlag(1);
01679 
01680                         MSG("AlgTrackCamList", Msg::kVerbose) << "Made missing Pref assoc, SegEnd "
01681                                                               << SegEnd->GetBegPlane() << ", " << SegEnd->GetEndPlane() << ", "
01682                                                               << SegEnd->GetBegTPos() << ", " << SegEnd->GetEndTPos()
01683                                                               << " PrevSeg " << PrevSeg->GetBegPlane() << ", " 
01684                                                               << PrevSeg->GetEndPlane() << ", " << PrevSeg->GetBegTPos() 
01685                                                               << ", " << PrevSeg->GetEndTPos() << endl;
01686                         break;
01687                       }
01688                     }
01689                   }
01691                 }
01692                 Increment+=2;
01693               }
01694 
01695               // Reset TmpTrkFlags
01696               for(int p=i; p>Module*(PlanesInModule); --p) {
01697                 for(unsigned int q=0; q<SegmentBank[p].size(); ++q) {SegmentBank[p][q]->SetTmpTrkFlag(0);}
01698               }
01699 
01700               if(JoinFlag==true) {break;}
01701             }
01702           }
01704 
01705         }
01706       }
01707     }
01708 
01709   }
01711  
01712   
01713 
01714 
01715   // Print out list of preferred associations
01717   MSG("AlgTrackCamList", Msg::kVerbose) << " *** LIST OF PREF SEG ASSOCIATIONS *** " << endl;
01718 
01719   // Print out list of triplets
01720   for(int i=0; i<500; ++i) {
01721     for(unsigned int j=0;j<SegmentBank[i].size(); ++j) {
01722       TrackSegmentCam* segment = SegmentBank[i][j];
01723 
01724       MSG("AlgTrackCamList", Msg::kVerbose) << " ----Plane " << i << ", Seg Number " << j 
01725                                             << ", BegPlane " << segment->GetBegPlane() 
01726                                             << ", EndPlane " << segment->GetEndPlane() 
01727                                             << ", BegTPos " << segment->GetBegTPos() 
01728                                             << ", EndTPos " << segment->GetEndTPos() 
01729                                             <<endl;
01730  
01731       MSG("AlgTrackCamList", Msg::kVerbose) << " Beg: " << endl;
01732       for(unsigned int k=0; k<segment->GetNPrefSegBeg(); ++k) {
01733         TrackSegmentCam* segtmp = segment->GetPrefSegBeg(k);
01734         MSG("AlgTrackCamList", Msg::kVerbose) << "  Pref number=" << k
01735                                               << "  begpln: " << segtmp->GetBegPlane()
01736                                               << "  begtpos: " << segtmp->GetBegTPos()
01737                                               << "  endpln: " << segtmp->GetEndPlane()
01738                                               << "  endtpos: " << segtmp->GetEndTPos() << endl;
01739       }
01740       
01741       MSG("AlgTrackCamList", Msg::kVerbose) << " End: " << endl;
01742       for(unsigned int k=0; k<segment->GetNPrefSegEnd(); ++k) {
01743         TrackSegmentCam* segtmp = segment->GetPrefSegEnd(k);
01744         MSG("AlgTrackCamList", Msg::kVerbose) << "  Pref number=" << k
01745                                               << "  begpln: " << segtmp->GetBegPlane()
01746                                               << "  begtpos: " << segtmp->GetBegTPos()
01747                                               << "  endpln: " << segtmp->GetEndPlane()
01748                                               << "  endtpos: " << segtmp->GetEndTPos() << endl;           
01749       }
01750     }
01751   }
01753   
01754   return;
01755 }
01757 
01758 
01759 
01760 
01762 void AlgTrackCamList::FindMatchedJoins()
01763 {
01764   // Having made all the preferred assocations, we actually match triplets 
01765   // together to form longer segments of the track.
01766 
01767   // We use the idea of seed segments to identify the last segment in a chain
01768   // of segments.
01769 
01770 
01771 
01772   int i;
01773   bool JoinFlag;
01774 
01775   // Loop over the planes
01776   for(int Module=0; Module<NumModules; ++Module) {
01777     for(int Plane=3; Plane<PlanesInModule-1; ++Plane) {
01778   
01779       i=Plane + Module*(PlanesInModule+1);
01780       
01781       // Loop over the triplets centered on plane i
01782       for(unsigned int j=0; j<SegmentBank[i].size(); ++j) {
01783         
01784         // Firstly, consider isolated segments. These must be their own seed segments.
01785         if(SegmentBank[i][j]->GetNAssocSegBeg()==0 && SegmentBank[i][j]->GetNAssocSegEnd()==0) {
01786           ViewSegBank[SegmentBank[i][j]->GetPlaneView()].push_back(SegmentBank[i][j]);
01787           SegmentBank[i][j]->SetSeedSegment(SegmentBank[i][j]);
01788         }
01789 
01790 
01791         // Then, consider those segments which have some preferred associations
01792         if(SegmentBank[i][j]->GetNPrefSegBeg()>0 || SegmentBank[i][j]->GetNPrefSegEnd()>0) {
01793           JoinFlag=false;
01794 
01795           // If there is one pref assoc at beginning (always false for first segment in module)
01796           if(SegmentBank[i][j]->GetNPrefSegBeg()==1) {
01797             TrackSegmentCam* Segm = SegmentBank[i][j]->GetPrefSegBeg(0);
01798 
01799             // Check that we are considering a simple chain of segments
01800             if(Segm->GetNPrefSegEnd()==1) {
01801               // Get the last segment in the chain of segments
01802               TrackSegmentCam* SeedSeg = Segm->GetSeedSegment();
01803 
01804               SeedSeg->AddSegment(SegmentBank[i][j]); 
01805               SegmentBank[i][j]->SetSeedSegment(SeedSeg);
01806               SegmentBank[i][j]->SetUID(-1);
01807               JoinFlag=true;
01808             }
01809           }
01810 
01811           // Now consider those triplets which aren't just one pref assoc at beg and one at end
01812           if(JoinFlag==false) {
01813             ViewSegBank[SegmentBank[i][j]->GetPlaneView()].push_back(SegmentBank[i][j]);
01814             SegmentBank[i][j]->SetSeedSegment(SegmentBank[i][j]);
01815             
01816             // Loop over the preferred associations at beginning
01817             for(unsigned int k=0; k<SegmentBank[i][j]->GetNPrefSegBeg(); ++k) {
01818               TrackSegmentCam* SeedSeg = SegmentBank[i][j]->GetPrefSegBeg(k)->GetSeedSegment();
01819               TrackSegmentCam* MatchSeg = SegmentBank[i][j];
01820 
01821               if(SeedSeg->GetBegPlane()<=MatchSeg->GetBegPlane() && SeedSeg->GetEndPlane()<=MatchSeg->GetEndPlane()) {
01822 
01823                 if( (SeedSeg->GetEntries()>3 && MatchSeg->GetEntries()>3)
01824                     || 4.*fabs( (SeedSeg->GetBegTPos()-SeedSeg->GetEndTPos())/(SeedSeg->GetEndPlane()-SeedSeg->GetBegPlane()) -
01825                                 (MatchSeg->GetBegTPos()-MatchSeg->GetEndTPos())/(MatchSeg->GetEndPlane()-MatchSeg->GetBegPlane()) ) < 10*StripWidth ) {
01826                   MatchSeg->AddMatchSegToBeg(SeedSeg);
01827                   SeedSeg->AddMatchSegToEnd(MatchSeg);
01828                 }
01829               }
01830 
01831             }
01832           }
01833         }
01834       } // End loop over triplets centered on plane i
01835       
01836     } // End loop over planes in module
01837 
01838   } // End loop over modules
01840 
01841 
01842 
01843   // Form matched associations between non-adjacent segments
01845   vector<TrackSegmentCam*> TempSeg1;
01846   vector<TrackSegmentCam*> TempSeg2;
01847 
01848   const int npts0=4; int npts; double inv_npts; int Module; int Plane;
01849   bool CheckCoilHole;
01850   
01851   
01852   // Loop over the planeviews U and V
01853   for(int view=0; view<2; ++view) {
01854     TempSeg1.clear(); TempSeg2.clear();
01855 
01856  
01857     // Loop over entries stored in ViewSegBank, above
01858     for(unsigned int i=0; i<ViewSegBank[view].size(); ++i) {
01859       TrackSegmentCam* Seg1 = ViewSegBank[view][i];
01860 
01861       // If no matched entries at end of segment
01862       if(Seg1->GetNMatchSegEnd()==0) {
01863         JoinFlag=false;
01864 
01865         
01866         // For FD, attempt to match segments across the coil hole
01867         // For ND, need to be careful making associations, so we don't join two separate tracks together
01869 
01870         // Check which module we are in
01871         Module=int(Seg1->GetEndPlane()/(PlanesInModule+1));
01872         npts=npts0;
01873 
01874         // These are the tpos values required to locate the FD coil hole
01875         if( (ModuleType==1 && Seg1->GetEndTPos()>-0.62 && Seg1->GetEndTPos()<0.62) 
01876             || ( 1+(Seg1->GetEndPlane()-Seg1->GetBegPlane())/2>5) ) {
01877           
01878           // Calculate range of possible association and configure
01879           // - worst case scenario - track crosses entire width of coil hole, tcoil = ~0.6m
01880           // - it will take a distance in z, zcoil = tcoil * dz/dt to do this
01881           // - zcoil is equivalent to nplanes = zcoil/0.0594 = tcoil / ( 0.0594 * dt/dz )
01882           // - npts = nplanes/2.0 = 1.0 / ( 0.198 * dt/dz)
01883           // - where dt/dz = Seg1->GetEndDir();
01884           inv_npts=0.198*Seg1->GetEndDir(); //was inv_npts=0.5*Seg1->GetEndDir();
01885           
01886           if(inv_npts<0) {inv_npts=-inv_npts;}
01887           if(inv_npts<0.01) {inv_npts=0.01;}
01888           npts=int(1./inv_npts);
01889 
01890           if(npts<13) {npts=13;}    //replaced 8 with 13
01891           if(npts>100) {npts=100;}  //replaced 18 with 30 - possibly this should be a function of the gradient of the track?
01892         }
01893 
01894         
01895         // Loop over this range of possible association
01896         for(int j=1; j<npts; ++j) {
01897           Plane=Seg1->GetEndPlane()+(2*j);
01898           
01899           if( JoinFlag==false && Plane<((PlanesInModule+1)*(Module+1)) ) {
01900             
01901             // Loop over segments on each possible plane
01902             for(unsigned int k=0; k<SegmentBank[Plane].size(); ++k) {
01903               TrackSegmentCam* Seg2 = SegmentBank[Plane][k];
01904 
01905               // Check association, first across coil-hole 
01906               if(ModuleType==1 && (( Seg2->GetBegTPos()>-0.62 && Seg2->GetBegTPos()<0.21
01907                                      && Seg1->GetEndTPos()>-0.21 && Seg1->GetEndTPos()<0.62)
01908                                    || (Seg2->GetBegTPos()>-0.21 && Seg2->GetBegTPos()<0.62
01909                                        && Seg1->GetEndTPos()>-0.62 && Seg1->GetEndTPos()<0.21)) ) {CheckCoilHole=true;}
01910               else {CheckCoilHole=false;}
01911               
01912 
01913               // Then main association checks
01914               if( (Seg2->GetSeedSegment()==Seg2 && Seg2->GetNMatchSegBeg()==0) 
01915                   && (Seg2->GetBegPlane()-Seg1->GetEndPlane()>0 || (Seg1->GetEntries()>5 && Seg2->GetEntries()>5) )
01916                   && (j<npts0 || CheckCoilHole==true || (1+(Seg1->GetEndPlane()-Seg1->GetBegPlane())/2>5) ) ) {
01917                 
01918                 if( Seg1->IsAssoc(Seg2) ) {
01919 
01920                   // ND nearby 2D track protection
01922                   if( ModuleType!=2 || (fabs(Seg1->GetEndDir()-Seg2->GetBegDir())<0.25 && 
01923                                         ((Seg1->GetEntries()<11 && Seg2->GetEntries()<11 
01924                                           && (ModuleType!=2 || Seg2->GetBegPlane()-Seg1->GetEndPlane()<50)) 
01925                                          || Seg2->GetBegPlane()-Seg1->GetEndPlane()<11) ) ) {
01926 
01927                     TempSeg1.push_back(Seg1);
01928                     TempSeg2.push_back(Seg2);
01929                     
01930                     JoinFlag=true;
01931                     
01932                     MSG("AlgTrackCamList", Msg::kVerbose) << "   NON-ADJ ASSOC: " 
01933                                                           << Seg1->GetBegPlane() << " " << Seg1->GetEndPlane() << " (" 
01934                                                           << Seg1->GetBegTPos() << ", " << Seg1->GetEndTPos() << ") "
01935                                                           << " enddir " << Seg1->GetEndDir()
01936                                                           << " Entries " << Seg1->GetEntries() << " "
01937                                                           << Seg2->GetBegPlane() << " " << Seg2->GetEndPlane() << " (" 
01938                                                           << Seg2->GetBegTPos() << ", " << Seg2->GetEndTPos() << ") " 
01939                                                           << " begdir " << Seg2->GetBegDir() << " Entries " << Seg2->GetEntries() << endl; 
01940                   }
01942                 }
01943               }
01944             }
01945           }
01946         } 
01947       }
01948     } // End loop over entries in ViewSegBank
01949     
01950 
01951     // Make the associations
01952     for(unsigned int i=0; i<TempSeg1.size(); ++i) {
01953       TrackSegmentCam* Seg1 = TempSeg1[i];
01954       TrackSegmentCam* Seg2 = TempSeg2[i];
01955 
01956       if(Seg1->GetBegPlane()<=Seg2->GetBegPlane() && Seg1->GetEndPlane()<=Seg2->GetEndPlane()) {
01957         
01958         if( (Seg1->GetEntries()>3 && Seg2->GetEntries()>3)
01959             || 4.*fabs( (Seg1->GetBegTPos()-Seg1->GetEndTPos())/(Seg1->GetBegPlane()-Seg1->GetEndPlane()) -
01960                         (Seg2->GetBegTPos()-Seg2->GetEndTPos())/(Seg2->GetBegPlane()-Seg2->GetEndPlane()) ) < 10*StripWidth ) {
01961           Seg2->AddMatchSegToBeg(Seg1);
01962           Seg1->AddMatchSegToEnd(Seg2);
01963         }
01964       }
01965 
01966     }
01967 
01968   } // End loop over planeviews
01970 
01971 
01972 
01973   // Print out list of segments
01975   MSG("AlgTrackCamList", Msg::kVerbose) << " *** LIST OF MATCHED SEG ASSOCIATIONS *** " << endl;
01976 
01977   for(int View=0; View<2; ++View) {
01978 
01979     MSG("AlgTrackCamList", Msg::kVerbose) << "View: " << View << endl;
01980 
01981     for(unsigned int i=0; i<ViewSegBank[View].size(); ++i) {
01982       TrackSegmentCam* segment = (TrackSegmentCam*)(ViewSegBank[View][i]);
01983       MSG("AlgTrackCamList", Msg::kVerbose) << "---  Seg0 number =" << i
01984                                             << "  begpln: "  << segment->GetBegPlane()
01985                                             << "  begtpos: " << segment->GetBegTPos()
01986                                             << "  endpln: "  << segment->GetEndPlane()
01987                                             << "  endtpos: " << segment->GetEndTPos() << endl;
01988 
01989       MSG("AlgTrackCamList", Msg::kVerbose) << "     Beg: " << endl;
01990       for(unsigned int j=0; j<segment->GetNMatchSegBeg(); ++j) {
01991         TrackSegmentCam* segtmp = segment->GetMatchSegBeg(j);
01992         MSG("AlgTrackCamList", Msg::kVerbose) << "  Match number=" << j
01993                                               << "  begpln: "  << segtmp->GetBegPlane()
01994                                               << "  begtpos: " << segtmp->GetBegTPos()
01995                                               << "  endpln: "  << segtmp->GetEndPlane()
01996                                               << "  endtpos: "  << segtmp->GetEndTPos() << endl;
01997       }
01998       
01999       MSG("AlgTrackCamList", Msg::kVerbose) << "     End: " << endl;
02000       for(unsigned int j=0; j<segment->GetNMatchSegEnd(); ++j) {
02001         TrackSegmentCam* segtmp = segment->GetMatchSegEnd(j);
02002         MSG("AlgTrackCamList", Msg::kVerbose) << "  Match number=" << j
02003                                               << "  begpln: "  << segtmp->GetBegPlane()
02004                                               << "  begtpos: " << segtmp->GetBegTPos()
02005                                               << "  endpln: "  << segtmp->GetEndPlane()
02006                                               << "  endtpos: " << segtmp->GetEndTPos() << endl;           
02007       }
02008     }
02009   }
02011 
02012 
02013 }
02015 
02016 
02017 
02018 
02019 
02021 void AlgTrackCamList::FirstUVComparison()
02022 {
02023   // Having made sections of the track, from 'matched' segments, we compare
02024   // the sections in the U view with those in the V view, looking for compatibity.
02025 
02026   // First all clusters are investigated to mark the segments as track-like or
02027   // shower-like. Then track-like segments which have 'overlapping' partners in the 
02028   // opposite view are marked by setting their UID values to 2
02029 
02030   MSG("AlgTrackCamList", Msg::kVerbose) << " *** Comparing views (1) *** " << endl;
02031 
02032 
02033   int shwctr, plnctr;
02034   unsigned int nsegments=0;
02035   unsigned int nsegmentsV=0;
02036   vector<TrackSegmentCam*> mysegbnk[2];
02037 
02038 
02039   // Determine track-like segments
02041   for(int View=0; View<2; ++View) {
02042 
02043     // Loop over all segments in the current view
02044     nsegments = ViewSegBank[View].size();
02045     for(unsigned int i=0; i<nsegments; ++i) {
02046 
02047       TrackSegmentCam* Seg = ViewSegBank[View][i];
02048       shwctr=0; plnctr=0;
02049       
02050       // Loop over all the clusters in the current segment
02051       const unsigned int ncluster = Seg->GetEntries();
02052       for(unsigned int j=0;j<ncluster;++j) {
02053         ClusterCam* cluster = Seg->GetCluster(j);
02054         
02055         // Find how track-like or shower-like the cluster is
02056         if(cluster->GetTrkFlag()>1) { 
02057           if(cluster->GetShwFlag()<1) {shwctr++;}
02058         }
02059         if(cluster->GetTrkPlnFlag()>0) {plnctr++;}
02060       }
02061       
02062       // Set the UID accordingly. This depends greatly on the initial values 
02063       // of the shower flags used when identifying track and shower clusters.
02064       if(CambridgeAnalysis==false) {Seg->SetUID(1);}
02065 
02066       if( plnctr>1 && Seg->GetEntries()>4 ) { // Just added
02067         if(CambridgeAnalysis==true && shwctr>0) {Seg->SetUID(1);} 
02068         if(shwctr>2) {Seg->SetUID(2);} 
02069       }
02070     }
02071   }
02073 
02074 
02075   // Loop over segments in U view
02077   nsegments = ViewSegBank[0].size();
02078   for(unsigned int i=0; i<nsegments; ++i) {
02079 
02080     TrackSegmentCam* Segu = ViewSegBank[0][i];
02081     
02082     // For these, loop over segments in V view
02083     nsegmentsV = ViewSegBank[1].size();
02084     for(unsigned int j=0; j<nsegmentsV; ++j) {
02085 
02086       TrackSegmentCam* Segv = ViewSegBank[1][j];
02087 
02088       // Select pairs of segments, one from each view, which overlap by more than 1 plane
02089       // and which both have UID>0 (i.e. were marked as track-like above)
02090       if( Segu->GetBegPlane()+1<Segv->GetEndPlane() 
02091           && Segu->GetEndPlane()>Segv->GetBegPlane()+1 
02092           && Segu->GetUID()>0 && Segv->GetUID()>0 ) {
02093         if(Segv->GetUID()>1) {mysegbnk[0].push_back(Segu); }
02094         if(Segu->GetUID()>1) {mysegbnk[1].push_back(Segv); }
02095       }
02096     }
02097   }
02099 
02100   
02101   // Loop over the segments we just selected and set their UIDs to 2
02103   for(int View=0; View<2; ++View) {
02104     nsegments = mysegbnk[View].size();
02105     for(unsigned int i=0; i<nsegments; ++i) {
02106       mysegbnk[View][i]->SetUID(2);
02107     }
02108   }
02110 
02111 
02112 
02113   // Mark clusters that aren't going to be available for ND +/-10 plane track finding
02115   if(vldc->GetDetector()==Detector::kNear) {
02116     
02117     // First mark all those for which we will probably find a +/-2 plane track
02119     for(int View=0; View<2; ++View) {
02120       for(unsigned int i=0; i<mysegbnk[View].size(); ++i) {
02121         TrackSegmentCam* Seg = mysegbnk[View][i];
02122 
02123         for(unsigned int j=0; j<Seg->GetEntries(); ++j) {
02124           Seg->GetCluster(j)->SetNDFlag(0);  
02125         }
02126       }
02127     }
02129 
02130 
02131     // Then look specifically for clusters that are in +/-2 plane sections of detector
02133     double BegTPos, EndTPos, Centre, HitTPos;
02134     double Tolerance=2.*StripWidth;
02135 
02136     // Loop over all clusters
02137     for(int i=0; i<PlanesInModule; ++i) {
02138       for(unsigned int j=0; j<ClusterBank[i].size(); ++j) {
02139         ClusterCam* Clust = ClusterBank[i][j];
02140 
02141         // Get cluster properties       
02142         BegTPos=Clust->GetBegTPos();
02143         EndTPos=Clust->GetEndTPos();
02144         Centre=0.5*(BegTPos+EndTPos);
02145 
02146 
02147         // Now compare with the hits +/-2 planes away
02148         if(Clust->GetNDFlag()>0 && i>1) {
02149           for(unsigned int k=0; k<HitBank[i-2].size(); ++k) {
02150             HitTPos=HitBank[i-2][k]->GetTPos();
02151 
02152             if(fabs(HitTPos-Centre)<Tolerance || fabs(HitTPos-BegTPos)<Tolerance 
02153                || fabs(HitTPos-EndTPos)<Tolerance) {Clust->SetNDFlag(0); break;}
02154           }
02155         }
02156 
02157         if(Clust->GetNDFlag()>0) {
02158           for(unsigned int k=0; k<HitBank[i+2].size(); ++k) {
02159             HitTPos=HitBank[i+2][k]->GetTPos();
02160             
02161             if(fabs(HitTPos-Centre)<Tolerance || fabs(HitTPos-BegTPos)<Tolerance 
02162                || fabs(HitTPos-EndTPos)<Tolerance) {Clust->SetNDFlag(0); break;}
02163           }
02164         }
02165       }
02166     }
02168 
02169   } // End ND only section
02171 
02172 
02173   // Print out the results
02175   for(int View=0; View<2; ++View) {
02176     MSG("AlgTrackCamList", Msg::kVerbose) << "  View =" << View << endl;
02177 
02178     nsegments = ViewSegBank[View].size();
02179     for(unsigned int i=0; i<nsegments; ++i) {
02180 
02181       TrackSegmentCam* Seg = ViewSegBank[View][i];
02182 
02183       MSG("AlgTrackCamList", Msg::kVerbose) << "  Seg number=" << i 
02184                                             << "  begpln: "  << Seg->GetBegPlane()
02185                                             << "  begtpos: " << Seg->GetBegTPos()
02186                                             << "  endpln: "  << Seg->GetEndPlane()
02187                                             << "  endtpos: " << Seg->GetEndTPos() 
02188                                             << "  UID: "     << Seg->GetUID() 
02189                                             << "  clusters: "<< Seg->GetEntries()
02190                                             << endl;
02191     }
02192   }
02194   
02195   return;
02196 }
02198 
02199 
02200 
02201 
02203 void AlgTrackCamList::NearDetectorTriplets()
02204 {
02205   MSG("AlgTrackCamList", Msg::kVerbose) << " MAKE ND TRIPLETS " << endl;
02206 
02207   int TripAssocNum; bool AlternateTriplets;
02208   vector<TrackSegmentCam*> NDViewSegBank[2];
02209   vector<TrackSegmentCam*> TempNDViewSegBank[2];
02210 
02211 
02212   // MAKE THE TRIPLETS
02214   for(int i=10; i<PlanesInModule-9; ++i) {
02215 
02216     // Only consider Fully Instrumented planes
02217     if((i-1)%10!=0 && (i-6)%10!=0) {continue;}
02218 
02219     // Loop over clusters on plane. This is our plane 0, the origin.
02220     for(unsigned int k0=0; k0<ClusterBank[i].size(); ++k0) {
02221     
02222       if(ClusterBank[i][k0]->GetTrkFlag()>0 && ClusterBank[i][k0]->GetNDFlag()>0) {
02223         
02224         // Look for triplets of form m 0 p
02226         if( (i-10)>=0 && ClusterBank[i-10].size()>0 && (i+10)<=PlanesInModule && ClusterBank[i+10].size()>0 ) {
02227           
02228           // Look at the clusters available on plane i-10...
02229           for(unsigned int km=0; km<ClusterBank[i-10].size(); ++km) {
02230             
02231             // ...and the clusters available on plane i+10
02232             for(unsigned int kp=0; kp<ClusterBank[i+10].size(); ++kp) {
02233               
02234               if( ClusterBank[i-10][km]->GetTrkFlag()>0 && ClusterBank[i-10][km]->GetNDFlag()>0
02235                   && ClusterBank[i+10][kp]->GetTrkFlag()>0 && ClusterBank[i+10][kp]->GetNDFlag()>0 ) {
02236                 
02237                 // Check the track-like association of the three clusters
02238                 TripAssocNum=ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-10][km],ClusterBank[i+10][kp],10);
02239         
02240                 // If the association is good, make the triplet
02241                 if(TripAssocNum>0) {
02242                   TrackSegmentCam* seg0 = new TrackSegmentCam(ClusterBank[i-10][km], ClusterBank[i][k0], ClusterBank[i+10][kp]);
02243                   for(unsigned int j=0; j<seg0->GetEntries(); ++j) {seg0->GetCluster(j)->SetNDFlag(2);}
02244 
02245                   NDSegmentBank[i].push_back(seg0);
02246                 }
02247               }
02248             }
02249           }
02250         }
02252 
02253 
02254 
02255         
02256         // Look for triplets of form m X 0 p  
02258         if( (i-20)>=0 && ClusterBank[i-20].size()>0 && (i+10)<=PlanesInModule && ClusterBank[i+10].size()>0 ) {
02259 
02260           // Look at the clusters on plane i+10...
02261           for(unsigned int kp=0; kp<ClusterBank[i+10].size(); ++kp) {
02262               
02263             // ...and the clusters on plane i-20
02264             for(unsigned int km=0; km<ClusterBank[i-20].size(); ++km) {
02265 
02266               if( ClusterBank[i-20][km]->GetTrkFlag()>0 && ClusterBank[i+10][kp]->GetTrkFlag()>0
02267                   && ClusterBank[i-20][km]->GetNDFlag()>0 && ClusterBank[i+10][kp]->GetNDFlag()>0 ) {
02268 
02269                 // Check the track-like association of the three clusters
02270                 TripAssocNum=ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-20][km],ClusterBank[i+10][kp],10);
02271                   
02272                 // If the association is good, check whether we can make the triplet
02273                 if(TripAssocNum>0) {
02274                   AlternateTriplets=false;
02275                       
02276                   // Check to see if there is also an alternate triplet possibility with clusters on plane i-2
02277                   // i.e. Want to make sure that the X in "m X 0 p" is correct.
02278 
02279                   if(AlternateTriplets==false && ClusterBank[i-10].size()>0) {
02280                     // Look at the clusters on plane i-10
02281                     for(unsigned int ktmp=0; ktmp<ClusterBank[i-10].size(); ++ktmp) {
02282                       if(AlternateTriplets==false && ClusterBank[i-10][ktmp]->GetTrkFlag()>0
02283                          && ClusterBank[i-10][ktmp]->GetNDFlag()>0
02284                          && ClusterBank[i-10][ktmp]->IsTrkAssoc(ClusterBank[i-20][km],ClusterBank[i][k0],10)>0 
02285                          && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-10][ktmp],ClusterBank[i+10][kp],10)>0) 
02286                         {AlternateTriplets=true;}
02287                     }
02288                   }
02289                                       
02290                   // If everything is good, make the triplet
02291                   if(AlternateTriplets==false) {
02292                     TrackSegmentCam* seg0 = new TrackSegmentCam(ClusterBank[i-20][km],ClusterBank[i][k0],ClusterBank[i+10][kp]);
02293                     for(unsigned int j=0; j<seg0->GetEntries(); ++j) {seg0->GetCluster(j)->SetNDFlag(2);}
02294 
02295                     NDSegmentBank[i].push_back(seg0);
02296                   }
02297                 }
02298               }
02299             }
02300           }
02301         }
02303 
02304 
02305 
02306 
02307         // Look for triplets of form m 0 X p  
02309         if( (i-10)>=0 && ClusterBank[i-10].size()>0 && (i+20)<=PlanesInModule && ClusterBank[i+20].size()>0 ) {
02310 
02311           // Look at the clusters on plane i-10...
02312           for(unsigned int km=0; km<ClusterBank[i-10].size(); ++km) {
02313               
02314             // ... and the clusters on plane i+20
02315             for(unsigned int kp=0; kp<ClusterBank[i+20].size(); ++kp) {
02316 
02317               if( ClusterBank[i-10][km]->GetTrkFlag()>0 && ClusterBank[i+20][kp]->GetTrkFlag()>0
02318                   && ClusterBank[i-10][km]->GetNDFlag()>0 && ClusterBank[i+20][kp]->GetNDFlag()>0 ) {
02319 
02320                 // Check the track-like association of the three clusters
02321                 TripAssocNum=ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-10][km],ClusterBank[i+20][kp],10);
02322                    
02323                 // If the association is good, check whether we can make the triplet
02324                 if(TripAssocNum>0) {
02325                   AlternateTriplets=false;
02326                       
02327                   // Check to see if there is also an alternate triplet possibility with clusters on plane i+2
02328                   // i.e. Want to make sure that the X in "m 0 X p" is correct.
02329 
02330                   if(AlternateTriplets==false && ClusterBank[i+10].size()>0) {
02331                     // Look at the clusters on plane i+10
02332                     for(unsigned int ktmp=0; ktmp<ClusterBank[i+10].size(); ++ktmp) {
02333                       if(AlternateTriplets==false && ClusterBank[i+10][ktmp]->GetTrkFlag()>0 
02334                          && ClusterBank[i+10][ktmp]->GetNDFlag()>0
02335                          && ClusterBank[i+10][ktmp]->IsTrkAssoc(ClusterBank[i][k0],ClusterBank[i+20][kp],10)>0 
02336                          && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-10][km],ClusterBank[i+10][ktmp],10)>0) 
02337                         {AlternateTriplets=true;}
02338                     }
02339                   }
02340                                       
02341                   // If everything is good, make the triplet
02342                   if(AlternateTriplets==false) {
02343                     // Store segment on empty plane too
02344                     for(int j=0; j<2; ++j) {
02345                       TrackSegmentCam* seg0 = new TrackSegmentCam(ClusterBank[i-10][km],ClusterBank[i][k0],ClusterBank[i+20][kp]);
02346                       for(unsigned int k=0; k<seg0->GetEntries(); ++k) {seg0->GetCluster(k)->SetNDFlag(2);}
02347   
02348                       NDSegmentBank[i+10*j].push_back(seg0);
02349                     }
02350                   }
02351                 }
02352               }
02353             }
02354           }
02355         }
02357 
02358 
02359 
02360 
02361         // Look for triplets of form m X 0 X p
02363         if( (i-20)>=0 && ClusterBank[i-20].size()>0 && (i+20)<=PlanesInModule && ClusterBank[i+20].size()>0 ) {
02364 
02365           // Look at clusters on planes i-20 and i+20
02366           for(unsigned int km=0; km<ClusterBank[i-20].size(); ++km) {
02367             for(unsigned int kp=0; kp<ClusterBank[i+20].size(); ++kp) {
02368 
02369               if( ClusterBank[i-20][km]->GetTrkFlag()>0 && ClusterBank[i+20][kp]->GetTrkFlag()>0
02370                   && ClusterBank[i-20][km]->GetNDFlag()>0 && ClusterBank[i+20][kp]->GetNDFlag()>0 ) {
02371 
02372                 // Check the track-like association of the three clusters
02373                 TripAssocNum=ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-20][km],ClusterBank[i+20][kp],10);
02374                   
02375                 // If the association is good, check whether we can make the triplet
02376                 if(TripAssocNum>0) {
02377                   AlternateTriplets=false;
02378                     
02379                   // Check to see if there are alternate triplet possibilities with clusters on plane i-10 or i+10
02380                   // i.e. Want to make sure that the Xs in "m X 0 X p" are correct.
02381                     
02382                   // Check first X, plane i-10
02383                   if(AlternateTriplets==false && ClusterBank[i-10].size()>0) {
02384                     // Look at any clusters on plane i-10
02385                     for(unsigned int ktmp=0; ktmp<ClusterBank[i-10].size(); ++ktmp) {
02386                       if(AlternateTriplets==false && ClusterBank[i-10][ktmp]->GetTrkFlag()>0 
02387                          && ClusterBank[i-10][ktmp]->GetNDFlag()>0
02388                          && ClusterBank[i-10][ktmp]->IsTrkAssoc(ClusterBank[i-20][km],ClusterBank[i][k0],10)>0 
02389                          && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-10][ktmp],ClusterBank[i+20][kp],10)>0) 
02390                         {AlternateTriplets=true;}
02391                     }
02392                   }
02393                     
02394                   // Check second X, plane i+10
02395                   if(AlternateTriplets==false && ClusterBank[i+10].size()>0) {
02396                     // Look at any clusters on plane i+10
02397                     for(unsigned int ktmp=0; ktmp<ClusterBank[i+10].size(); ++ktmp) {
02398                       if(AlternateTriplets==false  && ClusterBank[i+10][ktmp]->GetTrkFlag()>0 
02399                          && ClusterBank[i+10][ktmp]->GetNDFlag()>0
02400                          && ClusterBank[i+10][ktmp]->IsTrkAssoc(ClusterBank[i][k0],ClusterBank[i+20][kp],10)>0 
02401                          && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-20][km],ClusterBank[i+10][ktmp],10)>0) 
02402                         {AlternateTriplets=true;}
02403                     }
02404                   }
02405                     
02406                   // Check both Xs together, planes i-10 and i+10
02407                   if(AlternateTriplets==false && ClusterBank[i-10].size()>0 
02408                      && ClusterBank[i+10].size()>0) {
02409                       
02410                     // Loop again at any clusters on plane i-10
02411                     for(unsigned int ktmp=0; ktmp<ClusterBank[i-10].size(); ++ktmp) {
02412                         
02413                       // Look again at any clusters on plane i+10
02414                       for(unsigned int ktmp1=0; ktmp1<ClusterBank[i+10].size(); ++ktmp1) {
02415                         if(AlternateTriplets==false 
02416                            && ClusterBank[i-10][ktmp]->GetTrkFlag()>0 && ClusterBank[i+10][ktmp1]->GetTrkFlag()>0
02417                            && ClusterBank[i-10][ktmp]->GetNDFlag()>0  && ClusterBank[i+10][ktmp1]->GetNDFlag()>0 
02418                            && ClusterBank[i-10][ktmp]->IsTrkAssoc(ClusterBank[i-20][km],ClusterBank[i][k0],10)>0 
02419                            && ClusterBank[i][k0]->IsTrkAssoc(ClusterBank[i-10][ktmp],ClusterBank[i+10][ktmp1],10)>0 
02420                            && ClusterBank[i+10][ktmp1]->IsTrkAssoc(ClusterBank[i][k0],ClusterBank[i+20][kp],10)>0)
02421                           {AlternateTriplets=true;}
02422                       }
02423                     }
02424                   }
02425 
02426                   // If everything is good, make the triplet
02427                   if(AlternateTriplets==false) {
02428                     // Store segment on empty planes too
02429                     for(int j=0; j<2; ++j) {
02430                       TrackSegmentCam* seg0 = new TrackSegmentCam(ClusterBank[i-20][km],ClusterBank[i][k0],ClusterBank[i+20][kp]);
02431                       for(unsigned int k=0; k<seg0->GetEntries(); ++k) {seg0->GetCluster(k)->SetNDFlag(2);}
02432         
02433                       NDSegmentBank[i+10*j].push_back(seg0);
02434                     }
02435                   }
02436                 }
02437               }
02438             }
02439           }
02440         }
02442 
02443       }
02444     }
02445   }
02447 
02448 
02449 
02450   // Print out list of triplets
02452   MSG("AlgTrackCamList", Msg::kVerbose) << " *** LIST OF ND TRIPLETS *** " << endl;
02453   for(int i=0; i<500; ++i) {
02454     for(unsigned int j=0;j<NDSegmentBank[i].size(); ++j) {
02455       MSG("AlgTrackCamList", Msg::kVerbose) << " Segment Num " << j << ", Plane " << i <<endl;
02456       
02457       ClusterCam* clr0 = NDSegmentBank[i][j]->GetCluster(0);
02458       ClusterCam* clr1 = NDSegmentBank[i][j]->GetCluster(1);
02459       ClusterCam* clr2 = NDSegmentBank[i][j]->GetCluster(2);
02460       
02461       MSG("AlgTrackCamList", Msg::kVerbose) << " (" << clr0->GetPlane() << "," 
02462                                             << clr0->GetBegTPos() << "->" << clr0->GetEndTPos() << ") "
02463                                             << " (" << clr1->GetPlane() << "," << clr1->GetBegTPos() 
02464                                             << "->" << clr1->GetEndTPos() << ") "
02465                                             << " (" << clr2->GetPlane() << "," << clr2->GetBegTPos() 
02466                                             << "->" << clr2->GetEndTPos() << ") " << endl;
02467     }
02468   }
02470 
02471 
02472 
02473 
02474   // Now loop over these segments and check associations
02476   for(int i=10; i<PlanesInModule-9; ++i) {
02477     
02478     if((i+10)<=PlanesInModule && NDSegmentBank[i].size()>0 && NDSegmentBank[i+10].size()>0) {
02479         
02480       // Look at the segments on plane i
02481       for(unsigned int k0=0; k0<NDSegmentBank[i].size(); ++k0) {
02482         TrackSegmentCam* Seg0 = NDSegmentBank[i][k0];
02483 
02484         // For each of these, look at the segments on plane i+10
02485         for(unsigned int kp=0; kp<NDSegmentBank[i+10].size(); ++kp) {
02486           TrackSegmentCam* NextSeg = NDSegmentBank[i+10][kp];
02487 
02488           // Check associations. 
02489           if(Seg0->IsAssoc(NextSeg)) {
02490               
02491             // If segments are associated, add to list of all associations
02492             Seg0->AddAssocSegToEnd(NextSeg);
02493             NextSeg->AddAssocSegToBeg(Seg0);
02494           }
02495         }
02496       }
02497     }
02498   }
02500   
02501 
02502 
02503   // Print out list of all associations
02505   MSG("AlgTrackCamList", Msg::kVerbose) << " *** LIST OF ALL ND TRIPLET ASSOCIATIONS *** " << endl;
02506 
02507   // Print out list of triplets
02508   for(int i=0; i<500; ++i) {
02509     for(unsigned int j=0;j<NDSegmentBank[i].size(); ++j) {
02510       TrackSegmentCam* segment = NDSegmentBank[i][j];
02511 
02512       MSG("AlgTrackCamList", Msg::kVerbose) << "--- Plane " << i << ", Seg Number " << j 
02513                                             << ", BegPlane " << segment->GetBegPlane() 
02514                                             << ", EndPlane " << segment->GetEndPlane() 
02515                                             << ", BegTPos " << segment->GetBegTPos() 
02516                                             << ", EndTPos " << segment->GetEndTPos() 
02517                                             <<endl;
02518       
02519       MSG("AlgTrackCamList", Msg::kVerbose) << " Beg: " <<endl;
02520       for(unsigned int k=0; k<segment->GetNAssocSegBeg(); ++k) {
02521         TrackSegmentCam* segtmp = segment->GetAssocSegBeg(k);
02522         MSG("AlgTrackCamList", Msg::kVerbose) << "  Assoc number=" << k
02523                                               << "  begpln: " << segtmp->GetBegPlane()
02524                                               << "  begtpos: " << segtmp->GetBegTPos()
02525                                               << "  endpln: " << segtmp->GetEndPlane()
02526                                               << "  endtpos: " << segtmp->GetEndTPos() << endl;
02527       }
02528       
02529       MSG("AlgTrackCamList", Msg::kVerbose) << " End: " <<endl;
02530       for(unsigned int k=0; k<segment->GetNAssocSegEnd(); ++k) {
02531         TrackSegmentCam* segtmp = segment->GetAssocSegEnd(k);
02532         MSG("AlgTrackCamList", Msg::kVerbose) << "  Assoc number=" << k
02533                                               << "  begpln: " << segtmp->GetBegPlane()
02534                                               << "  begtpos: " << segtmp->GetBegTPos()
02535                                               << "  endpln: " << segtmp->GetEndPlane()
02536                                               << "  endtpos: " << segtmp->GetEndTPos() << endl;           
02537       }
02538     }
02539   }
02541 
02542 
02543 
02544   // Look for chains of associations and make ND 2D tracks
02546   bool JoinFlag;
02547   
02548   for(int i=10; i<PlanesInModule-9; ++i) {
02549     // Loop over the triplets centered on plane i
02550     for(unsigned int j=0; j<NDSegmentBank[i].size(); ++j) {
02551 
02552       TrackSegmentCam* Seg = NDSegmentBank[i][j];
02553 
02554 
02555       // Firstly, consider isolated segments. These must be their own seed segments.
02556       if(Seg->GetNAssocSegBeg()==0 && Seg->GetNAssocSegEnd()==0) {
02557         NDViewSegBank[Seg->GetPlaneView()].push_back(Seg);
02558         Seg->SetSeedSegment(Seg);
02559       }
02560 
02561 
02562       // Then, consider those segments which have some associations
02563       if(Seg->GetNAssocSegBeg()>0 || Seg->GetNAssocSegEnd()>0) {
02564         JoinFlag=false;
02565 
02566         // If there is one assoc at beginning (always false for first segment in module)
02567         if(Seg->GetNAssocSegBeg()==1) {
02568           TrackSegmentCam* Segm = Seg->GetAssocSegBeg(0);
02569 
02570           // Check that we are considering a simple chain of segments
02571           if(Segm->GetNAssocSegEnd()==1) {
02572             // Get the last segment in the chain of segments
02573             TrackSegmentCam* SeedSeg = Segm->GetSeedSegment();
02574 
02575             SeedSeg->AddSegment(Seg); 
02576             Seg->SetSeedSegment(SeedSeg);
02577             Seg->SetUID(-1);
02578             JoinFlag=true;
02579           }
02580         }
02581 
02582         // Now consider those triplets which aren't just one assoc at beg and one at end
02583         if(JoinFlag==false) {
02584           Seg->SetSeedSegment(Seg);
02585           NDViewSegBank[Seg->GetPlaneView()].push_back(Seg);
02586                   
02587           // Loop over the associations at beginning
02588           for(unsigned int k=0; k<Seg->GetNAssocSegBeg(); ++k) {
02589             TrackSegmentCam* SeedSeg = Seg->GetAssocSegBeg(k)->GetSeedSegment();
02590             
02591             Seg->AddMatchSegToBeg(SeedSeg);
02592             SeedSeg->AddMatchSegToEnd(Seg);
02593           }
02594         }
02595       }
02596 
02597     } 
02598   }
02600 
02601 
02602 
02603 
02604   // Print out the list of 2D tracks
02606   MSG("AlgTrackCamList", Msg::kVerbose)  << " *** LIST OF ND 2D TRACKS *** " << endl;
02607   for(int View=0; View<2; ++View) {
02608 
02609     MSG("AlgTrackCamList", Msg::kVerbose) << "View: " << View << endl;
02610     for(unsigned i=0; i<NDViewSegBank[View].size(); ++i) {
02611       TrackSegmentCam* Seg = NDViewSegBank[View][i];
02612       MSG("AlgTrackCamList", Msg::kVerbose) << "  i=" << i
02613                                             << "  begpln: "  << Seg->GetBegPlane()
02614                                             << "  begtpos: " << Seg->GetBegTPos()
02615                                             << "  endpln: "  << Seg->GetEndPlane()
02616                                             << "  endtpos: " << Seg->GetEndTPos() << endl;
02617     }
02618   }
02620 
02621 
02622 
02623 
02624   // Now match to existing 2D tracks
02625   // If no match, store separately in ViewSegBank
02627   bool Match;
02628 
02629   // For ND U segments
02631   for(unsigned int i=0; i<NDViewSegBank[0].size(); ++i) {
02632     TrackSegmentCam* NDSegu = NDViewSegBank[0][i];
02633     Match=false;
02634       
02635     // Consider the other U segments
02636     for(unsigned int j=0; j<ViewSegBank[0].size(); ++j) {
02637       TrackSegmentCam* Segu = ViewSegBank[0][j];
02638 
02639       if(Segu->GetUID()>1) {
02640 
02641         if(NDSegu->GetEndPlane()<Segu->GetEndPlane()) {Match=NDSegu->IsAssoc(Segu);}
02642         else {Match=Segu->IsAssoc(NDSegu);}
02643 
02644         if(Match) {
02645           if(NDSegu->GetBegPlane()<Segu->GetBegPlane()) {Segu->AddMatchSegToBeg(NDSegu);}
02646           else {Segu->AddMatchSegToEnd(NDSegu);}
02647 
02648           MSG("AlgTrackCamList", Msg::kVerbose) << "U Match, NDbegplane " << NDSegu->GetBegPlane() 
02649                                                 << " Endplane " << NDSegu->GetEndPlane()
02650                                                 << " Begtpos " << NDSegu->GetBegTPos() 
02651                                                 << " Endtpos " << NDSegu->GetEndTPos()
02652                                                 << " 2d track begplane " << Segu->GetBegPlane() 
02653                                                 << " Endplane " << Segu->GetEndPlane()
02654                                                 << " Begtpos " << Segu->GetBegTPos() 
02655                                                 << " Endtpos " << Segu->GetEndTPos() << endl;
02656         }
02657       }
02658     }
02659 
02660     if(Match) {NDSegu->SetUID(2);}
02661     else {NDSegu->SetUID(2); TempNDViewSegBank[0].push_back(NDSegu);}
02662   }
02664 
02665 
02666   // For ND V segments
02668   for(unsigned int i=0; i<NDViewSegBank[1].size(); ++i) {
02669     TrackSegmentCam* NDSegv = NDViewSegBank[1][i];
02670     Match=false;
02671         
02672     // Consider the other V segments
02673     for(unsigned int j=0; j<ViewSegBank[1].size(); ++j) {
02674       TrackSegmentCam* Segv = ViewSegBank[1][j];
02675 
02676       if(Segv->GetUID()>1) {
02677 
02678         if(NDSegv->GetEndPlane()<Segv->GetEndPlane()) {Match=NDSegv->IsAssoc(Segv);}
02679         else {Match=Segv->IsAssoc(NDSegv);}
02680 
02681         if(Match) {
02682           if(NDSegv->GetBegPlane()<Segv->GetBegPlane()) {Segv->AddMatchSegToBeg(NDSegv);}
02683           else {Segv->AddMatchSegToEnd(NDSegv);}
02684 
02685           MSG("AlgTrackCamList", Msg::kVerbose) << "V Match, NDbegplane " << NDSegv->GetBegPlane() 
02686                                                 << " Endplane " << NDSegv->GetEndPlane()
02687                                                 << " Begtpos " << NDSegv->GetBegTPos() 
02688                                                 << " Endtpos " << NDSegv->GetEndTPos()
02689                                                 << " 2d track begplane " << Segv->GetBegPlane() 
02690                                                 << " Endplane " << Segv->GetEndPlane()
02691                                                 << " Begtpos " << Segv->GetBegTPos() 
02692                                                 << " Endtpos " << Segv->GetEndTPos() << endl;
02693         }
02694       }
02695     }
02696 
02697     if(Match) {NDSegv->SetUID(2);}
02698     else {NDSegv->SetUID(2); TempNDViewSegBank[1].push_back(NDSegv);}
02699   }
02700 
02701 
02702   // Now store those segments marked above in ViewSegBank
02703   for(int View=0; View<2; ++View) {
02704     for(unsigned int i=0; i<TempNDViewSegBank[View].size(); ++i) {
02705       ViewSegBank[View].push_back(TempNDViewSegBank[View][i]);
02706     }
02707   }
02709 
02710 
02711   // Clean up
02712   for(int i=0; i<2; ++i) {NDViewSegBank[i].clear(); TempNDViewSegBank[i].clear();}
02713 
02714   return;
02715 }
02717 
02718 
02719 
02721 void AlgTrackCamList::Form2DTracks()
02722 {
02723   // Of the segments identified as good above, we identify the segments which
02724   // are good seeds for the track i.e. from which we can propagate back and forth
02725   // along matched segments to find a long track.
02726  
02727   // Then, for the first seed segment, we try to propagate backwards and forwards,
02728   // marking the segments we use with different TmpTrkFlag settings.
02729 
02730   // For a seed segment, Seg0, we firstly move in the direction of increasing plane
02731   // number. We mark all the segments we use with TmpTrkFlag 1. The seed segment is
02732   // labelled with TmpTrkFlag 3.
02733 
02734   // Some paths will lead further than others. We are interested in the longest paths, 
02735   // and move back towards Seg0 along the longest paths, marking the segments used 
02736   // with TmpTrkFlag 2.
02737 
02738   // Having done this, we can carry out a similar procedure, but initially moving 
02739   // backwards from Seg0 to lower plane numbers, before returning to Seg0 again.
02740 
02741   // So, this arrangement of segments...
02742   //
02743   //       Seg  Seg                                  Seg
02744   //                  Seg                      Seg
02745   //                        Seg   Seg0   Seg 
02746   //                  Seg                      Seg   Seg   Seg
02747   //                                                 
02748   //               Seg                               Seg
02749   //                                                       Seg   Seg
02750 
02751   // Is labelled as follows...
02752   //
02753   //       2     2                                    1 
02754   //                   2                        1 
02755   //                         2     3      2  
02756   //                   1                        2     2     2 
02757   //                                                 
02758   //                1                                 2 
02759   //                                                        2     2 
02760   //
02761 
02762   // It is possible that there are multiple paths along segments with TmpTrkFlag 2, 
02763   // as above. The best path is selected by obtaining a score for each, based on
02764   // straightness and length.
02765 
02766 
02767 
02768   // Define containers
02769   vector<TrackSegmentCam*> BestSeedSegments;
02770   vector<TrackSegmentCam*> SeedSegments;
02771 
02772   vector<TrackSegmentCam*> Temp;
02773   vector<TrackSegmentCam*> mTemp;
02774   vector<TrackSegmentCam*> pTemp;
02775   vector<TrackSegmentCam*> BegTemp;
02776   vector<TrackSegmentCam*> EndTemp;
02777   vector<TrackSegmentCam*> TempBank1;
02778   vector<TrackSegmentCam*> TempBank2;
02779 
02780   vector <vector<TrackSegmentCam*> > BegBank;
02781   vector <vector<TrackSegmentCam*> > EndBank;
02782 
02783   vector <vector<TrackSegmentCam*> > TempBegBank;
02784   vector <vector<TrackSegmentCam*> > TempEndBank;
02785 
02786 
02787   bool Cont; bool tmpFlag; bool TrackFlag;
02788   int ntrks; int Counter; int nplane; int npts;
02789   int ObjCounter; int ObjVectorCounter; const int fObjVectorMax=100000;
02790   int id; double Score; double TopScore;
02791 
02792   unsigned int MostClusters;
02793   bool AlreadyAdded;
02794 
02795 
02796   // Main loop is over the views, first for U, then V
02799   if(ViewSegBank[0].size()>0 && ViewSegBank[1].size()>0) {
02800     for(int View=0; View<2; ++View) {
02801     
02802       Cont=true; ntrks=0;
02803 
02804       while(Cont==true) {
02805         Cont=false;
02806         BegBank.clear(); EndBank.clear();
02807 
02808 
02809 
02810         // First selection of SEED SEGMENTS - segment from which we can move
02811         // along matched associations to find majority of the track.
02812         //
02813         // First guesses at seed segments are stored in SeedSegments Container
02815         BestSeedSegments.clear(); SeedSegments.clear();
02816 
02817         // Loop over the entries in ViewSegBank
02818         for(unsigned int i=0; i<ViewSegBank[View].size(); ++i) {
02819           TrackSegmentCam* Seg = ViewSegBank[View][i];
02820 
02821           if(Seg->GetUID()>0 && Seg->GetUID()<3) {
02822             Counter=0;
02823             
02824             // Loop over the constituent clusters and count the number that are track-like
02825             for(unsigned int j=0; j<Seg->GetEntries(); ++j) {
02826               ClusterCam* Clust = Seg->GetCluster(j);
02827               if(Clust->GetTrkPlnFlag()>0 && Clust->GetTrkFlag()==2) {Counter++;}
02828             }
02829             
02830             // If we've already made a track and this segment doesn't contain 3 track-like
02831             // clusters, don't consider it any further
02832             if(ntrks>0 && Counter<3) {Seg->SetUID(0);}
02833           }
02834 
02835           // Temporarily store all the likely seed segments. Those with UID 2 are most track-like.
02836           if(Seg->GetUID()==2) {BestSeedSegments.push_back(Seg);}
02837           if(Seg->GetUID()==1) {SeedSegments.push_back(Seg);}
02838         }
02839 
02840 
02841         // Hopefully we have segments with UID 2 (most track-like), else take those with UID 1
02842         // (just track-like) and move them from SeedSegments to BestSeedSegments. 
02843         // Can then empty SeedSegments.
02844         if(BestSeedSegments.size()==0) {BestSeedSegments=SeedSegments;}
02845         
02846         SeedSegments.clear();
02847 
02848         SeedSegments=BestSeedSegments;
02850 
02851 
02852 
02853 
02854         // Now, using our initial seed segments, try propagating back and forth
02855         // from each segment to refine our choice.
02856 
02857         // Final SEED SEGMENTS are stored BestSeedSegments Container
02859         BestSeedSegments.clear();
02860 
02861 
02862         // If we have some seed segments to work with, loop over them
02863         if(SeedSegments.size()>0) { 
02864           nplane=-1;
02865 
02866           for(unsigned int i=0; i<SeedSegments.size(); ++i) {
02867 
02868             // See how far we can propagate backwards to lower plane numbers
02870             mTemp.clear(); BegTemp.clear(); 
02871 
02872             // First put seed segment into BegTemp then begin while loop
02873             BegTemp.push_back(SeedSegments[i]); TempBank1.clear(); 
02874 
02875             while(BegTemp.size()>0) {
02876               Temp.clear();
02877               
02878               // Copy any segments into a temporary holder and loop over them,
02879               // gradually propagating back to lower plane numbers
02880               Temp=BegTemp; BegTemp.clear();
02881             
02882               for(unsigned int j=0; j<Temp.size(); ++j) {
02883                 tmpFlag=false;
02884                 
02885                 // For each segment, loop over their beginning matches
02886                 for(unsigned int k=0; k<Temp[j]->GetNMatchSegBeg(); ++k) {
02887                   TrackSegmentCam* Segb = Temp[j]->GetMatchSegBeg(k);
02888                   
02889                   // If matched segment is track-like and has zero TmpTrkFlag, 
02890                   // push it back into BegTemp, so the while loop continues.
02891                   if(Segb->GetUID()>-1 && Segb->GetUID()<3) {
02892                     tmpFlag=true;
02893                     
02894                     if(Segb->GetTmpTrkFlag()<1) {
02895                       BegTemp.push_back(Segb);
02896                       Segb->SetTmpTrkFlag(1); // Temporarily mark segments used
02897                       TempBank1.push_back(Segb);
02898                     }
02899                   }
02900                 }
02901                 
02902                 // Must have gone as far as we can go with this seed segment. Store segment at
02903                 // lowest plane.
02904                 if(tmpFlag==false) {mTemp.push_back(Temp[j]);}
02905               }
02906             } // End while BegTemp.size()>0
02907 
02908             // Set the flags back to zero, for when we carry out actual propagation, below.
02909             for(unsigned int j=0; j<TempBank1.size(); ++j) {TempBank1[j]->SetTmpTrkFlag(0);}
02911 
02912 
02913             
02914             // Now see how far we can propagate forwards to higher plane numbers
02916             pTemp.clear(); EndTemp.clear();
02917 
02918             // Put the seed segment into EndTemp then start while loop
02919             EndTemp.push_back(SeedSegments[i]); TempBank1.clear();
02920             
02921             while(EndTemp.size()>0) {
02922               Temp.clear();
02923               
02924               // Copy any segments into a temporary holder and loop over them,
02925               // gradually propagating to higher plane numbers
02926               Temp=EndTemp; EndTemp.clear();
02927              
02928               for(unsigned int j=0; j<Temp.size(); ++j) {
02929                 tmpFlag=false;
02930                 
02931                 // For each segment, loop over their end matches
02932                 for(unsigned int k=0; k<Temp[j]->GetNMatchSegEnd(); ++k) {
02933                   TrackSegmentCam* Sege = Temp[j]->GetMatchSegEnd(k);
02934 
02935                   // If the matched segment is track-like and has zero TmpTrkFlag, 
02936                   // push back into EndTemp, so the while loop continues.
02937                   if(Sege->GetUID()>-1 && Sege->GetUID()<3) {
02938                     tmpFlag=true;
02939                     
02940                     if(Sege->GetTmpTrkFlag()<1) {
02941                       EndTemp.push_back(Sege);
02942                       Sege->SetTmpTrkFlag(1); // Temporarily mark segments used
02943                       TempBank1.push_back(Sege);
02944                     }
02945                   }
02946                 }
02947                 
02948                 // Must have gone as far as we can go with this seed segment. Store segment at
02949                 // highest plane.
02950                 if(tmpFlag==false) {pTemp.push_back(Temp[j]);}
02951               }
02952             } // End while EndTemp.size()>0
02953             
02954             // Set the flags back to zero, for when we carry out actual propagation, below.
02955             for(unsigned int j=0; j<TempBank1.size(); ++j) {TempBank1[j]->SetTmpTrkFlag(0);}
02957             
02958             
02959             
02960             // Find the maximum number of planes we can span by propagating the seed segment
02961             // back and forth.
02963             npts=-1;
02964             for(unsigned int j=0; j<mTemp.size(); ++j) {
02965               for(unsigned int k=0; k<pTemp.size(); ++k) {
02966                 if((1+pTemp[k]->GetEndPlane()-mTemp[j]->GetBegPlane())>npts) {
02967                   npts=1+pTemp[k]->GetEndPlane()-mTemp[j]->GetBegPlane();
02968                 }
02969               }
02970             }
02971             
02972             SeedSegments[i]->SetNPlanes(npts);
02973             if(npts>nplane) {nplane=npts;}
02975           
02976           } // End loop over seed segments stored above
02977 
02978 
02979           // Store the seed segments that lead to the biggest propagation in BestSeedSegments
02981           if(nplane>0) {
02982             for(unsigned int i=0; i<SeedSegments.size(); ++i) {
02983               if(SeedSegments[i]->GetNPlanes()>nplane-5) {BestSeedSegments.push_back(SeedSegments[i]);}       
02984             }
02985           }
02987           
02988           
02989         } // End finding final seed segments
02991         
02992 
02993         // Order contents of BestSeedSegments
02995         SeedSegments=BestSeedSegments; BestSeedSegments.clear();
02996         
02997         for(unsigned int i=0; i<SeedSegments.size(); ++i) {
02998           MostClusters=0;
02999           TrackSegmentCam* LargestSeg = 0;        
03000           
03001           for(unsigned int j=0; j<SeedSegments.size(); ++j) {
03002             AlreadyAdded=false;
03003             
03004             for(unsigned int k=0; k<BestSeedSegments.size(); ++k) {
03005               if(BestSeedSegments[k]==SeedSegments[j]) {AlreadyAdded=true;}
03006             }
03007             if(AlreadyAdded) {continue;}
03008 
03009             if(SeedSegments[j]->GetEntries()>MostClusters) {
03010               MostClusters=SeedSegments[j]->GetEntries();
03011               LargestSeg=SeedSegments[j];
03012             }
03013           }
03014 
03015           if(LargestSeg) {BestSeedSegments.push_back(LargestSeg);}
03016         }
03018 
03019         
03020 
03021         // Now use the final seed segments to actually PROPAGATE back and forth, 
03022         // setting the TmpTrkFlags for the segments used in the propagation.
03024         TempBank2.clear();
03025 
03026         // Loop over the seed segments, which are stored in BestSeedSegments
03027         for(unsigned int i=0; i<BestSeedSegments.size(); ++i) {
03028           TrackSegmentCam* Seg0 = BestSeedSegments[i];
03029 
03030           MSG("AlgTrackCamList", Msg::kVerbose) << " Seed BegPlane" << Seg0->GetBegPlane() 
03031                                                 << " Endplane " << Seg0->GetEndPlane()
03032                                                 << " Begtpos " << Seg0->GetBegTPos() 
03033                                                 << " Endtpos " << Seg0->GetEndTPos()
03034                                                 << " UID " << Seg0->GetUID()
03035                                                 << " entries " << Seg0->GetEntries() << endl;
03036 
03037 
03038           // If we make a track, we will definitely include the seed segment, so set
03039           // it's TmpTrkFlag to 3.
03040           Seg0->SetTmpTrkFlag(3); 
03041           TrackFlag=false;
03042 
03043           TempBank1.clear(); TempBank1.push_back(Seg0); 
03044 
03045 
03046           // Track backwards (1)
03048           mTemp.clear(); BegTemp.clear();
03049 
03050           // Push the seed segment into BegTemp and begin while loop
03051           BegTemp.push_back(Seg0);
03052 
03053           while(BegTemp.size()>0) {
03054             Temp.clear();
03055 
03056             // Copy any segments into a temporary holder and loop over them,
03057             // gradually propagating back to lower plane numbers
03058             Temp=BegTemp; BegTemp.clear();
03059 
03060             for(unsigned int j=0; j<Temp.size(); ++j) {
03061               tmpFlag=false;
03062               TrackSegmentCam* Segtmp = Temp[j];
03063               
03064               // For each segment, loop over their beginning matches
03065               for(unsigned int k=0; k<Segtmp->GetNMatchSegBeg(); ++k){
03066                 TrackSegmentCam* Segb = Segtmp->GetMatchSegBeg(k);
03067                 
03068                 // If the matched segment is track-like and has zero TmpTrkFlag, 
03069                 // push back into BegTemp, so the while loop continues.
03070                 if(Segb->GetUID()>-1 && Segb->GetUID()<3) {
03071                   tmpFlag=true;
03072                   
03073                   if(Segb->GetTmpTrkFlag()<1) {
03074                     BegTemp.push_back(Segb);
03075                     Segb->SetTmpTrkFlag(1); // Mark the segments with TmpTrkFlag 1
03076                     TempBank1.push_back(Segb);
03077                   }
03078                 }
03079               }
03080 
03081               // Must have gone as far as we can go with this seed segment. Store segment at
03082               // lowest plane.
03083               if(tmpFlag==false) {mTemp.push_back(Segtmp);}
03084             }
03085           }
03086           
03087           // Note the first plane of the potential 2D track
03088           nplane=999;
03089           for(unsigned int j=0; j<mTemp.size(); ++j) {
03090             if(mTemp[j]->GetBegPlane()<nplane) {nplane=mTemp[j]->GetBegPlane();}
03091           }
03092 
03093 
03094           // For the longest possible paths, move back towards the seed segment,
03095           // setting TmpTrkFlags to 2 for the segments used.
03097 
03098           // Find the segments reached by the longest propagations
03099           BegTemp.clear();
03100           for(unsigned int j=0; j<mTemp.size(); ++j) {
03101             if(mTemp[j]->GetBegPlane()<nplane+5) {BegTemp.push_back(mTemp[j]);}
03102           }
03103 
03104 
03105           // From these segments, propagate forwards and set the flags.
03106           while(BegTemp.size()>0) {
03107             Temp.clear();
03108             
03109             for(unsigned int j=0; j<BegTemp.size(); ++j) {
03110               if(BegTemp[j]->GetTmpTrkFlag()<2) {
03111                 BegTemp[j]->SetTmpTrkFlag(2); // Mark the segments with TmpTrkFlag 2
03112                 Temp.push_back(BegTemp[j]);
03113               }
03114               
03115               if(BegTemp[j]->GetTrkFlag()<1) {
03116                 BegTemp[j]->SetTrkFlag(1);    // Also mark the segments with TrkFlag 1
03117                 TempBank2.push_back(BegTemp[j]);
03118                 TrackFlag=true;
03119               }
03120             }
03121             BegTemp.clear();
03122             
03123             
03124             for(unsigned int j=0; j<Temp.size(); ++j) {
03125               for(unsigned int k=0; k<Temp[j]->GetNMatchSegEnd(); ++k) {
03126                 if(Temp[j]->GetMatchSegEnd(k)->GetTmpTrkFlag()>0) {
03127                   BegTemp.push_back(Temp[j]->GetMatchSegEnd(k));
03128                 }
03129               }
03130             }
03131           }
03133           
03134 
03135 
03136           // Track forwards (1)
03138           pTemp.clear(); EndTemp.clear();
03139           
03140           
03141           // Push seed segment into EndTemp and begin while loop
03143           EndTemp.push_back(Seg0);
03144 
03145           while(EndTemp.size()>0) {
03146             Temp.clear();
03147          
03148             // Copy any segments into a temporary holder and loop over them,
03149             // gradually propagating to higher plane numbers
03150             Temp=EndTemp; EndTemp.clear();
03151 
03152             for(unsigned int j=0; j<Temp.size(); ++j) {
03153               tmpFlag=false;
03154               TrackSegmentCam* Segtmp = Temp[j];
03155               
03156               // For each segment, loop over their end matches
03157               for(unsigned int k=0; k<Segtmp->GetNMatchSegEnd(); ++k){
03158                 TrackSegmentCam* Sege = Segtmp->GetMatchSegEnd(k);
03159                 
03160                 // If the matched segment is track-like and has zero TmpTrkFlag, 
03161                 // push back into BegTemp, so the while loop continues.
03162                 if(Sege->GetUID()>-1 && Sege->GetUID()<3) {
03163                   tmpFlag=true;
03164                   
03165                   if(Sege->GetTmpTrkFlag()<1) {
03166                     EndTemp.push_back(Sege);
03167                     Sege->SetTmpTrkFlag(1); // Mark the segments with TmpTrkFlag 1
03168                     TempBank1.push_back(Sege);
03169                   }
03170                 }
03171               }
03172 
03173               // Must have gone as far as we can go with this seed segment. Store segment at
03174               // highest plane.
03175               if(tmpFlag==false) {pTemp.push_back(Segtmp);}
03176             }
03177           }
03178 
03179           // Note the end plane of potential 2D track     
03180           nplane=-999;
03181           for(unsigned int j=0; j<pTemp.size(); ++j) {
03182             if(pTemp[j]->GetEndPlane()>nplane) {nplane=pTemp[j]->GetEndPlane();}
03183           }
03184 
03185 
03186           // For the longest possible paths, move back towards the seed segment,
03187           // setting TmpTrkFlags to 2 for the segments used.
03189 
03190           // Find the segments reached by the longest propagations
03191           EndTemp.clear();
03192           for(unsigned int j=0; j<pTemp.size(); ++j) {
03193             if(pTemp[j]->GetEndPlane()>nplane-5) {EndTemp.push_back(pTemp[j]);}
03194           }
03195 
03196           
03197           // From these segments, propagate back and set the flags.
03198           while(EndTemp.size()>0) {
03199             Temp.clear();
03200             
03201             for(unsigned int j=0; j<EndTemp.size(); ++j) {
03202               if(EndTemp[j]->GetTmpTrkFlag()<2) {
03203                 EndTemp[j]->SetTmpTrkFlag(2); // Mark the segments with TmpTrkFlag 2
03204                 Temp.push_back(EndTemp[j]);
03205               }
03206               
03207               if(EndTemp[j]->GetTrkFlag()<1) {
03208                 EndTemp[j]->SetTrkFlag(1);    // Also mark the segments with TrkFlag 1
03209                 TempBank2.push_back(EndTemp[j]);
03210                 TrackFlag=true;
03211               }
03212             }
03213             EndTemp.clear();
03214             
03215             for(unsigned int j=0; j<Temp.size(); ++j) {
03216               for(unsigned int k=0; k<Temp[j]->GetNMatchSegBeg(); ++k) {
03217                 if(Temp[j]->GetMatchSegBeg(k)->GetTmpTrkFlag()>0) {
03218                   EndTemp.push_back(Temp[j]->GetMatchSegBeg(k));
03219                 }
03220               }
03221             }
03222           }
03223 
03224           // End setting TmpTrkFlags
03226 
03227 
03228 
03229 
03230           // From paths of segments with TmpTrkFlag==2, find the best set of
03231           // segments at the beginning and the best set of segments at the end
03233 
03234           // If propagation from the seed segment has given us a good potential 2D track
03235           MSG("AlgTrackCamList", Msg::kVerbose) << "TrackFlag " << TrackFlag << endl;
03236 
03237           if(TrackFlag==true) { 
03238 
03239             // Track backwards (2) and find best set of beginning segments
03241             TempBegBank.clear(); ObjVectorCounter=0;
03242             vector<TrackSegmentCam*> TmpBegSegBank;
03243 
03244             TmpBegSegBank.push_back(Seg0);
03245             TempBegBank.push_back(TmpBegSegBank);
03246             ObjCounter=1;
03247             
03248 
03249             // Store the series of beginning segments that were flagged above during the propagation.
03250             // Each entry in TempBegbank will be a vectors of segments (a series of beginning segments 
03251             // flagged above).
03252 
03253             // TempBegBank will contain vectors of segments representing every possible path back through
03254             // the segments marked with TmpTrkFlag 2 (possible beginning sections for the 2D track)
03256             while(ObjCounter>0 && ObjVectorCounter<fObjVectorMax) {
03257               ObjCounter=0;
03258               npts=TempBegBank.size();
03259 
03260               for(int j=0; j<npts; ++j) {
03261                 TrackSegmentCam* Segtmp = TempBegBank[j].back();
03262                 mTemp.clear();
03263                 
03264                 for(unsigned int k=0; k<Segtmp->GetNMatchSegBeg(); ++k) {
03265                   TrackSegmentCam* Segbeg = Segtmp->GetMatchSegBeg(k);
03266                   if(Segbeg->GetTmpTrkFlag()>1) {mTemp.push_back(Segbeg);};
03267                 }
03268 
03269                 if(mTemp.size()>0) {
03270                   for(unsigned int k=1; k<mTemp.size(); ++k) {
03271                     if(ObjVectorCounter<fObjVectorMax) { 
03272                       vector<TrackSegmentCam*> NewObj = TempBegBank[j];
03273                       
03274                       NewObj.push_back(mTemp[k]);
03275                       TempBegBank.push_back(NewObj);
03276 
03277                       ObjVectorCounter++;
03278                     }
03279                     else {MSG("AlgTrackCamList", Msg::kWarning) << " *** CRAZY MEMORY GUZZLING *** " << endl; break;}
03280                   }
03281 
03282                   if(ObjVectorCounter>=fObjVectorMax) {break;}
03283 
03284                   TempBegBank[j].push_back(mTemp[0]); ObjCounter++;
03285                 }
03286               }
03287             } // End while ObjCounter>0
03289 
03290             // Find beginning section with best score and store it
03291             MSG("AlgTrackCamList", Msg::kVerbose) << "beginning score " << endl;
03292 
03293             id=-1; TopScore=-1.;
03294             for(unsigned int j=0; j<TempBegBank.size(); ++j) {
03295               Score = Seg0->GetScore(&TempBegBank[j],0);
03296               if(Score>TopScore) {TopScore=Score; id=j;}
03297             }
03298 
03299             if(id!=-1) {BegBank.push_back(TempBegBank[id]);}
03300             TempBegBank.clear();
03302 
03303 
03304 
03305 
03306             // Track forwards (2) and find best set of end segments
03308             TempEndBank.clear(); ObjVectorCounter=0;
03309             vector<TrackSegmentCam*> TmpEndSegBank;
03310 
03311             TmpEndSegBank.push_back(Seg0);
03312             TempEndBank.push_back(TmpEndSegBank);
03313             ObjCounter=1;
03314             
03315 
03316             // Store the series of end segments that were flagged above during the propagation.
03317             // Each entry in TempEndbank will be a vectors of segments (a series of end segments 
03318             // flagged above).
03319 
03320             // TempBegBank will contain vectors of segments representing every possible path forward through
03321             // the segments marked with TmpTrkFlag 2 (possible end sections for the 2D track)
03323             while(ObjCounter>0 && ObjVectorCounter<fObjVectorMax) {
03324               ObjCounter=0;
03325               npts=TempEndBank.size();
03326               
03327               for(int j=0; j<npts; ++j) {
03328                 TrackSegmentCam* Segtmp = TempEndBank[j].back();
03329 
03330                 pTemp.clear();
03331                 
03332                 for(unsigned int k=0; k<Segtmp->GetNMatchSegEnd(); ++k) {
03333                   TrackSegmentCam* Segend = Segtmp->GetMatchSegEnd(k);
03334                   if(Segend->GetTmpTrkFlag()>1) {pTemp.push_back(Segend);};
03335                 }
03336 
03337                 if(pTemp.size()>0) {
03338                   for(unsigned int k=1; k<pTemp.size(); ++k) {
03339                     if(ObjVectorCounter<fObjVectorMax) {
03340                       vector<TrackSegmentCam*> NewObj = TempEndBank[j];
03341                       
03342                       NewObj.push_back(pTemp[k]);
03343                       TempEndBank.push_back(NewObj);
03344 
03345                       ObjVectorCounter++;
03346                     }
03347                     else {MSG("AlgTrackCamList", Msg::kWarning) << " *** CRAZY MEMORY GUZZLING *** " << endl; break;}
03348                   }
03349 
03350                   if(ObjVectorCounter>=fObjVectorMax) {break;}
03351 
03352                   TempEndBank[j].push_back(pTemp[0]); ObjCounter++;
03353                 }
03354               }
03355             } // End while ObjCounter>0
03357 
03358             // Find end section with best score and store it
03359             MSG("AlgTrackCamList", Msg::kVerbose) << "end score " << endl;
03360 
03361             id=-1; TopScore=-1.;
03362             for(unsigned int j=0; j<TempEndBank.size(); ++j) {
03363               Score = Seg0->GetScore(0,&TempEndBank[j]);
03364               if(Score>TopScore) {TopScore=Score; id=j;}
03365             }
03366 
03367             if(id!=-1) {EndBank.push_back(TempEndBank[id]);}
03368             TempEndBank.clear(); // maybe clear individual vectors of segments
03370           }
03372 
03373           
03374           // Clear up
03375           for(unsigned int j=0; j<TempBank1.size(); ++j) {TempBank1[j]->SetTmpTrkFlag(0);}
03376 
03377         } // End loop over BestSeedSegments
03379         for(unsigned int j=0; j<TempBank2.size(); ++j) {TempBank2[j]->SetTrkFlag(0);}
03380 
03381 
03382 
03383 
03384 
03385         // Using the best beginning sections and the best end sections from all 
03386         // seed segments, find the BEST COMPLETE 2D track
03388         if(BegBank.size()>0 && EndBank.size()>0) {
03389 
03390           // Calculate a score, including the seed segment and best beginning/end paths,
03391           // to find the 'best' complete track
03392           MSG("AlgTrackCamList", Msg::kVerbose) << "overall score " << endl;
03393 
03394           id=-1; TopScore=-1.;
03395           for(unsigned int i=0; i<BegBank.size(); ++i) {
03396             Score = BegBank[i][0]->GetScore(&BegBank[i],&EndBank[i]);
03397             if(Score>TopScore) {TopScore=Score; id=i;}
03398           }
03399 
03400           // If we have found a best track, add together the segments to form
03401           // a segment that is the 2D track, giving this UID 3. Mark segments  
03402           // used by setting their UID to -1.
03403           if(1+id>0) {
03404             // Get the seed segment
03405             TrackSegmentCam* Seg0 = BegBank[id][0];
03406 
03407             // Set segment UIDs to -1 if they are part of the track, so they
03408             // can't be used in another track.
03409             for(unsigned int i=1; i<BegBank[id].size(); ++i) {
03410               TrackSegmentCam* Segbeg = BegBank[id][i];
03411               Seg0->AddSegment(Segbeg);
03412               Segbeg->SetUID(-1);
03413             }
03414 
03415             for(unsigned int i=1; i<EndBank[id].size(); ++i) {
03416               TrackSegmentCam* Segend = EndBank[id][i];
03417               Seg0->AddSegment(Segend);
03418               Segend->SetUID(-1);
03419             }
03420             
03421             // Mark long segment as a 2D track by setting its UID to 3
03422             Seg0->SetUID(3);
03423 
03424             // Mark all the clusters in 2D track with TrkFlag 3
03425             for(unsigned int i=0; i<Seg0->GetEntries(); ++i) {
03426               Seg0->GetCluster(i)->SetTrkFlag(3);
03427             }
03428 
03429             // Store for use in Join2D tracks method
03430             PossibleJoins[View].push_back(Seg0);
03431 
03432             // Can now look for more 2D tracks
03433             Cont=true; ntrks++;
03434           }
03435         }
03437 
03438         // Clean up
03439         BegBank.clear(); EndBank.clear();
03440 
03441         
03442       } // End while Cont==true loop
03443     } // End loop over planeviews
03444   } // End check to see if there is anything in ViewSegBank
03447   
03448 
03449   
03450   // Print out the list of 2D tracks
03452   MSG("AlgTrackCamList", Msg::kVerbose) << " *** LIST OF 2D TRACKS *** " << endl;
03453   for(int View=0; View<2; ++View) {
03454 
03455     MSG("AlgTrackCamList", Msg::kVerbose) << "View: " << View << endl;
03456     for(unsigned i=0; i<ViewSegBank[View].size(); ++i) {
03457       TrackSegmentCam* Seg = ViewSegBank[View][i];
03458       if(Seg->GetUID()>2) {
03459         MSG("AlgTrackCamList", Msg::kVerbose) << "  i=" << i
03460                                               << "  begpln: "  << Seg->GetBegPlane()
03461                                               << "  begtpos: " << Seg->GetBegTPos()
03462                                               << "  endpln: "  << Seg->GetEndPlane()
03463                                               << "  endtpos: " << Seg->GetEndTPos() << endl;
03464       }
03465     }
03466   }
03468 
03469   return;
03470 }
03472 
03473 
03474 
03475 
03477 void AlgTrackCamList::Join2DTracks()
03478 {
03479   MSG("AlgTrackCamList", Msg::kVerbose) << " *** JOIN 2D TRACKS *** " << endl;
03480 
03481   double ShortestDist; double LongestAllowedDist=5.;
03482   double DeltaTPos, DeltaZPos, Dist;
03483   int DeltaPlane, Length, UID, NumAgree;
03484 
03485   TrackSegmentCam* Seg1ToAdd=0;
03486   TrackSegmentCam* Seg2ToAdd=0;
03487   bool PossibleAssocs, Cont, Overlap, DiffGrad;
03488 
03489   if(ModuleType==2) {LongestAllowedDist=2.;}
03490 
03491 
03492   // Deal with two nearby tracks in ND  
03494   if(ModuleType==2 && PossibleJoins[0].size()==2 && PossibleJoins[1].size()==2) {
03495     Overlap=false;
03496 
03497     // Check first to see if the 2D tracks overlap and share clusters
03499     for(int View=0; View<2; ++View) {
03500       NumAgree=0; 
03501 
03502       for(unsigned int i=0; i<PossibleJoins[View][0]->GetEntries(); ++i) {
03503         ClusterCam* Clust = PossibleJoins[View][0]->GetCluster(i);
03504         
03505         for(unsigned int j=0; j<PossibleJoins[View][1]->GetEntries(); ++j) {
03506           if(PossibleJoins[View][1]->GetCluster(j)==Clust) {Overlap=true; break;}
03507         }
03508         if(Overlap) {break;}
03509 
03510       }
03511       if(Overlap) {break;}
03512     }
03514 
03515     
03516 
03517     // Check for very different gradients
03519     DiffGrad=false;
03520 
03521     for(int View=0; View<2; ++View) {
03522       if(PossibleJoins[View][0]->GetBegPlane()<PossibleJoins[View][1]->GetBegPlane()) {
03523         if(fabs(PossibleJoins[View][0]->GetEndDir()
03524                 -PossibleJoins[View][1]->GetBegDir())>0.7) {DiffGrad=true;}
03525       }
03526       else {
03527         if(fabs(PossibleJoins[View][1]->GetEndDir()
03528                 -PossibleJoins[View][0]->GetBegDir())>0.7) {DiffGrad=true;}  
03529       }
03530       if(DiffGrad) {break;}
03531     }
03532 
03533     if(DiffGrad) {
03534       PossibleJoins[0].clear(); 
03535       PossibleJoins[1].clear();
03536       return;
03537     }
03539 
03540     
03541 
03543     if(Overlap==false) {
03544       // Check associations apply in both views
03545       if( (PossibleJoins[0][0]->IsAssoc(PossibleJoins[0][1])
03546            || PossibleJoins[0][1]->IsAssoc(PossibleJoins[0][0]))
03547           && (PossibleJoins[1][0]->IsAssoc(PossibleJoins[1][1])
03548               || PossibleJoins[1][1]->IsAssoc(PossibleJoins[1][0])) ) {
03549       
03550         PossibleJoins[0][0]->AddSegment(PossibleJoins[0][1]); 
03551         PossibleJoins[0][1]->SetUID(-1);
03552 
03553         PossibleJoins[1][0]->AddSegment(PossibleJoins[1][1]); 
03554         PossibleJoins[1][1]->SetUID(-1);        
03555       }
03556 
03557       // Clear up and leave Join2DTracks method
03558       PossibleJoins[0].clear(); PossibleJoins[1].clear();
03559     
03560       return;
03561     }
03563   }
03565 
03566 
03567 
03569   else if(ModuleType==2 && PossibleJoins[0].size()>2 && PossibleJoins[1].size()>2 
03570           && PossibleJoins[0].size()==PossibleJoins[1].size()) {
03571     
03572     const unsigned int Size = PossibleJoins[0].size();
03573 
03574     bool UView[100], VView[100]; bool AllMatch=true;
03575     int BegPlane, EndPlane;
03576 
03577     if(Size<100) {
03578       for(unsigned int i=0; i<Size; ++i) {UView[i]=false; VView[i]=false;}
03579 
03580       for(unsigned int i=0; i<Size; ++i) {
03581         BegPlane=PossibleJoins[0][i]->GetBegPlane();
03582         EndPlane=PossibleJoins[0][i]->GetEndPlane();
03583         
03584         for(unsigned int j=0; j<Size; ++j) {
03585           
03586           if(VView[j]) {continue;}
03587 
03588           if(abs(BegPlane-PossibleJoins[1][j]->GetBegPlane())<8 
03589              && abs(EndPlane-PossibleJoins[1][j]->GetEndPlane())<8) {
03590             
03591             UView[i]=true; VView[j]=true; break;
03592           }
03593         }
03594       }
03595       
03596       for(unsigned int i=0; i<Size; ++i) {if(UView[i]==false || VView[i]==false) {AllMatch=false;}}
03597       
03598       if(AllMatch) {
03599         PossibleJoins[0].clear(); 
03600         PossibleJoins[1].clear(); 
03601         return;
03602       }
03603     }
03604   }
03606 
03607 
03608 
03609   // First, make the best possible joins between the tracks
03611   for(int View=0; View<2; ++View) {
03612     PossibleAssocs=true;
03613 
03614     while(PossibleAssocs) {
03615       PossibleAssocs=false; 
03616       ShortestDist=LongestAllowedDist; Seg1ToAdd=0; Seg2ToAdd=0; 
03617 
03618       // Consider all pairs of 2D tracks and find the single best association.
03619       for(unsigned int i=0; i<PossibleJoins[View].size(); ++i) {
03620         TrackSegmentCam* Seg1 = PossibleJoins[View][i];
03621 
03622         if(Seg1->GetUID()>2) {
03623 
03624           for(unsigned int j=0; j<PossibleJoins[View].size(); ++j) {
03625             TrackSegmentCam* Seg2 = PossibleJoins[View][j];
03626           
03627             if(Seg2->GetUID()>2 && Seg1!=Seg2) {         
03628 
03629               // Calculate distance between segments
03630               DeltaTPos=fabs(Seg2->GetBegTPos()-Seg1->GetEndTPos());
03631               DeltaZPos=fabs(Seg2->GetBegZPos()-Seg1->GetEndZPos());
03632               DeltaPlane=Seg2->GetBegPlane()-Seg1->GetEndPlane();
03633 
03634               Dist=pow(DeltaTPos*DeltaTPos + DeltaZPos*DeltaZPos,0.5);
03635 
03636               if(DeltaPlane>=0 && Dist<ShortestDist)  {
03637                 if(Seg1->IsAssoc(Seg2)) {Seg1ToAdd=Seg1; Seg2ToAdd=Seg2; ShortestDist=Dist;}
03638               }
03639               else if(DeltaPlane<=0 && Dist<ShortestDist) {
03640                 if(Seg2->IsAssoc(Seg1)) {Seg1ToAdd=Seg1; Seg2ToAdd=Seg2; ShortestDist=Dist;}
03641               }
03642             }
03643           }
03644         }
03645       }
03646 
03647 
03648       // If a good association is found, add the segments and look for the next association.
03649       if(ShortestDist<LongestAllowedDist && Seg2ToAdd!=0 && Seg1ToAdd!=0) { 
03650         MSG("AlgTrackCamList", Msg::kVerbose) << "Missing 2D track assocation: Seg1 " 
03651                                               << Seg1ToAdd->GetBegPlane() << " " << Seg1ToAdd->GetEndPlane() 
03652                                               << " (" << Seg1ToAdd->GetBegTPos() << "," << Seg1ToAdd->GetEndTPos() 
03653                                               << "), Seg2 " << Seg2ToAdd->GetBegPlane() 
03654                                               << " " << Seg2ToAdd->GetEndPlane() << " (" << Seg2ToAdd->GetBegTPos() 
03655                                               << "," << Seg2ToAdd->GetEndTPos() << endl;
03656 
03657         Seg1ToAdd->AddSegment(Seg2ToAdd); Seg2ToAdd->SetUID(-1); PossibleAssocs=true;
03658       }
03659     }
03661 
03662 
03663 
03664     // Now find the longest possible 2D track and remove 2d tracks that overlap.
03666     Cont=true; 
03667 
03668     while(Cont) {
03669       Cont=false;
03670 
03671       TrackSegmentCam* BestTrk = 0;
03672       Length=0;
03673 
03674       for(unsigned int i=0; i<PossibleJoins[View].size(); ++i) {
03675         TrackSegmentCam* Seg = PossibleJoins[View][i];
03676         if(Seg->GetUID()>0 && Seg->GetUID()<4 && (Seg->GetEndPlane()-Seg->GetBegPlane())>Length) {
03677           BestTrk=Seg; Length=Seg->GetEndPlane()-Seg->GetBegPlane();
03678         }
03679       }
03680 
03681 
03682       if(BestTrk) {
03683         BestTrk->SetUID(4);
03684 
03685         for(unsigned int i=0; i<BestTrk->GetEntries(); ++i) {
03686           ClusterCam* BestTrkClust = BestTrk->GetCluster(i);
03687         
03688           if(BestTrkClust->GetPlane()==BestTrk->GetBegPlane() || BestTrkClust->GetPlane()==BestTrk->GetEndPlane()) {continue;}
03689 
03690           for(unsigned int j=0; j<PossibleJoins[View].size(); ++j) {
03691             TrackSegmentCam* Seg = PossibleJoins[View][j];
03692             NumAgree=0; 
03693 
03694             if(Seg->GetUID()<0 || Seg->GetUID()>3) {continue;}
03695   
03696             for(unsigned int k=0; k<Seg->GetEntries(); ++k) {
03697               ClusterCam* SegClust = Seg->GetCluster(k);
03698 
03699               if(SegClust==BestTrkClust) {NumAgree++;}
03700 
03701               if(NumAgree>2) {Seg->SetUID(-1); break;}
03702             }
03703           }
03704         }
03705       }
03706 
03707       // Conditions for continuing here
03708       for(unsigned int i=0; i<PossibleJoins[View].size(); ++i) {
03709         UID=PossibleJoins[View][i]->GetUID();
03710 
03711         if(UID>0 && UID<4) {Cont=true;}
03712       }
03713       
03714     }
03716 
03717    
03718     // Reset UIDs
03719     for(unsigned int i=0; i<PossibleJoins[View].size(); ++i) {
03720       if(PossibleJoins[View][i]->GetUID()==4) {PossibleJoins[View][i]->SetUID(3);}
03721     }
03722 
03723     PossibleJoins[View].clear();
03724   }
03726 
03727 
03728 
03729   // Print out the list of 2D tracks
03731   for(int View=0; View<2; ++View) {
03732     MSG("AlgTrackCamList", Msg::kVerbose) << "View: " << View << endl;
03733     for(unsigned i=0; i<ViewSegBank[View].size(); ++i) {
03734       TrackSegmentCam* Seg = ViewSegBank[View][i];
03735       if(Seg->GetUID()>2) {
03736         MSG("AlgTrackCamList", Msg::kVerbose)  << "  i=" << i
03737                                                << "  begpln: "  << Seg->GetBegPlane()
03738                                                << "  begtpos: " << Seg->GetBegTPos()
03739                                                << "  endpln: "  << Seg->GetEndPlane()
03740                                                << "  endtpos: " << Seg->GetEndTPos() << endl;
03741       }
03742     }
03743   }
03745 
03746   return;
03747 }
03749 
03750 
03751 
03752 
03754 void AlgTrackCamList::SecondUVComparison()
03755 {
03756   // Look at the 2D tracks formed and try to match 2D tracks in the U view
03757   // with those in the V view, based on a rough overlap in plane numbers and time.
03758   // Store those that match.
03759 
03760   // 2D tracks are only ever formed within a single SuperModule. At this point
03761   // we try to match FD 2D tracks across the SM gap. Using the 2D tracks we have
03762   // just stored, we check association across the gap. Any final ambiguity is
03763   // resolved by getting a score for each possible match. 
03764 
03765   // If things look good, U/V partners are set and 2D tracks are joined across the gap.
03766 
03767   // Any other possible 2D track matches between views are then considered and the
03768   // best matches chosen by obtaining a score characterising the degree of overlap.
03769 
03770 
03771 
03772   vector<TrackSegmentCam*> TempTrackSeg[2];
03773   int Module; bool Cont;
03774 
03775   int id, idm, idp; 
03776   double TopScore, Score, NClusters, TopClusters;
03777   int begplane1(0), begplane2(0), endplane1(0), endplane2(0), dplane1, dplane2;
03778   int NumUTrks(0), NumVTrks(0);
03779   
03780   // Store the 2D track segments which roughly overlap in terms of planes
03781   // and time.
03783  
03784   // Loop over all u segments
03785   for(unsigned int i=0; i<ViewSegBank[0].size(); ++i) {
03786     TrackSegmentCam* Segu = ViewSegBank[0][i];
03787  
03788     // If segment is a 2D track   
03789     if(Segu->GetUID()>2) {
03790 
03791       // For each of these, loop over 2D tracks in V view
03792       for(unsigned int j=0; j<ViewSegBank[1].size(); ++j) {
03793         TrackSegmentCam* Segv = ViewSegBank[1][j];
03794         
03795         if(Segv->GetUID()>2) {
03796         
03797           // Check overlap between u and v segments
03798           if( (abs(Segv->GetBegPlane()-Segu->GetBegPlane())<10 || abs(Segv->GetEndPlane()-Segu->GetEndPlane())<10 )
03799               && ( (Segv->GetEndPlane()-Segu->GetBegPlane())>2 && (Segu->GetEndPlane()-Segv->GetBegPlane())>2 )
03800               && ( (Segv->GetEndTime()-Segu->GetBegTime())>-100 && (Segu->GetEndTime()-Segv->GetBegTime())>-100 ) ) {
03801             
03802             TempTrackSeg[0].push_back(Segu);
03803             TempTrackSeg[1].push_back(Segv);
03804           }
03805         }
03806       }
03807     }
03808   }
03809 
03810   // Track combinations we may have missed above:
03812   // Simple combination
03813   TrackSegmentCam* USeg=0; TrackSegmentCam* VSeg=0;
03814 
03815   for(unsigned int i=0; i<ViewSegBank[0].size(); ++i) {if(ViewSegBank[0][i]->GetUID()>2) {NumUTrks++; USeg=ViewSegBank[0][i];}}
03816   for(unsigned int i=0; i<ViewSegBank[1].size(); ++i) {if(ViewSegBank[1][i]->GetUID()>2) {NumVTrks++; VSeg=ViewSegBank[1][i];}}
03817 
03818   if(TempTrackSeg[0].size()==0 && TempTrackSeg[1].size()==0 
03819      && NumUTrks==1 && NumVTrks==1 && USeg && VSeg) {
03820     TempTrackSeg[0].push_back(USeg); 
03821     TempTrackSeg[1].push_back(VSeg);
03822   }
03824 
03825 
03827   // Essentially same as above, but if we have also found a junky second track in one view
03828   if((ModuleType==1 || ModuleType==3) && TempTrackSeg[0].size()==0 && TempTrackSeg[1].size()==0) {
03829     // First combination
03830     if(NumUTrks==1 && NumVTrks==2) {
03831       TrackSegmentCam* VSeg2=0;
03832 
03833       for(unsigned int i=0; i<ViewSegBank[1].size(); ++i) {
03834         if(ViewSegBank[1][i]->GetUID()>2) {VSeg2=ViewSegBank[1][i]; break;}
03835       }
03836       
03837       if(USeg && VSeg && VSeg2) {
03838         if(abs(int(USeg->GetEntries())-int(VSeg->GetEntries()))<30 && abs(int(USeg->GetEntries())-int(VSeg2->GetEntries()))>30) {
03839           TempTrackSeg[0].push_back(USeg); 
03840           TempTrackSeg[1].push_back(VSeg);
03841         }
03842         else if(abs(int(USeg->GetEntries())-int(VSeg->GetEntries()))>30 && abs(int(USeg->GetEntries())-int(VSeg2->GetEntries()))<30) {
03843           TempTrackSeg[0].push_back(USeg); 
03844           TempTrackSeg[1].push_back(VSeg2);       
03845         }
03846       }      
03847     }
03848     // Equivalent combination
03849     else if(NumUTrks==2 && NumVTrks==1) {
03850       TrackSegmentCam* USeg2=0;
03851 
03852       for(unsigned int i=0; i<ViewSegBank[0].size(); ++i) {
03853         if(ViewSegBank[0][i]->GetUID()>2) {USeg2=ViewSegBank[0][i]; break;}
03854       }
03855       
03856       if(VSeg && USeg && USeg2) {
03857         if(abs(int(VSeg->GetEntries())-int(USeg->GetEntries()))<30 && abs(int(VSeg->GetEntries())-int(USeg2->GetEntries()))>30) {
03858           TempTrackSeg[0].push_back(USeg); 
03859           TempTrackSeg[1].push_back(VSeg);
03860         }
03861         else if(abs(int(VSeg->GetEntries())-int(USeg->GetEntries()))>30 && abs(int(VSeg->GetEntries())-int(USeg2->GetEntries()))<30) {
03862           TempTrackSeg[0].push_back(USeg2); 
03863           TempTrackSeg[1].push_back(VSeg);        
03864         }
03865       }      
03866     }
03867   }
03869 
03870 
03872 
03873 
03874 
03875 
03876   // Print out this initial overlap information
03878   MSG("AlgTrackCamList", Msg::kVerbose) << " ** Guesses at tracks (only showing for UID>2)"<<endl;
03879   MSG("AlgTrackCamList", Msg::kVerbose) << "================================" << endl;
03880   for(unsigned int i=0; i<TempTrackSeg[0].size(); ++i) {
03881     TrackSegmentCam* Seg = TempTrackSeg[0][i];
03882     TrackSegmentCam* SegPartner = TempTrackSeg[1][i];
03883     if(Seg->GetUID()>2 && SegPartner->GetUID()>2)
03884       {
03885         MSG("AlgTrackCamList", Msg::kVerbose) << "  Seg    " 
03886                                               << "  begpln: "  << Seg->GetBegPlane()
03887                                               << "  begtpos: " << Seg->GetBegTPos()
03888                                               << "  endpln: "  << Seg->GetEndPlane()
03889                                               << "  endtpos: " << Seg->GetEndTPos() << endl;
03890         MSG("AlgTrackCamList", Msg::kVerbose) << "  Partner" 
03891                                               << "  begpln: "  << SegPartner->GetBegPlane()
03892                                               << "  begtpos: " << SegPartner->GetBegTPos()
03893                                               << "  endpln: "  << SegPartner->GetEndPlane()
03894                                               << "  endtpos: " << SegPartner->GetEndTPos() << endl;
03895         MSG("AlgTrackCamList", Msg::kVerbose) << "================================" << endl;
03896       }
03897   }
03899 
03900 
03901 
03902 
03903   // Special FD specific section to consider matching 2D tracks across the SM gap
03905   if(NumModules>1) {
03906 
03907     // Initialise container: Create one vector of empty segment vectors for each SM
03908     vector< vector<TrackSegmentCam*> > TempMod[2]; 
03909     for(unsigned int i=0; i<2; ++i) {
03910       for(unsigned int j=0; j<2; ++j) {vector<TrackSegmentCam*> TempVector; TempMod[i].push_back(TempVector);}
03911     }
03912 
03913     // Loop over the roughly overlapping 2D tracks we stored above
03915     for(unsigned int i=0; i<TempTrackSeg[0].size(); ++i) {
03916       TrackSegmentCam* Segu = TempTrackSeg[0][i];
03917       TrackSegmentCam* Segv = TempTrackSeg[1][i];
03918       
03919       // Check which module the U 2D track ends in
03920       Module = int((Segu->GetEndPlane())/(PlanesInModule+1));
03921       
03922       // Store U and V 2D tracks if they are suitably near the SM gap
03923       if( Segu->GetBegPlane()<Module*(PlanesInModule+1)+20
03924           && Segv->GetBegPlane()<Module*(PlanesInModule+1)+20 && Module>0) {
03925    
03926         TempMod[1][0].push_back(Segu);
03927         TempMod[1][1].push_back(Segv);
03928       }
03929 
03930       if( Segu->GetEndPlane()>(Module+1)*(PlanesInModule+1)-20
03931           && Segv->GetEndPlane()>(Module+1)*(PlanesInModule+1)-20 && Module<1) {
03932         
03933         TempMod[0][0].push_back(Segu);
03934         TempMod[0][1].push_back(Segv);
03935       }
03936     }
03938 
03939 
03940 
03941     // If there are U and V 2D tracks on either side of the SM gap, look for associations.
03942     // Also calculate a score based on the degree of overlap we would have if a join was made.
03944     if(TempMod[0][0].size()>0 && TempMod[1][0].size()>0) {
03945       Cont=true;
03946 
03947       while(Cont==true) {
03948         Cont=false;
03949         idm=-1; idp=-1; TopScore=0.; NClusters=0; TopClusters=0;
03950 
03951         // Loop over the 2D tracks in SM 1
03952         for(unsigned int i=0; i<TempMod[0][0].size(); ++i) {  
03953           TrackSegmentCam* Segum = TempMod[0][0][i];
03954           TrackSegmentCam* Segvm = TempMod[0][1][i];
03955         
03956           // For these, loop over the 2D tracks in SM 2
03957           if( (Segum->GetPartner()==Segvm && Segvm->GetPartner()==Segum)
03958               || (Segum->GetPartner()==0 && Segvm->GetPartner()==0
03959                   && Segum->GetUID()>2 && Segvm->GetUID()>2) ) {
03960             
03961             for(unsigned int j=0; j<TempMod[1][0].size(); ++j) {
03962               TrackSegmentCam* Segup = TempMod[1][0][j];
03963               TrackSegmentCam* Segvp = TempMod[1][1][j];
03964 
03965               // Check the association of the 2D tracks across the gap
03967               if(Segup->GetUID()>2 && Segvp->GetUID()>2) {
03968                 if(Segum->IsAssoc(Segup) && Segvm->IsAssoc(Segvp)) {
03969                   
03970                   if(Segum->GetBegPlane()<=Segvm->GetBegPlane()) {
03971                     begplane2=Segum->GetBegPlane();
03972                     begplane1=Segvm->GetBegPlane();
03973                   }
03974 
03975                   if(Segvm->GetBegPlane()<=Segum->GetBegPlane()) {
03976                     begplane2=Segvm->GetBegPlane();
03977                     begplane1=Segum->GetBegPlane();
03978                   }
03979 
03980                   if(Segup->GetEndPlane()>=Segvp->GetEndPlane()) {
03981                     endplane2=Segup->GetEndPlane();
03982                     endplane1=Segvp->GetEndPlane();
03983                   }
03984 
03985                   if(Segvp->GetEndPlane()>=Segup->GetEndPlane()) {
03986                     endplane2=Segvp->GetEndPlane();
03987                     endplane1=Segup->GetEndPlane();
03988                   }               
03989 
03990                   dplane1=endplane2-begplane2;
03991                   dplane2=endplane1-begplane1;
03992                   
03993                   Score=double(dplane2*dplane2)/double(dplane1);
03994 
03995                   NClusters=int(Segum->GetEntries()+Segvm->GetEntries()+Segup->GetEntries()+Segvp->GetEntries());
03996 
03997                   if(Score>TopScore || (Score==TopScore && NClusters>TopClusters)) {idm=i; idp=j; TopScore=Score; TopClusters=NClusters;}
03998                 }
03999               }
04001             }
04002           }
04003         }
04004 
04005         // Add 2D tracks together across the SM gap, as a result of the match.
04006         // Can also reliably set U/V partners. Set UIDs to -1 to avoid considering
04007         // the old 2D track that is now a subsection of a larger 2D track.
04009         if((1+idm)>0 && (1+idp)>0) {
04010           TrackSegmentCam* Segum = TempMod[0][0][idm];
04011           TrackSegmentCam* Segvm = TempMod[0][1][idm];
04012           TrackSegmentCam* Segup = TempMod[1][0][idp];
04013           TrackSegmentCam* Segvp = TempMod[1][1][idp];
04014 
04015           Segup->AddSegment(Segum); Segup->SetPartner(Segvp); 
04016           Segum->SetUID(-1); Segum->SetPartner(0);
04017           
04018           Segvp->AddSegment(Segvm); Segvp->SetPartner(Segup); 
04019           Segvm->SetUID(-1); Segvm->SetPartner(0);
04020 
04021           Cont=true;
04022         }
04024         
04025       } // End while Cont==true
04026     }
04028 
04029     // Clean up
04030     for(unsigned int i=0; i<2; ++i) {TempMod[i].clear();}
04031   }
04033   
04034 
04035 
04036 
04037   // Find other 2D track matches between views.
04039   Cont=true;
04040   
04041   while(Cont==true) {
04042     Cont=false;
04043     id=-1; TopScore=0.; NClusters=0; TopClusters=0;
04044 
04045     // Loop over the roughly overlapping 2D tracks we stored above
04046     for(unsigned int i=0; i<TempTrackSeg[0].size(); ++i) {
04047       TrackSegmentCam* Segu = TempTrackSeg[0][i];
04048       TrackSegmentCam* Segv = TempTrackSeg[1][i];
04049 
04050       // If have already established U/V partners, but not made the 3D track
04051       // do this now. TempTrack separately stores the U and V components of the
04052       // 3D track, which are currently still track segments, identified by UID==4.
04053       if(Segu->GetPartner()==Segv && Segv->GetPartner()==Segu
04054          && Segu->GetUID()<4 && Segv->GetUID()<4) {
04055 
04056         TempTrack[0].push_back(Segu);
04057         TempTrack[1].push_back(Segv);
04058 
04059         Segu->SetUID(4);
04060         Segv->SetUID(4);
04061       }
04062 
04063       // Otherwise, find the 2D tracks which have the best overlap
04065       else {
04066         if(Segu->GetPartner()==0 && Segv->GetPartner()==0
04067            && Segu->GetUID()>2 && Segv->GetUID()>2) {
04068           
04069           if(Segu->GetBegPlane()<=Segv->GetBegPlane()) {
04070             begplane2=Segu->GetBegPlane();
04071             begplane1=Segv->GetBegPlane();
04072           }
04073 
04074           if(Segv->GetBegPlane()<=Segu->GetBegPlane()) {
04075             begplane2=Segv->GetBegPlane();
04076             begplane1=Segu->GetBegPlane();
04077           }
04078 
04079           if(Segu->GetEndPlane()>=Segv->GetEndPlane()) {
04080             endplane2=Segu->GetEndPlane();
04081             endplane1=Segv->GetEndPlane();
04082           }
04083 
04084           if(Segv->GetEndPlane()>=Segu->GetEndPlane()) {
04085             endplane2=Segv->GetEndPlane();
04086             endplane1=Segu->GetEndPlane();
04087           }
04088 
04089           dplane1=endplane2-begplane2;
04090           dplane2=endplane1-begplane1;
04091                   
04092           Score=double(dplane2*dplane2)/double(dplane1);
04093 
04094           NClusters=int(Segu->GetEntries()+Segv->GetEntries());
04095 
04096           MSG("AlgTrackCamList", Msg::kVerbose) << "NClusters " << NClusters << " TopClusters "<< TopClusters 
04097                                                 << " Score " << Score << " TopScore " << TopScore << " id " << i << endl;
04098           
04099           //      if(Score>TopScore || (Score==TopScore && NClusters>TopClusters)) {id=i; TopScore=Score; TopClusters=NClusters;}
04100           if((Score>TopScore && NClusters>TopClusters-4)
04101              || (Score>0.4*TopScore && NClusters>TopClusters+4) 
04102              || (Score==TopScore && NClusters>TopClusters)) {id=i; TopScore=Score; TopClusters=NClusters;}
04103         }
04104       }
04106     }
04107 
04108     // Set the U/V partners for the 2D tracks having the best overlap
04110     if((1+id)>0) {
04111       MSG("AlgTrackCamList", Msg::kVerbose) << "Final id " << id << endl;
04112 
04113       TrackSegmentCam* Segu = TempTrackSeg[0][id];
04114       TrackSegmentCam* Segv = TempTrackSeg[1][id];
04115       
04116       Segu->SetPartner(Segv); 
04117       Segv->SetPartner(Segu);
04118       Cont=true;
04119     }
04121 
04122   } // End while Cont==true
04124 
04125 
04126 
04127   // Set the cluster flags for those clusters in a 3D track, and print out results
04129   MSG("AlgTrackCamList", Msg::kVerbose) << " ** Tracks Chosen ** " << endl;
04130   
04131   for(int View=0; View<2; ++View) {
04132     MSG("AlgTrackCamList", Msg::kVerbose) << "View: "<<View<<endl;
04133     MSG("AlgTrackCamList", Msg::kVerbose) << "================================" << endl;
04134     
04135     for(unsigned int i=0; i<TempTrack[View].size(); ++i) {
04136       TrackSegmentCam* Seg = TempTrack[View][i];
04137       TrackSegmentCam* SegPartner = Seg->GetPartner();
04138 
04139       MSG("AlgTrackCamList", Msg::kVerbose) << "  Seg    " 
04140                                             << "  begpln: "  << Seg->GetBegPlane()
04141                                             << "  begtpos: " << Seg->GetBegTPos()
04142                                             << "  endpln: "  << Seg->GetEndPlane()
04143                                             << "  endtpos: " << Seg->GetEndTPos() << endl;
04144       MSG("AlgTrackCamList", Msg::kVerbose) << "  Partner" 
04145                                             << "  begpln: "  << SegPartner->GetBegPlane()
04146                                             << "  begtpos: " << SegPartner->GetBegTPos()
04147                                             << "  endpln: "  << SegPartner->GetEndPlane()
04148                                             << "  endtpos: " << SegPartner->GetEndTPos() << endl;
04149       MSG("AlgTrackCamList", Msg::kVerbose) << "================================" << endl;
04150 
04151       for(unsigned int j=0; j<Seg->GetEntries(); ++j) {
04152         Seg->GetCluster(j)->SetTrkFlag(4);      
04153       }
04154     }
04155   }
04157 
04158   return;
04159 }
04161 
04162 
04163 
04164 
04166 void AlgTrackCamList::Form3DTracks(CandSliceHandle* slice)
04167 {
04168   // The 3D track segments are now stored in the TempTracks container, with
04169   // U and V segments stored separately. In this method we look at the consituent
04170   // clusters and hits in these segments, performing fits to choose the final
04171   // strips for the track.
04172 
04173 
04174   MSG("AlgTrackCamList", Msg::kVerbose) << " *** Formation of 3D tracks *** " << endl;
04175 
04176   int ktemp, View;
04177   double swx, swy, swx2, swxy, sw, ProjectedTPos, TPosWindow(0.);
04178   double w, x, y, m, c;
04179   int UStrips, VStrips, TrackStrips, TrackPlanes;
04180 
04181   int begPlaneView[2], endPlaneView[2];
04182   int begplane1, begplane2, endplane1, endplane2, maxplane, Plane;
04183   double dScore, Score; int id;
04184 
04185   int ShwOrTrkList[500];
04186   int ViewList[500];
04187   vector<HitCam*> HitList[500];
04188   vector<TrackCam*> FinalTrackTempHolder[2];
04189   for(int k=0; k<500; ++k) {ShwOrTrkList[k]=-1; ViewList[k]=-1;}
04190 
04191 
04192 
04193   // Main loop is over the pairs of track segments, stored above
04195   for(unsigned int i=0; i<TempTrack[0].size(); ++i) {
04196     MSG("AlgTrackCamList", Msg::kVerbose) << " making track " << i << endl;
04197     
04198     
04199     // Find the beginning and end planes for each of this pair of segments.
04200     // Order them so that we have:
04201     // begplane2, begplane 1, endplane 1, endplane 2.
04203     begplane2=-1; endplane2=-1; begplane1=-1; endplane1=-1;
04204     
04205     for(View=0; View<2; ++View) {
04206       TrackSegmentCam* seg = TempTrack[View][i];
04207       if(begplane2<0 || seg->GetBegPlane()<begplane2) { begplane1=begplane2; begplane2=seg->GetBegPlane(); }
04208       else { begplane1=seg->GetBegPlane(); }
04209       
04210       if(endplane2<0 || seg->GetEndPlane()>endplane2) { endplane1=endplane2; endplane2=seg->GetEndPlane(); }
04211       else { endplane1=seg->GetEndPlane(); }
04212 
04213       begPlaneView[View]=-1; endPlaneView[View]=-1;
04214     }
04215 
04216     maxplane=1+endplane2;
04217     
04218     MSG("AlgTrackCamList", Msg::kVerbose) << begplane2 << " (" << begplane1 << ") -> (" << endplane1 << ") " << endplane2 << endl;
04220  
04221 
04222     // Unpack the clusters from the segments.
04223     // For each track, should only have one cluster on a plane.
04225     for(View=0; View<2; ++View) {
04226       TrackSegmentCam* Seg = TempTrack[View][i];
04227       
04228       for(unsigned int j=0; j<Seg->GetEntries(); ++j) {
04229         ClusterCam* Clust = Seg->GetCluster(j);
04230 
04231         Plane=Clust->GetPlane();
04232         if(Plane>=begplane2 && Plane<maxplane) {ClusterList[Plane].push_back(Clust);}
04233       }
04234     }
04236     
04237     
04238     
04239     // Trim the segments. Check we haven't tracked much further
04240     // in one view than the other, and adjust as necessary.
04241 
04242     // Maximum discrepancy allowed at each end is 3 planes. As only
04243     // clusters on planes greater than begplane1 are considered.
04245     int PrevPln, NextPln;
04246     bool LeavesAtEdge=false;
04247 
04248     // Check hasn't just left edge of detector in one view.
04249     if(ModuleType==1 && (ClusterList[begplane1][0]->GetEndTPos()>3.9 
04250                          || ClusterList[begplane1][0]->GetBegTPos()<-3.9)) {begplane1=begplane2+1; LeavesAtEdge=true;}
04251     if(ModuleType==1 && (ClusterList[endplane1][0]->GetEndTPos()>3.9 
04252                          || ClusterList[endplane1][0]->GetBegTPos()<-3.9)) {endplane1=endplane2-1; LeavesAtEdge=true;}
04253 
04254     if(!LeavesAtEdge) {
04255       // For the beginning
04257       // Jump back 4 planes before begplane1 (unless this takes us past begplane2)
04258       begplane1=begplane1-4; PrevPln=-1;
04259       Plane=begplane1; if(Plane<begplane2) {Plane=begplane2;}
04260     
04261       // Working forwards from this plane, find the first plane that has
04262       // a cluster.
04263       while(Plane<maxplane) {
04264         if(ClusterList[Plane].size()>0) {PrevPln=Plane; break;}
04265         else {Plane++;}
04266       }
04267     
04268       // Look at the next 2 planes in the same view as this cluster
04269       // and see if they have clusters too. Try and veto geometries such as
04270       //
04271       //                bp1
04272       // u       x   x   o   o
04273       // v         o   x   *   o
04274       //          bp2      * == shw-like, or gap
04275       //
04276       // In this case, begplane1 is set to begplane 2, so the lone hit at 
04277       // begplane 2 is later vetoed.
04278       if(PrevPln>-1 && PrevPln+4<maxplane && ClusterList[PrevPln+2].size()==0) {
04279         if(ClusterList[PrevPln+4].size()>0) {
04280           ClusterCam* Clust = ClusterList[PrevPln+4][0];
04281         
04282           if(Clust->GetTrkPlnFlag()>0 && Clust->GetShwPlnFlag()==0) {
04283             PrevPln=begplane1;
04284           }
04285         }
04286         begplane1=PrevPln;
04287       }
04288     
04289     
04290       // Similarly, for the end 
04292       // Jump forward 4 planes after endplane1 (unless this takes us past endplane2)
04293       endplane1=endplane1+4; NextPln=-1;
04294       Plane=endplane1; if(Plane>maxplane-1) {Plane=maxplane-1;}
04295     
04296       // Working backwards from this plane, find the first plane that has
04297       // a cluster.
04298       while(Plane>begplane2-1) {
04299         if(ClusterList[Plane].size()>0) {NextPln=Plane; break;}
04300         else {Plane--;}
04301       }
04302     
04303       // Look at the next 2 planes in the same view as this cluster
04304       // and see if they have clusters too, as above.
04305       if(NextPln>-1 && NextPln-4>(begplane2-1) && ClusterList[NextPln-2].size()==0) {
04306         if(ClusterList[NextPln-4].size()>0) {
04307           ClusterCam* Clust = ClusterList[NextPln-4][0];
04308         
04309           if(Clust->GetTrkPlnFlag()>0 && Clust->GetShwPlnFlag()==0) {
04310             NextPln=endplane1;
04311           }
04312         }
04313         endplane1=NextPln;
04314       }
04316     }
04318 
04319     
04320 
04321     // Count the strips and record planeviews, number of occupied planes, etc.
04323     UStrips=0; VStrips=0; TrackStrips=0;
04324 
04325     // Look at the region over which the track is now defined
04326     for(int k=begplane2; k<maxplane; ++k) {  
04327 
04328       if( //  (k>=begplane1 && k<=endplane1) &&
04329           ClusterList[k].size()>0 ) {
04330 
04331         ClusterCam* Clust = ClusterList[k][0];
04332         
04333         View=Clust->GetPlaneView();
04334         ViewList[k]=View;
04335         ShwOrTrkList[k]=1;
04336         
04337         // Record first and last planes in each view.
04338         if(begPlaneView[View]<0 || k<begPlaneView[View]) {begPlaneView[View]=k;}
04339         if(endPlaneView[View]<0 || k>endPlaneView[View]) {endPlaneView[View]=k;}
04340         
04341         if(View==0) {UStrips++;}
04342         if(View==1) {VStrips++;}
04343         
04344         if(Clust->GetTrkPlnFlag()>0) {TrackStrips++;}
04345       }
04346     }
04347     
04348     
04349     MSG("AlgTrackCamList", Msg::kVerbose) 
04350       << " U: (" << begPlaneView[0] << "," << endPlaneView[0] << ") " 
04351       << " V: (" << begPlaneView[1] << "," << endPlaneView[1] << ") " 
04352       << " UStrips " << UStrips << " VStrips " << VStrips << " TrackStrips " << TrackStrips << endl;
04354     
04355     
04356 
04357     
04358     // If we have at least 3 strips in each view and at least 2 clusters
04359     // on track-like planes, proceed with the fits.
04361     if(UStrips>2 && VStrips>2 && (CambridgeAnalysis==false || TrackStrips>2) ) {
04362 
04363 
04364       // FLAG PLANES which we think are track-like
04366       for(View=0; View<2; ++View) {
04367         for(Plane=begplane2; Plane<maxplane; ++Plane) {
04368 
04369           if(ViewList[Plane]==View && ShwOrTrkList[Plane]>0) {
04370             ClusterCam* Clust0 = ClusterList[Plane][0];
04371 
04372             // Always set flag to 3 for the +/- 5 plane ND track segments
04373             if(Clust0->GetNDFlag()==2) {ShwOrTrkList[Plane]=3;}
04374 
04375 
04376             // Find next planes, in the same view, where we have a cluster, both forwards
04377             // and backwards.
04379             ktemp=0; PrevPln=-1;
04380             while(Plane-ktemp>begplane2) {
04381               ktemp++;
04382               if(ViewList[Plane-ktemp]==View) {PrevPln=ktemp; break;}
04383             }
04384 
04385             ktemp=0; NextPln=-1;
04386             while(Plane+ktemp<maxplane-1) {
04387               ktemp++;
04388               if(ViewList[Plane+ktemp]==View) {NextPln=ktemp; break;}
04389             }
04391 
04392 
04393             // If there are planes forwards and backwards in the same view...
04395             if(PrevPln>0 && NextPln>0) {
04396               ClusterCam* NextClust = ClusterList[Plane+NextPln][0];
04397               ClusterCam* PrevClust = ClusterList[Plane-PrevPln][0];
04398               
04399               // If either both clusters are within range for this view, or they are the
04400               // next plane along and the current plane is a track plane.
04401               if( (PrevClust->GetPlane()>begPlaneView[View]
04402                    || (Clust0->GetPlane()-PrevClust->GetPlane()<3 && Clust0->GetTrkPlnFlag()>0))
04403                   && (NextClust->GetPlane()<endPlaneView[View]
04404                       || (NextClust->GetPlane()-Clust0->GetPlane()<3 && Clust0->GetTrkPlnFlag()>0) )) {
04405 
04406 
04407                 // If the clusters have track-like association, identify plane as
04408                 // being track like, by setting entry in ShwOrTrkList to 3.
04409                 if(Clust0->IsTrkAssoc(PrevClust,NextClust)>1) {
04410                   ShwOrTrkList[Plane]=3;
04411 
04412                   // If there is a good overlap of strip numbers between the three clusters
04413                   if( (NextClust->GetBegTPos()-Clust0->GetEndTPos()>-1.1*StripWidth 
04414                        && Clust0->GetBegTPos()-PrevClust->GetEndTPos()>-1.1*StripWidth)
04415                       || (NextClust->GetEndTPos()-Clust0->GetBegTPos()<1.1*StripWidth
04416                           && Clust0->GetEndTPos()-PrevClust->GetBegTPos()<1.1*StripWidth) ) {
04417 
04418                     // If forwards and backwards planes are adjacent in view,
04419                     // identify these planes as track-like too
04420                     if( Clust0->GetPlane()-PrevClust->GetPlane()<3 || Clust0->GetNDFlag()==2) {ShwOrTrkList[Plane-PrevPln]=3;}
04421                     if( NextClust->GetPlane()-Clust0->GetPlane()<3 || Clust0->GetNDFlag()==2) {ShwOrTrkList[Plane+NextPln]=3;}
04422                   }
04423                 }
04424 
04425                 // Otherwise, if cluster is small, can identify its plane as track-like.
04426                 // Don't set anything for forwards and backwards planes.
04427                 else {
04428                   if(Clust0->GetEndTPos()-Clust0->GetBegTPos()<2.1*StripWidth 
04429                      && Clust0->GetTrkPlnFlag()>0) {ShwOrTrkList[Plane]=3;}
04430                 }
04431               }
04432             }
04434 
04435           }
04436         } // End loop over planes
04437       } // End loop over views
04439 
04440 
04442       MSG("AlgTrackCamList", Msg::kVerbose) << " *** SORT TRACK HITS *** " << endl;
04443       
04444       for(Plane=begplane2;Plane<maxplane; ++Plane) {
04445         if(ViewList[Plane]>-1) {
04446           ClusterCam* Clust = ClusterList[Plane][0];
04447           MSG("AlgTrackCamList", Msg::kVerbose) << Clust->GetPlane() 
04448                                                 << " " << Clust->GetBegTPos() << " " << Clust->GetEndTPos()
04449                                                 << " " << ShwOrTrkList[Plane] << endl;
04450         }
04451       }
04453 
04454 
04455 
04456       // Perform GLOBAL LINEAR FIT
04458       int ShowerStart, ShowerEnd, FitStart, FitEnd, PrevTrkPln, NextTrkPln;
04459 
04460       for(View=0; View<2; ++View) {
04461         for(Plane=begplane2; Plane<maxplane; ++Plane) {
04462 
04463 
04464           // Currently ShwOrTrkList flag==1 means the plane was part of the 3D track.
04465           // ShwOrTrkList flag==3 means that we also flagged the plane as being track-like, above.
04466           //
04467           // Here, we look at the planes we haven't flagged as track-like, find track-like planes
04468           // on either side and carry out a linear fit through this 'shower-like' region.
04469           // 
04470           // Using the fit, clusters in this shower-like region are identified, then hits.
04472           if(ViewList[Plane]==View && ShwOrTrkList[Plane]<2) {
04473             MSG("AlgTrackCamList", Msg::kVerbose) << " *** GLOBAL FIT ***   Plane=" << Plane << endl;
04474 
04475             // Look for next planes in the view that we have flagged as track-like, 
04476             // forwards and backwards.
04478             ktemp=0; NextTrkPln=-1;
04479             while(Plane+ktemp<endplane1 && Plane+ktemp<maxplane-1) {
04480               ktemp++;
04481               if(ViewList[Plane+ktemp]==View && ShwOrTrkList[Plane+ktemp]>2) {NextTrkPln=ktemp; break;}
04482             }
04483             
04484             ktemp=0; PrevTrkPln=-1;
04485             while(Plane-ktemp>begplane1 && Plane-ktemp>begplane2) {
04486               ktemp++;
04487               if(ViewList[Plane-ktemp]==View && ShwOrTrkList[Plane-ktemp]>2) {PrevTrkPln=ktemp; break;}
04488             }
04490 
04491             
04492             // Find the track-like planes which are just outside of the shower-like region ('ShowerStart' 
04493             // and 'ShowerEnd' planes away), as well as the planes which are up to 7 planes either side 
04494             // of the shower-like region ('FitStart' and 'FitEnd' planes away). These are the 
04495             // track used in the linear fit through the shower.
04497             if(PrevTrkPln>0) {FitStart=-PrevTrkPln-7; ShowerStart=-PrevTrkPln;} 
04498             else {FitStart=begplane1-Plane+1; ShowerStart=FitStart;}
04499 
04500             if(Plane+FitStart<begplane2) {FitStart=-Plane+begplane2;}
04501             if(Plane+ShowerStart<begplane2) {ShowerStart=-Plane+begplane2;}
04502 
04503             if(NextTrkPln>0) {FitEnd=1+NextTrkPln+7; ShowerEnd=1+NextTrkPln;}
04504             else {FitEnd=endplane1-Plane; ShowerEnd=FitEnd;}
04505 
04506             if(Plane+FitEnd>maxplane) {FitEnd=maxplane-Plane;}
04507             if(Plane+ShowerEnd>maxplane) {ShowerEnd=maxplane-Plane;}
04509 
04510 
04511             ClusterCam* ClustSeed = ClusterList[Plane][0];
04512 
04513             m=0.; c=0.5*(ClustSeed->GetBegTPos()+ClustSeed->GetEndTPos());
04514             swx=0.; swy=0.; swx2=0.; swxy=0.; sw=0.;
04515 
04516 
04517             // Carry out the linear fit through the shower, obtaining gradient and intercept.
04519             for(int k=FitStart; k<FitEnd; ++k) {
04520               if(ViewList[Plane+k]==View) {
04521                 ClusterCam* ClustTemp = ClusterList[Plane+k][0];
04522                 
04523                 for(unsigned int l=0; l<ClustTemp->GetEntries(); ++l) {
04524                   HitCam* HitTemp = ClustTemp->GetHit(l);
04525 
04526                   x=HitTemp->GetZPos();
04527                   y=HitTemp->GetTPos();
04528                   w=HitTemp->GetCharge()/ClustTemp->GetCharge();
04529                   
04530                   if(ShwOrTrkList[Plane+k]>2) {w=5.*w;}
04531                   else {w=0.5*w;}
04532                   
04533                   swx+=w*x; swy+=w*y; swx2+=w*x*x; swxy+=w*x*y; sw+=w;
04534                 }
04535               }
04536             }
04537 
04538             if(sw>0. && (sw*swx2-swx*swx)!=0.) {
04539               m=(sw*swxy-swx*swy)/(sw*swx2-swx*swx);
04540               c=(swy*swx2-swx*swxy)/(sw*swx2-swx*swx);
04541             }
04543 
04544 
04545             // Now loop over the planes in the shower-like region
04547             for(int k=ShowerStart; k<ShowerEnd; ++k) {
04548               if(ViewList[Plane+k]==View && ShwOrTrkList[Plane+k]<2) {
04549                 // ***First cluster in ClusterList is that from segment in 3D track***
04550                 ClusterCam* ClustTemp = ClusterList[Plane+k][0];
04551                 
04552                 // Projected strip number in shower
04553                 ProjectedTPos = m*ClustTemp->GetZPos()+c;
04554 
04555                 // Calculate window around projected strip number
04556                 if(m>=0.) {TPosWindow = (0.6*StripWidth)+0.02*m;}
04557                 if(m<=0.) {TPosWindow = (0.6*StripWidth)-0.02*m;}
04558 
04559                 MSG("AlgTrackCamList", Msg::kVerbose) << " Plane=" << Plane+k << " ProjectedTPos=" << ProjectedTPos 
04560                                                       << " TPosWindow=" << TPosWindow << " (" << ClustTemp->GetBegTPos() 
04561                                                       << " " << ClustTemp->GetEndTPos() << ") " << endl;
04562 
04563 
04564                 // If  1. we have found track-like planes on either side of the shower-like region,
04565                 // or  2. we haven't found any of these track-like planes (entire track in this view must be shower),
04566                 // or  3. current cluster overlaps quite nicely with projected strip number from the fit,
04567                 //
04568                 // then proceed with trying to find the best hits from within the cluster.
04570                 if( (PrevTrkPln>0 && NextTrkPln>0) || (PrevTrkPln<0 && NextTrkPln<0)
04571                     || (ClustTemp->GetEndTPos()>ProjectedTPos-(1.6*StripWidth) && ClustTemp->GetBegTPos()<ProjectedTPos+(1.6*StripWidth)) ) {
04572 
04573                   id=-1; dScore=0.; Score=999.9;
04574 
04575                   // Loop over hits in cluster and get a 'score' for each. Score is based
04576                   // on distance from projected tpos, and we want to minimise this.
04577                   for(unsigned int l=0; l<ClustTemp->GetEntries(); ++l) {
04578                     HitCam* HitTemp = ClustTemp->GetHit(l);
04579                     
04580                     dScore=HitTemp->GetTPos()-ProjectedTPos;
04581                     if(dScore<0) {dScore=-dScore;}
04582 
04583                     if(dScore<Score) {id=l; Score=dScore;}
04584                   }
04586 
04587         
04588                   // If we have found a 'best hit'
04590                   if((1+id)>0) {
04591                     HitCam* Hit = ClustTemp->GetHit(id);
04592                     
04593                     // Create new cluster and store it. 
04594                     // ***Last cluster in ClusterList will be that found by the fit.***
04595                     ClusterCam* ClustNew = new ClusterCam(Hit);
04596                     ClusterList[Plane+k].push_back(ClustNew);
04597                     
04598                     ShwOrTrkList[Plane+k]=2;
04599                     
04600                     // If any other hits in the cluster found by the fit are also good, 
04601                     // add these to the new cluster too.
04602                     for(unsigned int l=0; l<ClustTemp->GetEntries(); ++l) {
04603                       HitCam* HitTemp = ClustTemp->GetHit(l);
04604                         
04605                       if( (HitTemp->GetTPos()-Hit->GetTPos()>0
04606                            && HitTemp->GetTPos()-Hit->GetTPos()<TPosWindow)
04607                           || (HitTemp->GetTPos()-Hit->GetTPos()<0
04608                               && HitTemp->GetTPos()-Hit->GetTPos()>-TPosWindow) ) {
04609                           
04610                         ClustNew->AddHit(HitTemp);
04611                       }
04612                     }
04613 
04614                     for(unsigned int l=0; l<ClustNew->GetEntries(); ++l) {
04615                       MSG("AlgTrackCamList", Msg::kVerbose) << "   ...global add hit=" << ClustNew->GetHit(l)->GetTPos() << " (" << Plane+k << ") " << endl;
04616                     }
04617                   }
04619 
04620                 }
04621               }
04622             }
04624           }
04625         }  // End loop over planes
04626       } // End loop over views
04628 
04629 
04630 
04631       // Now, Perform LOCAL LINEAR FITS
04633       for(View=0; View<2; ++View) {
04634         for(Plane=begplane2; Plane<maxplane; ++Plane) {
04635 
04636           // If plane has been declared track-like
04637           if(ViewList[Plane]==View && ShwOrTrkList[Plane]>1) {
04638             MSG("AlgTrackCamList", Msg::kVerbose) << " *** FIT (2) ***   Plane=" << Plane << endl;
04639 
04640             // Get last cluster from ClusterList. This will have been flagged immediately as track-like,
04641             // or have been stored as a result of a linear fit through a shower-like region.
04642             // Using the cluster, calculate a projected strip number and window for use in the local fit.
04643             ClusterCam* clr = ClusterList[Plane].back();
04644             ProjectedTPos=0.5*(clr->GetBegTPos()+clr->GetEndTPos()); 
04645             TPosWindow=0.6*StripWidth;
04646 
04647             // Loop over the hits in this cluster
04649             const unsigned int nhits = clr->GetEntries();
04650             if(nhits>1){
04651               for(unsigned int k=0; k<nhits; ++k) {clr->GetHit(k)->SetTrkFlag(1);}
04652               
04653               swx=0.0; swy=0.0; swx2=0.0; swxy=0.0; sw=0.0;
04654 
04655               // For these, loop over the hits in nearby clusters (within 4 planes of the current plane)
04656               // and carry out the linear fit
04658               for(int k=-4; k<5; ++k){
04659                 if( (Plane+k)>=begplane2 && (Plane+k)<(maxplane) && ViewList[Plane+k]==View && ShwOrTrkList[Plane+k]>1 ) {
04660                   ClusterCam* clrtmp = ClusterList[Plane+k].back(); // Again get last entry 
04661 
04662                   for(unsigned int l=0; l<clrtmp->GetEntries(); ++l){
04663                     HitCam* hittmp = clrtmp->GetHit(l);
04664                     x=hittmp->GetZPos(); 
04665                     y=hittmp->GetTPos(); 
04666                     w=hittmp->GetCharge()/clrtmp->GetCharge();
04667 
04668                     swx+=w*x; swy+=w*y; swx2+=w*x*x; swxy+=w*x*y; sw+=w;
04669                   }
04670                 }
04671               }
04672 
04673               if(sw>1.0 && (sw*swx2-swx*swx)!=0.){
04674                 m=(sw*swxy-swx*swy)/(sw*swx2-swx*swx);
04675                 c=(swy*swx2-swx*swxy)/(sw*swx2-swx*swx);
04676                 ProjectedTPos=m*clr->GetZPos()+c; 
04677                 if(m>=0.0) TPosWindow = (0.6*StripWidth)+0.02*m; 
04678                 if(m<=0) TPosWindow = (0.6*StripWidth)-0.02*m; 
04679               }
04681             }
04683             
04684             MSG("AlgTrackCamList", Msg::kVerbose) << "  local plane=" << Plane << " ProjectedTPos=" << ProjectedTPos 
04685                                                   << " TPosWindow=" << TPosWindow << endl;
04686 
04687 
04688             // Using the results of the fit, obtain a score for each hit. Again, this is
04689             // based on distance from the projected strip number. We want to pick the hit which
04690             // minimises this distance.
04692             id=-1; dScore=0.; Score=999.;
04693             
04694             for(unsigned int k=0; k<nhits; ++k){
04695               HitCam* hit = clr->GetHit(k);  
04696               dScore=hit->GetTPos()-ProjectedTPos; if(dScore<0) dScore=-dScore;
04697               
04698               if(dScore<Score){id=k; Score=dScore;}
04699             }
04700             
04701             // If we have found a good hit, store it and flag the plane as part of the 
04702             // final track
04703             if(1+id>0){  
04704               HitCam* hit = clr->GetHit(id); 
04705               HitList[Plane].push_back(hit); ShwOrTrkList[Plane]=4;
04706 
04707               // Include any other hits which also match projection within the window
04708               for(unsigned int k=0; k<nhits; ++k){
04709                 HitCam* hittmp = clr->GetHit(k);
04710                 if( ( hittmp->GetTPos()-hit->GetTPos()>0 && hittmp->GetTPos()-hit->GetTPos()<TPosWindow)
04711                     || ( hittmp->GetTPos()-hit->GetTPos()<0 && hittmp->GetTPos()-hit->GetTPos()>-TPosWindow) ){
04712                   HitList[Plane].push_back(hittmp);
04713                 }
04714               }
04715             }
04716 
04717             for(unsigned int l=0; l<HitList[Plane].size(); ++l){
04718               HitCam* hittmp = HitList[Plane][l];
04719               MSG("AlgTrackCamList", Msg::kVerbose) << "   ...local add hit=" << hittmp->GetTPos() << " (" << Plane << ") " << endl;
04720             }
04722 
04723           } // End demand that plane has been flagged as track-like
04724         } // End loop over planes
04725       } // End loop over views
04727       
04728 
04729 
04730       // *** FINALLY, FORM THE TRACKS ***
04732       // Count the number of planes flagged as being part of final track
04733       TrackPlanes=0;
04734       
04735       for(Plane=begplane2; Plane<maxplane; ++Plane) {
04736         if(ShwOrTrkList[Plane]>3) {TrackPlanes++;}
04737       }
04738 
04739       MSG("AlgTrackCamList", Msg::kVerbose) << " TrackPlanes " << TrackPlanes << endl;
04740 
04741       if(CambridgeAnalysis==false || TrackPlanes>5) {
04742         for(View=0; View<2; ++View) {
04743           
04744           TrackCam* Trk = new TrackCam(slice);
04745           FinalTrackTempHolder[View].push_back(Trk);
04746           
04747           for(Plane=begplane2; Plane<maxplane; ++Plane) {
04748             if(ViewList[Plane]==View && ShwOrTrkList[Plane]>3) {
04749               
04750               for(unsigned int k=0; k<HitList[Plane].size(); ++k) {
04751                 HitList[Plane][k]->SetTrkFlag(2);
04752                 Trk->AddHit(HitList[Plane][k]);
04753               }
04754             }
04755           }
04756         }
04757         
04758         TrackCam* Trku = FinalTrackTempHolder[0].back();
04759         TrackCam* Trkv = FinalTrackTempHolder[1].back();
04760         
04761         Trku->SetPartner(Trkv); 
04762         Trkv->SetPartner(Trku);
04763         
04764         for(unsigned int p=0; p<Trku->GetEntries(); ++p) {HitsInTracks[0].push_back(Trku->GetHit(p));}
04765         for(unsigned int p=0; p<Trkv->GetEntries(); ++p) {HitsInTracks[1].push_back(Trkv->GetHit(p));}
04766       }
04767       
04768     } // End U/V/TrackStrips check
04770 
04771     for(int k=0; k<500; ++k) {
04772       ShwOrTrkList[k]=-1; 
04773       ViewList[k]=-1;
04774       ClusterList[k].clear();
04775       HitList[k].clear();
04776     }
04777 
04778   } // End loop over temporary tracks   
04780  
04781  
04782 
04783   // Check tracks don't contain same hits as a previous track
04785   bool GoodTrack; bool ThreePlanes[2];
04786   int DuplicateStrips[2]; int Planes[2]; int ThisPlane;
04787   vector<HitCam*> HitsInPrevTracks[2];
04788 
04789   for(unsigned int p=0; p<FinalTrackTempHolder[0].size(); ++p) {
04790 
04791     TrackCam* Trku = FinalTrackTempHolder[0][p];
04792     TrackCam* Trkv = FinalTrackTempHolder[1][p];
04793 
04795     if(ModuleType==1) {LookForHitsAcrossGap(Trku); LookForHitsAcrossGap(Trkv);}
04796 
04797     ExtendTrack(Trku); ExtendTrack(Trkv);
04798     FillGapsInTrack(Trku); FillGapsInTrack(Trkv);
04800 
04801 
04803     GoodTrack=false; 
04804 
04805     if(Trku->GetEntries()>2 && Trkv->GetEntries()>2) {
04806       DuplicateStrips[0]=0; DuplicateStrips[1]=0;
04807 
04808       // For u
04809       Planes[0]=-999; Planes[1]=-999; ThreePlanes[0]=false;
04810 
04811       for(unsigned int p=0; p<Trku->GetEntries(); ++p) {
04812         HitCam* TrackHit = Trku->GetHit(p);
04813 
04814         for(unsigned int q=0; q<HitsInPrevTracks[0].size(); ++q) {
04815           if(TrackHit==HitsInPrevTracks[0][q]) {DuplicateStrips[0]++; break;}
04816         }
04817 
04818         ThisPlane=TrackHit->GetPlane();
04819         if(Planes[0]<0) {Planes[0]=ThisPlane;}
04820         else if(Planes[1]<0 && Planes[0]!=ThisPlane) {Planes[1]=ThisPlane;}
04821         else if(Planes[0]!=ThisPlane && Planes[1]!=ThisPlane) {ThreePlanes[0]=true;}
04822 
04823         if(DuplicateStrips[0]>2) {break;}
04824       }
04825 
04826 
04827       // For v
04828       Planes[0]=-999; Planes[1]=-999; ThreePlanes[1]=false;
04829 
04830       for(unsigned int p=0; p<Trkv->GetEntries(); ++p) {
04831         HitCam* TrackHit = Trkv->GetHit(p);
04832 
04833         for(unsigned int q=0; q<HitsInPrevTracks[1].size(); ++q) {
04834           if(TrackHit==HitsInPrevTracks[1][q]) {DuplicateStrips[1]++; break;}
04835         }
04836 
04837         ThisPlane=TrackHit->GetPlane();
04838         if(Planes[0]<0) {Planes[0]=ThisPlane;}
04839         else if(Planes[1]<0 && Planes[0]!=ThisPlane) {Planes[1]=ThisPlane;}
04840         else if(Planes[0]!=ThisPlane && Planes[1]!=ThisPlane) {ThreePlanes[1]=true;}
04841 
04842         if(DuplicateStrips[1]>2) {break;}
04843       }
04844 
04845       if(ThreePlanes[0] && ThreePlanes[1] && DuplicateStrips[0]<3 && DuplicateStrips[1]<3) {GoodTrack=true;}    
04846     }
04848 
04849 
04850     if(GoodTrack) {
04851       FinalTrackBank[0].push_back(Trku);
04852       FinalTrackBank[1].push_back(Trkv);
04853 
04854       for(unsigned int q=0; q<Trku->GetEntries(); ++q) {HitsInPrevTracks[0].push_back(Trku->GetHit(q));}
04855       for(unsigned int q=0; q<Trkv->GetEntries(); ++q) {HitsInPrevTracks[1].push_back(Trkv->GetHit(q));}
04856 
04857       if(ModuleType==2) {MatchUV(Trku,Trkv);}
04858     }
04859   }
04860 
04861   FinalTrackTempHolder[0].clear(); FinalTrackTempHolder[1].clear();
04862   HitsInPrevTracks[0].clear(); HitsInPrevTracks[1].clear();
04864 
04865 
04866 
04867   // Print out list of final tracks           
04869   MSG("AlgTrackCamList", Msg::kVerbose) << " *** LIST OF TRACKS *** " << endl;
04870   for(View=0; View<2; ++View) {
04871     for(unsigned int i=0; i<FinalTrackBank[View].size(); ++i) {
04872       TrackCam* TrkTemp = FinalTrackBank[View][i];
04873       
04874       MSG("AlgTrackCamList", Msg::kVerbose) 
04875         << "  " << View << " " << i
04876         << "  " << TrkTemp->GetBegPlane() << "  " << TrkTemp->GetEndPlane() << endl;
04877     }
04878   }
04880 
04881   return;
04882 }
04884 
04885 
04886 
04888 void AlgTrackCamList::ExtendTrack(TrackCam* Trk)
04889 {
04890   MSG("AlgTrackCamList", Msg::kVerbose) << " Attempting to extend track at beginning and end " << endl;
04891   
04892   int PlanesSinceAdded, CurrentPlane(0), Increment(0);
04893   unsigned int nhits;
04894   double TrkDir(0.), TrkTPos(0.), TrkZPos(0.), PredictedTPos, extrem1, extrem2;
04895   double StripCentre, CurrentZPos, MinDistanceToHit, StripCharge;
04896 
04897   double Tolerance; int MaxPlanes;
04898   int PlaneView=Trk->GetPlaneView();
04899 
04900   bool ConsiderHit;
04901 
04902   if(ModuleType==1 || ModuleType==3) {MaxPlanes=8; Tolerance=2.*StripWidth;}
04903   else {MaxPlanes=40; Tolerance=4.*StripWidth;}
04904 
04905   // Extend beginning first, then the end.
04907   for(int direction=0; direction<2; ++direction) {
04908   
04909     PlanesSinceAdded=1; 
04910     if(direction==0) {CurrentPlane=Trk->GetBegPlane()-1; Increment=-1;}
04911     else if(direction==1) {CurrentPlane=Trk->GetEndPlane()+1; Increment=1;}
04912 
04913     
04914     while(PlanesSinceAdded<=MaxPlanes && CurrentPlane>=0 && CurrentPlane<=PlanesInModule) { 
04915       // Don't do anything if there are no hits, or we aren't in the same view.
04916       nhits=AllHitBank[CurrentPlane].size();
04917       if(nhits>0 && AllHitBank[CurrentPlane][0]->GetPlaneView()==PlaneView) {
04918 
04919         if(direction==0) {
04920           TrkDir=Trk->GetBegDir(); 
04921           TrkTPos=Trk->GetBegTPos(); 
04922           TrkZPos=Trk->GetBegZPos(); 
04923         }
04924         else if(direction==1) {
04925           TrkDir=Trk->GetEndDir(); 
04926           TrkTPos=Trk->GetEndTPos(); 
04927           TrkZPos=Trk->GetEndZPos(); 
04928         }
04929 
04930         HitCam* CurrentHit = 0;
04931         CurrentZPos = AllHitBank[CurrentPlane][0]->GetZPos();
04932 
04933         MinDistanceToHit = Tolerance;
04934         
04935         // Loop over the hits on the plane
04936         for(unsigned int i=0; i<nhits; ++i) {
04937 
04938           // Don't add a hit that is already in another track in the slice
04939           ConsiderHit=true;
04940           for(unsigned int p=0; p<HitsInTracks[PlaneView].size(); ++p) {
04941             if(AllHitBank[CurrentPlane][i]==HitsInTracks[PlaneView][p]) {ConsiderHit=false; break;}
04942           }
04943           if(ConsiderHit==false) {continue;}
04944 
04945 
04946           // Find the most likely hit to add
04947           PredictedTPos = TrkTPos + TrkDir*(CurrentZPos-TrkZPos);
04948           extrem1 = PredictedTPos + (0.055*TrkDir);
04949           extrem2 = PredictedTPos - (0.055*TrkDir);
04950           
04951           StripCentre=AllHitBank[CurrentPlane][i]->GetTPos();
04952           StripCharge=AllHitBank[CurrentPlane][i]->GetCharge();
04953           
04954           MSG("AlgTrackCamList", Msg::kVerbose) << "Prediction " << direction << " " << PredictedTPos 
04955                                                 << " Actual " << StripCentre   << " CurrentZPos " << CurrentZPos << " trkdir " << TrkDir << endl;
04956           
04957           if(fabs(StripCentre-PredictedTPos)<MinDistanceToHit 
04958              && (ModuleType==1 || ModuleType==3 || StripCharge>2 || (fabs(StripCentre-PredictedTPos)<StripWidth && PlanesSinceAdded<20)) ) {
04959             MinDistanceToHit = fabs(StripCentre-PredictedTPos);
04960             CurrentHit = AllHitBank[CurrentPlane][i];
04961           }
04962           else if(fabs(StripCentre-extrem1)<MinDistanceToHit 
04963                   && (ModuleType==1 || ModuleType==3 || StripCharge>2 || (fabs(StripCentre-extrem1)<StripWidth && PlanesSinceAdded<20)) ) {
04964             MinDistanceToHit = fabs(StripCentre-extrem1);
04965             CurrentHit = AllHitBank[CurrentPlane][i];
04966           }
04967           else if(fabs(StripCentre-extrem2)<MinDistanceToHit 
04968                   && (ModuleType==1 || ModuleType==3 || StripCharge>2 || (fabs(StripCentre-extrem2)<StripWidth && PlanesSinceAdded<20)) ) {
04969             MinDistanceToHit = fabs(StripCentre-extrem2);
04970             CurrentHit = AllHitBank[CurrentPlane][i];
04971           }
04972         }
04973         
04974         // Add best hit we have found
04975         if(CurrentHit) {
04976           Trk->AddHit(CurrentHit); 
04977           HitsInTracks[PlaneView].push_back(CurrentHit);
04978 
04979           PlanesSinceAdded=0;
04980 
04981           MSG("AlgTrackCamList", Msg::kVerbose) << "Track extended " << direction << " TPos " << CurrentHit->GetTPos() 
04982                                                 << " ZPos " << CurrentHit->GetZPos() << endl;
04983         }
04984       }
04985       else {PlanesSinceAdded++;}
04986       
04987       CurrentPlane+=Increment;
04988     }
04989   }
04991 
04992 
04993   return;
04994 }
04996 
04997 
04998 
05000 void AlgTrackCamList::FillGapsInTrack(TrackCam* Trk)
05001 {
05002   MSG("AlgTrackCamList", Msg::kVerbose) << " Attempting to fill gaps in track " << endl;
05003 
05004 
05005   // First store track hits in plane order
05006   vector<HitCam*> TrackHits[490];
05007   int PlaneView=Trk->GetPlaneView();
05008 
05009   for(unsigned int i=0; i<Trk->GetEntries(); ++i) {
05010     HitCam* Hit = Trk->GetHit(i);
05011     TrackHits[Hit->GetPlane()].push_back(Hit);
05012   }
05013 
05014   
05015   // Find gaps
05016   int PrevPlaneWithHit=Trk->GetBegPlane();
05017   int NextPlaneWithHit=Trk->GetEndPlane();
05018 
05019   double PrevTPos, NextTPos, PrevZPos, NextZPos, CurrentZPos;
05020   double PredictedGradient, PredictedTPos, MinDistanceToHit, StripCharge;
05021   double Tolerance; bool ConsiderHit;
05022 
05023   if(ModuleType==1 || ModuleType==3) {Tolerance=1.5*StripWidth;}
05024   else {Tolerance=3.*StripWidth;}
05025 
05026   for(int i=Trk->GetBegPlane()+1; i<Trk->GetEndPlane(); i++) {
05027     // Don't do anything if there are no hits, or we aren't in the same view.
05028     if(AllHitBank[i].size()>0 && AllHitBank[i][0]->GetPlaneView()==PlaneView) {
05029       
05030       // Find the hit planes on either side of a gap.
05031       if(TrackHits[i].size()>0) {PrevPlaneWithHit=i; continue;}
05032 
05033       for(int j=i+2; j<=Trk->GetEndPlane(); j++) {
05034         if(TrackHits[j].size()>0) {NextPlaneWithHit=j; break;}
05035       }
05036  
05037       // Now try and fill the gap. Limit to maximum gap size?
05038       if(PrevPlaneWithHit!=NextPlaneWithHit) {
05039         CurrentZPos=AllHitBank[i][0]->GetZPos();
05040 
05041         PrevZPos=TrackHits[PrevPlaneWithHit][0]->GetZPos();
05042         NextZPos=TrackHits[NextPlaneWithHit][0]->GetZPos();
05043 
05044         PrevTPos=TrackHits[PrevPlaneWithHit][0]->GetTPos();
05045         NextTPos=TrackHits[NextPlaneWithHit][0]->GetTPos();
05046 
05047         PredictedGradient=(NextTPos-PrevTPos)/(NextZPos-PrevZPos);
05048         PredictedTPos=PrevTPos+((CurrentZPos-PrevZPos)*PredictedGradient);
05049 
05050         HitCam* CurrentHit = 0;
05051 
05052         MinDistanceToHit=Tolerance;
05053 
05054         for(unsigned int k=0; k<AllHitBank[i].size(); ++k) {
05055           HitCam* hit = AllHitBank[i][k];
05056 
05057 
05058           // Don't add a hit that is already in another track in the slice
05059           ConsiderHit=true;
05060           for(unsigned int p=0; p<HitsInTracks[PlaneView].size(); ++p) {
05061             if(hit==HitsInTracks[PlaneView][p]) {ConsiderHit=false; break;}
05062           }
05063           if(ConsiderHit==false) {continue;}
05064           
05065 
05066           // Find the most likely hit to add
05067           StripCharge=hit->GetCharge();
05068 
05069           if(fabs(PredictedTPos-hit->GetTPos())<MinDistanceToHit 
05070              && (ModuleType==1 || ModuleType==3 || StripCharge>2 || fabs(PredictedTPos-hit->GetTPos())<StripWidth)) {
05071 
05072             MinDistanceToHit=fabs(PredictedTPos-hit->GetTPos());
05073             CurrentHit=hit;
05074           }
05075         }
05076       
05077         if(CurrentHit) {
05078           Trk->AddHit(CurrentHit); 
05079           TrackHits[i].push_back(CurrentHit);
05080           HitsInTracks[PlaneView].push_back(CurrentHit);
05081 
05082           MSG("AlgTrackCamList", Msg::kVerbose) << "Gap filled at TPos " << CurrentHit->GetTPos()
05083                                                 << " ZPos " << CurrentHit->GetZPos() << endl;
05084         }
05085       }
05086     }
05087   }
05088   
05089   // Clean up
05090   for(int i=0; i<490; ++i) {TrackHits[i].clear();}
05091   
05092   return;
05093 }
05095 
05096 
05097 
05098 
05100 void AlgTrackCamList::LookForHitsAcrossGap(TrackCam* Trk)
05101 {
05102   // Try and add missing hits that are just across the SM gap
05103   
05104   int PlanesSinceAdded, CurrentPlane(0), HitsAdded(0);
05105   double CurrentZPos, TargetTPos;
05106   double TrkBegZPos, TrkBegTPos, TrkBegDir(0.);
05107   double TrkEndZPos, TrkEndTPos, TrkEndDir(0.);
05108   double Tolerance(0.);
05109 
05110   double MinDistanceToHit, DistanceToCurrentHit;
05111   double centre, extrem1, extrem2;
05112   unsigned int nhits; 
05113 
05114   double z, t, w, sw, swx, swx2, swy, swyx;
05115   bool ConsiderHit;
05116   
05117   int PlaneView=Trk->GetPlaneView();
05118 
05119   // If we want to look back into SM 1
05121   if(Trk->GetBegPlane()>248 && Trk->GetBegPlane()<=256) {
05122               
05123     if(PlaneView==0) {CurrentPlane=248;} else if(PlaneView==1) {CurrentPlane=247;}
05124     PlanesSinceAdded=0;
05125     TrkBegZPos=Trk->GetBegZPos();
05126     TrkBegTPos=Trk->GetBegTPos();
05127  
05128 
05129     // Get beginning direction
05131     z=0.; t=0.; sw=0.; swx=0.; swx2=0.; swy=0.; swyx=0.;
05132      
05133     // Include first few hits in track
05135     for(unsigned int i=0; i<Trk->GetEntries(); ++i) {
05136       HitCam* hit = Trk->GetHit(i);
05137 
05138       if(hit->GetPlane()<Trk->GetBegPlane()+8) {
05139         z=hit->GetZPos(); t=hit->GetTPos(); w=hit->GetCharge();
05140         sw+=w; swx+=w*z; swx2+=w*z*z; swy+=w*t; swyx+=w*t*z;  
05141       }
05142     }
05143     // Use result so far to define a tolerance
05144     if((swx*swx-sw*swx2)!=0) {TrkBegDir = (swx*swy-sw*swyx)/(swx*swx-sw*swx2); Tolerance = 0.2 + fabs(TrkBegDir);}
05146 
05147               
05148     // Look at some of the relevant hits across the gap
05150     for(int i=CurrentPlane; i>CurrentPlane-8; i-=2) {
05151       for(unsigned int j=0; j<AllHitBank[i].size(); ++j) {
05152         HitCam* hit = AllHitBank[i][j];
05153           
05154         z=hit->GetZPos(); t=hit->GetTPos(); w=hit->GetCharge();
05155 
05156         // If hit is within tolerance region, include with weight 0.5
05157         if(fabs(t-(TrkBegTPos+TrkBegDir*(z-TrkBegZPos)))<Tolerance) {
05158           sw+=w; swx+=w*z; swx2+=w*z*z; swy+=w*t; swyx+=w*t*z;  
05159         }
05160       }
05161     }
05163 
05164     // Get results of total fit
05165     if((swx*swx-sw*swx2)!=0) {TrkBegDir = (swx*swy-sw*swyx)/(swx*swx-sw*swx2);}
05167 
05168                       
05169 
05170     // Look to add the hits
05172     while(CurrentPlane>0 && PlanesSinceAdded<10 && HitsAdded<4) {
05173                 
05174       nhits=AllHitBank[CurrentPlane].size();
05175                 
05176       if(nhits>0) {
05177         CurrentZPos=AllHitBank[CurrentPlane][0]->GetZPos();
05178 
05179         HitCam* BestHit = 0;
05180         MinDistanceToHit=3.*StripWidth;
05181 
05182         for(unsigned int j=0; j<nhits; ++j) {
05183           // Don't add a hit that is already in another track in the slice
05184           ConsiderHit=true;
05185           for(unsigned int p=0; p<HitsInTracks[PlaneView].size(); ++p) {
05186             if(AllHitBank[CurrentPlane][j]==HitsInTracks[PlaneView][p]) {ConsiderHit=false; break;}
05187           }
05188           if(ConsiderHit==false) {continue;}
05189 
05190 
05191           // Compare transverse positions
05192           TargetTPos=TrkBegTPos+TrkBegDir*(CurrentZPos-TrkBegZPos);
05193 
05194           centre=AllHitBank[CurrentPlane][j]->GetTPos();
05195           extrem1=centre+(0.055*TrkBegDir);
05196           extrem2=centre-(0.055*TrkBegDir);
05197                     
05198           DistanceToCurrentHit=min(fabs(centre-TargetTPos),
05199                                    min(fabs(extrem1-TargetTPos),fabs(extrem2-TargetTPos)));
05200 
05201           if(DistanceToCurrentHit<MinDistanceToHit) {
05202             MinDistanceToHit=DistanceToCurrentHit; 
05203             BestHit=AllHitBank[CurrentPlane][j]; 
05204             PlanesSinceAdded=0;
05205           }
05206         }
05207 
05208         if(BestHit) {Trk->AddHit(BestHit);}
05209       }
05210       else {PlanesSinceAdded+=2;}
05211       CurrentPlane-=2;
05212     }
05214   }
05216 
05217 
05218 
05219 
05220   // If we want to look forward into SM 2
05222   if(Trk->GetEndPlane()>=242 && Trk->GetEndPlane()<250) {
05223         
05224     if(PlaneView==0) {CurrentPlane=251;} else if(PlaneView==1) {CurrentPlane=250;}
05225     PlanesSinceAdded=0;
05226     TrkEndZPos=Trk->GetEndZPos();
05227     TrkEndTPos=Trk->GetEndTPos();
05228         
05229     
05230     // Get end direction
05232     z=0.; t=0.; sw=0.; swx=0.; swx2=0.; swy=0.; swyx=0.;
05233      
05234     // Include last few hits in track
05236     for(unsigned int i=0; i<Trk->GetEntries(); ++i) {
05237       HitCam* hit = Trk->GetHit(i);
05238 
05239       if(hit->GetPlane()>Trk->GetEndPlane()-8) {
05240         z=hit->GetZPos(); t=hit->GetTPos(); w=hit->GetCharge();
05241         sw+=w; swx+=w*z; swx2+=w*z*z; swy+=w*t; swyx+=w*t*z; 
05242       }
05243     }
05244     // Use result so far to define a tolerance
05245     if((swx*swx-sw*swx2)!=0) {TrkEndDir = (swx*swy-sw*swyx)/(swx*swx-sw*swx2); Tolerance = 0.2 + fabs(TrkEndDir);}
05247               
05248 
05249     // Look at some of the relevant hits across the gap
05251     for(int i=CurrentPlane; i<CurrentPlane+8; i+=2) {
05252       for(unsigned int j=0; j<AllHitBank[i].size(); ++j) {
05253         HitCam* hit = AllHitBank[i][j];
05254           
05255         z=hit->GetZPos(); t=hit->GetTPos(); w=hit->GetCharge();
05256 
05257         // If hit is within tolerance region, include with weight 0.5
05258         if(fabs(t-(TrkEndTPos+TrkEndDir*(z-TrkEndZPos)))<Tolerance) {
05259           sw+=w; swx+=w*z; swx2+=w*z*z; swy+=w*t; swyx+=w*t*z;  
05260         }
05261       }
05262     }
05264 
05265     // Get results of total fit
05266     if((swx*swx-sw*swx2)!=0) {TrkEndDir = (swx*swy-sw*swyx)/(swx*swx-sw*swx2);}
05268   
05269     
05270 
05271     // Look at hits in region
05273     while(CurrentPlane<500 && PlanesSinceAdded<10 && HitsAdded<4) {
05274 
05275       nhits=AllHitBank[CurrentPlane].size();
05276         
05277       if(nhits>0) {
05278         CurrentZPos=AllHitBank[CurrentPlane][0]->GetZPos();
05279 
05280         HitCam* BestHit = 0;
05281         MinDistanceToHit=3.*StripWidth;
05282                   
05283         for(unsigned int j=0; j<nhits; ++j) {
05284           // Don't add a hit that is already in another track in the slice
05285           ConsiderHit=true;
05286           for(unsigned int p=0; p<HitsInTracks[PlaneView].size(); ++p) {
05287             if(AllHitBank[CurrentPlane][j]==HitsInTracks[PlaneView][p]) {ConsiderHit=false; break;}
05288           }
05289           if(ConsiderHit==false) {continue;}
05290 
05291 
05292           // Compare transverse positions
05293           TargetTPos=TrkEndTPos+TrkEndDir*(CurrentZPos-TrkEndZPos);
05294 
05295           centre=AllHitBank[CurrentPlane][j]->GetTPos();
05296           extrem1=centre+(0.055*TrkEndDir);
05297           extrem2=centre-(0.055*TrkEndDir);
05298                     
05299           DistanceToCurrentHit=min(fabs(centre-TargetTPos),
05300                                    min(fabs(extrem1-TargetTPos),fabs(extrem2-TargetTPos)));
05301 
05302           if(DistanceToCurrentHit<MinDistanceToHit) {
05303             MinDistanceToHit=DistanceToCurrentHit; 
05304             BestHit=AllHitBank[CurrentPlane][j]; 
05305             PlanesSinceAdded=0;
05306           }
05307         }
05308         
05309         if(BestHit) {Trk->AddHit(BestHit);}
05310       }
05311       else {PlanesSinceAdded+=2;}
05312       CurrentPlane+=2;
05313     }
05315   }
05317 
05318   return;
05319 }
05321 
05322 
05323 
05325 void AlgTrackCamList::ClearUp()
05326 {
05327   // Reset containers and tidy memory usage
05328   unsigned int i, j;
05329 
05330   TempTrack[0].clear(); TempTrack[1].clear();
05331   ViewSegBank[0].clear(); ViewSegBank[1].clear();
05332   HitsInTracks[0].clear(); HitsInTracks[1].clear(); 
05333 
05334   for (i=0; i<2; ++i) {
05335     for(j=0; j<FinalTrackBank[i].size(); ++j) {delete FinalTrackBank[i][j];}
05336     FinalTrackBank[i].clear();
05337   }
05338 
05339 
05340   for (i=0; i<500; ++i) {
05341     for(j=0; j<AllHitBank[i].size(); ++j) {if(AllHitBank[i][j]) delete AllHitBank[i][j];}
05342     AllHitBank[i].clear();
05343     HitBank[i].clear();
05344 
05345     for(j=0; j<ClusterBank[i].size(); ++j) {if(ClusterBank[i][j]) delete ClusterBank[i][j];}
05346     ClusterBank[i].clear();
05347 
05348     for(j=0; j<ClusterList[i].size(); ++j) {if(ClusterList[i][j]) delete ClusterList[i][j];}
05349     ClusterList[i].clear();
05350 
05351     for(j=0; j<SegmentBank[i].size(); ++j) {if(SegmentBank[i][j]) delete SegmentBank[i][j];}
05352     SegmentBank[i].clear();
05353 
05354     for(j=0; j<NDSegmentBank[i].size(); ++j) {if(NDSegmentBank[i][j]) delete NDSegmentBank[i][j];}
05355     NDSegmentBank[i].clear();
05356   }
05357 
05358 }
05360 
05361 
05362 
05364 void AlgTrackCamList::MatchUV(TrackCam* trku, TrackCam* trkv)
05365 {
05366   // Initial check and declarations
05367   if(PECut<1.) {return;}
05368 
05369   vector<HitCam*> UTrack[500];
05370   vector<HitCam*> VTrack[500];
05371 
05372 
05373   // Store track hits  
05375   for(unsigned int i=0; i<trku->GetEntries(); ++i) {
05376     HitCam* hit = trku->GetHit(i);
05377     UTrack[hit->GetPlane()].push_back(hit);
05378   }
05379 
05380   for(unsigned int i=0; i<trkv->GetEntries(); ++i) {
05381     HitCam* hit = trkv->GetHit(i);
05382     VTrack[hit->GetPlane()].push_back(hit);
05383   }
05385 
05386 
05387   // Find levels of overlap
05389   int MinUPlane=500, MaxUPlane=-20;
05390   int MinUPlaneGTPECut=500, MaxUPlaneGTPECut=-20;
05391 
05392   int MinVPlane=500, MaxVPlane=-20;
05393   int MinVPlaneGTPECut=500, MaxVPlaneGTPECut=-20;
05394 
05395   bool GTPECut=false, ConsiderHit=true, LowPH=false;
05396   double PredictedTPos=0; int LastPlaneAdded;
05397 
05398   for(int i=0; i<500; ++i) {
05399     // For U
05400     if(UTrack[i].size()>0) {
05401       if(i<MinUPlane) {MinUPlane=i;}
05402       if(i>MaxUPlane) {MaxUPlane=i;}
05403 
05404       GTPECut=false;
05405       
05406       for(unsigned int j=0; j<UTrack[i].size(); ++j) {
05407         if(UTrack[i][j]->GetCharge()>PECut) {GTPECut=true; break;}
05408       }
05409 
05410       if(GTPECut) {
05411         if(i<MinUPlaneGTPECut) {MinUPlaneGTPECut=i;}
05412         if(i>MaxUPlaneGTPECut) {MaxUPlaneGTPECut=i;}    
05413       }
05414     }
05415 
05416     // For V
05417     if(VTrack[i].size()>0) {
05418       if(i<MinVPlane) {MinVPlane=i;}
05419       if(i>MaxVPlane) {MaxVPlane=i;}
05420 
05421       GTPECut=false;
05422 
05423       for(unsigned int j=0; j<VTrack[i].size(); ++j) {
05424         if(VTrack[i][j]->GetCharge()>PECut) {GTPECut=true; break;}
05425       }
05426 
05427       if(GTPECut) {
05428         if(i<MinVPlaneGTPECut) {MinVPlaneGTPECut=i;}
05429         if(i>MaxVPlaneGTPECut) {MaxVPlaneGTPECut=i;}
05430       }
05431     }
05432   }
05434 
05435 
05436 
05437 
05438   // Carry out the PH dependent UV match
05439   //
05440   // Two cases:
05441   // 1. Have extended too far in one view, including low PH strips
05442   //
05443   // 2. Have missed hits in one view and need to add them
05444 
05445   // Beginning
05447   if(abs(MinUPlane-MinVPlane)>8) {
05448 
05449     if(MinUPlane<MinVPlane) {
05450       // Removing hits from beginning of u track
05452       if(MinVPlane-MinUPlaneGTPECut<8) {
05453         
05454         for(int i=MinUPlane; i<MinUPlaneGTPECut; ++i) {
05455           for(unsigned int j=0; j<UTrack[i].size(); ++j) {
05456             UTrack[i][j]->SetUID(-1);
05457           }
05458         }
05459       }
05461 
05462 
05463       // Adding hits to beginning of v track
05465       else {
05466         LastPlaneAdded=MinVPlane;
05467 
05468         for(int i=MinVPlane-1; i>=MinUPlane-6; --i) {
05469           if(i<0 || i>120 || LastPlaneAdded-i>30) {break;}
05470 
05471           if((AllHitBank[i].size()==1 || HitBank[i].size()==1) && AllHitBank[i][0]->GetPlaneView()==1) {
05472 
05473             PredictedTPos=trkv->GetBegTPos()+trkv->GetBegDir()*(AllHitBank[i][0]->GetZPos()-trkv->GetBegZPos());
05474 
05475             HitCam* hit = 0;
05476             if(HitBank[i].size()==1) {hit=HitBank[i][0]; LowPH=false;}
05477             else {hit=AllHitBank[i][0]; LowPH=true;}
05478 
05479             // Don't add a hit that is already in another track in the slice
05480             ConsiderHit=true;
05481             for(unsigned int p=0; p<HitsInTracks[1].size(); ++p) {
05482               if(hit==HitsInTracks[1][p]) {ConsiderHit=false; break;}
05483             }
05484 
05485             // Check to see if it is genuinely in a clean +/-5 plane instrumented part of detector
05486             if(ConsiderHit) {
05487               for(int q=-2; q<=2; ++q) {
05488                 if(!LowPH) {for(int q=-1; q<=1; ++q) {if(q!=0 && HitBank[i+2*q].size()>0) {ConsiderHit=false; break;}}}
05489                 else {for(int q=-1; q<=1; ++q) {if(q!=0 && AllHitBank[i+2*q].size()>0) {ConsiderHit=false; break;}}}
05490               }
05491             }
05492 
05493             if(ConsiderHit==false) {continue;}
05494 
05495             if(fabs(hit->GetTPos()-PredictedTPos)<0.4) {trkv->AddHit(hit); LastPlaneAdded=i;}
05496           }      
05497         }
05498       }
05500     }
05501 
05502     else {
05503       // Removing hits from beginning of V track
05505       if(MinUPlane-MinVPlaneGTPECut<8) {
05506         
05507         for(int i=MinVPlane; i<MinVPlaneGTPECut; ++i) {
05508           for(unsigned int j=0; j<VTrack[i].size(); ++j) {
05509             VTrack[i][j]->SetUID(-1);
05510           }
05511         }
05512       }
05514 
05515 
05516       // Adding hits to beginning of u track
05518       else {
05519         LastPlaneAdded=MinUPlane;
05520 
05521         for(int i=MinUPlane-1; i>=MinVPlane-6; --i) {
05522           if(i<0 || i>120 || LastPlaneAdded-i>30) {break;}
05523 
05524           if((AllHitBank[i].size()==1 || HitBank[i].size()==1) && AllHitBank[i][0]->GetPlaneView()==0) {
05525 
05526             PredictedTPos=trku->GetBegTPos()+trku->GetBegDir()*(AllHitBank[i][0]->GetZPos()-trku->GetBegZPos());
05527 
05528             HitCam* hit = 0;
05529             if(HitBank[i].size()==1) {hit=HitBank[i][0]; LowPH=false;}
05530             else {hit=AllHitBank[i][0]; LowPH=true;}
05531 
05532             // Don't add a hit that is already in another track in the slice
05533             ConsiderHit=true;
05534             for(unsigned int p=0; p<HitsInTracks[0].size(); ++p) {
05535               if(hit==HitsInTracks[0][p]) {ConsiderHit=false; break;}
05536             }
05537 
05538             // Check to see if it is genuinely in a clean +/-5 plane instrumented part of detector
05539             if(ConsiderHit) {
05540               if(!LowPH) {for(int q=-1; q<=1; ++q) {if(q!=0 && HitBank[i+2*q].size()>0) {ConsiderHit=false; break;}}}
05541               else {for(int q=-1; q<=1; ++q) {if(q!=0 && AllHitBank[i+2*q].size()>0) {ConsiderHit=false; break;}}}
05542             }
05543 
05544             if(ConsiderHit==false) {continue;}
05545 
05546             if(fabs(hit->GetTPos()-PredictedTPos)<0.4) {trku->AddHit(hit); LastPlaneAdded=i;}
05547           }
05548         }
05549       }
05551     }
05552   }
05554 
05555 
05556   // End
05558   if(abs(MaxUPlane-MaxVPlane)>8) {
05559 
05560     if(MaxUPlane>MaxVPlane) {
05561       // Removing hits from end of u track
05563       if(MaxUPlaneGTPECut-MaxVPlane<8) {
05564         
05565         for(int i=MaxUPlaneGTPECut+1; i<=MaxUPlane; ++i) {
05566           for(unsigned int j=0; j<UTrack[i].size(); ++j) {
05567             UTrack[i][j]->SetUID(-1);
05568           }
05569         }
05570       }
05572       
05573 
05574       // Adding hits to end of v track
05576       else {
05577         LastPlaneAdded=MaxVPlane;
05578 
05579         for(int i=MaxVPlane; i<MaxUPlane+6; ++i) {
05580           if(i<0 || i>120 || i-LastPlaneAdded>30) {break;}
05581 
05582           if((AllHitBank[i].size()==1 || HitBank[i].size()==1) && AllHitBank[i][0]->GetPlaneView()==1) {
05583 
05584             PredictedTPos=trkv->GetEndTPos()+trkv->GetEndDir()*(AllHitBank[i][0]->GetZPos()-trkv->GetEndZPos());
05585 
05586             HitCam* hit = 0;
05587             if(HitBank[i].size()==1) {hit=HitBank[i][0]; LowPH=false;}
05588             else {hit=AllHitBank[i][0]; LowPH=true;}
05589 
05590             // Don't add a hit that is already in another track in the slice
05591             ConsiderHit=true;
05592             for(unsigned int p=0; p<HitsInTracks[1].size(); ++p) {
05593               if(hit==HitsInTracks[1][p]) {ConsiderHit=false; break;}
05594             }
05595 
05596             // Check to see if it is genuinely in a clean +/-5 plane instrumented part of detector
05597             if(ConsiderHit) {
05598               if(!LowPH) {for(int q=-1; q<=1; ++q) {if(q!=0 && HitBank[i+2*q].size()>0) {ConsiderHit=false; break;}}}
05599               else {for(int q=-1; q<=1; ++q) {if(q!=0 && AllHitBank[i+2*q].size()>0) {ConsiderHit=false; break;}}}
05600             }
05601 
05602             if(ConsiderHit==false) {continue;}
05603 
05604             if(fabs(hit->GetTPos()-PredictedTPos)<0.4) {trkv->AddHit(hit); LastPlaneAdded=i;}
05605           }      
05606         }
05607       }
05609     }
05610     
05611     else {
05612       // Removing hits from end of v track
05614       if(MaxVPlaneGTPECut-MaxUPlane<8) {
05615         
05616         for(int i=MaxVPlaneGTPECut+1; i<=MaxVPlane; ++i) {
05617           for(unsigned int j=0; j<VTrack[i].size(); ++j) {
05618             VTrack[i][j]->SetUID(-1);
05619           }
05620         }
05621       }
05623       
05624 
05625       // Adding hits to end of u track
05627       else {
05628         LastPlaneAdded=MaxUPlane;
05629 
05630         for(int i=MaxUPlane; i<MaxVPlane+6; ++i) {
05631           if(i<0 || i>120 || i-LastPlaneAdded>30) {break;}
05632 
05633           if((AllHitBank[i].size()==1 || HitBank[i].size()==1) && AllHitBank[i][0]->GetPlaneView()==0) {
05634 
05635             PredictedTPos=trku->GetEndTPos()+trku->GetEndDir()*(AllHitBank[i][0]->GetZPos()-trku->GetEndZPos());
05636 
05637             HitCam* hit = 0;
05638             if(HitBank[i].size()==1) {hit=HitBank[i][0]; LowPH=false;}
05639             else {hit=AllHitBank[i][0]; LowPH=true;}
05640 
05641             // Don't add a hit that is already in another track in the slice
05642             ConsiderHit=true;
05643             for(unsigned int p=0; p<HitsInTracks[0].size(); ++p) {
05644               if(hit==HitsInTracks[0][p]) {ConsiderHit=false; break;}
05645             }
05646 
05647             // Check to see if it is genuinely in a clean +/-5 plane instrumented part of detector
05648             if(ConsiderHit) {
05649               if(!LowPH) {for(int q=-1; q<=1; ++q) {if(q!=0 && HitBank[i+2*q].size()>0) {ConsiderHit=false; break;}}}
05650               else {for(int q=-1; q<=1; ++q) {if(q!=0 && AllHitBank[i+2*q].size()>0) {ConsiderHit=false; break;}}}
05651             }
05652 
05653             if(ConsiderHit==false) {continue;}
05654 
05655             if(fabs(hit->GetTPos()-PredictedTPos)<0.4) {trku->AddHit(hit); LastPlaneAdded=i;}
05656           }      
05657         }
05658       }
05660     }
05661   }
05663 
05664 
05665   // Clear up and return
05666   for(int i=0; i<500; ++i) {UTrack[i].clear(); VTrack[i].clear();}
05667   
05668   return;
05669 }
05671 
05672 
05673 
05675 void AlgTrackCamList::Trace(const char * /* c */) const
05676 {
05677 }

Generated on Mon Feb 15 11:06:20 2010 for loon by  doxygen 1.3.9.1