CMS 3D CMS Logo

TrajectorySegmentBuilder.cc
Go to the documentation of this file.
1 #include <algorithm>
2 
4 
6 
20 
23 
24 // #define DBG_TSB
25 // #define STAT_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(),0);
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 
178  TempTrajectoryContainer candidates = addGroup(startingTrajectory,measGroups.begin(),measGroups.end());
179 
180  if UNLIKELY(theDbgFlg) cout << "TSB: back with " << candidates.size() << " candidates" << endl;
181 
182  //
183  // add invalid hit - try to get first detector hit by the extrapolation
184  //
185 
186  updateWithInvalidHit(startingTrajectory,measGroups,candidates);
187 
188  if UNLIKELY(theDbgFlg) cout << "TSB: " << candidates.size() << " candidates after invalid hit" << endl;
189 
190  statCount.incr(measGroups.size(), candidates.size(), theLockedHits.size());
191 
192 
193  theLockedHits.clear();
194 
195  return candidates;
196 }
197 
199 {
200  auto && predictedState = tm.predictedState();
201  auto && hit = tm.recHit();
202 
203  if ( hit->isValid()) {
204  auto && upState = theUpdator.update( predictedState, *hit);
205  traj.emplace(std::move(predictedState), std::move(upState),
206  std::move(hit), tm.estimate(), tm.layer());
207 
208 // TrajectoryMeasurement tm(traj.lastMeasurement());
209 // if ( tm.updatedState().isValid() ) {
210 // if ( !hit.det().surface()->bounds().inside(tm.updatedState().localPosition(),
211 // tm.updatedState().localError().positionError(),3.f) ) {
212 // cout << "Incompatibility after update for det at " << hit.det().position() << ":" << endl;
213 // cout << tm.predictedState().localPosition() << " "
214 // << tm.predictedState().localError().positionError() << endl;
215 // cout << hit.localPosition() << " " << hit.localPositionError() << endl;
216 // cout << tm.updatedState().localPosition() << " "
217 // << tm.updatedState().localError().positionError() << endl;
218 // }
219 // }
220  }
221  else {
222  traj.emplace(std::move(predictedState), std::move(hit),0, tm.layer());
223  }
224 }
225 
226 
229  vector<TMG>::const_iterator begin,
230  vector<TMG>::const_iterator end)
231 {
232  vector<TempTrajectory> ret;
233  if ( begin==end ) {
234  //std::cout << "TrajectorySegmentBuilder::addGroup" << " traj.empty()=" << traj.empty() << "EMPTY" << std::endl;
235  if UNLIKELY(theDbgFlg) cout << "TSB::addGroup : no groups left" << endl;
236  if ( !traj.empty() )
237  ret.push_back(traj);
238  return ret;
239  }
240 
241  if UNLIKELY(theDbgFlg) cout << "TSB::addGroup : traj.size() = " << traj.measurements().size()
242  << " first group at " << &(*begin)
243  // << " nr. of candidates = " << candidates.size()
244  << endl;
245 
246 
247  TempTrajectoryContainer updatedTrajectories; updatedTrajectories.reserve(2);
248  if ( traj.measurements().empty() ) {
249  if ( theMaxCand == 1 ) {
250  auto && firstMeasurements = unlockedMeasurements(begin->measurements());
251  if (!firstMeasurements.empty()) updateCandidatesWithBestHit(traj,std::move(firstMeasurements.front()),updatedTrajectories);
252  } else {
253  updateCandidates(traj,begin->measurements(),updatedTrajectories);
254  }
255  if UNLIKELY(theDbgFlg) cout << "TSB::addGroup : updating with first group - "
256  << updatedTrajectories.size() << " trajectories" << endl;
257  }
258  else {
259  auto && meas = redoMeasurements(traj,begin->detGroup());
260  if (!meas.empty()) {
261  if ( theBestHitOnly ) {
262  updateCandidatesWithBestHit(traj,std::move(meas.front()),
263  updatedTrajectories);
264  }else{
265  updateCandidates(traj,std::move(meas),
266  updatedTrajectories);
267  }
268  if UNLIKELY(theDbgFlg) cout << "TSB::addGroup : updating"
269  << updatedTrajectories.size() << " trajectories-1" << endl;
270  }
271  }
272  // keep old trajectory
273  //
274  updatedTrajectories.push_back(traj);
275 
276 
277  if (begin+1 != end) {
278  ret.reserve(4); // a good upper bound
279  for (auto const & ut : updatedTrajectories) {
280  if UNLIKELY(theDbgFlg) cout << "TSB::addGroup : trying to extend candidate at "
281  << &ut << " size " << ut.measurements().size() << endl;
282  vector<TempTrajectory> && finalTrajectories = addGroup(ut,begin+1,end);
283  if UNLIKELY(theDbgFlg) cout << "TSB::addGroup : " << finalTrajectories.size()
284  << " finalised candidates before cleaning" << endl;
285  //B.M. to be ported later
286  // V.I. only mark invalidate
287  cleanCandidates(finalTrajectories);
288 
289  if UNLIKELY(theDbgFlg) {
290  int ntf=0; for ( auto const & t : finalTrajectories) if (t.isValid()) ++ntf;
291  cout << "TSB::addGroup : got " << ntf
292  << " finalised candidates" << endl;
293  }
294 
295  for ( auto & t : finalTrajectories)
296  if (t.isValid()) ret.push_back(std::move(t));
297 
298  // ret.insert(ret.end(),make_move_iterator(finalTrajectories.begin()),
299  // make_move_iterator(finalTrajectories.end()));
300  }
301  } else {
302  ret.reserve(updatedTrajectories.size());
303  for (auto & t : updatedTrajectories)
304  if (!t.empty()) ret.push_back(std::move(t));
305  }
306 
307  //std::cout << "TrajectorySegmentBuilder::addGroup" <<
308  // " traj.empty()=" << traj.empty() <<
309  // " end-begin=" << (end-begin) <<
310  // " #updated=" << updatedTrajectories.size() <<
311  // " #result=" << ret.size() << std::endl;
312  return ret;
313 }
314 
315 void
317  const vector<TM>& measurements,
319 {
320  //
321  // generate updated candidates with all valid hits
322  //
323  for ( auto im=measurements.begin();
324  im!=measurements.end(); ++im ) {
325  if ( im->recHit()->isValid() ) {
326  candidates.push_back(traj);
327  updateTrajectory(candidates.back(),*im);
328  if ( theLockHits ) lockMeasurement(*im);
329  }
330  }
331 }
332 
333 void
335  TM measurement,
337 {
338  // here we arrive with only valid hits and sorted.
339  //so the best is the first!
340 
341  if ( theLockHits ) lockMeasurement(measurement);
342  candidates.push_back(traj);
343  updateTrajectory(candidates.back(),std::move(measurement));
344 }
345 
346 vector<TrajectoryMeasurement>
348  const DetGroup& detGroup) const
349 {
350  vector<TM> result;
351  //
352  // loop over all dets
353  //
354  if UNLIKELY(theDbgFlg) cout << "TSB::redoMeasurements : nr. of measurements / group =";
355 
357 
358  for (auto const & det : detGroup) {
359 
360  pair<bool, TrajectoryStateOnSurface> compat =
362  traj.lastMeasurement().updatedState(),
363  theGeomPropagator,theEstimator);
364 
365  if UNLIKELY(theDbgFlg && !compat.first) std::cout << " 0";
366 
367  if(!compat.first) continue;
368 
369  MeasurementDetWithData mdet = theLayerMeasurements->idToDet(det.det()->geographicalId());
370  // verify also that first (and only!) not be inactive..
371  if (mdet.measurements(compat.second, theEstimator,tmps) && tmps.hits[0]->isValid() )
372  for (std::size_t i=0; i!=tmps.size(); ++i)
373  result.emplace_back(compat.second,std::move(tmps.hits[i]),tmps.distances[i],&theLayer);
374 
375  if UNLIKELY(theDbgFlg) std::cout << " " << tmps.size();
376  tmps.clear();
377 
378  }
379 
380  if UNLIKELY(theDbgFlg) cout << endl;
381 
382  std::sort( result.begin(), result.end(), TrajMeasLessEstim());
383 
384  return result;
385 }
386 
387 void
389  const vector<TMG>& groups,
391 {
392  //
393  // first try to find an inactive hit with dets crossed by the prediction,
394  // then take any inactive hit
395  //
396  // loop over groups
397  for ( int iteration=0; iteration<2; iteration++ ) {
398  for ( auto const & gr : groups ) {
399  auto const & measurements = gr.measurements();
400  for ( auto im=measurements.rbegin(); im!=measurements.rend(); ++im ) {
401  auto const & hit = im->recHitR();
402  if ( (hit.getType()==TrackingRecHit::valid) |
403  (hit.getType()==TrackingRecHit::missing) ) continue;
404  //
405  // check, if the extrapolation traverses the Det or
406  // if 2nd iteration
407  //
408  if ( hit.det() ) {
409  auto const & predState = im->predictedState();
410  if ( iteration>0 ||
411  (predState.isValid() &&
412  hit.det()->surface().bounds().inside(predState.localPosition())) ) {
413  // add the hit
414  candidates.push_back(traj);
415  updateTrajectory(candidates.back(), *im);
416  if UNLIKELY( theDbgFlg ) cout << "TrajectorySegmentBuilder::updateWithInvalidHit "
417  << "added inactive hit" << endl;
418  return;
419  }
420  }
421  }
422  }
423  }
424  //
425  // No suitable inactive hit: add a missing one
426  //
427  for ( int iteration=0; iteration<2; iteration++ ) {
428  //
429  // loop over groups
430  //
431  for ( auto const & gr : groups ) {
432  auto const & measurements = gr.measurements();
433  for ( auto im=measurements.rbegin(); im!=measurements.rend(); ++im ) {
434  // only use invalid hits
435  auto const & hit = im->recHitR();
436  if LIKELY( hit.isValid() ) continue;
437 
438  // check, if the extrapolation traverses the Det
439  auto const & predState = im->predictedState();
440  if ( iteration>0 || (predState.isValid() &&
441  hit.surface()->bounds().inside(predState.localPosition())) ) {
442  // add invalid hit
443  candidates.push_back(traj);
444  updateTrajectory(candidates.back(), *im);
445  return;
446  }
447  }
448  }
449  if UNLIKELY( theDbgFlg && iteration==0 ) cout << "TrajectorySegmentBuilder::updateWithInvalidHit: "
450  << " did not find invalid hit on 1st iteration" << endl;
451  }
452 
453  if UNLIKELY( theDbgFlg)
454  cout << "TrajectorySegmentBuilder::updateWithInvalidHit: "
455  << " did not find invalid hit" << endl;
456 }
457 
458 vector<TrajectoryMeasurement>
459 TrajectorySegmentBuilder::unlockedMeasurements (const vector<TM>& measurements) const
460 {
461 // if ( !theLockHits ) return measurements;
462 
463  vector<TM> result;
464  result.reserve(measurements.size());
465 
466  //RecHitEqualByChannels recHitEqual(false,true);
467 
468  for ( auto const & m : measurements) {
469  auto const & testHit = m.recHitR();
470  if UNLIKELY( !testHit.isValid() ) continue;
471  bool found(false);
472  if LIKELY( theLockHits ) {
473  for ( auto const & h : theLockedHits) {
474  if ( h->hit()->sharesInput(testHit.hit(), TrackingRecHit::all) ) {
475  found = true;
476  break;
477  }
478  }
479  }
480  if LIKELY( !found ) result.push_back(m);
481  }
482  return result;
483 }
484 
485 void
487 {
488  theLockedHits.push_back(measurement.recHit());
489 }
490 
491 
492 
493 // ================= B.M. to be ported later ===============================
494 void
496 {
497  //
498  // remove candidates which are subsets of others
499  // assumptions: no invalid hits and no duplicates
500  //
501  if ( candidates.size()<=1 ) return;
502  //RecHitEqualByChannels recHitEqual(false,true);
503  //
504  const int NC = candidates.size();
505  int index[NC]; for (int i=0; i!=NC; ++i) index[i]=i;
506  std::sort(index,index+NC,[&candidates](int i, int j) { return lessByFoundHits(candidates[i],candidates[j]);});
507 // cout << "SortedCandidates.foundHits";
508 // for (auto i1 : index)
509 // cout << " " << candidates[i1].foundHits();
510 // cout << endl;
511  //
512  for ( auto i1 = index; i1!=index+NC-1; ++i1) {
513  // get measurements of candidate to be checked
514  const TempTrajectory::DataContainer & measurements1 = candidates[*i1].measurements();
515  for ( auto i2=i1+1; i2!=index+NC; ++i2 ) {
516  // no duplicates: two candidates of same size are different
517  if ( candidates[*i2].foundHits()==candidates[*i1].foundHits() ) continue;
518  // get measurements of "reference"
519  const TempTrajectory::DataContainer & measurements2 = candidates[*i2].measurements();
520  //
521  // use the fact that TMs are ordered:
522  // start search in trajectory#1 from last hit match found
523  //
524  bool allFound(true);
525  TempTrajectory::DataContainer::const_iterator from2 = measurements2.rbegin(), im2end = measurements2.rend();
526  for ( TempTrajectory::DataContainer::const_iterator im1=measurements1.rbegin(),im1end = measurements1.rend();
527  im1!=im1end; --im1 ) {
528  // redundant protection - segments should not contain invalid RecHits
529  // assert( im1->recHit()->isValid());
530  bool found(false);
531  for ( TempTrajectory::DataContainer::const_iterator im2=from2; im2!=im2end; --im2 ) {
532  // redundant protection - segments should not contain invalid RecHits
533  // assert (im2->recHit()->isValid());
534  if ( im1->recHitR().hit()->sharesInput(im2->recHitR().hit(), TrackingRecHit::all) ) {
535  found = true;
536  from2 = im2; --from2;
537  break;
538  }
539  }
540  if ( !found ) {
541  allFound = false;
542  break;
543  }
544  }
545  if ( allFound ) { candidates[*i1].invalidate(); statCount.invalid();}
546  }
547  }
548 
549 }
550 
551 //==================================================
552 
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.
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
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
const DataContainer & measurements() const
std::vector< TrajectoryMeasurement > unlockedMeasurements(const std::vector< TM > &measurements) const
get list of unused hits
#define LIKELY(x)
Definition: Likely.h:20
TempTrajectoryContainer segments(const TSOS startingState)
new segments within layer
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:66
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
const TrajectoryMeasurement & lastMeasurement() const
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
#define CMS_THREAD_SAFE
const AlgebraicSymMatrix55 & matrix() const
#define end
Definition: vmac.h:39
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:32
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
#define UNLIKELY(x)
Definition: Likely.h:21
bool measurements(const TrajectoryStateOnSurface &stateOnThisDet, const MeasurementEstimator &est, TempMeasurements &result) const
def move(src, dest)
Definition: eostools.py:511
#define constexpr
void updateWithInvalidHit(TempTrajectory &traj, const std::vector< TMG > &groups, TempTrajectoryContainer &candidates) const