CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
KFFittingSmoother.cc
Go to the documentation of this file.
2 // #include "TrackingTools/MaterialEffects/interface/PropagatorWithMaterial.h"
10 
11 // ggiurgiu@fnal.gov: Add headers needed to cut on pixel hit probability
14 
15 using namespace std;
16 
17 KFFittingSmoother::~KFFittingSmoother()
18 {
19  delete theSmoother;
20  delete theFitter;
21 }
22 
23 Trajectory KFFittingSmoother::fitOne(const Trajectory& t, fitType type) const {
24  if (!t.isValid() ) return Trajectory();
25  return smoothingStep(fitter()->fitOne(t,type));
26 }
27 
28 bool KFFittingSmoother::checkForNans(const Trajectory & theTraj) const
29 {
30  if (edm::isNotFinite(theTraj.chiSquared ())) return false;
31  const std::vector<TrajectoryMeasurement> & vtm = theTraj.measurements();
32  for (std::vector<TrajectoryMeasurement>::const_iterator tm=vtm.begin(); tm!=vtm.end();tm++) {
33  if (edm::isNotFinite(tm->estimate())) return false;
34  AlgebraicVector5 v = tm->updatedState ().localParameters ().vector();
35  for (int i=0;i<5;++i) if (edm::isNotFinite(v[i])) return false;
36  const AlgebraicSymMatrix55 & m = tm->updatedState ().curvilinearError ().matrix();
37  for (int i=0;i<5;++i)
38  for (int j=0;j<(i+1);++j) if (edm::isNotFinite(m(i,j))) return false;
39  }
40  return true;
41 }
42 
43 Trajectory KFFittingSmoother::fitOne(const TrajectorySeed& aSeed,
44  const RecHitContainer& hits,
45  const TrajectoryStateOnSurface& firstPredTsos,
46  fitType type) const
47 {
48  LogDebug("TrackFitters") << "In KFFittingSmoother::fit";
49 
50  if ( hits.empty() ) return Trajectory();
51 
52  bool hasoutliers=false;
53  bool has_low_pixel_prob=false; // ggiurgiu@fnal.gov: Add flag for pixel hits with low template probability
54 
55  // ggiurgiu@fnal.gov: If log(Prob) < -15.0 or if Prob <= 0.0 then set log(Prob) = -15.0
56  double log_pixel_probability_lower_limit = -15.0;
57 
58  RecHitContainer myHits = hits;
59  Trajectory smoothed;
60  Trajectory tmp_first;
61  bool firstTry=true;
62 
63  do {
64 
65  //if no outliers the fit is done only once
66  //for (unsigned int j=0;j<myHits.size();j++) {
67  //if (myHits[j]->det())
68  //LogTrace("TrackFitters") << "hit #:" << j+1 << " rawId=" << myHits[j]->det()->geographicalId().rawId()
69  //<< " validity=" << myHits[j]->isValid();
70  //else
71  //LogTrace("TrackFitters") << "hit #:" << j+1 << " Hit with no Det information";
72  //}
73 
74  hasoutliers = false;
75  has_low_pixel_prob = false; // ggiurgiu@fnal.gov
76 
77  double cut = theEstimateCut;
78 
79  double log_pixel_prob_cut = theLogPixelProbabilityCut; // ggiurgiu@fnal.gov
80 
81 
82  unsigned int outlierId = 0;
83  const GeomDet* outlierDet = 0;
84 
85  unsigned int low_pixel_prob_Id = 0; // ggiurgiu@fnal.gov
86  const GeomDet* low_pixel_prob_Det = 0; // ggiurgiu@fnal.gov
87 
88  //call the fitter
89  smoothed = smoothingStep(fitter()->fitOne(aSeed, myHits, firstPredTsos));
90 
91  //if (tmp_first.size()==0) tmp_first = smoothed; moved later
92 
93  if ( !smoothed.isValid() ) {
94  if ( rejectTracksFlag ) {
95  LogTrace("TrackFitters") << "smoothed invalid => trajectory rejected";
96  //return vector<Trajectory>(); // break is enough to get this
97  } else {
98  LogTrace("TrackFitters") << "smoothed invalid => returning orignal trajectory" ;
99  std::swap(smoothed, tmp_first); // if first attempt, tmp_first would be invalid anyway
100  }
101  break;
102  }
103  //else {
104  //LogTrace("TrackFitters") << "dump hits after smoothing";
105  //Trajectory::DataContainer meas = smoothed[0].measurements();
106  //for (Trajectory::DataContainer::iterator it=meas.begin();it!=meas.end();++it) {
107  //LogTrace("TrackFitters") << "hit #" << meas.end()-it-1 << " validity=" << it->recHit()->isValid()
108  //<< " det=" << it->recHit()->geographicalId().rawId();
109  //}
110  //}
111 
112  if (!checkForNans(smoothed)) {
113  edm::LogError("TrackNaN")<<"Track has NaN";
114  return Trajectory();
115  }
116 
117 
118  if ( theEstimateCut > 0 || log_pixel_prob_cut > log_pixel_probability_lower_limit ) {
119  if ( smoothed.foundHits() < theMinNumberOfHits ) {
120  if ( rejectTracksFlag ) {
121  LogTrace("TrackFitters") << "smoothed.foundHits()<theMinNumberOfHits => trajectory rejected";
122  return Trajectory(); // invalid
123  } else{
124  // it might be it's the first step
125  if ( firstTry ) {
126  firstTry = false;
127  std::swap(tmp_first,smoothed);
128  }
129 
130  LogTrace("TrackFitters")
131  << "smoothed.foundHits()<theMinNumberOfHits => returning orignal trajectory with chi2="
132  << smoothed.chiSquared() ;
133  }
134  break;
135  }
136 
137  // Check if there are outliers or low probability pixel rec hits
138  const std::vector<TrajectoryMeasurement> & vtm = smoothed.measurements();
139 
140  double log_pixel_hit_probability = -999999.9;
141 
142  for (std::vector<TrajectoryMeasurement>::const_iterator tm=vtm.begin(); tm!=vtm.end();tm++) {
143  double estimate = tm->estimate();
144 
145  // --- here is the block of code about generic chi2-based Outlier Rejection ---
146  if ( estimate > cut && theEstimateCut > 0 ) {
147  hasoutliers = true;
148  cut = estimate;
149  outlierId = tm->recHit()->geographicalId().rawId();
150  outlierDet = tm->recHit()->det();
151  }
152  // --- here the block of code about generic chi2-based Outlier Rejection ends ---
153 
154 
155  // --- here is the block of code about PXL Outlier Rejection ---
156  if(log_pixel_prob_cut > log_pixel_probability_lower_limit){
157  // TO BE FIXED: the following code should really be moved into an external class or
158  // at least in a separate function. Current solution is ugly!
159  // The KFFittingSmoother shouldn't handle the details of
160  // Outliers identification and rejection. It shoudl just fit tracks.
161 
162  // ggiurgiu@fnal.gov: Get pixel hit probability here
164  unsigned int testSubDetID = ( hit->geographicalId().subdetId() );
165 
166  if ( hit->isValid() &&
167  hit->geographicalId().det() == DetId::Tracker &&
168  ( testSubDetID == PixelSubdetector::PixelBarrel ||
169  testSubDetID == PixelSubdetector::PixelEndcap )
170  ){
171  // get the enclosed persistent hit
172  const TrackingRecHit* persistentHit = hit->hit();
173 
174  // check if it's not null, and if it's a valid pixel hit
175  if ( !persistentHit == 0 &&
176  typeid(*persistentHit) == typeid(SiPixelRecHit) )
177  {
178 
179  // tell the C++ compiler that the hit is a pixel hit
180  const SiPixelRecHit* pixhit = dynamic_cast<const SiPixelRecHit*>( hit->hit() );
181 
182  double pixel_hit_probability = (float)pixhit->clusterProbability(0);
183 
184  if ( pixel_hit_probability < 0.0 )
185  LogDebug("From KFFittingSmoother.cc")
186  << "Wraning : Negative pixel hit probability !!!! Will set the probability to 10^{-15} !!!" << endl;
187 
188  if ( pixel_hit_probability <= 0.0 || log10( pixel_hit_probability ) < log_pixel_probability_lower_limit )
189  log_pixel_hit_probability = log_pixel_probability_lower_limit;
190  else
191  log_pixel_hit_probability = log10( pixel_hit_probability );
192 
193  int qbin = (int)pixhit->qBin();
194 
195  if ( ( log_pixel_hit_probability < log_pixel_prob_cut ) &&
196  ( qbin != 0 ) )
197  {
198  has_low_pixel_prob = true;
199  log_pixel_prob_cut = log_pixel_hit_probability;
200  low_pixel_prob_Id = tm->recHit()->geographicalId().rawId();
201  low_pixel_prob_Det = tm->recHit()->det();
202  }
203 
204  } // if ( !persistentHit == 0 && ... )
205 
206  } // if ( hit->isValid() && ... )
207  }
208  // --- here the block of code about PXL Outlier Rejection ends ---
209 
210  } // for (std::vector<TrajectoryMeasurement>::const_iterator tm=vtm.begin(); tm!=vtm.end(); tm++)
211 
212 
213  if ( hasoutliers || has_low_pixel_prob ) { // Reject outliers and pixel hits with low probability
214 
215  // Replace outlier hit or low probability pixel hit with invalid hit
216  for ( unsigned int j=0; j<myHits.size(); ++j ) {
217  if ( hasoutliers && outlierId == myHits[j]->geographicalId().rawId() )
218  {
219  LogTrace("TrackFitters") << "Rejecting outlier hit with estimate " << cut << " at position "
220  << j << " with rawId=" << myHits[j]->geographicalId().rawId();
221  LogTrace("TrackFitters") << "The fit will be repeated without the outlier";
223  }
224  else if ( has_low_pixel_prob && low_pixel_prob_Id == myHits[j]->geographicalId().rawId() ){
225  LogTrace("TrackFitters") << "Rejecting low proability pixel hit with log_pixel_prob_cut = "
226  << log_pixel_prob_cut << " at position "
227  << j << " with rawId =" << myHits[j]->geographicalId().rawId();
228  LogTrace("TrackFitters") << "The fit will be repeated without the outlier";
229  myHits[j] = InvalidTransientRecHit::build(low_pixel_prob_Det, TrackingRecHit::missing);
230  }
231 
232  } // for ( unsigned int j=0; j<myHits.size(); ++j)
233 
234  // Look if there are two consecutive invalid hits
235  if ( breakTrajWith2ConsecutiveMissing ) {
236  unsigned int firstinvalid = myHits.size();
237  for ( unsigned int j=0; j<myHits.size()-1; ++j )
238  {
239  if ( ((myHits[j ]->type() == TrackingRecHit::missing) && (myHits[j ]->geographicalId().rawId() != 0)) &&
240  ((myHits[j+1]->type() == TrackingRecHit::missing) && (myHits[j+1]->geographicalId().rawId() != 0)) )
241  {
242  firstinvalid = j;
243  LogTrace("TrackFitters") << "Found two consecutive missing hits. First invalid: " << firstinvalid;
244  break;
245  }
246  }
247 
248  //reject all the hits after the last valid before two consecutive invalid (missing) hits
249  //hits are sorted in the same order as in the track candidate FIXME??????
250  if (firstinvalid != myHits.size()) myHits.erase(myHits.begin()+firstinvalid,myHits.end());
251 
252  }
253 
254  } // if ( hasoutliers || has_low_pixel_prob )
255 
256  } // if ( theEstimateCut > 0 ... )
257 
258  if ( ( hasoutliers || // otherwise there won't be a 'next' loop where tmp_first could be useful
259  has_low_pixel_prob ) && // ggiurgiu@fnal.gov
260  !rejectTracksFlag && // othewrise we won't ever need tmp_first
261  firstTry ) { // only at first step
262  std::swap(smoothed,tmp_first); firstTry=false;
263  }
264 
265  } // do
266  while ( hasoutliers || has_low_pixel_prob ); // ggiurgiu@fnal.gov
267 
268  if ( smoothed.isValid() ) {
269  if ( noInvalidHitsBeginEnd ) {
270  // discard latest dummy measurements
271  if (!smoothed.lastMeasurement().recHitR().isValid() )
272  LogTrace("TrackFitters") << "Last measurement is invalid";
273 
274  while (!smoothed.lastMeasurement().recHitR().isValid() )
275  smoothed.pop();
276 
277  //remove the invalid hits at the begin of the trajectory
278  if ( !smoothed.firstMeasurement().recHitR().isValid() ) {
279  LogTrace("TrackFitters") << "First measurement is in`valid";
280  Trajectory tmpTraj(smoothed.seed(),smoothed.direction());
281  Trajectory::DataContainer const & meas = smoothed.measurements();
282 
283  Trajectory::DataContainer::const_iterator it;//first valid hit
284  for ( it=meas.begin(); it!=meas.end(); ++it )
285  if ( it->recHitR().isValid() ) break;
286  tmpTraj.push(*it,smoothed.chiSquared());//push the first valid measurement and set the same global chi2
287 
288  for (Trajectory::DataContainer::const_iterator itt=it+1; itt!=meas.end();++itt)
289  tmpTraj.push(*itt,0);//add all the other measurements
290 
291  std::swap(smoothed,tmpTraj);
292 
293  } // if ( !smoothed[0].firstMeasurement().recHit()->isValid() )
294 
295  } // if ( noInvalidHitsBeginEnd )
296 
297  LogTrace("TrackFitters") << "end: returning smoothed trajectory with chi2="
298  << smoothed.chiSquared() ;
299 
300  //LogTrace("TrackFitters") << "dump hits before return";
301  //Trajectory::DataContainer meas = smoothed[0].measurements();
302  //for (Trajectory::DataContainer::iterator it=meas.begin();it!=meas.end();++it) {
303  //LogTrace("TrackFitters") << "hit #" << meas.end()-it-1 << " validity=" << it->recHit()->isValid()
304  //<< " det=" << it->recHit()->geographicalId().rawId();
305  //}
306 
307  }
308 
309  return smoothed;
310 
311 }
312 
313 
314 Trajectory KFFittingSmoother::fitOne(const TrajectorySeed& aSeed,
315  const RecHitContainer& hits,fitType type) const{
316 
317  throw cms::Exception("TrackFitters",
318  "KFFittingSmoother::fit(TrajectorySeed, <TransientTrackingRecHit>) not implemented");
319 
320  return Trajectory();
321 }
#define LogDebug(id)
type
Definition: HCALResponse.h:21
int foundHits() const
Definition: Trajectory.h:236
int i
Definition: DBlmapReader.cc:9
TrajectorySeed const & seed() const
Access to the seed used to reconstruct the Trajectory.
Definition: Trajectory.h:277
ROOT::Math::SMatrix< double, 5, 5, ROOT::Math::MatRepSym< double, 5 > > AlgebraicSymMatrix55
PropagationDirection const & direction() const
Definition: Trajectory.cc:196
DataContainer const & measurements() const
Definition: Trajectory.h:215
std::vector< TrajectoryMeasurement > DataContainer
Definition: Trajectory.h:42
bool isNotFinite(T x)
Definition: isFinite.h:10
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
TrajectoryMeasurement const & lastMeasurement() const
Definition: Trajectory.h:193
int j
Definition: DBlmapReader.cc:9
#define LogTrace(id)
bool isValid() const
Definition: Trajectory.h:271
TrajectoryMeasurement const & firstMeasurement() const
Definition: Trajectory.h:206
ROOT::Math::SVector< double, 5 > AlgebraicVector5
void pop()
Definition: Trajectory.cc:17
ConstRecHitPointer::element_type const & recHitR() const
double chiSquared() const
Definition: Trajectory.h:254
Pixel Reconstructed Hit.