CMS 3D CMS Logo

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