CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
GroupedCkfTrajectoryBuilder.cc
Go to the documentation of this file.
1 
4 
5 
8 
23 
31 
32 // only included for RecHit comparison operator:
34 
35 // for looper reconstruction
39 
40 
41 #include <algorithm>
42 #include <array>
43 
44 namespace {
45 #ifdef STAT_TSB
46  struct StatCount {
47  long long totSeed;
48  long long totTraj;
49  long long totRebuilt;
50  long long totInvCand;
51  void zero() {
52  totSeed=totTraj=totRebuilt=totInvCand=0;
53  }
54  void traj(long long t) {
55  totTraj+=t;
56  }
57  void seed() {++totSeed;}
58  void rebuilt(long long t) {
59  totRebuilt+=t;
60  }
61  void invalid() { ++totInvCand;}
62  void print() const {
63  std::cout << "GroupedCkfTrajectoryBuilder stat\nSeed/Traj/Rebuilt "
64  << totSeed <<'/'<< totTraj <<'/'<< totRebuilt
65  << std::endl;
66  }
67  StatCount() { zero();}
68  ~StatCount() { print();}
69  };
70 
71 #else
72  struct StatCount {
73  void traj(long long){}
74  void seed() {}
75  void rebuilt(long long) {}
76  void invalid() {}
77  };
78 #endif
79 
80  StatCount statCount;
81 
82 }
83 
84 
85 
86 using namespace std;
87 
88 //#define DBG2_GCTB
89 
90 //#define STANDARD_INTERMEDIARYCLEAN
91 
92 #ifdef STANDARD_INTERMEDIARYCLEAN
94 #endif
95 
96 /* ====== B.M. to be ported layer ===========
97 #ifdef DBG_GCTB
98 #include "RecoTracker/CkfPattern/src/ShowCand.h"
99 #endif
100 // #define DBG2_GCTB
101 #ifdef DBG2_GCTB
102 #include "RecoTracker/CkfPattern/src/SimIdPrinter.h"
103 #include "Tracker/TkDebugTools/interface/LayerFinderByDet.h"
104 #include "Tracker/TkLayout/interface/TkLayerName.h"
105 #endif
106 =================================== */
107 
108 
111  const TrajectoryStateUpdator* updator,
112  const Propagator* propagatorAlong,
113  const Propagator* propagatorOpposite,
114  const Chi2MeasurementEstimatorBase* estimator,
115  const TransientTrackingRecHitBuilder* recHitBuilder,
116  const MeasurementTracker* measurementTracker,
117  const TrajectoryFilter* filter,
118  const TrajectoryFilter* inOutFilter):
119 
120 
122  updator, propagatorAlong,propagatorOpposite,
123  estimator, recHitBuilder, measurementTracker, filter, inOutFilter)
124 {
125  // fill data members from parameters (eventually data members could be dropped)
126  //
127  theMaxCand = conf.getParameter<int>("maxCand");
128 
129  theLostHitPenalty = conf.getParameter<double>("lostHitPenalty");
130  theFoundHitBonus = conf.getParameter<double>("foundHitBonus");
131  theIntermediateCleaning = conf.getParameter<bool>("intermediateCleaning");
132  theAlwaysUseInvalid = conf.getParameter<bool>("alwaysUseInvalidHits");
133  theLockHits = conf.getParameter<bool>("lockHits");
134  theBestHitOnly = conf.getParameter<bool>("bestHitOnly");
136  theRequireSeedHitsInRebuild = conf.getParameter<bool>("requireSeedHitsInRebuild");
137  theKeepOriginalIfRebuildFails = conf.getParameter<bool>("keepOriginalIfRebuildFails");
138  theMinNrOfHitsForRebuild = max(0,conf.getParameter<int>("minNrOfHitsForRebuild"));
139  maxPt2ForLooperReconstruction = conf.existsAs<double>("maxPtForLooperReconstruction") ?
140  conf.getParameter<double>("maxPtForLooperReconstruction") : 0;
142  maxDPhiForLooperReconstruction = conf.existsAs<double>("maxDPhiForLooperReconstruction") ?
143  conf.getParameter<double>("maxDPhiForLooperReconstruction") : 2.0;
144 
145 
146  /* ======= B.M. to be ported layer ===========
147  bool setOK = thePropagator->setMaxDirectionChange(1.6);
148  if (!setOK)
149  cout << "GroupedCkfTrajectoryBuilder WARNING: "
150  << "propagator does not support setMaxDirectionChange"
151  << endl;
152  // addStopCondition(theMinPtStopCondition);
153 
154  theConfigurableCondition = createAlgo<TrajectoryFilter>(componentConfig("StopCondition"));
155  ===================================== */
156 
157 }
158 
159 /*
160  void GroupedCkfTrajectoryBuilder::setEvent(const edm::Event& event) const
161  {
162  theMeasurementTracker->update(event);
163 }
164 */
165 
168 {
170  ret.reserve(10);
171  buildTrajectories(seed, ret, 0);
172  return ret;
173 }
174 
177  const TrackingRegion& region) const
178 {
180  ret.reserve(10);
181  RegionalTrajectoryFilter regionalCondition(region);
182  buildTrajectories(seed, ret, &regionalCondition);
183  return ret;
184 }
185 
186 void
188 {
189  buildTrajectories(seed,ret,0);
190 }
191 
192 void
195  const TrackingRegion& region) const
196 {
197  RegionalTrajectoryFilter regionalCondition(region);
198  buildTrajectories(seed,ret,&regionalCondition);
199 }
200 
201 void
203  TrajectoryContainer& result) const {
204  TempTrajectory const & startingTraj = createStartingTrajectory( seed);
205  rebuildTrajectories(startingTraj,seed,result);
206 
207 }
208 
209 void
211  TrajectoryContainer& result) const {
213 
214  TrajectoryContainer final;
215 
216  work.reserve(result.size());
217  for (TrajectoryContainer::iterator traj=result.begin();
218  traj!=result.end(); ++traj) {
219  if(traj->isValid()) work.push_back(TempTrajectory(*traj));
220  }
221 
222  rebuildSeedingRegion(seed,startingTraj,work);
223  final.reserve(work.size());
224 
225  // better the seed to be always the same...
226  boost::shared_ptr<const TrajectorySeed> sharedSeed;
227  if (result.empty())
228  sharedSeed.reset(new TrajectorySeed(seed));
229  else sharedSeed = result.front().sharedSeed();
230 
231 
232  for (TempTrajectoryContainer::iterator traj=work.begin();
233  traj!=work.end(); ++traj) {
234  final.push_back(traj->toTrajectory()); final.back().setSharedSeed(sharedSeed);
235  }
236 
237  result.swap(final);
238 
239  statCount.rebuilt(result.size());
240 
241 }
242 
246  const TrajectoryFilter* regionalCondition) const
247 {
248  statCount.seed();
249  //
250  // Build trajectory outwards from seed
251  //
252 
253  analyseSeed( seed);
254 
255  TempTrajectory const & startingTraj = createStartingTrajectory( seed);
256 
257  work_.clear();
258  const bool inOut = true;
259  groupedLimitedCandidates( startingTraj, regionalCondition, theForwardPropagator, inOut, work_);
260  if ( work_.empty() ) return startingTraj;
261 
262 
263 
264  /* rebuilding is de-coupled from standard building
265  //
266  // try to additional hits in the seeding region
267  //
268  if ( theMinNrOfHitsForRebuild>0 ) {
269  // reverse direction
270  //thePropagator->setPropagationDirection(oppositeDirection(seed.direction()));
271  // rebuild part of the trajectory
272  rebuildSeedingRegion(startingTraj,work);
273  }
274 
275  */
276  boost::shared_ptr<const TrajectorySeed> pseed(new TrajectorySeed(seed));
277  result.reserve(work_.size());
278  for (TempTrajectoryContainer::const_iterator it = work_.begin(), ed = work_.end(); it != ed; ++it) {
279  result.push_back( it->toTrajectory() ); result.back().setSharedSeed(pseed);
280  }
281 
282  work_.clear();
283  if (work_.capacity() > work_MaxSize_) { TempTrajectoryContainer().swap(work_); work_.reserve(work_MaxSize_/2); }
284 
285  analyseResult(result);
286 
287  LogDebug("CkfPattern")<< "GroupedCkfTrajectoryBuilder: returning result of size " << result.size();
288  statCount.traj(result.size());
289 
290 
291  return startingTraj;
292 
293 }
294 
295 
296 void
298  const TrajectoryFilter* regionalCondition,
299  const Propagator* propagator,
300  bool inOut,
302 {
303  unsigned int nIter=1;
304  TempTrajectoryContainer candidates;
305  TempTrajectoryContainer newCand;
306  candidates.push_back( startingTraj);
307 
308  while ( !candidates.empty()) {
309 
310  newCand.clear();
311  for (TempTrajectoryContainer::iterator traj=candidates.begin();
312  traj!=candidates.end(); traj++) {
313  if ( !advanceOneLayer(*traj, regionalCondition, propagator, inOut, newCand, result) ) {
314  LogDebug("CkfPattern")<< "GCTB: terminating after advanceOneLayer==false";
315  continue;
316  }
317 
318  LogDebug("CkfPattern")<<"newCand(1): after advanced one layer:\n"<<PrintoutHelper::dumpCandidates(newCand);
319 
320  if ((int)newCand.size() > theMaxCand) {
321  //ShowCand()(newCand);
322 
323  sort( newCand.begin(), newCand.end(), GroupedTrajCandLess(theLostHitPenalty,theFoundHitBonus));
324  newCand.erase( newCand.begin()+theMaxCand, newCand.end());
325  }
326  LogDebug("CkfPattern")<<"newCand(2): after removing extra candidates.\n"<<PrintoutHelper::dumpCandidates(newCand);
327  }
328 
329  LogDebug("CkfPattern") << "newCand.size() at end = " << newCand.size();
330 /*
331  if (theIntermediateCleaning) {
332  candidates.clear();
333  candidates = groupedIntermediaryClean(newCand);
334  } else {
335  candidates.swap(newCand);
336  }
337 */
339 #ifdef STANDARD_INTERMEDIARYCLEAN
341 #else
342  groupedIntermediaryClean(newCand);
343 #endif
344 
345  }
346  candidates.swap(newCand);
347 
348  LogDebug("CkfPattern") <<"candidates(3): "<<result.size()<<" candidates after "<<nIter++<<" groupedCKF iteration: \n"
350  <<"\n "<<candidates.size()<<" running candidates are: \n"
351  <<PrintoutHelper::dumpCandidates(candidates);
352  }
353 }
354 
355 #ifdef EDM_ML_DEBUG
356 std::string whatIsTheNextStep(TempTrajectory const& traj , std::pair<TrajectoryStateOnSurface,std::vector<const DetLayer*> >& stateAndLayers){
357  std::stringstream buffer;
358  vector<const DetLayer*> & nl = stateAndLayers.second;
359  // #include "TrackingTools/DetLayers/interface/BarrelDetLayer.h"
360  // #include "TrackingTools/DetLayers/interface/ForwardDetLayer.h"
361  //B.M. TkLayerName layerName;
362  //B.M. buffer << "Started from " << layerName(traj.lastLayer())
363  const BarrelDetLayer* sbdl = dynamic_cast<const BarrelDetLayer*>(traj.lastLayer());
364  const ForwardDetLayer* sfdl = dynamic_cast<const ForwardDetLayer*>(traj.lastLayer());
365  if (sbdl) {
366  buffer << "Started from " << traj.lastLayer() << " r=" << sbdl->specificSurface().radius()
367  << " phi=" << sbdl->specificSurface().phi() << endl;
368  } else if (sfdl) {
369  buffer << "Started from " << traj.lastLayer() << " z " << sfdl->specificSurface().position().z()
370  << " phi " << sfdl->specificSurface().phi() << endl;
371  }
372  buffer << "Trying to go to";
373  for ( vector<const DetLayer*>::iterator il=nl.begin();
374  il!=nl.end(); il++){
375  //B.M. buffer << " " << layerName(*il) << " " << *il << endl;
376  const BarrelDetLayer* bdl = dynamic_cast<const BarrelDetLayer*>(*il);
377  const ForwardDetLayer* fdl = dynamic_cast<const ForwardDetLayer*>(*il);
378 
379  if (bdl) buffer << " r " << bdl->specificSurface().radius() << endl;
380  if (fdl) buffer << " z " << fdl->specificSurface().position().z() << endl;
381  //buffer << " " << *il << endl;
382  }
383  return buffer.str();
384 }
385 
386 std::string whatIsTheStateToUse(TrajectoryStateOnSurface &initial, TrajectoryStateOnSurface & stateToUse, const DetLayer * l){
387  std::stringstream buffer;
388  buffer << "GCTB: starting from "
389  << " r / phi / z = " << stateToUse.globalPosition().perp()
390  << " / " << stateToUse.globalPosition().phi()
391  << " / " << stateToUse.globalPosition().z()
392  << " , pt / phi / pz /charge = "
393  << stateToUse.globalMomentum().perp() << " / "
394  << stateToUse.globalMomentum().phi() << " / "
395  << stateToUse.globalMomentum().z() << " / "
396  << stateToUse.charge()
397  << " for layer at "<< l << endl;
398  buffer << " errors:";
399  for ( int i=0; i<5; i++ ) buffer << " " << sqrt(stateToUse.curvilinearError().matrix()(i,i));
400  buffer << endl;
401 
402  //buffer << "GCTB: starting from r / phi / z = " << initial.globalPosition().perp()
403  //<< " / " << initial.globalPosition().phi()
404  //<< " / " << initial.globalPosition().z() << " , pt / pz = "
405  //<< initial.globalMomentum().perp() << " / "
406  //<< initial.globalMomentum().z() << " for layer at "
407  //<< l << endl;
408  //buffer << " errors:";
409  //for ( int i=0; i<5; i++ ) buffer << " " << sqrt(initial.curvilinearError().matrix()(i,i));
410  //buffer << endl;
411  return buffer.str();
412 }
413 #endif
414 
415 bool
417  const TrajectoryFilter* regionalCondition,
418  const Propagator* propagator,
419  bool inOut,
420  TempTrajectoryContainer& newCand,
422 {
423  std::pair<TSOS,std::vector<const DetLayer*> > stateAndLayers = findStateAndLayers(traj);
424 
425 
427  if(
428  //stateAndLayers.second.size()==0 &&
429  traj.lastLayer()->location()==0) {
430  float pt2 = stateAndLayers.first.globalMomentum().perp2();
432  pt2>(0.3f*0.3f)
433  )
434  stateAndLayers.second.push_back(traj.lastLayer());
435  }
436  }
437 
438  vector<const DetLayer*>::iterator layerBegin = stateAndLayers.second.begin();
439  vector<const DetLayer*>::iterator layerEnd = stateAndLayers.second.end();
440 
441  // if (nl.empty()) {
442  // addToResult(traj,result,inOut);
443  // return false;
444  // }
445 
446 #ifdef EDM_ML_DEBUG
447  LogDebug("CkfPattern")<<whatIsTheNextStep(traj, stateAndLayers);
448 #endif
449 
450  bool foundSegments(false);
451  bool foundNewCandidates(false);
452  for ( vector<const DetLayer*>::iterator il=layerBegin;
453  il!=layerEnd; il++) {
454 
455  TSOS stateToUse = stateAndLayers.first;
456 
457  double dPhiCacheForLoopersReconstruction(0);
458  if unlikely((*il)==traj.lastLayer()){
459 
461  // ------ For loopers reconstruction
462  //cout<<" self propagating in advanceOneLayer (for loopers) \n";
463  const BarrelDetLayer* sbdl = dynamic_cast<const BarrelDetLayer*>(traj.lastLayer());
464  if(sbdl){
465  HelixBarrelCylinderCrossing cylinderCrossing(stateToUse.globalPosition(),
466  stateToUse.globalMomentum(),
467  stateToUse.transverseCurvature(),
468  propagator->propagationDirection(),
469  sbdl->specificSurface());
470  if(!cylinderCrossing.hasSolution()) continue;
471  GlobalPoint starting = stateToUse.globalPosition();
472  GlobalPoint target1 = cylinderCrossing.position1();
473  GlobalPoint target2 = cylinderCrossing.position2();
474 
475  GlobalPoint farther = fabs(starting.phi()-target1.phi()) > fabs(starting.phi()-target2.phi()) ?
476  target1 : target2;
477 
478  const Bounds& bounds( sbdl->specificSurface().bounds());
479  float length = 0.5f*bounds.length();
480 
481  /*
482  cout << "starting: " << starting << endl;
483  cout << "target1: " << target1 << endl;
484  cout << "target2: " << target2 << endl;
485  cout << "dphi: " << (target1.phi()-target2.phi()) << endl;
486  cout << "length: " << length << endl;
487  */
488 
489  /*
490  float deltaZ = bounds.thickness()/2.f/fabs(tan(stateToUse.globalDirection().theta()) ) ;
491  if(stateToUse.hasError())
492  deltaZ += 3*sqrt(stateToUse.cartesianError().position().czz());
493  if( fabs(farther.z()) > length + deltaZ ) continue;
494  */
495  if(fabs(farther.z())*0.95f>length) continue;
496 
497  Geom::Phi<float> tmpDphi = target1.phi()-target2.phi();
498  if(std::abs(tmpDphi)>maxDPhiForLooperReconstruction) continue;
499  GlobalPoint target(0.5f*(target1.basicVector()+target2.basicVector()));
500  //cout << "target: " << target << endl;
501 
502 
503 
505  stateToUse = extrapolator.extrapolate(stateToUse, target, *propagator);
506  if (!stateToUse.isValid()) continue; //SK: consider trying the original? probably not
507 
508  //dPhiCacheForLoopersReconstruction = fabs(target1.phi()-target2.phi())*2.;
509  dPhiCacheForLoopersReconstruction = std::abs(tmpDphi);
510  traj.incrementLoops();
511  }else{ // not barrel
512  continue;
513  }
514  }else{ // loopers not requested (why else???)
515  // ------ For cosmics reconstruction
516  LogDebug("CkfPattern")<<" self propagating in advanceOneLayer.\n from: \n"<<stateToUse;
517  //self navigation case
518  // go to a middle point first
520  GlobalPoint center(0,0,0);
521  stateToUse = middle.extrapolate(stateToUse, center, *theForwardPropagator);
522 
523  if (!stateToUse.isValid()) continue;
524  LogDebug("CkfPattern")<<"to: "<<stateToUse;
525  }
526  } // last layer...
527 
528  //unsigned int maxCandidates = theMaxCand > 21 ? theMaxCand*2 : 42; //limit the number of returned segments
531  **il,*propagator,
534 
535 #ifdef EDM_ML_DEBUG
536  LogDebug("CkfPattern")<<whatIsTheStateToUse(stateAndLayers.first,stateToUse,*il);
537 #endif
538 
539  TempTrajectoryContainer segments=
540  layerBuilder.segments(stateToUse);
541 
542  LogDebug("CkfPattern")<< "GCTB: number of segments = " << segments.size();
543 
544  if ( !segments.empty() ) foundSegments = true;
545 
546  for ( TempTrajectoryContainer::iterator is=segments.begin();
547  is!=segments.end(); is++ ) {
548  //
549  // assume "invalid hit only" segment is last in list
550  //
551  const TempTrajectory::DataContainer & measurements = is->measurements();
552  if ( !theAlwaysUseInvalid && is!=segments.begin() && measurements.size()==1 &&
553  (measurements.front().recHit()->getType() == TrackingRecHit::missing) ) break;
554 
555 
556  //---- avoid to add the same hits more than once in the trajectory ----
557  bool toBeRejected(false);
558  for(const TempTrajectory::DataContainer::const_iterator revIt = measurements.rbegin();
559  revIt!=measurements.rend(); --revIt){
560  // int tmpCounter(0);
561  for(const TempTrajectory::DataContainer::const_iterator newTrajMeasIt = traj.measurements().rbegin();
562  newTrajMeasIt != traj.measurements().rend(); --newTrajMeasIt){
563  //if(tmpCounter==2) break;
564  if(revIt->recHitR().geographicalId()==newTrajMeasIt->recHitR().geographicalId()
565  && (revIt->recHitR().geographicalId() != DetId(0)) ){
566  toBeRejected=true;
567  goto rejected; //break; // see http://stackoverflow.com/questions/1257744/can-i-use-break-to-exit-multiple-nested-for-loops
568  }
569  // tmpCounter++;
570  }
571  }
572 
573  rejected:; // http://xkcd.com/292/
574  if(toBeRejected){
575  /*cout << "WARNING: neglect candidate because it contains the same hit twice \n";
576  cout << "-- discarded track's pt,eta,#found: "
577  << traj.lastMeasurement().updatedState().globalMomentum().perp() << " , "
578  << traj.lastMeasurement().updatedState().globalMomentum().eta() << " , "
579  << traj.foundHits() << "\n";
580  */
581  traj.setDPhiCacheForLoopersReconstruction(dPhiCacheForLoopersReconstruction);
582  continue; //Are we sure about this????
583  }
584  // ------------------------
585 
586  //
587  // create new candidate
588  //
589  TempTrajectory newTraj(traj);
590  traj.setDPhiCacheForLoopersReconstruction(dPhiCacheForLoopersReconstruction);
591  newTraj.join(*is);
592 
593  //std::cout << "DEBUG: newTraj after push found,lost: "
594  // << newTraj.foundHits() << " , "
595  // << newTraj.lostHits() << " , "
596  // << newTraj.measurements().size() << std::endl;
597 
598 
599 
600  //GIO// for ( vector<TM>::const_iterator im=measurements.begin();
601  //GIO// im!=measurements.end(); im++ ) newTraj.push(*im);
602  //if ( toBeContinued(newTraj,regionalCondition) ) { TOBE FIXED
603  if ( toBeContinued(newTraj, inOut) ) {
604  // Have added one more hit to track candidate
605 
606  LogDebug("CkfPattern")<<"GCTB: adding updated trajectory to candidates: inOut="<<inOut<<" hits="<<newTraj.foundHits();
607 
608  newCand.push_back(std::move(newTraj));
609  foundNewCandidates = true;
610  }
611  else {
612  // Have finished building this track. Check if it passes cuts.
613 
614  LogDebug("CkfPattern")<< "GCTB: adding completed trajectory to results if passes cuts: inOut="<<inOut<<" hits="<<newTraj.foundHits();
615 
616  moveToResult(std::move(newTraj), result, inOut);
617  }
618  } // loop over segs
619  } // loop over layers
620 
621  if ( !foundSegments ){
622  LogDebug("CkfPattern")<< "GCTB: adding input trajectory to result";
623  addToResult(traj, result, inOut);
624  }
625  return foundNewCandidates;
626 }
627 
628 namespace {
631  struct LayersInTraj {
632  static constexpr int N=3;
633  TempTrajectory * traj;
634  std::array<DetLayer const *,N> layers;
635  int tot;
636  void fill(TempTrajectory & t) {
637  traj = &t;
638  tot=0;
639  const TempTrajectory::DataContainer& measurements = traj->measurements();
640 
641  auto currl = layers[tot] = measurements.back().layer();
643  --ifirst;
645  im!=measurements.rend(); --im ) {
646  if ( im->layer()!=currl ) { ++tot; currl = im->layer(); if (tot<N) layers[tot] = currl;}
647  }
648  ++tot;
649  }
650 
651  //void verify() {
652  // for (vector<const DetLayer*>::const_iterator iter = result.begin(); iter != result.end(); iter++)
653  // if (!*iter) edm::LogWarning("CkfPattern")<< "Warning: null det layer!! ";
654  // }
655  };
656 }
657 
658 
659 //TempTrajectoryContainer
660 void
662 {
663  //if (theTrajectories.empty()) return TrajectoryContainer();
664  //TrajectoryContainer result;
665  if (theTrajectories.empty()) return;
666  //RecHitEqualByChannels recHitEqualByChannels(false, false);
667  LayersInTraj layers[theTrajectories.size()];
668  int ntraj=0;
669  for ( auto & t : theTrajectories) {
670  if ( t.isValid() && t.lastMeasurement().recHitR().isValid() )
671  layers[ntraj++].fill(t);
672  }
673 
674  if (ntraj<2) return;
675 
676  for (int ifirst=0; ifirst!=ntraj-1; ++ifirst) {
677  auto firstTraj = layers[ifirst].traj;
678  if (!firstTraj->isValid()) continue;
679  const TempTrajectory::DataContainer & firstMeasurements = firstTraj->measurements();
680 
681  int firstLayerSize = layers[ifirst].tot;
682  if ( firstLayerSize<4 ) continue;
683  auto const & firstLayers = layers[ifirst].layers;
684 
685  for (int isecond= ifirst+1; isecond!=ntraj; ++isecond) {
686  auto secondTraj = layers[isecond].traj;
687  if (!secondTraj->isValid()) continue;
688 
689  const TempTrajectory::DataContainer & secondMeasurements = secondTraj->measurements();
690 
691  int secondLayerSize = layers[isecond].tot;
692  //
693  // only candidates using the same last 3 layers are compared
694  //
695  if ( firstLayerSize!=secondLayerSize ) continue; // V.I. why equal???
696  auto const & secondLayers = layers[isecond].layers;
697  if ( firstLayers[0]!=secondLayers[0] ||
698  firstLayers[1]!=secondLayers[1] ||
699  firstLayers[2]!=secondLayers[2] ) continue;
700 
701  TempTrajectory::DataContainer::const_iterator im1 = firstMeasurements.rbegin();
702  TempTrajectory::DataContainer::const_iterator im2 = secondMeasurements.rbegin();
703  //
704  // check for identical hits in the last layer
705  //
706  bool unequal(false);
707  const DetLayer* layerPtr = firstLayers[0];
708  while ( im1!=firstMeasurements.rend()&&im2!=secondMeasurements.rend() ) {
709  if ( im1->layer()!=layerPtr || im2->layer()!=layerPtr ) break;
710  if ( !(im1->recHit()->isValid()) || !(im2->recHit()->isValid()) ||
711  !im1->recHit()->hit()->sharesInput(im2->recHit()->hit(), TrackingRecHit::some) ) {
713  unequal = true;
714  break;
715  }
716  --im1;
717  --im2;
718  }
719  if ( im1==firstMeasurements.rend() || im2==secondMeasurements.rend() ||
720  im1->layer()==layerPtr || im2->layer()==layerPtr || unequal ) continue;
721  //
722  // check for invalid hits in the layer -2
723  // compare only candidates with invalid / valid combination
724  //
725  layerPtr = firstLayers[1];
726  bool firstValid(true);
727  while ( im1!=firstMeasurements.rend()&&im1->layer()==layerPtr ) {
728  if ( !im1->recHit()->isValid() ) firstValid = false;
729  --im1;
730  }
731  bool secondValid(true);
732  while ( im2!=secondMeasurements.rend()&&im2->layer()==layerPtr ) {
733  if ( !im2->recHit()->isValid() ) secondValid = false;
734  --im2;
735  }
736  if ( !tkxor(firstValid,secondValid) ) continue;
737  //
738  // ask for identical hits in layer -3
739  //
740  unequal = false;
741  layerPtr = firstLayers[2];
742  while ( im1!=firstMeasurements.rend()&&im2!=secondMeasurements.rend() ) {
743  if ( im1->layer()!=layerPtr || im2->layer()!=layerPtr ) break;
744  if ( !(im1->recHit()->isValid()) || !(im2->recHit()->isValid()) ||
745  !im1->recHit()->hit()->sharesInput(im2->recHit()->hit(), TrackingRecHit::some) ) {
747  unequal = true;
748  break;
749  }
750  --im1;
751  --im2;
752  }
753  if ( im1==firstMeasurements.rend() || im2==secondMeasurements.rend() ||
754  im1->layer()==layerPtr || im2->layer()==layerPtr || unequal ) continue;
755 
756  if ( !firstValid ) {
757  firstTraj->invalidate();
758  break;
759  }
760  else {
761  secondTraj->invalidate(); // V.I. why break?
762  break;
763  }
764  } // second
765  } // first
766 /*
767  for (TempTrajectoryContainer::const_iterator it = theTrajectories.begin();
768  it != theTrajectories.end(); it++) {
769  if(it->isValid()) result.push_back( *it);
770  }
771 
772  return result;
773 */
774  theTrajectories.erase(std::remove_if( theTrajectories.begin(),theTrajectories.end(),
775  std::not1(std::mem_fun_ref(&TempTrajectory::isValid))),
776  // boost::bind(&TempTrajectory::isValid,_1)),
777  theTrajectories.end());
778 }
779 
780 
781 void
783  TempTrajectory const & startingTraj,
785 {
786  //
787  // Rebuilding of trajectories. Candidates are taken from result,
788  // which will be replaced with the solutions after rebuild
789  // (assume vector::swap is more efficient than building new container)
790  //
791  LogDebug("CkfPattern")<< "Starting to rebuild " << result.size() << " tracks";
792  //
793  // Fitter (need to create it here since the propagation direction
794  // might change between different starting trajectories)
795  //
797  //
798  TrajectorySeed::range rseedHits = seed.recHits();
799  std::vector<const TrackingRecHit*> seedHits;
800  //seedHits.insert(seedHits.end(), rseedHits.first, rseedHits.second);
801  //for (TrajectorySeed::recHitContainer::const_iterator iter = rseedHits.first; iter != rseedHits.second; iter++){
802  // seedHits.push_back(&*iter);
803  //}
804 
805  //unsigned int nSeed(seedHits.size());
806  unsigned int nSeed(rseedHits.second-rseedHits.first);
807  //seedHits.reserve(nSeed);
808  TempTrajectoryContainer rebuiltTrajectories;
809 
810  for ( TempTrajectoryContainer::iterator it=result.begin();
811  it!=result.end(); it++ ) {
812  //
813  // skip candidates which are not exceeding the seed size
814  // (e.g. because no Tracker layers outside seeding region)
815  //
816 
817  if ( it->measurements().size()<=startingTraj.measurements().size() ) {
818  rebuiltTrajectories.push_back(std::move(*it));
819  LogDebug("CkfPattern")<< "RebuildSeedingRegion skipped as in-out trajectory does not exceed seed size.";
820  continue;
821  }
822  //
823  // Refit - keep existing trajectory in case fit is not possible
824  // or fails
825  //
826 
827  auto && reFitted = backwardFit(*it,nSeed,fitter,seedHits);
828  if unlikely( !reFitted.isValid() ) {
829  rebuiltTrajectories.push_back(std::move(*it));
830  LogDebug("CkfPattern")<< "RebuildSeedingRegion skipped as backward fit failed";
831  // << "after reFitted.size() " << reFitted.size();
832  continue;
833  }
834  //LogDebug("CkfPattern")<<"after reFitted.size() " << reFitted.size();
835  //
836  // Rebuild seeding part. In case it fails: keep initial trajectory
837  // (better to drop it??)
838  //
839  int nRebuilt =
840  rebuildSeedingRegion (seed, seedHits,reFitted,rebuiltTrajectories);
841 
842  if ( nRebuilt==0 && !theKeepOriginalIfRebuildFails ) it->invalidate(); // won't use original in-out track
843 
844  if ( nRebuilt<0 ) rebuiltTrajectories.push_back(std::move(*it));
845 
846  }
847  //
848  // Replace input trajectories with new ones
849  //
850  result.swap(rebuiltTrajectories);
851  result.erase(std::remove_if( result.begin(),result.end(),
852  std::not1(std::mem_fun_ref(&TempTrajectory::isValid))),
853  result.end());
854 }
855 
856 int
858  const std::vector<const TrackingRecHit*>& seedHits,
859  TempTrajectory& candidate,
861 {
862  //
863  // Starting from track found by in-out tracking phase, extrapolate it inwards through
864  // the seeding region if possible in towards smaller Tracker radii, searching for additional
865  // hits.
866  // The resulting trajectories are returned in result,
867  // the count is the return value.
868  //
869  TempTrajectoryContainer rebuiltTrajectories;
870 #ifdef DBG2_GCTB
871 /* const LayerFinderByDet layerFinder;
872  if ( !seedHits.empty() && seedHits.front().isValid() ) {
873  DetLayer* seedLayer = layerFinder(seedHits.front().det());
874  cout << "Seed hit at " << seedHits.front().globalPosition()
875  << " " << seedLayer << endl;
876  cout << "Started from "
877  << candidate.lastMeasurement().updatedState().globalPosition().perp() << " "
878  << candidate.lastMeasurement().updatedState().globalPosition().z() << endl;
879  pair<bool,TrajectoryStateOnSurface> layerComp(false,TrajectoryStateOnSurface());
880  if ( seedLayer ) layerComp =
881  seedLayer->compatible(candidate.lastMeasurement().updatedState(),
882  propagator(),estimator());
883  pair<bool,TrajectoryStateOnSurface> detComp =
884  seedHits.front().det().compatible(candidate.lastMeasurement().updatedState(),
885  propagator(),estimator());
886  cout << " layer compatibility = " << layerComp.first;
887  cout << " det compatibility = " << detComp.first;
888  if ( detComp.first ) {
889  cout << " estimate = "
890  << estimator().estimate(detComp.second,seedHits.front()).second ;
891  }
892  cout << endl;
893  }*/
894  cout << "Before backward building: #measurements = "
895  << candidate.measurements().size() ; //<< endl;;
896 #endif
897  //
898  // Use standard building with standard cuts. Maybe better to use different
899  // cuts from "forward" building (e.g. no check on nr. of invalid hits)?
900  //
901  const bool inOut = false;
902  groupedLimitedCandidates(candidate, (const TrajectoryFilter*)0, theBackwardPropagator, inOut, rebuiltTrajectories);
903 
904  LogDebug("CkfPattern")<<" After backward building: "<<PrintoutHelper::dumpCandidates(rebuiltTrajectories);
905 
906  //
907  // Check & count resulting candidates
908  //
909  int nrOfTrajectories(0);
910  bool orig_ok = false;
911  //const RecHitEqualByChannels recHitEqual(false,false);
912  //vector<TM> oldMeasurements(candidate.measurements());
913  for ( TempTrajectoryContainer::iterator it=rebuiltTrajectories.begin();
914  it!=rebuiltTrajectories.end(); it++ ) {
915 
916  TempTrajectory::DataContainer newMeasurements(it->measurements());
917  //
918  // Verify presence of seeding hits?
919  //
921  orig_ok = true;
922  // no hits found (and possibly some invalid hits discarded): drop track
923  if ( newMeasurements.size()<=candidate.measurements().size() ){
924  LogDebug("CkfPattern") << "newMeasurements.size()<=candidate.measurements().size()";
925  continue;
926  }
927  // verify presence of hits
928  //GIO//if ( !verifyHits(newMeasurements.begin()+candidate.measurements().size(),
929  //GIO// newMeasurements.end(),seedHits) ){
930  if ( !verifyHits(newMeasurements.rbegin(),
931  newMeasurements.size() - candidate.measurements().size(),
932  seedHits) ){
933  LogDebug("CkfPattern")<< "seed hits not found in rebuild";
934  continue;
935  }
936  }
937  //
938  // construct final trajectory in the right order
939  //
940  // save & count result
941  nrOfTrajectories++;
942  result.emplace_back(seed.direction());
943  TempTrajectory & reversedTrajectory = result.back();
944  reversedTrajectory.setNLoops(it->nLoops());
945  for (TempTrajectory::DataContainer::const_iterator im=newMeasurements.rbegin(), ed = newMeasurements.rend();
946  im != ed; --im ) {
947  reversedTrajectory.push(*im);
948  }
949 
950  LogDebug("CkgPattern")<<"New traj direction = " << reversedTrajectory.direction()<<"\n"
951  <<PrintoutHelper::dumpMeasurements(reversedTrajectory.measurements());
952  } // rebuiltTrajectories
953 
954  // If nrOfTrajectories = 0 and orig_ok = true, this means that a track was actually found on the
955  // out-in step (meeting those requirements) but did not have the seed hits in it.
956  // In this case when we return we will go ahead and use the original in-out track.
957 
958  // If nrOfTrajectories = 0 and orig_ok = false, this means that the out-in step failed to
959  // find any track. Two cases are a technical failure in fitting the original seed hits or
960  // because the track did not meet the out-in criteria (which may be stronger than the out-in
961  // criteria). In this case we will NOT allow the original in-out track to be used.
962 
963  if ( (nrOfTrajectories == 0) && orig_ok ) {
964  nrOfTrajectories = -1;
965  }
966  return nrOfTrajectories;
967 }
968 
971  const TrajectoryFitter& fitter,
972  std::vector<const TrackingRecHit*>& remainingHits) const
973 {
974  //
975  // clear array of non-fitted hits
976  //
977  remainingHits.clear();
978  //
979  // skip candidates which are not exceeding the seed size
980  // (e.g. Because no Tracker layers exist outside seeding region)
981  //
982  if unlikely( candidate.measurements().size()<=nSeed ) return TempTrajectory();
983 
984  LogDebug("CkfPattern")<<"nSeed " << nSeed << endl
985  << "Old traj direction = " << candidate.direction() << endl
987 
988  //
989  // backward fit trajectory.
990  // (Will try to fit only hits outside the seeding region. However,
991  // if there are not enough of these, it will also use the seeding hits).
992  //
993  // const unsigned int nHitAllMin(5);
994  // const unsigned int nHit2dMin(2);
995  unsigned int nHit(0); // number of valid hits after seeding region
996  //unsigned int nHit2d(0); // number of valid hits after seeding region with 2D info
997  // use all hits except the first n (from seed), but require minimum
998  // specified in configuration.
999  // Swapped over next two lines.
1000  unsigned int nHitMin = std::max(candidate.foundHits()-nSeed,theMinNrOfHitsForRebuild);
1001  // unsigned int nHitMin = oldMeasurements.size()-nSeed;
1002  // we want to rebuild only if the number of VALID measurements excluding the seed measurements is higher than the cut
1003  if unlikely(nHitMin<theMinNrOfHitsForRebuild) return TempTrajectory();
1004 
1005  LogDebug("CkfPattern")/* << "nHitMin " << nHitMin*/ <<"Sizes: " << candidate.measurements().size() << " / ";
1006  //
1007  // create input trajectory for backward fit
1008  //
1009  Trajectory fwdTraj(oppositeDirection(candidate.direction()));
1010  fwdTraj.setNLoops(candidate.nLoops());
1011  //const TrajectorySeed seed = TrajectorySeed(PTrajectoryStateOnDet(), TrajectorySeed::recHitContainer(), oppositeDirection(candidate.direction()));
1012  //Trajectory fwdTraj(seed, oppositeDirection(candidate.direction()));
1013 
1014  const DetLayer* bwdDetLayer[candidate.measurements().size()];
1015  int nl=0;
1016  for ( auto const & tm : candidate.measurements() ) {
1017  const TrackingRecHit* hit = tm.recHitR().hit();
1018  //
1019  // add hits until required number is reached
1020  //
1021  if ( nHit<nHitMin ){//|| nHit2d<theMinNrOf2dHitsForRebuild ) {
1022  fwdTraj.push(tm);
1023  bwdDetLayer[nl++]=tm.layer();
1024  //
1025  // count valid / 2D hits
1026  //
1027  if likely( hit->isValid() ) {
1028  nHit++;
1029  //if ( hit.isMatched() ||
1030  // hit.det().detUnits().front()->type().module()==pixel )
1031  //nHit2d++;
1032  }
1033  }
1034  //if (nHit==nHitMin) lastBwdDetLayer=im->layer();
1035  //
1036  // keep remaining (valid) hits for verification
1037  //
1038  else if ( hit->isValid() ) {
1039  //std::cout << "Adding a remaining hit" << std::endl;
1040  remainingHits.push_back(hit);
1041  }
1042  }
1043  //
1044  // Fit only if required number of valid hits can be used
1045  //
1046  if unlikely( nHit<nHitMin ) return TempTrajectory();
1047 
1048  //
1049  // Do the backward fit (important: start from scaled, not random cov. matrix!)
1050  //
1052  //cout << "firstTsos "<< firstTsos << endl;
1053  firstTsos.rescaleError(10.);
1054  //TrajectoryContainer bwdFitted(fitter.fit(fwdTraj.seed(),fwdTraj.recHits(),firstTsos));
1056  fwdTraj.recHits(),firstTsos);
1057  if unlikely(!bwdFitted.isValid()) return TempTrajectory();
1058 
1059 
1060  LogDebug("CkfPattern")<<"Obtained bwdFitted trajectory with measurement size " << bwdFitted.measurements().size();
1061  TempTrajectory fitted(fwdTraj.direction());
1062  fitted.setNLoops(fwdTraj.nLoops());
1063  vector<TM> const & tmsbf = bwdFitted.measurements();
1064  int iDetLayer=0;
1065  //this is ugly but the TM in the fitted track do not contain the DetLayer.
1066  //So we have to cache the detLayer pointers and replug them in.
1067  //For the backward building it would be enaugh to cache the last DetLayer,
1068  //but for the intermediary cleaning we need all
1069  for ( vector<TM>::const_iterator im=tmsbf.begin();im!=tmsbf.end(); im++ ) {
1070  fitted.emplace( (*im).forwardPredictedState(),
1071  (*im).backwardPredictedState(),
1072  (*im).updatedState(),
1073  (*im).recHit(),
1074  (*im).estimate(),
1075  bwdDetLayer[iDetLayer]
1076  );
1077 
1078  LogDebug("CkfPattern")<<PrintoutHelper::dumpMeasurement(*im);
1079  iDetLayer++;
1080  }
1081  /*
1082  TM lastMeas = bwdFitted.front().lastMeasurement();
1083  fitted.pop();
1084  fitted.push(TM(lastMeas.forwardPredictedState(),
1085  lastMeas.backwardPredictedState(),
1086  lastMeas.updatedState(),
1087  lastMeas.recHit(),
1088  lastMeas.estimate(),
1089  lastBwdDetLayer));
1090  */
1091 
1092 
1093  return fitted;
1094 }
1095 
1096 bool
1098  size_t maxDepth,
1099  const std::vector<const TrackingRecHit*>& hits) const
1100 {
1101  //
1102  // verify presence of the seeding hits
1103  //
1104  LogDebug("CkfPattern")<<"Checking for " << hits.size() << " hits in "
1105  << maxDepth << " measurements" << endl;
1106 
1108  while (maxDepth > 0) { --maxDepth; --rend; }
1109  for ( vector<const TrackingRecHit*>::const_iterator ir=hits.begin();
1110  ir!=hits.end(); ir++ ) {
1111  // assume that all seeding hits are valid!
1112  bool foundHit(false);
1113  for ( TempTrajectory::DataContainer::const_iterator im=rbegin; im!=rend; --im ) {
1114  if ( im->recHit()->isValid() && (*ir)->sharesInput(im->recHit()->hit(), TrackingRecHit::some) ) {
1115  foundHit = true;
1116  break;
1117  }
1118  }
1119  if ( !foundHit ) return false;
1120  }
1121  return true;
1122 }
1123 
1124 
1125 
1126 
#define LogDebug(id)
PropagationDirection direction() const
T getParameter(std::string const &) const
const_iterator rend() const
Definition: bqueue.h:165
int i
Definition: DBlmapReader.cc:9
#define maxDepth
static std::string dumpCandidates(collection &candidates)
void groupedIntermediaryClean(TempTrajectoryContainer &theTrajectories) const dso_internal
intermediate cleaning in the case of grouped measurements
string fill
Definition: lumiContext.py:319
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:187
virtual float length() const =0
T perp() const
Definition: PV3DBase.h:72
ConstRecHitPointer const & recHit() const
void join(TempTrajectory &segment)
const Propagator * theBackwardPropagator
virtual Location location() const =0
Which part of the detector (barrel, endcap)
static void clean(TempTrajectoryContainer &tracks)
TrajectoryContainer trajectories(const TrajectorySeed &) const
set Event for the internal MeasurementTracker data member
std::string print(const Track &, edm::Verbosity=edm::Concise)
Track print utility.
Definition: print.cc:8
const CurvilinearTrajectoryError & curvilinearError() const
TempTrajectory buildTrajectories(const TrajectorySeed &seed, TrajectoryContainer &ret, const TrajectoryFilter *) const
common part of both public trajectory building methods
bool advanceOneLayer(TempTrajectory &traj, const TrajectoryFilter *regionalCondition, const Propagator *propagator, bool inOut, TempTrajectoryContainer &newCand, TempTrajectoryContainer &result) const dso_internal
const DataContainer & measurements() const
GroupedCkfTrajectoryBuilder(const edm::ParameterSet &conf, const TrajectoryStateUpdator *updator, const Propagator *propagatorAlong, const Propagator *propagatorOpposite, const Chi2MeasurementEstimatorBase *estimator, const TransientTrackingRecHitBuilder *RecHitBuilder, const MeasurementTracker *measurementTracker, const TrajectoryFilter *filter, const TrajectoryFilter *inOutFilter)
constructor from ParameterSet
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
void setNLoops(signed char value)
Definition: Trajectory.h:334
void setNLoops(signed char value)
#define abs(x)
Definition: mlp_lapack.h:159
const TrajectoryStateUpdator * theUpdator
virtual void analyseSeed(const TrajectorySeed &seed) const
GlobalPoint globalPosition() const
int foundHits() const
obsolete name, use measurements() instead.
TempTrajectoryContainer segments(const TSOS startingState)
new segments within layer
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is rejected(acceptEvent retursns false).There are 3 relevant cases of types of criteria
bool tkxor(bool a, bool b) const dso_internal
static std::string dumpMeasurement(const TrajectoryMeasurement &tm)
static std::string dumpMeasurements(const std::vector< TrajectoryMeasurement > &v)
virtual PropagationDirection propagationDirection() const GCC11_FINAL
Definition: Propagator.h:145
bool verifyHits(TempTrajectory::DataContainer::const_iterator rbegin, size_t maxDepth, const std::vector< const TrackingRecHit * > &hits) const dso_internal
Verifies presence of a RecHits in a range of TrajectoryMeasurements.
signed char nLoops() const
Definition: Trajectory.h:332
ConstRecHitContainer recHits(bool splitting=false) const
Definition: Trajectory.cc:67
const T & front() const
Definition: bqueue.h:160
const TrajectoryMeasurement & lastMeasurement() const
PropagationDirection const & direction() const
Definition: Trajectory.cc:196
#define unlikely(x)
Definition: Likely.h:21
const LayerMeasurements * theLayerMeasurements
PropagationDirection direction() const
void setDPhiCacheForLoopersReconstruction(float dphi)
DataContainer const & measurements() const
Definition: Trajectory.h:215
void rebuildTrajectories(TempTrajectory const &startingTraj, const TrajectorySeed &, TrajectoryContainer &result) const
virtual void analyseResult(const TrajectoryContainer &result) const
void groupedLimitedCandidates(TempTrajectory const &startingTraj, const TrajectoryFilter *regionalCondition, const Propagator *propagator, bool inOut, TempTrajectoryContainer &result) const dso_internal
const T & max(const T &a, const T &b)
static PropagationDirection oppositeDirection(PropagationDirection dir)
change of propagation direction
T sqrt(T t)
Definition: SSEVec.h:48
T z() const
Definition: PV3DBase.h:64
tuple result
Definition: query.py:137
const Chi2MeasurementEstimatorBase & estimator() const
std::pair< const_iterator, const_iterator > range
void rebuildSeedingRegion(const TrajectorySeed &, TrajectoryContainer &result) const
const DetLayer * layer() const
double f[11][100]
void addToResult(boost::shared_ptr< const TrajectorySeed > const &seed, TempTrajectory &traj, TrajectoryContainer &result, bool inOut=false) const
virtual Trajectory fitOne(const Trajectory &traj, fitType type=standard) const =0
const T & back() const
Definition: bqueue.h:162
tuple conf
Definition: dbtoconf.py:185
const_iterator rbegin() const
Definition: bqueue.h:164
bool isValid() const
StateAndLayers findStateAndLayers(const TrajectorySeed &seed, const TempTrajectory &traj) const
Definition: DetId.h:20
const MeasurementTracker * theMeasurementTracker
bool isValid() const
Definition: Trajectory.h:271
TrajectoryMeasurement const & firstMeasurement() const
Definition: Trajectory.h:206
#define N
Definition: blowfish.cc:9
std::vector< TempTrajectory > TempTrajectoryContainer
range recHits() const
bool isValid() const
ConstRecHitPointer::element_type const & recHitR() const
virtual const BoundDisk & specificSurface() const GCC11_FINAL
TempTrajectory backwardFit(TempTrajectory &candidate, unsigned int nSeed, const TrajectoryFitter &fitter, std::vector< const TrackingRecHit * > &remainingHits) const dso_internal
const TrajectoryStateUpdator & updator() const
void moveToResult(TempTrajectory &&traj, TempTrajectoryContainer &result, bool inOut=false) const
TrajectoryStateOnSurface extrapolate(const FreeTrajectoryState &fts, const GlobalPoint &vtx) const
extrapolation with default (=geometrical) propagator
#define likely(x)
Definition: Likely.h:20
const AlgebraicSymMatrix55 & matrix() const
GlobalVector globalMomentum() const
bool toBeContinued(TempTrajectory &traj, bool inOut=false) const
tuple cout
Definition: gather_cfg.py:121
TrajectoryStateOnSurface const & updatedState() const
size_type size() const
Definition: bqueue.h:168
Definition: Bounds.h:22
signed char nLoops() const
const DetLayer * lastLayer() const
Redundant method, returns the layer of lastMeasurement() .
const BasicVectorType & basicVector() const
Definition: PV3DBase.h:56
virtual const BoundCylinder & specificSurface() const GCC11_FINAL
Extension of the interface.
void push(const TrajectoryMeasurement &tm)
Definition: Trajectory.cc:35
std::vector< Trajectory > TrajectoryContainer
const Chi2MeasurementEstimatorBase * theEstimator
#define constexpr
TempTrajectory createStartingTrajectory(const TrajectorySeed &seed) const
void push(const TrajectoryMeasurement &tm)
const Propagator * theForwardPropagator