CMS 3D CMS Logo

TrackExtenderWithMTD.cc
Go to the documentation of this file.
8 
11 
14 
16 
18 
21 
26 
29 
33 
35 
38 
41 
43 
46 
47 #include <sstream>
48 
50 
53 
56 #include "CLHEP/Units/GlobalPhysicalConstants.h"
58 
61 
62 using namespace std;
63 using namespace edm;
64 using namespace reco;
65 
66 namespace {
67  constexpr float c_cm_ns = geant_units::operators::convertMmToCm(CLHEP::c_light); // [mm/ns] -> [cm/ns]
68  constexpr float c_inv = 1.0f / c_cm_ns;
69 
70  class MTDHitMatchingInfo {
71  public:
72  MTDHitMatchingInfo() {
73  hit = nullptr;
76  }
77 
78  //Operator used to sort the hits while performing the matching step at the MTD
79  inline bool operator<(const MTDHitMatchingInfo& m2) const {
80  //only for good matching in time use estChi2, otherwise use mostly time compatibility
81  constexpr float chi2_cut = 10.f;
82  constexpr float low_weight = 3.f;
83  constexpr float high_weight = 8.f;
84  if (timeChi2 < chi2_cut && m2.timeChi2 < chi2_cut)
85  return chi2(low_weight) < m2.chi2(low_weight);
86  else
87  return chi2(high_weight) < m2.chi2(high_weight);
88  }
89 
90  inline float chi2(float timeWeight = 1.f) const { return estChi2 + timeWeight * timeChi2; }
91 
92  const MTDTrackingRecHit* hit;
93  float estChi2;
94  float timeChi2;
95  };
96 
97  class TrackSegments {
98  public:
99  TrackSegments() = default;
100 
101  inline uint32_t addSegment(float tPath, float tMom2) {
102  segmentPathOvc_.emplace_back(tPath * c_inv);
103  segmentMom2_.emplace_back(tMom2);
104  nSegment_++;
105 
106  LogTrace("TrackExtenderWithMTD") << "addSegment # " << nSegment_ << " s = " << tPath
107  << " p = " << std::sqrt(tMom2);
108 
109  return nSegment_;
110  }
111 
112  inline float computeTof(float mass_inv2) const {
113  float tof(0.f);
114  for (uint32_t iSeg = 0; iSeg < nSegment_; iSeg++) {
115  float gammasq = 1.f + segmentMom2_[iSeg] * mass_inv2;
116  float beta = std::sqrt(1.f - 1.f / gammasq);
117  tof += segmentPathOvc_[iSeg] / beta;
118 
119  LogTrace("TrackExtenderWithMTD") << " TOF Segment # " << iSeg + 1 << " p = " << std::sqrt(segmentMom2_[iSeg])
120  << " tof = " << tof;
121  }
122 
123  return tof;
124  }
125 
126  inline uint32_t size() const { return nSegment_; }
127 
128  inline uint32_t removeFirstSegment() {
129  if (nSegment_ > 0) {
130  segmentPathOvc_.erase(segmentPathOvc_.begin());
131  segmentMom2_.erase(segmentMom2_.begin());
132  nSegment_--;
133  }
134  return nSegment_;
135  }
136 
137  inline std::pair<float, float> getSegmentPathAndMom2(uint32_t iSegment) const {
138  if (iSegment >= nSegment_) {
139  throw cms::Exception("TrackExtenderWithMTD") << "Requesting non existing track segment #" << iSegment;
140  }
141  return std::make_pair(segmentPathOvc_[iSegment], segmentMom2_[iSegment]);
142  }
143 
144  uint32_t nSegment_ = 0;
145  std::vector<float> segmentPathOvc_;
146  std::vector<float> segmentMom2_;
147  };
148 
149  struct TrackTofPidInfo {
150  float tmtd;
151  float tmtderror;
152  float pathlength;
153 
154  float betaerror;
155 
156  float dt;
157  float dterror;
158  float dtchi2;
159 
160  float dt_best;
161  float dterror_best;
162  float dtchi2_best;
163 
164  float gammasq_pi;
165  float beta_pi;
166  float dt_pi;
167 
168  float gammasq_k;
169  float beta_k;
170  float dt_k;
171 
172  float gammasq_p;
173  float beta_p;
174  float dt_p;
175 
176  float prob_pi;
177  float prob_k;
178  float prob_p;
179  };
180 
181  enum class TofCalc { kCost = 1, kSegm = 2, kMixd = 3 };
182 
183  const TrackTofPidInfo computeTrackTofPidInfo(float magp2,
184  float length,
185  TrackSegments trs,
186  float t_mtd,
187  float t_mtderr,
188  float t_vtx,
189  float t_vtx_err,
190  bool addPIDError = true,
191  TofCalc choice = TofCalc::kCost) {
192  constexpr float m_pi = 0.13957018f;
193  constexpr float m_pi_inv2 = 1.0f / m_pi / m_pi;
194  constexpr float m_k = 0.493677f;
195  constexpr float m_k_inv2 = 1.0f / m_k / m_k;
196  constexpr float m_p = 0.9382720813f;
197  constexpr float m_p_inv2 = 1.0f / m_p / m_p;
198 
199  TrackTofPidInfo tofpid;
200 
201  tofpid.tmtd = t_mtd;
202  tofpid.tmtderror = t_mtderr;
203  tofpid.pathlength = length;
204 
205  auto deltat = [&](const float mass_inv2, const float betatmp) {
206  float res(1.f);
207  switch (choice) {
208  case TofCalc::kCost:
209  res = tofpid.pathlength / betatmp * c_inv;
210  break;
211  case TofCalc::kSegm:
212  res = trs.computeTof(mass_inv2);
213  break;
214  case TofCalc::kMixd:
215  res = trs.computeTof(mass_inv2) + tofpid.pathlength / betatmp * c_inv;
216  break;
217  }
218  return res;
219  };
220 
221  tofpid.gammasq_pi = 1.f + magp2 * m_pi_inv2;
222  tofpid.beta_pi = std::sqrt(1.f - 1.f / tofpid.gammasq_pi);
223  tofpid.dt_pi = deltat(m_pi_inv2, tofpid.beta_pi);
224 
225  tofpid.gammasq_k = 1.f + magp2 * m_k_inv2;
226  tofpid.beta_k = std::sqrt(1.f - 1.f / tofpid.gammasq_k);
227  tofpid.dt_k = deltat(m_k_inv2, tofpid.beta_k);
228 
229  tofpid.gammasq_p = 1.f + magp2 * m_p_inv2;
230  tofpid.beta_p = std::sqrt(1.f - 1.f / tofpid.gammasq_p);
231  tofpid.dt_p = deltat(m_p_inv2, tofpid.beta_p);
232 
233  tofpid.dt = tofpid.tmtd - tofpid.dt_pi - t_vtx; //assume by default the pi hypothesis
234  tofpid.dterror = sqrt(tofpid.tmtderror * tofpid.tmtderror + t_vtx_err * t_vtx_err);
235  tofpid.betaerror = 0.f;
236  if (addPIDError) {
237  tofpid.dterror =
238  sqrt(tofpid.dterror * tofpid.dterror + (tofpid.dt_p - tofpid.dt_pi) * (tofpid.dt_p - tofpid.dt_pi));
239  tofpid.betaerror = tofpid.beta_p - tofpid.beta_pi;
240  }
241 
242  tofpid.dtchi2 = (tofpid.dt * tofpid.dt) / (tofpid.dterror * tofpid.dterror);
243 
244  tofpid.dt_best = tofpid.dt;
245  tofpid.dterror_best = tofpid.dterror;
246  tofpid.dtchi2_best = tofpid.dtchi2;
247 
248  tofpid.prob_pi = -1.f;
249  tofpid.prob_k = -1.f;
250  tofpid.prob_p = -1.f;
251 
252  if (!addPIDError) {
253  //*TODO* deal with heavier nucleons and/or BSM case here?
254  float chi2_pi = tofpid.dtchi2;
255  float chi2_k =
256  (tofpid.tmtd - tofpid.dt_k - t_vtx) * (tofpid.tmtd - tofpid.dt_k - t_vtx) / (tofpid.dterror * tofpid.dterror);
257  float chi2_p =
258  (tofpid.tmtd - tofpid.dt_p - t_vtx) * (tofpid.tmtd - tofpid.dt_p - t_vtx) / (tofpid.dterror * tofpid.dterror);
259 
260  float rawprob_pi = exp(-0.5f * chi2_pi);
261  float rawprob_k = exp(-0.5f * chi2_k);
262  float rawprob_p = exp(-0.5f * chi2_p);
263  float normprob = 1.f / (rawprob_pi + rawprob_k + rawprob_p);
264 
265  tofpid.prob_pi = rawprob_pi * normprob;
266  tofpid.prob_k = rawprob_k * normprob;
267  tofpid.prob_p = rawprob_p * normprob;
268 
269  float prob_heavy = 1.f - tofpid.prob_pi;
270  constexpr float heavy_threshold = 0.75f;
271 
272  if (prob_heavy > heavy_threshold) {
273  if (chi2_k < chi2_p) {
274  tofpid.dt_best = (tofpid.tmtd - tofpid.dt_k - t_vtx);
275  tofpid.dtchi2_best = chi2_k;
276  } else {
277  tofpid.dt_best = (tofpid.tmtd - tofpid.dt_p - t_vtx);
278  tofpid.dtchi2_best = chi2_p;
279  }
280  }
281  }
282  return tofpid;
283  }
284 
285  bool getTrajectoryStateClosestToBeamLine(const Trajectory& traj,
286  const reco::BeamSpot& bs,
287  const Propagator* thePropagator,
289  // get the state closest to the beamline
290  TrajectoryStateOnSurface stateForProjectionToBeamLineOnSurface =
291  traj.closestMeasurement(GlobalPoint(bs.x0(), bs.y0(), bs.z0())).updatedState();
292 
293  if (!stateForProjectionToBeamLineOnSurface.isValid()) {
294  edm::LogError("CannotPropagateToBeamLine") << "the state on the closest measurement isnot valid. skipping track.";
295  return false;
296  }
297 
298  const FreeTrajectoryState& stateForProjectionToBeamLine = *stateForProjectionToBeamLineOnSurface.freeState();
299 
300  TSCBLBuilderWithPropagator tscblBuilder(*thePropagator);
301  tscbl = tscblBuilder(stateForProjectionToBeamLine, bs);
302 
303  return tscbl.isValid();
304  }
305 
306  bool trackPathLength(const Trajectory& traj,
308  const Propagator* thePropagator,
309  float& pathlength,
310  TrackSegments& trs) {
311  pathlength = 0.f;
312 
313  bool validpropagation = true;
314  float oldp = traj.measurements().begin()->updatedState().globalMomentum().mag();
315  float pathlength1 = 0.f;
316  float pathlength2 = 0.f;
317 
318  //add pathlength layer by layer
319  for (auto it = traj.measurements().begin(); it != traj.measurements().end() - 1; ++it) {
320  const auto& propresult = thePropagator->propagateWithPath(it->updatedState(), (it + 1)->updatedState().surface());
321  float layerpathlength = std::abs(propresult.second);
322  if (layerpathlength == 0.f) {
323  validpropagation = false;
324  }
325  pathlength1 += layerpathlength;
326  trs.addSegment(layerpathlength, (it + 1)->updatedState().globalMomentum().mag2());
327  LogTrace("TrackExtenderWithMTD") << "TSOS " << std::fixed << std::setw(4) << trs.size() << " R_i " << std::fixed
328  << std::setw(14) << it->updatedState().globalPosition().perp() << " z_i "
329  << std::fixed << std::setw(14) << it->updatedState().globalPosition().z()
330  << " R_e " << std::fixed << std::setw(14)
331  << (it + 1)->updatedState().globalPosition().perp() << " z_e " << std::fixed
332  << std::setw(14) << (it + 1)->updatedState().globalPosition().z() << " p "
333  << std::fixed << std::setw(14) << (it + 1)->updatedState().globalMomentum().mag()
334  << " dp " << std::fixed << std::setw(14)
335  << (it + 1)->updatedState().globalMomentum().mag() - oldp;
336  oldp = (it + 1)->updatedState().globalMomentum().mag();
337  }
338 
339  //add distance from bs to first measurement
340  auto const& tscblPCA = tscbl.trackStateAtPCA();
341  auto const& aSurface = traj.direction() == alongMomentum ? traj.firstMeasurement().updatedState().surface()
342  : traj.lastMeasurement().updatedState().surface();
343  pathlength2 = thePropagator->propagateWithPath(tscblPCA, aSurface).second;
344  if (pathlength2 == 0.f) {
345  validpropagation = false;
346  }
347  pathlength = pathlength1 + pathlength2;
348  trs.addSegment(pathlength2, tscblPCA.momentum().mag2());
349  LogTrace("TrackExtenderWithMTD") << "TSOS " << std::fixed << std::setw(4) << trs.size() << " R_e " << std::fixed
350  << std::setw(14) << tscblPCA.position().perp() << " z_e " << std::fixed
351  << std::setw(14) << tscblPCA.position().z() << " p " << std::fixed << std::setw(14)
352  << tscblPCA.momentum().mag() << " dp " << std::fixed << std::setw(14)
353  << tscblPCA.momentum().mag() - oldp;
354  return validpropagation;
355  }
356 
357  bool trackPathLength(const Trajectory& traj,
358  const reco::BeamSpot& bs,
359  const Propagator* thePropagator,
360  float& pathlength,
361  TrackSegments& trs) {
362  pathlength = 0.f;
363 
365  bool tscbl_status = getTrajectoryStateClosestToBeamLine(traj, bs, thePropagator, tscbl);
366 
367  if (!tscbl_status)
368  return false;
369 
370  return trackPathLength(traj, tscbl, thePropagator, pathlength, trs);
371  }
372 
373 } // namespace
374 
375 template <class TrackCollection>
377 public:
380 
382 
383  template <class H, class T>
384  void fillValueMap(edm::Event& iEvent, const H& handle, const std::vector<T>& vec, const edm::EDPutToken& token) const;
385 
386  void produce(edm::Event& ev, const edm::EventSetup& es) final;
387 
388  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
389 
391  const Trajectory& traj,
392  const float,
393  const float,
394  const TrackSegments&,
396  const MTDDetLayerGeometry*,
397  const MagneticField* field,
398  const Propagator* prop,
399  const reco::BeamSpot& bs,
400  const float vtxTime,
401  const bool matchVertex,
402  MTDHitMatchingInfo& bestHit) const;
403 
405  const Trajectory& traj,
406  const float,
407  const float,
408  const TrackSegments&,
410  const MTDDetLayerGeometry*,
411  const MagneticField* field,
412  const Propagator* prop,
413  const reco::BeamSpot& bs,
414  const float vtxTime,
415  const bool matchVertex,
416  MTDHitMatchingInfo& bestHit) const;
417 
418  void fillMatchingHits(const DetLayer*,
420  const Trajectory&,
421  const float,
422  const float,
423  const TrackSegments&,
425  const Propagator*,
426  const reco::BeamSpot&,
427  const float&,
428  const bool,
430  MTDHitMatchingInfo&) const;
431 
434  if (!recHits.empty()) {
435  GlobalPoint first = gtg_->idToDet(recHits.front()->geographicalId())->position();
436  GlobalPoint last = gtg_->idToDet(recHits.back()->geographicalId())->position();
437 
438  // maybe perp2?
439  auto rFirst = first.mag2();
440  auto rLast = last.mag2();
441  if (rFirst < rLast)
443  if (rFirst > rLast)
445  }
446  LogDebug("TrackExtenderWithMTD") << "Impossible to determine the rechits order" << endl;
448  }
449 
450  reco::Track buildTrack(const reco::TrackRef&,
451  const Trajectory&,
452  const Trajectory&,
453  const reco::BeamSpot&,
454  const MagneticField* field,
455  const Propagator* prop,
456  bool hasMTD,
457  float& pathLength,
458  float& tmtdOut,
459  float& sigmatmtdOut,
460  float& tofpi,
461  float& tofk,
462  float& tofp) const;
463  reco::TrackExtra buildTrackExtra(const Trajectory& trajectory) const;
464 
465  string dumpLayer(const DetLayer* layer) const;
466 
467 private:
485 
493 
494  const bool updateTraj_, updateExtra_, updatePattern_;
495  const std::string mtdRecHitBuilder_, propagator_, transientTrackBuilder_;
496  std::unique_ptr<MeasurementEstimator> theEstimator;
497  std::unique_ptr<TrackTransformer> theTransformer;
504 
509 
510  const float estMaxChi2_;
511  const float estMaxNSigma_;
512  const float btlChi2Cut_;
513  const float btlTimeChi2Cut_;
514  const float etlChi2Cut_;
515  const float etlTimeChi2Cut_;
516 
517  const bool useVertex_;
518  const bool useSimVertex_;
519  const float dzCut_;
520  const float bsTimeSpread_;
521 };
522 
523 template <class TrackCollection>
525  : tracksToken_(consumes<InputCollection>(iConfig.getParameter<edm::InputTag>("tracksSrc"))),
526  trajTrackAToken_(consumes<TrajTrackAssociationCollection>(iConfig.getParameter<edm::InputTag>("trjtrkAssSrc"))),
527  hitsToken_(consumes<MTDTrackingDetSetVector>(iConfig.getParameter<edm::InputTag>("hitsSrc"))),
528  bsToken_(consumes<reco::BeamSpot>(iConfig.getParameter<edm::InputTag>("beamSpotSrc"))),
529  updateTraj_(iConfig.getParameter<bool>("updateTrackTrajectory")),
530  updateExtra_(iConfig.getParameter<bool>("updateTrackExtra")),
531  updatePattern_(iConfig.getParameter<bool>("updateTrackHitPattern")),
532  mtdRecHitBuilder_(iConfig.getParameter<std::string>("MTDRecHitBuilder")),
533  propagator_(iConfig.getParameter<std::string>("Propagator")),
534  transientTrackBuilder_(iConfig.getParameter<std::string>("TransientTrackBuilder")),
535  estMaxChi2_(iConfig.getParameter<double>("estimatorMaxChi2")),
536  estMaxNSigma_(iConfig.getParameter<double>("estimatorMaxNSigma")),
537  btlChi2Cut_(iConfig.getParameter<double>("btlChi2Cut")),
538  btlTimeChi2Cut_(iConfig.getParameter<double>("btlTimeChi2Cut")),
539  etlChi2Cut_(iConfig.getParameter<double>("etlChi2Cut")),
540  etlTimeChi2Cut_(iConfig.getParameter<double>("etlTimeChi2Cut")),
541  useVertex_(iConfig.getParameter<bool>("useVertex")),
542  useSimVertex_(iConfig.getParameter<bool>("useSimVertex")),
543  dzCut_(iConfig.getParameter<double>("dZCut")),
544  bsTimeSpread_(iConfig.getParameter<double>("bsTimeSpread")) {
545  if (useVertex_) {
546  if (useSimVertex_) {
547  genVtxPositionToken_ = consumes<GlobalPoint>(iConfig.getParameter<edm::InputTag>("genVtxPositionSrc"));
548  genVtxTimeToken_ = consumes<float>(iConfig.getParameter<edm::InputTag>("genVtxTimeSrc"));
549  } else
550  vtxToken_ = consumes<VertexCollection>(iConfig.getParameter<edm::InputTag>("vtxSrc"));
551  }
552 
553  theEstimator = std::make_unique<Chi2MeasurementEstimator>(estMaxChi2_, estMaxNSigma_);
554  theTransformer = std::make_unique<TrackTransformer>(iConfig.getParameterSet("TrackTransformer"), consumesCollector());
555 
556  btlMatchChi2Token_ = produces<edm::ValueMap<float>>("btlMatchChi2");
557  etlMatchChi2Token_ = produces<edm::ValueMap<float>>("etlMatchChi2");
558  btlMatchTimeChi2Token_ = produces<edm::ValueMap<float>>("btlMatchTimeChi2");
559  etlMatchTimeChi2Token_ = produces<edm::ValueMap<float>>("etlMatchTimeChi2");
560  npixBarrelToken_ = produces<edm::ValueMap<int>>("npixBarrel");
561  npixEndcapToken_ = produces<edm::ValueMap<int>>("npixEndcap");
562  pOrigTrkToken_ = produces<edm::ValueMap<float>>("generalTrackp");
563  betaOrigTrkToken_ = produces<edm::ValueMap<float>>("generalTrackBeta");
564  t0OrigTrkToken_ = produces<edm::ValueMap<float>>("generalTrackt0");
565  sigmat0OrigTrkToken_ = produces<edm::ValueMap<float>>("generalTracksigmat0");
566  pathLengthOrigTrkToken_ = produces<edm::ValueMap<float>>("generalTrackPathLength");
567  tmtdOrigTrkToken_ = produces<edm::ValueMap<float>>("generalTracktmtd");
568  sigmatmtdOrigTrkToken_ = produces<edm::ValueMap<float>>("generalTracksigmatmtd");
569  tofpiOrigTrkToken_ = produces<edm::ValueMap<float>>("generalTrackTofPi");
570  tofkOrigTrkToken_ = produces<edm::ValueMap<float>>("generalTrackTofK");
571  tofpOrigTrkToken_ = produces<edm::ValueMap<float>>("generalTrackTofP");
572  assocOrigTrkToken_ = produces<edm::ValueMap<int>>("generalTrackassoc");
573 
574  builderToken_ = esConsumes<TransientTrackBuilder, TransientTrackRecord>(edm::ESInputTag("", transientTrackBuilder_));
576  esConsumes<TransientTrackingRecHitBuilder, TransientRecHitRecord>(edm::ESInputTag("", mtdRecHitBuilder_));
577  gtgToken_ = esConsumes<GlobalTrackingGeometry, GlobalTrackingGeometryRecord>();
578  dlgeoToken_ = esConsumes<MTDDetLayerGeometry, MTDRecoGeometryRecord>();
579  magfldToken_ = esConsumes<MagneticField, IdealMagneticFieldRecord>();
580  propToken_ = esConsumes<Propagator, TrackingComponentsRecord>(edm::ESInputTag("", propagator_));
581  ttopoToken_ = esConsumes<TrackerTopology, TrackerTopologyRcd>();
582 
583  produces<edm::OwnVector<TrackingRecHit>>();
584  produces<reco::TrackExtraCollection>();
585  produces<TrackCollection>();
586 }
587 
588 template <class TrackCollection>
591  desc.add<edm::InputTag>("tracksSrc", edm::InputTag("generalTracks"));
592  desc.add<edm::InputTag>("trjtrkAssSrc", edm::InputTag("generalTracks"));
593  desc.add<edm::InputTag>("hitsSrc", edm::InputTag("mtdTrackingRecHits"));
594  desc.add<edm::InputTag>("beamSpotSrc", edm::InputTag("offlineBeamSpot"));
595  desc.add<edm::InputTag>("genVtxPositionSrc", edm::InputTag("genParticles:xyz0"));
596  desc.add<edm::InputTag>("genVtxTimeSrc", edm::InputTag("genParticles:t0"));
597  desc.add<edm::InputTag>("vtxSrc", edm::InputTag("offlinePrimaryVertices4D"));
598  desc.add<bool>("updateTrackTrajectory", true);
599  desc.add<bool>("updateTrackExtra", true);
600  desc.add<bool>("updateTrackHitPattern", true);
601  desc.add<std::string>("TransientTrackBuilder", "TransientTrackBuilder");
602  desc.add<std::string>("MTDRecHitBuilder", "MTDRecHitBuilder");
603  desc.add<std::string>("Propagator", "PropagatorWithMaterialForMTD");
605  false,
606  "KFFitterForRefitInsideOut",
607  "KFSmootherForRefitInsideOut",
608  "PropagatorWithMaterialForMTD",
609  "alongMomentum",
610  true,
611  "WithTrackAngle",
612  "MuonRecHitBuilder",
613  "MTDRecHitBuilder");
614  desc.add<edm::ParameterSetDescription>("TrackTransformer", transDesc);
615  desc.add<double>("estimatorMaxChi2", 500.);
616  desc.add<double>("estimatorMaxNSigma", 10.);
617  desc.add<double>("btlChi2Cut", 50.);
618  desc.add<double>("btlTimeChi2Cut", 10.);
619  desc.add<double>("etlChi2Cut", 50.);
620  desc.add<double>("etlTimeChi2Cut", 10.);
621  desc.add<bool>("useVertex", false);
622  desc.add<bool>("useSimVertex", false);
623  desc.add<double>("dZCut", 0.1);
624  desc.add<double>("bsTimeSpread", 0.2);
625  descriptions.add("trackExtenderWithMTDBase", desc);
626 }
627 
628 template <class TrackCollection>
629 template <class H, class T>
631  const H& handle,
632  const std::vector<T>& vec,
633  const edm::EDPutToken& token) const {
634  auto out = std::make_unique<edm::ValueMap<T>>();
636  filler.insert(handle, vec.begin(), vec.end());
637  filler.fill();
638  iEvent.put(token, std::move(out));
639 }
640 
641 template <class TrackCollection>
643  //this produces pieces of the track extra
644  Traj2TrackHits t2t;
645 
646  theTransformer->setServices(es);
647 
648  TrackingRecHitRefProd hitsRefProd = ev.getRefBeforePut<TrackingRecHitCollection>();
649  reco::TrackExtraRefProd extrasRefProd = ev.getRefBeforePut<reco::TrackExtraCollection>();
650 
651  gtg_ = es.getHandle(gtgToken_);
652 
653  auto geo = es.getTransientHandle(dlgeoToken_);
654 
655  auto magfield = es.getTransientHandle(magfldToken_);
656 
657  builder_ = es.getHandle(builderToken_);
658  hitbuilder_ = es.getHandle(hitbuilderToken_);
659 
660  auto propH = es.getTransientHandle(propToken_);
661  const Propagator* prop = propH.product();
662 
663  auto httopo = es.getTransientHandle(ttopoToken_);
664  const TrackerTopology& ttopo = *httopo;
665 
666  auto output = std::make_unique<TrackCollection>();
667  auto extras = std::make_unique<reco::TrackExtraCollection>();
668  auto outhits = std::make_unique<edm::OwnVector<TrackingRecHit>>();
669 
670  std::vector<float> btlMatchChi2;
671  std::vector<float> etlMatchChi2;
672  std::vector<float> btlMatchTimeChi2;
673  std::vector<float> etlMatchTimeChi2;
674  std::vector<int> npixBarrel;
675  std::vector<int> npixEndcap;
676  std::vector<float> pOrigTrkRaw;
677  std::vector<float> betaOrigTrkRaw;
678  std::vector<float> t0OrigTrkRaw;
679  std::vector<float> sigmat0OrigTrkRaw;
680  std::vector<float> pathLengthsOrigTrkRaw;
681  std::vector<float> tmtdOrigTrkRaw;
682  std::vector<float> sigmatmtdOrigTrkRaw;
683  std::vector<float> tofpiOrigTrkRaw;
684  std::vector<float> tofkOrigTrkRaw;
685  std::vector<float> tofpOrigTrkRaw;
686  std::vector<int> assocOrigTrkRaw;
687 
688  auto const tracksH = ev.getHandle(tracksToken_);
689 
690  const auto& trjtrks = ev.get(trajTrackAToken_);
691 
692  //MTD hits DetSet
693  const auto& hits = ev.get(hitsToken_);
694 
695  //beam spot
696  const auto& bs = ev.get(bsToken_);
697 
698  const Vertex* pv = nullptr;
699  if (useVertex_ && !useSimVertex_) {
700  auto const& vtxs = ev.get(vtxToken_);
701  if (!vtxs.empty())
702  pv = &vtxs[0];
703  }
704 
705  std::unique_ptr<math::XYZTLorentzVectorF> genPV(nullptr);
706  if (useVertex_ && useSimVertex_) {
707  const auto& genVtxPosition = ev.get(genVtxPositionToken_);
708  const auto& genVtxTime = ev.get(genVtxTimeToken_);
709  genPV = std::make_unique<math::XYZTLorentzVectorF>(
710  genVtxPosition.x(), genVtxPosition.y(), genVtxPosition.z(), genVtxTime);
711  }
712 
713  float vtxTime = 0.f;
714  if (useVertex_) {
715  if (useSimVertex_ && genPV) {
716  vtxTime = genPV->t();
717  } else if (pv)
718  vtxTime = pv->t(); //already in ns
719  }
720 
721  std::vector<unsigned> track_indices;
722  unsigned itrack = 0;
723 
724  for (const auto& trjtrk : trjtrks) {
725  const Trajectory& trajs = *trjtrk.key;
726  const reco::TrackRef& track = trjtrk.val;
727 
728  LogTrace("TrackExtenderWithMTD") << "TrackExtenderWithMTD: extrapolating track " << itrack
729  << " p/pT = " << track->p() << " " << track->pt() << " eta = " << track->eta();
730 
731  float trackVtxTime = 0.f;
732  if (useVertex_) {
733  float dz;
734  if (useSimVertex_)
735  dz = std::abs(track->dz(math::XYZPoint(*genPV)));
736  else
737  dz = std::abs(track->dz(pv->position()));
738 
739  if (dz < dzCut_)
740  trackVtxTime = vtxTime;
741  }
742 
743  reco::TransientTrack ttrack(track, magfield.product(), gtg_);
744  auto thits = theTransformer->getTransientRecHits(ttrack);
746  MTDHitMatchingInfo mBTL, mETL;
747 
748  if (trajs.isValid()) {
749  // get the outermost trajectory point on the track
750  TrajectoryStateOnSurface tsos = builder_->build(track).outermostMeasurementState();
752  bool tscbl_status = getTrajectoryStateClosestToBeamLine(trajs, bs, prop, tscbl);
753 
754  if (tscbl_status) {
755  float pmag2 = tscbl.trackStateAtPCA().momentum().mag2();
756  float pathlength0;
757  TrackSegments trs0;
758  trackPathLength(trajs, tscbl, prop, pathlength0, trs0);
759 
760  const auto& btlhits = tryBTLLayers(tsos,
761  trajs,
762  pmag2,
763  pathlength0,
764  trs0,
765  hits,
766  geo.product(),
767  magfield.product(),
768  prop,
769  bs,
770  trackVtxTime,
771  trackVtxTime != 0.f,
772  mBTL);
773  mtdthits.insert(mtdthits.end(), btlhits.begin(), btlhits.end());
774 
775  // in the future this should include an intermediate refit before propagating to the ETL
776  // for now it is ok
777  const auto& etlhits = tryETLLayers(tsos,
778  trajs,
779  pmag2,
780  pathlength0,
781  trs0,
782  hits,
783  geo.product(),
784  magfield.product(),
785  prop,
786  bs,
787  trackVtxTime,
788  trackVtxTime != 0.f,
789  mETL);
790  mtdthits.insert(mtdthits.end(), etlhits.begin(), etlhits.end());
791  }
792  }
793 
794  auto ordering = checkRecHitsOrdering(thits);
796  thits.insert(thits.end(), mtdthits.begin(), mtdthits.end());
797  } else {
798  std::reverse(mtdthits.begin(), mtdthits.end());
799  mtdthits.insert(mtdthits.end(), thits.begin(), thits.end());
800  thits.swap(mtdthits);
801  }
802 
803  const auto& trajwithmtd =
804  mtdthits.empty() ? std::vector<Trajectory>(1, trajs) : theTransformer->transform(ttrack, thits);
805  float pMap = 0.f, betaMap = 0.f, t0Map = 0.f, sigmat0Map = -1.f, pathLengthMap = -1.f, tmtdMap = 0.f,
806  sigmatmtdMap = -1.f, tofpiMap = 0.f, tofkMap = 0.f, tofpMap = 0.f;
807  int iMap = -1;
808 
809  for (const auto& trj : trajwithmtd) {
810  const auto& thetrj = (updateTraj_ ? trj : trajs);
811  float pathLength = 0.f, tmtd = 0.f, sigmatmtd = -1.f, tofpi = 0.f, tofk = 0.f, tofp = 0.f;
812  LogTrace("TrackExtenderWithMTD") << "TrackExtenderWithMTD: refit track " << itrack << " p/pT = " << track->p()
813  << " " << track->pt() << " eta = " << track->eta();
814  reco::Track result = buildTrack(track,
815  thetrj,
816  trj,
817  bs,
818  magfield.product(),
819  prop,
820  !trajwithmtd.empty() && !mtdthits.empty(),
821  pathLength,
822  tmtd,
823  sigmatmtd,
824  tofpi,
825  tofk,
826  tofp);
827  if (result.ndof() >= 0) {
829  reco::TrackExtra::TrajParams trajParams;
831  size_t hitsstart = outhits->size();
832  if (updatePattern_) {
833  t2t(trj, *outhits, trajParams, chi2s); // this fills the output hit collection
834  } else {
835  t2t(thetrj, *outhits, trajParams, chi2s);
836  }
837  size_t hitsend = outhits->size();
838  extras->push_back(buildTrackExtra(trj)); // always push back the fully built extra, update by setting in track
839  extras->back().setHits(hitsRefProd, hitsstart, hitsend - hitsstart);
840  extras->back().setTrajParams(trajParams, chi2s);
841  //create the track
842  output->push_back(result);
843  btlMatchChi2.push_back(mBTL.hit ? mBTL.estChi2 : -1.f);
844  etlMatchChi2.push_back(mETL.hit ? mETL.estChi2 : -1.f);
845  btlMatchTimeChi2.push_back(mBTL.hit ? mBTL.timeChi2 : -1.f);
846  etlMatchTimeChi2.push_back(mETL.hit ? mETL.timeChi2 : -1.f);
847  pathLengthMap = pathLength;
848  tmtdMap = tmtd;
849  sigmatmtdMap = sigmatmtd;
850  auto& backtrack = output->back();
851  iMap = output->size() - 1;
852  pMap = backtrack.p();
853  betaMap = backtrack.beta();
854  t0Map = backtrack.t0();
855  sigmat0Map = std::copysign(std::sqrt(std::abs(backtrack.covt0t0())), backtrack.covt0t0());
856  tofpiMap = tofpi;
857  tofkMap = tofk;
858  tofpMap = tofp;
859  reco::TrackExtraRef extraRef(extrasRefProd, extras->size() - 1);
860  backtrack.setExtra((updateExtra_ ? extraRef : track->extra()));
861  for (unsigned ihit = hitsstart; ihit < hitsend; ++ihit) {
862  backtrack.appendHitPattern((*outhits)[ihit], ttopo);
863  }
864  npixBarrel.push_back(backtrack.hitPattern().numberOfValidPixelBarrelHits());
865  npixEndcap.push_back(backtrack.hitPattern().numberOfValidPixelEndcapHits());
866  LogTrace("TrackExtenderWithMTD") << "TrackExtenderWithMTD: tmtd " << tmtdMap << " +/- " << sigmatmtdMap
867  << " t0 " << t0Map << " +/- " << sigmat0Map << " tof pi/K/p " << tofpiMap
868  << " " << tofkMap << " " << tofpMap;
869  } else {
870  LogTrace("TrackExtenderWithMTD") << "Error in the MTD track refitting. This should not happen";
871  }
872  }
873 
874  pOrigTrkRaw.push_back(pMap);
875  betaOrigTrkRaw.push_back(betaMap);
876  t0OrigTrkRaw.push_back(t0Map);
877  sigmat0OrigTrkRaw.push_back(sigmat0Map);
878  pathLengthsOrigTrkRaw.push_back(pathLengthMap);
879  tmtdOrigTrkRaw.push_back(tmtdMap);
880  sigmatmtdOrigTrkRaw.push_back(sigmatmtdMap);
881  tofpiOrigTrkRaw.push_back(tofpiMap);
882  tofkOrigTrkRaw.push_back(tofkMap);
883  tofpOrigTrkRaw.push_back(tofpMap);
884  assocOrigTrkRaw.push_back(iMap);
885 
886  if (iMap == -1) {
887  btlMatchChi2.push_back(-1.f);
888  etlMatchChi2.push_back(-1.f);
889  btlMatchTimeChi2.push_back(-1.f);
890  etlMatchTimeChi2.push_back(-1.f);
891  npixBarrel.push_back(-1.f);
892  npixEndcap.push_back(-1.f);
893  }
894 
895  ++itrack;
896  }
897 
898  auto outTrksHandle = ev.put(std::move(output));
899  ev.put(std::move(extras));
900  ev.put(std::move(outhits));
901 
902  fillValueMap(ev, tracksH, btlMatchChi2, btlMatchChi2Token_);
903  fillValueMap(ev, tracksH, etlMatchChi2, etlMatchChi2Token_);
904  fillValueMap(ev, tracksH, btlMatchTimeChi2, btlMatchTimeChi2Token_);
905  fillValueMap(ev, tracksH, etlMatchTimeChi2, etlMatchTimeChi2Token_);
906  fillValueMap(ev, tracksH, npixBarrel, npixBarrelToken_);
907  fillValueMap(ev, tracksH, npixEndcap, npixEndcapToken_);
908  fillValueMap(ev, tracksH, pOrigTrkRaw, pOrigTrkToken_);
909  fillValueMap(ev, tracksH, betaOrigTrkRaw, betaOrigTrkToken_);
910  fillValueMap(ev, tracksH, t0OrigTrkRaw, t0OrigTrkToken_);
911  fillValueMap(ev, tracksH, sigmat0OrigTrkRaw, sigmat0OrigTrkToken_);
912  fillValueMap(ev, tracksH, pathLengthsOrigTrkRaw, pathLengthOrigTrkToken_);
913  fillValueMap(ev, tracksH, tmtdOrigTrkRaw, tmtdOrigTrkToken_);
914  fillValueMap(ev, tracksH, sigmatmtdOrigTrkRaw, sigmatmtdOrigTrkToken_);
915  fillValueMap(ev, tracksH, tofpiOrigTrkRaw, tofpiOrigTrkToken_);
916  fillValueMap(ev, tracksH, tofkOrigTrkRaw, tofkOrigTrkToken_);
917  fillValueMap(ev, tracksH, tofpOrigTrkRaw, tofpOrigTrkToken_);
918  fillValueMap(ev, tracksH, assocOrigTrkRaw, assocOrigTrkToken_);
919 }
920 
921 namespace {
922  bool cmp_for_detset(const unsigned one, const unsigned two) { return one < two; };
923 
924  void find_hits_in_dets(const MTDTrackingDetSetVector& hits,
925  const Trajectory& traj,
926  const DetLayer* layer,
927  const TrajectoryStateOnSurface& tsos,
928  const float pmag2,
929  const float pathlength0,
930  const TrackSegments& trs0,
931  const float vtxTime,
932  const reco::BeamSpot& bs,
933  const float bsTimeSpread,
934  const Propagator* prop,
936  bool useVtxConstraint,
937  std::set<MTDHitMatchingInfo>& out) {
938  pair<bool, TrajectoryStateOnSurface> comp = layer->compatible(tsos, *prop, *estimator);
939  if (comp.first) {
940  const vector<DetLayer::DetWithState> compDets = layer->compatibleDets(tsos, *prop, *estimator);
941  LogTrace("TrackExtenderWithMTD") << "Hit search: Compatible dets " << compDets.size();
942  if (!compDets.empty()) {
943  for (const auto& detWithState : compDets) {
944  auto range = hits.equal_range(detWithState.first->geographicalId(), cmp_for_detset);
945  if (range.first == range.second) {
946  LogTrace("TrackExtenderWithMTD")
947  << "Hit search: no hit in DetId " << detWithState.first->geographicalId().rawId();
948  continue;
949  }
950 
951  auto pl = prop->propagateWithPath(tsos, detWithState.second.surface());
952  if (pl.second == 0.) {
953  LogTrace("TrackExtenderWithMTD")
954  << "Hit search: no propagation to DetId " << detWithState.first->geographicalId().rawId();
955  continue;
956  }
957 
958  const float t_vtx = useVtxConstraint ? vtxTime : 0.f;
959 
960  constexpr float vtx_res = 0.008f;
961  const float t_vtx_err = useVtxConstraint ? vtx_res : bsTimeSpread;
962 
963  float lastpmag2 = trs0.getSegmentPathAndMom2(0).second;
964 
965  for (auto detitr = range.first; detitr != range.second; ++detitr) {
966  for (const auto& hit : *detitr) {
967  auto est = estimator->estimate(detWithState.second, hit);
968  if (!est.first) {
969  LogTrace("TrackExtenderWithMTD")
970  << "Hit search: no compatible estimate in DetId " << detWithState.first->geographicalId().rawId()
971  << " for hit at pos (" << std::fixed << std::setw(14) << hit.globalPosition().x() << ","
972  << std::fixed << std::setw(14) << hit.globalPosition().y() << "," << std::fixed << std::setw(14)
973  << hit.globalPosition().z() << ")";
974  continue;
975  }
976 
977  LogTrace("TrackExtenderWithMTD")
978  << "Hit search: spatial compatibility DetId " << detWithState.first->geographicalId().rawId()
979  << " TSOS dx/dy " << std::fixed << std::setw(14)
980  << std::sqrt(detWithState.second.localError().positionError().xx()) << " " << std::fixed
981  << std::setw(14) << std::sqrt(detWithState.second.localError().positionError().yy()) << " hit dx/dy "
982  << std::fixed << std::setw(14) << std::sqrt(hit.localPositionError().xx()) << " " << std::fixed
983  << std::setw(14) << std::sqrt(hit.localPositionError().yy()) << " chi2 " << std::fixed
984  << std::setw(14) << est.second;
985 
986  TrackTofPidInfo tof = computeTrackTofPidInfo(lastpmag2,
987  std::abs(pl.second),
988  trs0,
989  hit.time(),
990  hit.timeError(),
991  t_vtx,
992  t_vtx_err, //put vtx error by hand for the moment
993  false,
994  TofCalc::kMixd);
995  MTDHitMatchingInfo mi;
996  mi.hit = &hit;
997  mi.estChi2 = est.second;
998  mi.timeChi2 = tof.dtchi2_best; //use the chi2 for the best matching hypothesis
999 
1000  out.insert(mi);
1001  }
1002  }
1003  }
1004  }
1005  }
1006  }
1007 } // namespace
1008 
1009 template <class TrackCollection>
1011  const TrajectoryStateOnSurface& tsos,
1012  const Trajectory& traj,
1013  const float pmag2,
1014  const float pathlength0,
1015  const TrackSegments& trs0,
1017  const MTDDetLayerGeometry* geo,
1018  const MagneticField* field,
1019  const Propagator* prop,
1020  const reco::BeamSpot& bs,
1021  const float vtxTime,
1022  const bool matchVertex,
1023  MTDHitMatchingInfo& bestHit) const {
1024  const vector<const DetLayer*>& layers = geo->allBTLLayers();
1025 
1027  bestHit = MTDHitMatchingInfo();
1028  for (const DetLayer* ilay : layers) {
1029  LogTrace("TrackExtenderWithMTD") << "Hit search: BTL layer at R= "
1030  << static_cast<const BarrelDetLayer*>(ilay)->specificSurface().radius();
1031 
1032  fillMatchingHits(ilay, tsos, traj, pmag2, pathlength0, trs0, hits, prop, bs, vtxTime, matchVertex, output, bestHit);
1033  }
1034 
1035  return output;
1036 }
1037 
1038 template <class TrackCollection>
1040  const TrajectoryStateOnSurface& tsos,
1041  const Trajectory& traj,
1042  const float pmag2,
1043  const float pathlength0,
1044  const TrackSegments& trs0,
1046  const MTDDetLayerGeometry* geo,
1047  const MagneticField* field,
1048  const Propagator* prop,
1049  const reco::BeamSpot& bs,
1050  const float vtxTime,
1051  const bool matchVertex,
1052  MTDHitMatchingInfo& bestHit) const {
1053  const vector<const DetLayer*>& layers = geo->allETLLayers();
1054 
1056  bestHit = MTDHitMatchingInfo();
1057  for (const DetLayer* ilay : layers) {
1058  const BoundDisk& disk = static_cast<const ForwardDetLayer*>(ilay)->specificSurface();
1059  const float diskZ = disk.position().z();
1060 
1061  if (tsos.globalPosition().z() * diskZ < 0)
1062  continue; // only propagate to the disk that's on the same side
1063 
1064  LogTrace("TrackExtenderWithMTD") << "Hit search: ETL disk at Z = " << diskZ;
1065 
1066  fillMatchingHits(ilay, tsos, traj, pmag2, pathlength0, trs0, hits, prop, bs, vtxTime, matchVertex, output, bestHit);
1067  }
1068 
1069  // the ETL hits order must be from the innermost to the outermost
1070 
1071  if (output.size() == 2) {
1072  if (std::abs(output[0]->globalPosition().z()) > std::abs(output[1]->globalPosition().z())) {
1073  std::reverse(output.begin(), output.end());
1074  }
1075  }
1076  return output;
1077 }
1078 
1079 template <class TrackCollection>
1081  const TrajectoryStateOnSurface& tsos,
1082  const Trajectory& traj,
1083  const float pmag2,
1084  const float pathlength0,
1085  const TrackSegments& trs0,
1087  const Propagator* prop,
1088  const reco::BeamSpot& bs,
1089  const float& vtxTime,
1090  const bool matchVertex,
1092  MTDHitMatchingInfo& bestHit) const {
1093  std::set<MTDHitMatchingInfo> hitsInLayer;
1094  bool hitMatched = false;
1095 
1096  using namespace std::placeholders;
1097  auto find_hits = std::bind(find_hits_in_dets,
1098  std::cref(hits),
1099  std::cref(traj),
1100  ilay,
1101  std::cref(tsos),
1102  pmag2,
1103  pathlength0,
1104  trs0,
1105  _1,
1106  std::cref(bs),
1107  bsTimeSpread_,
1108  prop,
1109  theEstimator.get(),
1110  _2,
1111  std::ref(hitsInLayer));
1112 
1113  if (useVertex_ && matchVertex)
1114  find_hits(vtxTime, true);
1115  else
1116  find_hits(0, false);
1117 
1118  float spaceChi2Cut = ilay->isBarrel() ? btlChi2Cut_ : etlChi2Cut_;
1119  float timeChi2Cut = ilay->isBarrel() ? btlTimeChi2Cut_ : etlTimeChi2Cut_;
1120 
1121  //just take the first hit because the hits are sorted on their matching quality
1122  if (!hitsInLayer.empty()) {
1123  //check hits to pass minimum quality matching requirements
1124  auto const& firstHit = *hitsInLayer.begin();
1125  LogTrace("TrackExtenderWithMTD") << "TrackExtenderWithMTD: matching trial 1: estChi2= " << firstHit.estChi2
1126  << " timeChi2= " << firstHit.timeChi2;
1127  if (firstHit.estChi2 < spaceChi2Cut && firstHit.timeChi2 < timeChi2Cut) {
1128  hitMatched = true;
1129  output.push_back(hitbuilder_->build(firstHit.hit));
1130  if (firstHit < bestHit)
1131  bestHit = firstHit;
1132  }
1133  }
1134 
1135  if (useVertex_ && matchVertex && !hitMatched) {
1136  //try a second search with beamspot hypothesis
1137  hitsInLayer.clear();
1138  find_hits(0, false);
1139  if (!hitsInLayer.empty()) {
1140  auto const& firstHit = *hitsInLayer.begin();
1141  LogTrace("TrackExtenderWithMTD") << "TrackExtenderWithMTD: matching trial 2: estChi2= " << firstHit.estChi2
1142  << " timeChi2= " << firstHit.timeChi2;
1143  if (firstHit.timeChi2 < timeChi2Cut) {
1144  if (firstHit.estChi2 < spaceChi2Cut) {
1145  hitMatched = true;
1146  output.push_back(hitbuilder_->build(firstHit.hit));
1147  if (firstHit < bestHit)
1148  bestHit = firstHit;
1149  }
1150  }
1151  }
1152  }
1153 
1154 #ifdef EDM_ML_DEBUG
1155  if (hitMatched) {
1156  LogTrace("TrackExtenderWithMTD") << "TrackExtenderWithMTD: matched hit with time: " << bestHit.hit->time()
1157  << " +/- " << bestHit.hit->timeError();
1158  } else {
1159  LogTrace("TrackExtenderWithMTD") << "TrackExtenderWithMTD: no matched hit";
1160  }
1161 #endif
1162 }
1163 
1164 //below is unfortunately ripped from other places but
1165 //since track producer doesn't know about MTD we have to do this
1166 template <class TrackCollection>
1168  const Trajectory& traj,
1169  const Trajectory& trajWithMtd,
1170  const reco::BeamSpot& bs,
1171  const MagneticField* field,
1172  const Propagator* thePropagator,
1173  bool hasMTD,
1174  float& pathLengthOut,
1175  float& tmtdOut,
1176  float& sigmatmtdOut,
1177  float& tofpi,
1178  float& tofk,
1179  float& tofp) const {
1181  bool tsbcl_status = getTrajectoryStateClosestToBeamLine(traj, bs, thePropagator, tscbl);
1182 
1183  if (!tsbcl_status)
1184  return reco::Track();
1185 
1186  GlobalPoint v = tscbl.trackStateAtPCA().position();
1187  math::XYZPoint pos(v.x(), v.y(), v.z());
1188  GlobalVector p = tscbl.trackStateAtPCA().momentum();
1189  math::XYZVector mom(p.x(), p.y(), p.z());
1190 
1191  int ndof = traj.ndof();
1192 
1193  float t0 = 0.f;
1194  float covt0t0 = -1.f;
1195  pathLengthOut = -1.f; // if there is no MTD flag the pathlength with -1
1196  tmtdOut = 0.f;
1197  sigmatmtdOut = -1.f;
1198  float betaOut = 0.f;
1199  float covbetabeta = -1.f;
1200 
1201  auto routput = [&]() {
1202  return reco::Track(traj.chiSquared(),
1203  int(ndof),
1204  pos,
1205  mom,
1206  tscbl.trackStateAtPCA().charge(),
1208  orig->algo(),
1210  t0,
1211  betaOut,
1212  covt0t0,
1213  covbetabeta);
1214  };
1215 
1216  //compute path length for time backpropagation, using first MTD hit for the momentum
1217  if (hasMTD) {
1218  float pathlength;
1219  TrackSegments trs;
1220  bool validpropagation = trackPathLength(trajWithMtd, bs, thePropagator, pathlength, trs);
1221  float thit = 0.f;
1222  float thiterror = -1.f;
1223  bool validmtd = false;
1224 
1225  if (!validpropagation) {
1226  return routput();
1227  }
1228 
1229  uint32_t ihitcount(0), ietlcount(0);
1230  for (auto const& hit : trajWithMtd.measurements()) {
1231  if (hit.recHit()->geographicalId().det() == DetId::Forward &&
1232  ForwardSubdetector(hit.recHit()->geographicalId().subdetId()) == FastTime) {
1233  ihitcount++;
1234  if (MTDDetId(hit.recHit()->geographicalId()).mtdSubDetector() == MTDDetId::MTDType::ETL) {
1235  ietlcount++;
1236  }
1237  }
1238  }
1239 
1240  LogTrace("TrackExtenderWithMTD") << "TrackExtenderWithMTD: selected #hits " << ihitcount << " from ETL "
1241  << ietlcount;
1242 
1243  auto ihit1 = trajWithMtd.measurements().cbegin();
1244  if (ihitcount == 1) {
1245  const MTDTrackingRecHit* mtdhit = static_cast<const MTDTrackingRecHit*>((*ihit1).recHit()->hit());
1246  thit = mtdhit->time();
1247  thiterror = mtdhit->timeError();
1248  validmtd = true;
1249  } else if (ihitcount == 2 && ietlcount == 2) {
1250  std::pair<float, float> lastStep = trs.getSegmentPathAndMom2(0);
1251  float etlpathlength = std::abs(lastStep.first * c_cm_ns);
1252  //
1253  // The information of the two ETL hits is combined and attributed to the innermost hit
1254  //
1255  if (etlpathlength == 0.f) {
1256  validpropagation = false;
1257  } else {
1258  pathlength -= etlpathlength;
1259  trs.removeFirstSegment();
1260  const MTDTrackingRecHit* mtdhit1 = static_cast<const MTDTrackingRecHit*>((*ihit1).recHit()->hit());
1261  const MTDTrackingRecHit* mtdhit2 = static_cast<const MTDTrackingRecHit*>((*(ihit1 + 1)).recHit()->hit());
1262  TrackTofPidInfo tofInfo = computeTrackTofPidInfo(
1263  lastStep.second, etlpathlength, trs, mtdhit1->time(), mtdhit1->timeError(), 0.f, 0.f, true, TofCalc::kCost);
1264  //
1265  // Protect against incompatible times
1266  //
1267  float err1 = tofInfo.dterror * tofInfo.dterror;
1268  float err2 = mtdhit2->timeError() * mtdhit2->timeError();
1269  if (cms_rounding::roundIfNear0(err1) == 0.f || cms_rounding::roundIfNear0(err2) == 0.f) {
1270  edm::LogError("TrackExtenderWithMTD")
1271  << "MTD tracking hits with zero time uncertainty: " << err1 << " " << err2;
1272  } else {
1273  if ((tofInfo.dt - mtdhit2->time()) * (tofInfo.dt - mtdhit2->time()) < (err1 + err2) * etlTimeChi2Cut_) {
1274  //
1275  // Subtract the ETL time of flight from the outermost measurement, and combine it in a weighted average with the innermost
1276  // the mass ambiguity related uncertainty on the time of flight is added as an additional uncertainty
1277  //
1278  err1 = 1.f / err1;
1279  err2 = 1.f / err2;
1280  thiterror = 1.f / (err1 + err2);
1281  thit = (tofInfo.dt * err1 + mtdhit2->time() * err2) * thiterror;
1282  thiterror = std::sqrt(thiterror);
1283  LogTrace("TrackExtenderWithMTD")
1284  << "TrackExtenderWithMTD: p trk = " << p.mag() << " ETL hits times/errors: " << mtdhit1->time()
1285  << " +/- " << mtdhit1->timeError() << " , " << mtdhit2->time() << " +/- " << mtdhit2->timeError()
1286  << " extrapolated time1: " << tofInfo.dt << " +/- " << tofInfo.dterror << " average = " << thit
1287  << " +/- " << thiterror;
1288  validmtd = true;
1289  } else {
1290  LogTrace("TrackExtenderWithMTD")
1291  << "TrackExtenderWithMTD: issue with layer2 extrapolation to layer1, time difference "
1292  << (tofInfo.dt - mtdhit2->time()) << " larger than maximal uncertainty "
1293  << (err1 + err2) * etlTimeChi2Cut_;
1294  }
1295  }
1296  }
1297  } else {
1298  edm::LogInfo("TrackExtenderWithMTD")
1299  << "MTD hits #" << ihitcount << "ETL hits #" << ietlcount << " anomalous pattern, skipping...";
1300  }
1301 
1302  if (validmtd && validpropagation) {
1303  //here add the PID uncertainty for later use in the 1st step of 4D vtx reconstruction
1304  TrackTofPidInfo tofInfo =
1305  computeTrackTofPidInfo(p.mag2(), pathlength, trs, thit, thiterror, 0.f, 0.f, true, TofCalc::kSegm);
1306  pathLengthOut = pathlength; // set path length if we've got a timing hit
1307  tmtdOut = thit;
1308  sigmatmtdOut = thiterror;
1309  t0 = tofInfo.dt;
1310  covt0t0 = tofInfo.dterror * tofInfo.dterror;
1311  betaOut = tofInfo.beta_pi;
1312  covbetabeta = tofInfo.betaerror * tofInfo.betaerror;
1313  tofpi = tofInfo.dt_pi;
1314  tofk = tofInfo.dt_k;
1315  tofp = tofInfo.dt_p;
1316  }
1317  }
1318 
1319  return routput();
1320 }
1321 
1322 template <class TrackCollection>
1324  static const string metname = "TrackExtenderWithMTD";
1325 
1326  const Trajectory::RecHitContainer transRecHits = trajectory.recHits();
1327 
1328  // put the collection of TrackingRecHit in the event
1329 
1330  // sets the outermost and innermost TSOSs
1331  // ToDo: validation for track states with MTD
1332  TrajectoryStateOnSurface outerTSOS;
1333  TrajectoryStateOnSurface innerTSOS;
1334  unsigned int innerId = 0, outerId = 0;
1336  DetId outerDetId;
1337 
1338  if (trajectory.direction() == alongMomentum) {
1339  LogTrace(metname) << "alongMomentum";
1340  outerTSOS = trajectory.lastMeasurement().updatedState();
1341  innerTSOS = trajectory.firstMeasurement().updatedState();
1342  outerId = trajectory.lastMeasurement().recHit()->geographicalId().rawId();
1343  innerId = trajectory.firstMeasurement().recHit()->geographicalId().rawId();
1344  outerRecHit = trajectory.lastMeasurement().recHit();
1345  outerDetId = trajectory.lastMeasurement().recHit()->geographicalId();
1346  } else if (trajectory.direction() == oppositeToMomentum) {
1347  LogTrace(metname) << "oppositeToMomentum";
1348  outerTSOS = trajectory.firstMeasurement().updatedState();
1349  innerTSOS = trajectory.lastMeasurement().updatedState();
1350  outerId = trajectory.firstMeasurement().recHit()->geographicalId().rawId();
1351  innerId = trajectory.lastMeasurement().recHit()->geographicalId().rawId();
1352  outerRecHit = trajectory.firstMeasurement().recHit();
1353  outerDetId = trajectory.firstMeasurement().recHit()->geographicalId();
1354  } else
1355  LogError(metname) << "Wrong propagation direction!";
1356 
1357  const GeomDet* outerDet = gtg_->idToDet(outerDetId);
1358  GlobalPoint outerTSOSPos = outerTSOS.globalParameters().position();
1359  bool inside = outerDet->surface().bounds().inside(outerDet->toLocal(outerTSOSPos));
1360 
1361  GlobalPoint hitPos =
1362  (outerRecHit->isValid()) ? outerRecHit->globalPosition() : outerTSOS.globalParameters().position();
1363 
1364  if (!inside) {
1365  LogTrace(metname) << "The Global Muon outerMostMeasurementState is not compatible with the recHit detector!"
1366  << " Setting outerMost postition to recHit position if recHit isValid: "
1367  << outerRecHit->isValid();
1368  LogTrace(metname) << "From " << outerTSOSPos << " to " << hitPos;
1369  }
1370 
1371  //build the TrackExtra
1372  GlobalPoint v = (inside) ? outerTSOSPos : hitPos;
1373  GlobalVector p = outerTSOS.globalParameters().momentum();
1374  math::XYZPoint outpos(v.x(), v.y(), v.z());
1375  math::XYZVector outmom(p.x(), p.y(), p.z());
1376 
1377  v = innerTSOS.globalParameters().position();
1378  p = innerTSOS.globalParameters().momentum();
1379  math::XYZPoint inpos(v.x(), v.y(), v.z());
1380  math::XYZVector inmom(p.x(), p.y(), p.z());
1381 
1382  reco::TrackExtra trackExtra(outpos,
1383  outmom,
1384  true,
1385  inpos,
1386  inmom,
1387  true,
1388  outerTSOS.curvilinearError(),
1389  outerId,
1390  innerTSOS.curvilinearError(),
1391  innerId,
1392  trajectory.direction(),
1393  trajectory.seedRef());
1394 
1395  return trackExtra;
1396 }
1397 
1398 template <class TrackCollection>
1400  stringstream output;
1401 
1402  const BoundSurface* sur = nullptr;
1403  const BoundCylinder* bc = nullptr;
1404  const BoundDisk* bd = nullptr;
1405 
1406  sur = &(layer->surface());
1407  if ((bc = dynamic_cast<const BoundCylinder*>(sur))) {
1408  output << " Cylinder of radius: " << bc->radius() << endl;
1409  } else if ((bd = dynamic_cast<const BoundDisk*>(sur))) {
1410  output << " Disk at: " << bd->position().z() << endl;
1411  }
1412  return output.str();
1413 }
1414 
1415 //define this as a plug-in
1422 
size
Write out results.
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
float dt
Definition: AMPTWrapper.h:136
TrackExtenderWithMTDT< reco::TrackCollection > TrackExtenderWithMTD
edm::EDPutToken btlMatchTimeChi2Token_
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
bool isValid() const
Definition: Trajectory.h:257
edm::ESGetToken< TransientTrackingRecHitBuilder, TransientRecHitRecord > hitbuilderToken_
const CurvilinearTrajectoryError & curvilinearError() const
edm::EDPutToken btlMatchChi2Token_
std::vector< unsigned char > Chi2sFive
constexpr double c_cm_ns
virtual bool inside(const Local3DPoint &) const =0
Determine if the point is inside the bounds.
edm::EDPutToken tofpOrigTrkToken_
bool operator<(IOVSyncValue const &iLHS, IOVSyncValue const &iRHS)
Definition: IOVSyncValue.h:34
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:58
edm::ESGetToken< GlobalTrackingGeometry, GlobalTrackingGeometryRecord > gtgToken_
T z() const
Definition: PV3DBase.h:61
const std::string metname
edm::EDGetTokenT< reco::BeamSpot > bsToken_
std::unique_ptr< MeasurementEstimator > theEstimator
TrackExtenderWithMTDT(const ParameterSet &pset)
edm::ESGetToken< TrackerTopology, TrackerTopologyRcd > ttopoToken_
const GlobalTrajectoryParameters & globalParameters() const
ParameterSet const & getParameterSet(std::string const &) const
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
edm::EDPutToken etlMatchChi2Token_
edm::View< TrackType > InputCollection
edm::EDGetTokenT< GlobalPoint > genVtxPositionToken_
float chiSquared() const
Definition: Trajectory.h:241
edm::RefToBase< TrajectorySeed > seedRef(void) const
Definition: Trajectory.h:303
Log< level::Error, false > LogError
T mag2() const
Definition: PV3DBase.h:63
const SurfaceType & surface() const
edm::EDPutToken tofkOrigTrkToken_
edm::EDPutToken etlMatchTimeChi2Token_
ForwardSubdetector
edm::EDPutToken sigmat0OrigTrkToken_
void fillValueMap(edm::Event &iEvent, const H &handle, const std::vector< T > &vec, const edm::EDPutToken &token) const
float float float z
edm::EDPutToken tmtdOrigTrkToken_
Definition: Electron.h:6
TrajectoryMeasurement const & lastMeasurement() const
Definition: Trajectory.h:150
edm::EDGetTokenT< MTDTrackingDetSetVector > hitsToken_
#define LogTrace(id)
Detector identifier base class for the MIP Timing Layer.
Definition: MTDDetId.h:21
TransientTrackingRecHit::ConstRecHitContainer tryETLLayers(const TrajectoryStateOnSurface &, const Trajectory &traj, const float, const float, const TrackSegments &, const MTDTrackingDetSetVector &, const MTDDetLayerGeometry *, const MagneticField *field, const Propagator *prop, const reco::BeamSpot &bs, const float vtxTime, const bool matchVertex, MTDHitMatchingInfo &bestHit) const
DataContainer const & measurements() const
Definition: Trajectory.h:178
GlobalPoint position() const
string dumpLayer(const DetLayer *layer) const
std::vector< LocalTrajectoryParameters > TrajParams
int iEvent
Definition: GenABIO.cc:224
int ndof(bool bon=true) const
Definition: Trajectory.cc:97
GlobalPoint globalPosition() const
edm::ESGetToken< TransientTrackBuilder, TransientTrackRecord > builderToken_
const std::string mtdRecHitBuilder_
T sqrt(T t)
Definition: SSEVec.h:19
void fillMatchingHits(const DetLayer *, const TrajectoryStateOnSurface &, const Trajectory &, const float, const float, const TrackSegments &, const MTDTrackingDetSetVector &, const Propagator *, const reco::BeamSpot &, const float &, const bool, TransientTrackingRecHit::ConstRecHitContainer &, MTDHitMatchingInfo &) const
PropagationDirection const & direction() const
Definition: Trajectory.cc:133
TrackCharge charge() const
ConstRecHitContainer recHits() const
Definition: Trajectory.h:186
GlobalVector momentum() const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
edm::EDPutToken assocOrigTrkToken_
const std::string propagator_
edm::ESGetToken< Propagator, TrackingComponentsRecord > propToken_
virtual std::pair< TrajectoryStateOnSurface, double > propagateWithPath(const FreeTrajectoryState &, const Surface &) const final
Definition: Propagator.cc:10
constexpr valType roundIfNear0(valType value, double tolerance=1.e-7)
Definition: Rounding.h:11
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
Definition: EventSetup.h:130
edm::ESHandle< TransientTrackingRecHitBuilder > hitbuilder_
const std::vector< const DetLayer * > & allBTLLayers() const
return the BTL DetLayers (barrel), inside-out
std::vector< ConstRecHitPointer > ConstRecHitContainer
constexpr double c_inv
const std::string transientTrackBuilder_
Log< level::Info, false > LogInfo
Definition: DetId.h:17
std::vector< TrackExtra > TrackExtraCollection
collection of TrackExtra objects
Definition: TrackExtraFwd.h:10
ConstRecHitContainer RecHitContainer
Definition: Trajectory.h:42
constexpr NumType convertMmToCm(NumType millimeters)
Definition: angle_units.h:44
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:37
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
const CurvilinearTrajectoryError & curvilinearError() const
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
reco::TrackExtra buildTrackExtra(const Trajectory &trajectory) const
A 2D TrackerRecHit with time and time error information.
void add(std::string const &label, ParameterSetDescription const &psetDescription)
TrackingRecHit::ConstRecHitPointer ConstRecHitPointer
edm::ESHandle< TransientTrackBuilder > builder_
float timeError() const
static void fillPSetDescription(edm::ParameterSetDescription &descriptions, bool doPredictionsOnly=false, const std::string &fitter="KFFitterForRefitInsideOut", const std::string &smoother="KFSmootherForRefitInsideOut", const std::string &propagator="SmartPropagatorAnyRK", const std::string &refitDirection="alongMomentum", bool refitRPCHits=true, const std::string &trackerRecHitBuilder="WithTrackAngle", const std::string &muonRecHitBuilder="MuonRecHitBuilder", const std::string &mtdRecHitBuilder="MTDRecHitBuilder")
fillDescriptions
std::unique_ptr< TrackTransformer > theTransformer
TrajectoryStateOnSurface const & updatedState() const
edm::EDPutToken npixBarrelToken_
edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > magfldToken_
edm::EDPutToken npixEndcapToken_
fixed size matrix
HLT enums.
TrajectoryMeasurement const & firstMeasurement() const
Definition: Trajectory.h:166
static int position[264][3]
Definition: ReadPGInfo.cc:289
TrajectoryMeasurement const & closestMeasurement(GlobalPoint) const
Definition: Trajectory.cc:256
edm::EDPutToken betaOrigTrkToken_
FreeTrajectoryState const * freeState(bool withErrors=true) const
ESTransientHandle< T > getTransientHandle(const ESGetToken< T, R > &iToken) const
Definition: EventSetup.h:141
edm::EDGetTokenT< TrajTrackAssociationCollection > trajTrackAToken_
float time() const
edm::EDPutToken pathLengthOrigTrkToken_
Definition: output.py:1
edm::ESHandle< GlobalTrackingGeometry > gtg_
edm::EDPutToken sigmatmtdOrigTrkToken_
TransientTrackingRecHit::ConstRecHitContainer tryBTLLayers(const TrajectoryStateOnSurface &, const Trajectory &traj, const float, const float, const TrackSegments &, const MTDTrackingDetSetVector &, const MTDDetLayerGeometry *, const MagneticField *field, const Propagator *prop, const reco::BeamSpot &bs, const float vtxTime, const bool matchVertex, MTDHitMatchingInfo &bestHit) const
edm::EDPutToken tofpiOrigTrkToken_
edm::EDGetTokenT< float > genVtxTimeToken_
ordering
Definition: config.py:7
edm::EDGetTokenT< VertexCollection > vtxToken_
void produce(edm::Event &ev, const edm::EventSetup &es) final
bool isBarrel() const
Definition: DetLayer.h:31
TrackCollection::value_type TrackType
edm::EDGetTokenT< InputCollection > tracksToken_
const std::vector< const DetLayer * > & allETLLayers() const
return the ETL DetLayers (endcap), -Z to +Z
def move(src, dest)
Definition: eostools.py:511
RefitDirection::GeometricalDirection checkRecHitsOrdering(TransientTrackingRecHit::ConstRecHitContainer const &recHits) const
ConstRecHitPointer const & recHit() const
reco::Track buildTrack(const reco::TrackRef &, const Trajectory &, const Trajectory &, const reco::BeamSpot &, const MagneticField *field, const Propagator *prop, bool hasMTD, float &pathLength, float &tmtdOut, float &sigmatmtdOut, float &tofpi, float &tofk, float &tofp) const
#define LogDebug(id)
edm::ESGetToken< MTDDetLayerGeometry, MTDRecoGeometryRecord > dlgeoToken_
#define m_pi
Definition: RPCConst.cc:8
const Bounds & bounds() const
Definition: Surface.h:87