46 using CandidateToDuplicate = std::vector<std::pair<int, int>>;
56 bool checkForOverlappingTracks(
const reco::Track *t1,
const reco::Track *
t2,
unsigned int nvh1,
unsigned int nvh2,
double cosT)
const;
65 bool useForestFromDB_;
94 unsigned int overlapCheckMaxHits_;
96 unsigned int overlapCheckMaxMissingLayers_;
98 double overlapCheckMinCosT_;
138 desc.
add<
double>(
"minDeltaR3d",-4.0);
139 desc.add<
double>(
"minBDTG",-0.1);
140 desc.add<
double>(
"minpT",0.2);
141 desc.add<
double>(
"minP",0.4);
142 desc.add<
double>(
"maxDCA",30.0);
143 desc.add<
double>(
"maxDPhi",0.30);
144 desc.add<
double>(
"maxDLambda",0.30);
145 desc.add<
double>(
"maxDdsz",10.0);
146 desc.add<
double>(
"maxDdxy",10.0);
147 desc.add<
double>(
"maxDQoP",0.25);
148 desc.add<
unsigned>(
"overlapCheckMaxHits", 4);
149 desc.add<
unsigned>(
"overlapCheckMaxMissingLayers", 1);
150 desc.add<
double>(
"overlapCheckMinCosT", 0.99);
151 desc.add<
std::string>(
"forestLabel",
"MVADuplicate");
153 desc.add<
bool>(
"useInnermostState",
true);
154 desc.add<
std::string>(
"ttrhBuilderName",
"WithAngleAndTemplate");
155 desc.add<
std::string>(
"propagatorName",
"PropagatorWithMaterial");
156 desc.add<
std::string>(
"chi2EstimatorName",
"DuplicateTrackMergerChi2Est");
157 descriptions.add(
"DuplicateTrackMerger", desc);
165 minDeltaR3d2_ = iPara.getParameter<
double>(
"minDeltaR3d"); minDeltaR3d2_*=
std::abs(minDeltaR3d2_);
166 minBDTG_ = iPara.getParameter<
double>(
"minBDTG");
167 minpT2_ = iPara.getParameter<
double>(
"minpT"); minpT2_ *= minpT2_;
168 minP_ = iPara.getParameter<
double>(
"minP");
169 maxDCA2_ = iPara.getParameter<
double>(
"maxDCA"); maxDCA2_*=maxDCA2_;
170 maxDPhi_ = iPara.getParameter<
double>(
"maxDPhi");
171 maxDLambda_ = iPara.getParameter<
double>(
"maxDLambda");
172 maxDdsz_ = iPara.getParameter<
double>(
"maxDdsz");
173 maxDdxy_ = iPara.getParameter<
double>(
"maxDdxy");
174 maxDQoP_ = iPara.getParameter<
double>(
"maxDQoP");
175 overlapCheckMaxHits_ = iPara.getParameter<
unsigned>(
"overlapCheckMaxHits");
176 overlapCheckMaxMissingLayers_ = iPara.getParameter<
unsigned>(
"overlapCheckMaxMissingLayers");
177 overlapCheckMinCosT_ = iPara.getParameter<
double>(
"overlapCheckMinCosT");
179 produces<std::vector<TrackCandidate> >(
"candidates");
180 produces<CandidateToDuplicate>(
"candidateMap");
182 forestLabel_ = iPara.getParameter<
std::string>(
"forestLabel");
184 dbFileName_ = iPara.getParameter<
std::string>(
"GBRForestFileName");
185 useForestFromDB_ = dbFileName_.empty();
187 propagatorName_ = iPara.getParameter<
std::string>(
"propagatorName");
188 chi2EstimatorName_ = iPara.getParameter<
std::string>(
"chi2EstimatorName");
207 DuplicateTrackMerger::~DuplicateTrackMerger()
210 if(!useForestFromDB_)
delete forest_;
217 Stat() : maxCos(1.1), nCand(0),nLoop0(0) {}
219 std::cout <<
"Stats " << nCand <<
' ' << nLoop0 <<
' ' << maxCos << std::endl;
221 std::atomic<float> maxCos;
222 std::atomic<int> nCand, nLoop0;
228 void update_maximum(std::atomic<T>& maximum_value,
T const&
value)
noexcept 230 T prev_value = maximum_value;
231 while(prev_value <
value &&
232 !maximum_value.compare_exchange_weak(prev_value,
value))
237 void update_minimum(std::atomic<T>& minimum_value,
T const&
value)
noexcept 239 T prev_value = minimum_value;
240 while(prev_value >
value &&
241 !minimum_value.compare_exchange_weak(prev_value,
value))
249 merger_.init(iSetup);
252 if(useForestFromDB_){
255 forest_ = forestHandle.
product();
257 TFile gbrfile(dbFileName_.c_str());
258 forest_ =
dynamic_cast<const GBRForest*
>(gbrfile.Get(forestLabel_.c_str()));
269 magfield_ = hmagfield.
product();
281 propagator_ = hpropagator.
product();
285 chi2Estimator_ = hestimator.
product();
288 auto out_duplicateCandidates = std::make_unique<std::vector<TrackCandidate>>();
290 auto out_candidateMap = std::make_unique<CandidateToDuplicate>();
291 LogDebug(
"DuplicateTrackMerger") <<
"Number of tracks to be checked for merging: " <<
tracks.size();
297 const auto bOriAlgo =
b->originalAlgo();
299 const auto bSeed =
b->seedRef().key();
300 return ((
ev == 6903 && ((aOriAlgo == 23 && aSeed == 695 && bOriAlgo == 5 && bSeed == 652) ||
301 (aOriAlgo == 23 && aSeed == 400 && bOriAlgo == 7 && bSeed == 156) ||
302 (aOriAlgo == 4 && aSeed == 914 && bOriAlgo == 22 && bSeed == 503) ||
303 (aOriAlgo == 5 && aSeed == 809 && bOriAlgo == 4 && bSeed == 1030) ||
304 (aOriAlgo == 23 && aSeed == 749 && bOriAlgo == 5 && bSeed == 659) ||
305 (aOriAlgo == 4 && aSeed == 1053 && bOriAlgo == 23 && bSeed == 1035) ||
306 (aOriAlgo == 4 && aSeed == 810 && bOriAlgo == 5 && bSeed == 666) ||
307 (aOriAlgo == 4 && aSeed == 974 && bOriAlgo == 5 && bSeed == 778))) ||
308 (
ev == 6904 && ((aOriAlgo == 23 && aSeed == 526 && bOriAlgo == 5 && bSeed == 307) ||
309 (aOriAlgo == 4 && aSeed == 559 && bOriAlgo == 22 && bSeed == 472))) ||
310 (
ev == 6902 && ((aOriAlgo == 4 && aSeed == 750 && bOriAlgo == 22 && bSeed == 340) ||
311 (aOriAlgo == 4 && aSeed == 906 && bOriAlgo == 5 && bSeed == 609) ||
312 (aOriAlgo == 4 && aSeed == 724 && bOriAlgo == 5 && bSeed == 528) ||
313 (aOriAlgo == 4 && aSeed == 943 && bOriAlgo == 23 && bSeed == 739) ||
314 (aOriAlgo == 8 && aSeed == 2 && bOriAlgo == 9 && bSeed == 2282) ||
315 (aOriAlgo == 23 && aSeed == 827 && bOriAlgo == 5 && bSeed == 656) ||
316 (aOriAlgo == 22 && aSeed == 667 && bOriAlgo == 7 && bSeed == 516))));
342 if(
test(rt1, rt2) ||
test(rt2, rt1)) {
350 auto cosT = (*rt1).momentum().Dot((*rt2).momentum());
351 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" cosT " << cosT;
352 if (cosT<0.)
continue;
353 cosT /=
std::sqrt((*rt1).momentum().Mag2()*(*rt2).momentum().Mag2());
357 t1 = rt1; nhv1 = nValidHits[
i];
358 t2 = rt2; nhv2 = nValidHits[j];
360 t1 = rt2; nhv1 = nValidHits[j];
361 t2 = rt1; nhv2 = nValidHits[
i];
363 auto deltaR3d2 = (t1->outerPosition() - t2->innerPosition()).
mag2();
365 if(t1->outerPosition().perp2() > t2->innerPosition().perp2()) deltaR3d2 *= -1.0;
366 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" deltaR3d2 " << deltaR3d2 <<
" t1.outerPos2 " << t1->outerPosition().perp2() <<
" t2.innerPos2 " << t2->innerPosition().perp2();
368 bool compatible =
false;
370 if(deltaR3d2 >= minDeltaR3d2_) {
371 compatible = checkForDisjointTracks(t1, t2, tscpBuilder);
375 compatible = checkForOverlappingTracks(t1, t2, nhv1, nhv2, cosT);
378 if(!compatible)
continue;
381 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" marking as duplicates" << oriIndex[
i]<<
','<<oriIndex[j];
382 out_duplicateCandidates->push_back(merger_.merge(*t1,*t2, duplType));
383 out_candidateMap->emplace_back(oriIndex[
i],oriIndex[j]);
388 if (cosT>0) update_minimum(stat.maxCos,
float(cosT));
394 iEvent.
put(
std::move(out_duplicateCandidates),
"candidates");
402 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" Checking for disjoint duplicates";
411 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" TSCP1.isValid " << TSCP1.
isValid() <<
" TSCP2.isValid " << TSCP2.
isValid();
412 if(!TSCP1.
isValid())
return false;
413 if(!TSCP2.
isValid())
return false;
423 float tmva_dqoverp_ = qoverp1-qoverp2;
424 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" dqoverp " << tmva_dqoverp_;
425 if (
std::abs(tmva_dqoverp_) > maxDQoP_ )
return false;
433 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" dlambda " << tmva_dlambda_;
434 if (
std::abs(tmva_dlambda_) > maxDLambda_ )
return false;
438 float tmva_dphi_ = phi1-phi2;
440 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" dphi " << tmva_dphi_;
441 if (
std::abs(tmva_dphi_) > maxDPhi_ )
return false;
445 float tmva_ddxy_ = dxy1-dxy2;
446 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" ddxy " << tmva_ddxy_;
447 if (
std::abs(tmva_ddxy_) > maxDdxy_ )
return false;
453 float tmva_ddsz_ = dsz1-dsz2;
454 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" ddsz " << tmva_ddsz_;
455 if (
std::abs(tmva_ddsz_) > maxDdsz_ )
return false;
457 float tmva_d3dr_ = avgPoint.perp();
458 float tmva_d3dz_ = avgPoint.z();
463 gbrVals_[0] = tmva_ddsz_;
464 gbrVals_[1] = tmva_ddxy_;
465 gbrVals_[2] = tmva_dphi_;
466 gbrVals_[3] = tmva_dlambda_;
467 gbrVals_[4] = tmva_dqoverp_;
468 gbrVals_[5] = tmva_d3dr_;
469 gbrVals_[6] = tmva_d3dz_;
470 gbrVals_[7] = tmva_outer_nMissingInner_;
471 gbrVals_[8] = tmva_inner_nMissingOuter_;
473 auto mvaBDTG = forest_->GetClassifier(gbrVals_);
474 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" mvaBDTG " << mvaBDTG;
475 if(mvaBDTG < minBDTG_)
return false;
481 bool DuplicateTrackMerger::checkForOverlappingTracks(
const reco::Track *t1,
const reco::Track *t2,
unsigned int nvh1,
unsigned int nvh2,
double cosT)
const {
488 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" Checking for overlapping duplicates, cosT " << cosT <<
" t1 hits " << nvh1;
489 if(cosT < overlapCheckMinCosT_)
return false;
490 if(nvh1 > overlapCheckMaxHits_)
return false;
494 const auto hitDet = hit1->geographicalId().det();
495 const auto hitSubdet = hit1->geographicalId().subdetId();
496 const auto hitLayer = ttopo_->layer(hit1->geographicalId());
498 const auto& detId = hit2->geographicalId();
499 return (detId.det() == hitDet && detId.subdetId() == hitSubdet &&
500 ttopo_->layer(detId) == hitLayer);
505 if(!(*t1HitIter)->isValid()) {
506 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" first t1 hit invalid";
509 auto t2HitIter = findHitOnT2(*t1HitIter);
516 if(!(*t1HitIter)->isValid()) {
517 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" second t1 hit invalid";
520 t2HitIter = findHitOnT2(*t1HitIter);
521 if(t2HitIter == t2->
recHitsEnd())
return false;
526 auto prevSubdet = (*t1HitIter)->geographicalId().subdetId();
529 ++t1HitIter; ++t2HitIter;
530 unsigned int missedLayers = 0;
537 <<
" either is invalid, types t1 " << (*t1HitIter)->getType() <<
" t2 " << (*t2HitIter)->getType();
541 const auto& t1DetId = (*t1HitIter)->geographicalId();
542 const auto& t2DetId = (*t2HitIter)->geographicalId();
544 const auto t1Det = t1DetId.det();
545 const auto t2Det = t2DetId.det();
549 <<
" either not from Tracker, dets t1 " << t1Det <<
" t2 " << t2Det;
553 const auto t1Subdet = t1DetId.subdetId();
554 const auto t1Layer = ttopo_->layer(t1DetId);
557 if(t1DetId == t2DetId) {
561 <<
" same DetId (" << t1DetId.rawId() <<
") but do not share all input";
566 const auto t2Subdet = t2DetId.subdetId();
567 const auto t2Layer = ttopo_->layer(t2DetId);
570 if(t1Subdet != t2Subdet || t1Layer != t2Layer) {
571 bool recovered =
false;
573 if(t1Subdet == prevSubdet && t2Subdet != prevSubdet) {
578 else if(t1Subdet != prevSubdet && t2Subdet == prevSubdet) {
583 else if(t1Subdet == t2Subdet) {
584 prevSubdet = t1Subdet;
586 if(t2Layer > t1Layer) {
591 else if(t1Layer > t2Layer) {
599 if(missedLayers > overlapCheckMaxMissingLayers_) {
600 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" max number of missed layers exceeded";
608 <<
" are on different layers (subdet, layer) t1 " << t1Subdet <<
"," << t1Layer
609 <<
" t2 " << t2Subdet <<
"," << t2Layer;
616 <<
" are on same layer, but in non-pixel detector (det " << t1Det <<
" subdet " << t1Subdet <<
" layer " << t1Layer <<
")";
623 if(!tsosPropagated.
isValid()) {
626 <<
" TSOS not valid";
629 auto passChi2Pair = chi2Estimator_->estimate(tsosPropagated, **t1HitIter);
630 if(!passChi2Pair.first) {
633 <<
" hit chi2 compatibility failed with chi2 " << passChi2Pair.second;
637 prevSubdet = t1Subdet;
638 ++t1HitIter; ++t2HitIter;
641 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" hits on t2 ended before hits on t1";
645 IfLogTrace(debug_,
"DuplicateTrackMerger") <<
" all hits on t2 are on layers whre t1 has also a hit";
const edm::RefToBase< TrajectorySeed > & seedRef() const
T getParameter(std::string const &) const
EventNumber_t event() const
const unsigned int nTracks(const reco::Vertex &sv)
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
bool getByToken(EDGetToken token, Handle< PROD > &result) const
const FreeTrajectoryState & theState() const
#define DEFINE_FWK_MODULE(type)
Geom::Phi< T > phi() const
static void fillDescriptions(ConfigurationDescriptions &descriptions)
#define IfLogTrace(cond, cat)
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
auto const T2 &decltype(t1.eta()) t2
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
const HitPattern & hitPattern() const
Access the hit pattern, indicating in which Tracker layers the track has hits.
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)
double signedInverseMomentum() const
T const * product() const
GlobalVector momentum() const
int numberOfHits(HitCategory category) const
trackingRecHit_iterator recHitsEnd() const
Iterator to last hit on the track.