CMS 3D CMS Logo

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