46 using CandidateToDuplicate = std::vector<std::pair<int, int>>;
55 bool checkForOverlappingTracks(
64 bool useForestFromDB_;
93 unsigned int overlapCheckMaxHits_;
95 unsigned int overlapCheckMaxMissingLayers_;
97 double overlapCheckMinCosT_;
139 desc.
add<
double>(
"minDeltaR3d", -4.0);
140 desc.add<
double>(
"minBDTG", -0.1);
141 desc.add<
double>(
"minpT", 0.2);
142 desc.add<
double>(
"minP", 0.4);
143 desc.add<
double>(
"maxDCA", 30.0);
144 desc.add<
double>(
"maxDPhi", 0.30);
145 desc.add<
double>(
"maxDLambda", 0.30);
146 desc.add<
double>(
"maxDdsz", 10.0);
147 desc.add<
double>(
"maxDdxy", 10.0);
148 desc.add<
double>(
"maxDQoP", 0.25);
149 desc.add<
unsigned>(
"overlapCheckMaxHits", 4);
150 desc.add<
unsigned>(
"overlapCheckMaxMissingLayers", 1);
151 desc.add<
double>(
"overlapCheckMinCosT", 0.99);
154 desc.add<
bool>(
"useInnermostState",
true);
157 desc.add<
std::string>(
"chi2EstimatorName",
"DuplicateTrackMergerChi2Est");
158 descriptions.add(
"DuplicateTrackMerger",
desc);
162 : forest_(nullptr), merger_(iPara, consumesCollector()) {
164 minDeltaR3d2_ = iPara.getParameter<
double>(
"minDeltaR3d");
165 minDeltaR3d2_ *=
std::abs(minDeltaR3d2_);
166 minBDTG_ = iPara.getParameter<
double>(
"minBDTG");
167 minpT2_ = iPara.getParameter<
double>(
"minpT");
169 minP_ = iPara.getParameter<
double>(
"minP");
170 maxDCA2_ = iPara.getParameter<
double>(
"maxDCA");
171 maxDCA2_ *= maxDCA2_;
172 maxDPhi_ = iPara.getParameter<
double>(
"maxDPhi");
173 maxDLambda_ = iPara.getParameter<
double>(
"maxDLambda");
174 maxDdsz_ = iPara.getParameter<
double>(
"maxDdsz");
175 maxDdxy_ = iPara.getParameter<
double>(
"maxDdxy");
176 maxDQoP_ = iPara.getParameter<
double>(
"maxDQoP");
177 overlapCheckMaxHits_ = iPara.getParameter<
unsigned>(
"overlapCheckMaxHits");
178 overlapCheckMaxMissingLayers_ = iPara.getParameter<
unsigned>(
"overlapCheckMaxMissingLayers");
179 overlapCheckMinCosT_ = iPara.getParameter<
double>(
"overlapCheckMinCosT");
181 produces<std::vector<TrackCandidate>>(
"candidates");
182 produces<CandidateToDuplicate>(
"candidateMap");
184 forestLabel_ = iPara.getParameter<
std::string>(
"forestLabel");
186 dbFileName_ = iPara.getParameter<
std::string>(
"GBRForestFileName");
187 useForestFromDB_ = dbFileName_.empty();
189 propagatorName_ = iPara.getParameter<
std::string>(
"propagatorName");
190 chi2EstimatorName_ = iPara.getParameter<
std::string>(
"chi2EstimatorName");
191 if (useForestFromDB_) {
192 forestToken_ = esConsumes<GBRForest, GBRWrapperRcd>(
edm::ESInputTag(
"", forestLabel_));
194 magFieldToken_ = esConsumes<MagneticField, IdealMagneticFieldRecord>();
195 trackerTopoToken_ = esConsumes<TrackerTopology, TrackerTopologyRcd>();
196 geometryToken_ = esConsumes<TrackerGeometry, TrackerDigiGeometryRecord>();
197 propagatorToken_ = esConsumes<Propagator, TrackingComponentsRecord>(
edm::ESInputTag(
"", propagatorName_));
199 esConsumes<Chi2MeasurementEstimatorBase, TrackingComponentsRecord>(
edm::ESInputTag(
"", chi2EstimatorName_));
216 DuplicateTrackMerger::~DuplicateTrackMerger() {
217 if (!useForestFromDB_)
223 Stat() : maxCos(1.1), nCand(0), nLoop0(0) {}
224 ~Stat() {
std::cout <<
"Stats " << nCand <<
' ' << nLoop0 <<
' ' << maxCos << std::endl; }
225 std::atomic<float> maxCos;
226 std::atomic<int> nCand, nLoop0;
231 template <
typename T>
232 void update_maximum(std::atomic<T> &maximum_value,
T const &
value) noexcept {
233 T prev_value = maximum_value;
234 while (prev_value <
value && !maximum_value.compare_exchange_weak(prev_value,
value))
238 template <
typename T>
239 void update_minimum(std::atomic<T> &minimum_value,
T const &
value) noexcept {
240 T prev_value = minimum_value;
241 while (prev_value >
value && !minimum_value.compare_exchange_weak(prev_value,
value))
246 merger_.init(iSetup);
249 if (useForestFromDB_) {
251 forest_ = forestHandle.
product();
253 TFile gbrfile(dbFileName_.c_str());
254 forest_ =
dynamic_cast<const GBRForest *
>(gbrfile.Get(forestLabel_.c_str()));
264 magfield_ = hmagfield.
product();
273 propagator_ = hpropagator.
product();
276 chi2Estimator_ = hestimator.
product();
279 auto out_duplicateCandidates = std::make_unique<std::vector<TrackCandidate>>();
281 auto out_candidateMap = std::make_unique<CandidateToDuplicate>();
282 LogDebug(
"DuplicateTrackMerger") <<
"Number of tracks to be checked for merging: " <<
tracks.size();
288 const auto bOriAlgo =
b->originalAlgo();
290 const auto bSeed =
b->seedRef().key();
291 return ((
ev == 6903 && ((aOriAlgo == 23 && aSeed == 695 && bOriAlgo == 5 && bSeed == 652) ||
292 (aOriAlgo == 23 && aSeed == 400 && bOriAlgo == 7 && bSeed == 156) ||
293 (aOriAlgo == 4 && aSeed == 914 && bOriAlgo == 22 && bSeed == 503) ||
294 (aOriAlgo == 5 && aSeed == 809 && bOriAlgo == 4 && bSeed == 1030) ||
295 (aOriAlgo == 23 && aSeed == 749 && bOriAlgo == 5 && bSeed == 659) ||
296 (aOriAlgo == 4 && aSeed == 1053 && bOriAlgo == 23 && bSeed == 1035) ||
297 (aOriAlgo == 4 && aSeed == 810 && bOriAlgo == 5 && bSeed == 666) ||
298 (aOriAlgo == 4 && aSeed == 974 && bOriAlgo == 5 && bSeed == 778))) ||
299 (
ev == 6904 && ((aOriAlgo == 23 && aSeed == 526 && bOriAlgo == 5 && bSeed == 307) ||
300 (aOriAlgo == 4 && aSeed == 559 && bOriAlgo == 22 && bSeed == 472))) ||
301 (
ev == 6902 && ((aOriAlgo == 4 && aSeed == 750 && bOriAlgo == 22 && bSeed == 340) ||
302 (aOriAlgo == 4 && aSeed == 906 && bOriAlgo == 5 && bSeed == 609) ||
303 (aOriAlgo == 4 && aSeed == 724 && bOriAlgo == 5 && bSeed == 528) ||
304 (aOriAlgo == 4 && aSeed == 943 && bOriAlgo == 23 && bSeed == 739) ||
305 (aOriAlgo == 8 && aSeed == 2 && bOriAlgo == 9 && bSeed == 2282) ||
306 (aOriAlgo == 23 && aSeed == 827 && bOriAlgo == 5 && bSeed == 656) ||
307 (aOriAlgo == 22 && aSeed == 667 && bOriAlgo == 7 && bSeed == 516))));
316 for (
auto i = 0U;
i <
tracks.size();
i++) {
333 if (
test(rt1, rt2) ||
test(rt2, rt1)) {
347 auto cosT = (*rt1).momentum().Dot((*rt2).momentum());
351 cosT /=
std::sqrt((*rt1).momentum().Mag2() * (*rt2).momentum().Mag2());
354 unsigned int nhv1, nhv2;
357 nhv1 = nValidHits[
i];
359 nhv2 = nValidHits[
j];
362 nhv1 = nValidHits[
j];
364 nhv2 = nValidHits[
i];
366 auto deltaR3d2 = (t1->outerPosition() - t2->innerPosition()).
mag2();
368 if (t1->outerPosition().perp2() > t2->innerPosition().perp2())
371 <<
" deltaR3d2 " << deltaR3d2 <<
" t1.outerPos2 " << t1->outerPosition().perp2() <<
" t2.innerPos2 "
372 << t2->innerPosition().perp2();
374 bool compatible =
false;
376 if (deltaR3d2 >= minDeltaR3d2_) {
377 compatible = checkForDisjointTracks(t1, t2, tscpBuilder);
380 compatible = checkForOverlappingTracks(t1, t2, nhv1, nhv2, cosT);
386 IfLogTrace(
debug_,
"DuplicateTrackMerger") <<
" marking as duplicates" << oriIndex[
i] <<
',' << oriIndex[
j];
387 out_duplicateCandidates->push_back(merger_.merge(*t1, *t2, duplType));
388 out_candidateMap->emplace_back(oriIndex[
i], oriIndex[
j]);
394 update_minimum(stat.maxCos,
float(cosT));
400 iEvent.
put(
std::move(out_duplicateCandidates),
"candidates");
401 iEvent.
put(
std::move(out_candidateMap),
"candidateMap");
404 bool DuplicateTrackMerger::checkForDisjointTracks(
const reco::Track *t1,
407 IfLogTrace(
debug_,
"DuplicateTrackMerger") <<
" Checking for disjoint duplicates";
417 <<
" TSCP1.isValid " << TSCP1.
isValid() <<
" TSCP2.isValid " << TSCP2.
isValid();
432 float tmva_dqoverp_ = qoverp1 - qoverp2;
434 if (
std::abs(tmva_dqoverp_) > maxDQoP_)
443 if (
std::abs(tmva_dlambda_) > maxDLambda_)
448 float tmva_dphi_ = phi1 - phi2;
452 if (
std::abs(tmva_dphi_) > maxDPhi_)
459 float tmva_ddxy_ = dxy1 - dxy2;
461 if (
std::abs(tmva_ddxy_) > maxDdxy_)
470 float tmva_ddsz_ = dsz1 - dsz2;
472 if (
std::abs(tmva_ddsz_) > maxDdsz_)
475 float tmva_d3dr_ = avgPoint.perp();
476 float tmva_d3dz_ = avgPoint.z();
481 gbrVals_[0] = tmva_ddsz_;
482 gbrVals_[1] = tmva_ddxy_;
483 gbrVals_[2] = tmva_dphi_;
484 gbrVals_[3] = tmva_dlambda_;
485 gbrVals_[4] = tmva_dqoverp_;
486 gbrVals_[5] = tmva_d3dr_;
487 gbrVals_[6] = tmva_d3dz_;
488 gbrVals_[7] = tmva_outer_nMissingInner_;
489 gbrVals_[8] = tmva_inner_nMissingOuter_;
491 auto mvaBDTG = forest_->GetClassifier(gbrVals_);
493 if (mvaBDTG < minBDTG_)
500 bool DuplicateTrackMerger::checkForOverlappingTracks(
509 <<
" Checking for overlapping duplicates, cosT " << cosT <<
" t1 hits " << nvh1;
510 if (cosT < overlapCheckMinCosT_)
512 if (nvh1 > overlapCheckMaxHits_)
517 const auto hitDet = hit1->geographicalId().det();
518 const auto hitSubdet = hit1->geographicalId().subdetId();
519 const auto hitLayer = ttopo_->layer(hit1->geographicalId());
521 const auto &detId = hit2->geographicalId();
522 return (detId.det() == hitDet && detId.subdetId() == hitSubdet && ttopo_->layer(detId) == hitLayer);
527 if (!(*t1HitIter)->isValid()) {
531 auto t2HitIter = findHitOnT2(*t1HitIter);
538 if (!(*t1HitIter)->isValid()) {
542 t2HitIter = findHitOnT2(*t1HitIter);
550 auto prevSubdet = (*t1HitIter)->geographicalId().subdetId();
555 unsigned int missedLayers = 0;
563 << (*t1HitIter)->getType() <<
" t2 " << (*t2HitIter)->getType();
567 const auto &t1DetId = (*t1HitIter)->geographicalId();
568 const auto &t2DetId = (*t2HitIter)->geographicalId();
570 const auto t1Det = t1DetId.det();
571 const auto t2Det = t2DetId.det();
575 <<
" either not from Tracker, dets t1 " << t1Det <<
" t2 " << t2Det;
579 const auto t1Subdet = t1DetId.subdetId();
580 const auto t1Layer = ttopo_->layer(t1DetId);
583 if (t1DetId == t2DetId) {
588 <<
") but do not share all input";
592 const auto t2Subdet = t2DetId.subdetId();
593 const auto t2Layer = ttopo_->layer(t2DetId);
596 if (t1Subdet != t2Subdet || t1Layer != t2Layer) {
597 bool recovered =
false;
599 if (t1Subdet == prevSubdet && t2Subdet != prevSubdet) {
603 }
else if (t1Subdet != prevSubdet && t2Subdet == prevSubdet) {
607 }
else if (t1Subdet == t2Subdet) {
608 prevSubdet = t1Subdet;
610 if (t2Layer > t1Layer) {
614 }
else if (t1Layer > t2Layer) {
622 if (missedLayers > overlapCheckMaxMissingLayers_) {
623 IfLogTrace(
debug_,
"DuplicateTrackMerger") <<
" max number of missed layers exceeded";
632 << t1Subdet <<
"," << t1Layer <<
" t2 " << t2Subdet <<
"," << t2Layer;
640 << t1Det <<
" subdet " << t1Subdet <<
" layer " << t1Layer <<
")";
647 if (!tsosPropagated.
isValid()) {
653 auto passChi2Pair = chi2Estimator_->estimate(tsosPropagated, **t1HitIter);
654 if (!passChi2Pair.first) {
658 << passChi2Pair.second;
662 prevSubdet = t1Subdet;
667 IfLogTrace(
debug_,
"DuplicateTrackMerger") <<
" hits on t2 ended before hits on t1";
671 IfLogTrace(
debug_,
"DuplicateTrackMerger") <<
" all hits on t2 are on layers whre t1 has also a hit";
const edm::RefToBase< TrajectorySeed > & seedRef() const
EventNumber_t event() const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
bool getByToken(EDGetToken token, Handle< PROD > &result) const
#define IfLogTrace(cond, cat)
const FreeTrajectoryState & theState() const
#define DEFINE_FWK_MODULE(type)
Geom::Phi< T > phi() const
auto const & tracks
cannot be loose
const math::XYZPoint & outerPosition() const
position of the outermost hit
Geom::Theta< T > theta() const
const math::XYZPoint & innerPosition() const
position of the innermost hit
const SurfaceType & surface() const
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
Abs< T >::type abs(const T &t)
unsigned short numberOfValidHits() const
number of valid hits found
trackingRecHit_iterator recHitsBegin() const
Iterator to first hit on the track.
ParameterDescriptionBase * add(U const &iLabel, T const &value)
GlobalVector momentum() const
GlobalPoint position() const
TrackAlgorithm originalAlgo() const
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
const HitPattern & hitPattern() const
Access the hit pattern, indicating in which Tracker layers the track has hits.
T const * product() const
T getParameter(std::string const &) const
int numberOfLostHits(HitCategory category) const
const math::XYZVector & innerMomentum() const
momentum vector at the innermost hit position
bool isUndef(TrackingRecHit const &hit)
int charge() const
track electric charge
#define declareDynArray(T, n, x)
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
double signedInverseMomentum() const
GlobalVector momentum() const
trackingRecHit_iterator recHitsEnd() const
Iterator to last hit on the track.