56 #include "CLHEP/Units/GlobalPhysicalConstants.h"
66 class MTDHitMatchingInfo {
68 MTDHitMatchingInfo() {
75 inline bool operator<(
const MTDHitMatchingInfo& m2)
const {
77 constexpr
double chi2_cut = 10.;
78 constexpr
double low_weight = 3.;
79 constexpr
double high_weight = 8.;
80 if (timeChi2 < chi2_cut && m2.timeChi2 < chi2_cut)
81 return chi2(low_weight) < m2.chi2(low_weight);
83 return chi2(high_weight) < m2.chi2(high_weight);
86 inline double chi2(
double timeWeight = 1.)
const {
return estChi2 + timeWeight * timeChi2; }
93 struct TrackTofPidInfo {
125 const TrackTofPidInfo computeTrackTofPidInfo(
double magp2,
131 bool addPIDError =
true) {
132 constexpr
double m_pi = 0.13957018;
133 constexpr
double m_pi_inv2 = 1.0 /
m_pi /
m_pi;
134 constexpr
double m_k = 0.493677;
135 constexpr
double m_k_inv2 = 1.0 / m_k / m_k;
136 constexpr
double m_p = 0.9382720813;
137 constexpr
double m_p_inv2 = 1.0 / m_p / m_p;
141 TrackTofPidInfo tofpid;
144 tofpid.tmtderror = t_mtderr;
145 tofpid.pathlength = length;
147 tofpid.gammasq_pi = 1. + magp2 * m_pi_inv2;
148 tofpid.beta_pi =
std::sqrt(1. - 1. / tofpid.gammasq_pi);
149 tofpid.dt_pi = tofpid.pathlength / tofpid.beta_pi *
c_inv;
151 tofpid.gammasq_k = 1. + magp2 * m_k_inv2;
152 tofpid.beta_k =
std::sqrt(1. - 1. / tofpid.gammasq_k);
153 tofpid.dt_k = tofpid.pathlength / tofpid.beta_k *
c_inv;
155 tofpid.gammasq_p = 1. + magp2 * m_p_inv2;
156 tofpid.beta_p =
std::sqrt(1. - 1. / tofpid.gammasq_p);
157 tofpid.dt_p = tofpid.pathlength / tofpid.beta_p *
c_inv;
159 tofpid.dt = tofpid.tmtd - tofpid.dt_pi - t_vtx;
160 tofpid.dterror =
sqrt(tofpid.tmtderror * tofpid.tmtderror + t_vtx_err * t_vtx_err);
161 tofpid.betaerror = 0;
164 sqrt(tofpid.dterror * tofpid.dterror + (tofpid.dt_p - tofpid.dt_pi) * (tofpid.dt_p - tofpid.dt_pi));
165 tofpid.betaerror = tofpid.beta_p - tofpid.beta_pi;
168 tofpid.dtchi2 = (tofpid.dt * tofpid.dt) / (tofpid.dterror * tofpid.dterror);
170 tofpid.dt_best = tofpid.dt;
171 tofpid.dterror_best = tofpid.dterror;
172 tofpid.dtchi2_best = tofpid.dtchi2;
174 tofpid.prob_pi = -1.;
180 double chi2_pi = tofpid.dtchi2;
182 (tofpid.tmtd - tofpid.dt_k - t_vtx) * (tofpid.tmtd - tofpid.dt_k - t_vtx) / (tofpid.dterror * tofpid.dterror);
184 (tofpid.tmtd - tofpid.dt_p - t_vtx) * (tofpid.tmtd - tofpid.dt_p - t_vtx) / (tofpid.dterror * tofpid.dterror);
186 double rawprob_pi =
exp(-0.5 * chi2_pi);
187 double rawprob_k =
exp(-0.5 * chi2_k);
188 double rawprob_p =
exp(-0.5 * chi2_p);
189 double normprob = 1. / (rawprob_pi + rawprob_k + rawprob_p);
191 tofpid.prob_pi = rawprob_pi * normprob;
192 tofpid.prob_k = rawprob_k * normprob;
193 tofpid.prob_p = rawprob_p * normprob;
195 double prob_heavy = 1. - tofpid.prob_pi;
196 constexpr
double heavy_threshold = 0.75;
198 if (prob_heavy > heavy_threshold) {
199 if (chi2_k < chi2_p) {
200 tofpid.dt_best = (tofpid.tmtd - tofpid.dt_k - t_vtx);
201 tofpid.dtchi2_best = chi2_k;
203 tofpid.dt_best = (tofpid.tmtd - tofpid.dt_p - t_vtx);
204 tofpid.dtchi2_best = chi2_p;
211 template <
class TrackCollection>
219 template <
class H,
class T>
233 const double vtxTime,
234 const bool matchVertex,
235 MTDHitMatchingInfo& bestHit)
const;
244 const double vtxTime,
245 const bool matchVertex,
246 MTDHitMatchingInfo& bestHit)
const;
248 void fillMatchingHits(
const DetLayer*,
257 MTDHitMatchingInfo&)
const;
266 auto rFirst =
first.mag2();
267 auto rLast =
last.mag2();
273 LogDebug(
"TrackExtenderWithMTD") <<
"Impossible to determine the rechits order" << endl;
286 float& sigmatmtdOut)
const;
289 string dumpLayer(
const DetLayer* layer)
const;
337 template <
class TrackCollection>
342 updateTraj_(iConfig.getParameter<
bool>(
"updateTrackTrajectory")),
343 updateExtra_(iConfig.getParameter<
bool>(
"updateTrackExtra")),
344 updatePattern_(iConfig.getParameter<
bool>(
"updateTrackHitPattern")),
345 mtdRecHitBuilder_(iConfig.getParameter<
std::
string>(
"MTDRecHitBuilder")),
346 propagator_(iConfig.getParameter<
std::
string>(
"Propagator")),
347 transientTrackBuilder_(iConfig.getParameter<
std::
string>(
"TransientTrackBuilder")),
348 estMaxChi2_(iConfig.getParameter<double>(
"estimatorMaxChi2")),
349 estMaxNSigma_(iConfig.getParameter<double>(
"estimatorMaxNSigma")),
350 btlChi2Cut_(iConfig.getParameter<double>(
"btlChi2Cut")),
351 btlTimeChi2Cut_(iConfig.getParameter<double>(
"btlTimeChi2Cut")),
352 etlChi2Cut_(iConfig.getParameter<double>(
"etlChi2Cut")),
353 etlTimeChi2Cut_(iConfig.getParameter<double>(
"etlTimeChi2Cut")),
354 useVertex_(iConfig.getParameter<
bool>(
"useVertex")),
355 useSimVertex_(iConfig.getParameter<
bool>(
"useSimVertex")),
356 dzCut_(iConfig.getParameter<double>(
"dZCut")),
357 bsTimeSpread_(iConfig.getParameter<double>(
"bsTimeSpread")) {
374 tmtdToken = produces<edm::ValueMap<float>>(
"tmtd");
376 pOrigTrkToken = produces<edm::ValueMap<float>>(
"generalTrackp");
378 t0OrigTrkToken = produces<edm::ValueMap<float>>(
"generalTrackt0");
385 produces<edm::OwnVector<TrackingRecHit>>();
386 produces<reco::TrackExtraCollection>();
387 produces<TrackCollection>();
390 template <
class TrackCollection>
399 desc.
add<
bool>(
"updateTrackTrajectory",
true);
400 desc.
add<
bool>(
"updateTrackExtra",
true);
401 desc.
add<
bool>(
"updateTrackHitPattern",
true);
402 desc.
add<
std::string>(
"TransientTrackBuilder",
"TransientTrackBuilder");
404 desc.
add<
std::string>(
"Propagator",
"PropagatorWithMaterialForMTD");
407 "KFFitterForRefitInsideOut",
408 "KFSmootherForRefitInsideOut",
409 "PropagatorWithMaterialForMTD",
416 desc.
add<
double>(
"estimatorMaxChi2", 500.);
417 desc.
add<
double>(
"estimatorMaxNSigma", 10.);
418 desc.
add<
double>(
"btlChi2Cut", 50.);
419 desc.
add<
double>(
"btlTimeChi2Cut", 10.);
420 desc.
add<
double>(
"etlChi2Cut", 50.);
421 desc.
add<
double>(
"etlTimeChi2Cut", 10.);
422 desc.
add<
bool>(
"useVertex",
false);
423 desc.
add<
bool>(
"useSimVertex",
false);
424 desc.
add<
double>(
"dZCut", 0.1);
425 desc.
add<
double>(
"bsTimeSpread", 0.2);
426 descriptions.
add(
"trackExtenderWithMTDBase", desc);
429 template <
class TrackCollection>
430 template <
class H,
class T>
433 const std::vector<T>& vec,
435 auto out = std::make_unique<edm::ValueMap<T>>();
442 template <
class TrackCollection>
447 theTransformer->setServices(es);
470 auto output = std::make_unique<TrackCollection>();
471 auto extras = std::make_unique<reco::TrackExtraCollection>();
472 auto outhits = std::make_unique<edm::OwnVector<TrackingRecHit>>();
474 std::vector<float> btlMatchChi2;
475 std::vector<float> etlMatchChi2;
476 std::vector<float> btlMatchTimeChi2;
477 std::vector<float> etlMatchTimeChi2;
478 std::vector<float> pathLengthsRaw;
479 std::vector<float> tmtdRaw;
480 std::vector<float> sigmatmtdRaw;
481 std::vector<float> pOrigTrkRaw;
482 std::vector<float> betaOrigTrkRaw;
483 std::vector<float> t0OrigTrkRaw;
484 std::vector<float> sigmat0OrigTrkRaw;
485 std::vector<float> pathLengthsOrigTrkRaw;
486 std::vector<float> tmtdOrigTrkRaw;
487 std::vector<float> sigmatmtdOrigTrkRaw;
488 std::vector<int> assocOrigTrkRaw;
491 ev.getByToken(tracksToken_, tracksH);
492 const auto&
tracks = *tracksH;
495 ev.getByToken(hitsToken_, hitsH);
496 const auto&
hits = *hitsH;
499 ev.getByToken(bsToken_, bsH);
500 const auto&
bs = *bsH;
503 if (useVertex_ && !useSimVertex_) {
505 ev.getByToken(vtxToken_, vtxH);
510 std::unique_ptr<math::XYZTLorentzVectorF> genPV(
nullptr);
511 if (useVertex_ && useSimVertex_) {
512 const auto& genVtxPositionHandle =
ev.getHandle(genVtxPositionToken_);
513 const auto& genVtxTimeHandle =
ev.getHandle(genVtxTimeToken_);
514 genPV = std::make_unique<math::XYZTLorentzVectorF>(
515 genVtxPositionHandle->x(), genVtxPositionHandle->y(), genVtxPositionHandle->z(), *(genVtxTimeHandle));
520 if (useSimVertex_ && genPV) {
521 vtxTime = genPV->t();
526 std::vector<unsigned> track_indices;
530 double trackVtxTime = 0.;
539 trackVtxTime = vtxTime;
543 const auto& trajs = theTransformer->transform(
track);
544 auto thits = theTransformer->getTransientRecHits(ttrack);
546 MTDHitMatchingInfo mBTL, mETL;
547 if (!trajs.empty()) {
548 const auto& btlhits = tryBTLLayers(
track,
558 mtdthits.insert(mtdthits.end(), btlhits.begin(), btlhits.end());
562 const auto& etlhits = tryETLLayers(
track,
572 mtdthits.insert(mtdthits.end(), etlhits.begin(), etlhits.end());
575 auto ordering = checkRecHitsOrdering(thits);
577 thits.insert(thits.end(), mtdthits.begin(), mtdthits.end());
580 mtdthits.insert(mtdthits.end(), thits.begin(), thits.end());
581 thits.swap(mtdthits);
584 const auto& trajwithmtd = theTransformer->transform(ttrack, thits);
585 float pMap = 0.f, betaMap = 0.f, t0Map = 0.f, sigmat0Map = -1.f, pathLengthMap = -1.f, tmtdMap = 0.f,
589 for (
const auto& trj : trajwithmtd) {
590 const auto& thetrj = (updateTraj_ ? trj : trajs.front());
591 float pathLength = 0.f, tmtd = 0.f, sigmatmtd = -1.f;
598 !trajwithmtd.empty() && !mtdthits.empty(),
606 size_t hitsstart = outhits->size();
607 if (updatePattern_) {
608 t2t(trj, *outhits, trajParams, chi2s);
610 t2t(thetrj, *outhits, trajParams, chi2s);
612 size_t hitsend = outhits->size();
613 extras->push_back(buildTrackExtra(trj));
614 extras->back().setHits(hitsRefProd, hitsstart, hitsend - hitsstart);
615 extras->back().setTrajParams(trajParams, chi2s);
618 btlMatchChi2.push_back(mBTL.hit ? mBTL.estChi2 : -1);
619 etlMatchChi2.push_back(mETL.hit ? mETL.estChi2 : -1);
620 btlMatchTimeChi2.push_back(mBTL.hit ? mBTL.timeChi2 : -1);
621 etlMatchTimeChi2.push_back(mETL.hit ? mETL.timeChi2 : -1);
622 pathLengthsRaw.push_back(pathLength);
623 tmtdRaw.push_back(tmtd);
624 sigmatmtdRaw.push_back(sigmatmtd);
625 pathLengthMap = pathLength;
627 sigmatmtdMap = sigmatmtd;
628 auto& backtrack =
output->back();
629 iMap =
output->size() - 1;
630 pMap = backtrack.p();
631 betaMap = backtrack.beta();
632 t0Map = backtrack.t0();
633 sigmat0Map = std::copysign(
std::sqrt(
std::abs(backtrack.covt0t0())), backtrack.covt0t0());
635 backtrack.setExtra((updateExtra_ ? extraRef :
track.extra()));
636 for (
unsigned ihit = hitsstart; ihit < hitsend; ++ihit) {
637 backtrack.appendHitPattern((*outhits)[ihit], ttopo);
640 LogTrace(
"TrackExtenderWithMTD") <<
"Error in the MTD track refitting. This should not happen";
644 pOrigTrkRaw.push_back(pMap);
645 betaOrigTrkRaw.push_back(betaMap);
646 t0OrigTrkRaw.push_back(t0Map);
647 sigmat0OrigTrkRaw.push_back(sigmat0Map);
648 pathLengthsOrigTrkRaw.push_back(pathLengthMap);
649 tmtdOrigTrkRaw.push_back(tmtdMap);
650 sigmatmtdOrigTrkRaw.push_back(sigmatmtdMap);
651 assocOrigTrkRaw.push_back(iMap);
659 fillValueMap(
ev, outTrksHandle, btlMatchChi2, btlMatchChi2Token);
660 fillValueMap(
ev, outTrksHandle, etlMatchChi2, etlMatchChi2Token);
661 fillValueMap(
ev, outTrksHandle, btlMatchTimeChi2, btlMatchTimeChi2Token);
662 fillValueMap(
ev, outTrksHandle, etlMatchTimeChi2, etlMatchTimeChi2Token);
663 fillValueMap(
ev, outTrksHandle, pathLengthsRaw, pathLengthToken);
664 fillValueMap(
ev, outTrksHandle, tmtdRaw, tmtdToken);
665 fillValueMap(
ev, outTrksHandle, sigmatmtdRaw, sigmatmtdToken);
666 fillValueMap(
ev, tracksH, pOrigTrkRaw, pOrigTrkToken);
667 fillValueMap(
ev, tracksH, betaOrigTrkRaw, betaOrigTrkToken);
668 fillValueMap(
ev, tracksH, t0OrigTrkRaw, t0OrigTrkToken);
669 fillValueMap(
ev, tracksH, sigmat0OrigTrkRaw, sigmat0OrigTrkToken);
670 fillValueMap(
ev, tracksH, pathLengthsOrigTrkRaw, pathLengthOrigTrkToken);
671 fillValueMap(
ev, tracksH, tmtdOrigTrkRaw, tmtdOrigTrkToken);
672 fillValueMap(
ev, tracksH, sigmatmtdOrigTrkRaw, sigmatmtdOrigTrkToken);
673 fillValueMap(
ev, tracksH, assocOrigTrkRaw, assocOrigTrkToken);
677 bool cmp_for_detset(
const unsigned one,
const unsigned two) {
return one < two; };
679 bool getTrajectoryStateClosestToBeamLine(
const Trajectory& traj,
687 if (!stateForProjectionToBeamLineOnSurface.
isValid()) {
688 edm::LogError(
"CannotPropagateToBeamLine") <<
"the state on the closest measurement isnot valid. skipping track.";
695 tscbl = tscblBuilder(stateForProjectionToBeamLine,
bs);
703 double& pathlength) {
707 bool tscbl_status = getTrajectoryStateClosestToBeamLine(traj,
bs, thePropagator, tscbl);
712 bool validpropagation =
true;
713 double pathlength1 = 0.;
714 double pathlength2 = 0.;
719 double layerpathlength =
std::abs(propresult.second);
720 if (layerpathlength == 0.) {
721 validpropagation =
false;
723 pathlength1 += layerpathlength;
728 const auto& propresult2 =
730 pathlength2 = propresult2.second;
731 if (pathlength2 == 0.) {
732 validpropagation =
false;
734 pathlength = pathlength1 + pathlength2;
736 const auto& propresult2 =
738 pathlength2 = propresult2.second;
739 if (pathlength2 == 0.) {
740 validpropagation =
false;
742 pathlength = pathlength1 + pathlength2;
745 return validpropagation;
752 const double vtxTime,
754 const float bsTimeSpread,
756 const std::unique_ptr<MeasurementEstimator>& theEstimator,
757 bool useVtxConstraint,
758 std::set<MTDHitMatchingInfo>&
out) {
760 bool tscbl_status = getTrajectoryStateClosestToBeamLine(traj,
bs, prop, tscbl);
768 trackPathLength(traj,
bs, prop, pathlength);
770 pair<bool, TrajectoryStateOnSurface>
comp = layer->
compatible(tsos, *prop, *theEstimator);
772 vector<DetLayer::DetWithState> compDets = layer->
compatibleDets(tsos, *prop, *theEstimator);
773 if (!compDets.empty()) {
774 for (
const auto& detWithState : compDets) {
775 auto range =
hits.equal_range(detWithState.first->geographicalId(), cmp_for_detset);
776 for (
auto detitr =
range.first; detitr !=
range.second; ++detitr) {
777 for (
auto itr = detitr->begin();
itr != detitr->end(); ++
itr) {
778 auto est = theEstimator->estimate(detWithState.second, *
itr);
781 if (!est.first ||
std::abs(pl.second) == 0.)
784 double tot_pl = pathlength +
std::abs(pl.second);
785 double t_vtx = useVtxConstraint ? vtxTime : 0.;
787 constexpr
double vtx_res = 0.008;
788 double t_vtx_err = useVtxConstraint ? vtx_res : bsTimeSpread;
790 constexpr
double t_res_manual = 0.035;
792 TrackTofPidInfo tof = computeTrackTofPidInfo(
p.mag2(),
799 MTDHitMatchingInfo mi;
801 mi.estChi2 = est.second;
802 mi.timeChi2 = tof.dtchi2_best;
813 template <
class TrackCollection>
822 const double vtxTime,
823 const bool matchVertex,
824 MTDHitMatchingInfo& bestHit)
const {
827 auto tTrack = builder->build(
track);
832 bestHit = MTDHitMatchingInfo();
834 fillMatchingHits(ilay, tsos, traj,
hits, prop,
bs, vtxTime, matchVertex,
output, bestHit);
838 template <
class TrackCollection>
847 const double vtxTime,
848 const bool matchVertex,
849 MTDHitMatchingInfo& bestHit)
const {
852 auto tTrack = builder->build(
track);
857 bestHit = MTDHitMatchingInfo();
859 const BoundDisk& disk = static_cast<const MTDRingForwardDoubleLayer*>(ilay)->specificSurface();
860 const double diskZ = disk.position().z();
865 fillMatchingHits(ilay, tsos, traj,
hits, prop,
bs, vtxTime, matchVertex,
output, bestHit);
870 template <
class TrackCollection>
877 const double& vtxTime,
878 const bool matchVertex,
880 MTDHitMatchingInfo& bestHit)
const {
881 std::set<MTDHitMatchingInfo> hitsInLayer;
882 bool hitMatched =
false;
884 using namespace std::placeholders;
885 auto find_hits = std::bind(find_hits_in_dets,
894 std::ref(theEstimator),
896 std::ref(hitsInLayer));
898 if (useVertex_ && matchVertex)
899 find_hits(vtxTime,
true);
904 if (!hitsInLayer.empty()) {
906 if (hitsInLayer.begin()->estChi2 < etlChi2Cut_ && hitsInLayer.begin()->timeChi2 < etlTimeChi2Cut_) {
908 output.push_back(hitbuilder->build(hitsInLayer.begin()->hit));
909 if (*(hitsInLayer.begin()) < bestHit)
910 bestHit = *(hitsInLayer.begin());
914 if (useVertex_ && matchVertex && !hitMatched) {
918 if (!hitsInLayer.empty()) {
919 if (hitsInLayer.begin()->timeChi2 < etlTimeChi2Cut_) {
920 if (hitsInLayer.begin()->estChi2 < etlChi2Cut_) {
922 output.push_back(hitbuilder->build(hitsInLayer.begin()->hit));
923 if ((*hitsInLayer.begin()) < bestHit)
924 bestHit = *(hitsInLayer.begin());
933 template <
class TrackCollection>
941 float& pathLengthOut,
943 float& sigmatmtdOut)
const {
945 bool tsbcl_status = getTrajectoryStateClosestToBeamLine(traj,
bs, thePropagator, tscbl);
958 double covt0t0 = -1.;
959 pathLengthOut = -1.f;
963 double covbetabeta = -1.;
968 bool validpropagation = trackPathLength(trajWithMtd,
bs, thePropagator, pathlength);
970 double thiterror = -1.;
971 bool validmtd =
false;
979 thit = mtdhit->
time();
986 if (validmtd && validpropagation) {
988 TrackTofPidInfo tofInfo = computeTrackTofPidInfo(
p.mag2(), pathlength, thit, thiterror, 0., 0.,
true);
989 pathLengthOut = pathlength;
991 sigmatmtdOut = thiterror;
993 covt0t0 = tofInfo.dterror * tofInfo.dterror;
994 betaOut = tofInfo.beta_pi;
995 covbetabeta = tofInfo.betaerror * tofInfo.betaerror;
1013 template <
class TrackCollection>
1015 static const string metname =
"TrackExtenderWithMTD";
1025 unsigned int innerId = 0, outerId = 0;
1048 const GeomDet* outerDet = gtg->idToDet(outerDetId);
1056 LogTrace(
metname) <<
"The Global Muon outerMostMeasurementState is not compatible with the recHit detector!"
1057 <<
" Setting outerMost postition to recHit position if recHit isValid: "
1058 << outerRecHit->isValid();
1089 template <
class TrackCollection>
1098 if ((bc = dynamic_cast<const BoundCylinder*>(sur))) {
1099 output <<
" Cylinder of radius: " << bc->radius() << endl;
1100 }
else if ((
bd = dynamic_cast<const BoundDisk*>(sur))) {
1101 output <<
" Disk at: " <<
bd->position().z() << endl;