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 bool getTrajectoryStateClosestToBeamLine(
const Trajectory& traj,
219 if (!stateForProjectionToBeamLineOnSurface.
isValid()) {
220 edm::LogError(
"CannotPropagateToBeamLine") <<
"the state on the closest measurement isnot valid. skipping track.";
227 tscbl = tscblBuilder(stateForProjectionToBeamLine,
bs);
235 double& pathlength) {
238 bool validpropagation =
true;
239 double pathlength1 = 0.;
240 double pathlength2 = 0.;
244 const auto& propresult = thePropagator->
propagateWithPath(it->updatedState(), (it + 1)->updatedState().surface());
245 double layerpathlength =
std::abs(propresult.second);
246 if (layerpathlength == 0.) {
247 validpropagation =
false;
249 pathlength1 += layerpathlength;
257 if (pathlength2 == 0.) {
258 validpropagation =
false;
260 pathlength = pathlength1 + pathlength2;
262 return validpropagation;
268 double& pathlength) {
272 bool tscbl_status = getTrajectoryStateClosestToBeamLine(traj,
bs, thePropagator, tscbl);
277 return trackPathLength(traj, tscbl, thePropagator, pathlength);
282 template <
class TrackCollection>
290 template <
class H,
class T>
306 const double vtxTime,
307 const bool matchVertex,
308 MTDHitMatchingInfo& bestHit)
const;
319 const double vtxTime,
320 const bool matchVertex,
321 MTDHitMatchingInfo& bestHit)
const;
323 void fillMatchingHits(
const DetLayer*,
334 MTDHitMatchingInfo&)
const;
343 auto rFirst =
first.mag2();
344 auto rLast =
last.mag2();
350 LogDebug(
"TrackExtenderWithMTD") <<
"Impossible to determine the rechits order" << endl;
363 float& sigmatmtdOut)
const;
366 string dumpLayer(
const DetLayer* layer)
const;
413 template <
class TrackCollection>
418 updateTraj_(iConfig.getParameter<
bool>(
"updateTrackTrajectory")),
419 updateExtra_(iConfig.getParameter<
bool>(
"updateTrackExtra")),
420 updatePattern_(iConfig.getParameter<
bool>(
"updateTrackHitPattern")),
421 mtdRecHitBuilder_(iConfig.getParameter<
std::
string>(
"MTDRecHitBuilder")),
422 propagator_(iConfig.getParameter<
std::
string>(
"Propagator")),
423 transientTrackBuilder_(iConfig.getParameter<
std::
string>(
"TransientTrackBuilder")),
424 estMaxChi2_(iConfig.getParameter<double>(
"estimatorMaxChi2")),
425 estMaxNSigma_(iConfig.getParameter<double>(
"estimatorMaxNSigma")),
426 btlChi2Cut_(iConfig.getParameter<double>(
"btlChi2Cut")),
427 btlTimeChi2Cut_(iConfig.getParameter<double>(
"btlTimeChi2Cut")),
428 etlChi2Cut_(iConfig.getParameter<double>(
"etlChi2Cut")),
429 etlTimeChi2Cut_(iConfig.getParameter<double>(
"etlTimeChi2Cut")),
430 useVertex_(iConfig.getParameter<
bool>(
"useVertex")),
431 useSimVertex_(iConfig.getParameter<
bool>(
"useSimVertex")),
432 dzCut_(iConfig.getParameter<double>(
"dZCut")),
433 bsTimeSpread_(iConfig.getParameter<double>(
"bsTimeSpread")) {
450 tmtdToken = produces<edm::ValueMap<float>>(
"tmtd");
452 pOrigTrkToken = produces<edm::ValueMap<float>>(
"generalTrackp");
454 t0OrigTrkToken = produces<edm::ValueMap<float>>(
"generalTrackt0");
461 produces<edm::OwnVector<TrackingRecHit>>();
462 produces<reco::TrackExtraCollection>();
463 produces<TrackCollection>();
466 template <
class TrackCollection>
475 desc.add<
bool>(
"updateTrackTrajectory",
true);
476 desc.add<
bool>(
"updateTrackExtra",
true);
477 desc.add<
bool>(
"updateTrackHitPattern",
true);
478 desc.add<
std::string>(
"TransientTrackBuilder",
"TransientTrackBuilder");
483 "KFFitterForRefitInsideOut",
484 "KFSmootherForRefitInsideOut",
485 "PropagatorWithMaterialForMTD",
492 desc.add<
double>(
"estimatorMaxChi2", 500.);
493 desc.add<
double>(
"estimatorMaxNSigma", 10.);
494 desc.add<
double>(
"btlChi2Cut", 50.);
495 desc.add<
double>(
"btlTimeChi2Cut", 10.);
496 desc.add<
double>(
"etlChi2Cut", 50.);
497 desc.add<
double>(
"etlTimeChi2Cut", 10.);
498 desc.add<
bool>(
"useVertex",
false);
499 desc.add<
bool>(
"useSimVertex",
false);
500 desc.add<
double>(
"dZCut", 0.1);
501 desc.add<
double>(
"bsTimeSpread", 0.2);
502 descriptions.
add(
"trackExtenderWithMTDBase",
desc);
505 template <
class TrackCollection>
506 template <
class H,
class T>
509 const std::vector<T>& vec,
511 auto out = std::make_unique<edm::ValueMap<T>>();
518 template <
class TrackCollection>
523 theTransformer->setServices(es);
547 auto output = std::make_unique<TrackCollection>();
548 auto extras = std::make_unique<reco::TrackExtraCollection>();
549 auto outhits = std::make_unique<edm::OwnVector<TrackingRecHit>>();
551 std::vector<float> btlMatchChi2;
552 std::vector<float> etlMatchChi2;
553 std::vector<float> btlMatchTimeChi2;
554 std::vector<float> etlMatchTimeChi2;
555 std::vector<float> pathLengthsRaw;
556 std::vector<float> tmtdRaw;
557 std::vector<float> sigmatmtdRaw;
558 std::vector<float> pOrigTrkRaw;
559 std::vector<float> betaOrigTrkRaw;
560 std::vector<float> t0OrigTrkRaw;
561 std::vector<float> sigmat0OrigTrkRaw;
562 std::vector<float> pathLengthsOrigTrkRaw;
563 std::vector<float> tmtdOrigTrkRaw;
564 std::vector<float> sigmatmtdOrigTrkRaw;
565 std::vector<int> assocOrigTrkRaw;
567 auto const tracksH =
ev.getHandle(tracksToken_);
568 const auto&
tracks = *tracksH;
571 const auto&
hits =
ev.get(hitsToken_);
574 const auto&
bs =
ev.get(bsToken_);
577 if (useVertex_ && !useSimVertex_) {
578 auto const& vtxs =
ev.get(vtxToken_);
583 std::unique_ptr<math::XYZTLorentzVectorF> genPV(
nullptr);
584 if (useVertex_ && useSimVertex_) {
585 const auto& genVtxPosition =
ev.get(genVtxPositionToken_);
586 const auto& genVtxTime =
ev.get(genVtxTimeToken_);
587 genPV = std::make_unique<math::XYZTLorentzVectorF>(
588 genVtxPosition.x(), genVtxPosition.y(), genVtxPosition.z(), genVtxTime);
593 if (useSimVertex_ && genPV) {
594 vtxTime = genPV->t();
599 std::vector<unsigned> track_indices;
603 double trackVtxTime = 0.;
612 trackVtxTime = vtxTime;
616 const auto& trajs = theTransformer->transform(
track);
617 auto thits = theTransformer->getTransientRecHits(ttrack);
619 MTDHitMatchingInfo mBTL, mETL;
620 if (!trajs.empty()) {
624 bool tscbl_status = getTrajectoryStateClosestToBeamLine(trajs.front(),
bs, prop, tscbl);
629 trackPathLength(trajs.front(), tscbl, prop, pathlength0);
631 const auto& btlhits = tryBTLLayers(tsos,
643 mtdthits.insert(mtdthits.end(), btlhits.begin(), btlhits.end());
647 const auto& etlhits = tryETLLayers(tsos,
659 mtdthits.insert(mtdthits.end(), etlhits.begin(), etlhits.end());
663 auto ordering = checkRecHitsOrdering(thits);
665 thits.insert(thits.end(), mtdthits.begin(), mtdthits.end());
668 mtdthits.insert(mtdthits.end(), thits.begin(), thits.end());
669 thits.swap(mtdthits);
672 const auto& trajwithmtd = mtdthits.empty() ? trajs : theTransformer->transform(ttrack, thits);
673 float pMap = 0.f, betaMap = 0.f, t0Map = 0.f, sigmat0Map = -1.f, pathLengthMap = -1.f, tmtdMap = 0.f,
677 for (
const auto& trj : trajwithmtd) {
678 const auto& thetrj = (updateTraj_ ? trj : trajs.front());
679 float pathLength = 0.f, tmtd = 0.f, sigmatmtd = -1.f;
686 !trajwithmtd.empty() && !mtdthits.empty(),
694 size_t hitsstart = outhits->size();
695 if (updatePattern_) {
696 t2t(trj, *outhits, trajParams, chi2s);
698 t2t(thetrj, *outhits, trajParams, chi2s);
700 size_t hitsend = outhits->size();
701 extras->push_back(buildTrackExtra(trj));
702 extras->back().setHits(hitsRefProd, hitsstart, hitsend - hitsstart);
703 extras->back().setTrajParams(trajParams, chi2s);
706 btlMatchChi2.push_back(mBTL.hit ? mBTL.estChi2 : -1);
707 etlMatchChi2.push_back(mETL.hit ? mETL.estChi2 : -1);
708 btlMatchTimeChi2.push_back(mBTL.hit ? mBTL.timeChi2 : -1);
709 etlMatchTimeChi2.push_back(mETL.hit ? mETL.timeChi2 : -1);
710 pathLengthsRaw.push_back(pathLength);
711 tmtdRaw.push_back(tmtd);
712 sigmatmtdRaw.push_back(sigmatmtd);
713 pathLengthMap = pathLength;
715 sigmatmtdMap = sigmatmtd;
716 auto& backtrack =
output->back();
717 iMap =
output->size() - 1;
718 pMap = backtrack.p();
719 betaMap = backtrack.beta();
720 t0Map = backtrack.t0();
721 sigmat0Map = std::copysign(
std::sqrt(
std::abs(backtrack.covt0t0())), backtrack.covt0t0());
723 backtrack.setExtra((updateExtra_ ? extraRef :
track.extra()));
724 for (
unsigned ihit = hitsstart; ihit < hitsend; ++ihit) {
725 backtrack.appendHitPattern((*outhits)[ihit], ttopo);
728 LogTrace(
"TrackExtenderWithMTD") <<
"Error in the MTD track refitting. This should not happen";
732 pOrigTrkRaw.push_back(pMap);
733 betaOrigTrkRaw.push_back(betaMap);
734 t0OrigTrkRaw.push_back(t0Map);
735 sigmat0OrigTrkRaw.push_back(sigmat0Map);
736 pathLengthsOrigTrkRaw.push_back(pathLengthMap);
737 tmtdOrigTrkRaw.push_back(tmtdMap);
738 sigmatmtdOrigTrkRaw.push_back(sigmatmtdMap);
739 assocOrigTrkRaw.push_back(iMap);
747 fillValueMap(
ev, outTrksHandle, btlMatchChi2, btlMatchChi2Token);
748 fillValueMap(
ev, outTrksHandle, etlMatchChi2, etlMatchChi2Token);
749 fillValueMap(
ev, outTrksHandle, btlMatchTimeChi2, btlMatchTimeChi2Token);
750 fillValueMap(
ev, outTrksHandle, etlMatchTimeChi2, etlMatchTimeChi2Token);
751 fillValueMap(
ev, outTrksHandle, pathLengthsRaw, pathLengthToken);
752 fillValueMap(
ev, outTrksHandle, tmtdRaw, tmtdToken);
753 fillValueMap(
ev, outTrksHandle, sigmatmtdRaw, sigmatmtdToken);
754 fillValueMap(
ev, tracksH, pOrigTrkRaw, pOrigTrkToken);
755 fillValueMap(
ev, tracksH, betaOrigTrkRaw, betaOrigTrkToken);
756 fillValueMap(
ev, tracksH, t0OrigTrkRaw, t0OrigTrkToken);
757 fillValueMap(
ev, tracksH, sigmat0OrigTrkRaw, sigmat0OrigTrkToken);
758 fillValueMap(
ev, tracksH, pathLengthsOrigTrkRaw, pathLengthOrigTrkToken);
759 fillValueMap(
ev, tracksH, tmtdOrigTrkRaw, tmtdOrigTrkToken);
760 fillValueMap(
ev, tracksH, sigmatmtdOrigTrkRaw, sigmatmtdOrigTrkToken);
761 fillValueMap(
ev, tracksH, assocOrigTrkRaw, assocOrigTrkToken);
765 bool cmp_for_detset(
const unsigned one,
const unsigned two) {
return one <
two; };
772 const double pathlength0,
773 const double vtxTime,
775 const float bsTimeSpread,
778 bool useVtxConstraint,
779 std::set<MTDHitMatchingInfo>&
out) {
783 if (!compDets.empty()) {
784 for (
const auto& detWithState : compDets) {
785 auto range =
hits.equal_range(detWithState.first->geographicalId(), cmp_for_detset);
793 const double tot_pl = pathlength0 +
std::abs(pl.second);
794 const double t_vtx = useVtxConstraint ? vtxTime : 0.;
796 constexpr
double vtx_res = 0.008;
797 const double t_vtx_err = useVtxConstraint ? vtx_res : bsTimeSpread;
799 constexpr
double t_res_manual = 0.035;
801 for (
auto detitr =
range.first; detitr !=
range.second; ++detitr) {
802 for (
const auto&
hit : *detitr) {
803 auto est =
estimator->estimate(detWithState.second,
hit);
807 TrackTofPidInfo tof = computeTrackTofPidInfo(pmag2,
814 MTDHitMatchingInfo mi;
816 mi.estChi2 = est.second;
817 mi.timeChi2 = tof.dtchi2_best;
828 template <
class TrackCollection>
833 const double pathlength0,
839 const double vtxTime,
840 const bool matchVertex,
841 MTDHitMatchingInfo& bestHit)
const {
845 bestHit = MTDHitMatchingInfo();
847 fillMatchingHits(ilay, tsos, traj, pmag2, pathlength0,
hits, prop,
bs, vtxTime, matchVertex,
output, bestHit);
851 template <
class TrackCollection>
856 const double pathlength0,
862 const double vtxTime,
863 const bool matchVertex,
864 MTDHitMatchingInfo& bestHit)
const {
868 bestHit = MTDHitMatchingInfo();
870 const BoundDisk& disk = static_cast<const MTDRingForwardDoubleLayer*>(ilay)->specificSurface();
871 const double diskZ = disk.position().z();
876 fillMatchingHits(ilay, tsos, traj, pmag2, pathlength0,
hits, prop,
bs, vtxTime, matchVertex,
output, bestHit);
881 template <
class TrackCollection>
886 const double pathlength0,
890 const double& vtxTime,
891 const bool matchVertex,
893 MTDHitMatchingInfo& bestHit)
const {
894 std::set<MTDHitMatchingInfo> hitsInLayer;
895 bool hitMatched =
false;
897 using namespace std::placeholders;
898 auto find_hits = std::bind(find_hits_in_dets,
911 std::ref(hitsInLayer));
913 if (useVertex_ && matchVertex)
914 find_hits(vtxTime,
true);
919 if (!hitsInLayer.empty()) {
921 auto const& firstHit = *hitsInLayer.begin();
922 if (firstHit.estChi2 < etlChi2Cut_ && firstHit.timeChi2 < etlTimeChi2Cut_) {
924 output.push_back(hitbuilder_->build(firstHit.hit));
925 if (firstHit < bestHit)
930 if (useVertex_ && matchVertex && !hitMatched) {
934 if (!hitsInLayer.empty()) {
935 auto const& firstHit = *hitsInLayer.begin();
936 if (firstHit.timeChi2 < etlTimeChi2Cut_) {
937 if (firstHit.estChi2 < etlChi2Cut_) {
939 output.push_back(hitbuilder_->build(firstHit.hit));
940 if (firstHit < bestHit)
950 template <
class TrackCollection>
958 float& pathLengthOut,
960 float& sigmatmtdOut)
const {
962 bool tsbcl_status = getTrajectoryStateClosestToBeamLine(traj,
bs, thePropagator, tscbl);
975 double covt0t0 = -1.;
976 pathLengthOut = -1.f;
980 double covbetabeta = -1.;
985 bool validpropagation = trackPathLength(trajWithMtd,
bs, thePropagator, pathlength);
987 double thiterror = -1.;
988 bool validmtd =
false;
996 thit = mtdhit->
time();
1003 if (validmtd && validpropagation) {
1005 TrackTofPidInfo tofInfo = computeTrackTofPidInfo(
p.mag2(), pathlength, thit, thiterror, 0., 0.,
true);
1006 pathLengthOut = pathlength;
1008 sigmatmtdOut = thiterror;
1010 covt0t0 = tofInfo.dterror * tofInfo.dterror;
1011 betaOut = tofInfo.beta_pi;
1012 covbetabeta = tofInfo.betaerror * tofInfo.betaerror;
1030 template <
class TrackCollection>
1032 static const string metname =
"TrackExtenderWithMTD";
1042 unsigned int innerId = 0, outerId = 0;
1065 const GeomDet* outerDet = gtg_->idToDet(outerDetId);
1073 LogTrace(
metname) <<
"The Global Muon outerMostMeasurementState is not compatible with the recHit detector!"
1074 <<
" Setting outerMost postition to recHit position if recHit isValid: "
1075 << outerRecHit->isValid();
1106 template <
class TrackCollection>
1115 if ((bc = dynamic_cast<const BoundCylinder*>(sur))) {
1116 output <<
" Cylinder of radius: " << bc->radius() << endl;
1117 }
else if ((
bd = dynamic_cast<const BoundDisk*>(sur))) {
1118 output <<
" Disk at: " <<
bd->position().z() << endl;