CMS 3D CMS Logo

CkfTrajectoryBuilder.cc
Go to the documentation of this file.
2 
4 
6 
10 
17 
18 
20 
22 
26 
27 using namespace std;
28 
31  BaseCkfTrajectoryBuilder::createTrajectoryFilter(conf.getParameter<edm::ParameterSet>("trajectoryFilter"), iC))
32 {}
33 
35  BaseCkfTrajectoryBuilder(conf, filter)
36 {
37  theMaxCand = conf.getParameter<int>("maxCand");
38  theLostHitPenalty = conf.getParameter<double>("lostHitPenalty");
39  theIntermediateCleaning = conf.getParameter<bool>("intermediateCleaning");
40  theAlwaysUseInvalidHits = conf.getParameter<bool>("alwaysUseInvalidHits");
41  /*
42  theSharedSeedCheck = conf.getParameter<bool>("SharedSeedCheck");
43  std::stringstream ss;
44  ss<<"CkfTrajectoryBuilder_"<<conf.getParameter<std::string>("ComponentName")<<"_"<<this;
45  theUniqueName = ss.str();
46  LogDebug("CkfPattern")<<"my unique name is: "<<theUniqueName;
47  */
48 }
49 
50 /*
51  void CkfTrajectoryBuilder::setEvent(const edm::Event& event) const
52  {
53  theMeasurementTracker->update(event);
54  }
55 */
56 
58 }
59 
62 {
64  result.reserve(5);
65  trajectories(seed, result);
66  return result;
67 }
68 
69 /*
70  void CkfTrajectoryBuilder::rememberSeedAndTrajectories(const TrajectorySeed& seed,
71  CkfTrajectoryBuilder::TrajectoryContainer &result) const
72  {
73 
74  //result ----> theCachedTrajectories
75  //every first iteration on event. forget about everything that happened before
76  if (edm::Service<UpdaterService>()->checkOnce(theUniqueName))
77  theCachedTrajectories.clear();
78 
79  if (seed.nHits()==0) return;
80 
81  //then remember those trajectories
82  for (TrajectoryContainer::iterator traj=result.begin();
83  traj!=result.end(); ++traj) {
84  theCachedTrajectories.insert(std::make_pair(seed.recHits().first->geographicalId(),*traj));
85  }
86  }
87 
88  bool CkfTrajectoryBuilder::sharedSeed(const TrajectorySeed& s1,const TrajectorySeed& s2) const{
89  //quit right away on nH=0
90  if (s1.nHits()==0 || s2.nHits()==0) return false;
91  //quit right away if not the same number of hits
92  if (s1.nHits()!=s2.nHits()) return false;
93  TrajectorySeed::range r1=s1.recHits();
94  TrajectorySeed::range r2=s2.recHits();
95  TrajectorySeed::const_iterator i1,i2;
96  TrajectorySeed::const_iterator & i1_e=r1.second,&i2_e=r2.second;
97  TrajectorySeed::const_iterator & i1_b=r1.first,&i2_b=r2.first;
98  //quit right away if first detId does not match. front exist because of ==0 ->quit test
99  if(i1_b->geographicalId() != i2_b->geographicalId()) return false;
100  //then check hit by hit if they are the same
101  for (i1=i1_b,i2=i2_b;i1!=i1_e,i2!=i2_e;++i1,++i2){
102  if (!i1->sharesInput(&(*i2),TrackingRecHit::all)) return false;
103  }
104  return true;
105  }
106  bool CkfTrajectoryBuilder::seedAlreadyUsed(const TrajectorySeed& seed,
107  CkfTrajectoryBuilder::TempTrajectoryContainer &candidates) const
108  {
109  //theCachedTrajectories ---> candidates
110  if (seed.nHits()==0) return false;
111  bool answer=false;
112  pair<SharedTrajectory::const_iterator, SharedTrajectory::const_iterator> range =
113  theCachedTrajectories.equal_range(seed.recHits().first->geographicalId());
114  SharedTrajectory::const_iterator trajP;
115  for (trajP = range.first; trajP!=range.second;++trajP){
116  //check whether seeds are identical
117  if (sharedSeed(trajP->second.seed(),seed)){
118  candidates.push_back(trajP->second);
119  answer=true;
120  }//already existing trajectory shares the seed.
121  }//loop already made trajectories
122 
123  return answer;
124  }
125 */
126 
127 void
129 {
130  // analyseSeed( seed);
131  /*
132  if (theSharedSeedCheck){
133  TempTrajectoryContainer candidates;
134  if (seedAlreadyUsed(seed,candidates))
135  {
136  //start with those candidates already made before
137  limitedCandidates(candidates,result);
138  //and quit
139  return;
140  }
141  }
142  */
143 
144  unsigned int tmp;
145  buildTrajectories(seed, result, tmp, nullptr);
146 }
147 
150  unsigned int& nCandPerSeed,
151  const TrajectoryFilter*) const {
152  if (theMeasurementTracker == nullptr) {
153  throw cms::Exception("LogicError") << "Asking to create trajectories to an un-initialized CkfTrajectoryBuilder.\nYou have to call clone(const MeasurementTrackerEvent *data) and then call trajectories on it instead.\n";
154  }
155 
156  TempTrajectory startingTraj = createStartingTrajectory( seed );
157 
160  nCandPerSeed = limitedCandidates(seed, startingTraj, result);
161 
162  return startingTraj;
163 
164  /*
165  //and remember what you just did
166  if (theSharedSeedCheck) rememberSeedAndTrajectories(seed,result);
167  */
168 
169  // analyseResult(result);
170 }
171 
172 unsigned int CkfTrajectoryBuilder::
175 {
177  candidates.push_back( startingTraj);
178  boost::shared_ptr<const TrajectorySeed> sharedSeed(new TrajectorySeed(seed));
179  return limitedCandidates(sharedSeed, candidates,result);
180 }
181 
182 unsigned int CkfTrajectoryBuilder::
183 limitedCandidates(const boost::shared_ptr<const TrajectorySeed> & sharedSeed, TempTrajectoryContainer &candidates,
185 {
186  unsigned int nIter=1;
187  unsigned int nCands=0; // ignore startingTraj
188  unsigned int prevNewCandSize=0;
189  TempTrajectoryContainer newCand; // = TrajectoryContainer();
190  newCand.reserve(2*theMaxCand);
191 
192 
193  auto trajCandLess = [&](TempTrajectory const & a, TempTrajectory const & b) {
194  return (a.chiSquared() + a.lostHits()*theLostHitPenalty) <
195  (b.chiSquared() + b.lostHits()*theLostHitPenalty);
196  };
197 
198 
199  while ( !candidates.empty()) {
200 
201  newCand.clear();
202  for (auto traj=candidates.begin(); traj!=candidates.end(); traj++) {
203  std::vector<TM> meas;
204  findCompatibleMeasurements(*sharedSeed, *traj, meas);
205 
206  // --- method for debugging
207  if(!analyzeMeasurementsDebugger(*traj,meas,
209  forwardPropagator(*sharedSeed),theEstimator,
210  theTTRHBuilder)) return nCands;
211  // ---
212 
213  if ( meas.empty()) {
214  addToResult(sharedSeed, *traj, result);
215  }
216  else {
217  std::vector<TM>::const_iterator last;
218  if ( theAlwaysUseInvalidHits) last = meas.end();
219  else {
220  if (meas.front().recHit()->isValid()) {
221  last = find_if( meas.begin(), meas.end(), [](auto const& meas){ return !meas.recHit()->isValid(); });
222  }
223  else last = meas.end();
224  }
225 
226  for(auto itm = meas.begin(); itm != last; itm++) {
227  TempTrajectory newTraj = *traj;
228  updateTrajectory( newTraj, std::move(*itm));
229 
230  if ( toBeContinued(newTraj)) {
231  newCand.push_back(std::move(newTraj)); std::push_heap(newCand.begin(),newCand.end(),trajCandLess);
232  }
233  else {
234  addToResult(sharedSeed, newTraj, result);
236  }
237  }
238  }
239 
240  // account only new candidates, i.e.
241  // - 1 candidate -> 1 candidate, don't increase count
242  // - 1 candidate -> 2 candidates, increase count by 1
243  nCands += newCand.size() - prevNewCandSize;
244  prevNewCandSize = newCand.size();
245 
246  /*
247  auto trajVal = [&](TempTrajectory const & a) {
248  return a.chiSquared() + a.lostHits()*theLostHitPenalty;
249  };
250 
251  // safe (stable?) logig: always sort, kill exceeding only if worse than last to keep
252  // if ((int)newCand.size() > theMaxCand) std::cout << "TrajVal " << theMaxCand << ' ' << newCand.size() << ' ' << trajVal(newCand.front());
253  int toCut = int(newCand.size()) - int(theMaxCand);
254  if (toCut>0) {
255  // move largest "toCut" to the end
256  for (int i=0; i<toCut; ++i)
257  std::pop_heap(newCand.begin(),newCand.end()-i,trajCandLess);
258  auto fval = trajVal(newCand.front());
259  // remove till equal to highest to keep
260  for (int i=0; i<toCut; ++i) {
261  if (fval==trajVal(newCand.back())) break;
262  newCand.pop_back();
263  }
264  //assert((int)newCand.size() >= theMaxCand);
265  //std::cout << "; " << newCand.size() << ' ' << trajVal(newCand.front()) << " " << trajVal(newCand.back());
266 
267  // std::make_heap(newCand.begin(),newCand.end(),trajCandLess);
268  // push_heap again the one left
269  for (auto iter = newCand.begin()+theMaxCand+1; iter<=newCand.end(); ++iter )
270  std::push_heap(newCand.begin(),iter,trajCandLess);
271 
272  // std::cout << "; " << newCand.size() << ' ' << trajVal(newCand.front()) << " " << trajVal(newCand.back()) << std::endl;
273  }
274 
275  */
276 
277 
278  // intermedeate login: always sort, kill all exceeding
279  while ((int)newCand.size() > theMaxCand) {
280  std::pop_heap(newCand.begin(),newCand.end(),trajCandLess);
281  // if ((int)newCand.size() == theMaxCand+1) std::cout << " " << trajVal(newCand.front()) << " " << trajVal(newCand.back()) << std::endl;
282  newCand.pop_back();
283  }
284 
285  /*
286  // original logic: sort only if > theMaxCand, kill all exceeding
287  if ((int)newCand.size() > theMaxCand) {
288  std::sort( newCand.begin(), newCand.end(), TrajCandLess<TempTrajectory>(theLostHitPenalty));
289  // std::partial_sort( newCand.begin(), newCand.begin()+theMaxCand, newCand.end(), TrajCandLess<TempTrajectory>(theLostHitPenalty));
290  std::cout << "TrajVal " << theMaxCand << ' ' << newCand.size() << ' '
291  << trajVal(newCand.back()) << ' ' << trajVal(newCand[theMaxCand-1]) << ' ' << trajVal(newCand[theMaxCand]) << std::endl;
292  newCand.resize(theMaxCand);
293  }
294  */
295 
296  } // end loop on candidates
297 
298  std::sort_heap(newCand.begin(),newCand.end(),trajCandLess);
300 
301  candidates.swap(newCand);
302 
303  LogDebug("CkfPattern") <<result.size()<<" candidates after "<<nIter++<<" CKF iteration: \n"
305  <<"\n "<<candidates.size()<<" running candidates are: \n"
306  <<PrintoutHelper::dumpCandidates(candidates);
307 
308  }
309  return nCands;
310 }
311 
312 
313 
315  TM && tm) const
316 {
317  auto && predictedState = tm.predictedState();
318  auto && hit = tm.recHit();
319  if ( hit->isValid()) {
320  auto && upState = theUpdator->update( predictedState, *hit);
321  traj.emplace( std::move(predictedState), std::move(upState),
322  std::move(hit), tm.estimate(), tm.layer());
323  }
324  else {
325  traj.emplace( std::move(predictedState), std::move(hit), 0, tm.layer());
326  }
327 }
328 
329 
330 void
332  const TempTrajectory& traj,
333  std::vector<TrajectoryMeasurement> & result) const
334 {
335  int invalidHits = 0;
336  //Use findStateAndLayers which handles the hitless seed use case
337  std::pair<TSOS,std::vector<const DetLayer*> > && stateAndLayers = findStateAndLayers(seed,traj);
338  if (stateAndLayers.second.empty()) return;
339 
340  auto layerBegin = stateAndLayers.second.begin();
341  auto layerEnd = stateAndLayers.second.end();
342  LogDebug("CkfPattern")<<"looping on "<< stateAndLayers.second.size()<<" layers.";
343  const Propagator *fwdPropagator = forwardPropagator(seed);
344  for (auto il = layerBegin; il != layerEnd; il++) {
345 
346  LogDebug("CkfPattern")<<"looping on a layer in findCompatibleMeasurements.\n last layer: "<<traj.lastLayer()<<" current layer: "<<(*il);
347 
348  TSOS stateToUse = stateAndLayers.first;
349  //Added protection before asking for the lastLayer on the trajectory
350  if UNLIKELY (!traj.empty() && (*il)==traj.lastLayer()) {
351  LogDebug("CkfPattern")<<" self propagating in findCompatibleMeasurements.\n from: \n"<<stateToUse;
352  //self navigation case
353  // go to a middle point first
355  GlobalPoint center(0,0,0);
356  stateToUse = middle.extrapolate(stateToUse, center, *fwdPropagator);
357 
358  if (!stateToUse.isValid()) continue;
359  LogDebug("CkfPattern")<<"to: "<<stateToUse;
360  }
361 
362  LayerMeasurements layerMeasurements(theMeasurementTracker->measurementTracker(), *theMeasurementTracker);
363  std::vector<TrajectoryMeasurement> && tmp = layerMeasurements.measurements((**il),stateToUse, *fwdPropagator, *theEstimator);
364 
365  if ( !tmp.empty()) {
366  if ( result.empty()) result.swap(tmp);
367  else {
368  // keep one dummy TM at the end, skip the others
369  result.insert( result.end()-invalidHits,
370  std::make_move_iterator(tmp.begin()), std::make_move_iterator(tmp.end()));
371  }
372  invalidHits++;
373  }
374  }
375 
376  // sort the final result, keep dummy measurements at the end
377  if ( result.size() > 1) {
378  std::sort( result.begin(), result.end()-invalidHits, TrajMeasLessEstim());
379  }
380 
381  LogDebug("CkfPattern")<<"starting from:\n"
382  <<"x: "<<stateAndLayers.first.globalPosition()<<"\n"
383  <<"p: "<<stateAndLayers.first.globalMomentum()<<"\n"
385 
386 #ifdef DEBUG_INVALID
387  bool afterInvalid = false;
388  for (vector<TM>::const_iterator i=result.begin();
389  i!=result.end(); i++) {
390  if ( ! i->recHit().isValid()) afterInvalid = true;
391  if (afterInvalid && i->recHit().isValid()) {
392  edm::LogError("CkfPattern") << "CkfTrajectoryBuilder error: valid hit after invalid!" ;
393  }
394  }
395 #endif
396 
397  //analyseMeasurements( result, traj);
398 
399 }
400 
#define LogDebug(id)
T getParameter(std::string const &) const
static std::string dumpCandidates(collection &candidates)
std::vector< Trajectory > TrajectoryContainer
bool empty() const
True if trajectory has no measurements.
static void clean(TempTrajectoryContainer &tracks)
const Propagator * forwardPropagator(const TrajectorySeed &seed) const
TrajectoryContainer trajectories(const TrajectorySeed &seed) const override
trajectories building starting from a seed
CkfTrajectoryBuilder(const edm::ParameterSet &conf, edm::ConsumesCollector &iC)
virtual bool analyzeMeasurementsDebugger(Trajectory &traj, const std::vector< TrajectoryMeasurement > &meas, const MeasurementTrackerEvent *theMeasurementTracker, const Propagator *theForwardPropagator, const Chi2MeasurementEstimatorBase *theEstimator, const TransientTrackingRecHitBuilder *theTTRHBuilder) const
const TrajectoryStateUpdator * theUpdator
static std::string dumpMeasurements(const std::vector< TrajectoryMeasurement > &v)
virtual TrajectoryStateOnSurface update(const TrajectoryStateOnSurface &, const TrackingRecHit &) const =0
const TransientTrackingRecHitBuilder * theTTRHBuilder
void addToResult(boost::shared_ptr< const TrajectorySeed > const &seed, TempTrajectory &traj, TrajectoryContainer &result, bool inOut=false) const
StateAndLayers findStateAndLayers(const TrajectorySeed &seed, const TempTrajectory &traj) const
const MeasurementTrackerEvent * theMeasurementTracker
unsigned int limitedCandidates(const TrajectorySeed &seed, TempTrajectory &startingTraj, TrajectoryContainer &result) const
std::vector< TempTrajectory > TempTrajectoryContainer
float chiSquared() const
Value of the raw Chi2 of the trajectory, not normalised to the N.D.F.
double b
Definition: hdecay.h:120
TrajectoryStateOnSurface extrapolate(const FreeTrajectoryState &fts, const GlobalPoint &vtx) const
extrapolation with default (=geometrical) propagator
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
void emplace(Args &&...args)
HLT enums.
bool toBeContinued(TempTrajectory &traj, bool inOut=false) const
double a
Definition: hdecay.h:121
TempTrajectory buildTrajectories(const TrajectorySeed &, TrajectoryContainer &ret, unsigned int &nCandPerSeed, const TrajectoryFilter *) const override
virtual void findCompatibleMeasurements(const TrajectorySeed &seed, const TempTrajectory &traj, std::vector< TrajectoryMeasurement > &result) const
void updateTrajectory(TempTrajectory &traj, TM &&tm) const
void setEvent_(const edm::Event &iEvent, const edm::EventSetup &iSetup) override
const DetLayer * lastLayer() const
Redundant method, returns the layer of lastMeasurement() .
int theMaxCand
set Event for the internal MeasurementTracker data member
std::vector< Trajectory > TrajectoryContainer
def move(src, dest)
Definition: eostools.py:511
const Chi2MeasurementEstimatorBase * theEstimator
Definition: event.py:1
TempTrajectory createStartingTrajectory(const TrajectorySeed &seed) const
int lostHits() const
#define UNLIKELY(x)