CMS 3D CMS Logo

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