CMS 3D CMS Logo

MkFitOutputConverter.cc
Go to the documentation of this file.
2 
7 
16 
20 
23 
32 
39 
40 // mkFit indludes
44 
45 //extra for DNN with cands
52 
53 namespace {
54  template <typename T>
55  bool isBarrel(T subdet) {
56  return subdet == PixelSubdetector::PixelBarrel || subdet == StripSubdetector::TIB ||
57  subdet == StripSubdetector::TOB;
58  }
59 
60  template <typename T>
61  bool isEndcap(T subdet) {
62  return subdet == PixelSubdetector::PixelEndcap || subdet == StripSubdetector::TID ||
63  subdet == StripSubdetector::TEC;
64  }
65 } // namespace
66 
68 public:
69  explicit MkFitOutputConverter(edm::ParameterSet const& iConfig);
70  ~MkFitOutputConverter() override = default;
71 
72  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
73 
74 private:
75  void produce(edm::StreamID, edm::Event& iEvent, const edm::EventSetup& iSetup) const override;
76 
79  const MkFitClusterIndexToHit& pixelClusterIndexToHit,
80  const MkFitClusterIndexToHit& stripClusterIndexToHit,
82  const MagneticField& mf,
85  const MkFitGeometry& mkFitGeom,
86  const TkClonerImpl& hitCloner,
87  const std::vector<const DetLayer*>& detLayers,
89  const reco::BeamSpot* bs,
91  const tensorflow::Session* session) const;
92 
93  std::pair<TrajectoryStateOnSurface, const GeomDet*> backwardFit(const FreeTrajectoryState& fts,
97  const TkClonerImpl& hitCloner,
98  bool lastHitWasInvalid,
99  bool lastHitWasChanged) const;
100 
101  std::pair<TrajectoryStateOnSurface, const GeomDet*> convertInnermostState(const FreeTrajectoryState& fts,
104  const Propagator& propagatorOpposite) const;
105 
106  std::vector<float> computeDNNs(TrackCandidateCollection const& tkCC,
107  const std::vector<TrajectoryStateOnSurface>& states,
108  const reco::BeamSpot* bs,
110  const tensorflow::Session* session,
111  const std::vector<float>& chi2,
112  const bool rescaledError) const;
113 
127 
128  const float qualityMaxInvPt_;
129  const float qualityMinTheta_;
130  const float qualityMaxRsq_;
131  const float qualityMaxZ_;
132  const float qualityMaxPosErrSq_;
133  const bool qualitySignPt_;
134 
135  const bool doErrorRescale_;
136 
137  const int algo_;
138  const bool algoCandSelection_;
140  const int bsize_;
145 };
146 
148  : eventOfHitsToken_{consumes<MkFitEventOfHits>(iConfig.getParameter<edm::InputTag>("mkFitEventOfHits"))},
149  pixelClusterIndexToHitToken_{consumes(iConfig.getParameter<edm::InputTag>("mkFitPixelHits"))},
150  stripClusterIndexToHitToken_{consumes(iConfig.getParameter<edm::InputTag>("mkFitStripHits"))},
151  mkfitSeedToken_{consumes<MkFitSeedWrapper>(iConfig.getParameter<edm::InputTag>("mkFitSeeds"))},
152  tracksToken_{consumes<MkFitOutputWrapper>(iConfig.getParameter<edm::InputTag>("tracks"))},
153  seedToken_{consumes<edm::View<TrajectorySeed>>(iConfig.getParameter<edm::InputTag>("seeds"))},
154  propagatorAlongToken_{
155  esConsumes<Propagator, TrackingComponentsRecord>(iConfig.getParameter<edm::ESInputTag>("propagatorAlong"))},
156  propagatorOppositeToken_{esConsumes<Propagator, TrackingComponentsRecord>(
157  iConfig.getParameter<edm::ESInputTag>("propagatorOpposite"))},
158  mfToken_{esConsumes<MagneticField, IdealMagneticFieldRecord>()},
159  ttrhBuilderToken_{esConsumes<TransientTrackingRecHitBuilder, TransientRecHitRecord>(
160  iConfig.getParameter<edm::ESInputTag>("ttrhBuilder"))},
161  mkFitGeomToken_{esConsumes<MkFitGeometry, TrackerRecoGeometryRecord>()},
162  putTrackCandidateToken_{produces<TrackCandidateCollection>()},
163  putSeedStopInfoToken_{produces<std::vector<SeedStopInfo>>()},
164  qualityMaxInvPt_{float(iConfig.getParameter<double>("qualityMaxInvPt"))},
165  qualityMinTheta_{float(iConfig.getParameter<double>("qualityMinTheta"))},
166  qualityMaxRsq_{float(pow(iConfig.getParameter<double>("qualityMaxR"), 2))},
167  qualityMaxZ_{float(iConfig.getParameter<double>("qualityMaxZ"))},
168  qualityMaxPosErrSq_{float(pow(iConfig.getParameter<double>("qualityMaxPosErr"), 2))},
169  qualitySignPt_{iConfig.getParameter<bool>("qualitySignPt")},
170  doErrorRescale_{iConfig.getParameter<bool>("doErrorRescale")},
172  TString(iConfig.getParameter<edm::InputTag>("seeds").label()).ReplaceAll("Seeds", "").Data())},
173  algoCandSelection_{bool(iConfig.getParameter<bool>("candMVASel"))},
174  algoCandWorkingPoint_{float(iConfig.getParameter<double>("candWP"))},
175  bsize_{int(iConfig.getParameter<int>("batchSize"))},
176  bsToken_(algoCandSelection_ ? consumes<reco::BeamSpot>(edm::InputTag("offlineBeamSpot"))
178  verticesToken_(algoCandSelection_ ? consumes<reco::VertexCollection>(edm::InputTag("firstStepPrimaryVertices"))
180  tfDnnLabel_(iConfig.getParameter<std::string>("tfDnnLabel")),
181  tfDnnToken_(esConsumes(edm::ESInputTag("", tfDnnLabel_))) {}
182 
185 
186  desc.add("mkFitEventOfHits", edm::InputTag{"mkFitEventOfHits"});
187  desc.add("mkFitPixelHits", edm::InputTag{"mkFitSiPixelHits"});
188  desc.add("mkFitStripHits", edm::InputTag{"mkFitSiStripHits"});
189  desc.add("mkFitSeeds", edm::InputTag{"mkFitSeedConverter"});
190  desc.add("tracks", edm::InputTag{"mkFitProducer"});
191  desc.add("seeds", edm::InputTag{"initialStepSeeds"});
192  desc.add("ttrhBuilder", edm::ESInputTag{"", "WithTrackAngle"});
193  desc.add("propagatorAlong", edm::ESInputTag{"", "PropagatorWithMaterial"});
194  desc.add("propagatorOpposite", edm::ESInputTag{"", "PropagatorWithMaterialOpposite"});
195 
196  desc.add<double>("qualityMaxInvPt", 100)->setComment("max(1/pt) for converted tracks");
197  desc.add<double>("qualityMinTheta", 0.01)->setComment("lower bound on theta (or pi-theta) for converted tracks");
198  desc.add<double>("qualityMaxR", 120)->setComment("max(R) for the state position for converted tracks");
199  desc.add<double>("qualityMaxZ", 280)->setComment("max(|Z|) for the state position for converted tracks");
200  desc.add<double>("qualityMaxPosErr", 100)->setComment("max position error for converted tracks");
201  desc.add<bool>("qualitySignPt", true)->setComment("check sign of 1/pt for converted tracks");
202 
203  desc.add<bool>("doErrorRescale", true)->setComment("rescale candidate error before final fit");
204 
205  desc.add<std::string>("tfDnnLabel", "trackSelectionTf");
206 
207  desc.add<bool>("candMVASel", false)->setComment("flag used to trigger MVA selection at cand level");
208  desc.add<double>("candWP", 0)->setComment("MVA selection at cand level working point");
209  desc.add<int>("batchSize", 16)->setComment("batch size for cand DNN evaluation");
210 
211  descriptions.addWithDefaultLabel(desc);
212 }
213 
215  const auto& seeds = iEvent.get(seedToken_);
216  const auto& mkfitSeeds = iEvent.get(mkfitSeedToken_);
217 
218  const auto& ttrhBuilder = iSetup.getData(ttrhBuilderToken_);
219  const auto* tkBuilder = dynamic_cast<TkTransientTrackingRecHitBuilder const*>(&ttrhBuilder);
220  if (!tkBuilder) {
221  throw cms::Exception("LogicError") << "TTRHBuilder must be of type TkTransientTrackingRecHitBuilder";
222  }
223  const auto& mkFitGeom = iSetup.getData(mkFitGeomToken_);
224 
225  // primary vertices under the algo_ because in initialStepPreSplitting there are no firstStepPrimaryVertices
226  // beamspot as well since the producer can be used in hlt
227  const reco::VertexCollection* vertices = nullptr;
228  const reco::BeamSpot* beamspot = nullptr;
229  if (algoCandSelection_) {
231  beamspot = &iEvent.get(bsToken_);
232  }
233 
234  const tensorflow::Session* session = nullptr;
235  if (algoCandSelection_)
236  session = iSetup.getData(tfDnnToken_).getSession();
237 
238  // Convert mkfit presentation back to CMSSW
241  iEvent.get(eventOfHitsToken_).get(),
244  seeds,
245  iSetup.getData(mfToken_),
248  iSetup.getData(mkFitGeomToken_),
249  tkBuilder->cloner(),
250  mkFitGeom.detLayers(),
251  mkfitSeeds.seeds(),
252  beamspot,
253  vertices,
254  session));
255 
256  // TODO: SeedStopInfo is currently unfilled
257  iEvent.emplace(putSeedStopInfoToken_, seeds.size());
258 }
259 
262  const MkFitClusterIndexToHit& pixelClusterIndexToHit,
263  const MkFitClusterIndexToHit& stripClusterIndexToHit,
265  const MagneticField& mf,
268  const MkFitGeometry& mkFitGeom,
269  const TkClonerImpl& hitCloner,
270  const std::vector<const DetLayer*>& detLayers,
272  const reco::BeamSpot* bs,
274  const tensorflow::Session* session) const {
276  const auto& candidates = mkFitOutput.tracks();
277  output.reserve(candidates.size());
278 
279  LogTrace("MkFitOutputConverter") << "Number of candidates " << candidates.size();
280 
281  std::vector<float> chi2;
282  std::vector<TrajectoryStateOnSurface> states;
283  chi2.reserve(candidates.size());
284  states.reserve(candidates.size());
285 
286  int candIndex = -1;
287  for (const auto& cand : candidates) {
288  ++candIndex;
289  LogTrace("MkFitOutputConverter") << "Candidate " << candIndex << " pT " << cand.pT() << " eta " << cand.momEta()
290  << " phi " << cand.momPhi() << " chi2 " << cand.chi2();
291 
292  // state: check for basic quality first
293  if (cand.state().invpT() > qualityMaxInvPt_ || (qualitySignPt_ && cand.state().invpT() < 0) ||
294  cand.state().theta() < qualityMinTheta_ || (M_PI - cand.state().theta()) < qualityMinTheta_ ||
295  cand.state().posRsq() > qualityMaxRsq_ || std::abs(cand.state().z()) > qualityMaxZ_ ||
296  (cand.state().errors.At(0, 0) + cand.state().errors.At(1, 1) + cand.state().errors.At(2, 2)) >
298  edm::LogInfo("MkFitOutputConverter")
299  << "Candidate " << candIndex << " failed state quality checks" << cand.state().parameters;
300  continue;
301  }
302 
303  auto state = cand.state(); // copy because have to modify
304  state.convertFromCCSToGlbCurvilinear();
305  const auto& param = state.parameters;
306  const auto& err = state.errors;
308  for (int i = 0; i < 5; ++i) {
309  for (int j = i; j < 5; ++j) {
310  cov[i][j] = err.At(i, j);
311  }
312  }
313 
314  auto fts = FreeTrajectoryState(
316  GlobalPoint(param[0], param[1], param[2]), GlobalVector(param[3], param[4], param[5]), state.charge, &mf),
318  if (!fts.curvilinearError().posDef()) {
319  edm::LogInfo("MkFitOutputConverter")
320  << "Curvilinear error not pos-def\n"
321  << fts.curvilinearError().matrix() << "\ncandidate " << candIndex << "ignored";
322  continue;
323  }
324 
325  //Sylvester's criterion, start from the smaller submatrix size
326  double det = 0;
327  if ((!fts.curvilinearError().matrix().Sub<AlgebraicSymMatrix22>(0, 0).Det(det)) || det < 0) {
328  edm::LogInfo("MkFitOutputConverter")
329  << "Fail pos-def check sub2.det for candidate " << candIndex << " with fts " << fts;
330  continue;
331  } else if ((!fts.curvilinearError().matrix().Sub<AlgebraicSymMatrix33>(0, 0).Det(det)) || det < 0) {
332  edm::LogInfo("MkFitOutputConverter")
333  << "Fail pos-def check sub3.det for candidate " << candIndex << " with fts " << fts;
334  continue;
335  } else if ((!fts.curvilinearError().matrix().Sub<AlgebraicSymMatrix44>(0, 0).Det(det)) || det < 0) {
336  edm::LogInfo("MkFitOutputConverter")
337  << "Fail pos-def check sub4.det for candidate " << candIndex << " with fts " << fts;
338  continue;
339  } else if ((!fts.curvilinearError().matrix().Det2(det)) || det < 0) {
340  edm::LogInfo("MkFitOutputConverter")
341  << "Fail pos-def check det for candidate " << candIndex << " with fts " << fts;
342  continue;
343  }
344 
345  // hits
347  // nTotalHits() gives sum of valid hits (nFoundHits()) and invalid/missing hits.
348  const int nhits = cand.nTotalHits();
349  bool lastHitInvalid = false;
350  for (int i = 0; i < nhits; ++i) {
351  const auto& hitOnTrack = cand.getHitOnTrack(i);
352  LogTrace("MkFitOutputConverter") << " hit on layer " << hitOnTrack.layer << " index " << hitOnTrack.index;
353  if (hitOnTrack.index < 0) {
354  // See index-desc.txt file in mkFit for description of negative values
355  //
356  // In order to use the regular InvalidTrackingRecHit I'd need
357  // a GeomDet (and "unfortunately" that is needed in
358  // TrackProducer).
359  //
360  // I guess we could take the track state and propagate it to
361  // each layer to find the actual module the track crosses, and
362  // check whether it is active or not to be able to mark
363  // inactive hits
364  const auto* detLayer = detLayers.at(hitOnTrack.layer);
365  if (detLayer == nullptr) {
366  throw cms::Exception("LogicError") << "DetLayer for layer index " << hitOnTrack.layer << " is null!";
367  }
368  // In principle an InvalidTrackingRecHitNoDet could be
369  // inserted here, but it seems that it is best to deal with
370  // them in the TrackProducer.
371  lastHitInvalid = true;
372  } else {
373  auto const isPixel = eventOfHits[hitOnTrack.layer].is_pixel();
374  auto const& hits = isPixel ? pixelClusterIndexToHit.hits() : stripClusterIndexToHit.hits();
375 
376  auto const& thit = static_cast<BaseTrackerRecHit const&>(*hits[hitOnTrack.index]);
377  if (mkFitGeom.isPhase1()) {
378  if (thit.firstClusterRef().isPixel() || thit.detUnit()->type().isEndcap()) {
379  recHits.push_back(hits[hitOnTrack.index]->clone());
380  } else {
381  recHits.push_back(std::make_unique<SiStripRecHit1D>(
382  thit.localPosition(),
383  LocalError(thit.localPositionError().xx(), 0.f, std::numeric_limits<float>::max()),
384  *thit.det(),
385  thit.firstClusterRef()));
386  }
387  } else {
388  recHits.push_back(hits[hitOnTrack.index]->clone());
389  }
390  LogTrace("MkFitOutputConverter") << " pos " << recHits.back().globalPosition().x() << " "
391  << recHits.back().globalPosition().y() << " "
392  << recHits.back().globalPosition().z() << " mag2 "
393  << recHits.back().globalPosition().mag2() << " detid "
394  << recHits.back().geographicalId().rawId() << " cluster " << hitOnTrack.index;
395  lastHitInvalid = false;
396  }
397  }
398 
399  const auto lastHitId = recHits.back().geographicalId();
400 
401  // MkFit hits are *not* in the order of propagation, sort by 3D radius for now (as we don't have loopers)
402  // TODO: Improve the sorting (extract keys? maybe even bubble sort would work well as the hits are almost in the correct order)
403  recHits.sort([](const auto& a, const auto& b) {
404  const auto asub = a.geographicalId().subdetId();
405  const auto bsub = b.geographicalId().subdetId();
406  if (asub != bsub) {
407  // Subdetector order (BPix, FPix, TIB, TID, TOB, TEC) corresponds also the navigation
408  return asub < bsub;
409  }
410 
411  const auto& apos = a.globalPosition();
412  const auto& bpos = b.globalPosition();
413 
414  if (isBarrel(asub)) {
415  return apos.perp2() < bpos.perp2();
416  }
417  return std::abs(apos.z()) < std::abs(bpos.z());
418  });
419 
420  const bool lastHitChanged = (recHits.back().geographicalId() != lastHitId); // TODO: make use of the bools
421 
422  // seed
423  const auto seedIndex = cand.label();
424  LogTrace("MkFitOutputConverter") << " from seed " << seedIndex << " seed hits";
425 
426  // Rescale candidate error if candidate is already propagated to first layer,
427  // to be consistent with TransientInitialStateEstimator::innerState used in CkfTrackCandidateMakerBase
428  // Error is only rescaled for candidates propagated to first layer;
429  // otherwise, candidates undergo backwardFit where error is already rescaled
430  if (mkFitOutput.propagatedToFirstLayer() && doErrorRescale_)
431  fts.rescaleError(100.);
432  auto tsosDet =
433  mkFitOutput.propagatedToFirstLayer()
435  : backwardFit(fts, recHits, propagatorAlong, propagatorOpposite, hitCloner, lastHitInvalid, lastHitChanged);
436  if (!tsosDet.first.isValid()) {
437  edm::LogInfo("MkFitOutputConverter")
438  << "Backward fit of candidate " << candIndex << " failed, ignoring the candidate";
439  continue;
440  }
441 
442  // convert to persistent, from CkfTrackCandidateMakerBase
443  auto pstate = trajectoryStateTransform::persistentState(tsosDet.first, tsosDet.second->geographicalId().rawId());
444 
445  output.emplace_back(
446  recHits,
447  seeds.at(seedIndex),
448  pstate,
449  seeds.refAt(seedIndex),
450  0, // mkFit does not produce loopers, so set nLoops=0
451  static_cast<uint8_t>(StopReason::UNINITIALIZED) // TODO: ignore details of stopping reason as well for now
452  );
453 
454  chi2.push_back(cand.chi2());
455  states.push_back(tsosDet.first);
456  }
457 
458  if (algoCandSelection_) {
459  const auto& dnnScores = computeDNNs(
460  output, states, bs, vertices, session, chi2, mkFitOutput.propagatedToFirstLayer() && doErrorRescale_);
461 
462  TrackCandidateCollection reducedOutput;
463  reducedOutput.reserve(output.size());
464  int scoreIndex = 0;
465  for (const auto& score : dnnScores) {
467  reducedOutput.push_back(output[scoreIndex]);
468  scoreIndex++;
469  }
470 
471  output.swap(reducedOutput);
472  }
473 
474  return output;
475 }
476 
477 std::pair<TrajectoryStateOnSurface, const GeomDet*> MkFitOutputConverter::backwardFit(
478  const FreeTrajectoryState& fts,
482  const TkClonerImpl& hitCloner,
483  bool lastHitWasInvalid,
484  bool lastHitWasChanged) const {
485  // First filter valid hits as in TransientInitialStateEstimator
487 
488  for (int i = hits.size() - 1; i >= 0; --i) {
489  if (hits[i].det()) {
490  // TransientTrackingRecHit::ConstRecHitContainer has shared_ptr,
491  // and it is passed to backFitter below so it is really needed
492  // to keep the interface. Since we keep the ownership in hits,
493  // let's disable the deleter.
494  firstHits.emplace_back(&(hits[i]), edm::do_nothing_deleter{});
495  }
496  }
497 
498  // Then propagate along to the surface of the last hit to get a TSOS
499  const auto& lastHitSurface = firstHits.front()->det()->surface();
500 
501  const Propagator* tryFirst = &propagatorAlong;
502  const Propagator* trySecond = &propagatorOpposite;
503  if (lastHitWasInvalid || lastHitWasChanged) {
504  LogTrace("MkFitOutputConverter") << "Propagating first opposite, then along, because lastHitWasInvalid? "
505  << lastHitWasInvalid << " or lastHitWasChanged? " << lastHitWasChanged;
506  std::swap(tryFirst, trySecond);
507  } else {
508  const auto lastHitSubdet = firstHits.front()->geographicalId().subdetId();
509  const auto& surfacePos = lastHitSurface.position();
510  const auto& lastHitPos = firstHits.front()->globalPosition();
511  bool doSwitch = false;
512  if (isBarrel(lastHitSubdet)) {
513  doSwitch = (surfacePos.perp2() < lastHitPos.perp2());
514  } else {
515  doSwitch = (surfacePos.z() < lastHitPos.z());
516  }
517  if (doSwitch) {
518  LogTrace("MkFitOutputConverter")
519  << "Propagating first opposite, then along, because surface is inner than the hit; surface perp2 "
520  << surfacePos.perp() << " hit " << lastHitPos.perp2() << " surface z " << surfacePos.z() << " hit "
521  << lastHitPos.z();
522 
523  std::swap(tryFirst, trySecond);
524  }
525  }
526 
527  auto tsosDouble = tryFirst->propagateWithPath(fts, lastHitSurface);
528  if (!tsosDouble.first.isValid()) {
529  LogDebug("MkFitOutputConverter") << "Propagating to startingState failed, trying in another direction next";
530  tsosDouble = trySecond->propagateWithPath(fts, lastHitSurface);
531  }
532  auto& startingState = tsosDouble.first;
533 
534  if (!startingState.isValid()) {
535  edm::LogWarning("MkFitOutputConverter")
536  << "startingState is not valid, FTS was\n"
537  << fts << " last hit surface surface:"
538  << "\n position " << lastHitSurface.position() << "\n phiSpan " << lastHitSurface.phiSpan().first << ","
539  << lastHitSurface.phiSpan().first << "\n rSpan " << lastHitSurface.rSpan().first << ","
540  << lastHitSurface.rSpan().first << "\n zSpan " << lastHitSurface.zSpan().first << ","
541  << lastHitSurface.zSpan().first;
542  return std::pair<TrajectoryStateOnSurface, const GeomDet*>();
543  }
544 
545  // Then return back to the logic from TransientInitialStateEstimator
546  startingState.rescaleError(100.);
547 
548  // avoid cloning
549  KFUpdator const aKFUpdator;
550  Chi2MeasurementEstimator const aChi2MeasurementEstimator(100., 3);
551  KFTrajectoryFitter backFitter(
552  &propagatorAlong, &aKFUpdator, &aChi2MeasurementEstimator, firstHits.size(), nullptr, &hitCloner);
553 
554  // assume for now that the propagation in mkfit always alongMomentum
555  PropagationDirection backFitDirection = oppositeToMomentum;
556 
557  // only direction matters in this context
559 
560  // ignore loopers for now
561  Trajectory fitres = backFitter.fitOne(fakeSeed, firstHits, startingState, TrajectoryFitter::standard);
562 
563  LogDebug("MkFitOutputConverter") << "using a backward fit of :" << firstHits.size() << " hits, starting from:\n"
564  << startingState << " to get the estimate of the initial state of the track.";
565 
566  if (!fitres.isValid()) {
567  edm::LogWarning("MkFitOutputConverter") << "FitTester: first hits fit failed";
568  return std::pair<TrajectoryStateOnSurface, const GeomDet*>();
569  }
570 
571  TrajectoryMeasurement const& firstMeas = fitres.lastMeasurement();
572 
573  // magnetic field can be different!
574  TrajectoryStateOnSurface firstState(firstMeas.updatedState().localParameters(),
575  firstMeas.updatedState().localError(),
576  firstMeas.updatedState().surface(),
577  propagatorAlong.magneticField());
578 
579  firstState.rescaleError(100.);
580 
581  LogDebug("MkFitOutputConverter") << "the initial state is found to be:\n:" << firstState
582  << "\n it's field pointer is: " << firstState.magneticField()
583  << "\n the pointer from the state of the back fit was: "
584  << firstMeas.updatedState().magneticField();
585 
586  return std::make_pair(firstState, firstMeas.recHit()->det());
587 }
588 
589 std::pair<TrajectoryStateOnSurface, const GeomDet*> MkFitOutputConverter::convertInnermostState(
590  const FreeTrajectoryState& fts,
593  const Propagator& propagatorOpposite) const {
594  auto det = hits[0].det();
595  if (det == nullptr) {
596  throw cms::Exception("LogicError") << "Got nullptr from the first hit det()";
597  }
598 
599  const auto& firstHitSurface = det->surface();
600 
601  auto tsosDouble = propagatorAlong.propagateWithPath(fts, firstHitSurface);
602  if (!tsosDouble.first.isValid()) {
603  LogDebug("MkFitOutputConverter") << "Propagating to startingState along momentum failed, trying opposite next";
604  tsosDouble = propagatorOpposite.propagateWithPath(fts, firstHitSurface);
605  }
606 
607  return std::make_pair(tsosDouble.first, det);
608 }
609 
611  const std::vector<TrajectoryStateOnSurface>& states,
612  const reco::BeamSpot* bs,
614  const tensorflow::Session* session,
615  const std::vector<float>& chi2,
616  const bool rescaledError) const {
617  int size_in = (int)tkCC.size();
618  int nbatches = size_in / bsize_;
619 
620  std::vector<float> output(size_in, 0);
621 
622  TSCBLBuilderNoMaterial tscblBuilder;
623 
624  tensorflow::Tensor input1(tensorflow::DT_FLOAT, {bsize_, 29});
625  tensorflow::Tensor input2(tensorflow::DT_FLOAT, {bsize_, 1});
626 
627  for (auto nb = 0; nb < nbatches + 1; nb++) {
628  std::vector<bool> invalidProp(bsize_, false);
629 
630  for (auto nt = 0; nt < bsize_; nt++) {
631  int itrack = nt + bsize_ * nb;
632  if (itrack >= size_in)
633  continue;
634 
635  auto const& tkC = tkCC.at(itrack);
636 
637  TrajectoryStateOnSurface state = states.at(itrack);
638 
639  if (rescaledError)
640  state.rescaleError(1 / 100.f);
641 
642  TrajectoryStateClosestToBeamLine tsAtClosestApproachTrackCand =
643  tscblBuilder(*state.freeState(), *bs); //as in TrackProducerAlgorithm
644 
645  if (!(tsAtClosestApproachTrackCand.isValid())) {
646  edm::LogVerbatim("TrackBuilding") << "TrajectoryStateClosestToBeamLine not valid";
647  invalidProp[nt] = true;
648  continue;
649  }
650 
651  auto const& stateAtPCA = tsAtClosestApproachTrackCand.trackStateAtPCA();
652  auto v0 = stateAtPCA.position();
653  auto p = stateAtPCA.momentum();
654  math::XYZPoint pos(v0.x(), v0.y(), v0.z());
655  math::XYZVector mom(p.x(), p.y(), p.z());
656 
657  //pseudo track for access to easy methods
658  reco::Track trk(0, 0, pos, mom, stateAtPCA.charge(), stateAtPCA.curvilinearError());
659 
660  // get best vertex
661  float dzmin = std::numeric_limits<float>::max();
662  float dxy_zmin = 0;
663 
664  for (auto const& vertex : *vertices) {
665  if (std::abs(trk.dz(vertex.position())) < dzmin) {
666  dzmin = trk.dz(vertex.position());
667  dxy_zmin = trk.dxy(vertex.position());
668  }
669  }
670 
671  // loop over the RecHits
672  int ndof = 0;
673  int pix = 0;
674  int strip = 0;
675  for (auto const& recHit : tkC.recHits()) {
676  ndof += recHit.dimension();
677  auto const subdet = recHit.geographicalId().subdetId();
679  pix++;
680  else
681  strip++;
682  }
683  ndof = ndof - 5;
684 
685  input1.matrix<float>()(nt, 0) = trk.pt(); //using inner track only
686  input1.matrix<float>()(nt, 1) = p.x();
687  input1.matrix<float>()(nt, 2) = p.y();
688  input1.matrix<float>()(nt, 3) = p.z();
689  input1.matrix<float>()(nt, 4) = p.perp();
690  input1.matrix<float>()(nt, 5) = p.x();
691  input1.matrix<float>()(nt, 6) = p.y();
692  input1.matrix<float>()(nt, 7) = p.z();
693  input1.matrix<float>()(nt, 8) = p.perp();
694  input1.matrix<float>()(nt, 9) = trk.ptError();
695  input1.matrix<float>()(nt, 10) = dxy_zmin;
696  input1.matrix<float>()(nt, 11) = dzmin;
697  input1.matrix<float>()(nt, 12) = trk.dxy(bs->position());
698  input1.matrix<float>()(nt, 13) = trk.dz(bs->position());
699  input1.matrix<float>()(nt, 14) = trk.dxyError();
700  input1.matrix<float>()(nt, 15) = trk.dzError();
701  input1.matrix<float>()(nt, 16) = ndof > 0 ? chi2[itrack] / ndof : chi2[itrack] * 1e6;
702  input1.matrix<float>()(nt, 17) = trk.eta();
703  input1.matrix<float>()(nt, 18) = trk.phi();
704  input1.matrix<float>()(nt, 19) = trk.etaError();
705  input1.matrix<float>()(nt, 20) = trk.phiError();
706  input1.matrix<float>()(nt, 21) = pix;
707  input1.matrix<float>()(nt, 22) = strip;
708  input1.matrix<float>()(nt, 23) = ndof;
709  input1.matrix<float>()(nt, 24) = 0;
710  input1.matrix<float>()(nt, 25) = 0;
711  input1.matrix<float>()(nt, 26) = 0;
712  input1.matrix<float>()(nt, 27) = 0;
713  input1.matrix<float>()(nt, 28) = 0;
714 
715  input2.matrix<float>()(nt, 0) = algo_;
716  }
717 
718  //inputs finalized
720  inputs.resize(2);
723 
724  //eval and rescale
725  std::vector<tensorflow::Tensor> outputs;
726  tensorflow::run(session, inputs, {"Identity"}, &outputs);
727 
728  for (auto nt = 0; nt < bsize_; nt++) {
729  int itrack = nt + bsize_ * nb;
730  if (itrack >= size_in)
731  continue;
732 
733  float out0 = 2.0 * outputs[0].matrix<float>()(nt, 0) - 1.0;
734  if (invalidProp[nt])
735  out0 = -1;
736 
737  output[itrack] = out0;
738  }
739  }
740 
741  return output;
742 }
743 
bool isPhase1() const
Log< level::Info, true > LogVerbatim
static constexpr auto TEC
const edm::EDGetTokenT< MkFitClusterIndexToHit > pixelClusterIndexToHitToken_
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
std::vector< NamedTensor > NamedTensorList
Definition: TensorFlow.h:31
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
bool isValid() const
Definition: Trajectory.h:257
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
const edm::ESGetToken< MkFitGeometry, TrackerRecoGeometryRecord > mkFitGeomToken_
const edm::ESGetToken< Propagator, TrackingComponentsRecord > propagatorOppositeToken_
const LocalTrajectoryError & localError() const
std::pair< TrajectoryStateOnSurface, const GeomDet * > backwardFit(const FreeTrajectoryState &fts, const edm::OwnVector< TrackingRecHit > &hits, const Propagator &propagatorAlong, const Propagator &propagatorOpposite, const TkClonerImpl &hitCloner, bool lastHitWasInvalid, bool lastHitWasChanged) const
std::vector< TrackCandidate > TrackCandidateCollection
bool propagatedToFirstLayer() const
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
PTrajectoryStateOnDet persistentState(const TrajectoryStateOnSurface &ts, unsigned int detid)
GeometricSearchDet Det
Definition: DetBelowR.h:8
const edm::EDGetTokenT< reco::BeamSpot > bsToken_
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
void produce(edm::StreamID, edm::Event &iEvent, const edm::EventSetup &iSetup) const override
const LocalTrajectoryParameters & localParameters() const
std::string const & label() const
Definition: InputTag.h:36
PropagationDirection
const edm::EDGetTokenT< MkFitOutputWrapper > tracksToken_
const SurfaceType & surface() const
const edm::EDGetTokenT< reco::VertexCollection > verticesToken_
const std::string tfDnnLabel_
#define input2
Definition: AMPTWrapper.h:159
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:112
TrajectoryMeasurement const & lastMeasurement() const
Definition: Trajectory.h:150
#define LogTrace(id)
GlobalPoint position() const
std::pair< std::string, Tensor > NamedTensor
Definition: TensorFlow.h:30
const edm::EDPutTokenT< std::vector< SeedStopInfo > > putSeedStopInfoToken_
int iEvent
Definition: GenABIO.cc:224
mkfit::TrackVec const & tracks() const
TrackCandidateCollection convertCandidates(const MkFitOutputWrapper &mkFitOutput, const mkfit::EventOfHits &eventOfHits, const MkFitClusterIndexToHit &pixelClusterIndexToHit, const MkFitClusterIndexToHit &stripClusterIndexToHit, const edm::View< TrajectorySeed > &seeds, const MagneticField &mf, const Propagator &propagatorAlong, const Propagator &propagatorOpposite, const MkFitGeometry &mkFitGeom, const TkClonerImpl &hitCloner, const std::vector< const DetLayer *> &detLayers, const mkfit::TrackVec &mkFitSeeds, const reco::BeamSpot *bs, const reco::VertexCollection *vertices, const tensorflow::Session *session) const
const edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > mfToken_
~MkFitOutputConverter() override=default
MkFitOutputConverter(edm::ParameterSet const &iConfig)
void run(Session *session, const NamedTensorList &inputs, const std::vector< std::string > &outputNames, std::vector< Tensor > *outputs, const thread::ThreadPoolOptions &threadPoolOptions)
Definition: TensorFlow.cc:271
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const edm::EDGetTokenT< edm::View< TrajectorySeed > > seedToken_
const edm::EDPutTokenT< TrackCandidateCollection > putTrackCandidateToken_
double f[11][100]
#define input1
Definition: AMPTWrapper.h:139
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
ROOT::Math::SMatrix< double, 4, 4, ROOT::Math::MatRepSym< double, 4 > > AlgebraicSymMatrix44
static constexpr auto TOB
virtual std::pair< TrajectoryStateOnSurface, double > propagateWithPath(const FreeTrajectoryState &, const Surface &) const final
Definition: Propagator.cc:10
bool isEndcap(GeomDetEnumerators::SubDetector m)
const edm::EDGetTokenT< MkFitSeedWrapper > mkfitSeedToken_
int nt
Definition: AMPTWrapper.h:42
#define M_PI
std::vector< ConstRecHitPointer > ConstRecHitContainer
Log< level::Info, false > LogInfo
std::vector< Track > TrackVec
static constexpr auto TIB
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
ROOT::Math::SMatrix< double, 5, 5, ROOT::Math::MatRepSym< double, 5 > > AlgebraicSymMatrix55
double b
Definition: hdecay.h:120
ROOT::Math::SMatrix< double, 2, 2, ROOT::Math::MatRepSym< double, 2 > > AlgebraicSymMatrix22
TrajectoryStateOnSurface const & updatedState() const
std::vector< float > computeDNNs(TrackCandidateCollection const &tkCC, const std::vector< TrajectoryStateOnSurface > &states, const reco::BeamSpot *bs, const reco::VertexCollection *vertices, const tensorflow::Session *session, const std::vector< float > &chi2, const bool rescaledError) const
const edm::EDGetTokenT< MkFitEventOfHits > eventOfHitsToken_
double a
Definition: hdecay.h:121
bool isPixel(HitType hitType)
static TrackAlgorithm algoByName(const std::string &name)
Definition: TrackBase.cc:137
ROOT::Math::SMatrix< double, 3, 3, ROOT::Math::MatRepSym< double, 3 > > AlgebraicSymMatrix33
Definition: output.py:1
const edm::ESGetToken< Propagator, TrackingComponentsRecord > propagatorAlongToken_
const MagneticField * magneticField() const
std::vector< TrackingRecHit const * > & hits()
Log< level::Warning, false > LogWarning
const edm::ESGetToken< TfGraphDefWrapper, TfGraphRecord > tfDnnToken_
long double T
static constexpr auto TID
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
std::pair< TrajectoryStateOnSurface, const GeomDet * > convertInnermostState(const FreeTrajectoryState &fts, const edm::OwnVector< TrackingRecHit > &hits, const Propagator &propagatorAlong, const Propagator &propagatorOpposite) const
ConstRecHitPointer const & recHit() const
Global3DVector GlobalVector
Definition: GlobalVector.h:10
const edm::ESGetToken< TransientTrackingRecHitBuilder, TransientRecHitRecord > ttrhBuilderToken_
#define LogDebug(id)
const edm::EDGetTokenT< MkFitClusterIndexToHit > stripClusterIndexToHitToken_