CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_8_patch3/src/TrackingTools/TrackFitters/src/KFFittingSmoother.cc

Go to the documentation of this file.
00001 #include "TrackingTools/TrackFitters/interface/KFFittingSmoother.h"
00002 // #include "TrackingTools/MaterialEffects/interface/PropagatorWithMaterial.h"
00003 #include "TrackingTools/KalmanUpdators/interface/KFUpdator.h"
00004 #include "TrackingTools/TrackFitters/interface/KFTrajectoryFitter.h"
00005 #include "TrackingTools/TrackFitters/interface/KFTrajectorySmoother.h"
00006 #include "TrackingTools/GeomPropagators/interface/AnalyticalPropagator.h"
00007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00008 #include "TrackingTools/TransientTrackingRecHit/interface/InvalidTransientRecHit.h"
00009 
00010 // ggiurgiu@fnal.gov: Add headers needed to cut on pixel hit probability
00011 #include "DataFormats/TrackerRecHit2D/interface/SiPixelRecHit.h"
00012 #include "DataFormats/SiPixelDetId/interface/PXBDetId.h"
00013 #include "DataFormats/SiPixelDetId/interface/PXFDetId.h"
00014 #include <cmath>
00015 
00016 using namespace std;
00017 
00018 KFFittingSmoother::~KFFittingSmoother() 
00019 {
00020   delete theSmoother;
00021   delete theFitter;
00022 }
00023 
00024 vector<Trajectory> KFFittingSmoother::fit(const Trajectory& t) const 
00025 {
00026   vector<Trajectory> smoothed;
00027   if ( t.isValid() ) 
00028     { 
00029       vector<Trajectory> fitted = fitter()->fit(t);
00030       smoothingStep(fitted, smoothed);
00031     }
00032   return smoothed;
00033 }
00034 
00035 bool KFFittingSmoother::checkForNans(const Trajectory & theTraj) const
00036 {
00037   if (std::isnan(theTraj.chiSquared ())) return false;
00038   const std::vector<TrajectoryMeasurement> & vtm = theTraj.measurements();
00039   for (std::vector<TrajectoryMeasurement>::const_iterator tm=vtm.begin(); tm!=vtm.end();tm++) {
00040     if (std::isnan(tm->estimate())) return false;
00041     AlgebraicVector5 v = tm->updatedState ().localParameters ().vector();
00042     for (int i=0;i<5;++i) if (std::isnan(v[i])) return false;
00043     const AlgebraicSymMatrix55 & m = tm->updatedState ().curvilinearError ().matrix();
00044     for (int i=0;i<5;++i) 
00045       for (int j=0;j<(i+1);++j) if (std::isnan(m(i,j))) return false;
00046   }
00047   return true;
00048 }
00049 
00050 vector<Trajectory> KFFittingSmoother::fit(const TrajectorySeed& aSeed,
00051                                           const RecHitContainer& hits, 
00052                                           const TrajectoryStateOnSurface& firstPredTsos) const 
00053 {
00054   LogDebug("TrackFitters") << "In KFFittingSmoother::fit";
00055 
00056   //if(hits.empty()) return vector<Trajectory>(); // gio: moved later to optimize return value
00057   
00058   bool hasoutliers;
00059   bool has_low_pixel_prob; // ggiurgiu@fnal.gov: Add flag for pixel hits with low template probability
00060 
00061   // ggiurgiu@fnal.gov: If log(Prob) < -15.0 or if Prob <= 0.0 then set log(Prob) = -15.0
00062   double log_pixel_probability_lower_limit = -15.0;
00063 
00064   RecHitContainer myHits = hits; 
00065   vector<Trajectory> smoothed;
00066   vector<Trajectory> tmp_first;
00067 
00068   do
00069     {
00070       if ( hits.empty() ) 
00071         { 
00072           smoothed.clear(); 
00073           break; 
00074         }
00075       
00076       //if no outliers the fit is done only once
00077       //for (unsigned int j=0;j<myHits.size();j++) { 
00078       //if (myHits[j]->det()) 
00079       //LogTrace("TrackFitters") << "hit #:" << j+1 << " rawId=" << myHits[j]->det()->geographicalId().rawId() 
00080       //<< " validity=" << myHits[j]->isValid();
00081       //else
00082       //LogTrace("TrackFitters") << "hit #:" << j+1 << " Hit with no Det information";
00083       //}
00084       
00085       hasoutliers        = false;
00086       has_low_pixel_prob = false; // ggiurgiu@fnal.gov
00087       
00088       double cut = theEstimateCut;
00089       
00090       double log_pixel_prob_cut = theLogPixelProbabilityCut;  // ggiurgiu@fnal.gov
00091       
00092       
00093       unsigned int outlierId = 0;
00094       const GeomDet* outlierDet = 0;
00095       
00096       unsigned int low_pixel_prob_Id = 0; // ggiurgiu@fnal.gov
00097       const GeomDet* low_pixel_prob_Det = 0; // ggiurgiu@fnal.gov
00098       
00099       //call the fitter
00100       vector<Trajectory> fitted = fitter()->fit(aSeed, myHits, firstPredTsos);
00101       //call the smoother
00102       smoothed.clear();
00103       smoothingStep(fitted, smoothed);
00104       
00105       //if (tmp_first.size()==0) tmp_first = smoothed; moved later
00106       
00107       if ( smoothed.empty() ) 
00108         {
00109           if ( rejectTracksFlag )
00110             {
00111               LogTrace("TrackFitters") << "smoothed.size()==0 => trajectory rejected";
00112               //return vector<Trajectory>(); // break is enough to get this
00113             } 
00114           else 
00115             {
00116               LogTrace("TrackFitters") << "smoothed.size()==0 => returning orignal trajectory" ;
00117               smoothed.swap(tmp_first); // if first attempt, tmp_first would be empty anyway
00118             }
00119           break;
00120         } 
00121       //else {
00122       //LogTrace("TrackFitters") << "dump hits after smoothing";
00123       //Trajectory::DataContainer meas = smoothed[0].measurements();
00124       //for (Trajectory::DataContainer::iterator it=meas.begin();it!=meas.end();++it) {
00125       //LogTrace("TrackFitters") << "hit #" << meas.end()-it-1 << " validity=" << it->recHit()->isValid() 
00126       //<< " det=" << it->recHit()->geographicalId().rawId();
00127       //}
00128       //}
00129       if (!checkForNans(smoothed[0])) {
00130         edm::LogError("TrackNaN")<<"Track has NaN";
00131         smoothed.clear();
00132         break;
00133       }
00134       
00135       if ( theEstimateCut > 0 || log_pixel_prob_cut > log_pixel_probability_lower_limit ) 
00136         {
00137           if ( smoothed[0].foundHits() < theMinNumberOfHits ) 
00138             {
00139               if ( rejectTracksFlag ) 
00140                 {
00141                   LogTrace("TrackFitters") << "smoothed[0].foundHits()<theMinNumberOfHits => trajectory rejected";
00142                   smoothed.clear();
00143                   //return vector<Trajectory>(); // break is enough
00144                 } 
00145               else 
00146                 {
00147                   // it might be it's the first step
00148                   if ( !tmp_first.empty() ) 
00149                     { 
00150                       tmp_first.swap(smoothed); 
00151                     } 
00152                   
00153                   LogTrace("TrackFitters") 
00154                     << "smoothed[0].foundHits()<theMinNumberOfHits => returning orignal trajectory with chi2=" 
00155                     <<  smoothed[0].chiSquared() ;
00156                 }
00157               break;
00158             }
00159           
00160           // Check if there are outliers or low probability pixel rec hits
00161           const std::vector<TrajectoryMeasurement> & vtm = smoothed[0].measurements();
00162           
00163           double log_pixel_hit_probability = -999999.9;
00164           
00165           for (std::vector<TrajectoryMeasurement>::const_iterator tm=vtm.begin(); tm!=vtm.end();tm++)
00166             {
00167               double estimate = tm->estimate();
00168               
00169               // --- here is the block of code about generic chi2-based Outlier Rejection ---
00170               if ( estimate > cut && theEstimateCut > 0 ) 
00171                 {
00172                   hasoutliers = true;
00173                   cut = estimate;
00174                   outlierId  = tm->recHit()->geographicalId().rawId();
00175                   outlierDet = tm->recHit()->det();
00176                 }
00177               // --- here the block of code about generic chi2-based Outlier Rejection ends ---
00178 
00179 
00180               // --- here is the block of code about PXL Outlier Rejection ---
00181               if(log_pixel_prob_cut > log_pixel_probability_lower_limit){ 
00182                 // TO BE FIXED: the following code should really be moved into an external class or 
00183                 // at least in a separate function. Current solution is ugly!
00184                 // The KFFittingSmoother shouldn't handle the details of 
00185                 // Outliers identification and rejection. It shoudl just fit tracks.
00186 
00187                 // ggiurgiu@fnal.gov: Get pixel hit probability here 
00188                 TransientTrackingRecHit::ConstRecHitPointer hit = tm->recHit();
00189                 unsigned int testSubDetID = ( hit->geographicalId().subdetId() );
00190                 
00191                 if ( hit->isValid() && 
00192                      hit->geographicalId().det() == DetId::Tracker && 
00193                      ( testSubDetID == PixelSubdetector::PixelBarrel || 
00194                        testSubDetID == PixelSubdetector::PixelEndcap )
00195                      )
00196                   {
00197                     // get the enclosed persistent hit
00198                     const TrackingRecHit* persistentHit = hit->hit();
00199                     
00200                     // check if it's not null, and if it's a valid pixel hit
00201                     if ( !persistentHit == 0 && 
00202                          typeid(*persistentHit) == typeid(SiPixelRecHit) ) 
00203                       {
00204                         
00205                         // tell the C++ compiler that the hit is a pixel hit
00206                         const SiPixelRecHit* pixhit = dynamic_cast<const SiPixelRecHit*>( hit->hit() );
00207                         
00208                         double pixel_hit_probability = (float)pixhit->clusterProbability(0);
00209                         
00210                         if ( pixel_hit_probability < 0.0 )
00211                           LogDebug("From KFFittingSmoother.cc") 
00212                             << "Wraning : Negative pixel hit probability !!!! Will set the probability to 10^{-15} !!!" << endl;
00213                         
00214                         if ( pixel_hit_probability <= 0.0 || log10( pixel_hit_probability ) < log_pixel_probability_lower_limit )  
00215                           log_pixel_hit_probability = log_pixel_probability_lower_limit; 
00216                         else 
00217                           log_pixel_hit_probability = log10( pixel_hit_probability );
00218                         
00219                         int qbin = (int)pixhit->qBin();
00220 
00221                         if ( ( log_pixel_hit_probability <  log_pixel_prob_cut ) &&
00222                              ( qbin                      != 0                  ) )
00223                           {
00224                             has_low_pixel_prob = true;
00225                             log_pixel_prob_cut = log_pixel_hit_probability;
00226                             low_pixel_prob_Id  = tm->recHit()->geographicalId().rawId();
00227                             low_pixel_prob_Det = tm->recHit()->det();
00228                           }         
00229                         
00230                       } // if ( !persistentHit == 0 && ... )
00231                     
00232                   } // if ( hit->isValid() && ... )
00233               }       
00234               // --- here the block of code about PXL Outlier Rejection ends --- 
00235               
00236 
00237             } // for (std::vector<TrajectoryMeasurement>::const_iterator tm=vtm.begin(); tm!=vtm.end(); tm++)
00238           
00239       
00240           if ( hasoutliers || has_low_pixel_prob ) 
00241             { // Reject outliers and pixel hits with low probability 
00242               
00243               // Replace outlier hit or low probability pixel hit with invalid hit
00244               for ( unsigned int j=0; j<myHits.size(); ++j ) 
00245                 { 
00246                   if ( hasoutliers && outlierId == myHits[j]->geographicalId().rawId() )
00247                     {
00248                       LogTrace("TrackFitters") << "Rejecting outlier hit  with estimate " << cut << " at position " 
00249                                                << j << " with rawId=" << myHits[j]->geographicalId().rawId();
00250                       LogTrace("TrackFitters") << "The fit will be repeated without the outlier";
00251                       myHits[j] = InvalidTransientRecHit::build(outlierDet, TrackingRecHit::missing);
00252                     }
00253                   else if ( has_low_pixel_prob && low_pixel_prob_Id == myHits[j]->geographicalId().rawId() )
00254                     {
00255                       LogTrace("TrackFitters") << "Rejecting low proability pixel hit with log_pixel_prob_cut = " 
00256                                                << log_pixel_prob_cut << " at position " 
00257                                                << j << " with rawId =" << myHits[j]->geographicalId().rawId();
00258                       LogTrace("TrackFitters") << "The fit will be repeated without the outlier";
00259                       myHits[j] = InvalidTransientRecHit::build(low_pixel_prob_Det, TrackingRecHit::missing);
00260                     }
00261                   
00262                 } // for ( unsigned int j=0; j<myHits.size(); ++j)
00263               
00264               // Look if there are two consecutive invalid hits
00265               if ( breakTrajWith2ConsecutiveMissing ) 
00266                 {
00267                   unsigned int firstinvalid = myHits.size()-1;
00268                   for ( unsigned int j=0; j<myHits.size()-1; ++j ) 
00269                     { 
00270                       if ( ((myHits[j  ]->type() == TrackingRecHit::missing) && (myHits[j  ]->geographicalId().rawId() != 0)) && 
00271                            ((myHits[j+1]->type() == TrackingRecHit::missing) && (myHits[j+1]->geographicalId().rawId() != 0)) ) 
00272                         {
00273                           firstinvalid = j;
00274                           LogTrace("TrackFitters") << "Found two consecutive missing hits. First invalid: " << firstinvalid;
00275                           break;
00276                         }
00277                     }
00278                   
00279                   //reject all the hits after the last valid before two consecutive invalid (missing) hits
00280                   //hits are sorted in the same order as in the track candidate FIXME??????
00281                   myHits.erase(myHits.begin()+firstinvalid,myHits.end());
00282                   
00283                 }
00284               
00285             } // if ( hasoutliers || has_low_pixel_prob ) 
00286           
00287         } // if ( theEstimateCut > 0 ... )
00288   
00289       if ( ( hasoutliers ||        // otherwise there won't be a 'next' loop where tmp_first could be useful 
00290              has_low_pixel_prob ) &&  // ggiurgiu@fnal.gov
00291            !rejectTracksFlag &&  // othewrise we won't ever need tmp_first
00292            tmp_first.empty() ) 
00293         { // only at first step
00294           smoothed.swap(tmp_first);
00295         }   
00296       
00297     } // do
00298   while ( hasoutliers || has_low_pixel_prob ); // ggiurgiu@fnal.gov
00299   
00300   if ( !smoothed.empty() ) 
00301     {
00302       if ( noInvalidHitsBeginEnd ) 
00303         {
00304           // discard latest dummy measurements
00305           if ( !smoothed[0].empty() && 
00306                !smoothed[0].lastMeasurement().recHit()->isValid() ) 
00307             LogTrace("TrackFitters") << "Last measurement is invalid";
00308         
00309           while ( !smoothed[0].empty() && 
00310                   !smoothed[0].lastMeasurement().recHit()->isValid() ) 
00311             smoothed[0].pop();
00312           
00313           //remove the invalid hits at the begin of the trajectory
00314           if ( !smoothed[0].firstMeasurement().recHit()->isValid() ) 
00315             {
00316               LogTrace("TrackFitters") << "First measurement is invalid";
00317               Trajectory tmpTraj(smoothed[0].seed(),smoothed[0].direction());
00318               Trajectory::DataContainer meas = smoothed[0].measurements();
00319               
00320               Trajectory::DataContainer::iterator it;//first valid hit
00321               for ( it=meas.begin(); it!=meas.end(); ++it ) 
00322                 {
00323                   if ( !it->recHit()->isValid() ) 
00324                     continue;
00325                   else break;
00326                 }
00327               tmpTraj.push(*it,smoothed[0].chiSquared());//push the first valid measurement and set the same global chi2
00328              
00329               for (Trajectory::DataContainer::iterator itt=it+1; itt!=meas.end();++itt) 
00330                 {
00331                   tmpTraj.push(*itt,0);//add all the other measurements
00332                 }
00333               
00334               smoothed.clear();
00335               smoothed.push_back(tmpTraj);
00336            
00337             } //  if ( !smoothed[0].firstMeasurement().recHit()->isValid() ) 
00338         
00339         } // if ( noInvalidHitsBeginEnd ) 
00340       
00341       LogTrace("TrackFitters") << "end: returning smoothed trajectory with chi2=" 
00342                                << smoothed[0].chiSquared() ;
00343       
00344       //LogTrace("TrackFitters") << "dump hits before return";
00345       //Trajectory::DataContainer meas = smoothed[0].measurements();
00346       //for (Trajectory::DataContainer::iterator it=meas.begin();it!=meas.end();++it) {
00347       //LogTrace("TrackFitters") << "hit #" << meas.end()-it-1 << " validity=" << it->recHit()->isValid() 
00348       //<< " det=" << it->recHit()->geographicalId().rawId();
00349       //}
00350       
00351     }
00352 
00353   return smoothed;
00354 
00355 }
00356 
00357 
00358 void 
00359 KFFittingSmoother::smoothingStep(vector<Trajectory>& fitted, vector<Trajectory> &smoothed) const
00360 {
00361  
00362   for(vector<Trajectory>::iterator it = fitted.begin(); it != fitted.end();
00363       it++) {
00364     vector<Trajectory> mysmoothed = smoother()->trajectories(*it);
00365     smoothed.insert(smoothed.end(), mysmoothed.begin(), mysmoothed.end());
00366   }
00367   LogDebug("TrackFitters") << "In KFFittingSmoother::smoothingStep "<<smoothed.size();
00368 }
00369 
00370 vector<Trajectory> KFFittingSmoother::fit(const TrajectorySeed& aSeed,
00371                                           const RecHitContainer& hits) const{
00372 
00373   throw cms::Exception("TrackFitters", 
00374                        "KFFittingSmoother::fit(TrajectorySeed, <TransientTrackingRecHit>) not implemented"); 
00375 
00376   return vector<Trajectory>();
00377 }