31 #include "combination.hpp"
37 #define docast(x, y) dynamic_cast<x>(y)
38 #define LOGVERB(x) edm::LogVerbatim(x)
39 #define LOGWARN(x) edm::LogWarning(x)
40 #define LOGERR(x) edm::LogError(x)
41 #define LOGDRESSED(x) edm::LogInfo(x)
43 #define docast(x, y) static_cast<x>(y)
44 #define LOGVERB(x) LogTrace(x)
45 #define LOGWARN(x) edm::LogWarning(x)
46 #define LOGERR(x) edm::LogError(x)
47 #define LOGDRESSED(x) LogDebug(x)
52 using namespace std::placeholders;
57 typedef std::pair<CaloClusterPtr::key_type, CaloClusterPtr> EEtoPSElement;
60 class SeedMatchesToProtoObject {
65 if (scfromseed_.isNonnull()) {
71 if (scfromseed_.isNull() || !po.
parentSC)
84 template <
bool useConvs = false>
90 const float EoPin_cut = 1.0e6) {
92 auto elemkey = &(
block->elements()[
key]);
94 switch (elemkey->type()) {
98 const ClusterElement* elemasclus = static_cast<const ClusterElement*>(&(
block->elements()[
test]));
99 float cluster_e = elemasclus->clusterRef()->correctedEnergy();
100 float trk_pin = elemasgsf->
Pin().P();
101 if (cluster_e / trk_pin > EoPin_cut) {
102 LOGDRESSED(
"elementNotCloserToOther") <<
"GSF track failed EoP cut to match with cluster!";
110 const ClusterElement* elemasclus = static_cast<const ClusterElement*>(&(
block->elements()[
test]));
111 float cluster_e = elemasclus->clusterRef()->correctedEnergy();
113 if (cluster_e / trk_pin > EoPin_cut) {
114 LOGDRESSED(
"elementNotCloserToOther") <<
"KF track failed EoP cut to match with cluster!";
126 std::multimap<double, unsigned> dists_to_val;
129 for (
const auto& valdist : dists_to_val) {
130 const size_t idx = valdist.second;
136 if (!useConvs && elemasgsf->
trackType(ConvType))
139 const ClusterElement* elemasclus =
docast(
const ClusterElement*, &(
block->elements()[
test]));
140 float cluster_e = elemasclus->clusterRef()->correctedEnergy();
141 float trk_pin = elemasgsf->
Pin().P();
142 if (cluster_e / trk_pin > EoPin_cut)
149 if (!useConvs && elemaskf->
trackType(ConvType))
152 const ClusterElement* elemasclus = static_cast<const ClusterElement*>(&(
block->elements()[
test]));
153 float cluster_e = elemasclus->clusterRef()->correctedEnergy();
155 if (cluster_e / trk_pin > EoPin_cut)
162 if (valdist.first < dist &&
idx !=
key) {
164 <<
"key element of type " << keytype <<
" is closer to another element of type" << valtype << std::endl;
171 template <
class Element1,
class Element2>
172 bool compatibleEoPOut(
const Element1&
e,
const Element2&
comp) {
176 const ClusterElement& elemascluster =
docast(ClusterElement
const&,
e);
177 const float gsf_eta_diff =
std::abs(
comp.positionAtECALEntrance().eta() -
comp.Pout().eta());
179 return (gsf_eta_diff <= 0.3 && cRef->
energy() /
comp.Pout().t() <= 5);
184 template <PFBlockElement::Type keytype, PFBlockElement::Type valtype,
bool useConv = false>
186 struct NotCloserToOther {
189 const float EoPin_cut;
193 bool operator()(
const T&
e) {
194 if (!
e.flag() || valtype !=
e->type())
196 return elementNotCloserToOther<useConv>(
block, keytype,
comp->index(), valtype,
e->index(), EoPin_cut);
200 struct LesserByDistance {
210 dist1 = (dist1 == -1.0 ? 1e6 : dist1);
211 dist2 = (dist2 == -1.0 ? 1e6 : dist2);
212 return dist1 < dist2;
220 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"cannot merge, both have GSFs!" << std::endl;
226 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"cannot merge, different ECAL types!" << std::endl;
235 not_closer = elementNotCloserToOther(blk, cluster->type(), cluster->
index(), primgsf->type(), primgsf->index());
237 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by cluster to primary GSF" << std::endl;
240 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"cluster to primary GSF failed since"
241 <<
" cluster closer to another GSF" << std::endl;
245 not_closer = elementNotCloserToOther(blk, cluster->type(), cluster->
index(), primkf->type(), primkf->index());
247 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by cluster to primary KF" << std::endl;
252 not_closer = elementNotCloserToOther(blk, cluster->type(), cluster->
index(), secdkf->type(), secdkf->index());
254 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by cluster to secondary KF" << std::endl;
259 for (
const auto& brem : RO2.
brems) {
260 not_closer = elementNotCloserToOther(blk, cluster->type(), cluster->
index(), brem->type(), brem->index());
262 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by cluster to brem KF" << std::endl;
270 not_closer = elementNotCloserToOther(blk, primgsf->type(), primgsf->
index(), secdkf->type(), secdkf->index());
272 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by GSF to secondary KF" << std::endl;
280 not_closer = elementNotCloserToOther(blk, primkf->type(), primkf->
index(), secdkf->type(), secdkf->index());
282 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by primary KF to secondary KF" << std::endl;
291 elementNotCloserToOther<true>(blk, secdkf1->type(), secdkf1->
index(), secdkf2->type(), secdkf2->index());
293 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by secondary KF to secondary KF" << std::endl;
302 const bool result = (isROLinkedByClusterOrTrack(
comp, ro) || isROLinkedByClusterOrTrack(ro,
comp));
306 std::vector<const ClusterElement*> getSCAssociatedECALsSafe(
308 std::vector<const ClusterElement*> cluster_list;
309 auto sccl = scref->clustersBegin();
310 auto scend = scref->clustersEnd();
311 auto pfc = ecals.begin();
312 auto pfcend = ecals.end();
313 for (; sccl != scend; ++sccl) {
314 std::vector<const ClusterElement*> matched_pfcs;
315 const double eg_energy = (*sccl)->energy();
317 for (pfc = ecals.begin(); pfc != pfcend; ++pfc) {
318 const ClusterElement* pfcel =
docast(
const ClusterElement*, pfc->get());
322 if (
matched && pfcel->clusterRef()->energy() < 1.2 * scref->energy()) {
323 matched_pfcs.push_back(pfcel);
326 std::sort(matched_pfcs.begin(), matched_pfcs.end());
328 double min_residual = 1e6;
329 std::vector<const ClusterElement*> best_comb;
330 for (
size_t i = 1;
i <= matched_pfcs.size(); ++
i) {
335 double energy = std::accumulate(
336 matched_pfcs.begin(), matched_pfcs.begin() +
i, 0.0, [](
const double a,
const ClusterElement*
c) {
337 return a +
c->clusterRef()->energy();
340 if (resid < min_residual) {
342 best_comb.reserve(
i);
343 min_residual = resid;
344 best_comb.insert(best_comb.begin(), matched_pfcs.begin(), matched_pfcs.begin() +
i);
348 for (
const auto& clelem : best_comb) {
349 if (
std::find(cluster_list.begin(), cluster_list.end(), clelem) == cluster_list.end()) {
350 cluster_list.push_back(clelem);
363 if (clayer == blayer) {
381 *gsfCluster_noassc =
nullptr;
383 int nBremClusters = 0;
389 elementNotCloserToOther(
parent,
gsf->type(),
gsf->index(), cluster->type(), cluster->index());
390 const float deta =
std::abs(cluster->clusterRef()->positionREP().eta() -
gsf->positionAtECALEntrance().eta());
392 TVector2::Phi_mpi_pi(cluster->clusterRef()->positionREP().phi() -
gsf->positionAtECALEntrance().phi()));
393 const float dist = std::hypot(deta, dphi);
394 if (hasclu && dist < mDist_gsf) {
395 gsfCluster = cluster.get();
397 }
else if (dist < mDist_gsf_noassc) {
398 gsfCluster_noassc = cluster.get();
399 mDist_gsf_noassc = dist;
403 const bool hasclu = elementNotCloserToOther(
parent, kf->type(), kf->index(), cluster->type(), cluster->index());
405 if (hasclu && dist < mDist_kf) {
406 kfCluster = cluster.get();
410 for (
const auto& brem : RO.
brems) {
412 elementNotCloserToOther(
parent, brem->type(), brem->index(), cluster->type(), cluster->index());
415 if (!firstBrem || (firstBrem->
indTrajPoint() - 2 > brem->indTrajPoint() - 2)) {
418 if (!lastBrem || (lastBrem->indTrajPoint() - 2 < brem->indTrajPoint() - 2)) {
420 bremCluster = cluster.get();
425 if (!gsfCluster && !kfCluster && !bremCluster) {
426 gsfCluster = gsfCluster_noassc;
432 }
else if (kfCluster) {
435 if (bremCluster && !gsfCluster && !kfCluster) {
440 if (bremCluster == gsfCluster)
452 : gbrForests_(gbrForests),
456 channelStatus_(channelStatus) {
462 unsigned int trackIndex) {
468 const float chi2 =
elements[trackIndex].trackRef()->chi2() /
elements[trackIndex].trackRef()->ndof();
469 const float nlost =
elements[trackIndex].trackRef()->missingInnerHits();
470 const float nLayers =
elements[trackIndex].trackRef()->hitPattern().trackerLayersWithMeasurement();
472 const float stip =
elements[trackIndex].trackRefPF()->STIP();
476 std::multimap<double, unsigned int> ecalAssoTrack;
477 block.associatedElements(
479 std::multimap<double, unsigned int> hcalAssoTrack;
480 block.associatedElements(
482 if (!ecalAssoTrack.empty()) {
483 for (
auto& itecal : ecalAssoTrack) {
484 linkedE = linkedE +
elements[itecal.second].clusterRef()->energy();
487 if (!hcalAssoTrack.empty()) {
488 for (
auto& ithcal : hcalAssoTrack) {
489 linkedH = linkedH +
elements[ithcal.second].clusterRef()->energy();
492 const float eOverPt = linkedE /
elements[trackIndex].trackRef()->pt();
493 const float hOverPt = linkedH /
elements[trackIndex].trackRef()->pt();
495 elements[trackIndex].trackRef()->innerPosition().Y() - primaryVtx.
y(),
496 elements[trackIndex].trackRef()->innerPosition().Z() - primaryVtx.
z());
497 double vtxPhi = rvtx.
phi();
507 switch (pfbe.
type()) {
510 std::multimap<double, unsigned> tks;
513 for (
const auto& tk : tks) {
529 LOGVERB(
"PFEGammaAlgo") <<
"Resetting PFEGammaAlgo for new block and running!" << std::endl;
537 std::list<ProtoEGObject> refinableObjects;
545 LOGVERB(
"PFEGammaAlgo") <<
"Splaying block" << std::endl;
552 const size_t itype = (size_t)pfelement.type();
560 std::stringstream splayout;
561 for (
size_t itype = 0; itype <
_splayedblock.size(); ++itype) {
562 splayout <<
"\tType: " << itype <<
" indices: ";
564 splayout << flaggedelement->index() <<
' ';
567 splayout << std::endl;
569 LOGVERB(
"PFEGammaAlgo") << splayout.str();
577 LOGDRESSED(
"PFEGammaAlgo") <<
"Initialized " << refinableObjects.size() <<
" proto-EGamma objects" << std::endl;
588 for (
auto& RO : refinableObjects) {
603 LOGDRESSED(
"PFEGammaAlgo") <<
"Dumping after GSF and KF Track (Primary) Linking : " << std::endl;
609 LOGDRESSED(
"PFEGammaAlgo") <<
"Dumping after first merging operation : " << std::endl;
615 for (
auto& RO : refinableObjects) {
625 LOGDRESSED(
"PFEGammaAlgo") <<
"Dumping after ECAL to Track (Secondary) Linking : " << std::endl;
631 LOGDRESSED(
"PFEGammaAlgo") <<
"There are " << refinableObjects.size() <<
" after the 2nd merging step." << std::endl;
635 for (
auto& RO : refinableObjects) {
642 std::sort(RO.ecalclusters.begin(), RO.ecalclusters.end(), [](
auto const&
a,
auto const&
b) {
643 return (
a->clusterRef()->correctedEnergy() >
b->clusterRef()->correctedEnergy());
645 setROElectronCluster(RO);
648 LOGDRESSED(
"PFEGammaAlgo") <<
"There are " << refinableObjects.size() <<
" after the unlinking and vetos step."
661 LOGDRESSED(
"PFEGammaAlgo") <<
"creating SC-based proto-object" << std::endl
662 <<
"\tSC at index: " << element->index() <<
" has type: " << element->type()
664 element.setFlag(
false);
687 egobjs.insert(egobjs.end(), fromSC);
695 LOGDRESSED(
"PFEGammaAlgo") <<
"creating GSF-based proto-object" << std::endl
696 <<
"\tGSF at index: " << element->index() <<
" has type: " << element->type()
702 element.setFlag(
false);
715 std::stringstream gsf_err;
716 elementAsGSF->
Dump(gsf_err,
"\t");
718 <<
"Found a GSF track with no seed! This should not happen!" << std::endl
719 << gsf_err.str() << std::endl;
723 element.setFlag(
false);
730 if (dist == 0.001
f) {
732 fromGSF.
brems.push_back(eAsBrem);
743 LOGDRESSED(
"PFEGammaAlgo") <<
"GSF-based proto-object is ECAL driven, merging SC-cand" << std::endl;
747 SeedMatchesToProtoObject sctoseedmatch(fromGSF.
electronSeed);
748 auto objsbegin = egobjs.begin();
749 auto objsend = egobjs.end();
751 auto clusmatch = std::find_if(objsbegin, objsend, sctoseedmatch);
752 if (clusmatch != objsend) {
753 fromGSF.
parentSC = clusmatch->parentSC;
756 egobjs.erase(clusmatch);
761 LOGDRESSED(
"PFEGammaAlgo") <<
"Encountered the known GSF-SC splitting bug "
762 <<
" in PFBlockAlgo! We should really fix this!" << std::endl;
764 std::stringstream gsf_err;
765 elementAsGSF->
Dump(gsf_err,
"\t");
767 <<
"Expected SuperCluster from ECAL driven GSF seed "
768 <<
"was not found in the block!" << std::endl
769 << gsf_err.str() << std::endl;
773 egobjs.insert(egobjs.end(), fromGSF);
780 ecalclusters.clear();
782 LOGVERB(
"PFEGammaAlgo") <<
"Pointer to SC element: 0x" << std::hex << thesc <<
std::dec << std::endl
783 <<
"cleared ecalclusters and ecal2ps!" << std::endl;
788 if (ecalbegin == ecalend && hgcalbegin == hgcalend) {
789 LOGERR(
"PFEGammaAlgo::unwrapSuperCluster()") <<
"There are no ECAL elements in a block with imported SC!"
790 <<
" This is a bug we should fix this!" << std::endl;
797 <<
"SuperCluster pointed to by block element is null!" << std::endl;
799 LOGDRESSED(
"PFEGammaAlgo") <<
"Got a valid super cluster ref! 0x" << std::hex << scref.
get() <<
std::dec << std::endl;
800 const size_t nscclusters = scref->clustersSize();
801 const size_t nscpsclusters = scref->preshowerClustersSize();
802 size_t npfpsclusters = 0;
803 size_t npfclusters = 0;
804 LOGDRESSED(
"PFEGammaAlgo") <<
"Precalculated cluster multiplicities: " << nscclusters <<
' ' << nscpsclusters
806 NotCloserToOther<reco::PFBlockElement::SC, reco::PFBlockElement::ECAL> ecalClustersInSC(
_currentblock, thesc);
807 NotCloserToOther<reco::PFBlockElement::SC, reco::PFBlockElement::HGCAL> hgcalClustersInSC(
_currentblock, thesc);
808 auto ecalfirstnotinsc = std::partition(ecalbegin, ecalend, ecalClustersInSC);
809 auto hgcalfirstnotinsc = std::partition(hgcalbegin, hgcalend, hgcalClustersInSC);
819 std::vector<const ClusterElement*> safePFClusters =
820 is_pf_sc ? std::vector<const ClusterElement*>()
823 if (ecalfirstnotinsc == ecalbegin && hgcalfirstnotinsc == hgcalbegin) {
824 LOGERR(
"PFEGammaAlgo::unwrapSuperCluster()") <<
"No associated block elements to SuperCluster!"
825 <<
" This is a bug we should fix!" << std::endl;
831 if (is_pf_sc && nscclusters != npfclusters) {
832 std::stringstream sc_err;
833 thesc->
Dump(sc_err,
"\t");
835 <<
"The number of found ecal elements (" << nscclusters <<
") in block is not the same as"
836 <<
" the number of ecal PF clusters reported by the PFSuperCluster"
837 <<
" itself (" << npfclusters <<
")! This should not happen!" << std::endl
838 << sc_err.str() << std::endl;
840 for (
auto ecalitr = ecalbegin; ecalitr != ecalfirstnotinsc; ++ecalitr) {
845 if (!is_pf_sc &&
std::find(safePFClusters.begin(), safePFClusters.end(), elemascluster) == safePFClusters.end())
849 ecalclusters.emplace_back(elemascluster,
true);
851 ecalitr->setFlag(
false);
855 auto emplaceresult = ecal2ps.emplace(elemascluster, ClusterMap::mapped_type());
856 if (!emplaceresult.second) {
857 std::stringstream clus_err;
858 elemascluster->
Dump(clus_err,
"\t");
860 <<
"List of pointers to ECAL block elements contains non-unique items!"
861 <<
" This is very bad!" << std::endl
862 <<
"cluster ptr = 0x" << std::hex << elemascluster <<
std::dec << std::endl
863 << clus_err.str() << std::endl;
865 ClusterMap::mapped_type& eslist = emplaceresult.first->second;
869 for (
auto hgcalitr = hgcalbegin; hgcalitr != hgcalfirstnotinsc; ++hgcalitr) {
874 if (!is_pf_sc &&
std::find(safePFClusters.begin(), safePFClusters.end(), elemascluster) == safePFClusters.end())
878 ecalclusters.emplace_back(elemascluster,
true);
880 hgcalitr->setFlag(
false);
897 LOGDRESSED(
"PFEGammaAlgo") <<
" Unwrapped SC has " << npfclusters <<
" ECAL sub-clusters"
898 <<
" and " << npfpsclusters <<
" PreShower layers 1 & 2 clusters!" << std::endl;
906 EEtoPSElement ecalkey(clusptr.
key(), clusptr);
908 std::equal_range(
eetops_.cbegin(),
eetops_.cend(), ecalkey, [](
const EEtoPSElement&
a,
const EEtoPSElement&
b) {
909 return a.first <
b.first;
913 for (
auto pscl = assc_ps.first; pscl != assc_ps.second; ++pscl) {
914 if (pscl->second ==
temp) {
915 const ClusterElement* pstemp =
docast(
const ClusterElement*, ps1.get());
916 eslist.emplace_back(pstemp);
922 for (
auto pscl = assc_ps.first; pscl != assc_ps.second; ++pscl) {
923 if (pscl->second ==
temp) {
924 const ClusterElement* pstemp =
docast(
const ClusterElement*, ps2.get());
925 eslist.emplace_back(pstemp);
929 return eslist.size();
936 <<
"Dumping " << refinableObjects.size() <<
" refinable objects for this block: " << std::endl;
937 for (
const auto& ro : refinableObjects) {
938 std::stringstream
info;
939 info <<
"Refinable Object:" << std::endl;
941 info <<
"\tSuperCluster element attached to object:" << std::endl <<
'\t';
942 ro.parentSC->Dump(
info,
"\t");
945 if (ro.electronSeed.isNonnull()) {
946 info <<
"\tGSF element attached to object:" << std::endl;
947 ro.primaryGSFs.front()->Dump(
info,
"\t");
949 info <<
"firstBrem : " << ro.firstBrem <<
" lateBrem : " << ro.lateBrem
950 <<
" nBrems with cluster : " << ro.nBremsWithClusters << std::endl;
952 if (ro.electronClusters.size() && ro.electronClusters[0]) {
953 info <<
"electron cluster : ";
954 ro.electronClusters[0]->Dump(
info,
"\t");
957 info <<
" no electron cluster." << std::endl;
960 if (ro.primaryKFs.size()) {
961 info <<
"\tPrimary KF tracks attached to object: " << std::endl;
962 for (
const auto& kf : ro.primaryKFs) {
963 kf->Dump(
info,
"\t");
967 if (ro.secondaryKFs.size()) {
968 info <<
"\tSecondary KF tracks attached to object: " << std::endl;
969 for (
const auto& kf : ro.secondaryKFs) {
970 kf->Dump(
info,
"\t");
974 if (ro.brems.size()) {
975 info <<
"\tBrem tangents attached to object: " << std::endl;
976 for (
const auto& brem : ro.brems) {
977 brem->Dump(
info,
"\t");
981 if (ro.ecalclusters.size()) {
982 info <<
"\tECAL clusters attached to object: " << std::endl;
983 for (
const auto& clus : ro.ecalclusters) {
984 clus->Dump(
info,
"\t");
986 if (ro.ecal2ps.find(clus) != ro.ecal2ps.end()) {
987 for (
const auto& psclus : ro.ecal2ps.at(clus)) {
988 info <<
"\t\t Attached PS Cluster: ";
989 psclus->Dump(
info,
"");
1002 typedef std::multimap<double, unsigned> MatchedMap;
1006 MatchedMap matchedGSFs, matchedECALs;
1007 std::unordered_map<GsfTrackElementPtr, MatchedMap> gsf_ecal_cache;
1009 matchedGSFs.clear();
1012 if (matchedGSFs.empty()) {
1016 std::partial_sort(ecalbegin, ecalbegin + 1, ecalend, closestTrackToECAL);
1024 if (dist_sc != -1.0
f) {
1030 if (dist != -1.0
f && closestECAL.flag()) {
1031 bool gsflinked =
false;
1039 if (!gsf_ecal_cache.count(elemasgsf)) {
1040 matchedECALs.clear();
1046 gsf_ecal_cache.emplace(elemasgsf, matchedECALs);
1047 MatchedMap().swap(matchedECALs);
1049 const MatchedMap& ecal_matches = gsf_ecal_cache[elemasgsf];
1050 if (!ecal_matches.empty()) {
1051 if (ecal_matches.begin()->second == closestECAL->index()) {
1057 if (!gsflinked && !inSC) {
1062 const int nexhits = trackref->missingInnerHits();
1063 bool fromprimaryvertex =
false;
1066 fromprimaryvertex =
true;
1072 closestECAL.setFlag(
false);
1083 bool check_for_merge =
true;
1084 while (check_for_merge) {
1089 for (
auto it1 = ROs.begin(); it1 != ROs.end(); ++it1) {
1090 auto find_start = it1;
1092 auto has_merge = std::find_if(find_start, ROs.end(), std::bind(testIfROMergableByLink, _1, *it1));
1093 if (has_merge != ROs.end() && it1 != ROs.begin()) {
1099 auto mergestart = ROs.begin();
1101 auto nomerge = std::partition(mergestart, ROs.end(), std::bind(testIfROMergableByLink, _1, thefront));
1102 if (nomerge != mergestart) {
1103 LOGDRESSED(
"PFEGammaAlgo::mergeROsByAnyLink()")
1104 <<
"Found objects " <<
std::distance(mergestart, nomerge) <<
" to merge by links to the front!" << std::endl;
1105 for (
auto roToMerge = mergestart; roToMerge != nomerge; ++roToMerge) {
1108 if (!thefront.
ecalclusters.empty() && !roToMerge->ecalclusters.empty()) {
1109 if (thefront.
ecalclusters.front()->clusterRef()->layer() !=
1110 roToMerge->ecalclusters.front()->clusterRef()->layer()) {
1111 LOGWARN(
"PFEGammaAlgo::mergeROsByAnyLink") <<
"Tried to merge EB and EE clusters! Skipping!";
1112 ROs.push_back(*roToMerge);
1118 thefront.
ecalclusters.end(), roToMerge->ecalclusters.begin(), roToMerge->ecalclusters.end());
1119 thefront.
ecal2ps.insert(roToMerge->ecal2ps.begin(), roToMerge->ecal2ps.end());
1121 thefront.
secondaryKFs.end(), roToMerge->secondaryKFs.begin(), roToMerge->secondaryKFs.end());
1125 if (!thefront.
parentSC && roToMerge->parentSC) {
1126 thefront.
parentSC = roToMerge->parentSC;
1131 thefront.
primaryGSFs.end(), roToMerge->primaryGSFs.begin(), roToMerge->primaryGSFs.end());
1133 thefront.
primaryKFs.end(), roToMerge->primaryKFs.begin(), roToMerge->primaryKFs.end());
1134 thefront.
brems.insert(thefront.
brems.end(), roToMerge->brems.begin(), roToMerge->brems.end());
1137 thefront.
firstBrem = roToMerge->firstBrem;
1138 thefront.
lateBrem = roToMerge->lateBrem;
1140 LOGDRESSED(
"PFEGammaAlgo::mergeROsByAnyLink")
1141 <<
"Need to implement proper merging of two gsf candidates!" << std::endl;
1144 ROs.erase(mergestart, nomerge);
1146 ROs.push_back(ROs.front());
1149 check_for_merge =
false;
1152 LOGDRESSED(
"PFEGammaAlgo::mergeROsByAnyLink()")
1153 <<
"After merging by links there are: " << ROs.size() <<
" refinable EGamma objects!" << std::endl;
1171 NotCloserToOther<reco::PFBlockElement::GSF, reco::PFBlockElement::TRACK> gsfTrackToKFs(
_currentblock, seedtk);
1173 auto notlinked = std::partition(KFbegin, KFend, gsfTrackToKFs);
1175 for (
auto kft = KFbegin; kft != notlinked; ++kft) {
1180 kft->setFlag(
false);
1183 }
else if (elemaskf->
trackType(convType)) {
1184 kft->setFlag(
false);
1200 if (primkf->trackType(convType)) {
1201 throw cms::Exception(
"PFEGammaAlgo::linkRefinableObjectPrimaryKFsToSecondaryKFs()")
1202 <<
"A KF track from conversion has been assigned as a primary!!" << std::endl;
1204 NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::TRACK, true> kfTrackToKFs(
_currentblock,
1207 auto notlinked = std::partition(KFbegin, KFend, kfTrackToKFs);
1209 for (
auto kft = KFbegin; kft != notlinked; ++kft) {
1214 kft->setFlag(
false);
1231 NotCloserToOther<reco::PFBlockElement::GSF, reco::PFBlockElement::ECAL> gsfTracksToECALs(
_currentblock, primgsf);
1233 auto notmatched_blk = std::partition(ECALbegin, ECALend, gsfTracksToECALs);
1235 std::partition(ECALbegin, notmatched_blk, [&primgsf](
auto const&
x) {
return compatibleEoPOut(*
x, *primgsf); });
1238 notmatched_sc = std::partition(
1239 RO.
ecalclusters.begin(), notmatched_sc, [&primgsf](
auto const&
x) {
return compatibleEoPOut(*
x, *primgsf); });
1244 LOGDRESSED(
"PFEGammaAlgo::linkGSFTracktoECAL()") <<
"Found a cluster already in RO by GSF extrapolation"
1245 <<
" at ECAL surface!" << std::endl
1246 << *elemascluster << std::endl;
1251 for (
auto ecal = ECALbegin;
ecal != notmatched_blk; ++
ecal) {
1253 LOGDRESSED(
"PFEGammaAlgo::linkGSFTracktoECAL()") <<
"Found a cluster not already in RO by GSF extrapolation"
1254 <<
" at ECAL surface!" << std::endl
1255 << *elemascluster << std::endl;
1256 if (addPFClusterToROSafe(elemascluster, RO)) {
1259 ecal->setFlag(
false);
1272 NotCloserToOther<reco::PFBlockElement::GSF, reco::PFBlockElement::HCAL> gsfTracksToHCALs(
_currentblock, primgsf);
1273 auto notmatched = std::partition(HCALbegin, HCALend, gsfTracksToHCALs);
1274 for (
auto hcal = HCALbegin;
hcal != notmatched; ++
hcal) {
1277 LOGDRESSED(
"PFEGammaAlgo::linkGSFTracktoECAL()")
1278 <<
"Found an HCAL cluster associated to GSF extrapolation" << std::endl;
1281 hcal->setFlag(
false);
1297 std::vector<FlaggedPtr<const PFClusterElement>>& currentECAL = RO.
ecalclusters;
1300 NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::ECAL> kfTrackToECALs(
_currentblock, kfflagged);
1301 NotCloserToOther<reco::PFBlockElement::GSF, reco::PFBlockElement::ECAL> kfTrackGSFToECALs(
_currentblock, kfflagged);
1303 auto notmatched_sc = std::partition(currentECAL.begin(), currentECAL.end(), kfTrackToECALs);
1305 notmatched_sc = std::partition(currentECAL.begin(), notmatched_sc, kfTrackGSFToECALs);
1306 for (
auto ecalitr = currentECAL.begin(); ecalitr != notmatched_sc; ++ecalitr) {
1310 LOGDRESSED(
"PFEGammaAlgo::linkKFTracktoECAL()") <<
"Found a cluster already in RO by KF extrapolation"
1311 <<
" at ECAL surface!" << std::endl
1312 << *elemascluster << std::endl;
1316 auto notmatched_blk = std::partition(ECALbegin, ECALend, kfTrackToECALs);
1318 notmatched_blk = std::partition(ECALbegin, notmatched_blk, kfTrackGSFToECALs);
1319 for (
auto ecalitr = ECALbegin; ecalitr != notmatched_blk; ++ecalitr) {
1321 if (addPFClusterToROSafe(elemascluster, RO)) {
1323 ecalitr->setFlag(
false);
1325 LOGDRESSED(
"PFEGammaAlgo::linkKFTracktoECAL()") <<
"Found a cluster not in RO by KF extrapolation"
1326 <<
" at ECAL surface!" << std::endl
1327 << *elemascluster << std::endl;
1334 if (RO.
brems.empty())
1338 int lastBremTrajPos = -1;
1339 for (
auto& brem : RO.
brems) {
1340 bool has_clusters =
false;
1341 TrajPos = (brem->indTrajPoint()) - 2;
1344 NotCloserToOther<reco::PFBlockElement::BREM, reco::PFBlockElement::ECAL> BremToECALs(
_currentblock, brem);
1348 auto notmatched_rsc = std::partition(RSCBegin, RSCEnd, BremToECALs);
1349 for (
auto ecal = RSCBegin;
ecal != notmatched_rsc; ++
ecal) {
1350 float deta =
std::abs((*ecal)->clusterRef()->positionREP().eta() - brem->positionAtECALEntrance().eta());
1352 has_clusters =
true;
1353 if (lastBremTrajPos == -1 || lastBremTrajPos < TrajPos) {
1354 lastBremTrajPos = TrajPos;
1356 if (FirstBrem == -1 || TrajPos < FirstBrem) {
1357 FirstBrem = TrajPos;
1360 LOGDRESSED(
"PFEGammaAlgo::linkBremToECAL()") <<
"Found a cluster already in SC linked to brem extrapolation"
1361 <<
" at ECAL surface!" << std::endl;
1366 auto notmatched_block = std::partition(ECALbegin, ECALend, BremToECALs);
1367 for (
auto ecal = ECALbegin;
ecal != notmatched_block; ++
ecal) {
1368 float deta =
std::abs((*ecal)->clusterRef()->positionREP().eta() - brem->positionAtECALEntrance().eta());
1370 has_clusters =
true;
1371 if (lastBremTrajPos == -1 || lastBremTrajPos < TrajPos) {
1372 lastBremTrajPos = TrajPos;
1374 if (FirstBrem == -1 || TrajPos < FirstBrem) {
1376 FirstBrem = TrajPos;
1380 if (addPFClusterToROSafe(elemasclus, RO)) {
1384 ecal->setFlag(
false);
1385 LOGDRESSED(
"PFEGammaAlgo::linkBremToECAL()") <<
"Found a cluster not already associated by brem extrapolation"
1386 <<
" at ECAL surface!" << std::endl;
1403 auto ronotconv = std::partition(BeginROskfs, EndROskfs, [](
auto const&
x) {
return x->trackType(ConvType); });
1405 for (
size_t idx = 0;
idx < convkfs_end; ++
idx) {
1406 auto const& secKFs =
1408 NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::TRACK, true> TracksToTracks(
_currentblock,
1410 auto notmatched = std::partition(KFbegin, KFend, TracksToTracks);
1411 notmatched = std::partition(KFbegin, notmatched, [](
auto const&
x) {
return x->trackType(ConvType); });
1412 for (
auto kf = KFbegin; kf != notmatched; ++kf) {
1425 NotCloserToOther<reco::PFBlockElement::ECAL, reco::PFBlockElement::TRACK, true> ECALToTracks(
_currentblock,
1427 auto notmatchedkf = std::partition(KFbegin, KFend, ECALToTracks);
1428 auto notconvkf = std::partition(KFbegin, notmatchedkf, [](
auto const&
x) {
return x->trackType(ConvType); });
1430 for (
auto kf = KFbegin; kf != notconvkf; ++kf) {
1437 for (
auto kf = notconvkf; kf != notmatchedkf; ++kf) {
1455 NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::ECAL, false> TracksToECALwithCut(
1457 auto notmatched = std::partition(ECALbegin, ECALend, TracksToECALwithCut);
1458 for (
auto ecal = ECALbegin;
ecal != notmatched; ++
ecal) {
1460 if (addPFClusterToROSafe(elemascluster, RO)) {
1463 ecal->setFlag(
false);
1473 output.candidates.reserve(ROs.size());
1474 output.candidateExtras.reserve(ROs.size());
1475 output.refinedSuperClusters.reserve(ROs.size());
1477 for (
auto& RO : ROs) {
1483 if (!RO.primaryGSFs.empty() || !RO.primaryKFs.empty()) {
1488 if (!RO.primaryKFs.empty()) {
1489 cand.setCharge(RO.primaryKFs[0]->trackRef()->charge());
1491 cand.setTrackRef(RO.primaryKFs[0]->trackRef());
1492 cand.setVertex(RO.primaryKFs[0]->trackRef()->vertex());
1495 if (!RO.primaryGSFs.empty()) {
1496 cand.setCharge(RO.primaryGSFs[0]->GsftrackRef()->chargeMode());
1498 cand.setGsfTrackRef(RO.primaryGSFs[0]->GsftrackRef());
1499 cand.setVertex(RO.primaryGSFs[0]->GsftrackRef()->vertex());
1505 cand.setSuperClusterRef(RO.parentSC->superClusterRef());
1510 for (
const auto& brem : RO.brems) {
1514 for (
const auto&
ecal : RO.ecalclusters) {
1517 if (RO.ecal2ps.count(clus)) {
1518 for (
auto& psclus : RO.ecal2ps.at(clus)) {
1524 for (
const auto& kf : RO.secondaryKFs) {
1527 bool no_conv_ref =
true;
1528 for (
const auto& convref : convrefs) {
1529 if (convref.isNonnull() && convref.isAvailable()) {
1531 no_conv_ref =
false;
1538 const auto& mvavalmapped = RO.singleLegConversionMvaMap.find(kf);
1541 float mvaval = (mvavalmapped != RO.singleLegConversionMvaMap.end()
1542 ? mvavalmapped->second
1553 float trkTime = 0, trkTimeErr = -1;
1554 if (!RO.primaryGSFs.empty() && RO.primaryGSFs[0]->isTimeValid()) {
1555 trkTime = RO.primaryGSFs[0]->time();
1556 trkTimeErr = RO.primaryGSFs[0]->timeError();
1557 }
else if (!RO.primaryKFs.empty() && RO.primaryKFs[0]->isTimeValid()) {
1558 trkTime = RO.primaryKFs[0]->time();
1559 trkTimeErr = RO.primaryKFs[0]->timeError();
1561 if (trkTimeErr >= 0) {
1562 cand.setTime(trkTime, trkTimeErr);
1570 const double scE = the_sc.
energy();
1574 egDir = egDir.Unit();
1577 cand.setPositionAtECALEntrance(ecalPOS_f);
1584 cand.setPositionAtECALEntrance(
gsf->positionAtECALEntrance());
1595 xtra.
setMVA(eleMVAValue);
1596 cand.set_mva_e_pi(eleMVAValue);
1598 output.candidateExtras.push_back(xtra);
1615 constexpr
float mEl = 0.000511;
1616 const double eInGsf = std::hypot(refGsf->pMode(), mEl);
1617 double dEtGsfEcal = 1e6;
1619 const double eneHcalGsf =
1621 return a +
b->clusterRef()->energy();
1626 const double eOutGsf = gsfElement->
Pout().t();
1628 double firstEcalGsfEnergy{0.0};
1629 double otherEcalGsfEnergy{0.0};
1630 double ecalBremEnergy{0.0};
1632 std::vector<const reco::PFCluster*> gsfCluster;
1634 const double cenergy =
ecal->clusterRef()->correctedEnergy();
1637 bool hasbrem =
false;
1638 for (
const auto& brem : ro.
brems) {
1644 ecalBremEnergy += cenergy;
1648 otherEcalGsfEnergy += cenergy;
1650 ecalBremEnergy += cenergy;
1651 if (!(hasgsf || haskf))
1652 otherEcalGsfEnergy += cenergy;
1659 firstEcalGsfEnergy = cref->correctedEnergy();
1660 dEtGsfEcal = cref->positionREP().eta() - etaOutGsf;
1661 gsfCluster.push_back(cref.
get());
1667 float firstBrem{-1.0f};
1668 float earlyBrem{-1.0f};
1669 float lateBrem{-1.0f};
1672 earlyBrem = ro.
firstBrem < 4 ? 1.0f : 0.0f;
1673 lateBrem = ro.
lateBrem == 1 ? 1.0f : 0.0f;
1677 if (firstEcalGsfEnergy > 0.0) {
1678 if (refGsf.isNonnull()) {
1681 const float ptGsf = refGsf->ptMode();
1682 const float etaGsf = refGsf->etaMode();
1684 const double ptModeErrorGsf = refGsf->ptModeError();
1685 float ptModeErrOverPtGsf = (ptModeErrorGsf > 0. ? ptModeErrorGsf / ptGsf : 1.0);
1686 float chi2Gsf = refGsf->normalizedChi2();
1687 float dPtOverPtGsf = (ptGsf - gsfElement->
Pout().pt()) / ptGsf;
1689 float nHitKf = refKf.
isNonnull() ? refKf->hitPattern().trackerLayersWithMeasurement() : 0;
1690 float chi2Kf = refKf.
isNonnull() ? refKf->normalizedChi2() : -0.01;
1693 float eTotPinMode = (firstEcalGsfEnergy + otherEcalGsfEnergy + ecalBremEnergy) / eInGsf;
1694 float eGsfPoutMode = firstEcalGsfEnergy / eOutGsf;
1695 float eTotBremPinPoutMode = (ecalBremEnergy + otherEcalGsfEnergy) / (eInGsf - eOutGsf);
1696 float dEtaGsfEcalClust =
std::abs(dEtGsfEcal);
1698 float hOverHe = eneHcalGsf / (eneHcalGsf + firstEcalGsfEnergy);
1705 dPtOverPtGsf = std::clamp(dPtOverPtGsf, -0.2
f, 1.0
f);
1706 ptModeErrOverPtGsf =
std::min(ptModeErrOverPtGsf, 0.3
f);
1709 eTotPinMode = std::clamp(eTotPinMode, 0.0
f, 5.0
f);
1710 eGsfPoutMode = std::clamp(eGsfPoutMode, 0.0
f, 5.0
f);
1711 eTotBremPinPoutMode = std::clamp(eTotBremPinPoutMode, 0.0
f, 5.0
f);
1712 dEtaGsfEcalClust =
std::min(dEtaGsfEcalClust, 0.1
f);
1713 logSigmaEtaEta =
std::max(logSigmaEtaEta, -14.0
f);
1755 eTotBremPinPoutMode,
1774 NotCloserToOther<reco::PFBlockElement::ECAL, reco::PFBlockElement::TRACK, true> ECALToTracks(
_currentblock,
1776 auto notmatchedkf = std::partition(KFbegin, KFend, ECALToTracks);
1777 auto notconvkf = std::partition(KFbegin, notmatchedkf, [](
auto const&
x) {
return x->trackType(ConvType); });
1779 for (
auto kf = notconvkf; kf != notmatchedkf; ++kf) {
1796 std::vector<const reco::PFCluster*> bare_ptrs;
1798 double posX(0),
posY(0), posZ(0), rawSCEnergy(0), corrSCEnergy(0), corrPSEnergy(0), ps1_energy(0.0), ps2_energy(0.0);
1803 auto clusptr = edm::refToPtr<reco::PFClusterCollection>(clus->clusterRef());
1804 bare_ptrs.push_back(clusptr.get());
1806 const double cluseraw = clusptr->energy();
1807 double cluscalibe = clusptr->correctedEnergy();
1809 posX += cluseraw * cluspos.X();
1810 posY += cluseraw * cluspos.Y();
1811 posZ += cluseraw * cluspos.Z();
1813 if (isEE && RO.
ecal2ps.count(clus.get())) {
1814 const auto& psclusters = RO.
ecal2ps.at(clus.get());
1816 std::vector<reco::PFCluster const*> psClusterPointers;
1817 psClusterPointers.reserve(psclusters.size());
1818 for (
auto const& psc : psclusters) {
1819 psClusterPointers.push_back(psc->clusterRef().get());
1824 ePS1 = calibratedEnergies.ps1Energy;
1825 ePS2 = calibratedEnergies.ps2Energy;
1832 rawSCEnergy += cluseraw;
1833 corrSCEnergy += cluscalibe;
1836 corrPSEnergy += ePS1 + ePS2;
1838 posX /= rawSCEnergy;
1839 posY /= rawSCEnergy;
1840 posZ /= rawSCEnergy;
1845 auto clusptr = edm::refToPtr<reco::PFClusterCollection>(RO.
ecalclusters.front()->clusterRef());
1852 clusptr = edm::refToPtr<reco::PFClusterCollection>(clus->clusterRef());
1854 auto& hits_and_fractions = clusptr->hitsAndFractions();
1855 for (
auto& hit_and_fraction : hits_and_fractions) {
1859 if (RO.
ecal2ps.count(clus.get())) {
1860 const auto& cluspsassociation = RO.
ecal2ps.at(clus.get());
1864 for (
const auto& pscluselem : cluspsassociation) {
1867 auto found_pscluster =
1874 throw cms::Exception(
"PFECALSuperClusterAlgo::buildSuperCluster")
1875 <<
"Found a PS cluster matched to more than one EE cluster!" << std::endl
1876 << std::hex << psclus.
get() <<
" == " << found_pscluster->get() <<
std::dec << std::endl;
1899 const double Pin_gsf = RO.
primaryGSFs.front()->GsftrackRef()->pMode();
1900 const double gsfOuterEta = RO.
primaryGSFs.front()->positionAtECALEntrance().Eta();
1901 double tot_ecal = 0.0;
1902 std::vector<double> min_brem_dists;
1903 std::vector<double> closest_brem_eta;
1906 tot_ecal +=
ecal->clusterRef()->correctedEnergy();
1909 double min_brem_dist = 5000.0;
1910 double eta = -999.0;
1911 for (
const auto& brem : RO.
brems) {
1913 if (dist < min_brem_dist && dist != -1.0
f) {
1914 min_brem_dist = dist;
1915 eta = brem->positionAtECALEntrance().Eta();
1918 min_brem_dists.push_back(min_brem_dist);
1919 closest_brem_eta.push_back(
eta);
1926 const float secpin = (*secd_kf)->trackRef()->p();
1927 bool remove_this_kf =
false;
1930 const float minbremdist = min_brem_dists[bremidx];
1931 const double ecalenergy = (*ecal)->clusterRef()->correctedEnergy();
1932 const double Epin = ecalenergy / secpin;
1933 const double detaGsf =
std::abs(gsfOuterEta - (*ecal)->clusterRef()->positionREP().Eta());
1934 const double detaBrem =
std::abs(closest_brem_eta[bremidx] - (*ecal)->clusterRef()->positionREP().Eta());
1938 const float tkdist =
1944 if (Epin > 3 && kf_matched && tkdist != -1.0
f && tkdist < minbremdist && detaGsf > 0.05 && detaBrem > 0.015) {
1945 double res_with =
std::abs((tot_ecal - Pin_gsf) / Pin_gsf);
1946 double res_without =
std::abs((tot_ecal - ecalenergy - Pin_gsf) / Pin_gsf);
1947 if (res_without < res_with) {
1948 LOGDRESSED(
"PFEGammaAlgo") <<
" REJECTED_RES totenergy " << tot_ecal <<
" Pin_gsf " << Pin_gsf
1949 <<
" cluster to secondary " << ecalenergy <<
" res_with " << res_with
1950 <<
" res_without " << res_without << std::endl;
1951 tot_ecal -= ecalenergy;
1952 remove_this_kf =
true;
1959 if (remove_this_kf) {
1968 bool removeFreeECAL,
1969 bool removeSCEcal) {
1970 std::vector<bool> cluster_in_sc;
1976 bool remove_this_kf =
false;
1977 NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::HCAL> tracksToHCALs(
_currentblock, *secd_kf);
1981 const float secpin = trkRef->p();
1983 for (
auto ecal = ecal_begin;
ecal != ecal_end; ++
ecal) {
1984 const double ecalenergy = (*ecal)->clusterRef()->correctedEnergy();
1987 if (cluster_in_sc.size() < clus_idx + 1) {
1992 cluster_in_sc.push_back(dist != -1.0
f);
2000 auto hcal_matched = std::partition(hcal_begin, hcal_end, tracksToHCALs);
2001 for (
auto hcalclus = hcal_begin; hcalclus != hcal_matched; ++hcalclus) {
2003 const double hcalenergy = clusthcal->
clusterRef()->energy();
2004 const double hpluse = ecalenergy + hcalenergy;
2005 const bool isHoHE = ((hcalenergy / hpluse) > 0.1 &&
goodTrack);
2006 const bool isHoE = (hcalenergy > ecalenergy);
2007 const bool isPoHE = (secpin > hpluse);
2008 if (cluster_in_sc[clus_idx]) {
2009 if (isHoE || isPoHE) {
2010 LOGDRESSED(
"PFEGammaAlgo") <<
"REJECTED TRACK FOR H/E or P/(H+E), CLUSTER IN SC"
2011 <<
" H/H+E " << (hcalenergy / hpluse) <<
" H/E " << (hcalenergy > ecalenergy)
2012 <<
" P/(H+E) " << (secpin / hpluse) <<
" HCAL ENE " << hcalenergy
2013 <<
" ECAL ENE " << ecalenergy <<
" secPIN " << secpin <<
" Algo Track "
2014 << trkRef->algo() << std::endl;
2015 remove_this_kf =
true;
2019 LOGDRESSED(
"PFEGammaAlgo") <<
"REJECTED TRACK FOR H/H+E, CLUSTER NOT IN SC"
2020 <<
" H/H+E " << (hcalenergy / hpluse) <<
" H/E " << (hcalenergy > ecalenergy)
2021 <<
" P/(H+E) " << (secpin / hpluse) <<
" HCAL ENE " << hcalenergy
2022 <<
" ECAL ENE " << ecalenergy <<
" secPIN " << secpin <<
" Algo Track "
2023 << trkRef->algo() << std::endl;
2024 remove_this_kf =
true;
2030 if (remove_this_kf) {
2045 PFRecTrackRef kfPfRef_fromGsf = (*gsfPfRef).kfPFRecTrackRef();
2050 if (kfref == kfref_fromGsf)