CMS 3D CMS Logo

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