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

AlgFitTrackCam.cxx

Go to the documentation of this file.
00001 
00002 // Package: CandFitTrackCam - A Simplified implementation of the Kalman filter
00003 //
00004 // AlgFitTrackCam.cxx
00005 //
00006 // marshall@hep.phy.cam.ac.uk
00008 
00009 // 10/19/2006
00010 // Latest version of the code. Includes ND Spectrometer Swim.
00011 //
00012 // Note: Sets all fitted track properties in CandFitTrackHandle,
00013 // CandTrackHandle, CandRecoHandle and CandHandle
00014 //
00015 
00016 #include <cassert>
00017 #include <cmath>
00018 
00019 #include "MessageService/MsgService.h"
00020 #include "MinosObjectMap/MomNavigator.h"
00021 
00022 #include "Algorithm/AlgConfig.h"
00023 #include "Algorithm/AlgFactory.h"
00024 #include "Algorithm/AlgHandle.h"
00025 
00026 #include "Candidate/CandContext.h"
00027 
00028 #include "CandFitTrackCam/AlgFitTrackCam.h"
00029 #include "CandFitTrackCam/AlgFitTrackCam.h"
00030 #include "CandFitTrackCam/CandFitTrackCamHandle.h"
00031 
00032 #include "Calibrator/Calibrator.h"
00033 
00034 #include "Validity/VldContext.h"
00035 
00036 #include "CandData/CandRecord.h"
00037 #include "CandData/CandHeader.h"
00038 
00039 #include "RecoBase/CandStrip.h"
00040 #include "RecoBase/CandStripHandle.h"
00041 #include "RecoBase/CandTrackHandle.h"
00042 #include "RecoBase/AlgTrack.h"
00043 #include "RecoBase/CandSliceHandle.h"
00044 #include "RecoBase/CandStripListHandle.h"
00045 #include "CandDigit/CandDigitListHandle.h"
00046 
00047 #include "BField/BField.h"
00048 
00049 #include "Swimmer/SwimGeo.h"
00050 #include "Swimmer/SwimSwimmer.h"
00051 #include "Swimmer/SwimStepper.h"
00052 #include "Swimmer/SwimPrintStepAction.h"
00053 #include "Swimmer/SwimParticle.h"
00054 #include "Swimmer/SwimZCondition.h"
00055 #include "Swimmer/SwimPlaneInterface.h"
00056 
00057 #include "GeoSwimmer/GeoSwimmer.h"
00058 #include "GeoSwimmer/GeoSwimParticle.h"
00059 #include "GeoSwimmer/GeoSwimZCondition.h"
00060 
00061 #include "UgliGeometry/UgliGeomHandle.h"
00062 
00063 #include "DataUtil/GetMomFromRange.h"
00064 
00065 #include <sys/time.h>
00066 
00067 ClassImp(AlgFitTrackCam)
00068 
00069   CVSID("$Id: AlgFitTrackCam.cxx");
00070 
00072 AlgFitTrackCam::AlgFitTrackCam()
00073 {
00074 }
00076 
00077 
00079 AlgFitTrackCam::~AlgFitTrackCam()
00080 {
00081 }
00083 
00084 
00086 void AlgFitTrackCam::RunAlg(AlgConfig & ac, 
00087                             CandHandle &ch, CandContext &cx)
00088 {
00089   // get alg parameters
00090   if(!ac.Get("UseGeoSwimmer",UseGeoSwimmer)) cout << "Couldn't Get\n";
00091   //  cout << "UseGeoSwimmer in AlgFitTrackCam::RunAlg " << UseGeoSwimmer << endl;
00092  // Standard set-up
00093 
00094 
00095   assert(ch.InheritsFrom("CandFitTrackCamHandle"));
00096   CandFitTrackCamHandle &cth = dynamic_cast<CandFitTrackCamHandle &>(ch);
00097   
00098   nbfield=0;
00099   bave=0;
00100   TIter FitTrackStripItr = cth.GetDaughterIterator();
00101   while(CandStripHandle* FitTrackStrip = dynamic_cast<CandStripHandle*>(FitTrackStripItr())) cth.RemoveDaughter(FitTrackStrip);
00102   
00103   assert(cx.GetDataIn());
00104   
00105   // Get the track from the track finder
00106   assert(cx.GetDataIn()->InheritsFrom("CandTrackHandle"));
00107   track = dynamic_cast<const CandTrackHandle*>(cx.GetDataIn());
00108   if( !track || track->GetNDaughters()<1 )  { return; }
00109   cth.SetFinderTrack((CandTrackHandle*)(track));
00110   
00111   const CandSliceHandle* slice = dynamic_cast<const CandSliceHandle*>(track->GetCandSlice());
00112   assert(slice);
00113   cth.SetCandSlice(slice);
00114   
00115   
00117   // Track fitter //
00119   // Switch for screen output
00120   debug=false;
00121   
00122   // Initialisations
00124   if( track->GetEndZ() > track->GetVtxZ() )  {ZIncreasesWithTime=true;}
00125   else {ZIncreasesWithTime=false;}
00126   
00127   SaveData=false;
00128   SwimThroughShower=false;
00129   PassTrack=true;
00130   
00131   MaxPlane=-20;
00132   MinPlane=500;
00133 
00134   DeltaZ=-99;
00135   DeltaPlane=-99;
00136   ShowerEntryPlane=-99;
00137   
00138   NIter=0; TotalNSwimFail=0; NumFinderStrips=0;
00139   
00140   for (unsigned int i=0; i<5; ++i) {
00141     x_k[i]=0; x_k_minus[i]=0; H_k[i]=0; K_k[i]=0;
00142     VtxCov[i]=-999; EndCov[i]=-999;
00143     for (unsigned int j=0; j<5; ++j) {
00144       C_k[i][j]=0; C_k_minus[i][j]=0; C_k_intermediate[i][j]=0;
00145       F_k[i][j]=0; F_k_minus[i][j]=0;
00146       Q_k[i][j]=0; Q_k_minus[i][j]=0;
00147       Identity[i][j]=0;
00148     }
00149   }
00150   
00151   Identity[0][0]=1; Identity[1][1]=1; Identity[2][2]=1; Identity[3][3]=1; Identity[4][4]=1; 
00153   
00154   
00155   // Set initial parameters
00157   x_k_minus[0]=track->GetVtxU();
00158   x_k_minus[1]=track->GetVtxV();
00159   if(track->GetVtxDirCosZ()!=0.) {
00160     x_k_minus[2]=track->GetVtxDirCosU()/track->GetVtxDirCosZ();
00161     x_k_minus[3]=track->GetVtxDirCosV()/track->GetVtxDirCosZ();
00162   }
00163   x_k_minus[4]=0.;
00164   x_k4_biased=0;
00166   
00167   
00168   // Get header information
00170   CandRecord* candrec = (CandRecord*)(cx.GetCandRecord());
00171   assert(candrec);
00172   
00173   vldc = (VldContext*)(candrec->GetVldContext());
00174   assert(vldc);
00175   
00176   CandHeader* candhead = (CandHeader*)(candrec->GetCandHeader());
00177   assert(candhead);
00178   
00179   MSG("AlgFitTrackCam",Msg::kDebug) << "RunAlg, New track, Run: " << candhead->GetRun() 
00180                                     << " Snarl: " << candhead->GetSnarl() << endl;
00182   
00183   
00184   // Run the high level methods
00186   InitialFramework(slice,cx);
00187   GetFitData(MinPlane,MaxPlane);
00188   RunTheFitter(cth);
00190   
00191   
00192   // Clear up
00194   if(vldc->GetDetector()==DetectorType::kNear) {CleanNDLists(cth,cx);}
00195   
00196   for (unsigned int i=0; i<490; ++i) {
00197     InitTrkStripData[i].clear();
00198     SlcStripData[i].clear();
00199     TrkStripData[i].clear();
00200     FilteredData[i].clear();
00201   }
00203 }
00205 
00206 
00207 
00209 void AlgFitTrackCam::InitialFramework(const CandSliceHandle* slice,CandContext &cx)
00210 {
00211   // Store CandStripHandles and make the strips accessible by plane number
00212   DetectorType::Detector_t Detector = vldc->GetDetector();
00213 
00214   TIter SlcStripItr = slice->GetDaughterIterator();
00215   TIter TrkStripItr = track->GetDaughterIterator();
00216 
00217   
00218   // Store all strips in slice
00219   int SlicePlane; 
00220 
00221   while(CandStripHandle* SlcStrip = dynamic_cast<CandStripHandle*>(SlcStripItr()))
00222     {
00223       SlicePlane=SlcStrip->GetPlane();
00224       if(Detector==DetectorType::kNear && SlicePlane>=121) {continue;}
00225 
00226       StripStruct temp;
00227       temp.csh=SlcStrip;
00228      
00229       SlcStripData[SlicePlane].push_back(temp);
00230     }
00231   SlcStripItr.Reset();
00232 
00233 
00234   // Store all track strips found, except those in the Near Spectrometer
00235   int TrackPlane; 
00236   MeanTrackTime=0;
00237 
00238   while(CandStripHandle* TrkStrip = dynamic_cast<CandStripHandle*>(TrkStripItr()))
00239     {    
00240       TrackPlane=TrkStrip->GetPlane();
00241       if(Detector==DetectorType::kNear && TrackPlane>=121) {continue;}
00242 
00243       StripStruct temp;
00244       temp.csh=TrkStrip;
00245 
00246       InitTrkStripData[TrackPlane].push_back(temp);
00247       NumFinderStrips++;
00248       
00249       // Identify ends of initial track
00250       if (TrackPlane>MaxPlane) {MaxPlane=TrackPlane;}
00251       if (TrackPlane<MinPlane) {MinPlane=TrackPlane;}
00252 
00253       if(Detector==DetectorType::kNear) {MeanTrackTime+=NDStripBegTime(TrkStrip);}
00254     }
00255   TrkStripItr.Reset();
00256 
00257   // For DeMuxing ND Spectrometer
00258   if(Detector==DetectorType::kNear) {
00259     if(NumFinderStrips!=0) {MeanTrackTime/=double(NumFinderStrips);}
00260     GenerateNDSpectStrips(slice,cx);
00261   }
00262 
00263 
00264 } 
00266 
00267 
00268 
00270 void AlgFitTrackCam::ShowerStrips()
00271 {
00272   MSG("AlgFitTrackCam",Msg::kDebug) << "ShowerStrips, Look for large vertex shower" << endl;
00273      
00274   // Initialisations
00275   int Increment; int NumberOfStrips;
00276   int Plane; int NewPlane;
00277 
00278   int VtxShwWindow=8; 
00279   int StripsForShw=4;
00280   double PEThreshold=2.;
00281 
00282   if(ZIncreasesWithTime==true) {Plane=MinPlane; Increment=1;}
00283   else {Plane=MaxPlane; Increment=-1;}
00284   NewPlane=Plane;
00285 
00286 
00287   // Identify any vertex showers
00289   while(abs(Plane-NewPlane)<=VtxShwWindow && NewPlane>=MinPlane && NewPlane<=MaxPlane) {
00290 
00291     if(SlcStripData[NewPlane].size()>0) {
00292       NumberOfStrips=0;
00293 
00294 
00295       // Set the number of hits on a plane required for the plane to be identified as 'in the 
00296       // shower'. We account for the gradient of the track, with the factor of 0.25 representing
00297       // the approximate ratio of strip thickness to strip width.
00298       if(FilteredData[NewPlane].size()>0) {
00299         if(SlcStripData[NewPlane][0].csh->GetPlaneView()==2) {
00300           StripsForShw=min(7,int( 4+(0.25*fabs(FilteredData[NewPlane][0].x_k2)) ));
00301         }
00302         else {StripsForShw=min(7,int( 4+(0.25*fabs(FilteredData[NewPlane][0].x_k3)) ));}
00303       }
00304       else {StripsForShw=4;}
00305 
00306 
00307       // Count number of strips on plane with greater than 2PEs
00308       for(unsigned int j=0; j<SlcStripData[NewPlane].size(); ++j) {
00309         if(SlcStripData[NewPlane][j].csh->GetCharge()>PEThreshold) {NumberOfStrips++;}
00310       }
00311 
00312 
00313       // If a vertex shower is found, note that we should use the Swimmer
00314       // to find the most likely track strips inside the shower
00315       if(NumberOfStrips>=StripsForShw) {ShowerEntryPlane=NewPlane; SwimThroughShower=true; break;}
00316       
00317       NewPlane+=Increment;
00318     }
00319     else {NewPlane+=Increment;}
00320   }
00322 
00323 
00324  
00325   // Find the plane at which the 'clean' section of track enters the shower
00327   if(SwimThroughShower==true) {
00328     NewPlane=ShowerEntryPlane+Increment;
00329     int PlanesSinceLastHit=0;
00330     int PlaneWindow=4;
00331 
00332     while(PlanesSinceLastHit<PlaneWindow && NewPlane>=MinPlane && NewPlane<=MaxPlane) {
00333       if(SlcStripData[NewPlane].size()>0) {
00334         NumberOfStrips=0;
00335 
00336         // Account for gradient of track, as before
00337         if(FilteredData[NewPlane].size()>0) { 
00338           if(SlcStripData[NewPlane][0].csh->GetPlaneView()==2) {
00339             StripsForShw=min(7,int(4+(0.25*fabs(FilteredData[NewPlane][0].x_k2)) ));
00340           }
00341           else {StripsForShw=min(7,int(4+(0.25*fabs(FilteredData[NewPlane][0].x_k3)) ));}
00342         }
00343         else {StripsForShw=4;}
00344 
00345 
00346         // Count number of strips on plane with greater than 2PEs
00347         for(unsigned int j=0; j<SlcStripData[NewPlane].size(); ++j) {
00348           if(SlcStripData[NewPlane][j].csh->GetCharge()>PEThreshold) {NumberOfStrips++;}
00349         }
00350         if(NumberOfStrips>=StripsForShw) {
00351           ShowerEntryPlane=NewPlane; NewPlane+=Increment; PlanesSinceLastHit=0;
00352         }
00353         else {PlanesSinceLastHit++; NewPlane+=Increment;}
00354         
00355       }
00356       else {PlanesSinceLastHit++; NewPlane+=Increment;}
00357     }
00358   }
00360 }
00362 
00363 
00364 
00366 void AlgFitTrackCam::RunTheFitter(CandFitTrackCamHandle &cth)
00367 {
00368   MSG("AlgFitTrackCam",Msg::kDebug) << "RunTheFitter, Call methods in the appropriate order" << endl;
00369   GetInitialCovarianceMatrix(true);
00370   
00371   
00372   // Control the iterations backwards and forwards
00374   DetectorType::Detector_t Detector = vldc->GetDetector();
00375 
00376   // Control iterations over a track for which ZIncreasesWithTime
00377   if(ZIncreasesWithTime==true)
00378     {
00379       // First iteration
00380       NIter++;
00381   
00382       // Vtx to End
00383 
00384       SaveData=true; StoreFilteredData(MinPlane); 
00385       LastIteration=false;
00386       GoForwards(); ResetCovarianceMatrix();
00387       
00388 
00389       // End back to vtx, swimming through any large vtx shower
00390       ShowerStrips();  // Try to identify vtx showers, now we have an idea of gradient
00391       if(SwimThroughShower==true) {RemoveTrkHitsInShw();}
00392       
00393       for (unsigned int i=0; i<490; ++i) {FilteredData[i].clear();}
00394       StoreFilteredData(MaxPlane); GoBackwards();
00395       
00396       if(SwimThroughShower==true) {ShowerSwim();}
00397       ResetCovarianceMatrix();
00398 
00399       bool StripsFound = FindTheStrips(cth,false);
00400       
00401       // Second iteration
00402       if(StripsFound==true) { // Guard against finding no strips
00403         for(int nint=0;nint<=1;nint++){  
00404           NIter++;
00405           if(nint==1)LastIteration = true;        
00406           // Vtx to End again, identifying any strips in ND spectrometer
00407           for (unsigned int i=0; i<490; ++i) {TrkStripData[i].clear();} 
00408           GetFitData(MinPlane,MaxPlane);        
00409           SaveData=false; GoForwards();
00410           
00411           if(Detector==DetectorType::kNear && nint==0) {SpectrometerSwim(cth);}
00412           ResetCovarianceMatrix();
00413           
00414           // End back to vtx again
00415           for (unsigned int i=0; i<490; ++i) {FilteredData[i].clear();}
00416           if(nint==1) SaveData=true;  
00417           StoreFilteredData(MaxPlane);    
00418           GoBackwards();    ResetCovarianceMatrix();
00419           if(nint==0) x_k4_biased= x_k[4];
00420         }
00421       }
00422       else {PassTrack=false;}
00423     }
00424   
00425   
00426   // Control iterations over a track for which ZDecreasesWithTime
00427   else
00428     {
00429       // First iteration
00430       NIter++;
00431 
00432       // Vtx to End
00433       SaveData=true; StoreFilteredData(MaxPlane); 
00434       LastIteration=false;
00435 
00436       GoBackwards(); ResetCovarianceMatrix();
00437  
00438       // End back to vtx, swimming through any large vtx shower and
00439       // identifying any strips in ND spectrometer
00440       ShowerStrips();  // Try to identify vtx showers, now we have an idea of gradient
00441       if(SwimThroughShower==true) {RemoveTrkHitsInShw();}
00442 
00443       for (unsigned int i=0; i<490; ++i) {FilteredData[i].clear();}
00444       StoreFilteredData(MinPlane); GoForwards();
00445 
00446       if(SwimThroughShower==true) {ShowerSwim();}
00447 
00448       if(Detector==DetectorType::kNear) {SpectrometerSwim(cth);}
00449       ResetCovarianceMatrix();
00450 
00451       bool StripsFound = FindTheStrips(cth,false);
00452 
00453       // Second iteration
00454       if(StripsFound==true) { // Guard against finding no strips
00455         for(int nint=0;nint<=1;nint++){  
00456           if(nint==1)LastIteration = true;                
00457           NIter++;
00458           // Vtx to End again
00459           for (unsigned int i=0; i<490; ++i) {TrkStripData[i].clear();} 
00460           GetFitData(MinPlane,MaxPlane);          
00461           SaveData=false; GoBackwards(); ResetCovarianceMatrix();
00462           
00463           // End to Vtx again
00464           for (unsigned int i=0; i<490; ++i) {FilteredData[i].clear();}
00465           if(nint==1)SaveData=true;  
00466           StoreFilteredData(MinPlane);
00467           GoForwards(); ResetCovarianceMatrix();
00468           if(nint==0) x_k4_biased= x_k[4];
00469         }
00470       }
00471       else {PassTrack=false;}
00472     }
00474   
00475   
00476 
00477   // Organise the output
00479 
00480   // If the fit was successful
00481   if(x_k[4]!=0. && PassTrack==true) {
00482         
00483     //JAM modify tweak following range bias removal
00484     // Tweak q/p to remove offset
00485     //    x_k[4]*=1.01+(0.1*fabs(x_k[4]));
00486 
00487     x_k4_biased *=1.01+(0.1*fabs(x_k[4]));
00488     x_k[4] *=1.013;
00489 
00490     // Find final strips and add them to the fitted track
00491     FillGapsInTrack();
00492     bool FinalStripsFound = FindTheStrips(cth,true);
00493     
00494     // If final strips found, set the fitted track properties
00495     if(FinalStripsFound==true) {
00496 
00497       // Check there is >1 strip in each view. If not, then fail track.
00498       int NumInUView=0; int NumInVView=0;
00499       
00500       TIter FitTrackStripItr = cth.GetDaughterIterator();
00501       while(CandStripHandle* FitTrackStrip = dynamic_cast<CandStripHandle*>(FitTrackStripItr()))
00502         {
00503           if(FitTrackStrip->GetPlaneView()==2) {NumInUView++;}
00504           else if(FitTrackStrip->GetPlaneView()==3) {NumInVView++;}
00505           
00506           if(NumInUView>1 && NumInVView>1) {break;}
00507         }
00508       
00509       if(NumInUView>1 && NumInVView>1) {
00510         cth.SetPass(1);
00511         SetTrackProperties(cth);
00512       }
00513       else {PassTrack=false;}
00514       
00515     }
00516     // Otherwise fail the track at this final stage
00517     else {PassTrack=false;}
00518   }
00519   
00520   
00521   // If the fit has failed (e.g. q/p is zero and/or u, v are nonsense)
00522   if(x_k[4]==0. || PassTrack==false) {
00523  
00524     // Remove any existing strips in the failed fitted track
00525     vector<CandStripHandle*> Daughters;
00526 
00527     TIter FitTrackStripItr = cth.GetDaughterIterator();
00528     while(CandStripHandle* FitTrackStrip = dynamic_cast<CandStripHandle*>(FitTrackStripItr()))
00529       {Daughters.push_back(FitTrackStrip);}
00530 
00531     for(unsigned int i=0; i<Daughters.size(); ++i) {cth.RemoveDaughter(Daughters[i]);}
00532     Daughters.clear();
00533 
00534 
00535     // Put strips from track finder in failed fitted track
00536     TIter TrkStripItr = track->GetDaughterIterator();
00537     while(CandStripHandle* TrkStrip = dynamic_cast<CandStripHandle*>(TrkStripItr()))
00538       {cth.AddDaughterLink(*TrkStrip);}
00539     
00540     // Set position/direction properties using the finder track
00541     cth.SetPass(0); 
00542     cth.SetMomentumCurve(0.); cth.SetEMCharge(0); cth.SetVtxQPError(-999.);
00543     SetPropertiesFromFinderTrack(cth);
00544   }
00546 }  
00549 void AlgFitTrackCam::RemoveTrkHitsInShw()
00550 {
00551   // If the 'clean' section of track is large enough, remove the track finding
00552   // data for planes before the ShowerEntryPlane
00553   MSG("AlgFitTrackCam",Msg::kDebug) << "RemoveTrkHitsInShw, Discard track finding data in shower" << endl;
00554 
00555   int NumTrackStripsLeft=0;
00556   
00557   if(ZIncreasesWithTime==true) {
00558     for(int i=ShowerEntryPlane; i<=MaxPlane; ++i) {
00559       if(TrkStripData[i].size()>0) {NumTrackStripsLeft++;}
00560     }
00561   }
00562   else if(ZIncreasesWithTime==false) {
00563     for(int i=MinPlane; i<=ShowerEntryPlane; ++i) {
00564       if(TrkStripData[i].size()>0) {NumTrackStripsLeft++;}
00565     }
00566   }
00567   
00568   // Carry out removal if there will be 6 or more strips left afterwards
00569   if(NumTrackStripsLeft>5) { 
00570     if(ZIncreasesWithTime==true) {
00571       for(int i=MinPlane; i<=ShowerEntryPlane; ++i) {TrkStripData[i].clear();}
00572     }   
00573     else if(ZIncreasesWithTime==false) {
00574       for(int i=ShowerEntryPlane; i<=MaxPlane; ++i) {TrkStripData[i].clear();    }
00575     }
00576   } 
00577   // Otherwise note that we should not run the ShowerSwim method
00578   else {
00579     MSG("AlgFitTrackCam",Msg::kDebug) << "RemoveTrkHitsInShw, not enough hits after removal. Must use all finder data." << endl;
00580     SwimThroughShower=false;
00581   }
00582   
00583   
00584   // Find the new max and min planes
00585   MaxPlane=-20; MinPlane=500;
00586   for (int i=0; i<490; ++i) {   
00587     if(TrkStripData[i].size()>0) {
00588       if(i>MaxPlane) {MaxPlane=i;}
00589       if(i<MinPlane) {MinPlane=i;}
00590     }
00591   }
00592   
00593 }
00595 
00596 
00597 
00599 void AlgFitTrackCam::ShowerSwim()
00600 {
00601   // Method is called if we have a large shower near the track vertex
00602   //
00603   // The Swimmer is used to find the most likely track strip in the shower
00604   // and this strip is added to the fit
00605   MSG("AlgFitTrackCam",Msg::kDebug) << "ShowerSwim, improved track finding in shower" << endl;
00606 
00607   // Initialisations
00608   int Plane; int NewPlane;
00609   double StateVector[5]; double NState[5];
00610   bool GoForward; bool SwimBack;
00611   int PlanesSinceLastHit=0;
00612   int PlaneView;
00613   int Increment;
00614   
00615   double StripDistance; double MinDistanceToStrip;
00616   double StripWidth=4.108e-2;
00617 
00618 
00619   if(ZIncreasesWithTime==true) {GoForward=false; Plane=MinPlane; Increment=-1;}
00620   else {GoForward=true; Plane=MaxPlane; Increment=1;}
00621 
00622   NewPlane=Plane+Increment;
00623 
00624 
00625   // Continue until we reach a 4 plane window with no likely hit or we reach 
00626   // the end of the detector
00627   while(PlanesSinceLastHit<4 && NewPlane>0 && NewPlane<=485) {
00628     if(SlcStripData[NewPlane].size()>0) {
00629 
00630       if(SlcStripData[NewPlane][0].csh->GetPlaneView()==2) {PlaneView=0;}
00631       else {PlaneView=1;}
00632       
00633       for(int i=0; i<5; ++i) {StateVector[i]=x_k_minus[i];}
00634       SwimBack=Swim(StateVector, NState, Plane, NewPlane, GoForward);
00635       if(!SwimBack){break;}
00636       for(int i=0; i<5; ++i) {x_k[i]=NState[i];}
00637  
00638  
00639       // Find the closest strip (within a distance 'MinDistanceToStrip') and
00640       // temporarily store CandStripHandle
00641       // Results are very sensitive to value of MinDistanceToStrip
00642       CandStripHandle* CurrentStrip=0;
00643       MinDistanceToStrip=(1.5*StripWidth)+ fabs(0.0055*x_k[PlaneView+2]);
00644       
00645       for(unsigned int j=0; j<SlcStripData[NewPlane].size(); ++j) {
00646         StripDistance=fabs(SlcStripData[NewPlane][j].csh->GetTPos()-x_k[PlaneView]);
00647         
00648         if(StripDistance<MinDistanceToStrip) {
00649           MinDistanceToStrip=StripDistance;
00650           CurrentStrip=SlcStripData[NewPlane][j].csh;
00651         }
00652       }            
00653       
00654       // If we find a likely track strip, add it to the fit data and call the Kalman
00655       // update equations before repeating process to find next track strips in the shower
00656       if(CurrentStrip) {
00657         StripStruct temp;
00658         temp.csh = CurrentStrip;
00659         InitTrkStripData[NewPlane].push_back(temp);
00660         
00661         // Convert the strip to data required for Kalman fit
00662         GetFitData(NewPlane,NewPlane);
00663 
00664         // Carry out the Kalman fit
00665         if (PlaneView==1) {H_k[0]=0; H_k[1]=1; H_k[2]=0; H_k[3]=0; H_k[4]=0;}
00666         else {H_k[0]=1; H_k[1]=0; H_k[2]=0; H_k[3]=0; H_k[4]=0;}
00667         
00668         bool CombiPropagatorOk=GetCombiPropagator(Plane,NewPlane,GoForward);
00669         
00670         if(CombiPropagatorOk ) {
00671           GetNoiseMatrix(Plane,NewPlane);
00672           ExtrapCovMatrix();
00673           CalcKalmanGain(NewPlane);
00674           UpdateStateVector(Plane,NewPlane,GoForward);
00675           UpdateCovMatrix();
00676           MoveArrays();
00677           StoreFilteredData(NewPlane);
00678           
00679           if(ZIncreasesWithTime) {MinPlane=NewPlane; Plane=MinPlane;}
00680           else {MaxPlane=NewPlane; Plane=MaxPlane;}
00681           NewPlane=Plane+Increment;
00682           
00683           PlanesSinceLastHit=0;
00684         }
00685       }
00686       else {NewPlane+=Increment; PlanesSinceLastHit++;}
00687       
00688     }
00689     else {NewPlane+=Increment; PlanesSinceLastHit++;}
00690   }
00691   
00692   // Note that shower swim is complete
00693   SwimThroughShower=false;
00694 
00695 }
00697 
00698 
00699 
00701 void AlgFitTrackCam::GetFitData(int Plane1, int Plane2)
00702 {
00703   // Loop over the initial track strip data and create the final data for fitting
00704   MSG("AlgFitTrackCam",Msg::kDebug) << "GetFitData" << endl;
00705 
00706   // Initialisations
00707   double MisalignmentError=4e-6;  // Squared error for misalignment of strips
00708   double SumChargeTPos=0; double SumCharge=0; int MaxStrip=-20; int MinStrip=200;
00709   bool NewStripFound=true;
00710 
00711   int ThisStrip;
00712 
00713   // Get the data for region between the planes specified
00714   for(int i=Plane1; i<=Plane2; ++i) {
00715     if(InitTrkStripData[i].size()>0) {     
00716       
00717       // Find max and min strip numbers for strips in plane
00718       for(unsigned int j=0; j<InitTrkStripData[i].size(); ++j) {
00719         if(InitTrkStripData[i][j].csh->GetStrip()<MinStrip) {MinStrip=InitTrkStripData[i][j].csh->GetStrip();}
00720         if(InitTrkStripData[i][j].csh->GetStrip()>MaxStrip) {MaxStrip=InitTrkStripData[i][j].csh->GetStrip();}  
00721       }
00722 
00723 
00724       // Find continuous groups of strips
00726       NewStripFound=true;
00727       
00728       while(NewStripFound==true) {
00729         
00730         NewStripFound=false;
00731         
00732         for(unsigned int j=0; j<SlcStripData[i].size(); ++j) {
00733 
00734           ThisStrip=SlcStripData[i][j].csh->GetStrip();
00735 
00736           if( ThisStrip==(MaxStrip+1) ) {
00737             MaxStrip+=1;
00738             NewStripFound=true;
00739             
00740             InitTrkStripData[i].push_back(SlcStripData[i][j]);
00741           }
00742           
00743           if( ThisStrip==(MinStrip-1) ) {
00744             MinStrip-=1;
00745             NewStripFound=true;
00746             
00747             InitTrkStripData[i].push_back(SlcStripData[i][j]);
00748           }
00749         }
00750       }
00752 
00753 
00754 
00755       // Get the data for fitting
00757       for(unsigned int j=0; j<InitTrkStripData[i].size(); ++j) {
00758         SumCharge+=InitTrkStripData[i][j].csh->GetCharge();
00759         SumChargeTPos+=InitTrkStripData[i][j].csh->GetCharge()*InitTrkStripData[i][j].csh->GetTPos();
00760       }
00761 
00762       // Charge weighted TPos and Flat distribution error
00763       if(SumCharge!=0.) {
00764         TrkDataStruct temp;
00765         
00766         temp.ZPos=InitTrkStripData[i][0].csh->GetZPos();
00767         temp.PlaneView=InitTrkStripData[i][0].csh->GetPlaneView();
00768 
00769         temp.TPos=SumChargeTPos/SumCharge;
00770         temp.TPosError=( (1.406305333e-4 * (1 + MaxStrip-MinStrip) )+ MisalignmentError);
00771         
00772         TrkStripData[i].push_back(temp);
00773       }
00775 
00776 
00777       // Reset      
00778       SumChargeTPos=0; SumCharge=0; MaxStrip=-20; MinStrip=200;
00779     }
00780   }
00781   
00782 }
00784 
00785 
00786 
00788 void AlgFitTrackCam::FillGapsInTrack()
00789 {
00790   // If there is no filtered data for a plane (between MinPlane and MaxPlane),
00791   // but this plane has hits in the slice, we interpolate from the nearest 
00792   // state vectors
00793   //
00794   // As with all filtered data, the interpolated data will be compared to
00795   // strip positions in the FindTheStrips method
00796   MSG("AlgFitTrackCam",Msg::kDebug) << "FillGapsInTrack" << endl;
00797 
00798 
00799   int CurrentPlane; int ForwardsPlane; int BackwardsPlane;
00800   int Plane; int NewPlane;  bool GoForward;
00801   double StateVector[5]; double Prediction[5]; bool GetPrediction;
00802 
00803 
00804   for (int i=MinPlane; i<=MaxPlane; ++i) {   
00805     if(SlcStripData[i].size()>0) {
00806  
00807       if(FilteredData[i].size()==0) {
00808 
00809 
00810         // Find nearest filtered state vectors (within two planes) and ZPos differences
00812         // Forwards
00813         CurrentPlane=i+1; ForwardsPlane=-99;
00814 
00815         while(CurrentPlane<=MaxPlane && CurrentPlane<=(i+2)) {
00816           if(FilteredData[CurrentPlane].size()>0) {ForwardsPlane=CurrentPlane; break;}
00817           else {CurrentPlane++;}
00818         }
00819 
00820         // Backwards
00821         CurrentPlane=i-1; BackwardsPlane=-99;
00822 
00823         while(CurrentPlane>=MinPlane && CurrentPlane>=(i-2) ) {
00824           if(FilteredData[CurrentPlane].size()>0) {BackwardsPlane=CurrentPlane; break;}
00825           else {CurrentPlane--;}
00826         }
00828 
00829 
00830         // Find and store possible new filtered data, range and dS
00832         if(ForwardsPlane!=-99 && BackwardsPlane!=-99) {
00833 
00834           // Swimmer method
00835           GetPrediction=false;
00836           NewPlane=i;
00837 
00838           if(ZIncreasesWithTime==true) {Plane=ForwardsPlane; GoForward=false;}
00839           else{Plane=BackwardsPlane; GoForward=true;}
00840 
00841           if(FilteredData[Plane].size()>0) {
00842             StateVector[0] = FilteredData[Plane][0].x_k0;
00843             StateVector[1] = FilteredData[Plane][0].x_k1;
00844             StateVector[2] = FilteredData[Plane][0].x_k2;
00845             StateVector[3] = FilteredData[Plane][0].x_k3;
00846             StateVector[4] = FilteredData[Plane][0].x_k4;
00847             
00848             GetPrediction=Swim(StateVector, Prediction, Plane, NewPlane, GoForward);
00849             
00850             if(GetPrediction==true) {
00851               // Store possible new state vector
00852               FiltDataStruct temp;
00853               temp.x_k0 = Prediction[0];
00854               temp.x_k1 = Prediction[1];
00855               temp.x_k2 = Prediction[2]; 
00856               temp.x_k3 = Prediction[3];
00857               temp.x_k4 = Prediction[4];
00858               
00859               FilteredData[i].push_back(temp);
00860             }
00861           }
00862 
00863         }
00865       }
00866     }
00867   }
00868 
00869 }
00871 
00872 
00873 
00875 bool AlgFitTrackCam::FindTheStrips(CandFitTrackCamHandle &cth, bool MakeTheTrack)
00876 { 
00877   // Given output data from Kalman filter, we find the strips that match most closely
00878   // and store the CandStripHandles in plane order in InitTrkStripData
00879   //
00880   // At end of track fitting, method is called with MakeTheTrack==true, so fit track
00881   // strips are finalised
00882 
00883   // JM ADDED 6/07:  Add pulse height requirement for first 3 hits at track vertex, and 
00884   //                 remove isolated single hit at vertex. This reduces tendency to add 
00885   //                 extra hits upstream of vertex.
00886   
00887   // Initialisations
00889   for (unsigned int i=0; i<490; ++i) {InitTrkStripData[i].clear();}
00890 
00891   double Extrem1=0; double Extrem2=0;
00892   double StripCentre=0;
00893   double StripWidth=4.108e-2;
00894   double HalfStripWidth=0.5*StripWidth;
00895   double TwoStripWidth=2.*StripWidth;  
00896   double PEthresh = 4.0;
00897   double MinDistanceToStrip;
00899   
00900   int NoOfHitPlanes=0; int Counter=0; int PlanesAdded=0;
00901   Bool_t foundMIP=false;
00902   for (int i=MinPlane; i<=MaxPlane; ++i) {if(FilteredData[i].size()>0) {NoOfHitPlanes++;} }
00903 
00904   // Loop over the entire output from Kalman filter
00906   
00907   if(ZIncreasesWithTime==true){
00908     for (int i=MinPlane; i<=MaxPlane; ++i) {   
00909       if(FilteredData[i].size()>0) {
00910         Counter++;
00911         int numStrips = 0;
00912         
00913         // Mark the possible extremities in transverse position within scintillator
00914         // by multiplying gradient by half scintillator thickness and adding or subtracting
00915         if(SlcStripData[i][0].csh->GetPlaneView()==2) {
00916           Extrem1=FilteredData[i][0].x_k0 + (0.0055*FilteredData[i][0].x_k2);
00917           Extrem2=FilteredData[i][0].x_k0 - (0.0055*FilteredData[i][0].x_k2);
00918         }
00919         else {
00920           Extrem1=FilteredData[i][0].x_k1 + (0.0055*FilteredData[i][0].x_k3);
00921           Extrem2=FilteredData[i][0].x_k1 - (0.0055*FilteredData[i][0].x_k3);
00922         }
00923         
00924         // Add strips in the case that only one strip can have its centre within 
00925         // half a strip width of an extremal position...
00927         if(fabs(Extrem1-Extrem2)<StripWidth) {
00928           for(unsigned int j=0; j<SlcStripData[i].size(); ++j) {
00929             StripCentre=SlcStripData[i][j].csh->GetTPos();
00930             
00931             if(fabs(StripCentre-Extrem1)<HalfStripWidth || fabs(StripCentre-Extrem2)<HalfStripWidth) {
00932               if(Counter>1 || SlcStripData[i][j].csh->GetCharge()>PEthresh || foundMIP==true){
00933                 foundMIP=true;
00934                 if(MakeTheTrack==true) {cth.AddDaughterLink(*SlcStripData[i][j].csh);}        
00935                 InitTrkStripData[i].push_back(SlcStripData[i][j]);
00936         
00937                 if(j==0)PlanesAdded++;          
00938               } 
00939               
00940               numStrips++;
00941             }
00942           }
00943         }
00945         
00946         
00947         // ...Otherwise, cover the cases where multiple strips can have their centre
00948         // within half a strip width of an extremal position
00950         else {
00951           for(unsigned int j=0; j<SlcStripData[i].size(); ++j) {
00952             StripCentre=SlcStripData[i][j].csh->GetTPos();
00953             
00954             if( fabs(StripCentre-Extrem1)<HalfStripWidth || fabs(StripCentre-Extrem2)<HalfStripWidth
00955                 || (Extrem1>StripCentre && Extrem2<StripCentre) 
00956                 || (Extrem1<StripCentre && Extrem2>StripCentre) ) {
00957               if(Counter>1 || SlcStripData[i][j].csh->GetCharge()>PEthresh || foundMIP==true){
00958                 foundMIP=true;
00959                 if(MakeTheTrack==true) {cth.AddDaughterLink(*SlcStripData[i][j].csh);}
00960                 InitTrkStripData[i].push_back(SlcStripData[i][j]);
00961                 if(j==0)PlanesAdded++;
00962               }
00963               numStrips++;            
00964 
00965             }
00966           }
00967         }
00969         // If we have found no strips, we consider looking further, finding the closest  
00970         // strip within a distance 'MinDistanceToStrip' of an extremal position
00972         if(numStrips==0) {
00973           CandStripHandle* CurrentStrip=0;
00974           
00975           // Be more demanding near track vertex
00976           if(Counter>2) {
00977             MinDistanceToStrip = TwoStripWidth;
00978             if(MakeTheTrack==true) MinDistanceToStrip = 2*TwoStripWidth;
00979           }
00980           else {MinDistanceToStrip=StripWidth;}
00981           for(unsigned int j=0; j<SlcStripData[i].size(); ++j) {
00982             StripCentre=SlcStripData[i][j].csh->GetTPos();
00983             
00984             // Find the closest strip and temporarily store its CandStripHandle
00985             if(fabs(StripCentre-Extrem1)<MinDistanceToStrip) {
00986               MinDistanceToStrip=StripCentre-Extrem1;
00987               CurrentStrip=SlcStripData[i][j].csh;
00988             }
00989             if(fabs(StripCentre-Extrem2)<MinDistanceToStrip) {
00990               MinDistanceToStrip=StripCentre-Extrem2;
00991               CurrentStrip=SlcStripData[i][j].csh;
00992             }
00993           }
00994           
00995           // If we have found a strip then we add it
00996           if(CurrentStrip) {
00997             if(Counter>1 || CurrentStrip->GetCharge()>PEthresh || foundMIP==true){
00998               foundMIP=true;
00999               if(MakeTheTrack==true) {cth.AddDaughterLink(*CurrentStrip);}          
01000               StripStruct temp;
01001               temp.csh = CurrentStrip;
01002               InitTrkStripData[i].push_back(temp);
01003               PlanesAdded++;
01004             }
01005           }
01006         }
01008       }
01009       if(PlanesAdded==3 ){  // remove first hit if it is separated by >1 plane from second
01010         Int_t np = 0;
01011         Int_t planebuf[3];
01012         Int_t pln = MinPlane;
01013         while(np<3 && pln<490){
01014           if(InitTrkStripData[pln].size()>0){
01015             planebuf[np] = InitTrkStripData[pln][0].csh->GetPlane();
01016             np++;
01017           }
01018           pln++;
01019         }
01020         if(np==3){
01021           if(abs(planebuf[1]-planebuf[0])/abs(planebuf[2]-planebuf[1])>1.5){
01022             for(unsigned int j=0; j<InitTrkStripData[planebuf[0]].size(); ++j) {
01023               CandStripHandle* Strip = InitTrkStripData[planebuf[0]][j].csh;     
01024               cth.RemoveDaughter(Strip);
01025             }
01026             InitTrkStripData[planebuf[0]].clear();
01027           }
01028         }
01029       }
01030     }
01031   }
01032   else{
01033     for (int i=MaxPlane; i>=MinPlane; --i) {   
01034       if(FilteredData[i].size()>0) {
01035         Counter++;
01036         int numStrips=0;
01037         
01038         
01039         // Mark the possible extremities in transverse position within scintillator
01040         // by multiplying gradient by half scintillator thickness and adding or subtracting
01041         if(SlcStripData[i][0].csh->GetPlaneView()==2) {
01042           Extrem1=FilteredData[i][0].x_k0 + (0.0055*FilteredData[i][0].x_k2);
01043           Extrem2=FilteredData[i][0].x_k0 - (0.0055*FilteredData[i][0].x_k2);
01044         }
01045         else {
01046           Extrem1=FilteredData[i][0].x_k1 + (0.0055*FilteredData[i][0].x_k3);
01047           Extrem2=FilteredData[i][0].x_k1 - (0.0055*FilteredData[i][0].x_k3);
01048         }
01049         
01050         
01051         // Add strips in the case that only one strip can have its centre within 
01052         // half a strip width of an extremal position...
01054         if(fabs(Extrem1-Extrem2)<StripWidth) {
01055           for(unsigned int j=0; j<SlcStripData[i].size(); ++j) {
01056             StripCentre=SlcStripData[i][j].csh->GetTPos();
01057             
01058             if(fabs(StripCentre-Extrem1)<HalfStripWidth || fabs(StripCentre-Extrem2)<HalfStripWidth) {
01059               if(Counter>1 || SlcStripData[i][j].csh->GetCharge()>PEthresh || foundMIP){
01060                 foundMIP=true;
01061                 if(MakeTheTrack==true) {cth.AddDaughterLink(*SlcStripData[i][j].csh);}
01062                 InitTrkStripData[i].push_back(SlcStripData[i][j]);
01063                 numStrips++;
01064                 if(j==0)PlanesAdded++;
01065               }      
01066             }
01067           }
01068         }
01070         
01071         
01072         // ...Otherwise, cover the cases where multiple strips can have their centre
01073         // within half a strip width of an extremal position
01075         else {
01076           for(unsigned int j=0; j<SlcStripData[i].size(); ++j) {
01077             StripCentre=SlcStripData[i][j].csh->GetTPos();
01078             
01079             if( fabs(StripCentre-Extrem1)<HalfStripWidth || fabs(StripCentre-Extrem2)<HalfStripWidth
01080                 || (Extrem1>StripCentre && Extrem2<StripCentre) 
01081                 || (Extrem1<StripCentre && Extrem2>StripCentre) ) {
01082               if(Counter>1 || SlcStripData[i][j].csh->GetCharge()>PEthresh || foundMIP){
01083                 foundMIP=true;
01084                 if(MakeTheTrack==true) {cth.AddDaughterLink(*SlcStripData[i][j].csh);}          
01085                 InitTrkStripData[i].push_back(SlcStripData[i][j]);
01086                 numStrips++;
01087                 if(j==0)PlanesAdded++;
01088               }
01089             }
01090           }
01091         }
01093         
01094         // If we have found no strips, we consider looking further, finding the closest  
01095         // strip within a distance 'MinDistanceToStrip' of an extremal position
01097         if(numStrips==0) {
01098           CandStripHandle* CurrentStrip=0;
01099           
01100           // Be more demanding near track vertex
01101           if(Counter>2) {
01102             MinDistanceToStrip = TwoStripWidth;
01103             if(MakeTheTrack==true) MinDistanceToStrip = 2*TwoStripWidth;
01104           }
01105           
01106           for(unsigned int j=0; j<SlcStripData[i].size(); ++j) {
01107             StripCentre=SlcStripData[i][j].csh->GetTPos();
01108             
01109             // Find the closest strip and temporarily store its CandStripHandle
01110             if(fabs(StripCentre-Extrem1)<MinDistanceToStrip) {
01111               MinDistanceToStrip=StripCentre-Extrem1;
01112               CurrentStrip=SlcStripData[i][j].csh;
01113             }
01114             if(fabs(StripCentre-Extrem2)<MinDistanceToStrip) {
01115               MinDistanceToStrip=StripCentre-Extrem2;
01116               CurrentStrip=SlcStripData[i][j].csh;
01117             }
01118           }
01119           
01120           // If we have found a strip then we add it
01121           if(CurrentStrip) {
01122             if(Counter>1 || CurrentStrip->GetCharge()>PEthresh || foundMIP){
01123               foundMIP=true;    
01124               if(MakeTheTrack==true) {cth.AddDaughterLink(*CurrentStrip);}
01125               StripStruct temp;
01126               temp.csh = CurrentStrip;
01127               InitTrkStripData[i].push_back(temp);
01128               PlanesAdded++;
01129             }
01130           }
01131         }
01133       }
01134      if(PlanesAdded==3 ){  // remove first hit if it is separated by >1 plane from second
01135         Int_t np = 0;
01136         Int_t planebuf[3];
01137         Int_t pln = MaxPlane;
01138         while(np<3 && pln>=0){
01139           if(InitTrkStripData[pln].size()>0){
01140             planebuf[np]= InitTrkStripData[pln][0].csh->GetPlane();
01141             np++;
01142           }
01143           pln--;
01144         }
01145         if(np==3){
01146           if(abs(planebuf[1]-planebuf[0])/abs(planebuf[2]-planebuf[1])>1.5){
01147           for(unsigned int j=0; j<InitTrkStripData[planebuf[0]].size(); ++j) {
01148             CandStripHandle* Strip = InitTrkStripData[planebuf[0]][j].csh;       
01149             cth.RemoveDaughter(Strip);
01150           }
01151           InitTrkStripData[planebuf[0]].clear();
01152           }
01153         }
01154       }
01155     }  
01156   }
01158   
01159 
01160   // Find new max and min planes
01161   MaxPlane=-20; MinPlane=500;
01162   for (int i=0; i<490; ++i) {   
01163     if(InitTrkStripData[i].size()>0) {
01164       if(i>MaxPlane) {MaxPlane=i;}
01165       if(i<MinPlane) {MinPlane=i;}
01166     }
01167   }
01168 
01169   if(MaxPlane==-20 || MinPlane==500) {return false;}
01170   else {return true;}
01171 
01172 }
01174 
01175 
01176 
01178 void AlgFitTrackCam::GoForwards()
01179 { 
01180   // Carry out the Kalman fit along the track in the direction of increasing z
01181   MSG("AlgFitTrackCam",Msg::kDebug) << "GoForwards, carry out fit in positive z direction" << endl;
01182 
01183   // JAM in 2nd iteration, stop when end of range is reached.
01184  
01185   Int_t StartPlane = MinPlane; Int_t EndPlane=MaxPlane;
01186   if(!ZIncreasesWithTime){
01187     StartPlane = EndofRangePlane;
01188   }
01189   else EndofRangePlane = MaxPlane;
01190 
01191   for (int i=StartPlane; i<=EndPlane; ++i) {
01192     EndofRange = false;
01193     if (TrkStripData[i].size()>0) {
01194       if (PassTrack) {
01195         // Find Next Plane
01196         int NewPlane=-99;
01197         int k=(i+1);
01198         while (k<=MaxPlane) {
01199           if (TrkStripData[k].size()>0) {NewPlane=k; break;}
01200           ++k;
01201         }
01202         if (NewPlane!=-99) {
01203           // Define measurement function
01204           if (TrkStripData[NewPlane][0].PlaneView==3) {H_k[0]=0; H_k[1]=1; H_k[2]=0; H_k[3]=0; H_k[4]=0;}
01205           else if (TrkStripData[NewPlane][0].PlaneView==2)  {H_k[0]=1; H_k[1]=0; H_k[2]=0; H_k[3]=0; H_k[4]=0;}
01206           
01207           MSG("AlgFitTrackCam",Msg::kVerbose) << "GoForwards, Plane " << i << " ZPos " << TrkStripData[i][0].ZPos 
01208                                               << " PlaneView " << TrkStripData[i][0].PlaneView << endl
01209                                               << " NewPlane " << NewPlane << " NewZPos " << TrkStripData[NewPlane][0].ZPos 
01210                                               << " NewPlaneView " << TrkStripData[NewPlane][0].PlaneView << endl;
01211           
01212           bool CombiPropagatorOk=GetCombiPropagator(i,NewPlane,true);
01213           
01214           if(CombiPropagatorOk ) {
01215             GetNoiseMatrix(i,NewPlane);
01216             ExtrapCovMatrix();
01217             CalcKalmanGain(NewPlane);
01218             UpdateStateVector(i,NewPlane,true);
01219             UpdateCovMatrix();
01220             MoveArrays();
01221             if(SaveData) {StoreFilteredData(NewPlane);}
01222             MSG("AlgFitTrackCam",Msg::kVerbose) << "GoForwards, Filtered q/p " << x_k[4] << endl;
01223           }
01224           else {PassTrack=false;}
01225         }
01226         
01227       }
01228       else {MSG("AlgFitTrackCam",Msg::kDebug) << "GoForwards, Outside of detector - track failed" << endl;}
01229     }
01230     //JAM end of range found
01231     if(EndofRange && LastIteration && ZIncreasesWithTime){
01232       EndofRangePlane=i;
01233       break;
01234     }
01235   }
01236 
01237 
01238   // Store entries from covariance matrix for use in setting track properties
01239   if(NIter==2) {
01240     if(ZIncreasesWithTime==true) {
01241       EndCov[0]=C_k[0][0]; EndCov[1]=C_k[1][1];
01242       EndCov[2]=C_k[2][2]; EndCov[3]=C_k[3][3];
01243       EndCov[4]=C_k[4][4];
01244     }
01245     else {
01246       VtxCov[0]=C_k[0][0]; VtxCov[1]=C_k[1][1];
01247       VtxCov[2]=C_k[2][2]; VtxCov[3]=C_k[3][3];
01248       VtxCov[4]=C_k[4][4];
01249     }
01250   }
01251 
01252 }
01254 
01255 
01256 
01258 void AlgFitTrackCam::GoBackwards()
01259 { 
01260   // Carry out the Kalman fit along the track in the direction of decreasing z
01261   MSG("AlgFitTrackCam",Msg::kDebug) << "GoBackwards, carry out fit in negative z direction" << endl;
01262   Int_t StartPlane = MaxPlane; Int_t EndPlane=MinPlane;
01263   if(ZIncreasesWithTime){
01264     StartPlane = EndofRangePlane;
01265   }
01266   else EndofRangePlane = MinPlane;
01267  
01268   for (int i=StartPlane; i>=EndPlane; --i) {  
01269     if (TrkStripData[i].size()>0) {
01270       if (PassTrack) {
01271 
01272         //Find Prev Plane
01273         int NewPlane=-99;
01274         int k=(i-1);
01275         while (k>=MinPlane) {
01276           if (TrkStripData[k].size()>0) {NewPlane=k; break;}
01277           --k;
01278         }
01279         
01280         
01281         if (NewPlane!=-99) {
01282           // Define measurement function
01283           if (TrkStripData[NewPlane][0].PlaneView==3) {H_k[0]=0; H_k[1]=1; H_k[2]=0; H_k[3]=0; H_k[4]=0;}         else if (TrkStripData[NewPlane][0].PlaneView==2)  {H_k[0]=1; H_k[1]=0; H_k[2]=0; H_k[3]=0; H_k[4]=0;}
01284           
01285           MSG("AlgFitTrackCam",Msg::kVerbose) << "GoBackwards, Plane " << i << " ZPos " << TrkStripData[i][0].ZPos 
01286                                               << " PlaneView " << TrkStripData[i][0].PlaneView << endl
01287                                               << " NewPlane " << NewPlane << " NewZPos " << TrkStripData[NewPlane][0].ZPos 
01288                                               << " NewPlaneView " << TrkStripData[NewPlane][0].PlaneView << endl;
01289           
01290           bool CombiPropagatorOk=GetCombiPropagator(i,NewPlane,false);
01291           
01292           if(CombiPropagatorOk ) {
01293             GetNoiseMatrix(i,NewPlane);
01294             ExtrapCovMatrix();
01295             CalcKalmanGain(NewPlane);
01296             UpdateStateVector(i,NewPlane,false);
01297             UpdateCovMatrix();
01298             MoveArrays();
01299             if(SaveData) {StoreFilteredData(NewPlane);}
01300             MSG("AlgFitTrackCam",Msg::kVerbose) << "GoBackwards, Filtered q/p " << x_k[4] << endl;
01301           }
01302           else {PassTrack=false;}
01303         }
01304         
01305       }
01306       else {MSG("AlgFitTrackCam",Msg::kDebug) << "GoBackwards, Outside detector - track failed" << endl;}
01307     }
01308     //JAM end of range found
01309     if(EndofRange && LastIteration && !ZIncreasesWithTime){
01310       EndofRangePlane = i;
01311       break;
01312     }
01313 
01314   }
01315 
01316 
01317   // Store entries from covariance matrix for use in setting track properties
01318   if(NIter==2) {
01319     if(ZIncreasesWithTime==true) {
01320       VtxCov[0]=C_k[0][0]; VtxCov[1]=C_k[1][1];
01321       VtxCov[2]=C_k[2][2]; VtxCov[3]=C_k[3][3];
01322       VtxCov[4]=C_k[4][4];
01323     }
01324     else {
01325       EndCov[0]=C_k[0][0]; EndCov[1]=C_k[1][1];
01326       EndCov[2]=C_k[2][2]; EndCov[3]=C_k[3][3];
01327       EndCov[4]=C_k[4][4];
01328     }
01329   }
01330   
01331 }
01333 
01334 
01335 
01337 bool AlgFitTrackCam::GetCombiPropagator(const int Plane, const int NewPlane, const bool GoForward)
01338 {
01339   // Combination propagator, essentially same as SR propagator, but
01340   // generation of matrix reduces calls to swimmer by 80%
01341   MSG("AlgFitTrackCam",Msg::kDebug) << "GetCombiPropagator" << endl;
01342 
01343   for (int i=0; i<5; ++i) {
01344     for (int j=0; j<5; ++j) {
01345       F_k_minus[i][j]=0;  
01346     }
01347   }
01348 
01349   F_k_minus[0][0]=1; F_k_minus[1][1]=1; 
01350   F_k_minus[2][2]=1; F_k_minus[3][3]=1;
01351   
01352   DeltaZ=fabs(TrkStripData[NewPlane][0].ZPos-TrkStripData[Plane][0].ZPos);
01353   DeltaPlane=abs(NewPlane-Plane);
01354 
01355   // Swimmer section for last column
01356   double PState[5];  double NState[5];  double StateVector[5];
01357   double Increment=0.01;
01358   bool SwimInc=false; bool SwimDec=false;
01359   int nswimfail=0;
01360   
01361   if(GoForward==true) {F_k_minus[0][2]=DeltaZ; F_k_minus[1][3]=DeltaZ;}
01362   else if(GoForward==false) {F_k_minus[0][2]=-DeltaZ; F_k_minus[1][3]=-DeltaZ;}
01363   
01364   
01365   // Give swimmer fixed number of opportunities for successful swim
01366   while((SwimInc==false || SwimDec==false) && nswimfail<=10) {
01367     
01368     Increment=0.05*fabs(x_k_minus[4]); 
01369     if(Increment<.01) {Increment=.01;}
01370        
01371     for(int j=0; j<5; ++j) {StateVector[j]=x_k_minus[j];}  
01372     
01373     // Increment then swim
01374     StateVector[4]+=Increment;
01375     SwimInc=Swim(StateVector, NState, Plane, NewPlane, GoForward);
01376     
01377     StateVector[4]=x_k_minus[4];
01378     
01379     // Decrement then swim
01380     StateVector[4]-=Increment;
01381     SwimDec=Swim(StateVector, PState, Plane, NewPlane, GoForward);
01382     
01383     // If swim failed, double momentum and swim again
01384     if(SwimInc==false || SwimDec==false) {
01385       MSG("AlgFitTrackCam",Msg::kVerbose) << "GetCombiPropagator, Swim failed - Double momentum and swim again" << endl;
01386       x_k_minus[4]*=0.5;
01387       nswimfail++; TotalNSwimFail++;
01388       break;
01389     }
01390     
01391     // Form last row of propagator matrix.  Need to transpose to get proper Kalman F_k_minus
01392     else {
01393       if(Increment!=0.) {
01394         for(int j=0; j<5; ++j) {
01395           F_k_minus[j][4] = (NState[j]-PState[j]) / (2*Increment);
01396         }
01397       }
01398       else {F_k_minus[4][4]=1;}
01399     }
01400     
01401   } // End while statement
01402   
01403   if(nswimfail>10) {MSG("AlgFitTrackCam",Msg::kDebug) << "GetCombiPropagator, nswimfail>10, fail track" << endl; return false;}
01404 
01405 
01406   // Display
01407   if(debug) {
01408     cout << "Combi F_k_minus" << endl;
01409     for(int i=0; i<5; ++i) {  
01410       for(int j=0; j<5; ++j) {
01411         cout << F_k_minus[i][j] << " ";
01412       }
01413       cout << endl;
01414     }
01415   }
01416   
01417   return true;
01418 }
01420 
01421 
01422 
01424 bool AlgFitTrackCam::Swim(double* StateVector, double* Output, const int Plane, 
01425                           const int NewPlane,const bool GoForward, double* dS, double* Range, double* dE)
01426 {
01427   MSG("AlgFitTrackCam",Msg::kDebug) << "Swim" << endl;
01428 
01429   // Initialisations
01430   // customize for bfield scaling.
01431   BField * bf = new BField(*vldc,-1,0);
01432   SwimSwimmer* myswimmer = new SwimSwimmer(*vldc,bf);
01433   
01434   if(UseGeoSwimmer) GeoSwimmer::Instance()->Initialize(*vldc);
01435  
01436   double invSqrt2 = pow(1./2.,0.5);
01437   double charge = 0.;
01438   bool done = false;
01439     
01440   if(fabs(StateVector[4])>1.e-10) {
01441     double modp = fabs(1./StateVector[4]);
01442     
01443     // Fix, to account for fact the cosmic muons could move in direction of negative z
01444     if(ZIncreasesWithTime==false) {modp=-modp;}
01445     
01446     double dsdz = pow((1.+pow(StateVector[2],2)+pow(StateVector[3],2)),0.5);
01447     double dxdz = invSqrt2*(StateVector[2]-StateVector[3]);
01448     double dydz = invSqrt2*(StateVector[2]+StateVector[3]);
01449     
01450     // Set up current muon details
01451     if(StateVector[4]>0.) charge = 1.;
01452     else if(StateVector[4]<0.) charge = -1.;
01453     
01454     TVector3 position(invSqrt2*(StateVector[0]-StateVector[1]),
01455                       invSqrt2*(StateVector[0]+StateVector[1]),
01456                       SlcStripData[Plane][0].csh->GetZPos());
01457 
01458     TVector3 momentum(modp*(dxdz/dsdz),
01459                       modp*(dydz/dsdz),
01460                       modp/dsdz);
01461 
01462     TVector3 bfield = bf->GetBField(position);
01463     bave += TMath::Sqrt(bfield[0]*bfield[0]+bfield[1]*bfield[1]+bfield[2]*bfield[2]);
01464     nbfield++;
01465 
01466     SwimParticle muon(position,momentum);
01467     muon.SetCharge(charge);
01468     SwimZCondition zc(SlcStripData[NewPlane][0].csh->GetZPos());
01469     // Do the swim, accounting for direction of motion w.r.t time too
01470     if( (GoForward==true && ZIncreasesWithTime==true)  || (GoForward==false && ZIncreasesWithTime==false) ) {
01471       if(UseGeoSwimmer) {
01472         done = GeoSwimmer::Instance()->SwimForward(muon,SlcStripData[NewPlane][0].csh->GetZPos());
01473       } else {
01474         done = myswimmer->SwimForward(muon,zc);
01475       }
01476     }
01477     else if( (GoForward==true && ZIncreasesWithTime==false)  || (GoForward==false && ZIncreasesWithTime==true) ) {
01478       if(UseGeoSwimmer) {
01479         done = GeoSwimmer::Instance()->SwimBackward(muon,SlcStripData[NewPlane][0].csh->GetZPos());
01480       } else {
01481         done = myswimmer->SwimBackward(muon,zc);
01482       }
01483     }
01484     if(done==true) {
01485       if(muon.GetDirection().Z()!=0. && muon.GetMomentumModulus()!=0.) {
01486         Output[0]=invSqrt2*(muon.GetPosition().Y()+muon.GetPosition().X());
01487         Output[1]=invSqrt2*(muon.GetPosition().Y()-muon.GetPosition().X());
01488         Output[2]=invSqrt2*((muon.GetDirection().Y()/muon.GetDirection().Z())+(muon.GetDirection().X()/muon.GetDirection().Z()));
01489         Output[3]=invSqrt2*((muon.GetDirection().Y()/muon.GetDirection().Z())-(muon.GetDirection().X()/muon.GetDirection().Z()));
01490         Output[4]=muon.GetCharge()/muon.GetMomentumModulus();
01491         // Get range and dS from the Swimmer
01492         if(dS) {*dS=muon.GetS();} if(Range) {*Range=muon.GetRange();} if(dE){*dE=muon.GetMomentumModulus()-momentum.Mag();} 
01493       }
01494       else {done=false;}
01495     }
01496     
01497   }
01498 
01499   else{
01500     // If infinite momentum, use straight line extrapolation
01501     double delz = (SlcStripData[NewPlane][0].csh->GetZPos()-SlcStripData[Plane][0].csh->GetZPos());
01502     Output[0]=StateVector[0] + StateVector[2]*delz;
01503     Output[1]=StateVector[1] + StateVector[3]*delz;
01504     Output[2]=StateVector[2];
01505     Output[3]=StateVector[3];
01506     Output[4]=StateVector[4];
01507 
01508     done=true;
01509   }    
01510   
01511   delete myswimmer;
01512   delete bf;
01513   return done;
01514 }
01516 
01517 
01518 
01520 bool AlgFitTrackCam::Swim(double* StateVector, double* Output, const double z, 
01521                           const int NewPlane,const bool GoForward, double* dS, double* Range, double* dE)
01522 {
01523   MSG("AlgFitTrackCam",Msg::kDebug) << "Swim, specified starting Z" << endl;
01524 
01525   // Initialisations
01526   // customize for bfield scaling.
01527   BField * bf = new BField(*vldc,-1,0);
01528   SwimSwimmer* myswimmer = new SwimSwimmer(*vldc,bf);
01529   
01530   if(UseGeoSwimmer) GeoSwimmer::Instance()->Initialize(*vldc);
01531 
01532   double invSqrt2 = pow(1./2.,0.5);
01533   double charge = 0.;
01534   bool done = false;
01535     
01536   if(fabs(StateVector[4])>1.e-10) {
01537     double modp = fabs(1./StateVector[4]);
01538     
01539     // Fix, to account for fact the cosmic muons could move in direction of negative z
01540     if(ZIncreasesWithTime==false) {modp=-modp;}
01541     
01542     double dsdz = pow((1.+pow(StateVector[2],2)+pow(StateVector[3],2)),0.5);
01543     double dxdz = invSqrt2*(StateVector[2]-StateVector[3]);
01544     double dydz = invSqrt2*(StateVector[2]+StateVector[3]);
01545     
01546     // Set up current muon details
01547     if(StateVector[4]>0.) charge = 1.;
01548     else if(StateVector[4]<0.) charge = -1.;
01549     
01550     TVector3 position(invSqrt2*(StateVector[0]-StateVector[1]),
01551                       invSqrt2*(StateVector[0]+StateVector[1]),
01552                       z);
01553 
01554     TVector3 momentum(modp*(dxdz/dsdz),
01555                       modp*(dydz/dsdz),
01556                       modp/dsdz);
01557     SwimParticle muon(position,momentum);
01558     muon.SetCharge(charge);
01559     SwimZCondition zc(SlcStripData[NewPlane][0].csh->GetZPos());
01560 
01561    
01562     // Do the swim, accounting for direction of motion w.r.t time too
01563     if( (GoForward==true && ZIncreasesWithTime==true)  || (GoForward==false && ZIncreasesWithTime==false) ) {
01564       if(UseGeoSwimmer) {
01565         done = GeoSwimmer::Instance()->SwimForward(muon,SlcStripData[NewPlane][0].csh->GetZPos());
01566       } else {
01567         done = myswimmer->SwimForward(muon,zc);
01568       } 
01569     }
01570     else if( (GoForward==true && ZIncreasesWithTime==false)  || (GoForward==false && ZIncreasesWithTime==true) ) {
01571       if(UseGeoSwimmer) {
01572         done = GeoSwimmer::Instance()->SwimBackward(muon,SlcStripData[NewPlane][0].csh->GetZPos());
01573 
01574       } else {
01575         done = myswimmer->SwimBackward(muon,zc);
01576       }     
01577     }
01578     if(done==true) {
01579       if(muon.GetDirection().Z()!=0. && muon.GetMomentumModulus()!=0.) {
01580         Output[0]=invSqrt2*(muon.GetPosition().Y()+muon.GetPosition().X());
01581         Output[1]=invSqrt2*(muon.GetPosition().Y()-muon.GetPosition().X());
01582         Output[2]=invSqrt2*((muon.GetDirection().Y()/muon.GetDirection().Z())+(muon.GetDirection().X()/muon.GetDirection().Z()));
01583         Output[3]=invSqrt2*((muon.GetDirection().Y()/muon.GetDirection().Z())-(muon.GetDirection().X()/muon.GetDirection().Z()));
01584         Output[4]=muon.GetCharge()/muon.GetMomentumModulus();
01585         // Get range and dS from the Swimmer
01586         if(dS) {*dS=muon.GetS();} if(Range) {*Range=muon.GetRange();} if(dE){*dE=muon.GetMomentumModulus()-momentum.Mag();} 
01587       }
01588       else {done=false;}
01589     }
01590     
01591   }
01592 
01593   else{
01594     // If infinite momentum, use straight line extrapolation
01595     double delz = (SlcStripData[NewPlane][0].csh->GetZPos()-z);
01596     Output[0]=StateVector[0] + StateVector[2]*delz;
01597     Output[1]=StateVector[1] + StateVector[3]*delz;
01598     Output[2]=StateVector[2];
01599     Output[3]=StateVector[3];
01600     Output[4]=StateVector[4];
01601 
01602     done=true;
01603   }    
01604   
01605   delete myswimmer;
01606   delete bf;
01607 
01608   return done;
01609 }
01611 
01612 
01613 
01615 bool AlgFitTrackCam::Swim(double* StateVector, double* Output, const int Plane, 
01616                           const double Zend,const bool GoForward, double* dS, double* Range, double* dE)
01617 {
01618   MSG("AlgFitTrackCam",Msg::kDebug) << "Swim, specified end Z" << endl;
01619 
01620   // Initialisations
01621   // customize for bfield scaling.
01622 
01623   BField * bf = new BField(*vldc,-1,0);
01624   SwimSwimmer* myswimmer = new SwimSwimmer(*vldc,bf);
01625 
01626   if(UseGeoSwimmer) GeoSwimmer::Instance()->Initialize(*vldc);
01627 
01628   double invSqrt2 = pow(1./2.,0.5);
01629   double charge = 0.;
01630   bool done = false;
01631     
01632   if(fabs(StateVector[4])>1.e-10) {
01633     double modp = fabs(1./StateVector[4]);
01634     
01635     // Fix, to account for fact the cosmic muons could move in direction of negative z
01636     if(ZIncreasesWithTime==false) {modp=-modp;}
01637     
01638     double dsdz = pow((1.+pow(StateVector[2],2)+pow(StateVector[3],2)),0.5);
01639     double dxdz = invSqrt2*(StateVector[2]-StateVector[3]);
01640     double dydz = invSqrt2*(StateVector[2]+StateVector[3]);
01641   
01642     // Set up current muon details
01643     if(StateVector[4]>0.) charge = 1.;
01644     else if(StateVector[4]<0.) charge = -1.;
01645     
01646     TVector3 position(invSqrt2*(StateVector[0]-StateVector[1]),
01647                       invSqrt2*(StateVector[0]+StateVector[1]),
01648                       SlcStripData[Plane][0].csh->GetZPos());
01649 
01650 
01651     TVector3 momentum(modp*(dxdz/dsdz),
01652                       modp*(dydz/dsdz),
01653                       modp/dsdz);
01654     SwimParticle muon(position,momentum);
01655     muon.SetCharge(charge);
01656     SwimZCondition zc(Zend);
01657  
01658     // Do the swim, accounting for direction of motion w.r.t time too
01659     if( (GoForward==true && ZIncreasesWithTime==true)  || (GoForward==false && ZIncreasesWithTime==false) ) {
01660       if(UseGeoSwimmer){
01661         done = GeoSwimmer::Instance()->SwimForward(muon,Zend);
01662       } else {
01663         done = myswimmer->SwimForward(muon,zc);
01664       }   
01665     }
01666     else if( (GoForward==true && ZIncreasesWithTime==false)  || (GoForward==false && ZIncreasesWithTime==true) ) {
01667       if(UseGeoSwimmer){
01668         done = GeoSwimmer::Instance()->SwimBackward(muon,Zend);
01669       } else {
01670         done = myswimmer->SwimBackward(muon,zc);
01671       }    
01672     }
01673     if(done==true) {
01674       if(muon.GetDirection().Z()!=0. && muon.GetMomentumModulus()!=0.) {
01675         Output[0]=invSqrt2*(muon.GetPosition().Y()+muon.GetPosition().X());
01676         Output[1]=invSqrt2*(muon.GetPosition().Y()-muon.GetPosition().X());
01677         Output[2]=invSqrt2*((muon.GetDirection().Y()/muon.GetDirection().Z())+(muon.GetDirection().X()/muon.GetDirection().Z()));
01678         Output[3]=invSqrt2*((muon.GetDirection().Y()/muon.GetDirection().Z())-(muon.GetDirection().X()/muon.GetDirection().Z()));
01679         Output[4]=muon.GetCharge()/muon.GetMomentumModulus();
01680         // Get range and dS from the Swimmer
01681         if(dS) {*dS=muon.GetS();} if(Range) {*Range=muon.GetRange();} if(dE){*dE=muon.GetMomentumModulus()-momentum.Mag();}
01682       }
01683       else {done=false;}
01684     }
01685     
01686   }
01687 
01688   else{
01689     // If infinite momentum, use straight line extrapolation
01690     double delz = (Zend-SlcStripData[Plane][0].csh->GetZPos());
01691     Output[0]=StateVector[0] + StateVector[2]*delz;
01692     Output[1]=StateVector[1] + StateVector[3]*delz;
01693     Output[2]=StateVector[2];
01694     Output[3]=StateVector[3];
01695     Output[4]=StateVector[4];
01696 
01697     done=true;
01698   }    
01699   
01700   delete myswimmer;
01701   delete bf;
01702   return done;
01703 }
01705 
01706 
01707 
01709 void AlgFitTrackCam::ResetCovarianceMatrix()
01710 {
01711   // Simple method reset variables/arrays to allow propagation again
01712 
01713   DeltaPlane=0; DeltaZ=0; 
01714   GetInitialCovarianceMatrix(false);
01715 }
01717 
01718 
01719 
01721 void AlgFitTrackCam::GetInitialCovarianceMatrix(const bool FirstIteration)
01722 {
01723   MSG("AlgFitTrackCam",Msg::kDebug) << "GetInitialCovarianceMatrix" << endl;
01724 
01725   if(FirstIteration==true) {
01726     
01727     for(int i=0; i<5; ++i) {
01728       for(int j=0; j<5; ++j) {
01729         C_k_minus[i][j]=0.;
01730       }
01731     }
01732     
01733     // Diagonal terms
01734     C_k_minus[0][0]=0.25; C_k_minus[1][1]=0.25; 
01735     C_k_minus[2][2]=100.; C_k_minus[3][3]=100.; 
01736     C_k_minus[4][4]=1.;
01737     
01738     // Off diagonal terms. Taken from SR - Origin of this?
01739     if(ZIncreasesWithTime==true) {
01740       C_k_minus[0][4]=7.5e-5;  C_k_minus[1][4]=7.5e-5;
01741       C_k_minus[4][0]=7.5e-5;  C_k_minus[4][1]=7.5e-5;
01742     }
01743     else if(ZIncreasesWithTime==false) {
01744       C_k_minus[0][4]=-7.5e-5;  C_k_minus[1][4]=-7.5e-5;
01745       C_k_minus[4][0]=-7.5e-5;  C_k_minus[4][1]=-7.5e-5;
01746     }
01747     
01748     
01749   }
01750 
01751   else if(FirstIteration==false) {
01752     // Results are very sensitive to this multiplication. A large number means
01753     // that further iterations start with the same uncertainties as the first,
01754     // albeit with improved "track finder" strips
01755     for(int i=0; i<5; ++i) {C_k_minus[i][i]*=100;}
01756     
01757     
01758     // Make sure not larger than very first covariance elements
01759     C_k_minus[0][0]=min(C_k_minus[0][0],0.25); C_k_minus[1][1]=min(C_k_minus[1][1],0.25);
01760     C_k_minus[2][2]=min(C_k_minus[2][2],100.); C_k_minus[3][3]=min(C_k_minus[3][3],100.);
01761     C_k_minus[4][4]=min(C_k_minus[4][4],1.);
01762 
01763     double cov_xqp = 7.5e-5;             // Taken from SR - Origin of this?
01764     
01765     for(int i=0; i<2; ++i){
01766       if(fabs(C_k_minus[i][4])>cov_xqp) C_k_minus[i][4] = (C_k_minus[i][4] > 0 ? cov_xqp : -cov_xqp);
01767       if(fabs(C_k_minus[4][i])>cov_xqp) C_k_minus[4][i] = (C_k_minus[4][i] > 0 ? cov_xqp : -cov_xqp);
01768     }
01769 
01770     cov_xqp /= 0.06;                     // Taken from SR - Origin of this?
01771 
01772     for(int i=2; i<4; ++i){
01773       if(fabs(C_k_minus[i][4])>cov_xqp) C_k_minus[i][4] = (C_k_minus[i][4] > 0 ? cov_xqp : -cov_xqp);
01774       if(fabs(C_k_minus[4][i])>cov_xqp) C_k_minus[4][i] = (C_k_minus[4][i] > 0 ? cov_xqp : -cov_xqp);
01775     }
01776   }
01777 
01778 
01779   // Display
01780   if(debug) {
01781     cout << "Initial covariance matrix" << endl;
01782     for(int p=0; p<5; ++p){
01783       for(int q=0; q<5; ++q){
01784         cout << C_k_minus[p][q] << " ";
01785       }  
01786       cout << endl;
01787     }
01788   }
01789 
01790 }
01792 
01793 
01794 
01796 void AlgFitTrackCam::GetNoiseMatrix(const int Plane, const int NewPlane)
01797 {
01798   // This method is essentially the same as in SR fitter
01799   MSG("AlgFitTrackCam",Msg::kDebug) << "GetNoiseMatrix" << endl;
01800 
01801   for (int p=0; p<5; ++p) {
01802     for (int q=0; q<5; ++q) {
01803       Q_k_minus[p][q]=0;    }
01804   }
01805   
01806   // Get gradients, etc from x_k_minus
01807   double dsdzSquared = 1.+pow(x_k_minus[2],2)+pow(x_k_minus[3],2);
01808   double dsdz = pow(dsdzSquared,0.5);
01809 
01810   // Implement noise matrix as in SR
01811   if (DeltaPlane!=-99 && DeltaZ!=-99) {  
01812     double qp = x_k_minus[4];
01813     if(fabs(qp)<0.01) qp = (qp>0 ? 0.01 : -0.01);
01814     int izdir = ((NewPlane-Plane)>0 ? 0 : 1);
01815   
01816     double LocalRadiationLength=(dsdz * double(DeltaPlane) * 1.47); // 1.47 radiation lengths per iron plane
01817 
01818     double SigmaMS=(0.0136 * fabs(qp) * pow(LocalRadiationLength,0.5)
01819                     * (1. + (0.038 * log(LocalRadiationLength)) ));
01820     double SigmaMSSquared=pow(SigmaMS,2);
01821 
01822     double Sigma33Squared=0.5*SigmaMSSquared*dsdzSquared*(1.+pow(x_k_minus[2],2));
01823 
01824     double Sigma34Squared=0.5*SigmaMSSquared*dsdzSquared*(x_k_minus[2]*x_k_minus[3]);
01825 
01826     double Sigma44Squared=0.5*SigmaMSSquared*dsdzSquared*(1.+pow(x_k_minus[3],2));;
01827 
01828 
01829     // Treat steel as discrete scatter
01830     SwimGeo *spil = SwimGeo::Instance(*(const_cast<VldContext*>(vldc))); // Get edges of steel
01831     double z1 = spil->GetSteel(TrkStripData[Plane][0].ZPos,izdir)->GetZ();
01832     double z2 = spil->GetSteel(z1,izdir)->GetZ();
01833   
01834     double dzscatter = fabs(TrkStripData[NewPlane][0].ZPos-0.5*(z1+z2));
01835     double dzscatter2 = pow(dzscatter,2);
01836   
01837     UgliGeomHandle ugh(*vldc);
01838     BField bf(*vldc,-1,0);
01839     TVector3 uvz;
01840 
01841     uvz(0) = x_k_minus[0];
01842     uvz(1) = x_k_minus[1];
01843     uvz(2) = ugh.GetNearestSteelPlnHandle(TrkStripData[Plane][0].ZPos).GetZ0();
01844 
01845     TVector3 buvz = bf.GetBField(uvz, true);
01846     buvz[0] *= 0.3;
01847     buvz[1] *= 0.3;
01848     buvz[2] *= 0.3;
01849 
01850     
01851     double eloss = 0.038 * double(DeltaPlane);
01852     double sigmaeloss2 = 0.25*eloss*dsdz*qp*qp;
01853     sigmaeloss2 *= sigmaeloss2;
01854 
01855 
01856     // Fill elements of noise matrix
01857     Q_k_minus[0][0]=dzscatter2*Sigma33Squared;
01858     Q_k_minus[0][1]=dzscatter2*Sigma34Squared;
01859     Q_k_minus[0][2]=dzscatter*Sigma33Squared;
01860     Q_k_minus[0][3]=dzscatter*Sigma34Squared;
01861     Q_k_minus[0][4]=dzscatter*sigmaeloss2*double(DeltaPlane)*buvz(1)*0.0254*dsdz*(1.+pow(x_k_minus[2],2));
01862 
01863     Q_k_minus[1][0]=dzscatter2*Sigma34Squared;
01864     Q_k_minus[1][1]=dzscatter2*Sigma44Squared;
01865     Q_k_minus[1][2]=dzscatter*Sigma34Squared;
01866     Q_k_minus[1][3]=dzscatter*Sigma44Squared;
01867     Q_k_minus[1][4]=dzscatter*sigmaeloss2*double(DeltaPlane)*buvz(0)*0.0254*dsdz*(1.+pow(x_k_minus[3],2));
01868 
01869     Q_k_minus[2][0]=dzscatter*Sigma33Squared;
01870     Q_k_minus[2][1]=dzscatter*Sigma34Squared;
01871     Q_k_minus[2][2]=Sigma33Squared;
01872     Q_k_minus[2][3]=Sigma34Squared;
01873     Q_k_minus[2][4]=sigmaeloss2*double(DeltaPlane)*buvz(1)*0.0254*dsdz*(1.+pow(x_k_minus[2],2));
01874 
01875     Q_k_minus[3][0]=dzscatter*Sigma34Squared;
01876     Q_k_minus[3][1]=dzscatter*Sigma44Squared;
01877     Q_k_minus[3][2]=Sigma34Squared;
01878     Q_k_minus[3][3]=Sigma44Squared;
01879     Q_k_minus[3][4]=sigmaeloss2*double(DeltaPlane)*buvz(0)*0.0254*dsdz*(1.+pow(x_k_minus[3],2));
01880 
01881     Q_k_minus[4][0]=dzscatter*sigmaeloss2*double(DeltaPlane)*buvz(1)*0.0254*dsdz*(1.+pow(x_k_minus[2],2));
01882     Q_k_minus[4][1]=dzscatter*sigmaeloss2*double(DeltaPlane)*buvz(0)*0.0254*dsdz*(1.+pow(x_k_minus[3],2));
01883     Q_k_minus[4][2]=sigmaeloss2*double(DeltaPlane)*buvz(1)*0.0254*dsdz*(1.+pow(x_k_minus[2],2));
01884     Q_k_minus[4][3]=sigmaeloss2*double(DeltaPlane)*buvz(0)*0.0254*dsdz*(1.+pow(x_k_minus[3],2));
01885     Q_k_minus[4][4]=sigmaeloss2;
01886   }
01887  
01888 
01889   // Display
01890   if(debug) {
01891     cout << "1e6 * Q_k_minus" << endl;
01892     for(int i=0; i<5; ++i) {
01893       for(int j=0; j<5; ++j) {
01894         cout << 1e6*Q_k_minus[i][j] << " ";
01895       }
01896       cout << endl;
01897     }
01898   }
01899 
01900 }
01902 
01903 
01904 
01906 void AlgFitTrackCam::ExtrapCovMatrix()
01907 {
01908   // C_k_intermediate = (F_k_minus * C_k_minus * F_k_minus^T) + Q_k_minus
01909   MSG("AlgFitTrackCam",Msg::kDebug) << "ExtrapCovMatrix" << endl;
01910 
01911   for (int i=0; i<5; ++i) {
01912     for (int j=0; j<5; ++j) {  
01913       C_k_intermediate[i][j]=0;
01914       
01915       for (int l=0; l<5; ++l) {
01916         for (int m=0; m<5; ++m) {   
01917           C_k_intermediate[i][j]+=F_k_minus[i][m]*C_k_minus[m][l]*F_k_minus[j][l];
01918         }
01919       }
01920 
01921       C_k_intermediate[i][j]+=Q_k_minus[i][j];
01922     }
01923     
01924   }
01925 
01926 
01927   // Diagonal elements should be positive
01928   double covlim = 1.e-8;
01929 
01930   for(int i=0; i<5; ++i) {
01931     if(C_k_intermediate[i][i]<covlim) {
01932       MSG("AlgFitTrackCam",Msg::kVerbose) << "Negative diagonal element in C_k_intermediate" << endl;
01933       C_k_intermediate[i][i]=covlim;
01934     }
01935   }
01936 
01937 
01938   // Display
01939   if(debug) {
01940     cout << "C_k_intermediate" << endl;
01941     for(int i=0; i<5; ++i) {
01942       for(int j=0; j<5; ++j) {
01943         cout << C_k_intermediate[i][j] << " ";
01944       }
01945       cout << endl;
01946     }
01947   }
01948   
01949 }
01951 
01952 
01953 
01955 void AlgFitTrackCam::CalcKalmanGain(const int NewPlane)
01956 {
01957   // K_k = C_k_intermediate * H_k^T * ( V_k + H_k * C_k_intermediate * H_k^T )^-1
01958   MSG("AlgFitTrackCam",Msg::kDebug) << "CalcKalmanGain" << endl;
01959 
01960   double Denominator=0;
01961 
01962   // H_k has only one non-zero element, so we can reduce matrix multiplication required
01963   if(TrkStripData[NewPlane][0].PlaneView==2) {Denominator=C_k_intermediate[0][0];}
01964   else {Denominator=C_k_intermediate[1][1];}
01965   
01966 
01967   // Add uncertainty in measurement
01968   Denominator+=TrkStripData[NewPlane][0].TPosError;
01969 
01970   MSG("AlgFitTrackCam",Msg::kVerbose) << "V_k " << TrkStripData[NewPlane][0].TPosError 
01971                                       << ", Kalman Gain Denominator " << Denominator << endl;
01972 
01973   if (Denominator!=0.) {
01974     for (int i=0; i<5; ++i) {
01975       K_k[i]=0;
01976       
01977       for (int m=0; m<5; ++m) {K_k[i]+=(C_k_intermediate[i][m])*(H_k[m]);}
01978       
01979       K_k[i]=K_k[i]/Denominator;
01980     }
01981 
01982     MSG("AlgFitTrackCam",Msg::kVerbose) << "Kalman Gain: " 
01983                                         << K_k[0] << " " << K_k[1] << " " << K_k[2] << " "
01984                                         << K_k[3] << " " << K_k[4] << endl;
01985   }
01986   else MSG("AlgFitTrackCam",Msg::kDebug) << "V_k + (H_k * C_k_intermediate * H_k_transpose) is zero!" << endl;
01987 }
01989 
01990 
01991 
01993 void AlgFitTrackCam::UpdateStateVector(const int Plane, const int NewPlane, const bool GoForward)
01994 {  
01995   // x_k = (F_k_minus * x_k_minus) + K_k(m_k - (H_k * F_k_minus * x_k_minus) )
01996   MSG("AlgFitTrackCam",Msg::kDebug) << "UpdateStateVector" << endl;
01997 
01998 
01999   double HFx=0;
02000   double m_k=0;
02001   double MeasurementFactor=0;
02002   int nswimfail=0;
02003 
02004 
02005   // Calculate F_k_minus * x_k_minus, using the Swimmer
02006   // Also get an accurate measure of dS and Range from the Swimmer
02008   double StateVector[5];
02009   double Prediction[5];
02010   bool GetPrediction=false;
02011 
02012   for(int i=0; i<5; ++i) {StateVector[i]=x_k_minus[i];}
02013 
02014   // Do the swim
02016   while(GetPrediction==false && nswimfail<=10) {
02017     MSG("AlgFitTrackCam",Msg::kVerbose) << " state " << StateVector[0] << " " 
02018                                         << StateVector[1] << " " << StateVector[2] << " " 
02019                                         << StateVector[3] << " " << StateVector[4] << endl;   
02020     
02021     GetPrediction=Swim(StateVector, Prediction, Plane, NewPlane, GoForward);
02022     
02023     MSG("AlgFitTrackCam",Msg::kVerbose) << " predict state " << Prediction[0] << " " 
02024                                         << Prediction[1] << " " << Prediction[2] << " " 
02025                                         << Prediction[3] << " " << Prediction[4] << endl;
02026 
02027     if(GetPrediction==false) {
02028       StateVector[4]*=0.5; 
02029       nswimfail++; TotalNSwimFail++;
02030       MSG("AlgFitTrackCam",Msg::kVerbose) << "UpdateStateVector, Prediction failed - Double momentum and swim again" << endl;
02031     }
02032   }
02033 
02034   if(nswimfail>10) {  // Swim shouldn't fail, as it succeeded to get the propagator
02035     MSG("AlgFitTrackCam",Msg::kDebug) << "UpdateStateVector, nswimfail>10, fail track" << endl;
02036     PassTrack=false;
02037   }
02039 
02040   
02042 
02043 
02044   MSG("AlgFitTrackCam",Msg::kDebug) << "UpdateStateVector, Check predicted state " << endl;
02045   CheckValues(Prediction, NewPlane);
02046 
02047 
02048   // Calculate H_k * F_k_minus * x_k_minus
02050   if(TrkStripData[NewPlane][0].PlaneView==2) {HFx=Prediction[0];}
02051   if(TrkStripData[NewPlane][0].PlaneView==3) {HFx=Prediction[1];}
02052 
02053   MSG("AlgFitTrackCam",Msg::kVerbose) << "HFx " << HFx << endl;
02055 
02056   
02057   // Read in measurement
02059   m_k=TrkStripData[NewPlane][0].TPos;
02060   MSG("AlgFitTrackCam",Msg::kVerbose) << "m_k " << TrkStripData[NewPlane][0].TPos << endl;
02061   
02062   MeasurementFactor=(m_k-HFx);
02064 
02065   
02066   // Calculate x_k
02068   for (int i=0; i<5; ++i) {
02069     x_k[i]=0.;
02070     x_k[i]+=Prediction[i]+(K_k[i]*MeasurementFactor);
02071   }
02073 
02074 
02075   MSG("AlgFitTrackCam",Msg::kDebug) << "UpdateStateVector, Check filtered state " << endl;
02076   CheckValues(x_k, NewPlane);
02077 
02078 
02079   // Care with multiple range corrections - do not want to flip sign
02080   // (multiple corrections mean sign changes can occur even though absolute value stays same)
02082   // JAM up to 40 from 4
02083 
02084   double Maxqp = 4.;
02085   if(fabs(x_k_minus[4])==Maxqp && 
02086      ( (GoForward==true && ZIncreasesWithTime==true) 
02087        || (GoForward==false && ZIncreasesWithTime==false) ) ) 
02088     {
02089       if(!LastIteration) x_k[4] = (x_k_minus[4]>0 ? Maxqp : -Maxqp);
02090       //      cout << " resetting in UpdateStateVector " <<  endl;
02091     }
02093 
02094   //if on last plane in forward swim, disregard sign flip
02095   if(x_k_minus[4]!=0){
02096     if ( x_k[4]/x_k_minus[4]<0 && 
02097         ( (GoForward==true && ZIncreasesWithTime==true && NewPlane >= EndofRangePlane ) 
02098           || (GoForward==false && ZIncreasesWithTime==false && NewPlane <= EndofRangePlane ) )) 
02099       {
02100         x_k[4] = -x_k[4];
02101       }
02102   }
02103   
02104   // Display
02105   MSG("AlgFitTrackCam",Msg::kVerbose) << "Filtered State vector: "
02106                                       << x_k[0] << " " << x_k[1] << " " << x_k[2] << " "
02107                                       << x_k[3] << " " << x_k[4] << endl;
02108 }
02110 
02111 
02112 
02114 void AlgFitTrackCam::UpdateCovMatrix()
02115 {
02116   // C_k = (Identity - (K_k * H_k) ) * C_k_intermediate
02117   MSG("AlgFitTrackCam",Msg::kDebug) << "UpdateCovMatrix" << endl;
02118 
02119   for (int i=0; i<5; ++i) {
02120     for (int j=0; j<5; ++j) {  
02121       C_k[i][j]=0;
02122       for (int m=0; m<5; ++m) {   
02123         C_k[i][j]+=(Identity[i][m] - K_k[i]*H_k[m]) * C_k_intermediate[m][j];
02124       }
02125     }
02126   }
02127 
02128 
02129   // Diagonal elements should be positive
02130   double covlim = 1.e-8;
02131 
02132   for(int i=0; i<5; ++i) {
02133     if(C_k[i][i]<covlim) {
02134       MSG("AlgFitTrackCam",Msg::kVerbose) << "Negative diagonal element in C_k" << endl;
02135       C_k[i][i]=covlim;
02136     }
02137   }
02138 
02139 
02140   // Display
02141   if(debug) {
02142     cout << "Filtered Covariance matrix" << endl;
02143     for(int i=0; i<5; ++i) {
02144       for(int j=0; j<5; ++j) {
02145         cout << C_k[i][j] << " ";
02146       }
02147       cout << endl;  
02148     }
02149   }
02150 
02151 }
02153 
02154 
02155 
02157 void AlgFitTrackCam::MoveArrays()
02158 {
02159   // Move k to k-1 ready to consider next hit
02160   MSG("AlgFitTrackCam",Msg::kDebug) << "MoveArrays" << endl;
02161 
02162   for (int i=0; i<5; ++i) {
02163     for (int j=0; j<5; ++j) { 
02164       C_k_minus[i][j]=C_k[i][j];
02165     }
02166   }
02167   
02168   for (int l=0; l<5; ++l) {
02169     x_k_minus[l]=x_k[l];
02170   }
02171 }
02173 
02174 
02175 
02177 void AlgFitTrackCam::CheckValues(double* Input, const int NewPlane)
02178 {
02179   // Make range and gradient corrections
02180   // Possible source of offset in q/p resolutions
02181 
02182   // Range check
02183     
02184   double Maxqp=4.; double Maxqpfrac=1.2;
02185   double Range=track->GetRange(NewPlane);
02186 
02187   //JAM signal end of range found
02188   if(fabs(Input[4])>10.0) EndofRange=true; 
02189 
02190    if(Range>0. && (Maxqpfrac*500/Range)<Maxqp) {Maxqp=(Maxqpfrac*500/Range);}
02191   MSG("AlgFitTrackCam",Msg::kVerbose) << " Range " << Range << " Maxqp " << Maxqp << endl;
02192 
02193 
02194 
02195   if(LastIteration) Maxqp=40;
02196   if(fabs(Input[4])>Maxqp){
02197     //    cout << " CheckValues: Range check correction " << Input[4] << " " << Maxqp << endl;
02198     MSG("AlgFitTrackCam",Msg::kVerbose) << "CheckValues, Range check correction" << endl;
02199     Input[4]=(Input[4]>0 ? Maxqp : -Maxqp);
02200   }
02201   
02202   
02203   // Gradient check
02204   double Maxgradient=25.;
02205 
02206   if(fabs(Input[2])>Maxgradient) {
02207     MSG("AlgFitTrackCam",Msg::kVerbose) << "CheckValues, Gradient correction, U" << endl;
02208     Input[2]=(Input[2]>0 ? Maxgradient : -Maxgradient);
02209   }
02210 
02211   if(fabs(Input[3])>Maxgradient) {
02212     MSG("AlgFitTrackCam",Msg::kVerbose) << "CheckValues, Gradient correction, V" << endl;
02213     Input[3]=(Input[3]>0 ? Maxgradient : -Maxgradient);
02214   }
02215   
02216 
02217   // Check u and v values are not rubbish
02218   if(fabs(Input[0])<5000. && fabs(Input[1])<5000.) {PassTrack=true;}
02219   else {PassTrack=false;}
02220 }
02222 
02223 
02224 
02226 void AlgFitTrackCam::StoreFilteredData(const int NewPlane)
02227 {
02228   // Store the data required for matching Kalman output data to strips
02229   MSG("AlgFitTrackCam",Msg::kDebug) << "StoreFilteredData" << endl;
02230 
02231   FiltDataStruct temp;
02232   
02233   temp.x_k0=x_k[0]; temp.x_k1=x_k[1];
02234   temp.x_k2=x_k[2]; temp.x_k3=x_k[3];
02235   temp.x_k4=x_k[4];
02236 
02237   FilteredData[NewPlane].push_back(temp);
02238 }
02240 
02241 
02242 
02244 void AlgFitTrackCam::SetTrackProperties(CandFitTrackCamHandle &cth)
02245 { 
02246 
02247   if(nbfield>0) bave /=nbfield;
02248   
02249   // Carry out the assignment of variables to the new fitted track 
02250   MSG("AlgFitTrackCam",Msg::kDebug) << "SetTrackProperties" << endl;
02251   
02252   
02253   // Momentum, charge and error on q/p
02255   if(x_k[4]!=0.) {cth.SetMomentumCurve(fabs(1./x_k[4]));}
02256   cth.SetRangeBiasedQP(x_k4_biased);
02257   if(x_k[4]>0.) {cth.SetEMCharge(1.);}
02258   else if(x_k[4]<0.) {cth.SetEMCharge(-1.);}
02259   
02260   cth.SetVtxQPError(pow(VtxCov[4],0.5));
02262   
02263   
02264   // Positions and angles  
02266   int VtxPlane;
02267   int EndPlane;
02268   double dsdz;
02269   
02270   if(ZIncreasesWithTime==true) {VtxPlane=MinPlane; EndPlane=MaxPlane;}
02271   else {VtxPlane=MaxPlane; EndPlane=MinPlane;}
02272   
02273   // Vtx and end coordinates  
02274   cth.SetVtxU(FilteredData[VtxPlane][0].x_k0);
02275   cth.SetVtxV(FilteredData[VtxPlane][0].x_k1);
02276   cth.SetVtxZ(SlcStripData[VtxPlane][0].csh->GetZPos());
02277   cth.SetVtxPlane(VtxPlane);
02278   
02279   cth.SetEndU(FilteredData[EndPlane][0].x_k0);
02280   cth.SetEndV(FilteredData[EndPlane][0].x_k1);
02281 
02282   cth.SetEndZ(SlcStripData[EndPlane][0].csh->GetZPos());
02283   cth.SetEndPlane(EndPlane);
02284   
02285   
02286   // Vtx and end direction cosines
02287   dsdz=pow(1.+pow(FilteredData[VtxPlane][0].x_k2,2)+pow(FilteredData[VtxPlane][0].x_k3,2),0.5);
02288   if(ZIncreasesWithTime==false) {dsdz=-dsdz;}
02289   
02290   cth.SetVtxDirCosU(FilteredData[VtxPlane][0].x_k2/dsdz);
02291   cth.SetVtxDirCosV(FilteredData[VtxPlane][0].x_k3/dsdz);
02292   cth.SetVtxDirCosZ(1./dsdz);
02293   
02294   cth.SetDirCosU(FilteredData[VtxPlane][0].x_k2/dsdz);
02295   cth.SetDirCosV(FilteredData[VtxPlane][0].x_k3/dsdz);
02296   cth.SetDirCosZ(1./dsdz);
02297     
02298   dsdz=pow(1.+pow(FilteredData[EndPlane][0].x_k2,2)+pow(FilteredData[EndPlane][0].x_k3,2),0.5);
02299   if(ZIncreasesWithTime==false) {dsdz=-dsdz;}
02300   
02301   cth.SetEndDirCosU(FilteredData[EndPlane][0].x_k2/dsdz);
02302   cth.SetEndDirCosV(FilteredData[EndPlane][0].x_k3/dsdz);
02303   cth.SetEndDirCosZ(1./dsdz);
02304   
02305   // End q/p value
02306   cth.SetEndQP(FilteredData[EndPlane][0].x_k4);
02307     
02308   // Errors on vtx positions and angles  
02309   cth.SetVtxUError(pow(VtxCov[0],0.5));
02310   cth.SetVtxVError(pow(VtxCov[1],0.5));
02311   cth.SetVtxdUError(pow(VtxCov[2],0.5));
02312   cth.SetVtxdVError(pow(VtxCov[3],0.5)); 
02313   
02314   // Errors on end positions, angles and q/p
02315   cth.SetEndUError(pow(EndCov[0],0.5));
02316   cth.SetEndVError(pow(EndCov[1],0.5));
02317   cth.SetEnddUError(pow(EndCov[2],0.5));
02318   cth.SetEnddVError(pow(EndCov[3],0.5)); 
02319   cth.SetEndQPError(pow(EndCov[4],0.5)); 
02320 
02322 
02323   cth.SetBave(bave);
02324 
02325   // More variables to be set, in order to ensure compatibility
02327   cth.SetNTrackStrip(cth.GetNDaughters());
02328   cth.SetNTrackDigit(cth.GetNDigit());
02329   
02330   cth.SetNIterate(NIter);
02331   cth.SetNSwimFail(TotalNSwimFail);
02332   
02333   
02334   // Obtain "fitting data" for the final track strips
02335   for (int i=0; i<490; ++i) {TrkStripData[i].clear();} 
02336   GetFitData(MinPlane,MaxPlane);
02337   
02338   
02339   // Set tpos error and Calculate chi2, NDOF
02340   double Chi2=0; double Chi2Contrib=0; int NDOF=0; double FilteredTPos=0;
02341   
02342   for(int i=MinPlane; i<=MaxPlane; ++i) {
02343     if(TrkStripData[i].size()>0) {
02344       
02345       if(TrkStripData[i][0].TPosError>0.) {
02346         cth.SetTrackPointError(i,pow(TrkStripData[i][0].TPosError,0.5));
02347         
02348         if(TrkStripData[i][0].PlaneView==2) {FilteredTPos=FilteredData[i][0].x_k0;}
02349         else {FilteredTPos=FilteredData[i][0].x_k1;}
02350         
02351         Chi2Contrib = pow((TrkStripData[i][0].TPos-FilteredTPos),2) / TrkStripData[i][0].TPosError;
02352         cth.SetPlaneChi2(i,Chi2Contrib);        
02353         
02354         Chi2+=Chi2Contrib;
02355         
02356         NDOF++;
02357       }
02358     }
02359   }
02360   cth.SetChi2(Chi2);
02361   cth.SetNDOF(NDOF-5); // Number of constraints set to 5
02362   
02363   
02364   // Assign U, V and q/p values
02365   for(int i=MinPlane; i<=MaxPlane; ++i) {
02366     if(FilteredData[i].size()>0) {
02367       cth.SetU(i,FilteredData[i][0].x_k0);
02368       cth.SetV(i,FilteredData[i][0].x_k1);
02369       cth.SetPlaneQP(i,FilteredData[i][0].x_k4);
02370     }
02371   }
02372   
02373   
02374   // Set Trace and TraceZ
02375   CalculateTrace(cth);
02376   
02377   
02378   // Fill time and range maps
02379   SetT(&cth);
02380   SetRangeAnddS(cth);
02381   
02382   
02383   // Set momentum to our best estimate (range or curvature)
02384   cth.SetMomentum(cth.GetMomentumCurve());
02385   if(cth.IsContained()){
02386     cth.SetMomentum(cth.GetMomentumRange());
02387   }
02388   
02389   
02390   // Identify track strips inside in vertex shower
02391   
02392   TIter FitTrackStripItr = cth.GetDaughterIterator();
02393   while(CandStripHandle* FitTrackStrip = dynamic_cast<CandStripHandle*>(FitTrackStripItr()))
02394     {
02395       if(ShowerEntryPlane!=-99) {
02396         if( (ZIncreasesWithTime==true && FitTrackStrip->GetPlane()<=ShowerEntryPlane)
02397             || (ZIncreasesWithTime==false && FitTrackStrip->GetPlane()>=ShowerEntryPlane) ) {
02398           cth.SetInShower(FitTrackStrip,2);
02399         }
02400         else {cth.SetInShower(FitTrackStrip,0);}
02401       }
02402       else {cth.SetInShower(FitTrackStrip,0);}
02403     }
02404   
02405   
02406   // Set all time related variables
02407   TimingFit(cth);
02408   
02409   
02410   // Calibrate, to get track pulse height in MIPs, GeV, etc
02411   Calibrator& cal = Calibrator::Instance();
02412   cal.ReInitialise(*vldc);
02413   Calibrate(&cth);
02414 
02415 
02416 }
02418 
02419 
02420 
02422 void AlgFitTrackCam::TimingFit(CandFitTrackCamHandle &cth)
02423 {
02424   MSG("AlgFitTrackCam",Msg::kDebug) << "TimingFit" << endl;
02425 
02426   // Initialisations
02428   double s; double t; double q; int n=0; 
02429   double MinUncertainty = 0.; double MinCT=-3000.;
02430   
02431   // Time of first strip in track
02432   StripListTime=9.e30;
02433 
02434   // Create an offset such that dS=0 at the MinPlane
02435   double dSOffset=0.; double Sign=-1.; double dS[490];
02436   if(ZIncreasesWithTime==true) {dSOffset=cth.GetdS(MinPlane); Sign=1.;}
02437 
02438   // Store data needed in arrays. Charge is in PEs.
02439   double Qp[490];  double Qm[490];
02440   double CTp[490]; double CTm[490];
02441   int Skipp[490];  int Skipm[490];
02442   double C=3.e8;   
02443 
02444   double ErrorParam[3];
02445   ErrorParam[0]=0.; ErrorParam[1]=0.; ErrorParam[2]=0.;
02446 
02447   // Zero the arrays
02448   for(int i=0; i<490; ++i) { 
02449     dS[i]=0.; Qp[i]=0.; Qm[i]=0.; CTp[i]=0.; 
02450     CTm[i]=0.; Skipp[i]=0; Skipm[i]=0;
02451   }
02453 
02454 
02455 
02456   // Organise timing for the Far Detector
02458   if(vldc->GetDetector()==DetectorType::kFar) {  
02459     // Parameters for PE vs time fit residual
02460     MinUncertainty=0.56;
02461     ErrorParam[0]=0.56; ErrorParam[1]=0.50; ErrorParam[2]=-0.34;
02462 
02463     // Loop over all planes
02464     for(int i=MinPlane; i<=MaxPlane; ++i) {
02465         
02466       if(InitTrkStripData[i].size()>0) {
02467         dS[i]=Sign*(dSOffset-cth.GetdS(i));
02468         
02469         CTp[i]=C*cth.GetT(i,StripEnd::kPositive);
02470         CTm[i]=C*cth.GetT(i,StripEnd::kNegative);
02471         
02472         if(CTp[i]>MinCT && CTp[i]<StripListTime) {StripListTime=CTp[i];}
02473         if(CTm[i]>MinCT && CTm[i]<StripListTime) {StripListTime=CTm[i];}
02474         
02475         for(unsigned int j=0; j<InitTrkStripData[i].size(); ++j) {
02476           Qp[i]+=InitTrkStripData[i][j].csh->GetCharge(StripEnd::kPositive);
02477           Qm[i]+=InitTrkStripData[i][j].csh->GetCharge(StripEnd::kNegative);
02478         }
02479       }
02480     }
02481 
02482     // Subtract StripList time
02483     if(StripListTime<8.e30) {
02484       for(int i=MinPlane; i<=MaxPlane; ++i) {
02485         if(InitTrkStripData[i].size()>0) {
02486           CTp[i]-=StripListTime;
02487           CTm[i]-=StripListTime;
02488         }
02489       }
02490     }
02491     else {StripListTime=0.;}
02492 
02493   } // End Far Detector Section
02495 
02496 
02497 
02498   // Organise timing for the Near Detector
02500   if(vldc->GetDetector()==DetectorType::kNear) {
02501     // Parameters for PE vs time fit residual
02502     MinUncertainty=1.19;
02503     ErrorParam[0]=1.13; ErrorParam[1]=0.63; ErrorParam[2]=-0.21;
02504 
02505     double Index=1.77; double DistFromCentre=0.; double CTime=0.;  double FibreDist=0.;    
02506     double halfLength=0.; double DigChg=0.; double PlaneDigChg;
02507 
02508     StripEnd::StripEnd_t StpEnd = StripEnd::kUnknown;
02509     CandStripHandle* strip; CandDigitHandle* digit;
02510 
02511     UgliGeomHandle ugh = UgliGeomHandle(*vldc);
02512     UgliStripHandle striphandle;
02513 
02514 
02515     // Loop over all planes
02516     for(int i=MinPlane; i<=MaxPlane; ++i)
02517       {
02518         if(InitTrkStripData[i].size()>0) {dS[i]=Sign*(dSOffset-cth.GetdS(i));}
02519         PlaneDigChg=0.;
02520 
02521         // Loop over track strips on plane. Only +ve StripEnds should have charge.
02522         for(unsigned int j=0; j<InitTrkStripData[i].size(); ++j) {
02523           strip = InitTrkStripData[i][j].csh;
02524           CandDigitHandleItr digitItr(strip->GetDaughterIterator());
02525 
02526           Qp[i]+=strip->GetCharge(StripEnd::kPositive);
02527 
02528 
02529           // Loop over digits on strip. 
02531           while( (digit = digitItr()) ) { 
02532             StpEnd=digit->GetPlexSEIdAltL().GetEnd();
02533 
02534             if(StpEnd==StripEnd::kPositive) {
02535               FibreDist = 0.; DistFromCentre = 0.; CTime=0.; DigChg=0.;
02536               UgliStripHandle stripHandle = ugh.GetStripHandle(strip->GetStripEndId());
02537               halfLength = stripHandle.GetHalfLength(); 
02538          
02539               if(strip->GetPlaneView()==2) {DistFromCentre = cth.GetV(i);}
02540               if(strip->GetPlaneView()==3) {DistFromCentre = -cth.GetU(i);}
02541               
02542               FibreDist = (halfLength + DistFromCentre + stripHandle.ClearFiber(StpEnd) 
02543                            + stripHandle.WlsPigtail(StpEnd));
02544               
02545               CTime = C*(strip->GetTime(StpEnd)) - Index*FibreDist;
02546               DigChg=digit->GetCharge();
02547               
02548               PlaneDigChg+=DigChg; CTp[i]+=DigChg*CTime;
02549 
02550               if(CTime>MinCT && CTime<StripListTime) {StripListTime=CTime;}
02551             }
02552           }
02554         }
02555         if(PlaneDigChg>0.) CTp[i]/=PlaneDigChg;
02556       }
02557 
02558 
02559     // Subtract StripList time
02560     if(StripListTime<8.e30) {
02561       for(int i=MinPlane; i<=MaxPlane; ++i) {
02562         if(InitTrkStripData[i].size()>0) {
02563           CTp[i]-=StripListTime;
02564         }
02565       }
02566     }
02567     else {StripListTime=0.;}
02568     
02569   } // End near detector section
02571     
02572     
02573 
02574   // Carry out a simple straight line fit for T vs dS
02576   // Sqt: sum of charge*time, Sqss: sum of charge*dS*dS, etc.
02577   double Sqs=0; double Sqt=0; double Sqss=0; double Sqst=0; double Sqtt=0; double Sq=0;
02578   double TimeSlope=-999; double TimeOffset=-999; double RMS=-999;
02579   double CTCut = 0.; bool CalculateChi2=true;
02580 
02581   
02582   // On first iteration, carry out simple fit. Remove outlying points on subsequent passes.
02583   for(int itr=0; itr<3; ++itr) {
02584  
02585     for(int i=MinPlane; i<=MaxPlane; ++i) { 
02586 
02587       // Only consider planes where we found our final strips
02588       if(InitTrkStripData[i].size()>0) { 
02589         
02590         // For positive strip ends      
02591         s=dS[i]; q=Qp[i]; t=CTp[i];
02592         
02593         if(q>0. && t>MinCT && Skipp[i]==0) {
02594           if(itr==0) {Sq+=q; Sqs+=q*s; Sqt+=q*t; Sqss+=q*s*s; Sqst+=q*s*t; Sqtt+=q*t*t; n++;}
02595           
02596           else if(fabs(t-TimeOffset-(s*TimeSlope)) > CTCut) {
02597             Sqs-=q*s; Sqt-=q*t; Sqss-=q*s*s; Sqst-=q*s*t; Sqtt-=q*t*t; Sq-=q; n--; Skipp[i]=1;
02598           }
02599         }
02600 
02601 
02602         // For negative strip ends
02603         q=Qm[i]; t=CTm[i];
02604         
02605         if(q>0. && t>MinCT && Skipm[i]==0) {
02606           if(itr==0) {Sq+=q; Sqs+=q*s; Sqt+=q*t; Sqss+=q*s*s; Sqst+=q*s*t; Sqtt+=q*t*t; n++;}
02607           
02608           else if(fabs(t-TimeOffset-(s*TimeSlope)) > CTCut) {
02609             Sqs-=q*s; Sqt-=q*t; Sqss-=q*s*s; Sqst-=q*s*t; Sqtt-=q*t*t; Sq-=q; n--; Skipm[i]=1;
02610           }
02611         }
02612 
02613       }
02614     }
02615     
02616     // Calculate parameters
02617     if( (Sq*Sqss-Sqs*Sqs)!=0. && Sq!=0. ) {
02618       TimeSlope  = (Sq*Sqst-Sqs*Sqt)/(Sq*Sqss-Sqs*Sqs);
02619       TimeOffset = (Sqt*Sqss-Sqs*Sqst)/(Sq*Sqss-Sqs*Sqs);
02620       if( ((Sqtt/Sq)-((Sqt/Sq)*(Sqt/Sq)))>0. ) {
02621         RMS = pow((Sqtt/Sq)-((Sqt/Sq)*(Sqt/Sq)),0.5);
02622         CTCut = 3.+RMS;
02623       }
02624       else {CTCut = 3.5;}
02625     }
02626     else  {CalculateChi2=false; break;}
02627   }
02629 
02630 
02631 
02632   // Set timing properties for the fitted track
02634   if(n!=0 && CalculateChi2==true) {
02635 
02636     // Offset, slope and vtx/end times
02638     cth.SetTimeOffset((TimeOffset+StripListTime)/C);
02639     cth.SetTimeSlope(TimeSlope/C);
02640 
02641     if(ZIncreasesWithTime==true) {
02642       cth.SetVtxT((TimeOffset+StripListTime)/C); 
02643       cth.SetEndT((TimeOffset+StripListTime)/C+(dS[MaxPlane]*TimeSlope/C));
02644     }
02645     else {
02646       cth.SetEndT((TimeOffset+StripListTime)/C); 
02647       cth.SetVtxT((TimeOffset+StripListTime)/C+(dS[MaxPlane]*TimeSlope/C));
02648     }
02650 
02651 
02652     // Chi2
02654     double Uncertainty; double Residual2; double Chi2=0; 
02655  
02656     for(int i=MinPlane; i<=MaxPlane; ++i) { 
02657       
02658       if(InitTrkStripData[i].size()>0) { 
02659         // For positive strip ends
02660         s=dS[i]; q=Qp[i]; t=CTp[i];
02661         if(q>0. && t>MinCT && Skipp[i]==0) {
02662           Residual2=pow(t-TimeOffset-(s*TimeSlope),2);
02663 
02664           // From a rough parameterisation of uncertainty (in CT) vs number of PEs
02665           if (q<20) {Uncertainty = ErrorParam[0]+exp(ErrorParam[1]+ErrorParam[2]*q);}
02666           else {Uncertainty=MinUncertainty;}
02667 
02668           if(Uncertainty!=0.) {Chi2+=Residual2/pow(Uncertainty,2);}
02669         }
02670 
02671 
02672         // For negative strip ends
02673         q=Qm[i]; t=CTm[i];
02674         if(q>0. && t>MinCT && Skipm[i]==0) {
02675           Residual2=pow(t-TimeOffset-(s*TimeSlope),2);
02676 
02677           // From a rough parameterisation of uncertainty (in CT) vs number of PEs
02678           if (q<20) {Uncertainty = ErrorParam[0]+exp(ErrorParam[1]+ErrorParam[2]*q);}
02679           else {Uncertainty=MinUncertainty;}
02680           
02681           if(Uncertainty!=0.) {Chi2+=Residual2/pow(Uncertainty,2);}
02682         }
02683       }
02684       
02685     }
02686     // Set these properties
02687     cth.SetTimeFitChi2(Chi2);
02688     cth.SetNTimeFitDigit(n);
02689   }
02691 
02692 
02693 
02694   // Now carry out fits with gradients constrained to be +/- c
02696   double CTIntercept[2]; double Csigma[2]; double Ctrunc[2]; 
02697   double ChiSqPositive=-999; double ChiSqNegative=-999; 
02698   int ChiSqNdfPos=-999; int ChiSqNdfNeg=-999;  
02699   double Swtt[2]; double Swt[2]; double Sw[2]; int npts[2]={0,0};
02700 
02701   if(Sq!=0.) {
02702     CTIntercept[0]=Sqt/Sq; Csigma[0]=-99999.9; Ctrunc[0]=-99999.9;
02703     CTIntercept[1]=Sqt/Sq; Csigma[1]=-99999.9; Ctrunc[1]=-99999.9;
02704     
02705     for(int itr=0; itr<2; ++itr)
02706       {
02707         Swtt[0]=0.; Swt[0]=0.; Sw[0]=0.; npts[0]=0;
02708         Swtt[1]=0.; Swt[1]=0.; Sw[1]=0.; npts[1]=0;
02709         
02710         for(int i=0; i<490; ++i)
02711           {
02712             // For positive strip ends
02713             if(Qp[i]>0. && CTp[i]>MinCT) {
02714               q=Qp[i]; 
02715               
02716               t=CTp[i]-dS[i]+CTIntercept[0];
02717               if(Ctrunc[0]<0. || fabs(t)<Ctrunc[0]) {Swtt[0]+=q*t*t; Swt[0]+=q*t; Sw[0]+=q; ++npts[0];}
02718               
02719               t=CTp[i]+dS[i]+CTIntercept[1];
02720               if(Ctrunc[1]<0. || fabs(t)<Ctrunc[1]) {Swtt[1]+=q*t*t; Swt[1]+=q*t; Sw[1]+=q; ++npts[1];}
02721             }
02722             
02723             // For negative strip ends
02724             if(Qm[i]>0. && CTm[i]>MinCT) {
02725               q=Qm[i]; 
02726               
02727               t=CTm[i]-dS[i]+CTIntercept[0];
02728               if(Ctrunc[0]<0. || fabs(t)<Ctrunc[0]) {Swtt[0]+=q*t*t; Swt[0]+=q*t; Sw[0]+=q; ++npts[0];}
02729               
02730               t=CTm[i]+dS[i]+CTIntercept[1];
02731               if(Ctrunc[1]<0. || fabs(t)<Ctrunc[1]) {Swtt[1]+=q*t*t; Swt[1]+=q*t; Sw[1]+=q; ++npts[1];}
02732             }
02733           }
02734         
02735         // Results for fit with gradient +C
02736         if(npts[0]>1 && Sw[0]!=0.) {
02737           CTIntercept[0]=CTIntercept[0]-Swt[0]/Sw[0]; Csigma[0]=0.; 
02738           if((Swtt[0]/Sw[0])-(Swt[0]/Sw[0])*(Swt[0]/Sw[0])>0.) {Csigma[0]=pow((Swtt[0]/Sw[0])-(Swt[0]/Sw[0])*(Swt[0]/Sw[0]),0.5);}
02739           ChiSqPositive=Csigma[0]; ChiSqNdfPos=npts[0]-1; 
02740           Ctrunc[0]=Csigma[0]+3.;
02741         }
02742         
02743         // Results for fit with gradient -C
02744         if(npts[1]>1 && Sw[1]!=0.) {
02745           CTIntercept[1]=CTIntercept[1]-Swt[1]/Sw[1]; Csigma[1]=0.;
02746           if((Swtt[1]/Sw[1])-(Swt[1]/Sw[1])*(Swt[1]/Sw[1])>0.) {Csigma[1]=pow((Swtt[1]/Sw[1])-(Swt[1]/Sw[1])*(Swt[1]/Sw[1]),0.5);}
02747           ChiSqNegative=Csigma[1]; ChiSqNdfNeg=npts[1]-1; 
02748           Ctrunc[1]=Csigma[1]+3.;
02749         }
02750         
02751       }
02752   }
02753   // Set these properties
02754   cth.SetTimeForwardFitRMS(ChiSqPositive);
02755   cth.SetTimeForwardFitNDOF(ChiSqNdfPos);
02756   cth.SetTimeBackwardFitRMS(ChiSqNegative);
02757   cth.SetTimeBackwardFitNDOF(ChiSqNdfNeg);
02759    
02760 }
02762 
02763 
02764 
02766 void AlgFitTrackCam::SetRangeAnddS(CandFitTrackCamHandle& cth)
02767 {
02768 
02769   // Set range and dS as calculated by the swimmer
02770   MSG("AlgFitTrackCam",Msg::kDebug) << "SetRangeAnddS from swimmer values " << endl;
02771 
02772   UgliGeomHandle ugh = UgliGeomHandle(*vldc);
02773 
02774   int ZDir; int VtxPlane; int EndPlane; int Increment;
02775   DetectorType::Detector_t Detector = vldc->GetDetector();
02776   double dS; double dRange; double dP;
02777 
02778 
02779   // Start at the end of the track and calculate the required additions to range
02781 
02782   // find ending Z position (defined as Z position where muon has 100 MeV of residual energy.  This corresponds to 1/2 inch of Fe.
02783 
02784   // NOTE: Average dP for 1" iron is 95 MeV.
02785  
02786   if(ZIncreasesWithTime==true) {ZDir=1; EndPlane=MaxPlane; VtxPlane=MinPlane; Increment=-1;}
02787   else {ZDir=-1; EndPlane=MinPlane; VtxPlane=MaxPlane; Increment=1;}
02788 
02789   PlexPlaneId plnid(Detector,EndPlane,false);
02790   PlexPlaneId endplnid(Detector,EndPlane,false);
02791 
02792   double Zscint = SlcStripData[EndPlane][0].csh->GetZPos();
02793   double Znextscint = Zscint;
02794 
02795   UgliScintPlnHandle scintpln = ugh.GetScintPlnHandle(plnid); 
02796   double Zend = Zscint + double(ZDir)*scintpln.GetHalfThickness();
02797 
02798 
02799   PlexPlaneId nextscint =  endplnid.GetAdjoinScint(ZDir);
02800   UgliScintPlnHandle nextscintpln = ugh.GetScintPlnHandle(nextscint);
02801   if(nextscintpln.IsValid() && nextscint.GetPlaneView()!=PlaneView::kUnknown){
02802     Znextscint = nextscintpln.GetZ0();
02803   }
02804   else{
02805     nextscint = endplnid;
02806   }
02807 
02808   plnid = plnid.GetAdjoinSteel(ZDir);
02809   if(plnid.IsValid()){
02810     UgliSteelPlnHandle steelpln = ugh.GetSteelPlnHandle(plnid);
02811     Zend = steelpln.GetZ0() - double(ZDir)*steelpln.GetHalfThickness();
02812   }
02813 
02814   // add two planes of steel for the ND spectrometer
02815   if(Detector==DetectorType::kNear && EndPlane>=121) {
02816     for(int i=0;i<2;i++){
02817       if(plnid.GetAdjoinSteel(ZDir).IsValid()){
02818         PlexPlaneId plnid_after = plnid.GetAdjoinSteel(ZDir);
02819         if(plnid_after.IsValid()) {
02820           plnid = plnid_after;
02821           UgliSteelPlnHandle steelpln = ugh.GetSteelPlnHandle(plnid);
02822           Zend = steelpln.GetZ0() - double(ZDir)*steelpln.GetHalfThickness();
02823         }
02824       }
02825     }
02826   }
02827 
02828   // Determine whether track stops in coil
02829   float u_end = FilteredData[EndPlane][0].x_k0;
02830   float v_end = FilteredData[EndPlane][0].x_k1;
02831   float du_end = FilteredData[EndPlane][0].x_k2;
02832   float dv_end = FilteredData[EndPlane][0].x_k3;
02833   float delz = Znextscint-Zscint;
02834   float u_extrap = u_end +delz*du_end;
02835   float v_extrap = v_end +delz*dv_end;
02836   float x_extrap = 0.707*(u_extrap-v_extrap);
02837   float y_extrap = 0.707*(u_extrap+v_extrap);
02838 
02839   PlaneCoverage::PlaneCoverage_t kPC = PlaneCoverage::kComplete;
02840   if(Detector==DetectorType::kNear) kPC=PlaneCoverage::kNearFull;
02841 
02842   bool isInOutline = fPL.IsInside(x_extrap,y_extrap,nextscint.GetPlaneView(),kPC,false);
02843   bool isInCoil = isInOutline && !fPL.IsInside(x_extrap,y_extrap,nextscint.GetPlaneView(),kPC,true);
02844   double S = 0; double Range = 0; double Prange = 0.0;
02845   double StateVector[5]; double Output[5];
02846   double chargesign = -1;
02847   bool GoForward = true; bool done=true; bool swimOK=true;
02848   cout << "r " << TMath::Sqrt(u_end*u_end+v_end*v_end) << " " <<  TMath::Sqrt(u_extrap*u_extrap+v_extrap*v_extrap) << endl;
02849   // if in coil find midpoint and swim upstream from there
02850   if(isInCoil){
02851     float zCoil = Znextscint;
02852     float u_extrapC = u_extrap;
02853     float v_extrapC = v_extrap;
02854     float x_extrapC = x_extrap;
02855     float y_extrapC = y_extrap;
02856     while(isInCoil){
02857       zCoil -= 1.0*Munits::cm*ZDir;
02858       float delzC = zCoil - Zscint;
02859       u_extrapC = u_end +delzC*du_end;
02860       v_extrapC = v_end +delzC*dv_end;
02861       x_extrapC = 0.707*(u_extrapC-v_extrapC);
02862       y_extrapC = 0.707*(u_extrapC+v_extrapC);
02863       isInCoil = !fPL.IsInside(x_extrapC,y_extrapC,nextscint.GetPlaneView(),kPC,true);        
02864     }
02865     float zMinCoil = zCoil;
02866     if(zMinCoil<Zscint) zMinCoil=Zscint;
02867   
02868     zCoil = Znextscint;
02869     isInCoil = true;
02870     while(isInCoil){
02871       zCoil += 1.0*Munits::cm*ZDir;
02872       float delzC = zCoil - Zscint;
02873       u_extrapC = u_end +delzC*du_end;
02874       v_extrapC = v_end +delzC*dv_end;
02875       x_extrapC = 0.707*(u_extrapC-v_extrapC);
02876       y_extrapC = 0.707*(u_extrapC+v_extrapC);
02877       isInCoil = !fPL.IsInside(x_extrapC,y_extrapC,nextscint.GetPlaneView(),kPC,true);        
02878     }
02879     float zMaxCoil = zCoil;
02880     float zmin; float zmax;
02881     ugh.GetZExtent(zmin,zmax);
02882     if(zMaxCoil>zmax)zMaxCoil=zmax;
02883 
02884     // now swim from mid-coil back to endplane
02885     float zMidCoil = 0.5*(zMinCoil + zMaxCoil);
02886     float delzC  = zMidCoil -Zscint;
02887     u_extrapC = u_end +delzC*du_end;
02888     v_extrapC = v_end +delzC*dv_end;
02889     x_extrapC = 0.707*(u_extrapC-v_extrapC);
02890     y_extrapC = 0.707*(u_extrapC+v_extrapC);
02891     
02892     StateVector[0] = u_extrapC; Output[0]=StateVector[0];
02893     StateVector[1] = v_extrapC; Output[1]=StateVector[1];
02894     StateVector[2] = FilteredData[EndPlane][0].x_k2; Output[2]=StateVector[2];
02895     StateVector[3] = FilteredData[EndPlane][0].x_k3; Output[3]=StateVector[3];
02896     chargesign = -1;
02897     if(FilteredData[EndPlane][0].x_k4!=0.) {chargesign =  FilteredData[EndPlane][0].x_k4/fabs(FilteredData[EndPlane][0].x_k4);}
02898     
02899     GoForward = !ZIncreasesWithTime;
02900     StateVector[4] = 10.*chargesign; Output[4]=StateVector[4]; 
02901 
02902     double dsdz = pow((1. + pow(StateVector[2],2) + pow(StateVector[3],2)),0.5);    
02903 
02904     // set fallback to nominal energy loss in case coil swim fails
02905     Prange = 0.095*dsdz;
02906     if(Detector==DetectorType::kNear && EndPlane>121) Prange = 0.2*dsdz;  
02907     Prange += 0.5*dsdz*0.1*fabs(zMaxCoil-zMinCoil)*2.357*1.97;
02908 
02909     swimOK = Swim(StateVector, Output, zMidCoil, EndPlane , GoForward, &dS, &dRange, &dP);
02910     cout << " Z coil range " << zMinCoil << "/" << zMaxCoil << "/" << Zscint << " " << swimOK << endl;
02911     if(swimOK ){
02912       S = dS; Range = dRange; Prange = fabs(dP);
02913       cth.SetdS(EndPlane,S); 
02914       cth.SetRange(EndPlane,Range);
02915     }
02916     if(!swimOK) {Output[4] = chargesign/Prange;}
02917     cout <<  " *** Coil **** " << Zscint-zMidCoil << " " << Prange << endl;
02918   }
02919 
02920   else{
02921     // normal case - track does not end in coil
02922     if((Zend<Zscint && ZDir==1) || (Zend>Zscint && ZDir==-1)) {
02923       MSG("AlgFitTrackCam",Msg::kWarning) << " Zend on wrong side of last scint! " << endl;
02924       Zend=Zscint;
02925     }
02926     
02927     // now swim to Zend
02928     StateVector[0]=FilteredData[EndPlane][0].x_k0; Output[0]=StateVector[0];
02929     StateVector[1]=FilteredData[EndPlane][0].x_k1; Output[1]=StateVector[1];
02930     StateVector[2]=FilteredData[EndPlane][0].x_k2; Output[2]=StateVector[2];
02931     StateVector[3]=FilteredData[EndPlane][0].x_k3; Output[3]=StateVector[3];
02932     StateVector[4]=FilteredData[EndPlane][0].x_k4; Output[4]=StateVector[4];
02933     chargesign = -1;
02934     if(StateVector[4]!=0.) {chargesign = StateVector[4]/fabs(StateVector[4]);}
02935     
02936     GoForward = ZIncreasesWithTime;
02937     done = Swim(StateVector, Output, EndPlane, Zend, GoForward,  &dS, &dRange, &dP);
02938     
02939     GoForward = !ZIncreasesWithTime;
02940     double dsdz = pow((1. + pow(StateVector[2],2) + pow(StateVector[3],2)),0.5); 
02941     S = 0; Range = 10.0*dsdz; Prange = 0.095*dsdz;
02942     swimOK = false;
02943     if(done){
02944       for(int j=0;j<5;j++) {StateVector[j]=Output[j];}
02945       
02946       // now swim from Zend to EndPlane
02947       StateVector[4] = chargesign * 10.52;  // start @ P = 100 MeV (Eloss in 1/2 " Iron)
02948       swimOK = Swim(StateVector, Output, Zend, EndPlane , GoForward, &dS, &dRange, &dP);
02949       if(swimOK){
02950         S += dS; Range += dRange; Prange += fabs(dP);
02951         cth.SetdS(EndPlane,S); 
02952         cth.SetRange(EndPlane,Range);
02953       }
02954     }
02955     if(!swimOK) {Output[4] = chargesign/Prange;}
02956     cout << " no coil " << Prange << " " << dsdz << " " << dS <<  endl;
02957   }
02958   
02959   int thisplane = EndPlane;
02960   // now swim back to vertex
02961   bool firstplane=true;
02962  for(int i=EndPlane+Increment; Increment*i<=Increment*VtxPlane; i+=Increment) {
02963     if(FilteredData[i].size()>0) {
02964       double delU = FilteredData[i][0].x_k0 - StateVector[0] ;
02965       double delV = FilteredData[i][0].x_k1 - StateVector[1] ;
02966       double dSperPlane=0.;
02967       if(thisplane!=i) {dSperPlane = pow(delU*delU + delV*delV,0.5)/double(abs(thisplane-i));}
02968 
02969       // only update state vector if change in U/V is reasonable.
02970       if(dSperPlane < 1.5*Munits::m) {
02971         StateVector[0]=FilteredData[i][0].x_k0;
02972         StateVector[1]=FilteredData[i][0].x_k1;
02973         StateVector[2]=FilteredData[i][0].x_k2;
02974         StateVector[3]=FilteredData[i][0].x_k3;
02975 
02976         chargesign=-1;
02977         if(FilteredData[i][0].x_k4!=0.) {chargesign = FilteredData[i][0].x_k4/fabs(FilteredData[i][0].x_k4);}
02978       }
02979 
02980       StateVector[4] = chargesign * fabs(Output[4]);
02981       done = Swim(StateVector, Output, thisplane, i , GoForward, &dS, &dRange, &dP);
02982       if(done){
02983         S+=dS; Range+=dRange; Prange+=fabs(dP);
02984         cth.SetdS(i,S); cth.SetRange(i,Range);
02985         if(firstplane) cout << " first prange " << Prange << " " << EndPlane << " " << i << " " << dS <<  endl;
02986         firstplane=false;
02987       }
02988       else {
02989         MSG("AlgFitTrackCam",Msg::kDebug) << " swim fail " << endl;
02990       }
02991       thisplane=i;
02992     }
02993   }
02994 
02995   PlexPlaneId vtxplnid(Detector,VtxPlane,false);
02996   PlexPlaneId plnid_before = vtxplnid.GetAdjoinSteel(-ZDir);
02997   
02998   if(plnid_before.IsValid()) {
02999     plnid = plnid_before;
03000     UgliSteelPlnHandle steelpln = ugh.GetSteelPlnHandle(plnid);
03001     double Zstart = steelpln.GetZ0();
03002     StateVector[0]=FilteredData[VtxPlane][0].x_k0;
03003     StateVector[1]=FilteredData[VtxPlane][0].x_k1;
03004     StateVector[2]=FilteredData[VtxPlane][0].x_k2;
03005     StateVector[3]=FilteredData[VtxPlane][0].x_k3;
03006     StateVector[4]=Output[4];
03007     Swim(StateVector, Output, VtxPlane, Zstart, GoForward, &dS,&dRange,&dP);
03008     S+=dS; Range+=dRange; Prange+=fabs(dP);
03009 
03010     cth.SetRange(VtxPlane,Range);
03011     cth.SetdS(VtxPlane,S);
03012   }
03013 
03014   // if Prange < 21 GeV, use this value.  Otherwise, use finder track energy, which is somewhat less prone to gross errors.
03015  
03016   // apply fudge factor for nominal steel thickness in ND geometry.
03017   //********* !!!!!!!!!!!!! ***********
03018   float ecorr = 1.0;
03019  if(vldc->GetDetector()==DetectorType::kNear && vldc->GetSimFlag()==SimFlag::kData) ecorr = 1.008; 
03020   
03021   cth.SetMomentumRange(Prange*ecorr);
03022   CandTrackHandle* findertrack = cth.GetFinderTrack();
03023   if(((Detector==DetectorType::kFar && Prange>21.) || (Detector==DetectorType::kNear && Prange>12.)) && findertrack) {cth.SetMomentumRange(findertrack->GetMomentum());}
03024 
03025 }
03027 
03028 
03029 
03031 void AlgFitTrackCam::SetPropertiesFromFinderTrack(CandFitTrackCamHandle &cth)
03032 {
03033   // This method is only called if the fit fails. We set properties from finder track.
03034   // This clearly does not include fitted properties such as q/p or QPVtxError.
03035  MSG("AlgFitTrackCam",Msg::kDebug) << "SetPropertiesFromFinderTrack" << endl;
03036   cth.SetDirCosU(track->GetDirCosU());
03037   cth.SetDirCosV(track->GetDirCosV());
03038   cth.SetDirCosZ(track->GetDirCosZ());
03039   cth.SetVtxU(track->GetVtxU());
03040   cth.SetVtxV(track->GetVtxV());
03041   cth.SetVtxZ(track->GetVtxZ());
03042   cth.SetVtxT(track->GetVtxT());
03043   cth.SetVtxPlane(track->GetVtxPlane());
03044 
03045   cth.SetEndDirCosU(track->GetEndDirCosU());
03046   cth.SetEndDirCosV(track->GetEndDirCosV());
03047   cth.SetEndDirCosZ(track->GetEndDirCosZ());
03048   cth.SetEndU(track->GetEndU());
03049   cth.SetEndV(track->GetEndV());
03050   cth.SetEndZ(track->GetEndZ());
03051   cth.SetEndT(track->GetEndT());
03052   cth.SetEndPlane(track->GetEndPlane());
03053 
03054   cth.SetMomentumRange(track->GetMomentum());
03055   cth.SetMomentum(track->GetMomentum());
03056 
03057   cth.SetTimeSlope(track->GetTimeSlope());
03058   cth.SetTimeOffset(track->GetTimeOffset());
03059   cth.SetTimeFitChi2(track->GetTimeFitChi2());
03060   cth.SetNTimeFitDigit(track->GetNTimeFitDigit());
03061   cth.SetTimeForwardFitRMS(track->GetTimeForwardFitRMS());
03062   cth.SetTimeForwardFitNDOF(track->GetTimeForwardFitNDOF());
03063   cth.SetTimeBackwardFitRMS(track->GetTimeBackwardFitRMS());
03064   cth.SetTimeBackwardFitNDOF(track->GetTimeBackwardFitNDOF());
03065 
03066 
03067   // Set quantities required at each plane in finder track
03068   int direction=1;
03069   if(ZIncreasesWithTime==false) {direction=-1;}
03070 
03071   for(int i=cth.GetVtxPlane(); i*direction<=cth.GetEndPlane()*direction; i+=direction){
03072     if(track->IsTPosValid(i)) {
03073       cth.SetTrackPointError(i,track->GetTrackPointError(i));
03074       cth.SetdS(i,track->GetdS(i));
03075       cth.SetRange(i,track->GetRange(i));
03076       cth.SetU(i,track->GetU(i));
03077       cth.SetV(i,track->GetV(i));
03078     }
03079   }
03080 
03081   CalculateTrace(cth);  
03082   SetT(&cth);
03083 
03084   Calibrator& cal = Calibrator::Instance();
03085   cal.ReInitialise(*vldc);
03086   Calibrate(&cth);
03087 
03088 
03089 }
03091 
03092 
03093 
03094 
03096 void AlgFitTrackCam::GenerateNDSpectStrips(const CandSliceHandle *slice,CandContext &cx)
03097 {
03098   MSG("AlgFitTrackCam",Msg::kDebug) << "GenerateNDSpectStrips" << endl;
03099 
03100   bool AlreadyAssigned;
03101 
03102 
03103   CandContext cxx(this,cx.GetMom());
03104 
03105   // Get singleton instance of AlgFactory
03106   AlgFactory &af = AlgFactory::GetInstance();
03107   AlgHandle stripah = af.GetAlgHandle("AlgStripSR","default");
03108 
03109   // Store CandStripHandles and make the strips accessible by plane number
03110   TIter SlcStripItr = slice->GetDaughterIterator();
03111   StripStruct temp;
03112   
03113   // Store all strips in slice
03114   while(CandStripHandle* SlcStrip = dynamic_cast<CandStripHandle*>(SlcStripItr()))  {
03115     if (SlcStrip->GetPlane()>120 && (SlcStrip->GetPlaneView()==PlaneView::kU || SlcStrip->GetPlaneView()==PlaneView::kV) ) {
03116       AlreadyAssigned=false;
03117       
03118       TIter digitItr(SlcStrip->GetDaughterIterator());
03119       CandDigitHandle* dig = dynamic_cast<CandDigitHandle*>(digitItr());              
03120       const PlexSEIdAltL& altl = dig->GetPlexSEIdAltL();
03121       int siz = altl.size();
03122       
03123       for (int ind = 0; ind<siz; ++ind) {
03124         // Only want to make the single copy of an assigned strip
03125         if(AlreadyAssigned) {break;}
03126         
03127         TObjArray diglist;  
03128         TIter newstripdauItr(SlcStrip->GetDaughterIterator());
03129         
03130         while(CandDigitHandle* olddig = dynamic_cast<CandDigitHandle*>(newstripdauItr())) {
03131           CandDigitHandle* newdig = olddig->DupHandle();
03132           PlexSEIdAltL& newaltl = newdig->GetPlexSEIdAltLWritable(); 
03133           
03134           // Don't make any strips which have already been assigned to a 'better' track
03135           if(NumFinderStrips<=newaltl.GetBestWeight()) {AlreadyAssigned=true; delete newdig;}
03136           else {
03137             for (int newind = 0; newind < siz; ++newind) {
03138               if(newind==ind){newaltl[newind].SetWeight((float)NumFinderStrips);}
03139               else{newaltl[newind].SetWeight((float)0.);}
03140             }
03141             
03142             newdig->SetCandRecord(olddig->GetCandRecord());
03143             diglist.Add(newdig);   // diglist does not own newdig. These must be explicitly deleted 
03144           }
03145         
03146         }
03147         // Only make a new strip if we have any digits  
03148         if(1+diglist.GetLast()>0) {
03149           cxx.SetDataIn(&diglist);
03150           CandStripHandle newstrip = CandStrip::MakeCandidate(stripah,cxx);
03151           newstrip.SetCandRecord(slice->GetCandRecord());
03152           CandStripHandle* daustrip = new CandStripHandle(newstrip);
03153           
03154           for (int i=0; i<=diglist.GetLast(); ++i) {
03155             CandDigitHandle* deldig =  dynamic_cast<CandDigitHandle*>(diglist.At(i));
03156             delete deldig;
03157           }
03158           temp.csh=daustrip;      
03159           SlcStripData[SlcStrip->GetPlane()].push_back(temp);
03160         }
03161       }
03162     }
03163   }
03164   SlcStripItr.Reset();
03165 }
03166 
03168 
03169 
03170 
03172 void AlgFitTrackCam::SpectrometerSwim(CandFitTrackCamHandle &cth)
03173 {
03174   MSG("AlgFitTrackCam",Msg::kDebug) << "SpectrometerSwim, improved track finding in spectrometer" << endl;
03175 
03176   // Initialisations
03177   // Sort out the lists for the ND spectrometer
03178   bool AddedStrip = false;
03179   int Plane; int NewPlane;
03180   double StateVector[5]; double NState[5]; double temp_x_k[5];
03181   bool GoForward; bool SpectSwim;
03182   int ActivePlanesSinceLastHit=0;
03183   int PlaneView; int Increment; int Counter;
03184   double LastHitTimes[2]={MeanTrackTime,MeanTrackTime};
03185   double TimeWindow=40.e-9;
03186 
03187   double StripDistance; double MinDistanceToStrip;
03188   double SwimError2;
03189   double StripWidth = 4.108e-2;
03190   double PlanePitch = 0.0594;
03191 
03192   bool TrackInActiveRegion;
03193   GoForward=true; Plane=MaxPlane; Increment=1;
03194 
03195   // Linear extrapolation from end of track to start of spectrometer.
03196   // Count number of active planes  
03197   while(ActivePlanesSinceLastHit<6 && Plane<121) {
03198     Plane += Increment;
03199     double u = x_k_minus[0] + x_k_minus[2]*(Plane-MaxPlane)*PlanePitch;
03200     double v = x_k_minus[1] + x_k_minus[3]*(Plane-MaxPlane)*PlanePitch;
03201     if (NDPlaneIsActive(Plane, u, v, 0.3)) ActivePlanesSinceLastHit++;
03202   }
03203 
03204   // If we are clearly not near spectrometer, return from method
03205   if(ActivePlanesSinceLastHit>5 || abs(121-MaxPlane)>=40) {return;}
03206 
03207   // Set initial positions for swim
03208   ActivePlanesSinceLastHit=0;
03209   Plane = MaxPlane;  NewPlane = Plane+1;
03210 
03211   // Continue until we reach a 8 plane gap (counting only active planes) since prior
03212   // hit or we reach the end of the detector
03213   while(ActivePlanesSinceLastHit<8 && abs(NewPlane-Plane)<=70 && NewPlane<=290 && PassTrack==true) {
03214     
03215     PlexPlaneId plexPlane(DetectorType::kNear,NewPlane, 0); 
03216     if(SlcStripData[NewPlane].size()>0 && plexPlane.IsValid() && plexPlane.GetPlaneCoverage()!=PlaneCoverage::kNoActive) {
03217 
03218       if(SlcStripData[NewPlane][0].csh->GetPlaneView()==2) {PlaneView=0;}
03219       else {PlaneView=1;}
03220       
03221       for(int i=0; i<5; ++i) {StateVector[i]=x_k_minus[i];}
03222 
03223       // For the purposes of spectrometer track hit finding, don't allow track to range out before
03224       // we have swum all the hit spectrometer planes in this slice
03225       SpectSwim = Swim(StateVector, NState, Plane, NewPlane, GoForward);
03226 
03227       // If swim has failed and there is a large gap to next hit plane, stop the spectrometer swim.
03228       if(!SpectSwim && (NewPlane-Plane)>=40) {
03229         break;}
03230 
03231       // If swim has failed, but there is no large gap, make a momentum correction and swim again.
03232       if(!SpectSwim && StateVector[4]!=0) {
03233         Counter=0;
03234         // Double momentum and attempt to swim again
03235         while(!SpectSwim && Counter<2) {
03236           StateVector[4]*=0.5;  
03237           SpectSwim = Swim(StateVector, NState, Plane, NewPlane, GoForward);
03238           
03239           if(!SpectSwim) {Counter++;}
03240         }
03241       }
03242       
03243       if(!SpectSwim) {break;}
03244 
03245       for(int i=0; i<5; ++i) {temp_x_k[i]=NState[i];}
03246 
03247       // Calculate error in track extrapolation, based on covariance matrix on-diagonal elements
03248       SwimError2 = C_k[PlaneView][PlaneView] + (C_k[PlaneView+2][PlaneView+2]*PlanePitch*PlanePitch*(NewPlane-Plane)*(NewPlane-Plane)); 
03249       MinDistanceToStrip = 3.0 * pow(StripWidth*StripWidth + SwimError2,0.5);
03250       
03251 
03252       // Find the closest strip (within a distance 'MinDistanceToStrip') and temporarily store CandStripHandle
03253       CandStripHandle* CurrentStrip = 0;      
03254       for(unsigned int j=0; j<SlcStripData[NewPlane].size(); ++j) {
03255         StripDistance = fabs(SlcStripData[NewPlane][j].csh->GetTPos()-temp_x_k[PlaneView]);
03256 
03257         if(StripDistance<MinDistanceToStrip 
03258            && fabs(0.5*(LastHitTimes[0]+LastHitTimes[1])-NDStripBegTime(SlcStripData[NewPlane][j].csh,temp_x_k[0],temp_x_k[1]))<TimeWindow) {
03259           MinDistanceToStrip=StripDistance;
03260           CurrentStrip=SlcStripData[NewPlane][j].csh;
03261         }
03262       }
03263 
03264       // If we find a likely track strip, add it to the fit data and call the Kalman
03265       // update equations before repeating process to find next track strips in the shower
03266       if(CurrentStrip) {
03267         LastHitTimes[1]=LastHitTimes[0];
03268         LastHitTimes[0]=NDStripBegTime(CurrentStrip,temp_x_k[0],temp_x_k[1]);
03269 
03270         StripStruct temp;
03271         temp.csh = CurrentStrip;
03272         InitTrkStripData[NewPlane].push_back(temp);
03273         
03274         // Convert the strip to data required for Kalman fit
03275         GetFitData(NewPlane,NewPlane);
03276         
03277         // Carry out the Kalman fit
03278         if (PlaneView==1) {H_k[0]=0; H_k[1]=1; H_k[2]=0; H_k[3]=0; H_k[4]=0;}
03279         else {H_k[0]=1; H_k[1]=0; H_k[2]=0; H_k[3]=0; H_k[4]=0;}
03280         
03281         bool CombiPropagatorOk = GetCombiPropagator(Plane,NewPlane,GoForward);
03282 
03283         if(CombiPropagatorOk) {
03284           GetNoiseMatrix(Plane,NewPlane);
03285           ExtrapCovMatrix();
03286           CalcKalmanGain(NewPlane);
03287           UpdateStateVector(Plane,NewPlane,GoForward);
03288           UpdateCovMatrix();
03289           MoveArrays();
03290           StoreFilteredData(NewPlane);
03291           
03292           MaxPlane=NewPlane; Plane=MaxPlane;
03293           NewPlane=Plane+Increment;
03294           
03295           ActivePlanesSinceLastHit=0;
03296         }
03297 
03298         // Extend finder track, including the ND Spectrometer hits found in the fit
03300 
03301        
03302         CandTrackHandle * findertrack = cth.GetFinderTrack();
03303         if(findertrack) {
03304           bool SlushyOnEntry = CandHandle::IsSlushyEnabled();
03305           CandHandle::SetSlushyEnabled(kTRUE);
03306           AddedStrip = true;
03307           findertrack->AddDaughterLink(*CurrentStrip);
03308           findertrack->SetEndPlane(CurrentStrip->GetPlane());
03309           findertrack->SetEndZ(CurrentStrip->GetZPos());
03310           findertrack->SetEndU(FilteredData[CurrentStrip->GetPlane()][0].x_k0);
03311           findertrack->SetEndV(FilteredData[CurrentStrip->GetPlane()][0].x_k1);
03312           findertrack->SetEndDirCosU(FilteredData[CurrentStrip->GetPlane()][0].x_k2);
03313           findertrack->SetEndDirCosV(FilteredData[CurrentStrip->GetPlane()][0].x_k3);
03314           if(!SlushyOnEntry) CandHandle::SetSlushyEnabled(kFALSE);
03315         }
03317         
03318       }
03319       else {
03320         TrackInActiveRegion=NDPlaneIsActive(NewPlane, temp_x_k[0], temp_x_k[1], 0.3);
03321         if(plexPlane.IsValid() && plexPlane.GetPlaneCoverage()!=PlaneCoverage::kNoActive && TrackInActiveRegion) 
03322           {ActivePlanesSinceLastHit++;}
03323         NewPlane+=Increment;
03324       }
03325     }
03326     else {
03327       double u = x_k_minus[0] + x_k_minus[2]*(NewPlane-Plane)*PlanePitch;
03328       double v = x_k_minus[1] + x_k_minus[3]*(NewPlane-Plane)*PlanePitch;
03329       
03330       TrackInActiveRegion=NDPlaneIsActive(NewPlane, u, v, 0.3); 
03331       
03332       if(plexPlane.IsValid() && plexPlane.GetPlaneCoverage()!=PlaneCoverage::kNoActive && TrackInActiveRegion) 
03333         {ActivePlanesSinceLastHit++;}
03334       NewPlane+=Increment; 
03335     }
03336   }
03337 
03338   
03339   // Sort out range and dS for finder track
03341   if(AddedStrip) {
03342     CandTrackHandle * findertrack = cth.GetFinderTrack();
03343     if(findertrack) {
03344       bool SlushyOnEntry = CandHandle::IsSlushyEnabled();
03345       CandHandle::SetSlushyEnabled(kTRUE);
03346       
03347       SetUVZT(findertrack);
03348       Double_t range = findertrack->GetRange();
03349       if (range>0.) {
03350         findertrack->SetMomentum(GetMomFromRange(range));   
03351       }
03352       if(!SlushyOnEntry) CandHandle::SetSlushyEnabled(kFALSE);
03353     }
03354   }
03356 
03357 }
03359 
03360 
03361 
03363 bool AlgFitTrackCam::NDPlaneIsActive(int plane, float u, float v, float projErr)
03364 { 
03365   // Method to determine whether this u/v position is active
03366 
03367   PlexPlaneId plexPlane(DetectorType::kNear,plane, 0); 
03368   if(!plexPlane.IsValid()) {return false;}
03369   if(plexPlane.GetPlaneCoverage()==PlaneCoverage::kNoActive) {return false;}
03370   if(projErr<0.3)projErr=0.3;
03371   float x = 0.707*(u-v);
03372   float y = 0.707*(u+v);
03373   float dist,xedge,yedge;
03374   fPL.DistanceToEdge(x, y,
03375                      plexPlane.GetPlaneView(),
03376                      plexPlane.GetPlaneCoverage(),
03377                      dist, xedge, yedge);
03378   bool isInside = fPL.IsInside(x, y,
03379                                plexPlane.GetPlaneView(),
03380                                plexPlane.GetPlaneCoverage());
03381   isInside &= dist>projErr;
03382 
03383   return isInside;
03384 }
03386 
03387 
03388 
03390 void AlgFitTrackCam::CleanNDLists(CandFitTrackHandle &cth,CandContext &cx)
03391 {
03392 
03393 
03394   // Sort out the lists for the ND spectrometer
03395 
03396   // Delete the strip handles created in GenerateNDSpectStrips.
03397   // All strip handles not added to a track daughter list are deleted here.
03399   for(int iplane=121; iplane<=290; ++iplane){
03400     for(unsigned int i=0; i<SlcStripData[iplane].size(); ++i){
03401       CandStripHandle* delstrip = SlcStripData[iplane][i].csh;
03402       delete delstrip; 
03403     }
03404   }
03406 
03407   bool SlushyOnEntry = CandHandle::IsSlushyEnabled();
03408   CandHandle::SetSlushyEnabled(kTRUE);
03409 
03410   // Get DigitList and StripList from CandRecord
03412   const MomNavigator* mom = cx.GetMom();
03413   CandRecord* crec = dynamic_cast<CandRecord *> (mom->GetFragment("CandRecord", "PrimaryCandidateRecord"));
03414 
03415   // DupHandle step added by gmieg.  Must delete StripList and DigitList.
03416   CandStripListHandle* StripListOH = dynamic_cast<CandStripListHandle *>
03417     (crec->FindCandHandle("CandStripListHandle"));
03418   CandStripListHandle* StripList = StripListOH->DupHandle();
03419 
03420   CandDigitListHandle* DigitListOH = dynamic_cast<CandDigitListHandle *>
03421     (crec->FindCandHandle("CandDigitListHandle","canddigitlist"));
03422   CandDigitListHandle* DigitList = DigitListOH->DupHandle();
03423 
03424   CandSliceHandle* Slice = dynamic_cast<CandSliceHandle*>(cth.GetCandSliceWritable());
03426 
03427  
03428   // Compare new fitted track, with DeMuxed spectrometer strips, 
03429   // to StripList, Slice and DigitList
03431   vector<CandStripHandle*> StripsToAdd;
03432   vector<CandStripHandle*> StripsToRemove;
03433 
03434   vector<CandStripHandle*> SliceStripsToAdd;
03435   vector<CandStripHandle*> SliceStripsToRemove;
03436 
03437   vector<CandDigitHandle*> DigitsToAdd;
03438   vector<CandDigitHandle*> DigitsToRemove;
03439 
03440 
03441   CandStripHandleItr TrkStripItr(cth.GetDaughterIterator());
03442   for(CandStripHandle* TrkStrip=TrkStripItr(); TrkStrip; TrkStrip=TrkStripItr()){
03443 
03444     if(TrkStrip->GetPlane()>120 ) {
03445       CandDigitHandleItr TrkDigitItr(TrkStrip->GetDaughterIterator());
03446       CandDigitHandle* TrkDigit = dynamic_cast<CandDigitHandle*>(TrkDigitItr());
03447 
03448       // Sort out StripList
03450       if(StripList) {
03451         bool AddedTrkStrip = false;
03452         CandStripHandleItr stripItr(StripList->GetDaughterIterator());
03453         
03454         for(CandStripHandle* strip=stripItr(); strip ; strip=stripItr()) {
03455           if(strip->GetPlane()==TrkStrip->GetPlane()){
03456             CandDigitHandleItr digitItr(strip->GetDaughterIterator());
03457             CandDigitHandle* digit = dynamic_cast<CandDigitHandle*>(digitItr());
03458             bool SameCandStrip = false;
03459             bool SameHit = false;
03460             
03461             if(TrkStrip->IsEqual(strip)) {SameCandStrip = true;}
03462             
03463             if(digit->GetChannelId()==TrkDigit->GetChannelId() &&
03464                strip->GetCharge(CalDigitType::kNone)==TrkStrip->GetCharge(CalDigitType::kNone))
03465               {SameHit=true;}
03466             
03467             if(!SameCandStrip && SameHit) {
03468               StripsToRemove.push_back(strip);
03469               if(!AddedTrkStrip) {StripsToAdd.push_back(TrkStrip);}
03470               AddedTrkStrip=true;
03471             }
03472           }
03473         }
03474       }
03476       
03477 
03478 
03479       // Sort out Slice
03481       if(Slice){
03482         bool AddedTrkStrip = false;
03483         CandStripHandleItr stripItr(Slice->GetDaughterIterator());
03484 
03485         for(CandStripHandle* strip=stripItr(); strip; strip=stripItr()) {
03486           if(strip->GetPlane()==TrkStrip->GetPlane()){
03487             CandDigitHandleItr digitItr(strip->GetDaughterIterator());
03488             CandDigitHandle* digit = dynamic_cast<CandDigitHandle*>(digitItr());
03489             bool SameCandStrip = false;
03490             bool SameHit = false;
03491 
03492             if(TrkStrip->IsEqual(strip)) {SameCandStrip=true;}
03493 
03494             if(digit->GetChannelId()==TrkDigit->GetChannelId() &&
03495                strip->GetCharge(CalDigitType::kNone)==TrkStrip->GetCharge(CalDigitType::kNone))
03496               {SameHit=true;}
03497 
03498             if(!SameCandStrip && SameHit) {
03499               SliceStripsToRemove.push_back(strip);
03500               if(!AddedTrkStrip) {SliceStripsToAdd.push_back(TrkStrip);}
03501               AddedTrkStrip=true;
03502             }
03503           }
03504         }
03505       }
03507 
03508 
03509       // Loop over track strip Digits, and rationalise DigitList
03511       if(DigitList) {
03512         CandDigitHandleItr TrkDigitItr2(TrkStrip->GetDaughterIterator());
03513         for(TrkDigit=TrkDigitItr2(); TrkDigit ; TrkDigit=TrkDigitItr2()) {
03514           bool AddedTrkDigit=false;
03515           CandDigitHandleItr DigitItr(DigitList->GetDaughterIterator());
03516 
03517           for(CandDigitHandle* digit=DigitItr(); digit; digit=DigitItr()) {
03518             bool SameCandDigit=false;
03519             bool SameHit=false;
03520 
03521             if(TrkDigit->IsEqual(digit)) {SameCandDigit=true;}
03522 
03523             if(digit->GetChannelId()==TrkDigit->GetChannelId() &&
03524                digit->GetCharge(CalDigitType::kNone)==TrkDigit->GetCharge(CalDigitType::kNone))
03525               {SameHit=true;}
03526 
03527             if(!SameCandDigit && SameHit) {
03528               DigitsToRemove.push_back(digit);
03529               if(!AddedTrkDigit) {DigitsToAdd.push_back(TrkDigit);}
03530               AddedTrkDigit=true;
03531             }
03532           }
03533         }
03534       }
03536     
03538     }
03539   } // End loop over track strips
03540 
03541 
03542   // Now make the actual modifications to the lists
03544   for(unsigned int i=0; i<StripsToAdd.size(); ++i) {StripList->AddDaughterLink(*(StripsToAdd[i]));}
03545   for(unsigned int i=0; i<StripsToRemove.size(); ++i) {StripList->RemoveDaughter(StripsToRemove[i]);}
03546   StripsToAdd.clear();
03547   StripsToRemove.clear();
03548 
03549   for(unsigned int i=0; i<SliceStripsToAdd.size(); ++i) {Slice->AddDaughterLink(*(SliceStripsToAdd[i]));}
03550   for(unsigned int i=0; i<SliceStripsToRemove.size(); ++i) {Slice->RemoveDaughter(SliceStripsToRemove[i]);}
03551   SliceStripsToAdd.clear();
03552   SliceStripsToRemove.clear();
03553 
03554   for(unsigned int i=0; i<DigitsToAdd.size(); ++i) {DigitList->AddDaughterLink(*(DigitsToAdd[i]));}
03555   for(unsigned int i=0; i<DigitsToRemove.size(); ++i) {DigitList->RemoveDaughter(DigitsToRemove[i]);}
03556   DigitsToAdd.clear();
03557   DigitsToRemove.clear();
03559 
03560   
03562 
03563   // Must delete DupHandle StripList and Digitlist (gmieg)
03564   delete StripList;
03565   delete DigitList;
03566 
03567   if(!SlushyOnEntry) CandHandle::SetSlushyEnabled(kFALSE); 
03568 }
03570 
03571 
03572 
03574 double AlgFitTrackCam::NDStripBegTime(CandStripHandle* Strip, double U, double V)
03575 {
03576   double BegTime=999; double Time=0;
03577   double Index=1.77; double DistFromCentre=0.; 
03578   double FibreDist=0.; double halfLength=0.;
03579 
03580   // Get from track. Otherwise, will have guessed using Swimmer
03581   if(U==0) {U=track->GetU(Strip->GetPlane());}
03582   if(V==0) {V=track->GetV(Strip->GetPlane());}
03583 
03584   StripEnd::StripEnd_t StpEnd = StripEnd::kUnknown;
03585   CandDigitHandle* digit;
03586   
03587   UgliGeomHandle ugh = UgliGeomHandle(*vldc);
03588   UgliStripHandle Striphandle;
03589 
03590   CandDigitHandleItr digitItr(Strip->GetDaughterIterator());
03591 
03592 
03593   // Loop over digits on Strip. 
03595   while( (digit = digitItr()) ) { 
03596     StpEnd=digit->GetPlexSEIdAltL().GetEnd();
03597     
03598     if(StpEnd==StripEnd::kPositive) {
03599       FibreDist = 0.; DistFromCentre = 0.; Time=0.;
03600       UgliStripHandle StripHandle = ugh.GetStripHandle(Strip->GetStripEndId());
03601       halfLength = StripHandle.GetHalfLength(); 
03602       
03603       if(Strip->GetPlaneView()==2) {DistFromCentre = V;}
03604       if(Strip->GetPlaneView()==3) {DistFromCentre = -U;}
03605               
03606       FibreDist = (halfLength + DistFromCentre + StripHandle.ClearFiber(StpEnd) 
03607                    + StripHandle.WlsPigtail(StpEnd));
03608       
03609       Time = digit->GetSubtractedTime(CalTimeType::kT0) - (Index/3.e8)*FibreDist;
03610 
03611       if(Time<BegTime) {BegTime=Time;}
03612     }
03613   }
03614   
03615   return BegTime;
03616 }
03618 
03619 
03620 
03622 void AlgFitTrackCam::Trace(const char * /* c */) const
03623 {
03624 }

Generated on Thu Nov 1 11:49:10 2007 for loon by  doxygen 1.3.9.1