30 #include "combination.hpp"
36 #define docast(x, y) dynamic_cast<x>(y)
37 #define LOGVERB(x) edm::LogVerbatim(x)
38 #define LOGWARN(x) edm::LogWarning(x)
39 #define LOGERR(x) edm::LogError(x)
40 #define LOGDRESSED(x) edm::LogInfo(x)
42 #define docast(x, y) reinterpret_cast<x>(y)
43 #define LOGVERB(x) LogTrace(x)
44 #define LOGWARN(x) edm::LogWarning(x)
45 #define LOGERR(x) edm::LogError(x)
46 #define LOGDRESSED(x) LogDebug(x)
51 using namespace std::placeholders;
56 typedef std::pair<CaloClusterPtr::key_type, CaloClusterPtr> EEtoPSElement;
59 class SeedMatchesToProtoObject {
64 if (scfromseed_.isNonnull()) {
70 if (scfromseed_.isNull() || !po.
parentSC)
83 template <
bool useConvs = false>
89 const float EoPin_cut = 1.0e6) {
97 const ClusterElement* elemasclus = reinterpret_cast<const ClusterElement*>(&(
block->elements()[
test]));
98 float cluster_e = elemasclus->clusterRef()->correctedEnergy();
99 float trk_pin = elemasgsf->
Pin().P();
100 if (cluster_e / trk_pin > EoPin_cut) {
101 LOGDRESSED(
"elementNotCloserToOther") <<
"GSF track failed EoP cut to match with cluster!";
109 const ClusterElement* elemasclus = reinterpret_cast<const ClusterElement*>(&(
block->elements()[
test]));
110 float cluster_e = elemasclus->clusterRef()->correctedEnergy();
112 if (cluster_e / trk_pin > EoPin_cut) {
113 LOGDRESSED(
"elementNotCloserToOther") <<
"KF track failed EoP cut to match with cluster!";
125 std::multimap<double, unsigned> dists_to_val;
128 for (
const auto& valdist : dists_to_val) {
129 const size_t idx = valdist.second;
135 if (!useConvs && elemasgsf->
trackType(ConvType))
138 const ClusterElement* elemasclus =
docast(
const ClusterElement*, &(
block->elements()[
test]));
139 float cluster_e = elemasclus->clusterRef()->correctedEnergy();
140 float trk_pin = elemasgsf->
Pin().P();
141 if (cluster_e / trk_pin > EoPin_cut)
148 if (!useConvs && elemaskf->
trackType(ConvType))
151 const ClusterElement* elemasclus = reinterpret_cast<const ClusterElement*>(&(
block->elements()[
test]));
152 float cluster_e = elemasclus->clusterRef()->correctedEnergy();
154 if (cluster_e / trk_pin > EoPin_cut)
161 if (valdist.first < dist &&
idx !=
key) {
163 <<
"key element of type " << keytype <<
" is closer to another element of type" << valtype << std::endl;
170 template <
class Element1,
class Element2>
171 bool compatibleEoPOut(
const Element1&
e,
const Element2&
comp) {
175 const ClusterElement& elemascluster =
docast(ClusterElement
const&,
e);
176 const float gsf_eta_diff =
std::abs(
comp.positionAtECALEntrance().eta() -
comp.Pout().eta());
178 return (gsf_eta_diff <= 0.3 && cRef->
energy() /
comp.Pout().t() <= 5);
183 template <PFBlockElement::Type keytype, PFBlockElement::Type valtype,
bool useConv = false>
185 struct NotCloserToOther {
188 const float EoPin_cut;
192 bool operator()(
const T&
e) {
193 if (!
e.flag() || valtype !=
e->type())
195 return elementNotCloserToOther<useConv>(
block, keytype,
comp->index(), valtype,
e->index(), EoPin_cut);
199 struct LesserByDistance {
209 dist1 = (dist1 == -1.0 ? 1e6 : dist1);
210 dist2 = (dist2 == -1.0 ? 1e6 : dist2);
211 return dist1 < dist2;
219 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"cannot merge, both have GSFs!" << std::endl;
225 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"cannot merge, different ECAL types!" << std::endl;
234 not_closer = elementNotCloserToOther(blk, cluster->type(), cluster->
index(), primgsf->type(), primgsf->index());
236 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by cluster to primary GSF" << std::endl;
239 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"cluster to primary GSF failed since"
240 <<
" cluster closer to another GSF" << std::endl;
244 not_closer = elementNotCloserToOther(blk, cluster->type(), cluster->
index(), primkf->type(), primkf->index());
246 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by cluster to primary KF" << std::endl;
251 not_closer = elementNotCloserToOther(blk, cluster->type(), cluster->
index(), secdkf->type(), secdkf->index());
253 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by cluster to secondary KF" << std::endl;
258 for (
const auto& brem : RO2.
brems) {
259 not_closer = elementNotCloserToOther(blk, cluster->type(), cluster->
index(), brem->type(), brem->index());
261 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by cluster to brem KF" << std::endl;
269 not_closer = elementNotCloserToOther(blk, primgsf->type(), primgsf->
index(), secdkf->type(), secdkf->index());
271 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by GSF to secondary KF" << std::endl;
279 not_closer = elementNotCloserToOther(blk, primkf->type(), primkf->
index(), secdkf->type(), secdkf->index());
281 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by primary KF to secondary KF" << std::endl;
290 elementNotCloserToOther<true>(blk, secdkf1->type(), secdkf1->
index(), secdkf2->type(), secdkf2->index());
292 LOGDRESSED(
"isROLinkedByClusterOrTrack") <<
"merged by secondary KF to secondary KF" << std::endl;
301 const bool result = (isROLinkedByClusterOrTrack(
comp, ro) || isROLinkedByClusterOrTrack(ro,
comp));
305 std::vector<const ClusterElement*> getSCAssociatedECALsSafe(
307 std::vector<const ClusterElement*> cluster_list;
308 auto sccl = scref->clustersBegin();
309 auto scend = scref->clustersEnd();
310 auto pfc = ecals.begin();
311 auto pfcend = ecals.end();
312 for (; sccl != scend; ++sccl) {
313 std::vector<const ClusterElement*> matched_pfcs;
314 const double eg_energy = (*sccl)->energy();
316 for (pfc = ecals.begin(); pfc != pfcend; ++pfc) {
317 const ClusterElement* pfcel =
docast(
const ClusterElement*, pfc->get());
321 if (
matched && pfcel->clusterRef()->energy() < 1.2 * scref->energy()) {
322 matched_pfcs.push_back(pfcel);
325 std::sort(matched_pfcs.begin(), matched_pfcs.end());
327 double min_residual = 1e6;
328 std::vector<const ClusterElement*> best_comb;
329 for (
size_t i = 1;
i <= matched_pfcs.size(); ++
i) {
334 double energy = std::accumulate(
335 matched_pfcs.begin(), matched_pfcs.begin() +
i, 0.0, [](
const double a,
const ClusterElement*
c) {
336 return a +
c->clusterRef()->energy();
339 if (resid < min_residual) {
341 best_comb.reserve(
i);
342 min_residual = resid;
343 best_comb.insert(best_comb.begin(), matched_pfcs.begin(), matched_pfcs.begin() +
i);
347 for (
const auto& clelem : best_comb) {
348 if (
std::find(cluster_list.begin(), cluster_list.end(), clelem) == cluster_list.end()) {
349 cluster_list.push_back(clelem);
362 if (clayer == blayer) {
380 *gsfCluster_noassc =
nullptr;
382 int nBremClusters = 0;
388 elementNotCloserToOther(
parent,
gsf->type(),
gsf->index(), cluster->type(), cluster->index());
389 const float deta =
std::abs(cluster->clusterRef()->positionREP().eta() -
gsf->positionAtECALEntrance().eta());
391 TVector2::Phi_mpi_pi(cluster->clusterRef()->positionREP().phi() -
gsf->positionAtECALEntrance().phi()));
392 const float dist = std::hypot(deta, dphi);
393 if (hasclu && dist < mDist_gsf) {
394 gsfCluster = cluster.get();
396 }
else if (dist < mDist_gsf_noassc) {
397 gsfCluster_noassc = cluster.get();
398 mDist_gsf_noassc = dist;
402 const bool hasclu = elementNotCloserToOther(
parent, kf->type(), kf->index(), cluster->type(), cluster->index());
404 if (hasclu && dist < mDist_kf) {
405 kfCluster = cluster.get();
409 for (
const auto& brem : RO.
brems) {
411 elementNotCloserToOther(
parent, brem->type(), brem->index(), cluster->type(), cluster->index());
414 if (!firstBrem || (firstBrem->
indTrajPoint() - 2 > brem->indTrajPoint() - 2)) {
417 if (!lastBrem || (lastBrem->indTrajPoint() - 2 < brem->indTrajPoint() - 2)) {
419 bremCluster = cluster.get();
424 if (!gsfCluster && !kfCluster && !bremCluster) {
425 gsfCluster = gsfCluster_noassc;
431 }
else if (kfCluster) {
434 if (bremCluster && !gsfCluster && !kfCluster) {
439 if (bremCluster == gsfCluster)
451 : gbrForests_(gbrForests),
455 channelStatus_(channelStatus) {
461 unsigned int trackIndex) {
467 const float chi2 =
elements[trackIndex].trackRef()->chi2() /
elements[trackIndex].trackRef()->ndof();
468 const float nlost =
elements[trackIndex].trackRef()->missingInnerHits();
469 const float nLayers =
elements[trackIndex].trackRef()->hitPattern().trackerLayersWithMeasurement();
471 const float stip =
elements[trackIndex].trackRefPF()->STIP();
475 std::multimap<double, unsigned int> ecalAssoTrack;
476 block.associatedElements(
478 std::multimap<double, unsigned int> hcalAssoTrack;
479 block.associatedElements(
481 if (!ecalAssoTrack.empty()) {
482 for (
auto& itecal : ecalAssoTrack) {
483 linkedE = linkedE +
elements[itecal.second].clusterRef()->energy();
486 if (!hcalAssoTrack.empty()) {
487 for (
auto& ithcal : hcalAssoTrack) {
488 linkedH = linkedH +
elements[ithcal.second].clusterRef()->energy();
491 const float eOverPt = linkedE /
elements[trackIndex].trackRef()->pt();
492 const float hOverPt = linkedH /
elements[trackIndex].trackRef()->pt();
494 elements[trackIndex].trackRef()->innerPosition().Y() - primaryVtx.
y(),
495 elements[trackIndex].trackRef()->innerPosition().Z() - primaryVtx.
z());
496 double vtxPhi = rvtx.
phi();
506 switch (pfbe.
type()) {
509 std::multimap<double, unsigned> tks;
512 for (
const auto& tk : tks) {
528 LOGVERB(
"PFEGammaAlgo") <<
"Resetting PFEGammaAlgo for new block and running!" << std::endl;
536 std::list<ProtoEGObject> refinableObjects;
544 LOGVERB(
"PFEGammaAlgo") <<
"Splaying block" << std::endl;
551 const size_t itype = (size_t)pfelement.type();
559 std::stringstream splayout;
560 for (
size_t itype = 0; itype <
_splayedblock.size(); ++itype) {
561 splayout <<
"\tType: " << itype <<
" indices: ";
563 splayout << flaggedelement->index() <<
' ';
566 splayout << std::endl;
568 LOGVERB(
"PFEGammaAlgo") << splayout.str();
576 LOGDRESSED(
"PFEGammaAlgo") <<
"Initialized " << refinableObjects.size() <<
" proto-EGamma objects" << std::endl;
587 for (
auto& RO : refinableObjects) {
602 LOGDRESSED(
"PFEGammaAlgo") <<
"Dumping after GSF and KF Track (Primary) Linking : " << std::endl;
608 LOGDRESSED(
"PFEGammaAlgo") <<
"Dumping after first merging operation : " << std::endl;
614 for (
auto& RO : refinableObjects) {
624 LOGDRESSED(
"PFEGammaAlgo") <<
"Dumping after ECAL to Track (Secondary) Linking : " << std::endl;
630 LOGDRESSED(
"PFEGammaAlgo") <<
"There are " << refinableObjects.size() <<
" after the 2nd merging step." << std::endl;
634 for (
auto& RO : refinableObjects) {
641 std::sort(RO.ecalclusters.begin(), RO.ecalclusters.end(), [](
auto const&
a,
auto const&
b) {
642 return (
a->clusterRef()->correctedEnergy() >
b->clusterRef()->correctedEnergy());
644 setROElectronCluster(RO);
647 LOGDRESSED(
"PFEGammaAlgo") <<
"There are " << refinableObjects.size() <<
" after the unlinking and vetos step."
660 LOGDRESSED(
"PFEGammaAlgo") <<
"creating SC-based proto-object" << std::endl
661 <<
"\tSC at index: " << element->index() <<
" has type: " << element->type()
663 element.setFlag(
false);
686 egobjs.insert(egobjs.end(), fromSC);
694 LOGDRESSED(
"PFEGammaAlgo") <<
"creating GSF-based proto-object" << std::endl
695 <<
"\tGSF at index: " << element->index() <<
" has type: " << element->type()
701 element.setFlag(
false);
714 std::stringstream gsf_err;
715 elementAsGSF->
Dump(gsf_err,
"\t");
717 <<
"Found a GSF track with no seed! This should not happen!" << std::endl
718 << gsf_err.str() << std::endl;
722 element.setFlag(
false);
729 if (dist == 0.001
f) {
731 fromGSF.
brems.push_back(eAsBrem);
742 LOGDRESSED(
"PFEGammaAlgo") <<
"GSF-based proto-object is ECAL driven, merging SC-cand" << std::endl;
746 SeedMatchesToProtoObject sctoseedmatch(fromGSF.
electronSeed);
747 auto objsbegin = egobjs.begin();
748 auto objsend = egobjs.end();
750 auto clusmatch = std::find_if(objsbegin, objsend, sctoseedmatch);
751 if (clusmatch != objsend) {
752 fromGSF.
parentSC = clusmatch->parentSC;
755 egobjs.erase(clusmatch);
760 LOGDRESSED(
"PFEGammaAlgo") <<
"Encountered the known GSF-SC splitting bug "
761 <<
" in PFBlockAlgo! We should really fix this!" << std::endl;
763 std::stringstream gsf_err;
764 elementAsGSF->
Dump(gsf_err,
"\t");
766 <<
"Expected SuperCluster from ECAL driven GSF seed "
767 <<
"was not found in the block!" << std::endl
768 << gsf_err.str() << std::endl;
772 egobjs.insert(egobjs.end(), fromGSF);
779 ecalclusters.clear();
781 LOGVERB(
"PFEGammaAlgo") <<
"Pointer to SC element: 0x" << std::hex << thesc <<
std::dec << std::endl
782 <<
"cleared ecalclusters and ecal2ps!" << std::endl;
787 if (ecalbegin == ecalend && hgcalbegin == hgcalend) {
788 LOGERR(
"PFEGammaAlgo::unwrapSuperCluster()") <<
"There are no ECAL elements in a block with imported SC!"
789 <<
" This is a bug we should fix this!" << std::endl;
796 <<
"SuperCluster pointed to by block element is null!" << std::endl;
798 LOGDRESSED(
"PFEGammaAlgo") <<
"Got a valid super cluster ref! 0x" << std::hex << scref.
get() <<
std::dec << std::endl;
799 const size_t nscclusters = scref->clustersSize();
800 const size_t nscpsclusters = scref->preshowerClustersSize();
801 size_t npfpsclusters = 0;
802 size_t npfclusters = 0;
803 LOGDRESSED(
"PFEGammaAlgo") <<
"Precalculated cluster multiplicities: " << nscclusters <<
' ' << nscpsclusters
805 NotCloserToOther<reco::PFBlockElement::SC, reco::PFBlockElement::ECAL> ecalClustersInSC(
_currentblock, thesc);
806 NotCloserToOther<reco::PFBlockElement::SC, reco::PFBlockElement::HGCAL> hgcalClustersInSC(
_currentblock, thesc);
807 auto ecalfirstnotinsc = std::partition(ecalbegin, ecalend, ecalClustersInSC);
808 auto hgcalfirstnotinsc = std::partition(hgcalbegin, hgcalend, hgcalClustersInSC);
818 std::vector<const ClusterElement*> safePFClusters =
819 is_pf_sc ? std::vector<const ClusterElement*>()
822 if (ecalfirstnotinsc == ecalbegin && hgcalfirstnotinsc == hgcalbegin) {
823 LOGERR(
"PFEGammaAlgo::unwrapSuperCluster()") <<
"No associated block elements to SuperCluster!"
824 <<
" This is a bug we should fix!" << std::endl;
830 if (is_pf_sc && nscclusters != npfclusters) {
831 std::stringstream sc_err;
832 thesc->
Dump(sc_err,
"\t");
834 <<
"The number of found ecal elements (" << nscclusters <<
") in block is not the same as"
835 <<
" the number of ecal PF clusters reported by the PFSuperCluster"
836 <<
" itself (" << npfclusters <<
")! This should not happen!" << std::endl
837 << sc_err.str() << std::endl;
839 for (
auto ecalitr = ecalbegin; ecalitr != ecalfirstnotinsc; ++ecalitr) {
844 if (!is_pf_sc &&
std::find(safePFClusters.begin(), safePFClusters.end(), elemascluster) == safePFClusters.end())
848 ecalclusters.emplace_back(elemascluster,
true);
850 ecalitr->setFlag(
false);
854 auto emplaceresult = ecal2ps.emplace(elemascluster, ClusterMap::mapped_type());
855 if (!emplaceresult.second) {
856 std::stringstream clus_err;
857 elemascluster->
Dump(clus_err,
"\t");
859 <<
"List of pointers to ECAL block elements contains non-unique items!"
860 <<
" This is very bad!" << std::endl
861 <<
"cluster ptr = 0x" << std::hex << elemascluster <<
std::dec << std::endl
862 << clus_err.str() << std::endl;
864 ClusterMap::mapped_type& eslist = emplaceresult.first->second;
868 for (
auto hgcalitr = hgcalbegin; hgcalitr != hgcalfirstnotinsc; ++hgcalitr) {
873 if (!is_pf_sc &&
std::find(safePFClusters.begin(), safePFClusters.end(), elemascluster) == safePFClusters.end())
877 ecalclusters.emplace_back(elemascluster,
true);
879 hgcalitr->setFlag(
false);
896 LOGDRESSED(
"PFEGammaAlgo") <<
" Unwrapped SC has " << npfclusters <<
" ECAL sub-clusters"
897 <<
" and " << npfpsclusters <<
" PreShower layers 1 & 2 clusters!" << std::endl;
905 EEtoPSElement ecalkey(clusptr.
key(), clusptr);
907 std::equal_range(
eetops_.cbegin(),
eetops_.cend(), ecalkey, [](
const EEtoPSElement&
a,
const EEtoPSElement&
b) {
908 return a.first <
b.first;
912 for (
auto pscl = assc_ps.first; pscl != assc_ps.second; ++pscl) {
913 if (pscl->second ==
temp) {
914 const ClusterElement* pstemp =
docast(
const ClusterElement*, ps1.get());
915 eslist.emplace_back(pstemp);
921 for (
auto pscl = assc_ps.first; pscl != assc_ps.second; ++pscl) {
922 if (pscl->second ==
temp) {
923 const ClusterElement* pstemp =
docast(
const ClusterElement*, ps2.get());
924 eslist.emplace_back(pstemp);
928 return eslist.size();
935 <<
"Dumping " << refinableObjects.size() <<
" refinable objects for this block: " << std::endl;
936 for (
const auto& ro : refinableObjects) {
937 std::stringstream
info;
938 info <<
"Refinable Object:" << std::endl;
940 info <<
"\tSuperCluster element attached to object:" << std::endl <<
'\t';
941 ro.parentSC->Dump(
info,
"\t");
944 if (ro.electronSeed.isNonnull()) {
945 info <<
"\tGSF element attached to object:" << std::endl;
946 ro.primaryGSFs.front()->Dump(
info,
"\t");
948 info <<
"firstBrem : " << ro.firstBrem <<
" lateBrem : " << ro.lateBrem
949 <<
" nBrems with cluster : " << ro.nBremsWithClusters << std::endl;
951 if (ro.electronClusters.size() && ro.electronClusters[0]) {
952 info <<
"electron cluster : ";
953 ro.electronClusters[0]->Dump(
info,
"\t");
956 info <<
" no electron cluster." << std::endl;
959 if (ro.primaryKFs.size()) {
960 info <<
"\tPrimary KF tracks attached to object: " << std::endl;
961 for (
const auto& kf : ro.primaryKFs) {
962 kf->Dump(
info,
"\t");
966 if (ro.secondaryKFs.size()) {
967 info <<
"\tSecondary KF tracks attached to object: " << std::endl;
968 for (
const auto& kf : ro.secondaryKFs) {
969 kf->Dump(
info,
"\t");
973 if (ro.brems.size()) {
974 info <<
"\tBrem tangents attached to object: " << std::endl;
975 for (
const auto& brem : ro.brems) {
976 brem->Dump(
info,
"\t");
980 if (ro.ecalclusters.size()) {
981 info <<
"\tECAL clusters attached to object: " << std::endl;
982 for (
const auto& clus : ro.ecalclusters) {
983 clus->Dump(
info,
"\t");
985 if (ro.ecal2ps.find(clus) != ro.ecal2ps.end()) {
986 for (
const auto& psclus : ro.ecal2ps.at(clus)) {
987 info <<
"\t\t Attached PS Cluster: ";
988 psclus->Dump(
info,
"");
1001 typedef std::multimap<double, unsigned> MatchedMap;
1005 MatchedMap matchedGSFs, matchedECALs;
1006 std::unordered_map<GsfTrackElementPtr, MatchedMap> gsf_ecal_cache;
1008 matchedGSFs.clear();
1011 if (matchedGSFs.empty()) {
1015 std::partial_sort(ecalbegin, ecalbegin + 1, ecalend, closestTrackToECAL);
1023 if (dist_sc != -1.0
f) {
1029 if (dist != -1.0
f && closestECAL.flag()) {
1030 bool gsflinked =
false;
1038 if (!gsf_ecal_cache.count(elemasgsf)) {
1039 matchedECALs.clear();
1045 gsf_ecal_cache.emplace(elemasgsf, matchedECALs);
1046 MatchedMap().swap(matchedECALs);
1048 const MatchedMap& ecal_matches = gsf_ecal_cache[elemasgsf];
1049 if (!ecal_matches.empty()) {
1050 if (ecal_matches.begin()->second == closestECAL->index()) {
1056 if (!gsflinked && !inSC) {
1061 const int nexhits = trackref->missingInnerHits();
1062 bool fromprimaryvertex =
false;
1065 fromprimaryvertex =
true;
1071 closestECAL.setFlag(
false);
1082 bool check_for_merge =
true;
1083 while (check_for_merge) {
1088 for (
auto it1 = ROs.begin(); it1 != ROs.end(); ++it1) {
1089 auto find_start = it1;
1091 auto has_merge = std::find_if(find_start, ROs.end(), std::bind(testIfROMergableByLink, _1, *it1));
1092 if (has_merge != ROs.end() && it1 != ROs.begin()) {
1098 auto mergestart = ROs.begin();
1100 auto nomerge = std::partition(mergestart, ROs.end(), std::bind(testIfROMergableByLink, _1, thefront));
1101 if (nomerge != mergestart) {
1102 LOGDRESSED(
"PFEGammaAlgo::mergeROsByAnyLink()")
1103 <<
"Found objects " <<
std::distance(mergestart, nomerge) <<
" to merge by links to the front!" << std::endl;
1104 for (
auto roToMerge = mergestart; roToMerge != nomerge; ++roToMerge) {
1107 if (!thefront.
ecalclusters.empty() && !roToMerge->ecalclusters.empty()) {
1108 if (thefront.
ecalclusters.front()->clusterRef()->layer() !=
1109 roToMerge->ecalclusters.front()->clusterRef()->layer()) {
1110 LOGWARN(
"PFEGammaAlgo::mergeROsByAnyLink") <<
"Tried to merge EB and EE clusters! Skipping!";
1111 ROs.push_back(*roToMerge);
1117 thefront.
ecalclusters.end(), roToMerge->ecalclusters.begin(), roToMerge->ecalclusters.end());
1118 thefront.
ecal2ps.insert(roToMerge->ecal2ps.begin(), roToMerge->ecal2ps.end());
1120 thefront.
secondaryKFs.end(), roToMerge->secondaryKFs.begin(), roToMerge->secondaryKFs.end());
1124 if (!thefront.
parentSC && roToMerge->parentSC) {
1125 thefront.
parentSC = roToMerge->parentSC;
1130 thefront.
primaryGSFs.end(), roToMerge->primaryGSFs.begin(), roToMerge->primaryGSFs.end());
1132 thefront.
primaryKFs.end(), roToMerge->primaryKFs.begin(), roToMerge->primaryKFs.end());
1133 thefront.
brems.insert(thefront.
brems.end(), roToMerge->brems.begin(), roToMerge->brems.end());
1136 thefront.
firstBrem = roToMerge->firstBrem;
1137 thefront.
lateBrem = roToMerge->lateBrem;
1139 LOGDRESSED(
"PFEGammaAlgo::mergeROsByAnyLink")
1140 <<
"Need to implement proper merging of two gsf candidates!" << std::endl;
1143 ROs.erase(mergestart, nomerge);
1145 ROs.push_back(ROs.front());
1148 check_for_merge =
false;
1151 LOGDRESSED(
"PFEGammaAlgo::mergeROsByAnyLink()")
1152 <<
"After merging by links there are: " << ROs.size() <<
" refinable EGamma objects!" << std::endl;
1170 NotCloserToOther<reco::PFBlockElement::GSF, reco::PFBlockElement::TRACK> gsfTrackToKFs(
_currentblock, seedtk);
1172 auto notlinked = std::partition(KFbegin, KFend, gsfTrackToKFs);
1174 for (
auto kft = KFbegin; kft != notlinked; ++kft) {
1179 kft->setFlag(
false);
1182 }
else if (elemaskf->
trackType(convType)) {
1183 kft->setFlag(
false);
1199 if (primkf->trackType(convType)) {
1200 throw cms::Exception(
"PFEGammaAlgo::linkRefinableObjectPrimaryKFsToSecondaryKFs()")
1201 <<
"A KF track from conversion has been assigned as a primary!!" << std::endl;
1203 NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::TRACK, true> kfTrackToKFs(
_currentblock,
1206 auto notlinked = std::partition(KFbegin, KFend, kfTrackToKFs);
1208 for (
auto kft = KFbegin; kft != notlinked; ++kft) {
1213 kft->setFlag(
false);
1230 NotCloserToOther<reco::PFBlockElement::GSF, reco::PFBlockElement::ECAL> gsfTracksToECALs(
_currentblock, primgsf);
1232 auto notmatched_blk = std::partition(ECALbegin, ECALend, gsfTracksToECALs);
1234 std::partition(ECALbegin, notmatched_blk, [&primgsf](
auto const&
x) {
return compatibleEoPOut(*
x, *primgsf); });
1237 notmatched_sc = std::partition(
1238 RO.
ecalclusters.begin(), notmatched_sc, [&primgsf](
auto const&
x) {
return compatibleEoPOut(*
x, *primgsf); });
1243 LOGDRESSED(
"PFEGammaAlgo::linkGSFTracktoECAL()") <<
"Found a cluster already in RO by GSF extrapolation"
1244 <<
" at ECAL surface!" << std::endl
1245 << *elemascluster << std::endl;
1250 for (
auto ecal = ECALbegin;
ecal != notmatched_blk; ++
ecal) {
1252 LOGDRESSED(
"PFEGammaAlgo::linkGSFTracktoECAL()") <<
"Found a cluster not already in RO by GSF extrapolation"
1253 <<
" at ECAL surface!" << std::endl
1254 << *elemascluster << std::endl;
1255 if (addPFClusterToROSafe(elemascluster, RO)) {
1258 ecal->setFlag(
false);
1271 NotCloserToOther<reco::PFBlockElement::GSF, reco::PFBlockElement::HCAL> gsfTracksToHCALs(
_currentblock, primgsf);
1272 auto notmatched = std::partition(HCALbegin, HCALend, gsfTracksToHCALs);
1273 for (
auto hcal = HCALbegin;
hcal != notmatched; ++
hcal) {
1276 LOGDRESSED(
"PFEGammaAlgo::linkGSFTracktoECAL()")
1277 <<
"Found an HCAL cluster associated to GSF extrapolation" << std::endl;
1280 hcal->setFlag(
false);
1296 std::vector<FlaggedPtr<const PFClusterElement>>& currentECAL = RO.
ecalclusters;
1299 NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::ECAL> kfTrackToECALs(
_currentblock, kfflagged);
1300 NotCloserToOther<reco::PFBlockElement::GSF, reco::PFBlockElement::ECAL> kfTrackGSFToECALs(
_currentblock, kfflagged);
1302 auto notmatched_sc = std::partition(currentECAL.begin(), currentECAL.end(), kfTrackToECALs);
1304 notmatched_sc = std::partition(currentECAL.begin(), notmatched_sc, kfTrackGSFToECALs);
1305 for (
auto ecalitr = currentECAL.begin(); ecalitr != notmatched_sc; ++ecalitr) {
1309 LOGDRESSED(
"PFEGammaAlgo::linkKFTracktoECAL()") <<
"Found a cluster already in RO by KF extrapolation"
1310 <<
" at ECAL surface!" << std::endl
1311 << *elemascluster << std::endl;
1315 auto notmatched_blk = std::partition(ECALbegin, ECALend, kfTrackToECALs);
1317 notmatched_blk = std::partition(ECALbegin, notmatched_blk, kfTrackGSFToECALs);
1318 for (
auto ecalitr = ECALbegin; ecalitr != notmatched_blk; ++ecalitr) {
1320 if (addPFClusterToROSafe(elemascluster, RO)) {
1322 ecalitr->setFlag(
false);
1324 LOGDRESSED(
"PFEGammaAlgo::linkKFTracktoECAL()") <<
"Found a cluster not in RO by KF extrapolation"
1325 <<
" at ECAL surface!" << std::endl
1326 << *elemascluster << std::endl;
1333 if (RO.
brems.empty())
1337 int lastBremTrajPos = -1;
1338 for (
auto& brem : RO.
brems) {
1339 bool has_clusters =
false;
1340 TrajPos = (brem->indTrajPoint()) - 2;
1343 NotCloserToOther<reco::PFBlockElement::BREM, reco::PFBlockElement::ECAL> BremToECALs(
_currentblock, brem);
1347 auto notmatched_rsc = std::partition(RSCBegin, RSCEnd, BremToECALs);
1348 for (
auto ecal = RSCBegin;
ecal != notmatched_rsc; ++
ecal) {
1349 float deta =
std::abs((*ecal)->clusterRef()->positionREP().eta() - brem->positionAtECALEntrance().eta());
1351 has_clusters =
true;
1352 if (lastBremTrajPos == -1 || lastBremTrajPos < TrajPos) {
1353 lastBremTrajPos = TrajPos;
1355 if (FirstBrem == -1 || TrajPos < FirstBrem) {
1356 FirstBrem = TrajPos;
1359 LOGDRESSED(
"PFEGammaAlgo::linkBremToECAL()") <<
"Found a cluster already in SC linked to brem extrapolation"
1360 <<
" at ECAL surface!" << std::endl;
1365 auto notmatched_block = std::partition(ECALbegin, ECALend, BremToECALs);
1366 for (
auto ecal = ECALbegin;
ecal != notmatched_block; ++
ecal) {
1367 float deta =
std::abs((*ecal)->clusterRef()->positionREP().eta() - brem->positionAtECALEntrance().eta());
1369 has_clusters =
true;
1370 if (lastBremTrajPos == -1 || lastBremTrajPos < TrajPos) {
1371 lastBremTrajPos = TrajPos;
1373 if (FirstBrem == -1 || TrajPos < FirstBrem) {
1375 FirstBrem = TrajPos;
1379 if (addPFClusterToROSafe(elemasclus, RO)) {
1383 ecal->setFlag(
false);
1384 LOGDRESSED(
"PFEGammaAlgo::linkBremToECAL()") <<
"Found a cluster not already associated by brem extrapolation"
1385 <<
" at ECAL surface!" << std::endl;
1402 auto ronotconv = std::partition(BeginROskfs, EndROskfs, [](
auto const&
x) {
return x->trackType(ConvType); });
1404 for (
size_t idx = 0;
idx < convkfs_end; ++
idx) {
1405 auto const& secKFs =
1407 NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::TRACK, true> TracksToTracks(
_currentblock,
1409 auto notmatched = std::partition(KFbegin, KFend, TracksToTracks);
1410 notmatched = std::partition(KFbegin, notmatched, [](
auto const&
x) {
return x->trackType(ConvType); });
1411 for (
auto kf = KFbegin; kf != notmatched; ++kf) {
1424 NotCloserToOther<reco::PFBlockElement::ECAL, reco::PFBlockElement::TRACK, true> ECALToTracks(
_currentblock,
1426 auto notmatchedkf = std::partition(KFbegin, KFend, ECALToTracks);
1427 auto notconvkf = std::partition(KFbegin, notmatchedkf, [](
auto const&
x) {
return x->trackType(ConvType); });
1429 for (
auto kf = KFbegin; kf != notconvkf; ++kf) {
1436 for (
auto kf = notconvkf; kf != notmatchedkf; ++kf) {
1454 NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::ECAL, false> TracksToECALwithCut(
1456 auto notmatched = std::partition(ECALbegin, ECALend, TracksToECALwithCut);
1457 for (
auto ecal = ECALbegin;
ecal != notmatched; ++
ecal) {
1459 if (addPFClusterToROSafe(elemascluster, RO)) {
1462 ecal->setFlag(
false);
1472 output.candidates.reserve(ROs.size());
1473 output.candidateExtras.reserve(ROs.size());
1474 output.refinedSuperClusters.reserve(ROs.size());
1476 for (
auto& RO : ROs) {
1482 if (!RO.primaryGSFs.empty() || !RO.primaryKFs.empty()) {
1487 if (!RO.primaryKFs.empty()) {
1488 cand.setCharge(RO.primaryKFs[0]->trackRef()->charge());
1490 cand.setTrackRef(RO.primaryKFs[0]->trackRef());
1491 cand.setVertex(RO.primaryKFs[0]->trackRef()->vertex());
1494 if (!RO.primaryGSFs.empty()) {
1495 cand.setCharge(RO.primaryGSFs[0]->GsftrackRef()->chargeMode());
1497 cand.setGsfTrackRef(RO.primaryGSFs[0]->GsftrackRef());
1498 cand.setVertex(RO.primaryGSFs[0]->GsftrackRef()->vertex());
1504 cand.setSuperClusterRef(RO.parentSC->superClusterRef());
1509 for (
const auto& brem : RO.brems) {
1513 for (
const auto&
ecal : RO.ecalclusters) {
1516 if (RO.ecal2ps.count(clus)) {
1517 for (
auto& psclus : RO.ecal2ps.at(clus)) {
1523 for (
const auto& kf : RO.secondaryKFs) {
1526 bool no_conv_ref =
true;
1527 for (
const auto& convref : convrefs) {
1528 if (convref.isNonnull() && convref.isAvailable()) {
1530 no_conv_ref =
false;
1537 const auto& mvavalmapped = RO.singleLegConversionMvaMap.find(kf);
1540 float mvaval = (mvavalmapped != RO.singleLegConversionMvaMap.end()
1541 ? mvavalmapped->second
1552 float trkTime = 0, trkTimeErr = -1;
1553 if (!RO.primaryGSFs.empty() && RO.primaryGSFs[0]->isTimeValid()) {
1554 trkTime = RO.primaryGSFs[0]->time();
1555 trkTimeErr = RO.primaryGSFs[0]->timeError();
1556 }
else if (!RO.primaryKFs.empty() && RO.primaryKFs[0]->isTimeValid()) {
1557 trkTime = RO.primaryKFs[0]->time();
1558 trkTimeErr = RO.primaryKFs[0]->timeError();
1560 if (trkTimeErr >= 0) {
1561 cand.setTime(trkTime, trkTimeErr);
1569 const double scE = the_sc.
energy();
1573 egDir = egDir.Unit();
1576 cand.setPositionAtECALEntrance(ecalPOS_f);
1583 cand.setPositionAtECALEntrance(
gsf->positionAtECALEntrance());
1594 xtra.
setMVA(eleMVAValue);
1595 cand.set_mva_e_pi(eleMVAValue);
1597 output.candidateExtras.push_back(xtra);
1614 constexpr
float mEl = 0.000511;
1615 const double eInGsf = std::hypot(refGsf->pMode(), mEl);
1616 double dEtGsfEcal = 1e6;
1618 const double eneHcalGsf =
1620 return a +
b->clusterRef()->energy();
1625 const double eOutGsf = gsfElement->
Pout().t();
1627 double firstEcalGsfEnergy{0.0};
1628 double otherEcalGsfEnergy{0.0};
1629 double ecalBremEnergy{0.0};
1631 std::vector<const reco::PFCluster*> gsfCluster;
1633 const double cenergy =
ecal->clusterRef()->correctedEnergy();
1636 bool hasbrem =
false;
1637 for (
const auto& brem : ro.
brems) {
1643 ecalBremEnergy += cenergy;
1647 otherEcalGsfEnergy += cenergy;
1649 ecalBremEnergy += cenergy;
1650 if (!(hasgsf || haskf))
1651 otherEcalGsfEnergy += cenergy;
1658 firstEcalGsfEnergy = cref->correctedEnergy();
1659 dEtGsfEcal = cref->positionREP().eta() - etaOutGsf;
1660 gsfCluster.push_back(cref.
get());
1666 float firstBrem{-1.0f};
1667 float earlyBrem{-1.0f};
1668 float lateBrem{-1.0f};
1671 earlyBrem = ro.
firstBrem < 4 ? 1.0f : 0.0f;
1672 lateBrem = ro.
lateBrem == 1 ? 1.0f : 0.0f;
1676 if (firstEcalGsfEnergy > 0.0) {
1677 if (refGsf.isNonnull()) {
1680 const float ptGsf = refGsf->ptMode();
1681 const float etaGsf = refGsf->etaMode();
1683 const double ptModeErrorGsf = refGsf->ptModeError();
1684 float ptModeErrOverPtGsf = (ptModeErrorGsf > 0. ? ptModeErrorGsf / ptGsf : 1.0);
1685 float chi2Gsf = refGsf->normalizedChi2();
1686 float dPtOverPtGsf = (ptGsf - gsfElement->
Pout().pt()) / ptGsf;
1688 float nHitKf = refKf.
isNonnull() ? refKf->hitPattern().trackerLayersWithMeasurement() : 0;
1689 float chi2Kf = refKf.
isNonnull() ? refKf->normalizedChi2() : -0.01;
1692 float eTotPinMode = (firstEcalGsfEnergy + otherEcalGsfEnergy + ecalBremEnergy) / eInGsf;
1693 float eGsfPoutMode = firstEcalGsfEnergy / eOutGsf;
1694 float eTotBremPinPoutMode = (ecalBremEnergy + otherEcalGsfEnergy) / (eInGsf - eOutGsf);
1695 float dEtaGsfEcalClust =
std::abs(dEtGsfEcal);
1697 float hOverHe = eneHcalGsf / (eneHcalGsf + firstEcalGsfEnergy);
1704 dPtOverPtGsf = std::clamp(dPtOverPtGsf, -0.2
f, 1.0
f);
1705 ptModeErrOverPtGsf =
std::min(ptModeErrOverPtGsf, 0.3
f);
1708 eTotPinMode = std::clamp(eTotPinMode, 0.0
f, 5.0
f);
1709 eGsfPoutMode = std::clamp(eGsfPoutMode, 0.0
f, 5.0
f);
1710 eTotBremPinPoutMode = std::clamp(eTotBremPinPoutMode, 0.0
f, 5.0
f);
1711 dEtaGsfEcalClust =
std::min(dEtaGsfEcalClust, 0.1
f);
1712 logSigmaEtaEta =
std::max(logSigmaEtaEta, -14.0
f);
1754 eTotBremPinPoutMode,
1773 NotCloserToOther<reco::PFBlockElement::ECAL, reco::PFBlockElement::TRACK, true> ECALToTracks(
_currentblock,
1775 auto notmatchedkf = std::partition(KFbegin, KFend, ECALToTracks);
1776 auto notconvkf = std::partition(KFbegin, notmatchedkf, [](
auto const&
x) {
return x->trackType(ConvType); });
1778 for (
auto kf = notconvkf; kf != notmatchedkf; ++kf) {
1795 std::vector<const reco::PFCluster*> bare_ptrs;
1797 double posX(0),
posY(0), posZ(0), rawSCEnergy(0), corrSCEnergy(0), corrPSEnergy(0), ps1_energy(0.0), ps2_energy(0.0);
1802 auto clusptr = edm::refToPtr<reco::PFClusterCollection>(clus->clusterRef());
1803 bare_ptrs.push_back(clusptr.get());
1805 const double cluseraw = clusptr->energy();
1806 double cluscalibe = clusptr->correctedEnergy();
1808 posX += cluseraw * cluspos.X();
1809 posY += cluseraw * cluspos.Y();
1810 posZ += cluseraw * cluspos.Z();
1812 if (isEE && RO.
ecal2ps.count(clus.get())) {
1813 const auto& psclusters = RO.
ecal2ps.at(clus.get());
1815 std::vector<reco::PFCluster const*> psClusterPointers;
1816 psClusterPointers.reserve(psclusters.size());
1817 for (
auto const& psc : psclusters) {
1818 psClusterPointers.push_back(psc->clusterRef().get());
1823 ePS1 = calibratedEnergies.ps1Energy;
1824 ePS2 = calibratedEnergies.ps2Energy;
1831 rawSCEnergy += cluseraw;
1832 corrSCEnergy += cluscalibe;
1835 corrPSEnergy += ePS1 + ePS2;
1837 posX /= rawSCEnergy;
1838 posY /= rawSCEnergy;
1839 posZ /= rawSCEnergy;
1844 auto clusptr = edm::refToPtr<reco::PFClusterCollection>(RO.
ecalclusters.front()->clusterRef());
1851 clusptr = edm::refToPtr<reco::PFClusterCollection>(clus->clusterRef());
1853 auto& hits_and_fractions = clusptr->hitsAndFractions();
1854 for (
auto& hit_and_fraction : hits_and_fractions) {
1858 if (RO.
ecal2ps.count(clus.get())) {
1859 const auto& cluspsassociation = RO.
ecal2ps.at(clus.get());
1863 for (
const auto& pscluselem : cluspsassociation) {
1866 auto found_pscluster =
1873 throw cms::Exception(
"PFECALSuperClusterAlgo::buildSuperCluster")
1874 <<
"Found a PS cluster matched to more than one EE cluster!" << std::endl
1875 << std::hex << psclus.
get() <<
" == " << found_pscluster->get() <<
std::dec << std::endl;
1898 const double Pin_gsf = RO.
primaryGSFs.front()->GsftrackRef()->pMode();
1899 const double gsfOuterEta = RO.
primaryGSFs.front()->positionAtECALEntrance().Eta();
1900 double tot_ecal = 0.0;
1901 std::vector<double> min_brem_dists;
1902 std::vector<double> closest_brem_eta;
1905 tot_ecal +=
ecal->clusterRef()->correctedEnergy();
1908 double min_brem_dist = 5000.0;
1909 double eta = -999.0;
1910 for (
const auto& brem : RO.
brems) {
1912 if (dist < min_brem_dist && dist != -1.0
f) {
1913 min_brem_dist = dist;
1914 eta = brem->positionAtECALEntrance().Eta();
1917 min_brem_dists.push_back(min_brem_dist);
1918 closest_brem_eta.push_back(
eta);
1925 const float secpin = (*secd_kf)->trackRef()->p();
1926 bool remove_this_kf =
false;
1929 const float minbremdist = min_brem_dists[bremidx];
1930 const double ecalenergy = (*ecal)->clusterRef()->correctedEnergy();
1931 const double Epin = ecalenergy / secpin;
1932 const double detaGsf =
std::abs(gsfOuterEta - (*ecal)->clusterRef()->positionREP().Eta());
1933 const double detaBrem =
std::abs(closest_brem_eta[bremidx] - (*ecal)->clusterRef()->positionREP().Eta());
1937 const float tkdist =
1943 if (Epin > 3 && kf_matched && tkdist != -1.0
f && tkdist < minbremdist && detaGsf > 0.05 && detaBrem > 0.015) {
1944 double res_with =
std::abs((tot_ecal - Pin_gsf) / Pin_gsf);
1945 double res_without =
std::abs((tot_ecal - ecalenergy - Pin_gsf) / Pin_gsf);
1946 if (res_without < res_with) {
1947 LOGDRESSED(
"PFEGammaAlgo") <<
" REJECTED_RES totenergy " << tot_ecal <<
" Pin_gsf " << Pin_gsf
1948 <<
" cluster to secondary " << ecalenergy <<
" res_with " << res_with
1949 <<
" res_without " << res_without << std::endl;
1950 tot_ecal -= ecalenergy;
1951 remove_this_kf =
true;
1958 if (remove_this_kf) {
1967 bool removeFreeECAL,
1968 bool removeSCEcal) {
1969 std::vector<bool> cluster_in_sc;
1975 bool remove_this_kf =
false;
1976 NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::HCAL> tracksToHCALs(
_currentblock, *secd_kf);
1980 const float secpin = trkRef->p();
1982 for (
auto ecal = ecal_begin;
ecal != ecal_end; ++
ecal) {
1983 const double ecalenergy = (*ecal)->clusterRef()->correctedEnergy();
1986 if (cluster_in_sc.size() < clus_idx + 1) {
1991 cluster_in_sc.push_back(dist != -1.0
f);
1999 auto hcal_matched = std::partition(hcal_begin, hcal_end, tracksToHCALs);
2000 for (
auto hcalclus = hcal_begin; hcalclus != hcal_matched; ++hcalclus) {
2002 dynamic_cast<const reco::PFBlockElementCluster*>(hcalclus->get());
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)