7 #include "TDecompChol.h"
24 nSigmaECAL_(nSigmaECAL),
25 nSigmaHCAL_(nSigmaHCAL),
26 nSigmaHFEM_(nSigmaHFEM),
27 nSigmaHFHAD_(nSigmaHFHAD),
30 thepfEnergyCalibrationHF_(thepfEnergyCalibrationHF),
40 muonHCAL_ =
pset.getParameter<std::vector<double>>(
"muon_HCAL");
41 muonECAL_ =
pset.getParameter<std::vector<double>>(
"muon_ECAL");
42 muonHO_ =
pset.getParameter<std::vector<double>>(
"muon_HO");
119 bool primaryVertexFound =
false;
124 primaryVertexFound =
true;
133 auto const&
blocks = *blockHandle;
138 LogTrace(
"PFAlgo|reconstructParticles")
139 <<
"start of function PFAlgo::reconstructParticles, blocks.size()=" <<
blocks.size();
142 std::list<reco::PFBlockRef> hcalBlockRefs;
143 std::list<reco::PFBlockRef> ecalBlockRefs;
144 std::list<reco::PFBlockRef> hoBlockRefs;
145 std::list<reco::PFBlockRef> otherBlockRefs;
147 for (
unsigned i = 0;
i <
blocks.size(); ++
i) {
153 bool singleEcalOrHcal =
false;
156 ecalBlockRefs.push_back(blockref);
157 singleEcalOrHcal =
true;
160 hcalBlockRefs.push_back(blockref);
161 singleEcalOrHcal =
true;
165 hoBlockRefs.push_back(blockref);
166 singleEcalOrHcal =
true;
170 if (!singleEcalOrHcal) {
171 otherBlockRefs.push_back(blockref);
175 LogTrace(
"PFAlgo|reconstructParticles")
176 <<
"# Ecal blocks: " << ecalBlockRefs.size() <<
", # Hcal blocks: " << hcalBlockRefs.size()
177 <<
", # HO blocks: " << hoBlockRefs.size() <<
", # Other blocks: " << otherBlockRefs.size();
183 for (
auto const&
other : otherBlockRefs) {
184 LogTrace(
"PFAlgo|reconstructParticles") <<
"processBlock, Block number " << nblcks++;
188 std::list<reco::PFBlockRef>
empty;
192 for (
auto const&
hcal : hcalBlockRefs) {
193 LogTrace(
"PFAlgo|reconstructParticles") <<
"processBlock, HCAL block number " << hblcks++;
199 for (
auto const&
ecal : ecalBlockRefs) {
200 LogTrace(
"PFAlgo|reconstructParticles") <<
"processBlock, ECAL block number " << eblcks++;
218 LogTrace(
"PFAlgo|reconstructParticles")
219 <<
"end of function PFAlgo::reconstructParticles, pfCandidates_->size()=" <<
pfCandidates_->size();
223 std::vector<bool>& active,
228 LogTrace(
"PFAlgo|egammaFilters") <<
"start of function PFAlgo::egammaFilters(), negmcandidates=" << negmcandidates;
230 for (
unsigned int ieg = 0; ieg < negmcandidates; ++ieg) {
235 PFCandidate::ElementsInBlocks::const_iterator iegfirst = theElements.begin();
236 bool sameBlock =
false;
237 bool isGoodElectron =
false;
238 bool isGoodPhoton =
false;
239 bool isPrimaryElectron =
false;
240 if (iegfirst->first == blockref)
243 LogTrace(
"PFAlgo|egammaFilters") <<
" I am in looping on EGamma Candidates: pt " << (*pfEgmRef).pt()
244 <<
" eta,phi " << (*pfEgmRef).eta() <<
", " << (*pfEgmRef).phi() <<
" charge "
245 << (*pfEgmRef).charge();
247 if ((*pfEgmRef).gsfTrackRef().isNonnull()) {
251 isPrimaryElectron = pfegamma->
isElectron(*gedEleRef);
254 <<
"** Good Electron, pt " << gedEleRef->pt() <<
" eta, phi " << gedEleRef->eta() <<
", "
255 << gedEleRef->phi() <<
" charge " << gedEleRef->charge() <<
" isPrimary " << isPrimaryElectron
257 << (gedEleRef->dr03TkSumPt() + gedEleRef->dr03EcalRecHitSumEt() + gedEleRef->dr03HcalTowerSumEt())
258 <<
" mva_isolated " << gedEleRef->mva_Isolated() <<
" mva_e_pi " << gedEleRef->mva_e_pi();
261 if ((*pfEgmRef).superClusterRef().isNonnull()) {
266 LogTrace(
"PFAlgo|egammaFilters") <<
"** Good Photon, pt " << gedPhoRef->pt() <<
" eta, phi "
267 << gedPhoRef->eta() <<
", " << gedPhoRef->phi() << endl;
272 if (isGoodElectron && isGoodPhoton) {
273 if (isPrimaryElectron)
274 isGoodPhoton =
false;
276 isGoodElectron =
false;
280 if (isGoodElectron) {
284 bool lockTracks =
false;
294 myPFElectron.
setCharge(gedEleRef->charge());
295 myPFElectron.
setP4(gedEleRef->p4());
299 LogTrace(
"PFAlgo|egammaFilters") <<
" PFAlgo: found an electron with NEW EGamma code ";
300 LogTrace(
"PFAlgo|egammaFilters") <<
" myPFElectron: pt " << myPFElectron.
pt() <<
" eta,phi "
301 << myPFElectron.
eta() <<
", " << myPFElectron.
phi() <<
" mva "
302 << myPFElectron.
mva_e_pi() <<
" charge " << myPFElectron.
charge();
304 LogTrace(
"PFAlgo|egammaFilters") <<
" THE BLOCK " << *blockref;
305 for (
auto const& eb : theElements) {
306 active[eb.second] =
false;
307 LogTrace(
"PFAlgo|egammaFilters") <<
" Elements used " << eb.second;
313 for (
auto const& trk : extraTracks) {
314 LogTrace(
"PFAlgo|egammaFilters") <<
" Extra locked track " << trk.second;
315 active[trk.second] =
false;
319 LogTrace(
"PFAlgo|egammaFilters") <<
"Creating PF electron: pt=" << myPFElectron.
pt()
320 <<
" eta=" << myPFElectron.
eta() <<
" phi=" << myPFElectron.
phi();
324 LogTrace(
"PFAlgo|egammaFilters") <<
"PFAlgo: Electron DISCARDED, NOT SAFE FOR JETMET ";
343 myPFPhoton.
setP4(gedPhoRef->p4());
344 LogTrace(
"PFAlgo|egammaFilters") <<
" PFAlgo: found a photon with NEW EGamma code ";
345 LogTrace(
"PFAlgo|egammaFilters") <<
" myPFPhoton: pt " << myPFPhoton.
pt() <<
" eta,phi " << myPFPhoton.
eta()
346 <<
", " << myPFPhoton.
phi() <<
" charge " << myPFPhoton.
charge();
349 LogTrace(
"PFAlgo|egammaFilters") <<
" THE BLOCK " << *blockref;
350 for (
auto const& eb : theElements) {
351 active[eb.second] =
false;
352 LogTrace(
"PFAlgo|egammaFilters") <<
" Elements used " << eb.second;
354 LogTrace(
"PFAlgo|egammaFilters") <<
"Creating PF photon: pt=" << myPFPhoton.
pt() <<
" eta=" << myPFPhoton.
eta()
355 <<
" phi=" << myPFPhoton.
phi();
361 LogTrace(
"PFAlgo|egammaFilters") <<
"end of function PFAlgo::egammaFilters";
365 LogTrace(
"PFAlgo|conversionAlgo") <<
"start of function PFAlgo::conversionAlgo(), elements.size()="
367 for (
unsigned iEle = 0; iEle <
elements.size(); iEle++) {
369 if (
type == PFBlockElement::TRACK) {
370 LogTrace(
"PFAlgo|conversionAlgo") <<
"elements[" << iEle <<
"].type() == TRACK, active[" << iEle
371 <<
"]=" << active[iEle];
373 active[iEle] =
false;
376 LogTrace(
"PFAlgo|conversionAlgo") <<
"Track is high purity";
379 const auto* trackRef = dynamic_cast<const reco::PFBlockElementTrack*>((&
elements[iEle]));
381 LogTrace(
"PFAlgo|conversionAlgo") <<
"!trackType(T_FROM_GAMMACONV)";
385 active[iEle] =
false;
387 LogTrace(
"PFAlgo|conversionAlgo") <<
"active[iEle=" << iEle <<
"]=" << active[iEle];
390 LogTrace(
"PFAlgo|conversionAlgo") <<
"end of function PFAlgo::conversionAlgo";
397 std::vector<bool>& active,
398 bool goodTrackDeadHcal,
401 std::multimap<double, unsigned>& ecalElems,
403 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"start of function PFAlgo::recoTracksNotHCAL(), now dealing with tracks "
404 "linked to no HCAL clusters. Was HCal active? "
427 if (!ecalElems.empty()) {
428 unsigned thisEcal = ecalElems.begin()->second;
430 bool useCluster =
true;
432 std::multimap<double, unsigned> sortedTracks;
433 block.associatedElements(
435 useCluster = (sortedTracks.begin()->second == iTrack);
438 deficit -= clusterRef->energy();
447 active[iTrack] =
false;
448 LogTrace(
"PFAlgo|recoTracksNotHCAL")
450 <<
" deficit " << deficit <<
" > " <<
nSigmaTRACK_ <<
" x " <<
resol <<
" track pt " << trackRef->pt()
451 <<
" +- " << trackRef->ptError() <<
" layers valid " << trackRef->hitPattern().trackerLayersWithMeasurement()
452 <<
", lost " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS)
453 <<
", lost outer " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS)
454 <<
", lost inner " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS)
455 <<
"(valid fraction " << trackRef->validFraction() <<
")"
456 <<
" chi2/ndf " << trackRef->normalizedChi2() <<
" |dxy| "
459 <<
"is probably a fake (1) --> lock the track";
467 std::vector<unsigned> tmpi;
468 std::vector<unsigned> kTrack;
471 double dpt = trackRef->ptError();
475 double dptRel = dpt / trackRef->pt() * 100;
481 unsigned nHits =
elements[iTrack].trackRef()->hitPattern().trackerLayersWithMeasurement();
482 unsigned int NLostHit = trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS);
484 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"A track (algo = " << trackRef->algo() <<
") with momentum "
486 << dpt <<
" / " <<
elements[iTrack].trackRef()->eta()
487 <<
" without any link to ECAL/HCAL and with " << nHits <<
" (" << NLostHit
488 <<
") hits (lost hits) has been cleaned";
490 active[iTrack] =
false;
496 kTrack.push_back(iTrack);
497 active[iTrack] =
false;
500 if (ecalElems.empty()) {
501 (*pfCandidates_)[tmpi[0]].setEcalEnergy(0., 0.);
502 (*pfCandidates_)[tmpi[0]].setHcalEnergy(0., 0.);
503 (*pfCandidates_)[tmpi[0]].setHoEnergy(0., 0.);
504 (*pfCandidates_)[tmpi[0]].setPs1Energy(0);
505 (*pfCandidates_)[tmpi[0]].setPs2Energy(0);
506 (*pfCandidates_)[tmpi[0]].addElementInBlock(blockref, kTrack[0]);
511 const unsigned int thisEcal = ecalElems.begin()->second;
513 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
" is associated to " <<
elements[thisEcal];
517 (*pfCandidates_)[tmpi[0]].setEcalEnergy(clusterRef->energy(),
std::min(clusterRef->energy(),
muonECAL_[0]));
518 (*pfCandidates_)[tmpi[0]].setHcalEnergy(0., 0.);
519 (*pfCandidates_)[tmpi[0]].setHoEnergy(0., 0.);
520 (*pfCandidates_)[tmpi[0]].setPs1Energy(0);
521 (*pfCandidates_)[tmpi[0]].setPs2Energy(0);
522 (*pfCandidates_)[tmpi[0]].addElementInBlock(blockref, kTrack[0]);
525 double slopeEcal = 1.;
526 bool connectedToEcal =
false;
527 unsigned iEcal = 99999;
528 double calibEcal = 0.;
529 double calibHcal = 0.;
530 double totalEcal = thisIsAMuon ? -
muonECAL_[0] : 0.;
533 std::multimap<double, unsigned> sortedTracks;
535 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"the closest ECAL cluster, id " << thisEcal <<
", has " << sortedTracks.size()
536 <<
" associated tracks, now processing them. ";
538 if (hasDeadHcal && !sortedTracks.empty()) {
540 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
" the closest track to ECAL " << thisEcal <<
" is "
541 << sortedTracks.begin()->second <<
" (distance " << sortedTracks.begin()->first
543 if (sortedTracks.begin()->second != iTrack) {
544 LogTrace(
"PFAlgo|recoTracksNotHCAL")
545 <<
" the closest track to ECAL " << thisEcal <<
" is " << sortedTracks.begin()->second
546 <<
" which is not the one being processed. Will skip ECAL linking for this track";
547 (*pfCandidates_)[tmpi[0]].setEcalEnergy(0., 0.);
548 (*pfCandidates_)[tmpi[0]].setHcalEnergy(0., 0.);
549 (*pfCandidates_)[tmpi[0]].setHoEnergy(0., 0.);
550 (*pfCandidates_)[tmpi[0]].setPs1Energy(0);
551 (*pfCandidates_)[tmpi[0]].setPs2Energy(0);
552 (*pfCandidates_)[tmpi[0]].addElementInBlock(blockref, kTrack[0]);
555 LogTrace(
"PFAlgo|recoTracksNotHCAL")
556 <<
" the closest track to ECAL " << thisEcal <<
" is " << sortedTracks.begin()->second
557 <<
" which is the one being processed. Will skip ECAL linking for all other track";
558 sortedTracks.clear();
562 for (
auto const& trk : sortedTracks) {
563 unsigned jTrack = trk.second;
570 if (jTrack == iTrack)
579 std::multimap<double, unsigned> sortedECAL;
581 if (sortedECAL.begin()->second != thisEcal)
586 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
" found track " << jTrack << (thatIsAMuon ?
" (muon) " :
" (non-muon)")
587 <<
", with distance = " << sortedECAL.begin()->first;
590 bool rejectFake =
false;
592 if (!thatIsAMuon && trackRef->ptError() >
ptError_) {
595 double deficit =
trackMomentum + trackRef->p() - clusterRef->energy();
601 kTrack.push_back(jTrack);
602 active[jTrack] =
false;
603 LogTrace(
"PFAlgo|recoTracksNotHCAL")
605 <<
"is probably a fake (2) --> lock the track"
606 <<
"(trackMomentum = " <<
trackMomentum <<
", clusterEnergy = " << clusterRef->energy()
608 <<
" assuming neutralHadronEnergyResolution "
619 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"Track momentum increased from " <<
trackMomentum <<
" GeV ";
625 totalEcal =
std::max(totalEcal, 0.);
632 kTrack.push_back(jTrack);
633 active[jTrack] =
false;
636 (*pfCandidates_)[tmpi.back()].setEcalEnergy(clusterRef->energy(),
std::min(clusterRef->energy(),
muonECAL_[0]));
637 (*pfCandidates_)[tmpi.back()].setHcalEnergy(0., 0.);
638 (*pfCandidates_)[tmpi.back()].setHoEnergy(0., 0.);
639 (*pfCandidates_)[tmpi.back()].setPs1Energy(0);
640 (*pfCandidates_)[tmpi.back()].setPs2Energy(0);
641 (*pfCandidates_)[tmpi.back()].addElementInBlock(blockref, kTrack.back());
645 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"Loop over all associated ECAL clusters";
647 for (
auto const&
ecal : ecalElems) {
654 if (!active[
index]) {
655 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"is not active - ignore ";
662 const bool skip = std::none_of(
663 kTrack.begin(), kTrack.end(), [&](
unsigned iTrack) {
return sortedTracks.begin()->second == iTrack; });
666 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"is closer to another track - ignore ";
674 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"Ecal cluster with raw energy = " << clusterRef->energy()
675 <<
" linked with distance = " <<
ecal.first;
681 vector<double> ps1Ene{0.};
683 vector<double> ps2Ene{0.};
687 const double ecalEnergy = clusterRef->energy();
688 const double ecalEnergyCalibrated = clusterRef->correctedEnergy();
689 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"Corrected ECAL(+PS) energy = " << ecalEnergy;
693 totalEcal += ecalEnergy;
694 const double previousCalibEcal = calibEcal;
695 const double previousSlopeEcal = slopeEcal;
696 calibEcal =
std::max(totalEcal, 0.);
699 trackMomentum, calibEcal, calibHcal, clusterRef->positionREP().Eta(), clusterRef->positionREP().Phi());
701 slopeEcal = calibEcal / totalEcal;
703 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"The total calibrated energy so far amounts to = " << calibEcal
704 <<
" (slope = " << slopeEcal <<
")";
710 calibEcal = previousCalibEcal;
711 slopeEcal = previousSlopeEcal;
712 totalEcal = calibEcal / slopeEcal;
716 active[
index] =
false;
719 std::multimap<double, unsigned> assTracks;
723 *clusterRef, ecalEnergyCalibrated)];
724 ecalCand.setEcalEnergy(clusterRef->energy(), ecalEnergyCalibrated);
725 ecalCand.setHcalEnergy(0., 0.);
726 ecalCand.setHoEnergy(0., 0.);
727 ecalCand.setPs1Energy(ps1Ene[0]);
728 ecalCand.setPs2Energy(ps2Ene[0]);
729 ecalCand.addElementInBlock(blockref,
index);
731 if (!assTracks.empty()) {
732 ecalCand.addElementInBlock(blockref, assTracks.begin()->second);
736 dynamic_cast<const reco::PFBlockElementTrack*>(&
elements[assTracks.begin()->second])
737 ->positionAtECALEntrance();
738 ecalCand.setPositionAtECALEntrance(chargedPosition);
744 connectedToEcal =
true;
746 active[
index] =
false;
747 for (
unsigned ic : tmpi)
748 (*pfCandidates_)[ic].addElementInBlock(blockref, iEcal);
752 bool bNeutralProduced =
false;
755 if (connectedToEcal) {
797 neutralEnergy /= slopeEcal;
799 (*pfCandidates_)[tmpj].setEcalEnergy(pivotalRef->energy(), neutralEnergy);
800 (*pfCandidates_)[tmpj].setHcalEnergy(0., 0.);
801 (*pfCandidates_)[tmpj].setHoEnergy(0., 0.);
802 (*pfCandidates_)[tmpj].setPs1Energy(0.);
803 (*pfCandidates_)[tmpj].setPs2Energy(0.);
804 (*pfCandidates_)[tmpj].addElementInBlock(blockref, iEcal);
805 bNeutralProduced =
true;
806 for (
unsigned ic = 0; ic < kTrack.size(); ++ic)
807 (*
pfCandidates_)[tmpj].addElementInBlock(blockref, kTrack[ic]);
811 for (
unsigned ic = 0; ic < tmpi.size(); ++ic) {
817 double ecalCal = bNeutralProduced ? (calibEcal - neutralEnergy * slopeEcal) *
fraction : calibEcal *
fraction;
818 double ecalRaw = totalEcal *
fraction;
820 LogTrace(
"PFAlgo|recoTracksNotHCAL")
821 <<
"The fraction after photon supression is " <<
fraction <<
" calibrated ecal = " << ecalCal;
823 (*pfCandidates_)[tmpi[ic]].setEcalEnergy(ecalRaw, ecalCal);
824 (*pfCandidates_)[tmpi[ic]].setHcalEnergy(0., 0.);
825 (*pfCandidates_)[tmpi[ic]].setHoEnergy(0., 0.);
826 (*pfCandidates_)[tmpi[ic]].setPs1Energy(0);
827 (*pfCandidates_)[tmpi[ic]].setPs2Energy(0);
828 (*pfCandidates_)[tmpi[ic]].addElementInBlock(blockref, kTrack[ic]);
834 for (
unsigned ic = 0; ic < tmpi.size(); ++ic) {
835 const PFCandidate& pfc = (*pfCandidates_)[tmpi[ic]];
837 if (eleInBlocks.empty()) {
838 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"Single track / Fill element in block! ";
839 (*pfCandidates_)[tmpi[ic]].addElementInBlock(blockref, kTrack[ic]);
842 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"end of function PFAlgo::recoTracksNotHCAL";
855 bool isPrimaryTrack =
856 elements[iElement].displacedVertexRef(PFBlockElement::T_TO_DISP)->displacedVertexRef()->isTherePrimaryTracks();
857 if (isPrimaryTrack) {
858 LogTrace(
"PFAlgo|elementLoop") <<
"Primary Track reconstructed alone";
861 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iElement);
882 bool hasDeadHcal =
false;
883 if (!hcalElems.empty() && deadArea[hcalElems.begin()->second]) {
897 bool goodTrackDeadHcal =
false;
906 trackRef->hitPattern().pixelLayersWithMeasurement() >= 3 &&
907 trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS) == 0 &&
908 trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS) == 0 &&
909 trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS) <=
917 goodTrackDeadHcal =
true;
922 <<
" track pt " << trackRef->pt() <<
" +- " << trackRef->ptError() <<
" layers valid "
923 << trackRef->hitPattern().trackerLayersWithMeasurement() <<
", lost "
924 << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS) <<
", lost outer "
925 << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS) <<
", lost inner "
926 << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS) <<
"(valid fraction "
927 << trackRef->validFraction() <<
")"
930 << trackRef->dzError() << (goodTrackDeadHcal ?
" passes " :
" fails ") <<
"quality cuts";
932 return goodTrackDeadHcal;
936 std::multimap<double, unsigned>& ecalElems,
937 std::multimap<double, unsigned>& hcalElems,
938 const std::vector<bool>& active,
940 unsigned int iTrack) {
942 unsigned index = ecalElems.begin()->second;
943 std::multimap<double, unsigned> sortedTracks;
945 LogTrace(
"PFAlgo|elementLoop") <<
"The closest ECAL cluster is linked to " << sortedTracks.size()
946 <<
" tracks, with distance = " << ecalElems.begin()->first;
948 LogTrace(
"PFAlgo|elementLoop") <<
"Looping over sortedTracks";
950 for (
auto const& trk : sortedTracks) {
951 unsigned jTrack = trk.second;
952 LogTrace(
"PFAlgo|elementLoop") <<
"jTrack=" << jTrack;
956 LogTrace(
"PFAlgo|elementLoop") <<
"active[jTrack]=" << active[jTrack];
959 if (jTrack == iTrack)
961 LogTrace(
"PFAlgo|elementLoop") <<
"skipping jTrack=" << jTrack <<
" for same iTrack";
965 std::multimap<double, unsigned> sortedECAL;
967 if (sortedECAL.begin()->second !=
index)
969 LogTrace(
"PFAlgo|elementLoop") <<
" track " << jTrack <<
" with closest ECAL identical ";
972 std::multimap<double, unsigned> sortedHCAL;
974 if (sortedHCAL.empty())
976 LogTrace(
"PFAlgo|elementLoop") <<
" and with an HCAL cluster " << sortedHCAL.begin()->second;
980 block.setLink(iTrack, sortedHCAL.begin()->second, sortedECAL.begin()->first, linkData, PFBlock::LINKTEST_RECHIT);
987 if (!hcalElems.empty())
988 LogTrace(
"PFAlgo|elementLoop") <<
"Track linked back to HCAL due to ECAL sharing with other tracks";
994 std::vector<bool>& active,
997 std::vector<bool>& deadArea) {
998 LogTrace(
"PFAlgo|elementLoop") <<
"start of function PFAlgo::elementLoop, elements.size()" <<
elements.size();
1000 for (
unsigned iEle = 0; iEle <
elements.size(); iEle++) {
1003 LogTrace(
"PFAlgo|elementLoop") <<
"elements[iEle=" << iEle <<
"]=" <<
elements[iEle];
1007 if (ret_decideType == 1) {
1008 LogTrace(
"PFAlgo|elementLoop") <<
"ret_decideType==1, continuing";
1011 LogTrace(
"PFAlgo|elementLoop") <<
"ret_decideType=" << ret_decideType <<
" type=" <<
type;
1015 if (!active[iEle]) {
1016 LogTrace(
"PFAlgo|elementLoop") <<
"Already used by electrons, muons, conversions";
1023 LogTrace(
"PFAlgo|elementLoop") <<
"PFAlgo:processBlock"
1024 <<
" trackIs.size()=" << inds.
trackIs.size()
1025 <<
" ecalIs.size()=" << inds.
ecalIs.size() <<
" hcalIs.size()=" << inds.
hcalIs.size()
1026 <<
" hoIs.size()=" << inds.
hoIs.size() <<
" hfEmIs.size()=" << inds.
hfEmIs.size()
1027 <<
" hfHadIs.size()=" << inds.
hfHadIs.size();
1033 std::multimap<double, unsigned> ecalElems;
1036 std::multimap<double, unsigned> hcalElems;
1039 std::multimap<double, unsigned> hfEmElems;
1040 std::multimap<double, unsigned> hfHadElems;
1044 LogTrace(
"PFAlgo|elementLoop") <<
"\tTrack " << iEle <<
" is linked to " << ecalElems.size() <<
" ecal and "
1045 << hcalElems.size() <<
" hcal and " << hfEmElems.size() <<
" hfEm and "
1046 << hfHadElems.size() <<
" hfHad elements";
1049 for (
const auto& pair : ecalElems) {
1050 LogTrace(
"PFAlgo|elementLoop") <<
"ecal: dist " << pair.first <<
"\t elem " << pair.second;
1052 for (
const auto& pair : hcalElems) {
1053 LogTrace(
"PFAlgo|elementLoop") <<
"hcal: dist " << pair.first <<
"\t elem " << pair.second
1054 << (deadArea[pair.second] ?
" DEAD AREA MARKER" :
"");
1067 if (hcalElems.empty() && !ecalElems.empty() && !hasDeadHcal) {
1078 std::multimap<double, unsigned> gsfElems;
1081 if (hcalElems.empty()) {
1082 LogTrace(
"PFAlgo|elementLoop") <<
"no hcal element connected to track " << iEle;
1086 bool hcalFound =
false;
1087 bool hfhadFound =
false;
1089 LogTrace(
"PFAlgo|elementLoop") <<
"now looping on elements associated to the track: ecalElems";
1093 for (
auto const&
ecal : ecalElems) {
1098 double dist =
ecal.first;
1099 LogTrace(
"PFAlgo|elementLoop") <<
"\telement " <<
elements[
index] <<
" linked with distance = " << dist;
1101 LogTrace(
"PFAlgo|elementLoop") <<
"This ECAL is already used - skip it";
1113 if (!hcalElems.empty())
1114 LogTrace(
"PFAlgo|elementLoop") <<
"\t\tat least one hcal element connected to the track."
1115 <<
" Sparing Ecal cluster for the hcal loop";
1122 if (hcalElems.empty() && hfHadElems.empty()) {
1124 block, linkData,
elements, blockref, active, goodTrackDeadHcal, hasDeadHcal, iEle, ecalElems, trackRef);
1132 for (
auto const&
hcal : hcalElems) {
1139 LogTrace(
"PFAlgo|elementLoop") <<
"\telement " <<
elements[
index] <<
" linked with distance " << dist;
1146 LogTrace(
"PFAlgo|elementLoop") <<
"\t\tclosest hcal cluster, doing nothing";
1154 LogTrace(
"PFAlgo|elementLoop") <<
"\t\tsecondary hcal cluster. unlinking";
1155 block.setLink(iEle,
index, -1., linkData, PFBlock::LINKTEST_RECHIT);
1162 for (
auto const& hfhad : hfHadElems) {
1163 unsigned index = hfhad.second;
1169 LogTrace(
"PFAlgo|elementLoop") <<
"\telement " <<
elements[
index] <<
" linked with distance " << dist;
1176 LogTrace(
"PFAlgo|elementLoop") <<
"\t\tclosest hfhad cluster, doing nothing";
1182 LogTrace(
"PFAlgo|elementLoop") <<
"\t\tsecondary hfhad cluster. unlinking";
1183 block.setLink(iEle,
index, -1., linkData, PFBlock::LINKTEST_RECHIT);
1187 LogTrace(
"PFAlgo|elementLoop") <<
"end of loop over iEle";
1189 LogTrace(
"PFAlgo|elementLoop") <<
"end of function PFAlgo::elementLoop";
1197 std::vector<bool>& active,
1199 std::vector<bool>& deadArea,
1200 unsigned int iEle) {
1202 case PFBlockElement::TRACK:
1205 LogTrace(
"PFAlgo|decideType") <<
"TRACK, stored index, continue";
1210 inds.
ecalIs.push_back(iEle);
1211 LogTrace(
"PFAlgo|decideType") <<
"ECAL, stored index, continue";
1217 LogTrace(
"PFAlgo|decideType") <<
"HCAL DEAD AREA: remember and skip.";
1218 active[iEle] =
false;
1219 deadArea[iEle] =
true;
1222 inds.
hcalIs.push_back(iEle);
1223 LogTrace(
"PFAlgo|decideType") <<
"HCAL, stored index, continue";
1229 inds.
hoIs.push_back(iEle);
1230 LogTrace(
"PFAlgo|decideType") <<
"HO, stored index, continue";
1234 case PFBlockElement::HFEM:
1236 inds.
hfEmIs.push_back(iEle);
1237 LogTrace(
"PFAlgo|decideType") <<
"HFEM, stored index, continue";
1240 case PFBlockElement::HFHAD:
1243 LogTrace(
"PFAlgo|decideType") <<
"HFHAD, stored index, continue";
1249 LogTrace(
"PFAlgo|decideType") <<
"Did not match type to anything, return 0";
1256 std::vector<bool>& active,
1259 LogTrace(
"PFAlgo|createCandidatesHF") <<
"starting function PFAlgo::createCandidatesHF";
1261 bool trackInBlock = !inds.
trackIs.empty();
1265 for (
unsigned iEle = 0; iEle <
elements.size(); iEle++) {
1267 if (
type == PFBlockElement::TRACK) {
1268 trackInBlock =
true;
1283 std::multimap<double, unsigned> sortedTracks;
1284 std::multimap<double, unsigned> sortedTracksActive;
1286 std::multimap<unsigned, std::pair<double, unsigned>> associatedHfEms;
1288 std::multimap<double, std::pair<unsigned, double>> hfemSatellites;
1293 for (
unsigned iHfHad : inds.
hfHadIs) {
1300 sortedTracks.clear();
1301 sortedTracksActive.clear();
1302 associatedHfEms.clear();
1303 hfemSatellites.clear();
1306 block.associatedElements(
1309 LogTrace(
"PFAlgo|createCandidatesHF") <<
"elements[" << iHfHad <<
"]=" <<
elements[iHfHad];
1311 if (sortedTracks.empty()) {
1312 LogTrace(
"PFAlgo|createCandidatesHCF") <<
"\tno associated tracks, keep for later";
1317 active[iHfHad] =
false;
1319 LogTrace(
"PFAlgo|createCandidatesHF") << sortedTracks.size() <<
" associated tracks:";
1321 double totalChargedMomentum = 0.;
1322 double sumpError2 = 0.;
1327 for (
auto const& trk : sortedTracks) {
1328 unsigned iTrack = trk.second;
1331 if (!active[iTrack])
1346 sumpError2 +=
dp *
dp;
1349 sortedTracksActive.emplace(trk);
1352 std::multimap<double, unsigned> sortedHfEms;
1353 block.associatedElements(
1356 LogTrace(
"PFAlgo|createCandidatesHF") <<
"number of HfEm elements linked to this track: " << sortedHfEms.size();
1358 bool connectedToHfEm =
false;
1363 for (
auto const& hfem : sortedHfEms) {
1364 unsigned iHfEm = hfem.second;
1365 double dist = hfem.first;
1368 if (!active[iHfEm]) {
1369 LogTrace(
"PFAlgo|createCandidatesHF") <<
"cluster locked";
1380 std::multimap<double, unsigned> sortedTracksHfEm;
1381 block.associatedElements(
1383 unsigned jTrack = sortedTracksHfEm.begin()->second;
1384 if (jTrack != iTrack)
1388 double hfemEnergy = eclusterRef->energy();
1390 if (!connectedToHfEm) {
1393 connectedToHfEm =
true;
1394 std::pair<unsigned, double> satellite(iHfEm, hfemEnergy);
1395 hfemSatellites.emplace(-1., satellite);
1400 std::pair<unsigned, double> satellite(iHfEm, hfemEnergy);
1401 hfemSatellites.emplace(dist, satellite);
1404 std::pair<double, unsigned> associatedHfEm(distHfEm, iHfEm);
1405 associatedHfEms.emplace(iTrack, associatedHfEm);
1411 double uncalibratedenergyHfHad = hclusterRef->energy();
1412 double energyHfHad = uncalibratedenergyHfHad;
1415 uncalibratedenergyHfHad,
1416 hclusterRef->positionREP().Eta(),
1417 hclusterRef->positionREP().Phi());
1419 double calibFactorHfHad = (uncalibratedenergyHfHad > 0.) ? energyHfHad / uncalibratedenergyHfHad : 1.;
1422 double energyHfEmTmp = 0.;
1423 double uncalibratedenergyHfEmTmp = 0.;
1424 double energyHfEm = 0.;
1425 double uncalibratedenergyHfEm = 0.;
1429 caloResolution *= totalChargedMomentum;
1430 double totalError =
sqrt(caloResolution * caloResolution + sumpError2);
1431 double nsigmaHFEM =
nSigmaHFEM(totalChargedMomentum);
1432 double nsigmaHFHAD =
nSigmaHFHAD(totalChargedMomentum);
1435 if (sortedTracksActive.empty()) {
1437 std::multimap<double, unsigned> sortedHfEms;
1438 std::multimap<double, unsigned> sortedHfEmsActive;
1439 block.associatedElements(
1444 if (!sortedHfEms.empty()) {
1445 for (
auto const& hfem : sortedHfEms) {
1446 unsigned iHfEm = hfem.second;
1450 sortedHfEmsActive.emplace(hfem);
1453 double hfemEnergy = eclusterRef->energy();
1454 uncalibratedenergyHfEm += hfemEnergy;
1455 energyHfEm = uncalibratedenergyHfEm;
1458 uncalibratedenergyHfEm, 0.0, eclusterRef->positionREP().Eta(), eclusterRef->positionREP().Phi());
1460 0.0, uncalibratedenergyHfHad, hclusterRef->positionREP().Eta(), hclusterRef->positionREP().Phi());
1467 (*pfCandidates_)[tmpi].setHcalEnergy(uncalibratedenergyHfHad, energyHfHad);
1468 (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHfEm, energyHfEm);
1469 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfHad);
1470 for (
auto const& hfem : sortedHfEmsActive) {
1471 unsigned iHfEm = hfem.second;
1472 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfEm);
1473 active[iHfEm] =
false;
1480 else if ((energyHfHad - totalChargedMomentum) > nsigmaHFHAD * totalError) {
1481 assert(energyHfEm == 0.);
1483 double energyHfHadExcess =
max(energyHfHad - totalChargedMomentum, 0.);
1484 double uncalibratedenergyHfHadExcess = energyHfHadExcess / calibFactorHfHad;
1486 (*pfCandidates_)[tmpi].setHcalEnergy(uncalibratedenergyHfHadExcess, energyHfHadExcess);
1487 (*pfCandidates_)[tmpi].setEcalEnergy(0., 0.);
1488 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfHad);
1489 energyHfHad =
max(energyHfHad - energyHfHadExcess, 0.);
1490 uncalibratedenergyHfHad =
max(uncalibratedenergyHfHad - uncalibratedenergyHfHadExcess, 0.);
1498 for (
auto const& hfemSatellite : hfemSatellites) {
1500 uncalibratedenergyHfEmTmp += std::get<1>(hfemSatellite.second);
1501 energyHfEmTmp = uncalibratedenergyHfEmTmp;
1502 double energyHfHadTmp = uncalibratedenergyHfHad;
1503 unsigned iHfEm = std::get<0>(hfemSatellite.second);
1508 uncalibratedenergyHfEmTmp, 0.0, eclusterRef->positionREP().Eta(), eclusterRef->positionREP().Phi());
1510 0.0, uncalibratedenergyHfHad, hclusterRef->positionREP().Eta(), hclusterRef->positionREP().Phi());
1513 double caloEnergyTmp = energyHfEmTmp + energyHfHadTmp;
1514 double calibFactorHfEm = (uncalibratedenergyHfEmTmp > 0.) ? energyHfEmTmp / uncalibratedenergyHfEmTmp : 1.;
1518 if (hfemSatellite.first < 0. || caloEnergyTmp < totalChargedMomentum) {
1519 LogTrace(
"PFAlgo|createCandidatesHF")
1520 <<
"\t\t\tactive, adding " << std::get<1>(hfemSatellite.second) <<
" to HFEM energy, and locking";
1521 active[std::get<0>(hfemSatellite.second)] =
false;
1523 if (hfemSatellite.first < 0. && (caloEnergyTmp - totalChargedMomentum) > nsigmaHFEM * totalError) {
1525 double energyHfEmExcess =
max(caloEnergyTmp - totalChargedMomentum, 0.);
1526 double uncalibratedenergyHfEmExcess = energyHfEmExcess / calibFactorHfEm;
1528 (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHfEmExcess, energyHfEmExcess);
1529 (*pfCandidates_)[tmpi].setHcalEnergy(0, 0.);
1530 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfEm);
1531 energyHfEmTmp =
max(energyHfEmTmp - energyHfEmExcess, 0.);
1532 uncalibratedenergyHfEmTmp =
max(uncalibratedenergyHfEmTmp - uncalibratedenergyHfEmExcess, 0.);
1534 energyHfEm = energyHfEmTmp;
1535 uncalibratedenergyHfEm = uncalibratedenergyHfEmTmp;
1536 energyHfHad = energyHfHadTmp;
1546 for (
auto const& trk : sortedTracksActive) {
1547 unsigned iTrack = trk.second;
1557 active[iTrack] =
false;
1558 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfHad);
1559 auto myHfEms = associatedHfEms.equal_range(iTrack);
1560 for (
auto ii = myHfEms.first;
ii != myHfEms.second; ++
ii) {
1561 unsigned iHfEm =
ii->second.second;
1564 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfEm);
1567 if (totalChargedMomentum)
1568 frac = trackRef->p() / totalChargedMomentum;
1569 (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHfEm *
frac, energyHfEm *
frac);
1570 (*pfCandidates_)[tmpi].setHcalEnergy(uncalibratedenergyHfHad *
frac, energyHfHad *
frac);
1579 for (
unsigned iHfEm = 0; iHfEm <
elements.size(); iHfEm++) {
1581 if (
type == PFBlockElement::HFEM && active[iHfEm]) {
1584 double uncalibratedenergyHF = 0.;
1591 uncalibratedenergyHF, eclusterRef->positionREP().Eta(), eclusterRef->positionREP().Phi());
1594 (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHF,
energyHF);
1595 (*pfCandidates_)[tmpi].setHcalEnergy(0., 0.);
1596 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfEm);
1597 active[iHfEm] =
false;
1598 LogTrace(
"PFAlgo|createCandidatesHF") <<
"HF EM alone from blocks with tracks! " <<
energyHF;
1612 double uncalibratedenergyHF = 0.;
1614 switch (clusterRef->layer()) {
1621 uncalibratedenergyHF, clusterRef->positionREP().Eta(), clusterRef->positionREP().Phi());
1624 (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHF,
energyHF);
1625 (*pfCandidates_)[tmpi].setHcalEnergy(0., 0.);
1626 (*pfCandidates_)[tmpi].setHoEnergy(0., 0.);
1627 (*pfCandidates_)[tmpi].setPs1Energy(0.);
1628 (*pfCandidates_)[tmpi].setPs2Energy(0.);
1629 (*pfCandidates_)[tmpi].addElementInBlock(blockref, inds.
hfEmIs[0]);
1638 uncalibratedenergyHF, clusterRef->positionREP().Eta(), clusterRef->positionREP().Phi());
1641 (*pfCandidates_)[tmpi].setHcalEnergy(uncalibratedenergyHF,
energyHF);
1642 (*pfCandidates_)[tmpi].setEcalEnergy(0., 0.);
1643 (*pfCandidates_)[tmpi].setHoEnergy(0., 0.);
1644 (*pfCandidates_)[tmpi].setPs1Energy(0.);
1645 (*pfCandidates_)[tmpi].setPs2Energy(0.);
1646 (*pfCandidates_)[tmpi].addElementInBlock(blockref, inds.
hfHadIs[0]);
1661 edm::LogError(
"PFAlgo::createCandidatesHF") <<
"Error: 2 elements, but not 1 HFEM and 1 HFHAD";
1668 double energyHfEm = cem->energy();
1669 double energyHfHad = chad->energy();
1670 double uncalibratedenergyHfEm = energyHfEm;
1671 double uncalibratedenergyHfHad = energyHfHad;
1674 uncalibratedenergyHfEm, 0.0,
c0->positionREP().Eta(),
c0->positionREP().Phi());
1676 0.0, uncalibratedenergyHfHad,
c1->positionREP().Eta(),
c1->positionREP().Phi());
1679 cand.setEcalEnergy(uncalibratedenergyHfEm, energyHfEm);
1680 cand.setHcalEnergy(uncalibratedenergyHfHad, energyHfHad);
1681 cand.setHoEnergy(0., 0.);
1682 cand.setPs1Energy(0.);
1683 cand.setPs2Energy(0.);
1684 cand.addElementInBlock(blockref, inds.
hfEmIs[0]);
1685 cand.addElementInBlock(blockref, inds.
hfHadIs[0]);
1686 LogTrace(
"PFAlgo|createCandidatesHF") <<
"HF EM+HAD found ! " << energyHfEm <<
" " << energyHfHad;
1690 <<
"Warning: HF, but n elem different from 1 or 2 or >=3 or !trackIs.empty()";
1693 LogTrace(
"PFAlgo|createCandidateHF") <<
"end of function PFAlgo::createCandidateHF";
1699 std::vector<bool>& active,
1702 std::vector<bool>& deadArea) {
1703 LogTrace(
"PFAlgo|createCandidatesHCAL")
1704 <<
"start of function PFAlgo::createCandidatesHCAL, inds.hcalIs.size()=" << inds.
hcalIs.size();
1708 for (
unsigned iHcal : inds.
hcalIs) {
1713 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"elements[" << iHcal <<
"]=" <<
elements[iHcal];
1716 std::multimap<double, unsigned> sortedTracks;
1719 std::multimap<unsigned, std::pair<double, unsigned>> associatedEcals;
1721 std::map<unsigned, std::pair<double, double>> associatedPSs;
1723 std::multimap<double, std::pair<unsigned, bool>> associatedTracks;
1726 std::multimap<double, std::tuple<unsigned, ::math::XYZVector, double>>
1728 std::tuple<unsigned, ::math::XYZVector, double> fakeSatellite(iHcal, ::
math::XYZVector(0., 0., 0.), 1.);
1729 ecalSatellites.emplace(-1., fakeSatellite);
1731 std::multimap<unsigned, std::pair<double, unsigned>> associatedHOs;
1743 if (sortedTracks.empty()) {
1744 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\tno associated tracks, keep for later";
1749 active[iHcal] =
false;
1756 LogTrace(
"PFAlgo|createCandidatesHCAL") << sortedTracks.size() <<
" associated tracks:";
1758 double totalChargedMomentum = 0;
1759 double sumpError2 = 0.;
1760 double totalHO = 0.;
1761 double totalEcal = 0.;
1762 double totalEcalEGMCalib = 0.;
1763 double totalHcal = hclusterref->energy();
1764 vector<double> hcalP;
1765 vector<double> hcalDP;
1766 vector<unsigned> tkIs;
1767 double maxDPovP = -9999.;
1770 vector<unsigned> chargedHadronsIndices;
1771 vector<unsigned> chargedHadronsInBlock;
1772 double mergedNeutralHadronEnergy = 0;
1773 double mergedPhotonEnergy = 0;
1774 double muonHCALEnergy = 0.;
1775 double muonECALEnergy = 0.;
1776 double muonHCALError = 0.;
1777 double muonECALError = 0.;
1781 std::vector<std::tuple<unsigned, ::math::XYZVector, double>>
1783 double sumEcalClusters = 0;
1785 hclusterref->position().X(), hclusterref->position().Y(), hclusterref->position().Z());
1786 hadronDirection = hadronDirection.Unit();
1790 for (
auto const& trk : sortedTracks) {
1791 unsigned iTrack = trk.second;
1794 if (!active[iTrack])
1805 dynamic_cast<const reco::PFBlockElementTrack*>(&
elements[iTrack])->positionAtECALEntrance();
1806 ::math::XYZVector chargedDirection(chargedPosition.X(), chargedPosition.Y(), chargedPosition.Z());
1807 chargedDirection = chargedDirection.Unit();
1810 std::multimap<double, unsigned> sortedEcals;
1813 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"number of Ecal elements linked to this track: " << sortedEcals.size();
1816 std::multimap<double, unsigned> sortedHOs;
1820 LogTrace(
"PFAlgo|createCandidatesHCAL")
1821 <<
"PFAlgo : number of HO elements linked to this track: " << sortedHOs.size();
1828 bool thisIsALooseMuon =
false;
1835 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"This track is identified as a muon - remove it from the stack";
1842 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iTrack);
1843 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHcal);
1849 bool letMuonEatCaloEnergy =
false;
1851 if (thisIsAnIsolatedMuon) {
1853 double totalCaloEnergy = totalHcal / 1.30;
1855 if (!sortedEcals.empty()) {
1856 iEcal = sortedEcals.begin()->second;
1858 totalCaloEnergy += eclusterref->energy();
1864 if (!sortedHOs.empty()) {
1865 iHO = sortedHOs.begin()->second;
1867 totalCaloEnergy += eclusterref->energy() / 1.30;
1872 letMuonEatCaloEnergy =
true;
1875 if (letMuonEatCaloEnergy)
1876 muonHcal = totalHcal;
1877 double muonEcal = 0.;
1879 if (!sortedEcals.empty()) {
1880 iEcal = sortedEcals.begin()->second;
1882 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iEcal);
1884 if (letMuonEatCaloEnergy)
1885 muonEcal = eclusterref->energy();
1887 if (eclusterref->energy() - muonEcal < 0.2)
1888 active[iEcal] =
false;
1889 (*pfCandidates_)[tmpi].setEcalEnergy(eclusterref->energy(), muonEcal);
1894 if (!sortedHOs.empty()) {
1895 iHO = sortedHOs.begin()->second;
1897 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHO);
1899 if (letMuonEatCaloEnergy)
1900 muonHO = hoclusterref->energy();
1902 if (hoclusterref->energy() - muonHO < 0.2)
1903 active[iHO] =
false;
1904 (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal, muonHcal);
1905 (*pfCandidates_)[tmpi].setHoEnergy(hoclusterref->energy(), muonHO);
1908 (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal, muonHcal);
1912 if (letMuonEatCaloEnergy) {
1913 muonHCALEnergy += totalHcal;
1915 muonHCALEnergy += muonHO;
1916 muonHCALError += 0.;
1917 muonECALEnergy += muonEcal;
1918 muonECALError += 0.;
1919 photonAtECAL -= muonEcal * chargedDirection;
1920 hadronAtECAL -= totalHcal * chargedDirection;
1921 if (!sortedEcals.empty())
1922 active[iEcal] =
false;
1923 active[iHcal] =
false;
1924 if (
useHO_ && !sortedHOs.empty())
1925 active[iHO] =
false;
1937 photonAtECAL -=
muonECAL_[0] * chargedDirection;
1938 hadronAtECAL -=
muonHCAL_[0] * chargedDirection;
1942 active[iTrack] =
false;
1949 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"elements[iTrack=" << iTrack <<
"]=" <<
elements[iTrack];
1957 if (thisIsALooseMuon && !thisIsAMuon)
1963 double dpt = trackRef->ptError();
1968 if (isPrimaryOrSecondary)
1971 std::pair<unsigned, bool> tkmuon(iTrack, thisIsALooseMuon);
1972 associatedTracks.emplace(-dpt * blowError, tkmuon);
1976 sumpError2 +=
dp *
dp;
1978 bool connectedToEcal =
false;
1979 if (!sortedEcals.empty()) {
1982 for (
auto const&
ecal : sortedEcals) {
1983 unsigned iEcal =
ecal.second;
1984 double dist =
ecal.first;
1987 if (!active[iEcal]) {
1988 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"cluster locked";
1999 std::multimap<double, unsigned> sortedTracksEcal;
2000 block.associatedElements(
2002 unsigned jTrack = sortedTracksEcal.begin()->second;
2003 if (jTrack != iTrack)
2008 float ecalEnergyCalibrated = eclusterref->correctedEnergy();
2009 float ecalEnergy = eclusterref->energy();
2011 eclusterref->position().X(), eclusterref->position().Y(), eclusterref->position().Z());
2012 photonDirection = photonDirection.Unit();
2014 if (!connectedToEcal) {
2018 connectedToEcal =
true;
2023 double ecalCalibFactor = (ecalEnergy > 1E-9) ? ecalEnergyCalibrated / ecalEnergy : 1.;
2024 std::tuple<unsigned, ::math::XYZVector, double> satellite(
2025 iEcal, ecalEnergy * photonDirection, ecalCalibFactor);
2026 ecalSatellites.emplace(-1., satellite);
2031 double ecalCalibFactor = (ecalEnergy > 1E-9) ? ecalEnergyCalibrated / ecalEnergy : 1.;
2032 std::tuple<unsigned, ::math::XYZVector, double> satellite(
2033 iEcal, ecalEnergy * photonDirection, ecalCalibFactor);
2034 ecalSatellites.emplace(dist, satellite);
2037 std::pair<double, unsigned> associatedEcal(distEcal, iEcal);
2038 associatedEcals.emplace(iTrack, associatedEcal);
2043 if (
useHO_ && !sortedHOs.empty()) {
2046 for (
auto const&
ho : sortedHOs) {
2047 unsigned iHO =
ho.second;
2048 double distHO =
ho.first;
2052 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"cluster locked";
2063 std::multimap<double, unsigned> sortedTracksHO;
2064 block.associatedElements(
2066 unsigned jTrack = sortedTracksHO.begin()->second;
2067 if (jTrack != iTrack)
2076 totalHO += hoclusterref->energy();
2077 active[iHO] =
false;
2079 std::pair<double, unsigned> associatedHO(distHO, iHO);
2080 associatedHOs.emplace(iTrack, associatedHO);
2088 totalHcal += totalHO;
2092 double caloEnergy = 0.;
2093 double slopeEcal = 1.0;
2094 double calibEcal = 0.;
2095 double calibHcal = 0.;
2096 hadronDirection = hadronAtECAL.Unit();
2100 caloResolution *= totalChargedMomentum;
2102 caloResolution =
std::sqrt(caloResolution * caloResolution + muonHCALError + muonECALError);
2103 totalEcal -=
std::min(totalEcal, muonECALEnergy);
2104 totalEcalEGMCalib -=
std::min(totalEcalEGMCalib, muonECALEnergy);
2105 totalHcal -=
std::min(totalHcal, muonHCALEnergy);
2106 if (totalEcal < 1E-9)
2108 if (totalHcal < 1E-9)
2115 for (
auto const& ecalSatellite : ecalSatellites) {
2117 double previousCalibEcal = calibEcal;
2118 double previousCalibHcal = calibHcal;
2119 double previousCaloEnergy = caloEnergy;
2120 double previousSlopeEcal = slopeEcal;
2124 sqrt(std::get<1>(ecalSatellite.second).Mag2());
2125 totalEcalEGMCalib +=
sqrt(std::get<1>(ecalSatellite.second).Mag2()) *
2126 std::get<2>(ecalSatellite.second);
2127 photonAtECAL += std::get<1>(ecalSatellite.second) *
2128 std::get<2>(ecalSatellite.second);
2129 calibEcal =
std::max(0., totalEcal);
2130 calibHcal =
std::max(0., totalHcal);
2131 hadronAtECAL = calibHcal * hadronDirection;
2136 hclusterref->positionREP().Eta(),
2137 hclusterref->positionREP().Phi());
2138 caloEnergy = calibEcal + calibHcal;
2140 slopeEcal = calibEcal / totalEcal;
2142 hadronAtECAL = calibHcal * hadronDirection;
2146 if (ecalSatellite.first < 0. || caloEnergy - totalChargedMomentum <= 0.) {
2147 LogTrace(
"PFAlgo|createCandidatesHCAL")
2148 <<
"\t\t\tactive, adding " << std::get<1>(ecalSatellite.second) <<
" to ECAL energy, and locking";
2149 active[std::get<0>(ecalSatellite.second)] =
false;
2150 double clusterEnergy =
2151 sqrt(std::get<1>(ecalSatellite.second).Mag2()) *
2152 std::get<2>(ecalSatellite.second);
2153 if (clusterEnergy > 50) {
2155 sumEcalClusters += clusterEnergy;
2162 totalEcal -=
sqrt(std::get<1>(ecalSatellite.second).Mag2());
2163 totalEcalEGMCalib -=
sqrt(std::get<1>(ecalSatellite.second).Mag2()) * std::get<2>(ecalSatellite.second);
2164 photonAtECAL -= std::get<1>(ecalSatellite.second) * std::get<2>(ecalSatellite.second);
2165 calibEcal = previousCalibEcal;
2166 calibHcal = previousCalibHcal;
2167 hadronAtECAL = previousHadronAtECAL;
2168 slopeEcal = previousSlopeEcal;
2169 caloEnergy = previousCaloEnergy;
2189 if (totalChargedMomentum - caloEnergy >
nSigmaTRACK_ * caloResolution) {
2192 for (
auto const& trk : associatedTracks) {
2194 if (!trk.second.second)
2197 const unsigned int iTrack = trk.second.first;
2199 if (!active[iTrack])
2205 std::multimap<double, unsigned> sortedEcals;
2206 block.associatedElements(
2208 std::multimap<double, unsigned> sortedHOs;
2214 muon.addElementInBlock(blockref, iTrack);
2215 muon.addElementInBlock(blockref, iHcal);
2218 muon.setHcalEnergy(totalHcal, muonHcal);
2219 if (!sortedEcals.empty()) {
2220 const unsigned int iEcal = sortedEcals.begin()->second;
2222 muon.addElementInBlock(blockref, iEcal);
2224 muon.setEcalEnergy(eclusterref->energy(), muonEcal);
2226 if (
useHO_ && !sortedHOs.empty()) {
2227 const unsigned int iHO = sortedHOs.begin()->second;
2229 muon.addElementInBlock(blockref, iHO);
2231 muon.setHcalEnergy(
max(totalHcal - totalHO, 0.0), muonHcal);
2232 muon.setHoEnergy(hoclusterref->energy(), muonHO);
2237 dynamic_cast<const reco::PFBlockElementTrack*>(&
elements[trk.second.first])->positionAtECALEntrance();
2238 ::math::XYZVector chargedDirection(chargedPosition.X(), chargedPosition.Y(), chargedPosition.Z());
2239 chargedDirection = chargedDirection.Unit();
2249 photonAtECAL -=
muonECAL_[0] * chargedDirection;
2251 hadronAtECAL -=
muonHCAL_[0] * calibHcal / totalHcal * chargedDirection;
2252 caloEnergy = calibEcal + calibHcal;
2258 if (totalHcal > 0.) {
2265 active[iTrack] =
false;
2272 caloResolution *= totalChargedMomentum;
2273 caloResolution =
std::sqrt(caloResolution * caloResolution + muonHCALError + muonECALError);
2278 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\tBefore Cleaning ";
2279 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\tCompare Calo Energy to total charged momentum ";
2280 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tsum p = " << totalChargedMomentum <<
" +- " <<
sqrt(sumpError2);
2281 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tsum ecal = " << totalEcal;
2282 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tsum hcal = " << totalHcal;
2283 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\t => Calo Energy = " << caloEnergy <<
" +- " << caloResolution;
2284 LogTrace(
"PFAlgo|createCandidatesHCAL")
2285 <<
"\t\t => Calo Energy- total charged momentum = " << caloEnergy - totalChargedMomentum <<
" +- "
2286 <<
sqrt(sumpError2 + caloResolution * caloResolution);
2290 unsigned corrTrack = 10000000;
2291 double corrFact = 1.;
2294 for (
auto const& trk : associatedTracks) {
2295 const unsigned iTrack = trk.second.first;
2297 if (!active[iTrack])
2301 const double dptRel = fabs(trk.first) / trackref->pt() * 100;
2311 const double wouldBeTotalChargedMomentum = totalChargedMomentum - trackref->p();
2315 if (wouldBeTotalChargedMomentum > caloEnergy) {
2317 LogTrace(
"PFAlgo|createCandidatesHCAL")
2318 <<
"In bad track rejection step dptRel = " << dptRel <<
" dptRel_DispVtx_ = " <<
dptRel_DispVtx_;
2319 LogTrace(
"PFAlgo|createCandidatesHCAL")
2320 <<
"The calo energy would be still smaller even without this track but it is attached to a NI";
2325 active[iTrack] =
false;
2326 totalChargedMomentum = wouldBeTotalChargedMomentum;
2327 LogTrace(
"PFAlgo|createCandidatesHCAL")
2328 <<
"\tElement " <<
elements[iTrack] <<
" rejected (dpt = " << -trk.first
2329 <<
" GeV/c, algo = " << trackref->algo() <<
")";
2335 corrFact = (caloEnergy - wouldBeTotalChargedMomentum) /
elements[trk.second.first].trackRef()->p();
2336 if (trackref->p() * corrFact < 0.05) {
2338 active[iTrack] =
false;
2340 totalChargedMomentum -= trackref->p() * (1. - corrFact);
2341 LogTrace(
"PFAlgo|createCandidatesHCAL")
2342 <<
"\tElement " <<
elements[iTrack] <<
" (dpt = " << -trk.first <<
" GeV/c, algo = " << trackref->algo()
2343 <<
") rescaled by " << corrFact <<
" Now the total charged momentum is " << totalChargedMomentum;
2351 caloResolution *= totalChargedMomentum;
2352 caloResolution =
std::sqrt(caloResolution * caloResolution + muonHCALError + muonECALError);
2358 totalChargedMomentum - caloEnergy >
nSigmaTRACK_ * caloResolution) {
2359 for (
auto const& trk : associatedTracks) {
2360 unsigned iTrack = trk.second.first;
2362 if (!active[iTrack])
2365 double dptRel = fabs(trk.first) / trackref->pt() * 100;
2372 active[iTrack] =
false;
2373 totalChargedMomentum -= trackref->p();
2375 LogTrace(
"PFAlgo|createCandidatesHCAL")
2376 <<
"\tElement " <<
elements[iTrack] <<
" rejected (dpt = " << -trk.first
2377 <<
" GeV/c, algo = " << trackref->algo() <<
")";
2384 caloResolution *= totalChargedMomentum;
2385 caloResolution =
std::sqrt(caloResolution * caloResolution + muonHCALError + muonECALError);
2389 for (
auto const& trk : associatedTracks) {
2390 unsigned iTrack = trk.second.first;
2391 if (!active[iTrack])
2398 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iTrack);
2399 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHcal);
2401 auto myEcals = associatedEcals.equal_range(iTrack);
2402 for (
auto ii = myEcals.first;
ii != myEcals.second; ++
ii) {
2403 unsigned iEcal =
ii->second.second;
2406 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iEcal);
2410 auto myHOs = associatedHOs.equal_range(iTrack);
2411 for (
auto ii = myHOs.first;
ii != myHOs.second; ++
ii) {
2412 unsigned iHO =
ii->second.second;
2415 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHO);
2419 if (iTrack == corrTrack) {
2422 (*pfCandidates_)[tmpi].rescaleMomentum(corrFact);
2425 chargedHadronsIndices.push_back(tmpi);
2426 chargedHadronsInBlock.push_back(iTrack);
2427 active[iTrack] =
false;
2429 hcalDP.push_back(
dp);
2432 sumpError2 +=
dp *
dp;
2436 double totalError =
sqrt(sumpError2 + caloResolution * caloResolution);
2439 LogTrace(
"PFAlgo|createCandidatesHCAL")
2440 <<
"\tCompare Calo Energy to total charged momentum " << endl
2441 <<
"\t\tsum p = " << totalChargedMomentum <<
" +- " <<
sqrt(sumpError2) << endl
2442 <<
"\t\tsum ecal = " << totalEcal << endl
2443 <<
"\t\tsum hcal = " << totalHcal << endl
2444 <<
"\t\t => Calo Energy = " << caloEnergy <<
" +- " << caloResolution << endl
2445 <<
"\t\t => Calo Energy- total charged momentum = " << caloEnergy - totalChargedMomentum <<
" +- "
2452 double nsigma =
nSigmaHCAL(totalChargedMomentum, hclusterref->positionREP().Eta());
2454 if (
abs(totalChargedMomentum - caloEnergy) < nsigma * totalError) {
2459 LogTrace(
"PFAlgo|createCandidatesHCAL")
2460 <<
"\t\tcase 1: COMPATIBLE "
2461 <<
"|Calo Energy- total charged momentum| = " <<
abs(caloEnergy - totalChargedMomentum) <<
" < " << nsigma
2462 <<
" x " << totalError;
2464 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\t\tmax DP/P = " << maxDPovP <<
" less than 0.1: do nothing ";
2466 LogTrace(
"PFAlgo|createCandidatesHCAL")
2467 <<
"\t\t\tmax DP/P = " << maxDPovP <<
" > 0.1: take weighted averages ";
2471 if (maxDPovP > 0.1) {
2474 int nrows = chargedHadronsIndices.size();
2475 TMatrixTSym<double>
a(nrows);
2477 TVectorD
check(nrows);
2478 double sigma2E = caloResolution * caloResolution;
2479 for (
int i = 0;
i < nrows;
i++) {
2480 double sigma2i = hcalDP[
i] * hcalDP[
i];
2481 LogTrace(
"PFAlgo|createCandidatesHCAL")
2482 <<
"\t\t\ttrack associated to hcal " <<
i <<
" P = " << hcalP[
i] <<
" +- " << hcalDP[
i];
2483 a(
i,
i) = 1. / sigma2i + 1. / sigma2E;
2484 b(
i) = hcalP[
i] / sigma2i + caloEnergy / sigma2E;
2485 for (
int j = 0;
j < nrows;
j++) {
2488 a(
i,
j) = 1. / sigma2E;
2493 TDecompChol decomp(
a);
2495 TVectorD
x = decomp.Solve(
b,
ok);
2499 for (
int i = 0;
i < nrows;
i++) {
2501 unsigned ich = chargedHadronsIndices[
i];
2502 double rescaleFactor =
x(
i) / hcalP[
i];
2503 if (rescaleFactor < 0.)
2505 (*pfCandidates_)[ich].rescaleMomentum(rescaleFactor);
2507 LogTrace(
"PFAlgo|createCandidatesHCAL")
2508 <<
"\t\t\told p " << hcalP[
i] <<
" new p " <<
x(
i) <<
" rescale " << rescaleFactor;
2511 edm::LogError(
"PFAlgo::createCandidatesHCAL") <<
"TDecompChol.Solve returned ok=false";
2518 else if (caloEnergy > totalChargedMomentum) {
2523 double eNeutralHadron = caloEnergy - totalChargedMomentum;
2524 double ePhoton = (caloEnergy - totalChargedMomentum) /
2530 if (!sortedTracks.empty()) {
2531 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tcase 2: NEUTRAL DETECTION " << caloEnergy <<
" > " << nsigma
2532 <<
"x" << totalError <<
" + " << totalChargedMomentum;
2533 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tneutral activity detected: " << endl
2534 <<
"\t\t\t photon = " << ePhoton << endl
2535 <<
"\t\t\tor neutral hadron = " << eNeutralHadron;
2537 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tphoton or hadron ?";
2540 if (sortedTracks.empty())
2541 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tno track -> hadron ";
2543 LogTrace(
"PFAlgo|createCandidatesHCAL")
2544 <<
"\t\t" << sortedTracks.size() <<
" tracks -> check if the excess is photonic or hadronic";
2549 unsigned maxiEcal = 9999;
2553 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"loop over sortedTracks.size()=" << sortedTracks.size();
2554 for (
auto const& trk : sortedTracks) {
2555 unsigned iTrack = trk.second;
2563 auto iae = associatedEcals.find(iTrack);
2565 if (iae == associatedEcals.end())
2569 unsigned iEcal = iae->second.second;
2577 double pTrack = trackRef->p();
2578 double eECAL = clusterRef->energy();
2579 double eECALOverpTrack = eECAL / pTrack;
2583 maxEcalRef = clusterRef;
2589 std::vector<reco::PFClusterRef> pivotalClusterRef;
2590 std::vector<unsigned> iPivotal;
2591 std::vector<double> particleEnergy, ecalEnergy, hcalEnergy, rawecalEnergy, rawhcalEnergy;
2592 std::vector<::math::XYZVector> particleDirection;
2596 if (ePhoton < totalEcal || eNeutralHadron - calibEcal < 1E-10) {
2597 if (!maxEcalRef.
isNull()) {
2599 mergedPhotonEnergy = ePhoton;
2603 if (!maxEcalRef.
isNull()) {
2605 mergedPhotonEnergy = totalEcalEGMCalib;
2608 mergedNeutralHadronEnergy = eNeutralHadron - calibEcal;
2611 if (mergedPhotonEnergy > 0) {
2621 sumEcalClusters =
sqrt(photonAtECAL.Mag2());
2624 const double clusterEnergyCalibrated =
2625 sqrt(std::get<1>(pae).Mag2()) *
2628 particleEnergy.push_back(mergedPhotonEnergy * clusterEnergyCalibrated / sumEcalClusters);
2629 particleDirection.push_back(std::get<1>(pae));
2630 ecalEnergy.push_back(mergedPhotonEnergy * clusterEnergyCalibrated / sumEcalClusters);
2631 hcalEnergy.push_back(0.);
2632 rawecalEnergy.push_back(totalEcal);
2633 rawhcalEnergy.push_back(0.);
2634 pivotalClusterRef.push_back(
elements[std::get<0>(pae)].clusterRef());
2635 iPivotal.push_back(std::get<0>(pae));
2639 if (mergedNeutralHadronEnergy > 1.0) {
2648 sumEcalClusters =
sqrt(hadronAtECAL.Mag2());
2651 const double clusterEnergyCalibrated =
2652 sqrt(std::get<1>(pae).Mag2()) *
2655 particleEnergy.push_back(mergedNeutralHadronEnergy * clusterEnergyCalibrated / sumEcalClusters);
2656 particleDirection.push_back(std::get<1>(pae));
2657 ecalEnergy.push_back(0.);
2658 hcalEnergy.push_back(mergedNeutralHadronEnergy * clusterEnergyCalibrated / sumEcalClusters);
2659 rawecalEnergy.push_back(0.);
2660 rawhcalEnergy.push_back(totalHcal);
2661 pivotalClusterRef.push_back(hclusterref);
2662 iPivotal.push_back(iHcal);
2670 for (
unsigned iPivot = 0; iPivot < iPivotal.size(); ++iPivot) {
2671 if (particleEnergy[iPivot] < 0.)
2673 <<
"ALARM = Negative energy for iPivot=" << iPivot <<
", " << particleEnergy[iPivot];
2675 const bool useDirection =
true;
2677 particleEnergy[iPivot],
2679 particleDirection[iPivot].
X(),
2680 particleDirection[iPivot].
Y(),
2681 particleDirection[iPivot].
Z())];
2683 neutral.setEcalEnergy(rawecalEnergy[iPivot], ecalEnergy[iPivot]);
2685 neutral.setHcalEnergy(rawhcalEnergy[iPivot], hcalEnergy[iPivot]);
2686 neutral.setHoEnergy(0., 0.);
2688 if (rawhcalEnergy[iPivot] == 0.) {
2689 neutral.setHcalEnergy(0., 0.);
2690 neutral.setHoEnergy(0., 0.);
2692 neutral.setHcalEnergy(
max(rawhcalEnergy[iPivot] - totalHO, 0.0),
2693 hcalEnergy[iPivot] *
max(1. - totalHO / rawhcalEnergy[iPivot], 0.));
2694 neutral.setHoEnergy(totalHO, totalHO * hcalEnergy[iPivot] / rawhcalEnergy[iPivot]);
2697 neutral.setPs1Energy(0.);
2698 neutral.setPs2Energy(0.);
2699 neutral.set_mva_nothing_gamma(-1.);
2702 neutral.addElementInBlock(blockref, iHcal);
2703 for (
unsigned iTrack : chargedHadronsInBlock) {
2704 neutral.addElementInBlock(blockref, iTrack);
2707 dynamic_cast<const reco::PFBlockElementTrack*>(&
elements[iTrack])->positionAtECALEntrance();
2708 neutral.setPositionAtECALEntrance(chargedPosition);
2710 auto myEcals = associatedEcals.equal_range(iTrack);
2711 for (
auto ii = myEcals.first;
ii != myEcals.second; ++
ii) {
2712 unsigned iEcal =
ii->second.second;
2715 neutral.addElementInBlock(blockref, iEcal);
2730 double totalHcalEnergyCalibrated =
std::max(calibHcal - mergedNeutralHadronEnergy, 0.);
2732 double totalEcalEnergyCalibrated =
std::max(calibEcal - mergedPhotonEnergy, 0.);
2737 double chargedHadronsTotalEnergy = 0;
2738 for (
unsigned index : chargedHadronsIndices) {
2743 for (
unsigned index : chargedHadronsIndices) {
2752 fraction * totalHcalEnergyCalibrated * (1. - totalHO / totalHcal));
2760 for (
auto const& ecalSatellite : ecalSatellites) {
2762 unsigned iEcal = std::get<0>(ecalSatellite.second);
2773 active[iEcal] =
false;
2776 std::multimap<double, unsigned> assTracks;
2780 double ecalClusterEnergyCalibrated =
2781 sqrt(std::get<1>(ecalSatellite.second).Mag2()) *
2783 ecalSatellite.second);
2785 cand.setEcalEnergy(eclusterref->energy(), ecalClusterEnergyCalibrated);
2786 cand.setHcalEnergy(0., 0.);
2787 cand.setHoEnergy(0., 0.);
2788 cand.setPs1Energy(associatedPSs[iEcal].
first);
2789 cand.setPs2Energy(associatedPSs[iEcal].
second);
2790 cand.addElementInBlock(blockref, iEcal);
2791 cand.addElementInBlock(blockref, sortedTracks.begin()->second);
2793 if (fabs(eclusterref->energy() -
sqrt(std::get<1>(ecalSatellite.second).Mag2())) > 1
e-3 ||
2794 fabs(eclusterref->correctedEnergy() - ecalClusterEnergyCalibrated) > 1
e-3)
2796 <<
"ecalCluster vs ecalSatellites look inconsistent (eCluster E, calibE, ecalSatellite E, calib E): "
2797 << eclusterref->energy() <<
" " << eclusterref->correctedEnergy() <<
" "
2798 <<
sqrt(std::get<1>(ecalSatellite.second).Mag2()) <<
" " << ecalClusterEnergyCalibrated;
2804 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"end of function PFAlgo::createCandidatesHCAL";
2810 std::vector<bool>& active,
2813 std::vector<bool>& deadArea) {
2815 LogTrace(
"PFAlgo|createCandidatesHCALUnlinked")
2816 <<
"start of function PFAlgo::createCandidatesHCALUnlinked, hcalIs.size()=" << inds.
hcalIs.size();
2820 for (
unsigned iHcal : inds.
hcalIs) {
2822 std::vector<unsigned> ecalRefs;
2823 std::vector<unsigned> hoRefs;
2827 if (!active[iHcal]) {
2828 LogTrace(
"PFAlgo|createCandidatesHCALUnlinked") <<
"not active " << iHcal;
2833 std::multimap<double, unsigned> ecalElems;
2837 float totalEcal = 0.;
2840 for (
auto const&
ecal : ecalElems) {
2841 unsigned iEcal =
ecal.second;
2842 double dist =
ecal.first;
2869 std::multimap<double, unsigned> hcalElems;
2872 const bool isClosest = std::none_of(hcalElems.begin(), hcalElems.end(), [&](
auto const&
hcal) {
2873 return active[
hcal.second] &&
hcal.first < dist;
2880 LogTrace(
"PFAlgo|createCandidatesHCALUnlinked")
2881 <<
"\telement " <<
elements[iEcal] <<
" linked with dist " << dist;
2882 LogTrace(
"PFAlgo|createCandidatesHCALUnlinked") <<
"Added to HCAL cluster to form a neutral hadron";
2889 double ecalEnergy = eclusterRef->energy();
2891 totalEcal += ecalEnergy;
2892 if (ecalEnergy > ecalMax) {
2893 ecalMax = ecalEnergy;
2894 eClusterRef = eclusterRef;
2897 ecalRefs.push_back(iEcal);
2898 active[iEcal] =
false;
2903 double totalHO = 0.;
2907 std::multimap<double, unsigned> hoElems;
2915 for (
auto const&
ho : hoElems) {
2916 unsigned iHO =
ho.second;
2917 double dist =
ho.first;
2929 std::multimap<double, unsigned> hcalElems;
2932 const bool isClosest = std::none_of(hcalElems.begin(), hcalElems.end(), [&](
auto const&
hcal) {
2933 return active[
hcal.second] &&
hcal.first < dist;
2941 LogTrace(
"PFAlgo|createCandidatesHCALUnlinked")
2942 <<
"\telement " <<
elements[iHO] <<
" linked with dist " << dist;
2943 LogTrace(
"PFAlgo|createCandidatesHCALUnlinked") <<
"Added to HCAL cluster to form a neutral hadron";
2951 hoclusterRef->energy();
2953 totalHO += hoEnergy;
2954 if (hoEnergy > hoMax) {
2956 hoClusterRef = hoclusterRef;
2960 hoRefs.push_back(iHO);
2961 active[iHO] =
false;
2970 double totalHcal = hclusterRef->energy();
2973 totalHcal += totalHO;
2976 double calibEcal = totalEcal > 0. ? totalEcal : 0.;
2977 double calibHcal =
std::max(0., totalHcal);
2979 calibEcal = totalEcal;
2982 -1., calibEcal, calibHcal, hclusterRef->positionREP().Eta(), hclusterRef->positionREP().Phi());
2987 cand.setEcalEnergy(totalEcal, calibEcal);
2989 cand.setHcalEnergy(totalHcal, calibHcal);
2990 cand.setHoEnergy(0., 0.);
2992 cand.setHcalEnergy(
max(totalHcal - totalHO, 0.0), calibHcal * (1. - totalHO / totalHcal));
2993 cand.setHoEnergy(totalHO, totalHO * calibHcal / totalHcal);
2995 cand.setPs1Energy(0.);
2996 cand.setPs2Energy(0.);
2997 cand.addElementInBlock(blockref, iHcal);
2998 for (
auto const& ec : ecalRefs)
2999 cand.addElementInBlock(blockref, ec);
3000 for (
auto const&
ho : hoRefs)
3001 cand.addElementInBlock(blockref,
ho);
3009 std::vector<bool>& active,
3012 std::vector<bool>& deadArea) {
3013 LogTrace(
"PFAlgo|createCandidatesECAL")
3014 <<
"start of function PFAlgo::createCandidatesECAL(), ecalIs.size()=" << inds.
ecalIs.size();
3020 for (
unsigned i = 0;
i < inds.
ecalIs.size();
i++) {
3021 unsigned iEcal = inds.
ecalIs[
i];
3023 LogTrace(
"PFAlgo|createCandidatesECAL") <<
"elements[" << iEcal <<
"]=" <<
elements[iEcal];
3025 if (!active[iEcal]) {
3026 LogTrace(
"PFAlgo|createCandidatesECAL") <<
"iEcal=" << iEcal <<
" not active";
3036 active[iEcal] =
false;
3038 float ecalEnergy = clusterref->correctedEnergy();
3040 double particleEnergy = ecalEnergy;
3044 cand.setEcalEnergy(clusterref->energy(), ecalEnergy);
3045 cand.setHcalEnergy(0., 0.);
3046 cand.setHoEnergy(0., 0.);
3047 cand.setPs1Energy(0.);
3048 cand.setPs2Energy(0.);
3049 cand.addElementInBlock(blockref, iEcal);
3052 LogTrace(
"PFAlgo|createCandidatesECAL") <<
"end of function PFALgo::createCandidatesECAL";
3056 std::list<reco::PFBlockRef>& hcalBlockRefs,
3057 std::list<reco::PFBlockRef>& ecalBlockRefs,
3062 LogTrace(
"PFAlgo|processBlock") <<
"start of function PFAlgo::processBlock, block=" <<
block;
3070 vector<bool> active(
elements.size(),
true);
3074 std::vector<reco::PFCandidate> tempElectronCandidates;
3075 tempElectronCandidates.clear();
3108 vector<bool> deadArea(
elements.size(),
false);
3117 if (!(inds.hfEmIs.empty() && inds.hfHadIs.empty())) {
3119 if (inds.hcalIs.empty() && inds.ecalIs.empty())
3122 <<
"Block contains HF clusters, and also contains ECAL or HCAL clusters. Continue.\n"
3131 LogTrace(
"PFAlgo|processBlock") <<
"end of function PFAlgo::processBlock";
3136 const auto* eltTrack = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
3146 double pz =
track.pz();
3149 LogTrace(
"PFAlgo|reconstructTrack") <<
"Reconstructing PF candidate from track of pT = " <<
track.pt()
3150 <<
" eta = " <<
track.eta() <<
" phi = " <<
track.phi() <<
" px = " <<
px
3151 <<
" py = " <<
py <<
" pz = " << pz <<
" energy = " <<
energy;
3159 <<
", pt=" << momentum.pt() <<
", eta=" << momentum.eta()
3160 <<
", phi=" << momentum.phi();
3165 pfCandidates_->back().setPositionAtECALEntrance(eltTrack->positionAtECALEntrance());
3177 if ((!
isMuon) && isFromDisp) {
3178 double dpt = trackRef->ptError();
3179 double dptRel = dpt / trackRef->pt() * 100;
3184 LogTrace(
"PFAlgo|reconstructTrack")
3185 <<
"Not refitted px = " <<
px <<
" py = " <<
py <<
" pz = " << pz <<
" energy = " <<
energy;
3189 reco::Track trackRefit = vRef->refittedTrack(trackRef);
3192 trackRefit.
px(), trackRefit.
py(), trackRefit.
pz(),
sqrt(trackRefit.
p() * trackRefit.
p() + 0.13957 * 0.13957));
3193 LogTrace(
"PFAlgo|reconstructTrack")
3194 <<
"Refitted px = " <<
px <<
" py = " <<
py <<
" pz = " << pz <<
" energy = " <<
energy;
3215 double particleEnergy,
3220 LogTrace(
"PFAlgo|reconstructCluster") <<
"start of function PFAlgo::reconstructCluster, cluster=" << cluster
3221 <<
"particleEnergy=" << particleEnergy <<
"useDirection=" << useDirection
3222 <<
"particleX=" << particleX <<
"particleY=" << particleY
3223 <<
"particleZ=" << particleZ;
3233 switch (cluster.
layer()) {
3256 cluster.
position().Y() - vertexPos.Y(),
3257 cluster.
position().Z() - vertexPos.Z());
3259 particleX *
factor - vertexPos.X(), particleY *
factor - vertexPos.Y(), particleZ *
factor - vertexPos.Z());
3264 clusterPos = useDirection ? particleDirection.Unit() : clusterPos.Unit();
3265 clusterPos *= particleEnergy;
3271 ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double>> momentum(
3272 clusterPos.X(), clusterPos.Y(), clusterPos.Z(),
mass);
3282 switch (cluster.
layer()) {
3303 <<
", pt=" <<
tmp.pt() <<
", eta=" <<
tmp.eta() <<
", phi=" <<
tmp.phi();
3326 std::array<double, 7> energyPerDepth;
3327 std::fill(energyPerDepth.begin(), energyPerDepth.end(), 0.0);
3329 const auto&
hit = *hitRefAndFrac.recHitRef();
3331 if (
hit.depth() == 0) {
3335 if (
hit.depth() < 1 ||
hit.depth() > 7) {
3336 throw cms::Exception(
"CorruptData") <<
"Bogus depth " <<
hit.depth() <<
" at detid " <<
hit.detId() <<
"\n";
3338 energyPerDepth[
hit.depth() - 1] += hitRefAndFrac.fraction() *
hit.energy();
3341 double sum = std::accumulate(energyPerDepth.begin(), energyPerDepth.end(), 0.);
3342 std::array<float, 7> depthFractions;
3344 for (
unsigned int i = 0;
i < depthFractions.size(); ++
i) {
3345 depthFractions[
i] = energyPerDepth[
i] / sum;
3348 std::fill(depthFractions.begin(), depthFractions.end(), 0.f);
3350 cand.setHcalDepthEnergyFractions(depthFractions);
3357 clusterEnergyHCAL =
std::max(clusterEnergyHCAL, 1.);
3359 double resol = fabs(
eta) < 1.48 ?
sqrt(1.02 * 1.02 / clusterEnergyHCAL + 0.065 * 0.065)
3360 :
sqrt(1.20 * 1.20 / clusterEnergyHCAL + 0.028 * 0.028);
3374 clusterEnergyHF =
std::max(clusterEnergyHF, 1.);
3398 out <<
"====== Particle Flow Algorithm ======= ";
3400 out <<
"nSigmaECAL_ " <<
algo.nSigmaECAL_ << endl;
3401 out <<
"nSigmaHCAL_ " <<
algo.nSigmaHCAL_ << endl;
3402 out <<
"nSigmaHFEM_ " <<
algo.nSigmaHFEM_ << endl;
3403 out <<
"nSigmaHFHAD_ " <<
algo.nSigmaHFHAD_ << endl;
3405 out <<
algo.calibration_ << endl;
3407 out <<
"reconstructed particles: " << endl;
3409 if (!
algo.pfCandidates_.get()) {
3410 out <<
"candidates already transfered" << endl;
3413 for (
auto const&
c : *
algo.pfCandidates_)
3424 std::vector<bool>& active,
3425 std::vector<double>& psEne) {
3432 std::multimap<double, unsigned> sortedPS;
3436 double totalPS = 0.;
3437 for (
auto const& ps : sortedPS) {
3439 unsigned iPS = ps.second;
3447 std::multimap<double, unsigned> sortedECAL;
3449 unsigned jEcal = sortedECAL.begin()->second;
3455 assert(pstype == psElementType);
3458 totalPS += psclusterref->energy();
3459 psEne[0] += psclusterref->energy();
3460 active[iPS] =
false;
3470 bool bPrimary = (
order.find(
"primary") != string::npos);
3471 bool bSecondary = (
order.find(
"secondary") != string::npos);
3472 bool bAll = (
order.find(
"all") != string::npos);
3477 if (bPrimary && isToDisp)
3479 if (bSecondary && isFromDisp)
3481 if (bAll && (isToDisp || isFromDisp))
3498 std::vector<unsigned int> pfCandidatesToBeRemoved;
3504 double met2 = metX * metX + metY * metY;
3509 double metXCor = metX;
3510 double metYCor = metY;
3511 double sumetCor = sumet;
3512 double met2Cor = met2;
3514 double deltaPhiPt = 100.;
3516 unsigned iCor = 1E9;
3520 double metReduc = -1.;
3534 const bool skip = std::any_of(
3535 pfCandidatesToBeRemoved.begin(), pfCandidatesToBeRemoved.end(), [&](
unsigned int j) {
return i ==
j; });
3546 double metXInt = metX - pfc.
px();
3547 double metYInt = metY - pfc.
py();
3548 double sumetInt = sumet - pfc.
pt();
3549 double met2Int = metXInt * metXInt + metYInt * metYInt;
3550 if (met2Int < met2Cor) {
3553 metReduc = (met2 - met2Int) / met2Int;
3555 sumetCor = sumetInt;
3556 significanceCor =
std::sqrt(met2Cor / sumetCor);
3563 pfCandidatesToBeRemoved.push_back(iCor);
3578 for (
unsigned int toRemove : pfCandidatesToBeRemoved) {
3579 edm::LogInfo(
"PFAlgo|postCleaning") <<
"Removed : " << (*pfCandidates_)[toRemove];
3581 (*pfCandidates_)[toRemove].rescaleMomentum(1E-6);
3591 if (cleanedHits.empty())
3598 std::vector<unsigned int> hitsToBeAdded;
3604 double met2 = metX * metX + metY * metY;
3605 double met2_Original = met2;
3609 double metXCor = metX;
3610 double metYCor = metY;
3611 double sumetCor = sumet;
3612 double met2Cor = met2;
3614 unsigned iCor = 1E9;
3618 double metReduc = -1.;
3620 for (
unsigned i = 0;
i < cleanedHits.size(); ++
i) {
3623 double px =
hit.energy() *
hit.position().
x() / length;
3624 double py =
hit.energy() *
hit.position().
y() / length;
3629 for (
unsigned int hitIdx : hitsToBeAdded) {
3639 double metXInt = metX +
px;
3640 double metYInt = metY +
py;
3641 double sumetInt = sumet +
pt;
3642 double met2Int = metXInt * metXInt + metYInt * metYInt;
3645 if (met2Int < met2Cor) {
3648 metReduc = (met2 - met2Int) / met2Int;
3650 sumetCor = sumetInt;
3659 hitsToBeAdded.push_back(iCor);
3672 LogTrace(
"PFAlgo|checkCleaning") << hitsToBeAdded.size() <<
" hits were re-added ";
3675 LogTrace(
"PFAlgo|checkCleaning") <<
"Added after cleaning check : ";
3676 for (
unsigned int hitIdx : hitsToBeAdded) {