CMS 3D CMS Logo

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