CMS 3D CMS Logo

TrajectorySegmentBuilder.cc
Go to the documentation of this file.
1 
3 
6 
20 
22 
23 #include <algorithm>
24 
25 // #define DBG_TSB
26 // #define STAT_TSB
27 
28 namespace {
29 #ifdef STAT_TSB
30  struct StatCount {
31  long long totGroup;
32  long long totSeg;
33  long long totLockHits;
34  long long totInvCand;
35  long long trunc;
36  void zero() {
37  totGroup=totSeg=totLockHits=totInvCand=trunc=0;
38  }
39  void incr(long long g, long long s, long long l) {
40  totGroup+=g;
41  totSeg+=s;
42  totLockHits+=l;
43  }
44  void truncated() { ++trunc;}
45  void invalid() { ++totInvCand;}
46  void print() const {
47  std::cout << "TrajectorySegmentBuilder stat\nGroup/Seg/Lock/Inv/Trunc "
48  << totGroup<<'/'<<totSeg<<'/'<<totLockHits<<'/'<<totInvCand<<'/'<<trunc
49  << std::endl;
50  }
51  StatCount() { zero();}
52  ~StatCount() { print();}
53  };
54  StatCount statCount;
55 
56 #else
57  struct StatCount {
58  void incr(long long, long long, long long){}
59  void truncated() {}
60  void invalid() {}
61  };
62  [[cms::thread_safe]] StatCount statCount;
63 #endif
64 
65 
66 }
67 
68 
69 using namespace std;
70 
73 {
74  //
75  // create empty trajectory
76  //
77  theLockedHits.clear();
78  TempTrajectory startingTrajectory(theFullPropagator.propagationDirection(),0);
79  //
80  // get measurement groups
81  //
82  auto && measGroups =
83  theLayerMeasurements->groupedMeasurements(theLayer,startingState,theFullPropagator,theEstimator);
84 
85 #ifdef DBG_TSB
86  cout << "TSB: number of measurement groups = " << measGroups.size() << endl;
87  // theDbgFlg = measGroups.size()>1;
88  theDbgFlg = true;
89 #else
90  theDbgFlg = false;
91 #endif
92 
93 
94 #ifdef TSB_TRUNCATE
95  // V.I. to me makes things slower...
96 
97  //
98  // check number of combinations
99  //
100  constexpr long long MAXCOMB = 100000000;
101  long long ncomb(1);
102  int ngrp(0);
103  bool truncate(false);
104  for (auto const & gr : measGroups) {
105  ++ngrp;
106  int nhit(0);
107  for ( auto const & m : gr.measurements()) if likely( m.recHitR().isValid() ) nhit++;
108 
109  if ( nhit>1 ) ncomb *= nhit;
110  if unlikely( ncomb>MAXCOMB ) {
111  edm::LogInfo("TrajectorySegmentBuilder") << " found " << measGroups.size()
112  << " groups and more than " << static_cast<unsigned int>(MAXCOMB)
113  << " combinations - limiting to "
114  << (ngrp-1) << " groups";
115  truncate = true;
116 
117  statCount.truncated();
118 
119  break;
120  }
121  }
122  // cout << "Groups / combinations = " << measGroups.size() << " " << ncomb << endl;
123  if unlikely( truncate && ngrp>0 ) measGroups.resize(ngrp-1);
124 
125 #endif
126 
127 
128 #ifdef DBG_TSB
129  if ( theDbgFlg ) {
130  int ntot(1);
131  for (vector<TMG>::const_iterator ig=measGroups.begin();
132  ig!=measGroups.end(); ++ig) {
133  int ngrp(0);
134  const vector<TM>& measurements = ig->measurements();
135  for ( vector<TM>::const_iterator im=measurements.begin();
136  im!=measurements.end(); ++im ) {
137  if ( im->recHit()->isValid() ) ngrp++;
138  }
139  cout << " " << ngrp;
140  if ( ngrp>0 ) ntot *= ngrp;
141  }
142  cout << endl;
143  cout << "TrajectorySegmentBuilder::partialTrajectories:: det ids & hit types / group" << endl;
144  for (vector<TMG>::const_iterator ig=measGroups.begin();
145  ig!=measGroups.end(); ++ig) {
146  const vector<TM>& measurements = ig->measurements();
147  for ( vector<TM>::const_iterator im=measurements.begin();
148  im!=measurements.end(); ++im ) {
149  if ( im!=measurements.begin() ) cout << " / ";
150  if ( im->recHit()->det() )
151  cout << im->recHit()->det()->geographicalId().rawId() << " "
152  << im->recHit()->getType();
153  else
154  cout << "no det";
155  }
156  cout << endl;
157  }
158 
159 
160 // if ( measGroups.size()>4 ) {
161  cout << typeid(theLayer).name() << endl;
162  cout << startingState.localError().matrix() << endl;
163 // for (vector<TMG>::const_iterator ig=measGroups.begin();
164 // ig!=measGroups.end(); ig++) {
165 // cout << "Nr. of measurements = " << ig->measurements().size() << endl;
166 // const DetGroup& dg = ig->detGroup();
167 // for ( DetGroup::const_iterator id=dg.begin();
168 // id!=dg.end(); id++ ) {
169 // GlobalPoint p(id->det()->position());
170 // GlobalVector v(id->det()->toGlobal(LocalVector(0.,0.,1.)));
171 // cout << p.perp() << " " << p.phi() << " " << p.z() << " ; "
172 // << v.phi() << " " << v.z() << endl;
173 // }
174 // }
175 // }
176  }
177 #endif
178 
180  addGroup(startingTrajectory,measGroups.begin(),measGroups.end());
181 
182  if unlikely(theDbgFlg) cout << "TSB: back with " << candidates.size() << " candidates" << endl;
183 
184  //
185  // add invalid hit - try to get first detector hit by the extrapolation
186  //
187 
188  updateWithInvalidHit(startingTrajectory,measGroups,candidates);
189 
190  if unlikely(theDbgFlg) cout << "TSB: " << candidates.size() << " candidates after invalid hit" << endl;
191 
192  statCount.incr(measGroups.size(), candidates.size(), theLockedHits.size());
193 
194 
195  theLockedHits.clear();
196 
197  return candidates;
198 }
199 
201 {
202  auto && predictedState = tm.predictedState();
203  auto && hit = tm.recHit();
204 
205  if ( hit->isValid()) {
206  auto && upState = theUpdator.update( predictedState, *hit);
207  traj.emplace(std::move(predictedState), std::move(upState),
208  std::move(hit), tm.estimate(), tm.layer());
209 
210 // TrajectoryMeasurement tm(traj.lastMeasurement());
211 // if ( tm.updatedState().isValid() ) {
212 // if ( !hit.det().surface()->bounds().inside(tm.updatedState().localPosition(),
213 // tm.updatedState().localError().positionError(),3.f) ) {
214 // cout << "Incompatibility after update for det at " << hit.det().position() << ":" << endl;
215 // cout << tm.predictedState().localPosition() << " "
216 // << tm.predictedState().localError().positionError() << endl;
217 // cout << hit.localPosition() << " " << hit.localPositionError() << endl;
218 // cout << tm.updatedState().localPosition() << " "
219 // << tm.updatedState().localError().positionError() << endl;
220 // }
221 // }
222  }
223  else {
224  traj.emplace(std::move(predictedState), std::move(hit),0, tm.layer());
225  }
226 }
227 
228 
231  vector<TMG>::const_iterator begin,
232  vector<TMG>::const_iterator end)
233 {
234  vector<TempTrajectory> ret;
235  if ( begin==end ) {
236  //std::cout << "TrajectorySegmentBuilder::addGroup" << " traj.empty()=" << traj.empty() << "EMPTY" << std::endl;
237  if unlikely(theDbgFlg) cout << "TSB::addGroup : no groups left" << endl;
238  if ( !traj.empty() )
239  ret.push_back(traj);
240  return ret;
241  }
242 
243  if unlikely(theDbgFlg) cout << "TSB::addGroup : traj.size() = " << traj.measurements().size()
244  << " first group at " << &(*begin)
245  // << " nr. of candidates = " << candidates.size()
246  << endl;
247 
248 
249  TempTrajectoryContainer updatedTrajectories; updatedTrajectories.reserve(2);
250  if ( traj.measurements().empty() ) {
251  if ( theMaxCand == 1 ) {
252  auto && firstMeasurements = unlockedMeasurements(begin->measurements());
253  if (!firstMeasurements.empty()) updateCandidatesWithBestHit(traj,std::move(firstMeasurements.front()),updatedTrajectories);
254  } else {
255  updateCandidates(traj,begin->measurements(),updatedTrajectories);
256  }
257  if unlikely(theDbgFlg) cout << "TSB::addGroup : updating with first group - "
258  << updatedTrajectories.size() << " trajectories" << endl;
259  }
260  else {
261  auto && meas = redoMeasurements(traj,begin->detGroup());
262  if (!meas.empty()) {
263  if ( theBestHitOnly ) {
264  updateCandidatesWithBestHit(traj,std::move(meas.front()),
265  updatedTrajectories);
266  }else{
267  updateCandidates(traj,std::move(meas),
268  updatedTrajectories);
269  }
270  if unlikely(theDbgFlg) cout << "TSB::addGroup : updating"
271  << updatedTrajectories.size() << " trajectories-1" << endl;
272  }
273  }
274  // keep old trajectory
275  //
276  updatedTrajectories.push_back(traj);
277 
278 
279  if (begin+1 != end) {
280  ret.reserve(4); // a good upper bound
281  for (auto const & ut : updatedTrajectories) {
282  if unlikely(theDbgFlg) cout << "TSB::addGroup : trying to extend candidate at "
283  << &ut << " size " << ut.measurements().size() << endl;
284  vector<TempTrajectory> && finalTrajectories = addGroup(ut,begin+1,end);
285  if unlikely(theDbgFlg) cout << "TSB::addGroup : " << finalTrajectories.size()
286  << " finalised candidates before cleaning" << endl;
287  //B.M. to be ported later
288  // V.I. only mark invalidate
289  cleanCandidates(finalTrajectories);
290 
291  if unlikely(theDbgFlg) {
292  int ntf=0; for ( auto const & t : finalTrajectories) if (t.isValid()) ++ntf;
293  cout << "TSB::addGroup : got " << ntf
294  << " finalised candidates" << endl;
295  }
296 
297  for ( auto & t : finalTrajectories)
298  if (t.isValid()) ret.push_back(std::move(t));
299 
300  // ret.insert(ret.end(),make_move_iterator(finalTrajectories.begin()),
301  // make_move_iterator(finalTrajectories.end()));
302  }
303  } else {
304  ret.reserve(updatedTrajectories.size());
305  for (auto & t : updatedTrajectories)
306  if (!t.empty()) ret.push_back(std::move(t));
307  }
308 
309  //std::cout << "TrajectorySegmentBuilder::addGroup" <<
310  // " traj.empty()=" << traj.empty() <<
311  // " end-begin=" << (end-begin) <<
312  // " #updated=" << updatedTrajectories.size() <<
313  // " #result=" << ret.size() << std::endl;
314  return ret;
315 }
316 
317 void
319  const vector<TM>& measurements,
321 {
322  //
323  // generate updated candidates with all valid hits
324  //
325  for ( auto im=measurements.begin();
326  im!=measurements.end(); ++im ) {
327  if ( im->recHit()->isValid() ) {
328  candidates.push_back(traj);
329  updateTrajectory(candidates.back(),*im);
330  if ( theLockHits ) lockMeasurement(*im);
331  }
332  }
333 }
334 
335 void
337  TM measurement,
339 {
340  // here we arrive with only valid hits and sorted.
341  //so the best is the first!
342 
343  if ( theLockHits ) lockMeasurement(measurement);
344  candidates.push_back(traj);
345  updateTrajectory(candidates.back(),std::move(measurement));
346 }
347 
348 vector<TrajectoryMeasurement>
350  const DetGroup& detGroup) const
351 {
352  vector<TM> result;
353  //
354  // loop over all dets
355  //
356  if unlikely(theDbgFlg) cout << "TSB::redoMeasurements : nr. of measurements / group =";
357 
359 
360  for (auto const & det : detGroup) {
361 
362  pair<bool, TrajectoryStateOnSurface> compat =
364  traj.lastMeasurement().updatedState(),
365  theGeomPropagator,theEstimator);
366 
367  if unlikely(theDbgFlg && !compat.first) std::cout << " 0";
368 
369  if(!compat.first) continue;
370 
371  MeasurementDetWithData mdet = theLayerMeasurements->idToDet(det.det()->geographicalId());
372  // verify also that first (and only!) not be inactive..
373  if (mdet.measurements(compat.second, theEstimator,tmps) && tmps.hits[0]->isValid() )
374  for (std::size_t i=0; i!=tmps.size(); ++i)
375  result.emplace_back(compat.second,std::move(tmps.hits[i]),tmps.distances[i],&theLayer);
376 
377  if unlikely(theDbgFlg) std::cout << " " << tmps.size();
378  tmps.clear();
379 
380  }
381 
382  if unlikely(theDbgFlg) cout << endl;
383 
384  std::sort( result.begin(), result.end(), TrajMeasLessEstim());
385 
386  return result;
387 }
388 
389 void
391  const vector<TMG>& groups,
393 {
394  //
395  // first try to find an inactive hit with dets crossed by the prediction,
396  // then take any inactive hit
397  //
398  // loop over groups
399  for ( int iteration=0; iteration<2; iteration++ ) {
400  for ( auto const & gr : groups ) {
401  auto const & measurements = gr.measurements();
402  for ( auto im=measurements.rbegin(); im!=measurements.rend(); ++im ) {
403  auto const & hit = im->recHitR();
404  if ( (hit.getType()==TrackingRecHit::valid) |
405  (hit.getType()==TrackingRecHit::missing) ) continue;
406  //
407  // check, if the extrapolation traverses the Det or
408  // if 2nd iteration
409  //
410  if ( hit.det() ) {
411  auto const & predState = im->predictedState();
412  if ( iteration>0 ||
413  (predState.isValid() &&
414  hit.det()->surface().bounds().inside(predState.localPosition())) ) {
415  // add the hit
416  candidates.push_back(traj);
417  updateTrajectory(candidates.back(), *im);
418  if unlikely( theDbgFlg ) cout << "TrajectorySegmentBuilder::updateWithInvalidHit "
419  << "added inactive hit" << endl;
420  return;
421  }
422  }
423  }
424  }
425  }
426  //
427  // No suitable inactive hit: add a missing one
428  //
429  for ( int iteration=0; iteration<2; iteration++ ) {
430  //
431  // loop over groups
432  //
433  for ( auto const & gr : groups ) {
434  auto const & measurements = gr.measurements();
435  for ( auto im=measurements.rbegin(); im!=measurements.rend(); ++im ) {
436  // only use invalid hits
437  auto const & hit = im->recHitR();
438  if likely( hit.isValid() ) continue;
439 
440  // check, if the extrapolation traverses the Det
441  auto const & predState = im->predictedState();
442  if ( iteration>0 || (predState.isValid() &&
443  hit.surface()->bounds().inside(predState.localPosition())) ) {
444  // add invalid hit
445  candidates.push_back(traj);
446  updateTrajectory(candidates.back(), *im);
447  return;
448  }
449  }
450  }
451  if unlikely( theDbgFlg && iteration==0 ) cout << "TrajectorySegmentBuilder::updateWithInvalidHit: "
452  << " did not find invalid hit on 1st iteration" << endl;
453  }
454 
455  if unlikely( theDbgFlg)
456  cout << "TrajectorySegmentBuilder::updateWithInvalidHit: "
457  << " did not find invalid hit" << endl;
458 }
459 
460 vector<TrajectoryMeasurement>
461 TrajectorySegmentBuilder::unlockedMeasurements (const vector<TM>& measurements) const
462 {
463 // if ( !theLockHits ) return measurements;
464 
465  vector<TM> result;
466  result.reserve(measurements.size());
467 
468  //RecHitEqualByChannels recHitEqual(false,true);
469 
470  for ( auto const & m : measurements) {
471  auto const & testHit = m.recHitR();
472  if unlikely( !testHit.isValid() ) continue;
473  bool found(false);
474  if likely( theLockHits ) {
475  for ( auto const & h : theLockedHits) {
476  if ( h->hit()->sharesInput(testHit.hit(), TrackingRecHit::all) ) {
477  found = true;
478  break;
479  }
480  }
481  }
482  if likely( !found ) result.push_back(m);
483  }
484  return result;
485 }
486 
487 void
489 {
490  theLockedHits.push_back(measurement.recHit());
491 }
492 
493 
494 
495 // ================= B.M. to be ported later ===============================
496 void
498 {
499  //
500  // remove candidates which are subsets of others
501  // assumptions: no invalid hits and no duplicates
502  //
503  if ( candidates.size()<=1 ) return;
504  //RecHitEqualByChannels recHitEqual(false,true);
505  //
506  const int NC = candidates.size();
507  int index[NC]; for (int i=0; i!=NC; ++i) index[i]=i;
508  std::sort(index,index+NC,[&candidates](int i, int j) { return lessByFoundHits(candidates[i],candidates[j]);});
509 // cout << "SortedCandidates.foundHits";
510 // for (auto i1 : index)
511 // cout << " " << candidates[i1].foundHits();
512 // cout << endl;
513  //
514  for ( auto i1 = index; i1!=index+NC-1; ++i1) {
515  // get measurements of candidate to be checked
516  const TempTrajectory::DataContainer & measurements1 = candidates[*i1].measurements();
517  for ( auto i2=i1+1; i2!=index+NC; ++i2 ) {
518  // no duplicates: two candidates of same size are different
519  if ( candidates[*i2].foundHits()==candidates[*i1].foundHits() ) continue;
520  // get measurements of "reference"
521  const TempTrajectory::DataContainer & measurements2 = candidates[*i2].measurements();
522  //
523  // use the fact that TMs are ordered:
524  // start search in trajectory#1 from last hit match found
525  //
526  bool allFound(true);
527  TempTrajectory::DataContainer::const_iterator from2 = measurements2.rbegin(), im2end = measurements2.rend();
528  for ( TempTrajectory::DataContainer::const_iterator im1=measurements1.rbegin(),im1end = measurements1.rend();
529  im1!=im1end; --im1 ) {
530  // redundant protection - segments should not contain invalid RecHits
531  // assert( im1->recHit()->isValid());
532  bool found(false);
533  for ( TempTrajectory::DataContainer::const_iterator im2=from2; im2!=im2end; --im2 ) {
534  // redundant protection - segments should not contain invalid RecHits
535  // assert (im2->recHit()->isValid());
536  if ( im1->recHitR().hit()->sharesInput(im2->recHitR().hit(), TrackingRecHit::all) ) {
537  found = true;
538  from2 = im2; --from2;
539  break;
540  }
541  }
542  if ( !found ) {
543  allFound = false;
544  break;
545  }
546  }
547  if ( allFound ) { candidates[*i1].invalidate(); statCount.invalid();}
548  }
549  }
550 
551 }
552 
553 //==================================================
554 
const_iterator rend() const
Definition: bqueue.h:164
TrajectoryStateOnSurface const & predictedState() const
ConstRecHitPointer const & recHit() const
bool empty() const
True if trajectory has no measurements.
std::size_t size() const
bool empty() const
Definition: bqueue.h:168
std::vector< TempTrajectory > TempTrajectoryContainer
void cleanCandidates(std::vector< TempTrajectory > &candidates) const
clean a set of candidates
std::string print(const Track &, edm::Verbosity=edm::Concise)
Track print utility.
Definition: print.cc:10
const DataContainer & measurements() const
std::vector< TrajectoryMeasurement > unlockedMeasurements(const std::vector< TM > &measurements) const
get list of unused hits
TempTrajectoryContainer segments(const TSOS startingState)
new segments within layer
std::vector< TempTrajectory > addGroup(TempTrajectory const &traj, std::vector< TrajectoryMeasurementGroup >::const_iterator begin, std::vector< TrajectoryMeasurementGroup >::const_iterator end)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
#define constexpr
const TrajectoryMeasurement & lastMeasurement() const
#define unlikely(x)
#define likely(x)
static std::pair< bool, TrajectoryStateOnSurface > isCompatible(const GeomDet *theDet, const TrajectoryStateOnSurface &ts, const Propagator &prop, const MeasurementEstimator &est)
void updateTrajectory(TempTrajectory &traj, TM tm) const
update of a trajectory with a hit
void updateCandidatesWithBestHit(TempTrajectory const &traj, TM measurements, TempTrajectoryContainer &candidates)
creation of a new candidate from a segment and the best hit out of a collection
void lockMeasurement(const TM &measurement)
mark a hit as used
std::vector< TrajectoryMeasurement > redoMeasurements(const TempTrajectory &traj, const DetGroup &detGroup) const
retrieve compatible hits from a DetGroup
const DetLayer * layer() const
const AlgebraicSymMatrix55 & matrix() const
#define end
Definition: vmac.h:37
const LocalTrajectoryError & localError() const
const_iterator rbegin() const
Definition: bqueue.h:163
bool lessByFoundHits(const Trajectory &a, const Trajectory &b)
void emplace(Args &&...args)
#define begin
Definition: vmac.h:30
void updateCandidates(TempTrajectory const &traj, const std::vector< TM > &measurements, TempTrajectoryContainer &candidates)
creation of new candidates from a segment and a collection of hits
TrajectoryStateOnSurface const & updatedState() const
size_type size() const
Definition: bqueue.h:167
bool measurements(const TrajectoryStateOnSurface &stateOnThisDet, const MeasurementEstimator &est, TempMeasurements &result) const
def move(src, dest)
Definition: eostools.py:510
void updateWithInvalidHit(TempTrajectory &traj, const std::vector< TMG > &groups, TempTrajectoryContainer &candidates) const