File indexing completed on 2023-03-17 11:22:19
0001 #include "TrackMerger.h"
0002
0003 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
0004 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
0005
0006 #define TRACK_SORT 1
0007 #define DET_SORT 0
0008 #define HIT_SORT 0
0009
0010 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0011
0012
0013
0014 #ifdef VI_DEBUG
0015 #define DPRINT(x) std::cout << x << ": "
0016 #define PRINT std::cout
0017 #else
0018 #define DPRINT(x) LogTrace(x)
0019 #define PRINT LogTrace("")
0020 #endif
0021
0022 TrackMerger::TrackMerger(const edm::ParameterSet &iConfig, edm::ConsumesCollector cc)
0023 : useInnermostState_(iConfig.getParameter<bool>("useInnermostState")),
0024 debug_(false),
0025 theBuilderName(iConfig.getParameter<std::string>("ttrhBuilderName")),
0026 geometryToken_(cc.esConsumes<TrackerGeometry, TrackerDigiGeometryRecord>()),
0027 magFieldToken_(cc.esConsumes<MagneticField, IdealMagneticFieldRecord>()),
0028 builderToken_(
0029 cc.esConsumes<TransientTrackingRecHitBuilder, TransientRecHitRecord>(edm::ESInputTag("", theBuilderName))),
0030 trackerTopoToken_(cc.esConsumes<TrackerTopology, TrackerTopologyRcd>()) {}
0031
0032 TrackMerger::~TrackMerger() {}
0033
0034 void TrackMerger::init(const edm::EventSetup &iSetup) {
0035 theGeometry = iSetup.getHandle(geometryToken_);
0036 theMagField = iSetup.getHandle(magFieldToken_);
0037 theBuilder = iSetup.getHandle(builderToken_);
0038 theTrkTopo = iSetup.getHandle(trackerTopoToken_);
0039 }
0040
0041 TrackCandidate TrackMerger::merge(const reco::Track &inner,
0042 const reco::Track &outer,
0043 DuplicateTrackType duplicateType) const {
0044 DPRINT("TrackMerger") << std::abs(inner.eta()) << " merging " << inner.algo() << '/' << outer.algo() << ' '
0045 << inner.eta() << '/' << outer.eta() << std::endl;
0046
0047 std::vector<const TrackingRecHit *> hits;
0048 hits.reserve(inner.recHitsSize() + outer.recHitsSize());
0049 DPRINT("TrackMerger") << "Inner track hits: " << std::endl;
0050 for (auto it = inner.recHitsBegin(), ed = inner.recHitsEnd(); it != ed; ++it) {
0051 hits.push_back(&**it);
0052 if (debug_) {
0053 DetId id(hits.back()->geographicalId());
0054 PRINT << " subdet " << id.subdetId() << " layer " << theTrkTopo->layer(id) << " valid "
0055 << hits.back()->isValid() << " detid: " << id() << std::endl;
0056 }
0057 }
0058 DPRINT("TrackMerger") << "Outer track hits: " << std::endl;
0059
0060 if (duplicateType == DuplicateTrackType::Disjoint) {
0061 #if TRACK_SORT
0062 DetId lastId(hits.back()->geographicalId());
0063 int lastSubdet = lastId.subdetId();
0064 unsigned int lastLayer = theTrkTopo->layer(lastId);
0065 for (auto it = outer.recHitsBegin(), ed = outer.recHitsEnd(); it != ed; ++it) {
0066 const TrackingRecHit *hit = &**it;
0067 DetId id(hit->geographicalId());
0068 int thisSubdet = id.subdetId();
0069 if (thisSubdet > lastSubdet || (thisSubdet == lastSubdet && theTrkTopo->layer(id) > lastLayer)) {
0070 hits.push_back(hit);
0071 PRINT << " adding subdet " << id.subdetId() << " layer " << theTrkTopo->layer(id) << " valid "
0072 << hit->isValid() << " detid: " << id() << std::endl;
0073 } else {
0074 PRINT << " skipping subdet " << thisSubdet << " layer " << theTrkTopo->layer(id) << " valid "
0075 << hit->isValid() << " detid: " << id() << std::endl;
0076 }
0077 }
0078 #else
0079 addSecondTrackHits(hits, outer);
0080 #endif
0081 } else if (duplicateType == DuplicateTrackType::Overlapping) {
0082 addSecondTrackHits(hits, outer);
0083 }
0084
0085 math::XYZVector p = (inner.innerMomentum() + outer.outerMomentum());
0086 GlobalVector v(p.x(), p.y(), p.z());
0087 if (!useInnermostState_)
0088 v *= -1;
0089
0090 TrackCandidate::RecHitContainer ownHits;
0091 unsigned int nhits = hits.size();
0092 ownHits.reserve(nhits);
0093
0094 if (duplicateType == DuplicateTrackType::Disjoint) {
0095 #if TRACK_SORT
0096 if (!useInnermostState_)
0097 std::reverse(hits.begin(), hits.end());
0098 for (auto hit : hits)
0099 ownHits.push_back(*hit);
0100 #elif DET_SORT
0101
0102 std::sort(hits.begin(), hits.end(), MomentumSort(v, &*theGeometry));
0103 for (auto hit : hits)
0104 ownHits.push_back(*hit);
0105 #else
0106 sortByHitPosition(v, hits, ownHits);
0107 #endif
0108 } else if (duplicateType == DuplicateTrackType::Overlapping) {
0109 sortByHitPosition(v, hits, ownHits);
0110 }
0111
0112 PTrajectoryStateOnDet state;
0113 PropagationDirection pdir;
0114 if (useInnermostState_) {
0115 pdir = alongMomentum;
0116 if ((inner.outerPosition() - inner.innerPosition()).Dot(inner.momentum()) >= 0) {
0117
0118 TrajectoryStateOnSurface originalTsosIn(
0119 trajectoryStateTransform::innerStateOnSurface(inner, *theGeometry, &*theMagField));
0120 state = trajectoryStateTransform::persistentState(originalTsosIn, DetId(inner.innerDetId()));
0121 } else {
0122
0123 TrajectoryStateOnSurface originalTsosOut(
0124 trajectoryStateTransform::outerStateOnSurface(inner, *theGeometry, &*theMagField));
0125 state = trajectoryStateTransform::persistentState(originalTsosOut, DetId(inner.outerDetId()));
0126 }
0127 } else {
0128 pdir = oppositeToMomentum;
0129 if ((outer.outerPosition() - inner.innerPosition()).Dot(inner.momentum()) >= 0) {
0130
0131 TrajectoryStateOnSurface originalTsosOut(
0132 trajectoryStateTransform::outerStateOnSurface(outer, *theGeometry, &*theMagField));
0133 state = trajectoryStateTransform::persistentState(originalTsosOut, DetId(outer.outerDetId()));
0134 } else {
0135
0136 TrajectoryStateOnSurface originalTsosIn(
0137 trajectoryStateTransform::innerStateOnSurface(outer, *theGeometry, &*theMagField));
0138 state = trajectoryStateTransform::persistentState(originalTsosIn, DetId(outer.innerDetId()));
0139 }
0140 }
0141 TrajectorySeed seed(state, TrackCandidate::RecHitContainer(), pdir);
0142 TrackCandidate ret(ownHits, seed, state, (useInnermostState_ ? inner : outer).seedRef());
0143 ret.setStopReason((uint8_t)(useInnermostState_ ? inner : outer).stopReason());
0144 return ret;
0145 }
0146
0147 void TrackMerger::addSecondTrackHits(std::vector<const TrackingRecHit *> &hits, const reco::Track &outer) const {
0148 size_t nHitsFirstTrack = hits.size();
0149 for (auto it = outer.recHitsBegin(), ed = outer.recHitsEnd(); it != ed; ++it) {
0150 const TrackingRecHit *hit = &**it;
0151 DetId id(hit->geographicalId());
0152 const auto lay = theTrkTopo->layer(id);
0153 bool shared = false;
0154 bool valid = hit->isValid();
0155 PRINT << " subdet " << id.subdetId() << " layer " << theTrkTopo->layer(id) << " valid " << valid
0156 << " detid: " << id() << std::endl;
0157 size_t iHit = 0;
0158 for (auto hit2 : hits) {
0159 ++iHit;
0160 if (iHit > nHitsFirstTrack)
0161 break;
0162 DetId id2 = hit2->geographicalId();
0163 if (id.subdetId() != id2.subdetId())
0164 continue;
0165 if (theTrkTopo->layer(id2) != lay)
0166 continue;
0167 if (hit->sharesInput(hit2, TrackingRecHit::all)) {
0168 PRINT << " discared as duplicate of other hit" << id() << std::endl;
0169 shared = true;
0170 break;
0171 }
0172 if (hit2->isValid() && !valid) {
0173 PRINT << " replacing old invalid hit on detid " << id2() << std::endl;
0174 hit = hit2;
0175 shared = true;
0176 break;
0177 }
0178 PRINT << " discared as additional hit on layer that already contains hit with detid " << id() << std::endl;
0179 shared = true;
0180 break;
0181 }
0182 if (shared)
0183 continue;
0184 hits.push_back(hit);
0185 }
0186 }
0187
0188 void TrackMerger::sortByHitPosition(const GlobalVector &v,
0189 const std::vector<const TrackingRecHit *> &hits,
0190 TrackCandidate::RecHitContainer &ownHits) const {
0191
0192 unsigned int nhits = hits.size();
0193 std::vector<TransientTrackingRecHit::RecHitPointer> ttrh(nhits);
0194 for (unsigned int i = 0; i < nhits; ++i)
0195 ttrh[i] = theBuilder->build(hits[i]);
0196 std::sort(ttrh.begin(), ttrh.end(), GlobalMomentumSort(v));
0197 for (const auto &hit : ttrh)
0198 ownHits.push_back(*hit);
0199 }
0200
0201 bool TrackMerger::MomentumSort::operator()(const TrackingRecHit *hit1, const TrackingRecHit *hit2) const {
0202 const GeomDet *det1 = geom_->idToDet(hit1->geographicalId());
0203 const GeomDet *det2 = geom_->idToDet(hit2->geographicalId());
0204 GlobalPoint p1 = det1->toGlobal(LocalPoint(0, 0, 0));
0205 GlobalPoint p2 = det2->toGlobal(LocalPoint(0, 0, 0));
0206 return (p2 - p1).dot(dir_) > 0;
0207 }
0208
0209 bool TrackMerger::GlobalMomentumSort::operator()(const TransientTrackingRecHit::RecHitPointer &hit1,
0210 const TransientTrackingRecHit::RecHitPointer &hit2) const {
0211 GlobalPoint p1 = hit1->isValid() ? hit1->globalPosition() : hit1->det()->position();
0212 GlobalPoint p2 = hit2->isValid() ? hit2->globalPosition() : hit2->det()->position();
0213 return (p2 - p1).dot(dir_) > 0;
0214 }