File indexing completed on 2024-04-06 12:28:07
0001
0002
0003
0004
0005
0006
0007
0008 #include "FWCore/Framework/interface/stream/EDProducer.h"
0009
0010 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0011 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0012 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0013 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0014 #include "FWCore/Utilities/interface/ESGetToken.h"
0015
0016 #include "DataFormats/TrackReco/interface/TrackFwd.h"
0017 #include "DataFormats/TrackReco/interface/Track.h"
0018
0019 #include "DataFormats/TrackCandidate/interface/TrackCandidate.h"
0020
0021 #include "TrackingTools/PatternTools/interface/TSCPBuilderNoMaterial.h"
0022 #include "TrackingTools/GeomPropagators/interface/Propagator.h"
0023 #include "TrackingTools/KalmanUpdators/interface/Chi2MeasurementEstimatorBase.h"
0024 #include "TrackMerger.h"
0025
0026 #include "CommonTools/Utils/interface/DynArray.h"
0027 #include <vector>
0028 #include <algorithm>
0029 #include <string>
0030 #include <iostream>
0031 #include <atomic>
0032
0033 #include "CondFormats/GBRForest/interface/GBRForest.h"
0034 #include "CondFormats/DataRecord/interface/GBRWrapperRcd.h"
0035 #include "TrackingTools/Records/interface/TrackingComponentsRecord.h"
0036
0037 using namespace reco;
0038 namespace {
0039 class DuplicateTrackMerger final : public edm::stream::EDProducer<> {
0040 public:
0041
0042 explicit DuplicateTrackMerger(const edm::ParameterSet &iPara);
0043
0044 ~DuplicateTrackMerger() override;
0045
0046 using CandidateToDuplicate = std::vector<std::pair<int, int>>;
0047
0048 static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
0049
0050 private:
0051
0052 void produce(edm::Event &, const edm::EventSetup &) override;
0053
0054 bool checkForDisjointTracks(const reco::Track *t1, const reco::Track *t2, TSCPBuilderNoMaterial &tscpBuilder) const;
0055 bool checkForOverlappingTracks(
0056 const reco::Track *t1, const reco::Track *t2, unsigned int nvh1, unsigned int nvh2, double cosT) const;
0057
0058 private:
0059
0060 const GBRForest *forest_;
0061
0062
0063 std::string dbFileName_;
0064 bool useForestFromDB_;
0065 std::string forestLabel_;
0066
0067 std::string propagatorName_;
0068 std::string chi2EstimatorName_;
0069
0070
0071 edm::EDGetTokenT<reco::TrackCollection> trackSource_;
0072
0073 double minDeltaR3d2_;
0074
0075 double minBDTG_;
0076
0077 double minpT2_;
0078
0079 double minP_;
0080
0081 float maxDCA2_;
0082
0083 float maxDPhi_;
0084
0085 float maxDLambda_;
0086
0087 float maxDdxy_;
0088
0089 float maxDdsz_;
0090
0091 float maxDQoP_;
0092
0093 unsigned int overlapCheckMaxHits_;
0094
0095 unsigned int overlapCheckMaxMissingLayers_;
0096
0097 double overlapCheckMinCosT_;
0098
0099 const MagneticField *magfield_;
0100 const TrackerTopology *ttopo_;
0101 const TrackerGeometry *geom_;
0102 const Propagator *propagator_;
0103 const Chi2MeasurementEstimatorBase *chi2Estimator_;
0104
0105 edm::ESGetToken<GBRForest, GBRWrapperRcd> forestToken_;
0106 edm::ESGetToken<MagneticField, IdealMagneticFieldRecord> magFieldToken_;
0107 edm::ESGetToken<TrackerTopology, TrackerTopologyRcd> trackerTopoToken_;
0108 edm::ESGetToken<TrackerGeometry, TrackerDigiGeometryRecord> geometryToken_;
0109 edm::ESGetToken<Propagator, TrackingComponentsRecord> propagatorToken_;
0110 edm::ESGetToken<Chi2MeasurementEstimatorBase, TrackingComponentsRecord> estimatorToken_;
0111
0112
0113 TrackMerger merger_;
0114
0115 #ifdef EDM_ML_DEBUG
0116 bool debug_;
0117 #endif
0118 };
0119 }
0120
0121 #include "FWCore/Framework/interface/Event.h"
0122 #include "TrackingTools/TrajectoryState/interface/FreeTrajectoryState.h"
0123 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
0124 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
0125 #include "FWCore/Framework/interface/EventSetup.h"
0126 #include "FWCore/Framework/interface/ESHandle.h"
0127 #include "TFile.h"
0128
0129 #include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
0130 #include "DataFormats/TrackerRecHit2D/interface/BaseTrackerRecHit.h"
0131
0132 #include "DuplicateTrackType.h"
0133
0134 namespace {
0135
0136 void DuplicateTrackMerger::fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0137 edm::ParameterSetDescription desc;
0138 desc.add<edm::InputTag>("source", edm::InputTag());
0139 desc.add<double>("minDeltaR3d", -4.0);
0140 desc.add<double>("minBDTG", -0.1);
0141 desc.add<double>("minpT", 0.2);
0142 desc.add<double>("minP", 0.4);
0143 desc.add<double>("maxDCA", 30.0);
0144 desc.add<double>("maxDPhi", 0.30);
0145 desc.add<double>("maxDLambda", 0.30);
0146 desc.add<double>("maxDdsz", 10.0);
0147 desc.add<double>("maxDdxy", 10.0);
0148 desc.add<double>("maxDQoP", 0.25);
0149 desc.add<unsigned>("overlapCheckMaxHits", 4);
0150 desc.add<unsigned>("overlapCheckMaxMissingLayers", 1);
0151 desc.add<double>("overlapCheckMinCosT", 0.99);
0152 desc.add<std::string>("forestLabel", "MVADuplicate");
0153 desc.add<std::string>("GBRForestFileName", "");
0154 desc.add<bool>("useInnermostState", true);
0155 desc.add<std::string>("ttrhBuilderName", "WithAngleAndTemplate");
0156 desc.add<std::string>("propagatorName", "PropagatorWithMaterial");
0157 desc.add<std::string>("chi2EstimatorName", "DuplicateTrackMergerChi2Est");
0158 descriptions.add("DuplicateTrackMerger", desc);
0159 }
0160
0161 DuplicateTrackMerger::DuplicateTrackMerger(const edm::ParameterSet &iPara)
0162 : forest_(nullptr), merger_(iPara, consumesCollector()) {
0163 trackSource_ = consumes<reco::TrackCollection>(iPara.getParameter<edm::InputTag>("source"));
0164 minDeltaR3d2_ = iPara.getParameter<double>("minDeltaR3d");
0165 minDeltaR3d2_ *= std::abs(minDeltaR3d2_);
0166 minBDTG_ = iPara.getParameter<double>("minBDTG");
0167 minpT2_ = iPara.getParameter<double>("minpT");
0168 minpT2_ *= minpT2_;
0169 minP_ = iPara.getParameter<double>("minP");
0170 maxDCA2_ = iPara.getParameter<double>("maxDCA");
0171 maxDCA2_ *= maxDCA2_;
0172 maxDPhi_ = iPara.getParameter<double>("maxDPhi");
0173 maxDLambda_ = iPara.getParameter<double>("maxDLambda");
0174 maxDdsz_ = iPara.getParameter<double>("maxDdsz");
0175 maxDdxy_ = iPara.getParameter<double>("maxDdxy");
0176 maxDQoP_ = iPara.getParameter<double>("maxDQoP");
0177 overlapCheckMaxHits_ = iPara.getParameter<unsigned>("overlapCheckMaxHits");
0178 overlapCheckMaxMissingLayers_ = iPara.getParameter<unsigned>("overlapCheckMaxMissingLayers");
0179 overlapCheckMinCosT_ = iPara.getParameter<double>("overlapCheckMinCosT");
0180
0181 produces<std::vector<TrackCandidate>>("candidates");
0182 produces<CandidateToDuplicate>("candidateMap");
0183
0184 forestLabel_ = iPara.getParameter<std::string>("forestLabel");
0185
0186 dbFileName_ = iPara.getParameter<std::string>("GBRForestFileName");
0187 useForestFromDB_ = dbFileName_.empty();
0188
0189 propagatorName_ = iPara.getParameter<std::string>("propagatorName");
0190 chi2EstimatorName_ = iPara.getParameter<std::string>("chi2EstimatorName");
0191 if (useForestFromDB_) {
0192 forestToken_ = esConsumes<GBRForest, GBRWrapperRcd>(edm::ESInputTag("", forestLabel_));
0193 }
0194 magFieldToken_ = esConsumes<MagneticField, IdealMagneticFieldRecord>();
0195 trackerTopoToken_ = esConsumes<TrackerTopology, TrackerTopologyRcd>();
0196 geometryToken_ = esConsumes<TrackerGeometry, TrackerDigiGeometryRecord>();
0197 propagatorToken_ = esConsumes<Propagator, TrackingComponentsRecord>(edm::ESInputTag("", propagatorName_));
0198 estimatorToken_ =
0199 esConsumes<Chi2MeasurementEstimatorBase, TrackingComponentsRecord>(edm::ESInputTag("", chi2EstimatorName_));
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214 }
0215
0216 DuplicateTrackMerger::~DuplicateTrackMerger() {
0217 if (!useForestFromDB_)
0218 delete forest_;
0219 }
0220
0221 #ifdef VI_STAT
0222 struct Stat {
0223 Stat() : maxCos(1.1), nCand(0), nLoop0(0) {}
0224 ~Stat() { std::cout << "Stats " << nCand << ' ' << nLoop0 << ' ' << maxCos << std::endl; }
0225 std::atomic<float> maxCos;
0226 std::atomic<int> nCand, nLoop0;
0227 };
0228 Stat stat;
0229 #endif
0230
0231 template <typename T>
0232 void update_maximum(std::atomic<T> &maximum_value, T const &value) noexcept {
0233 T prev_value = maximum_value;
0234 while (prev_value < value && !maximum_value.compare_exchange_weak(prev_value, value))
0235 ;
0236 }
0237
0238 template <typename T>
0239 void update_minimum(std::atomic<T> &minimum_value, T const &value) noexcept {
0240 T prev_value = minimum_value;
0241 while (prev_value > value && !minimum_value.compare_exchange_weak(prev_value, value))
0242 ;
0243 }
0244
0245 void DuplicateTrackMerger::produce(edm::Event &iEvent, const edm::EventSetup &iSetup) {
0246 merger_.init(iSetup);
0247
0248 if (!forest_) {
0249 if (useForestFromDB_) {
0250 edm::ESHandle<GBRForest> forestHandle = iSetup.getHandle(forestToken_);
0251 forest_ = forestHandle.product();
0252 } else {
0253 TFile gbrfile(dbFileName_.c_str());
0254 forest_ = dynamic_cast<const GBRForest *>(gbrfile.Get(forestLabel_.c_str()));
0255 }
0256 }
0257
0258
0259 edm::Handle<reco::TrackCollection> handle;
0260 iEvent.getByToken(trackSource_, handle);
0261 auto const &tracks = *handle;
0262
0263 edm::ESHandle<MagneticField> hmagfield = iSetup.getHandle(magFieldToken_);
0264 magfield_ = hmagfield.product();
0265
0266 edm::ESHandle<TrackerTopology> httopo = iSetup.getHandle(trackerTopoToken_);
0267 ttopo_ = httopo.product();
0268
0269 edm::ESHandle<TrackerGeometry> hgeom = iSetup.getHandle(geometryToken_);
0270 geom_ = hgeom.product();
0271
0272 edm::ESHandle<Propagator> hpropagator = iSetup.getHandle(propagatorToken_);
0273 propagator_ = hpropagator.product();
0274
0275 edm::ESHandle<Chi2MeasurementEstimatorBase> hestimator = iSetup.getHandle(estimatorToken_);
0276 chi2Estimator_ = hestimator.product();
0277
0278 TSCPBuilderNoMaterial tscpBuilder;
0279 auto out_duplicateCandidates = std::make_unique<std::vector<TrackCandidate>>();
0280
0281 auto out_candidateMap = std::make_unique<CandidateToDuplicate>();
0282 LogDebug("DuplicateTrackMerger") << "Number of tracks to be checked for merging: " << tracks.size();
0283
0284 #ifdef EDM_ML_DEBUG
0285 auto test = [&](const reco::Track *a, const reco::Track *b) {
0286 const auto ev = iEvent.id().event();
0287 const auto aOriAlgo = a->originalAlgo();
0288 const auto bOriAlgo = b->originalAlgo();
0289 const auto aSeed = a->seedRef().key();
0290 const auto bSeed = b->seedRef().key();
0291 return ((ev == 6903 && ((aOriAlgo == 23 && aSeed == 695 && bOriAlgo == 5 && bSeed == 652) ||
0292 (aOriAlgo == 23 && aSeed == 400 && bOriAlgo == 7 && bSeed == 156) ||
0293 (aOriAlgo == 4 && aSeed == 914 && bOriAlgo == 22 && bSeed == 503) ||
0294 (aOriAlgo == 5 && aSeed == 809 && bOriAlgo == 4 && bSeed == 1030) ||
0295 (aOriAlgo == 23 && aSeed == 749 && bOriAlgo == 5 && bSeed == 659) ||
0296 (aOriAlgo == 4 && aSeed == 1053 && bOriAlgo == 23 && bSeed == 1035) ||
0297 (aOriAlgo == 4 && aSeed == 810 && bOriAlgo == 5 && bSeed == 666) ||
0298 (aOriAlgo == 4 && aSeed == 974 && bOriAlgo == 5 && bSeed == 778))) ||
0299 (ev == 6904 && ((aOriAlgo == 23 && aSeed == 526 && bOriAlgo == 5 && bSeed == 307) ||
0300 (aOriAlgo == 4 && aSeed == 559 && bOriAlgo == 22 && bSeed == 472))) ||
0301 (ev == 6902 && ((aOriAlgo == 4 && aSeed == 750 && bOriAlgo == 22 && bSeed == 340) ||
0302 (aOriAlgo == 4 && aSeed == 906 && bOriAlgo == 5 && bSeed == 609) ||
0303 (aOriAlgo == 4 && aSeed == 724 && bOriAlgo == 5 && bSeed == 528) ||
0304 (aOriAlgo == 4 && aSeed == 943 && bOriAlgo == 23 && bSeed == 739) ||
0305 (aOriAlgo == 8 && aSeed == 2 && bOriAlgo == 9 && bSeed == 2282) ||
0306 (aOriAlgo == 23 && aSeed == 827 && bOriAlgo == 5 && bSeed == 656) ||
0307 (aOriAlgo == 22 && aSeed == 667 && bOriAlgo == 7 && bSeed == 516))));
0308 };
0309 #endif
0310
0311
0312 int nTracks = 0;
0313 declareDynArray(const reco::Track *, tracks.size(), selTracks);
0314 declareDynArray(unsigned int, tracks.size(), nValidHits);
0315 declareDynArray(unsigned int, tracks.size(), oriIndex);
0316 for (auto i = 0U; i < tracks.size(); i++) {
0317 const reco::Track *rt1 = &tracks[i];
0318 if (rt1->innerMomentum().perp2() < minpT2_)
0319 continue;
0320 selTracks[nTracks] = rt1;
0321 nValidHits[nTracks] = rt1->numberOfValidHits();
0322 oriIndex[nTracks] = i;
0323 ++nTracks;
0324 }
0325
0326 for (int i = 0; i < nTracks; i++) {
0327 const reco::Track *rt1 = selTracks[i];
0328 for (int j = i + 1; j < nTracks; j++) {
0329 const reco::Track *rt2 = selTracks[j];
0330
0331 #ifdef EDM_ML_DEBUG
0332 debug_ = false;
0333 if (test(rt1, rt2) || test(rt2, rt1)) {
0334 debug_ = true;
0335 LogTrace("DuplicateTrackMerger")
0336 << "Track1 " << i << " originalAlgo " << rt1->originalAlgo() << " seed " << rt1->seedRef().key() << " pT "
0337 << std::sqrt(rt1->innerMomentum().perp2()) << " charge " << rt1->charge() << " outerPosition2 "
0338 << rt1->outerPosition().perp2() << "\n"
0339 << "Track2 " << j << " originalAlgo " << rt2->originalAlgo() << " seed " << rt2->seedRef().key() << " pT "
0340 << std::sqrt(rt2->innerMomentum().perp2()) << " charge " << rt2->charge() << " outerPosition2 "
0341 << rt2->outerPosition().perp2();
0342 }
0343 #endif
0344
0345 if (rt1->charge() != rt2->charge())
0346 continue;
0347 auto cosT = (*rt1).momentum().Dot((*rt2).momentum());
0348 IfLogTrace(debug_, "DuplicateTrackMerger") << " cosT " << cosT;
0349 if (cosT < 0.)
0350 continue;
0351 cosT /= std::sqrt((*rt1).momentum().Mag2() * (*rt2).momentum().Mag2());
0352
0353 const reco::Track *t1, *t2;
0354 unsigned int nhv1, nhv2;
0355 if (rt1->outerPosition().perp2() < rt2->outerPosition().perp2()) {
0356 t1 = rt1;
0357 nhv1 = nValidHits[i];
0358 t2 = rt2;
0359 nhv2 = nValidHits[j];
0360 } else {
0361 t1 = rt2;
0362 nhv1 = nValidHits[j];
0363 t2 = rt1;
0364 nhv2 = nValidHits[i];
0365 }
0366 auto deltaR3d2 = (t1->outerPosition() - t2->innerPosition()).mag2();
0367
0368 if (t1->outerPosition().perp2() > t2->innerPosition().perp2())
0369 deltaR3d2 *= -1.0;
0370 IfLogTrace(debug_, "DuplicateTrackMerger")
0371 << " deltaR3d2 " << deltaR3d2 << " t1.outerPos2 " << t1->outerPosition().perp2() << " t2.innerPos2 "
0372 << t2->innerPosition().perp2();
0373
0374 bool compatible = false;
0375 DuplicateTrackType duplType;
0376 if (deltaR3d2 >= minDeltaR3d2_) {
0377 compatible = checkForDisjointTracks(t1, t2, tscpBuilder);
0378 duplType = DuplicateTrackType::Disjoint;
0379 } else {
0380 compatible = checkForOverlappingTracks(t1, t2, nhv1, nhv2, cosT);
0381 duplType = DuplicateTrackType::Overlapping;
0382 }
0383 if (!compatible)
0384 continue;
0385
0386 IfLogTrace(debug_, "DuplicateTrackMerger") << " marking as duplicates" << oriIndex[i] << ',' << oriIndex[j];
0387 out_duplicateCandidates->push_back(merger_.merge(*t1, *t2, duplType));
0388 out_candidateMap->emplace_back(oriIndex[i], oriIndex[j]);
0389
0390 #ifdef VI_STAT
0391 ++stat.nCand;
0392
0393 if (cosT > 0)
0394 update_minimum(stat.maxCos, float(cosT));
0395 else
0396 ++stat.nLoop0;
0397 #endif
0398 }
0399 }
0400 iEvent.put(std::move(out_duplicateCandidates), "candidates");
0401 iEvent.put(std::move(out_candidateMap), "candidateMap");
0402 }
0403
0404 bool DuplicateTrackMerger::checkForDisjointTracks(const reco::Track *t1,
0405 const reco::Track *t2,
0406 TSCPBuilderNoMaterial &tscpBuilder) const {
0407 IfLogTrace(debug_, "DuplicateTrackMerger") << " Checking for disjoint duplicates";
0408
0409 FreeTrajectoryState fts1 = trajectoryStateTransform::outerFreeState(*t1, &*magfield_, false);
0410 FreeTrajectoryState fts2 = trajectoryStateTransform::innerFreeState(*t2, &*magfield_, false);
0411 GlobalPoint avgPoint((t1->outerPosition().x() + t2->innerPosition().x()) * 0.5,
0412 (t1->outerPosition().y() + t2->innerPosition().y()) * 0.5,
0413 (t1->outerPosition().z() + t2->innerPosition().z()) * 0.5);
0414 TrajectoryStateClosestToPoint TSCP1 = tscpBuilder(fts1, avgPoint);
0415 TrajectoryStateClosestToPoint TSCP2 = tscpBuilder(fts2, avgPoint);
0416 IfLogTrace(debug_, "DuplicateTrackMerger")
0417 << " TSCP1.isValid " << TSCP1.isValid() << " TSCP2.isValid " << TSCP2.isValid();
0418 if (!TSCP1.isValid())
0419 return false;
0420 if (!TSCP2.isValid())
0421 return false;
0422
0423 const FreeTrajectoryState &ftsn1 = TSCP1.theState();
0424 const FreeTrajectoryState &ftsn2 = TSCP2.theState();
0425
0426 IfLogTrace(debug_, "DuplicateTrackMerger") << " DCA2 " << (ftsn2.position() - ftsn1.position()).mag2();
0427 if ((ftsn2.position() - ftsn1.position()).mag2() > maxDCA2_)
0428 return false;
0429
0430 auto qoverp1 = ftsn1.signedInverseMomentum();
0431 auto qoverp2 = ftsn2.signedInverseMomentum();
0432 float tmva_dqoverp_ = qoverp1 - qoverp2;
0433 IfLogTrace(debug_, "DuplicateTrackMerger") << " dqoverp " << tmva_dqoverp_;
0434 if (std::abs(tmva_dqoverp_) > maxDQoP_)
0435 return false;
0436
0437
0438
0439
0440
0441 float tmva_dlambda_ = ftsn2.momentum().theta() - ftsn1.momentum().theta();
0442 IfLogTrace(debug_, "DuplicateTrackMerger") << " dlambda " << tmva_dlambda_;
0443 if (std::abs(tmva_dlambda_) > maxDLambda_)
0444 return false;
0445
0446 auto phi1 = ftsn1.momentum().phi();
0447 auto phi2 = ftsn2.momentum().phi();
0448 float tmva_dphi_ = phi1 - phi2;
0449 if (std::abs(tmva_dphi_) > float(M_PI))
0450 tmva_dphi_ = 2.f * float(M_PI) - std::abs(tmva_dphi_);
0451 IfLogTrace(debug_, "DuplicateTrackMerger") << " dphi " << tmva_dphi_;
0452 if (std::abs(tmva_dphi_) > maxDPhi_)
0453 return false;
0454
0455 auto dxy1 =
0456 (-ftsn1.position().x() * ftsn1.momentum().y() + ftsn1.position().y() * ftsn1.momentum().x()) / TSCP1.pt();
0457 auto dxy2 =
0458 (-ftsn2.position().x() * ftsn2.momentum().y() + ftsn2.position().y() * ftsn2.momentum().x()) / TSCP2.pt();
0459 float tmva_ddxy_ = dxy1 - dxy2;
0460 IfLogTrace(debug_, "DuplicateTrackMerger") << " ddxy " << tmva_ddxy_;
0461 if (std::abs(tmva_ddxy_) > maxDdxy_)
0462 return false;
0463
0464 auto dsz1 = ftsn1.position().z() * TSCP1.pt() / TSCP1.momentum().mag() -
0465 (ftsn1.position().x() * ftsn1.momentum().y() + ftsn1.position().y() * ftsn1.momentum().x()) /
0466 TSCP1.pt() * ftsn1.momentum().z() / ftsn1.momentum().mag();
0467 auto dsz2 = ftsn2.position().z() * TSCP2.pt() / TSCP2.momentum().mag() -
0468 (ftsn2.position().x() * ftsn2.momentum().y() + ftsn2.position().y() * ftsn2.momentum().x()) /
0469 TSCP2.pt() * ftsn2.momentum().z() / ftsn2.momentum().mag();
0470 float tmva_ddsz_ = dsz1 - dsz2;
0471 IfLogTrace(debug_, "DuplicateTrackMerger") << " ddsz " << tmva_ddsz_;
0472 if (std::abs(tmva_ddsz_) > maxDdsz_)
0473 return false;
0474
0475 float tmva_d3dr_ = avgPoint.perp();
0476 float tmva_d3dz_ = avgPoint.z();
0477 float tmva_outer_nMissingInner_ = t2->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS);
0478 float tmva_inner_nMissingOuter_ = t1->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS);
0479
0480 float gbrVals_[9];
0481 gbrVals_[0] = tmva_ddsz_;
0482 gbrVals_[1] = tmva_ddxy_;
0483 gbrVals_[2] = tmva_dphi_;
0484 gbrVals_[3] = tmva_dlambda_;
0485 gbrVals_[4] = tmva_dqoverp_;
0486 gbrVals_[5] = tmva_d3dr_;
0487 gbrVals_[6] = tmva_d3dz_;
0488 gbrVals_[7] = tmva_outer_nMissingInner_;
0489 gbrVals_[8] = tmva_inner_nMissingOuter_;
0490
0491 auto mvaBDTG = forest_->GetClassifier(gbrVals_);
0492 IfLogTrace(debug_, "DuplicateTrackMerger") << " mvaBDTG " << mvaBDTG;
0493 if (mvaBDTG < minBDTG_)
0494 return false;
0495
0496
0497 return true;
0498 }
0499
0500 bool DuplicateTrackMerger::checkForOverlappingTracks(
0501 const reco::Track *t1, const reco::Track *t2, unsigned int nvh1, unsigned int nvh2, double cosT) const {
0502
0503 if (nvh2 < nvh1) {
0504 std::swap(t1, t2);
0505 std::swap(nvh1, nvh2);
0506 }
0507
0508 IfLogTrace(debug_, "DuplicateTrackMerger")
0509 << " Checking for overlapping duplicates, cosT " << cosT << " t1 hits " << nvh1;
0510 if (cosT < overlapCheckMinCosT_)
0511 return false;
0512 if (nvh1 > overlapCheckMaxHits_)
0513 return false;
0514
0515
0516 auto findHitOnT2 = [&](const TrackingRecHit *hit1) {
0517 const auto hitDet = hit1->geographicalId().det();
0518 const auto hitSubdet = hit1->geographicalId().subdetId();
0519 const auto hitLayer = ttopo_->layer(hit1->geographicalId());
0520 return std::find_if(t2->recHitsBegin(), t2->recHitsEnd(), [&](const TrackingRecHit *hit2) {
0521 const auto &detId = hit2->geographicalId();
0522 return (detId.det() == hitDet && detId.subdetId() == hitSubdet && ttopo_->layer(detId) == hitLayer);
0523 });
0524 };
0525
0526 auto t1HitIter = t1->recHitsBegin();
0527 if (!(*t1HitIter)->isValid()) {
0528 IfLogTrace(debug_, "DuplicateTrackMerger") << " first t1 hit invalid";
0529 return false;
0530 }
0531 auto t2HitIter = findHitOnT2(*t1HitIter);
0532 if (t2HitIter == t2->recHitsEnd()) {
0533
0534
0535 ++t1HitIter;
0536 assert(t1HitIter != t1->recHitsEnd());
0537
0538 if (!(*t1HitIter)->isValid()) {
0539 IfLogTrace(debug_, "DuplicateTrackMerger") << " second t1 hit invalid";
0540 return false;
0541 }
0542 t2HitIter = findHitOnT2(*t1HitIter);
0543 if (t2HitIter == t2->recHitsEnd())
0544 return false;
0545 }
0546 IfLogTrace(debug_, "DuplicateTrackMerger")
0547 << " starting overlap check from t1 hit " << std::distance(t1->recHitsBegin(), t1HitIter) << " t2 hit "
0548 << std::distance(t2->recHitsBegin(), t2HitIter);
0549
0550 auto prevSubdet = (*t1HitIter)->geographicalId().subdetId();
0551 const TrajectoryStateOnSurface tsosInner = trajectoryStateTransform::innerStateOnSurface(*t2, *geom_, magfield_);
0552
0553 ++t1HitIter;
0554 ++t2HitIter;
0555 unsigned int missedLayers = 0;
0556 while (t1HitIter != t1->recHitsEnd() && t2HitIter != t2->recHitsEnd()) {
0557
0558 if ((*t1HitIter)->getType() != TrackingRecHit::valid || trackerHitRTTI::isUndef(**t1HitIter) ||
0559 (*t2HitIter)->getType() != TrackingRecHit::valid || trackerHitRTTI::isUndef(**t2HitIter)) {
0560 IfLogTrace(debug_, "DuplicateTrackMerger")
0561 << " t1 hit " << std::distance(t1->recHitsBegin(), t1HitIter) << " t2 hit "
0562 << std::distance(t2->recHitsBegin(), t2HitIter) << " either is invalid, types t1 "
0563 << (*t1HitIter)->getType() << " t2 " << (*t2HitIter)->getType();
0564 return false;
0565 }
0566
0567 const auto &t1DetId = (*t1HitIter)->geographicalId();
0568 const auto &t2DetId = (*t2HitIter)->geographicalId();
0569
0570 const auto t1Det = t1DetId.det();
0571 const auto t2Det = t2DetId.det();
0572 if (t1Det != DetId::Tracker || t2Det != DetId::Tracker) {
0573 IfLogTrace(debug_, "DuplicateTrackMerger") << " t1 hit " << std::distance(t1->recHitsBegin(), t1HitIter)
0574 << " t2 hit " << std::distance(t2->recHitsBegin(), t2HitIter)
0575 << " either not from Tracker, dets t1 " << t1Det << " t2 " << t2Det;
0576 return false;
0577 }
0578
0579 const auto t1Subdet = t1DetId.subdetId();
0580 const auto t1Layer = ttopo_->layer(t1DetId);
0581
0582
0583 if (t1DetId == t2DetId) {
0584 if (!(*t1HitIter)->sharesInput(*t2HitIter, TrackingRecHit::all)) {
0585 IfLogTrace(debug_, "DuplicateTrackMerger")
0586 << " t1 hit " << std::distance(t1->recHitsBegin(), t1HitIter) << " t2 hit "
0587 << std::distance(t2->recHitsBegin(), t2HitIter) << " same DetId (" << t1DetId.rawId()
0588 << ") but do not share all input";
0589 return false;
0590 }
0591 } else {
0592 const auto t2Subdet = t2DetId.subdetId();
0593 const auto t2Layer = ttopo_->layer(t2DetId);
0594
0595
0596 if (t1Subdet != t2Subdet || t1Layer != t2Layer) {
0597 bool recovered = false;
0598
0599 if (t1Subdet == prevSubdet && t2Subdet != prevSubdet) {
0600
0601 ++t1HitIter;
0602 recovered = true;
0603 } else if (t1Subdet != prevSubdet && t2Subdet == prevSubdet) {
0604
0605 ++t2HitIter;
0606 recovered = true;
0607 } else if (t1Subdet == t2Subdet) {
0608 prevSubdet = t1Subdet;
0609
0610 if (t2Layer > t1Layer) {
0611
0612 ++t1HitIter;
0613 recovered = true;
0614 } else if (t1Layer > t2Layer) {
0615
0616 ++t2HitIter;
0617 recovered = true;
0618 }
0619 }
0620 if (recovered) {
0621 ++missedLayers;
0622 if (missedLayers > overlapCheckMaxMissingLayers_) {
0623 IfLogTrace(debug_, "DuplicateTrackMerger") << " max number of missed layers exceeded";
0624 return false;
0625 }
0626 continue;
0627 }
0628
0629 IfLogTrace(debug_, "DuplicateTrackMerger")
0630 << " t1 hit " << std::distance(t1->recHitsBegin(), t1HitIter) << " t2 hit "
0631 << std::distance(t2->recHitsBegin(), t2HitIter) << " are on different layers (subdet, layer) t1 "
0632 << t1Subdet << "," << t1Layer << " t2 " << t2Subdet << "," << t2Layer;
0633 return false;
0634 }
0635
0636 else if (t1Subdet != PixelSubdetector::PixelBarrel && t1Subdet != PixelSubdetector::PixelEndcap) {
0637 IfLogTrace(debug_, "DuplicateTrackMerger")
0638 << " t1 hit " << std::distance(t1->recHitsBegin(), t1HitIter) << " t2 hit "
0639 << std::distance(t2->recHitsBegin(), t2HitIter) << " are on same layer, but in non-pixel detector (det "
0640 << t1Det << " subdet " << t1Subdet << " layer " << t1Layer << ")";
0641 return false;
0642 }
0643 }
0644
0645
0646 TrajectoryStateOnSurface tsosPropagated = propagator_->propagate(tsosInner, (*t1HitIter)->det()->surface());
0647 if (!tsosPropagated.isValid()) {
0648 IfLogTrace(debug_, "DuplicateTrackMerger")
0649 << " t1 hit " << std::distance(t1->recHitsBegin(), t1HitIter) << " t2 hit "
0650 << std::distance(t2->recHitsBegin(), t2HitIter) << " TSOS not valid";
0651 return false;
0652 }
0653 auto passChi2Pair = chi2Estimator_->estimate(tsosPropagated, **t1HitIter);
0654 if (!passChi2Pair.first) {
0655 IfLogTrace(debug_, "DuplicateTrackMerger")
0656 << " t1 hit " << std::distance(t1->recHitsBegin(), t1HitIter) << " t2 hit "
0657 << std::distance(t2->recHitsBegin(), t2HitIter) << " hit chi2 compatibility failed with chi2 "
0658 << passChi2Pair.second;
0659 return false;
0660 }
0661
0662 prevSubdet = t1Subdet;
0663 ++t1HitIter;
0664 ++t2HitIter;
0665 }
0666 if (t1HitIter != t1->recHitsEnd()) {
0667 IfLogTrace(debug_, "DuplicateTrackMerger") << " hits on t2 ended before hits on t1";
0668 return false;
0669 }
0670
0671 IfLogTrace(debug_, "DuplicateTrackMerger") << " all hits on t2 are on layers whre t1 has also a hit";
0672 return true;
0673 }
0674 }
0675
0676 #include "FWCore/PluginManager/interface/ModuleDef.h"
0677 #include "FWCore/Framework/interface/MakerMacros.h"
0678
0679 DEFINE_FWK_MODULE(DuplicateTrackMerger);