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");
117 bool primaryVertexFound =
false;
122 primaryVertexFound =
true;
131 auto const&
blocks = *blockHandle;
136 LogTrace(
"PFAlgo|reconstructParticles")
137 <<
"start of function PFAlgo::reconstructParticles, blocks.size()=" <<
blocks.size();
140 std::list<reco::PFBlockRef> hcalBlockRefs;
141 std::list<reco::PFBlockRef> ecalBlockRefs;
142 std::list<reco::PFBlockRef> hoBlockRefs;
143 std::list<reco::PFBlockRef> otherBlockRefs;
145 for (
unsigned i = 0;
i <
blocks.size(); ++
i) {
151 bool singleEcalOrHcal =
false;
154 ecalBlockRefs.push_back(blockref);
155 singleEcalOrHcal =
true;
158 hcalBlockRefs.push_back(blockref);
159 singleEcalOrHcal =
true;
163 hoBlockRefs.push_back(blockref);
164 singleEcalOrHcal =
true;
168 if (!singleEcalOrHcal) {
169 otherBlockRefs.push_back(blockref);
173 LogTrace(
"PFAlgo|reconstructParticles")
174 <<
"# Ecal blocks: " << ecalBlockRefs.size() <<
", # Hcal blocks: " << hcalBlockRefs.size()
175 <<
", # HO blocks: " << hoBlockRefs.size() <<
", # Other blocks: " << otherBlockRefs.size();
181 for (
auto const&
other : otherBlockRefs) {
182 LogTrace(
"PFAlgo|reconstructParticles") <<
"processBlock, Block number " << nblcks++;
186 std::list<reco::PFBlockRef>
empty;
190 for (
auto const&
hcal : hcalBlockRefs) {
191 LogTrace(
"PFAlgo|reconstructParticles") <<
"processBlock, HCAL block number " << hblcks++;
197 for (
auto const&
ecal : ecalBlockRefs) {
198 LogTrace(
"PFAlgo|reconstructParticles") <<
"processBlock, ECAL block number " << eblcks++;
216 LogTrace(
"PFAlgo|reconstructParticles")
217 <<
"end of function PFAlgo::reconstructParticles, pfCandidates_->size()=" <<
pfCandidates_->size();
221 std::vector<bool>& active,
226 LogTrace(
"PFAlgo|egammaFilters") <<
"start of function PFAlgo::egammaFilters(), negmcandidates=" << negmcandidates;
228 for (
unsigned int ieg = 0; ieg < negmcandidates; ++ieg) {
233 PFCandidate::ElementsInBlocks::const_iterator iegfirst = theElements.begin();
234 bool sameBlock =
false;
235 bool isGoodElectron =
false;
236 bool isGoodPhoton =
false;
237 bool isPrimaryElectron =
false;
238 if (iegfirst->first == blockref)
241 LogTrace(
"PFAlgo|egammaFilters") <<
" I am in looping on EGamma Candidates: pt " << (*pfEgmRef).pt()
242 <<
" eta,phi " << (*pfEgmRef).eta() <<
", " << (*pfEgmRef).phi() <<
" charge "
243 << (*pfEgmRef).charge();
245 if ((*pfEgmRef).gsfTrackRef().isNonnull()) {
249 isPrimaryElectron = pfegamma->
isElectron(*gedEleRef);
252 <<
"** Good Electron, pt " << gedEleRef->pt() <<
" eta, phi " << gedEleRef->eta() <<
", "
253 << gedEleRef->phi() <<
" charge " << gedEleRef->charge() <<
" isPrimary " << isPrimaryElectron
255 << (gedEleRef->dr03TkSumPt() + gedEleRef->dr03EcalRecHitSumEt() + gedEleRef->dr03HcalTowerSumEt())
256 <<
" mva_isolated " << gedEleRef->mva_Isolated() <<
" mva_e_pi " << gedEleRef->mva_e_pi();
259 if ((*pfEgmRef).superClusterRef().isNonnull()) {
264 LogTrace(
"PFAlgo|egammaFilters") <<
"** Good Photon, pt " << gedPhoRef->pt() <<
" eta, phi "
265 << gedPhoRef->eta() <<
", " << gedPhoRef->phi() << endl;
270 if (isGoodElectron && isGoodPhoton) {
271 if (isPrimaryElectron)
272 isGoodPhoton =
false;
274 isGoodElectron =
false;
278 if (isGoodElectron) {
282 bool lockTracks =
false;
292 myPFElectron.
setCharge(gedEleRef->charge());
293 myPFElectron.
setP4(gedEleRef->p4());
297 LogTrace(
"PFAlgo|egammaFilters") <<
" PFAlgo: found an electron with NEW EGamma code ";
298 LogTrace(
"PFAlgo|egammaFilters") <<
" myPFElectron: pt " << myPFElectron.
pt() <<
" eta,phi "
299 << myPFElectron.
eta() <<
", " << myPFElectron.
phi() <<
" mva "
300 << myPFElectron.
mva_e_pi() <<
" charge " << myPFElectron.
charge();
302 LogTrace(
"PFAlgo|egammaFilters") <<
" THE BLOCK " << *blockref;
303 for (
auto const& eb : theElements) {
304 active[eb.second] =
false;
305 LogTrace(
"PFAlgo|egammaFilters") <<
" Elements used " << eb.second;
311 for (
auto const& trk : extraTracks) {
312 LogTrace(
"PFAlgo|egammaFilters") <<
" Extra locked track " << trk.second;
313 active[trk.second] =
false;
317 LogTrace(
"PFAlgo|egammaFilters") <<
"Creating PF electron: pt=" << myPFElectron.
pt()
318 <<
" eta=" << myPFElectron.
eta() <<
" phi=" << myPFElectron.
phi();
322 LogTrace(
"PFAlgo|egammaFilters") <<
"PFAlgo: Electron DISCARDED, NOT SAFE FOR JETMET ";
341 myPFPhoton.
setP4(gedPhoRef->p4());
342 LogTrace(
"PFAlgo|egammaFilters") <<
" PFAlgo: found a photon with NEW EGamma code ";
343 LogTrace(
"PFAlgo|egammaFilters") <<
" myPFPhoton: pt " << myPFPhoton.
pt() <<
" eta,phi " << myPFPhoton.
eta()
344 <<
", " << myPFPhoton.
phi() <<
" charge " << myPFPhoton.
charge();
347 LogTrace(
"PFAlgo|egammaFilters") <<
" THE BLOCK " << *blockref;
348 for (
auto const& eb : theElements) {
349 active[eb.second] =
false;
350 LogTrace(
"PFAlgo|egammaFilters") <<
" Elements used " << eb.second;
352 LogTrace(
"PFAlgo|egammaFilters") <<
"Creating PF photon: pt=" << myPFPhoton.
pt() <<
" eta=" << myPFPhoton.
eta()
353 <<
" phi=" << myPFPhoton.
phi();
359 LogTrace(
"PFAlgo|egammaFilters") <<
"end of function PFAlgo::egammaFilters";
363 LogTrace(
"PFAlgo|conversionAlgo") <<
"start of function PFAlgo::conversionAlgo(), elements.size()="
365 for (
unsigned iEle = 0; iEle <
elements.size(); iEle++) {
367 if (
type == PFBlockElement::TRACK) {
368 LogTrace(
"PFAlgo|conversionAlgo") <<
"elements[" << iEle <<
"].type() == TRACK, active[" << iEle
369 <<
"]=" << active[iEle];
371 active[iEle] =
false;
374 LogTrace(
"PFAlgo|conversionAlgo") <<
"Track is high purity";
377 const auto* trackRef = dynamic_cast<const reco::PFBlockElementTrack*>((&
elements[iEle]));
379 LogTrace(
"PFAlgo|conversionAlgo") <<
"!trackType(T_FROM_GAMMACONV)";
383 active[iEle] =
false;
385 LogTrace(
"PFAlgo|conversionAlgo") <<
"active[iEle=" << iEle <<
"]=" << active[iEle];
388 LogTrace(
"PFAlgo|conversionAlgo") <<
"end of function PFAlgo::conversionAlgo";
395 std::vector<bool>& active,
396 bool goodTrackDeadHcal,
399 std::multimap<double, unsigned>& ecalElems,
401 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"start of function PFAlgo::recoTracksNotHCAL(), now dealing with tracks "
402 "linked to no HCAL clusters. Was HCal active? "
425 if (!ecalElems.empty()) {
426 unsigned thisEcal = ecalElems.begin()->second;
428 bool useCluster =
true;
430 std::multimap<double, unsigned> sortedTracks;
431 block.associatedElements(
433 useCluster = (sortedTracks.begin()->second == iTrack);
436 deficit -= clusterRef->energy();
445 active[iTrack] =
false;
446 LogTrace(
"PFAlgo|recoTracksNotHCAL")
448 <<
" deficit " << deficit <<
" > " <<
nSigmaTRACK_ <<
" x " <<
resol <<
" track pt " << trackRef->pt()
449 <<
" +- " << trackRef->ptError() <<
" layers valid " << trackRef->hitPattern().trackerLayersWithMeasurement()
450 <<
", lost " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS)
451 <<
", lost outer " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS)
452 <<
", lost inner " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS)
453 <<
"(valid fraction " << trackRef->validFraction() <<
")"
454 <<
" chi2/ndf " << trackRef->normalizedChi2() <<
" |dxy| "
457 <<
"is probably a fake (1) --> lock the track";
465 std::vector<unsigned> tmpi;
466 std::vector<unsigned> kTrack;
469 double dpt = trackRef->ptError();
473 double dptRel = dpt / trackRef->pt() * 100;
479 unsigned nHits =
elements[iTrack].trackRef()->hitPattern().trackerLayersWithMeasurement();
480 unsigned int NLostHit = trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS);
482 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"A track (algo = " << trackRef->algo() <<
") with momentum "
484 << dpt <<
" / " <<
elements[iTrack].trackRef()->eta()
485 <<
" without any link to ECAL/HCAL and with " <<
nHits <<
" (" << NLostHit
486 <<
") hits (lost hits) has been cleaned";
488 active[iTrack] =
false;
494 kTrack.push_back(iTrack);
495 active[iTrack] =
false;
498 if (ecalElems.empty()) {
499 (*pfCandidates_)[tmpi[0]].setEcalEnergy(0., 0.);
500 (*pfCandidates_)[tmpi[0]].setHcalEnergy(0., 0.);
501 (*pfCandidates_)[tmpi[0]].setHoEnergy(0., 0.);
502 (*pfCandidates_)[tmpi[0]].setPs1Energy(0);
503 (*pfCandidates_)[tmpi[0]].setPs2Energy(0);
504 (*pfCandidates_)[tmpi[0]].addElementInBlock(blockref, kTrack[0]);
509 const unsigned int thisEcal = ecalElems.begin()->second;
511 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
" is associated to " <<
elements[thisEcal];
515 (*pfCandidates_)[tmpi[0]].setEcalEnergy(clusterRef->energy(),
std::min(clusterRef->energy(),
muonECAL_[0]));
516 (*pfCandidates_)[tmpi[0]].setHcalEnergy(0., 0.);
517 (*pfCandidates_)[tmpi[0]].setHoEnergy(0., 0.);
518 (*pfCandidates_)[tmpi[0]].setPs1Energy(0);
519 (*pfCandidates_)[tmpi[0]].setPs2Energy(0);
520 (*pfCandidates_)[tmpi[0]].addElementInBlock(blockref, kTrack[0]);
523 double slopeEcal = 1.;
524 bool connectedToEcal =
false;
525 unsigned iEcal = 99999;
526 double calibEcal = 0.;
527 double calibHcal = 0.;
528 double totalEcal = thisIsAMuon ? -
muonECAL_[0] : 0.;
531 std::multimap<double, unsigned> sortedTracks;
533 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"the closest ECAL cluster, id " << thisEcal <<
", has " << sortedTracks.size()
534 <<
" associated tracks, now processing them. ";
536 if (hasDeadHcal && !sortedTracks.empty()) {
538 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
" the closest track to ECAL " << thisEcal <<
" is "
539 << sortedTracks.begin()->second <<
" (distance " << sortedTracks.begin()->first
541 if (sortedTracks.begin()->second != iTrack) {
542 LogTrace(
"PFAlgo|recoTracksNotHCAL")
543 <<
" the closest track to ECAL " << thisEcal <<
" is " << sortedTracks.begin()->second
544 <<
" which is not the one being processed. Will skip ECAL linking for this track";
545 (*pfCandidates_)[tmpi[0]].setEcalEnergy(0., 0.);
546 (*pfCandidates_)[tmpi[0]].setHcalEnergy(0., 0.);
547 (*pfCandidates_)[tmpi[0]].setHoEnergy(0., 0.);
548 (*pfCandidates_)[tmpi[0]].setPs1Energy(0);
549 (*pfCandidates_)[tmpi[0]].setPs2Energy(0);
550 (*pfCandidates_)[tmpi[0]].addElementInBlock(blockref, kTrack[0]);
553 LogTrace(
"PFAlgo|recoTracksNotHCAL")
554 <<
" the closest track to ECAL " << thisEcal <<
" is " << sortedTracks.begin()->second
555 <<
" which is the one being processed. Will skip ECAL linking for all other track";
556 sortedTracks.clear();
560 for (
auto const& trk : sortedTracks) {
561 unsigned jTrack = trk.second;
568 if (jTrack == iTrack)
577 std::multimap<double, unsigned> sortedECAL;
579 if (sortedECAL.begin()->second != thisEcal)
584 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
" found track " << jTrack << (thatIsAMuon ?
" (muon) " :
" (non-muon)")
585 <<
", with distance = " << sortedECAL.begin()->first;
588 bool rejectFake =
false;
590 if (!thatIsAMuon && trackRef->ptError() >
ptError_) {
593 double deficit =
trackMomentum + trackRef->p() - clusterRef->energy();
599 kTrack.push_back(jTrack);
600 active[jTrack] =
false;
601 LogTrace(
"PFAlgo|recoTracksNotHCAL")
603 <<
"is probably a fake (2) --> lock the track"
604 <<
"(trackMomentum = " <<
trackMomentum <<
", clusterEnergy = " << clusterRef->energy()
606 <<
" assuming neutralHadronEnergyResolution "
617 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"Track momentum increased from " <<
trackMomentum <<
" GeV ";
623 totalEcal =
std::max(totalEcal, 0.);
630 kTrack.push_back(jTrack);
631 active[jTrack] =
false;
634 (*pfCandidates_)[tmpi.back()].setEcalEnergy(clusterRef->energy(),
std::min(clusterRef->energy(),
muonECAL_[0]));
635 (*pfCandidates_)[tmpi.back()].setHcalEnergy(0., 0.);
636 (*pfCandidates_)[tmpi.back()].setHoEnergy(0., 0.);
637 (*pfCandidates_)[tmpi.back()].setPs1Energy(0);
638 (*pfCandidates_)[tmpi.back()].setPs2Energy(0);
639 (*pfCandidates_)[tmpi.back()].addElementInBlock(blockref, kTrack.back());
643 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"Loop over all associated ECAL clusters";
645 for (
auto const&
ecal : ecalElems) {
652 if (!active[
index]) {
653 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"is not active - ignore ";
660 const bool skip = std::none_of(
661 kTrack.begin(), kTrack.end(), [&](
unsigned iTrack) {
return sortedTracks.begin()->second == iTrack; });
664 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"is closer to another track - ignore ";
672 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"Ecal cluster with raw energy = " << clusterRef->energy()
673 <<
" linked with distance = " <<
ecal.first;
679 vector<double> ps1Ene{0.};
681 vector<double> ps2Ene{0.};
685 const double ecalEnergy = clusterRef->energy();
686 const double ecalEnergyCalibrated = clusterRef->correctedEnergy();
687 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"Corrected ECAL(+PS) energy = " << ecalEnergy;
691 totalEcal += ecalEnergy;
692 const double previousCalibEcal = calibEcal;
693 const double previousSlopeEcal = slopeEcal;
694 calibEcal =
std::max(totalEcal, 0.);
697 trackMomentum, calibEcal, calibHcal, clusterRef->positionREP().Eta(), clusterRef->positionREP().Phi());
699 slopeEcal = calibEcal / totalEcal;
701 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"The total calibrated energy so far amounts to = " << calibEcal
702 <<
" (slope = " << slopeEcal <<
")";
708 calibEcal = previousCalibEcal;
709 slopeEcal = previousSlopeEcal;
710 totalEcal = calibEcal / slopeEcal;
714 active[
index] =
false;
717 std::multimap<double, unsigned> assTracks;
721 *clusterRef, ecalEnergyCalibrated)];
722 ecalCand.setEcalEnergy(clusterRef->energy(), ecalEnergyCalibrated);
723 ecalCand.setHcalEnergy(0., 0.);
724 ecalCand.setHoEnergy(0., 0.);
725 ecalCand.setPs1Energy(ps1Ene[0]);
726 ecalCand.setPs2Energy(ps2Ene[0]);
727 ecalCand.addElementInBlock(blockref,
index);
729 if (!assTracks.empty()) {
730 ecalCand.addElementInBlock(blockref, assTracks.begin()->second);
734 dynamic_cast<const reco::PFBlockElementTrack*>(&
elements[assTracks.begin()->second])
735 ->positionAtECALEntrance();
736 ecalCand.setPositionAtECALEntrance(chargedPosition);
742 connectedToEcal =
true;
744 active[
index] =
false;
745 for (
unsigned ic : tmpi)
746 (*pfCandidates_)[ic].addElementInBlock(blockref, iEcal);
750 bool bNeutralProduced =
false;
753 if (connectedToEcal) {
795 neutralEnergy /= slopeEcal;
797 (*pfCandidates_)[tmpj].setEcalEnergy(pivotalRef->energy(), neutralEnergy);
798 (*pfCandidates_)[tmpj].setHcalEnergy(0., 0.);
799 (*pfCandidates_)[tmpj].setHoEnergy(0., 0.);
800 (*pfCandidates_)[tmpj].setPs1Energy(0.);
801 (*pfCandidates_)[tmpj].setPs2Energy(0.);
802 (*pfCandidates_)[tmpj].addElementInBlock(blockref, iEcal);
803 bNeutralProduced =
true;
804 for (
unsigned ic = 0; ic < kTrack.size(); ++ic)
805 (*
pfCandidates_)[tmpj].addElementInBlock(blockref, kTrack[ic]);
809 for (
unsigned ic = 0; ic < tmpi.size(); ++ic) {
815 double ecalCal = bNeutralProduced ? (calibEcal - neutralEnergy * slopeEcal) *
fraction : calibEcal *
fraction;
816 double ecalRaw = totalEcal *
fraction;
818 LogTrace(
"PFAlgo|recoTracksNotHCAL")
819 <<
"The fraction after photon supression is " <<
fraction <<
" calibrated ecal = " << ecalCal;
821 (*pfCandidates_)[tmpi[ic]].setEcalEnergy(ecalRaw, ecalCal);
822 (*pfCandidates_)[tmpi[ic]].setHcalEnergy(0., 0.);
823 (*pfCandidates_)[tmpi[ic]].setHoEnergy(0., 0.);
824 (*pfCandidates_)[tmpi[ic]].setPs1Energy(0);
825 (*pfCandidates_)[tmpi[ic]].setPs2Energy(0);
826 (*pfCandidates_)[tmpi[ic]].addElementInBlock(blockref, kTrack[ic]);
832 for (
unsigned ic = 0; ic < tmpi.size(); ++ic) {
833 const PFCandidate& pfc = (*pfCandidates_)[tmpi[ic]];
835 if (eleInBlocks.empty()) {
836 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"Single track / Fill element in block! ";
837 (*pfCandidates_)[tmpi[ic]].addElementInBlock(blockref, kTrack[ic]);
840 LogTrace(
"PFAlgo|recoTracksNotHCAL") <<
"end of function PFAlgo::recoTracksNotHCAL";
853 bool isPrimaryTrack =
854 elements[iElement].displacedVertexRef(PFBlockElement::T_TO_DISP)->displacedVertexRef()->isTherePrimaryTracks();
855 if (isPrimaryTrack) {
856 LogTrace(
"PFAlgo|elementLoop") <<
"Primary Track reconstructed alone";
859 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iElement);
880 bool hasDeadHcal =
false;
881 if (!hcalElems.empty() && deadArea[hcalElems.begin()->second]) {
895 bool goodTrackDeadHcal =
false;
904 trackRef->hitPattern().pixelLayersWithMeasurement() >= 3 &&
905 trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS) == 0 &&
906 trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS) == 0 &&
907 trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS) <=
915 goodTrackDeadHcal =
true;
920 <<
" track pt " << trackRef->pt() <<
" +- " << trackRef->ptError() <<
" layers valid "
921 << trackRef->hitPattern().trackerLayersWithMeasurement() <<
", lost "
922 << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS) <<
", lost outer "
923 << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS) <<
", lost inner "
924 << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS) <<
"(valid fraction "
925 << trackRef->validFraction() <<
")"
928 << trackRef->dzError() << (goodTrackDeadHcal ?
" passes " :
" fails ") <<
"quality cuts";
930 return goodTrackDeadHcal;
934 std::multimap<double, unsigned>& ecalElems,
935 std::multimap<double, unsigned>& hcalElems,
936 const std::vector<bool>& active,
938 unsigned int iTrack) {
940 unsigned index = ecalElems.begin()->second;
941 std::multimap<double, unsigned> sortedTracks;
943 LogTrace(
"PFAlgo|elementLoop") <<
"The closest ECAL cluster is linked to " << sortedTracks.size()
944 <<
" tracks, with distance = " << ecalElems.begin()->first;
946 LogTrace(
"PFAlgo|elementLoop") <<
"Looping over sortedTracks";
948 for (
auto const& trk : sortedTracks) {
949 unsigned jTrack = trk.second;
950 LogTrace(
"PFAlgo|elementLoop") <<
"jTrack=" << jTrack;
954 LogTrace(
"PFAlgo|elementLoop") <<
"active[jTrack]=" << active[jTrack];
957 if (jTrack == iTrack)
959 LogTrace(
"PFAlgo|elementLoop") <<
"skipping jTrack=" << jTrack <<
" for same iTrack";
963 std::multimap<double, unsigned> sortedECAL;
965 if (sortedECAL.begin()->second !=
index)
967 LogTrace(
"PFAlgo|elementLoop") <<
" track " << jTrack <<
" with closest ECAL identical ";
970 std::multimap<double, unsigned> sortedHCAL;
972 if (sortedHCAL.empty())
974 LogTrace(
"PFAlgo|elementLoop") <<
" and with an HCAL cluster " << sortedHCAL.begin()->second;
978 block.setLink(iTrack, sortedHCAL.begin()->second, sortedECAL.begin()->first, linkData, PFBlock::LINKTEST_RECHIT);
985 if (!hcalElems.empty())
986 LogTrace(
"PFAlgo|elementLoop") <<
"Track linked back to HCAL due to ECAL sharing with other tracks";
992 std::vector<bool>& active,
995 std::vector<bool>& deadArea) {
996 LogTrace(
"PFAlgo|elementLoop") <<
"start of function PFAlgo::elementLoop, elements.size()" <<
elements.size();
998 for (
unsigned iEle = 0; iEle <
elements.size(); iEle++) {
1001 LogTrace(
"PFAlgo|elementLoop") <<
"elements[iEle=" << iEle <<
"]=" <<
elements[iEle];
1005 if (ret_decideType == 1) {
1006 LogTrace(
"PFAlgo|elementLoop") <<
"ret_decideType==1, continuing";
1009 LogTrace(
"PFAlgo|elementLoop") <<
"ret_decideType=" << ret_decideType <<
" type=" <<
type;
1013 if (!active[iEle]) {
1014 LogTrace(
"PFAlgo|elementLoop") <<
"Already used by electrons, muons, conversions";
1021 LogTrace(
"PFAlgo|elementLoop") <<
"PFAlgo:processBlock"
1022 <<
" trackIs.size()=" << inds.
trackIs.size()
1023 <<
" ecalIs.size()=" << inds.
ecalIs.size() <<
" hcalIs.size()=" << inds.
hcalIs.size()
1024 <<
" hoIs.size()=" << inds.
hoIs.size() <<
" hfEmIs.size()=" << inds.
hfEmIs.size()
1025 <<
" hfHadIs.size()=" << inds.
hfHadIs.size();
1031 std::multimap<double, unsigned> ecalElems;
1034 std::multimap<double, unsigned> hcalElems;
1037 std::multimap<double, unsigned> hfEmElems;
1038 std::multimap<double, unsigned> hfHadElems;
1042 LogTrace(
"PFAlgo|elementLoop") <<
"\tTrack " << iEle <<
" is linked to " << ecalElems.size() <<
" ecal and "
1043 << hcalElems.size() <<
" hcal and " << hfEmElems.size() <<
" hfEm and "
1044 << hfHadElems.size() <<
" hfHad elements";
1047 for (
const auto& pair : ecalElems) {
1048 LogTrace(
"PFAlgo|elementLoop") <<
"ecal: dist " << pair.first <<
"\t elem " << pair.second;
1050 for (
const auto& pair : hcalElems) {
1051 LogTrace(
"PFAlgo|elementLoop") <<
"hcal: dist " << pair.first <<
"\t elem " << pair.second
1052 << (deadArea[pair.second] ?
" DEAD AREA MARKER" :
"");
1065 if (hcalElems.empty() && !ecalElems.empty() && !hasDeadHcal) {
1076 std::multimap<double, unsigned> gsfElems;
1079 if (hcalElems.empty()) {
1080 LogTrace(
"PFAlgo|elementLoop") <<
"no hcal element connected to track " << iEle;
1084 bool hcalFound =
false;
1085 bool hfhadFound =
false;
1087 LogTrace(
"PFAlgo|elementLoop") <<
"now looping on elements associated to the track: ecalElems";
1091 for (
auto const&
ecal : ecalElems) {
1096 double dist =
ecal.first;
1097 LogTrace(
"PFAlgo|elementLoop") <<
"\telement " <<
elements[
index] <<
" linked with distance = " << dist;
1099 LogTrace(
"PFAlgo|elementLoop") <<
"This ECAL is already used - skip it";
1111 if (!hcalElems.empty())
1112 LogTrace(
"PFAlgo|elementLoop") <<
"\t\tat least one hcal element connected to the track."
1113 <<
" Sparing Ecal cluster for the hcal loop";
1120 if (hcalElems.empty() && hfHadElems.empty()) {
1122 block, linkData,
elements, blockref, active, goodTrackDeadHcal, hasDeadHcal, iEle, ecalElems, trackRef);
1130 for (
auto const&
hcal : hcalElems) {
1137 LogTrace(
"PFAlgo|elementLoop") <<
"\telement " <<
elements[
index] <<
" linked with distance " << dist;
1144 LogTrace(
"PFAlgo|elementLoop") <<
"\t\tclosest hcal cluster, doing nothing";
1152 LogTrace(
"PFAlgo|elementLoop") <<
"\t\tsecondary hcal cluster. unlinking";
1153 block.setLink(iEle,
index, -1., linkData, PFBlock::LINKTEST_RECHIT);
1160 for (
auto const& hfhad : hfHadElems) {
1161 unsigned index = hfhad.second;
1167 LogTrace(
"PFAlgo|elementLoop") <<
"\telement " <<
elements[
index] <<
" linked with distance " << dist;
1174 LogTrace(
"PFAlgo|elementLoop") <<
"\t\tclosest hfhad cluster, doing nothing";
1180 LogTrace(
"PFAlgo|elementLoop") <<
"\t\tsecondary hfhad cluster. unlinking";
1181 block.setLink(iEle,
index, -1., linkData, PFBlock::LINKTEST_RECHIT);
1185 LogTrace(
"PFAlgo|elementLoop") <<
"end of loop over iEle";
1187 LogTrace(
"PFAlgo|elementLoop") <<
"end of function PFAlgo::elementLoop";
1195 std::vector<bool>& active,
1197 std::vector<bool>& deadArea,
1198 unsigned int iEle) {
1200 case PFBlockElement::TRACK:
1203 LogTrace(
"PFAlgo|decideType") <<
"TRACK, stored index, continue";
1208 inds.
ecalIs.push_back(iEle);
1209 LogTrace(
"PFAlgo|decideType") <<
"ECAL, stored index, continue";
1215 LogTrace(
"PFAlgo|decideType") <<
"HCAL DEAD AREA: remember and skip.";
1216 active[iEle] =
false;
1217 deadArea[iEle] =
true;
1220 inds.
hcalIs.push_back(iEle);
1221 LogTrace(
"PFAlgo|decideType") <<
"HCAL, stored index, continue";
1227 inds.
hoIs.push_back(iEle);
1228 LogTrace(
"PFAlgo|decideType") <<
"HO, stored index, continue";
1232 case PFBlockElement::HFEM:
1234 inds.
hfEmIs.push_back(iEle);
1235 LogTrace(
"PFAlgo|decideType") <<
"HFEM, stored index, continue";
1238 case PFBlockElement::HFHAD:
1241 LogTrace(
"PFAlgo|decideType") <<
"HFHAD, stored index, continue";
1247 LogTrace(
"PFAlgo|decideType") <<
"Did not match type to anything, return 0";
1254 std::vector<bool>& active,
1257 LogTrace(
"PFAlgo|createCandidatesHF") <<
"starting function PFAlgo::createCandidatesHF";
1259 bool trackInBlock = !inds.
trackIs.empty();
1263 for (
unsigned iEle = 0; iEle <
elements.size(); iEle++) {
1265 if (
type == PFBlockElement::TRACK) {
1266 trackInBlock =
true;
1281 std::multimap<double, unsigned> sortedTracks;
1282 std::multimap<double, unsigned> sortedTracksActive;
1284 std::multimap<unsigned, std::pair<double, unsigned>> associatedHfEms;
1286 std::multimap<double, std::pair<unsigned, double>> hfemSatellites;
1291 for (
unsigned iHfHad : inds.
hfHadIs) {
1298 sortedTracks.clear();
1299 sortedTracksActive.clear();
1300 associatedHfEms.clear();
1301 hfemSatellites.clear();
1304 block.associatedElements(
1307 LogTrace(
"PFAlgo|createCandidatesHF") <<
"elements[" << iHfHad <<
"]=" <<
elements[iHfHad];
1309 if (sortedTracks.empty()) {
1310 LogTrace(
"PFAlgo|createCandidatesHCF") <<
"\tno associated tracks, keep for later";
1315 active[iHfHad] =
false;
1317 LogTrace(
"PFAlgo|createCandidatesHF") << sortedTracks.size() <<
" associated tracks:";
1319 double totalChargedMomentum = 0.;
1320 double sumpError2 = 0.;
1325 for (
auto const& trk : sortedTracks) {
1326 unsigned iTrack = trk.second;
1329 if (!active[iTrack])
1344 sumpError2 +=
dp *
dp;
1347 sortedTracksActive.emplace(trk);
1350 std::multimap<double, unsigned> sortedHfEms;
1351 block.associatedElements(
1354 LogTrace(
"PFAlgo|createCandidatesHF") <<
"number of HfEm elements linked to this track: " << sortedHfEms.size();
1356 bool connectedToHfEm =
false;
1361 for (
auto const& hfem : sortedHfEms) {
1362 unsigned iHfEm = hfem.second;
1363 double dist = hfem.first;
1366 if (!active[iHfEm]) {
1367 LogTrace(
"PFAlgo|createCandidatesHF") <<
"cluster locked";
1378 std::multimap<double, unsigned> sortedTracksHfEm;
1379 block.associatedElements(
1381 unsigned jTrack = sortedTracksHfEm.begin()->second;
1382 if (jTrack != iTrack)
1386 double hfemEnergy = eclusterRef->energy();
1388 if (!connectedToHfEm) {
1391 connectedToHfEm =
true;
1392 std::pair<unsigned, double> satellite(iHfEm, hfemEnergy);
1393 hfemSatellites.emplace(-1., satellite);
1398 std::pair<unsigned, double> satellite(iHfEm, hfemEnergy);
1399 hfemSatellites.emplace(dist, satellite);
1402 std::pair<double, unsigned> associatedHfEm(distHfEm, iHfEm);
1403 associatedHfEms.emplace(iTrack, associatedHfEm);
1409 double uncalibratedenergyHfHad = hclusterRef->energy();
1410 double energyHfHad = uncalibratedenergyHfHad;
1413 uncalibratedenergyHfHad,
1414 hclusterRef->positionREP().Eta(),
1415 hclusterRef->positionREP().Phi());
1417 double calibFactorHfHad = (uncalibratedenergyHfHad > 0.) ? energyHfHad / uncalibratedenergyHfHad : 1.;
1420 double energyHfEmTmp = 0.;
1421 double uncalibratedenergyHfEmTmp = 0.;
1422 double energyHfEm = 0.;
1423 double uncalibratedenergyHfEm = 0.;
1427 caloResolution *= totalChargedMomentum;
1428 double totalError =
sqrt(caloResolution * caloResolution + sumpError2);
1429 double nsigmaHFEM =
nSigmaHFEM(totalChargedMomentum);
1430 double nsigmaHFHAD =
nSigmaHFHAD(totalChargedMomentum);
1433 if (sortedTracksActive.empty()) {
1435 std::multimap<double, unsigned> sortedHfEms;
1436 std::multimap<double, unsigned> sortedHfEmsActive;
1437 block.associatedElements(
1442 if (!sortedHfEms.empty()) {
1443 for (
auto const& hfem : sortedHfEms) {
1444 unsigned iHfEm = hfem.second;
1448 sortedHfEmsActive.emplace(hfem);
1451 double hfemEnergy = eclusterRef->energy();
1452 uncalibratedenergyHfEm += hfemEnergy;
1453 energyHfEm = uncalibratedenergyHfEm;
1456 uncalibratedenergyHfEm, 0.0, eclusterRef->positionREP().Eta(), eclusterRef->positionREP().Phi());
1458 0.0, uncalibratedenergyHfHad, hclusterRef->positionREP().Eta(), hclusterRef->positionREP().Phi());
1465 (*pfCandidates_)[tmpi].setHcalEnergy(uncalibratedenergyHfHad, energyHfHad);
1466 (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHfEm, energyHfEm);
1467 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfHad);
1468 for (
auto const& hfem : sortedHfEmsActive) {
1469 unsigned iHfEm = hfem.second;
1470 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfEm);
1471 active[iHfEm] =
false;
1478 else if ((energyHfHad - totalChargedMomentum) > nsigmaHFHAD * totalError) {
1479 assert(energyHfEm == 0.);
1481 double energyHfHadExcess =
max(energyHfHad - totalChargedMomentum, 0.);
1482 double uncalibratedenergyHfHadExcess = energyHfHadExcess / calibFactorHfHad;
1484 (*pfCandidates_)[tmpi].setHcalEnergy(uncalibratedenergyHfHadExcess, energyHfHadExcess);
1485 (*pfCandidates_)[tmpi].setEcalEnergy(0., 0.);
1486 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfHad);
1487 energyHfHad =
max(energyHfHad - energyHfHadExcess, 0.);
1488 uncalibratedenergyHfHad =
max(uncalibratedenergyHfHad - uncalibratedenergyHfHadExcess, 0.);
1496 for (
auto const& hfemSatellite : hfemSatellites) {
1498 uncalibratedenergyHfEmTmp += std::get<1>(hfemSatellite.second);
1499 energyHfEmTmp = uncalibratedenergyHfEmTmp;
1500 double energyHfHadTmp = uncalibratedenergyHfHad;
1501 unsigned iHfEm = std::get<0>(hfemSatellite.second);
1506 uncalibratedenergyHfEmTmp, 0.0, eclusterRef->positionREP().Eta(), eclusterRef->positionREP().Phi());
1508 0.0, uncalibratedenergyHfHad, hclusterRef->positionREP().Eta(), hclusterRef->positionREP().Phi());
1511 double caloEnergyTmp = energyHfEmTmp + energyHfHadTmp;
1512 double calibFactorHfEm = (uncalibratedenergyHfEmTmp > 0.) ? energyHfEmTmp / uncalibratedenergyHfEmTmp : 1.;
1516 if (hfemSatellite.first < 0. || caloEnergyTmp < totalChargedMomentum) {
1517 LogTrace(
"PFAlgo|createCandidatesHF")
1518 <<
"\t\t\tactive, adding " << std::get<1>(hfemSatellite.second) <<
" to HFEM energy, and locking";
1519 active[std::get<0>(hfemSatellite.second)] =
false;
1521 if (hfemSatellite.first < 0. && (caloEnergyTmp - totalChargedMomentum) > nsigmaHFEM * totalError) {
1523 double energyHfEmExcess =
max(caloEnergyTmp - totalChargedMomentum, 0.);
1524 double uncalibratedenergyHfEmExcess = energyHfEmExcess / calibFactorHfEm;
1526 (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHfEmExcess, energyHfEmExcess);
1527 (*pfCandidates_)[tmpi].setHcalEnergy(0, 0.);
1528 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfEm);
1529 energyHfEmTmp =
max(energyHfEmTmp - energyHfEmExcess, 0.);
1530 uncalibratedenergyHfEmTmp =
max(uncalibratedenergyHfEmTmp - uncalibratedenergyHfEmExcess, 0.);
1532 energyHfEm = energyHfEmTmp;
1533 uncalibratedenergyHfEm = uncalibratedenergyHfEmTmp;
1534 energyHfHad = energyHfHadTmp;
1544 for (
auto const& trk : sortedTracksActive) {
1545 unsigned iTrack = trk.second;
1555 active[iTrack] =
false;
1556 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfHad);
1557 auto myHfEms = associatedHfEms.equal_range(iTrack);
1558 for (
auto ii = myHfEms.first;
ii != myHfEms.second; ++
ii) {
1559 unsigned iHfEm =
ii->second.second;
1562 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfEm);
1565 if (totalChargedMomentum)
1566 frac = trackRef->p() / totalChargedMomentum;
1567 (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHfEm *
frac, energyHfEm *
frac);
1568 (*pfCandidates_)[tmpi].setHcalEnergy(uncalibratedenergyHfHad *
frac, energyHfHad *
frac);
1577 for (
unsigned iHfEm = 0; iHfEm <
elements.size(); iHfEm++) {
1579 if (
type == PFBlockElement::HFEM && active[iHfEm]) {
1582 double uncalibratedenergyHF = 0.;
1589 uncalibratedenergyHF, eclusterRef->positionREP().Eta(), eclusterRef->positionREP().Phi());
1592 (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHF,
energyHF);
1593 (*pfCandidates_)[tmpi].setHcalEnergy(0., 0.);
1594 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHfEm);
1595 active[iHfEm] =
false;
1596 LogTrace(
"PFAlgo|createCandidatesHF") <<
"HF EM alone from blocks with tracks! " <<
energyHF;
1610 double uncalibratedenergyHF = 0.;
1612 switch (clusterRef->layer()) {
1619 uncalibratedenergyHF, clusterRef->positionREP().Eta(), clusterRef->positionREP().Phi());
1622 (*pfCandidates_)[tmpi].setEcalEnergy(uncalibratedenergyHF,
energyHF);
1623 (*pfCandidates_)[tmpi].setHcalEnergy(0., 0.);
1624 (*pfCandidates_)[tmpi].setHoEnergy(0., 0.);
1625 (*pfCandidates_)[tmpi].setPs1Energy(0.);
1626 (*pfCandidates_)[tmpi].setPs2Energy(0.);
1627 (*pfCandidates_)[tmpi].addElementInBlock(blockref, inds.
hfEmIs[0]);
1636 uncalibratedenergyHF, clusterRef->positionREP().Eta(), clusterRef->positionREP().Phi());
1639 (*pfCandidates_)[tmpi].setHcalEnergy(uncalibratedenergyHF,
energyHF);
1640 (*pfCandidates_)[tmpi].setEcalEnergy(0., 0.);
1641 (*pfCandidates_)[tmpi].setHoEnergy(0., 0.);
1642 (*pfCandidates_)[tmpi].setPs1Energy(0.);
1643 (*pfCandidates_)[tmpi].setPs2Energy(0.);
1644 (*pfCandidates_)[tmpi].addElementInBlock(blockref, inds.
hfHadIs[0]);
1659 edm::LogError(
"PFAlgo::createCandidatesHF") <<
"Error: 2 elements, but not 1 HFEM and 1 HFHAD";
1666 double energyHfEm = cem->energy();
1667 double energyHfHad = chad->energy();
1668 double uncalibratedenergyHfEm = energyHfEm;
1669 double uncalibratedenergyHfHad = energyHfHad;
1672 uncalibratedenergyHfEm, 0.0,
c0->positionREP().Eta(),
c0->positionREP().Phi());
1674 0.0, uncalibratedenergyHfHad,
c1->positionREP().Eta(),
c1->positionREP().Phi());
1677 cand.setEcalEnergy(uncalibratedenergyHfEm, energyHfEm);
1678 cand.setHcalEnergy(uncalibratedenergyHfHad, energyHfHad);
1679 cand.setHoEnergy(0., 0.);
1680 cand.setPs1Energy(0.);
1681 cand.setPs2Energy(0.);
1682 cand.addElementInBlock(blockref, inds.
hfEmIs[0]);
1683 cand.addElementInBlock(blockref, inds.
hfHadIs[0]);
1684 LogTrace(
"PFAlgo|createCandidatesHF") <<
"HF EM+HAD found ! " << energyHfEm <<
" " << energyHfHad;
1688 <<
"Warning: HF, but n elem different from 1 or 2 or >=3 or !trackIs.empty()";
1691 LogTrace(
"PFAlgo|createCandidateHF") <<
"end of function PFAlgo::createCandidateHF";
1697 std::vector<bool>& active,
1700 std::vector<bool>& deadArea) {
1701 LogTrace(
"PFAlgo|createCandidatesHCAL")
1702 <<
"start of function PFAlgo::createCandidatesHCAL, inds.hcalIs.size()=" << inds.
hcalIs.size();
1706 for (
unsigned iHcal : inds.
hcalIs) {
1711 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"elements[" << iHcal <<
"]=" <<
elements[iHcal];
1714 std::multimap<double, unsigned> sortedTracks;
1717 std::multimap<unsigned, std::pair<double, unsigned>> associatedEcals;
1719 std::map<unsigned, std::pair<double, double>> associatedPSs;
1721 std::multimap<double, std::pair<unsigned, bool>> associatedTracks;
1724 std::multimap<double, std::tuple<unsigned, ::math::XYZVector, double>>
1726 std::tuple<unsigned, ::math::XYZVector, double> fakeSatellite(iHcal, ::
math::XYZVector(0., 0., 0.), 1.);
1727 ecalSatellites.emplace(-1., fakeSatellite);
1729 std::multimap<unsigned, std::pair<double, unsigned>> associatedHOs;
1741 if (sortedTracks.empty()) {
1742 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\tno associated tracks, keep for later";
1747 active[iHcal] =
false;
1754 LogTrace(
"PFAlgo|createCandidatesHCAL") << sortedTracks.size() <<
" associated tracks:";
1756 double totalChargedMomentum = 0;
1757 double sumpError2 = 0.;
1758 double totalHO = 0.;
1759 double totalEcal = 0.;
1760 double totalEcalEGMCalib = 0.;
1761 double totalHcal = hclusterref->energy();
1762 vector<double> hcalP;
1763 vector<double> hcalDP;
1764 vector<unsigned> tkIs;
1765 double maxDPovP = -9999.;
1768 vector<unsigned> chargedHadronsIndices;
1769 vector<unsigned> chargedHadronsInBlock;
1770 double mergedNeutralHadronEnergy = 0;
1771 double mergedPhotonEnergy = 0;
1772 double muonHCALEnergy = 0.;
1773 double muonECALEnergy = 0.;
1774 double muonHCALError = 0.;
1775 double muonECALError = 0.;
1779 std::vector<std::tuple<unsigned, ::math::XYZVector, double>>
1781 double sumEcalClusters = 0;
1783 hclusterref->position().X(), hclusterref->position().Y(), hclusterref->position().Z());
1784 hadronDirection = hadronDirection.Unit();
1788 for (
auto const& trk : sortedTracks) {
1789 unsigned iTrack = trk.second;
1792 if (!active[iTrack])
1803 dynamic_cast<const reco::PFBlockElementTrack*>(&
elements[iTrack])->positionAtECALEntrance();
1804 ::math::XYZVector chargedDirection(chargedPosition.X(), chargedPosition.Y(), chargedPosition.Z());
1805 chargedDirection = chargedDirection.Unit();
1808 std::multimap<double, unsigned> sortedEcals;
1811 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"number of Ecal elements linked to this track: " << sortedEcals.size();
1814 std::multimap<double, unsigned> sortedHOs;
1818 LogTrace(
"PFAlgo|createCandidatesHCAL")
1819 <<
"PFAlgo : number of HO elements linked to this track: " << sortedHOs.size();
1826 bool thisIsALooseMuon =
false;
1833 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"This track is identified as a muon - remove it from the stack";
1840 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iTrack);
1841 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHcal);
1847 bool letMuonEatCaloEnergy =
false;
1849 if (thisIsAnIsolatedMuon) {
1851 double totalCaloEnergy = totalHcal / 1.30;
1853 if (!sortedEcals.empty()) {
1854 iEcal = sortedEcals.begin()->second;
1856 totalCaloEnergy += eclusterref->energy();
1862 if (!sortedHOs.empty()) {
1863 iHO = sortedHOs.begin()->second;
1865 totalCaloEnergy += eclusterref->energy() / 1.30;
1870 letMuonEatCaloEnergy =
true;
1873 if (letMuonEatCaloEnergy)
1874 muonHcal = totalHcal;
1875 double muonEcal = 0.;
1877 if (!sortedEcals.empty()) {
1878 iEcal = sortedEcals.begin()->second;
1880 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iEcal);
1882 if (letMuonEatCaloEnergy)
1883 muonEcal = eclusterref->energy();
1885 if (eclusterref->energy() - muonEcal < 0.2)
1886 active[iEcal] =
false;
1887 (*pfCandidates_)[tmpi].setEcalEnergy(eclusterref->energy(), muonEcal);
1892 if (!sortedHOs.empty()) {
1893 iHO = sortedHOs.begin()->second;
1895 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHO);
1897 if (letMuonEatCaloEnergy)
1898 muonHO = hoclusterref->energy();
1900 if (hoclusterref->energy() - muonHO < 0.2)
1901 active[iHO] =
false;
1902 (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal, muonHcal);
1903 (*pfCandidates_)[tmpi].setHoEnergy(hoclusterref->energy(), muonHO);
1906 (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal, muonHcal);
1910 if (letMuonEatCaloEnergy) {
1911 muonHCALEnergy += totalHcal;
1913 muonHCALEnergy += muonHO;
1914 muonHCALError += 0.;
1915 muonECALEnergy += muonEcal;
1916 muonECALError += 0.;
1917 photonAtECAL -= muonEcal * chargedDirection;
1918 hadronAtECAL -= totalHcal * chargedDirection;
1919 if (!sortedEcals.empty())
1920 active[iEcal] =
false;
1921 active[iHcal] =
false;
1922 if (
useHO_ && !sortedHOs.empty())
1923 active[iHO] =
false;
1935 photonAtECAL -=
muonECAL_[0] * chargedDirection;
1936 hadronAtECAL -=
muonHCAL_[0] * chargedDirection;
1940 active[iTrack] =
false;
1947 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"elements[iTrack=" << iTrack <<
"]=" <<
elements[iTrack];
1955 if (thisIsALooseMuon && !thisIsAMuon)
1961 double dpt = trackRef->ptError();
1966 if (isPrimaryOrSecondary)
1969 std::pair<unsigned, bool> tkmuon(iTrack, thisIsALooseMuon);
1970 associatedTracks.emplace(-dpt * blowError, tkmuon);
1974 sumpError2 +=
dp *
dp;
1976 bool connectedToEcal =
false;
1977 if (!sortedEcals.empty()) {
1980 for (
auto const&
ecal : sortedEcals) {
1981 unsigned iEcal =
ecal.second;
1982 double dist =
ecal.first;
1985 if (!active[iEcal]) {
1986 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"cluster locked";
1997 std::multimap<double, unsigned> sortedTracksEcal;
1998 block.associatedElements(
2000 unsigned jTrack = sortedTracksEcal.begin()->second;
2001 if (jTrack != iTrack)
2006 float ecalEnergyCalibrated = eclusterref->correctedEnergy();
2007 float ecalEnergy = eclusterref->energy();
2009 eclusterref->position().X(), eclusterref->position().Y(), eclusterref->position().Z());
2010 photonDirection = photonDirection.Unit();
2012 if (!connectedToEcal) {
2016 connectedToEcal =
true;
2021 double ecalCalibFactor = (ecalEnergy > 1E-9) ? ecalEnergyCalibrated / ecalEnergy : 1.;
2022 std::tuple<unsigned, ::math::XYZVector, double> satellite(
2023 iEcal, ecalEnergy * photonDirection, ecalCalibFactor);
2024 ecalSatellites.emplace(-1., satellite);
2029 double ecalCalibFactor = (ecalEnergy > 1E-9) ? ecalEnergyCalibrated / ecalEnergy : 1.;
2030 std::tuple<unsigned, ::math::XYZVector, double> satellite(
2031 iEcal, ecalEnergy * photonDirection, ecalCalibFactor);
2032 ecalSatellites.emplace(dist, satellite);
2035 std::pair<double, unsigned> associatedEcal(distEcal, iEcal);
2036 associatedEcals.emplace(iTrack, associatedEcal);
2041 if (
useHO_ && !sortedHOs.empty()) {
2044 for (
auto const&
ho : sortedHOs) {
2045 unsigned iHO =
ho.second;
2046 double distHO =
ho.first;
2050 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"cluster locked";
2061 std::multimap<double, unsigned> sortedTracksHO;
2062 block.associatedElements(
2064 unsigned jTrack = sortedTracksHO.begin()->second;
2065 if (jTrack != iTrack)
2074 totalHO += hoclusterref->energy();
2075 active[iHO] =
false;
2077 std::pair<double, unsigned> associatedHO(distHO, iHO);
2078 associatedHOs.emplace(iTrack, associatedHO);
2086 totalHcal += totalHO;
2090 double caloEnergy = 0.;
2091 double slopeEcal = 1.0;
2092 double calibEcal = 0.;
2093 double calibHcal = 0.;
2094 hadronDirection = hadronAtECAL.Unit();
2098 caloResolution *= totalChargedMomentum;
2100 caloResolution =
std::sqrt(caloResolution * caloResolution + muonHCALError + muonECALError);
2101 totalEcal -=
std::min(totalEcal, muonECALEnergy);
2102 totalEcalEGMCalib -=
std::min(totalEcalEGMCalib, muonECALEnergy);
2103 totalHcal -=
std::min(totalHcal, muonHCALEnergy);
2104 if (totalEcal < 1E-9)
2106 if (totalHcal < 1E-9)
2113 for (
auto const& ecalSatellite : ecalSatellites) {
2115 double previousCalibEcal = calibEcal;
2116 double previousCalibHcal = calibHcal;
2117 double previousCaloEnergy = caloEnergy;
2118 double previousSlopeEcal = slopeEcal;
2122 sqrt(std::get<1>(ecalSatellite.second).Mag2());
2123 totalEcalEGMCalib +=
sqrt(std::get<1>(ecalSatellite.second).Mag2()) *
2124 std::get<2>(ecalSatellite.second);
2125 photonAtECAL += std::get<1>(ecalSatellite.second) *
2126 std::get<2>(ecalSatellite.second);
2127 calibEcal =
std::max(0., totalEcal);
2128 calibHcal =
std::max(0., totalHcal);
2129 hadronAtECAL = calibHcal * hadronDirection;
2134 hclusterref->positionREP().Eta(),
2135 hclusterref->positionREP().Phi());
2136 caloEnergy = calibEcal + calibHcal;
2138 slopeEcal = calibEcal / totalEcal;
2140 hadronAtECAL = calibHcal * hadronDirection;
2144 if (ecalSatellite.first < 0. || caloEnergy - totalChargedMomentum <= 0.) {
2145 LogTrace(
"PFAlgo|createCandidatesHCAL")
2146 <<
"\t\t\tactive, adding " << std::get<1>(ecalSatellite.second) <<
" to ECAL energy, and locking";
2147 active[std::get<0>(ecalSatellite.second)] =
false;
2148 double clusterEnergy =
2149 sqrt(std::get<1>(ecalSatellite.second).Mag2()) *
2150 std::get<2>(ecalSatellite.second);
2151 if (clusterEnergy > 50) {
2153 sumEcalClusters += clusterEnergy;
2160 totalEcal -=
sqrt(std::get<1>(ecalSatellite.second).Mag2());
2161 totalEcalEGMCalib -=
sqrt(std::get<1>(ecalSatellite.second).Mag2()) * std::get<2>(ecalSatellite.second);
2162 photonAtECAL -= std::get<1>(ecalSatellite.second) * std::get<2>(ecalSatellite.second);
2163 calibEcal = previousCalibEcal;
2164 calibHcal = previousCalibHcal;
2165 hadronAtECAL = previousHadronAtECAL;
2166 slopeEcal = previousSlopeEcal;
2167 caloEnergy = previousCaloEnergy;
2187 if (totalChargedMomentum - caloEnergy >
nSigmaTRACK_ * caloResolution) {
2190 for (
auto const& trk : associatedTracks) {
2192 if (!trk.second.second)
2195 const unsigned int iTrack = trk.second.first;
2197 if (!active[iTrack])
2203 std::multimap<double, unsigned> sortedEcals;
2204 block.associatedElements(
2206 std::multimap<double, unsigned> sortedHOs;
2212 muon.addElementInBlock(blockref, iTrack);
2213 muon.addElementInBlock(blockref, iHcal);
2216 muon.setHcalEnergy(totalHcal, muonHcal);
2217 if (!sortedEcals.empty()) {
2218 const unsigned int iEcal = sortedEcals.begin()->second;
2220 muon.addElementInBlock(blockref, iEcal);
2222 muon.setEcalEnergy(eclusterref->energy(), muonEcal);
2224 if (
useHO_ && !sortedHOs.empty()) {
2225 const unsigned int iHO = sortedHOs.begin()->second;
2227 muon.addElementInBlock(blockref, iHO);
2229 muon.setHcalEnergy(
max(totalHcal - totalHO, 0.0), muonHcal);
2230 muon.setHoEnergy(hoclusterref->energy(), muonHO);
2235 dynamic_cast<const reco::PFBlockElementTrack*>(&
elements[trk.second.first])->positionAtECALEntrance();
2236 ::math::XYZVector chargedDirection(chargedPosition.X(), chargedPosition.Y(), chargedPosition.Z());
2237 chargedDirection = chargedDirection.Unit();
2247 photonAtECAL -=
muonECAL_[0] * chargedDirection;
2249 hadronAtECAL -=
muonHCAL_[0] * calibHcal / totalHcal * chargedDirection;
2250 caloEnergy = calibEcal + calibHcal;
2256 if (totalHcal > 0.) {
2263 active[iTrack] =
false;
2270 caloResolution *= totalChargedMomentum;
2271 caloResolution =
std::sqrt(caloResolution * caloResolution + muonHCALError + muonECALError);
2276 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\tBefore Cleaning ";
2277 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\tCompare Calo Energy to total charged momentum ";
2278 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tsum p = " << totalChargedMomentum <<
" +- " <<
sqrt(sumpError2);
2279 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tsum ecal = " << totalEcal;
2280 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tsum hcal = " << totalHcal;
2281 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\t => Calo Energy = " << caloEnergy <<
" +- " << caloResolution;
2282 LogTrace(
"PFAlgo|createCandidatesHCAL")
2283 <<
"\t\t => Calo Energy- total charged momentum = " << caloEnergy - totalChargedMomentum <<
" +- "
2284 <<
sqrt(sumpError2 + caloResolution * caloResolution);
2288 unsigned corrTrack = 10000000;
2289 double corrFact = 1.;
2292 for (
auto const& trk : associatedTracks) {
2293 const unsigned iTrack = trk.second.first;
2295 if (!active[iTrack])
2299 const double dptRel = fabs(trk.first) / trackref->pt() * 100;
2309 const double wouldBeTotalChargedMomentum = totalChargedMomentum - trackref->p();
2313 if (wouldBeTotalChargedMomentum > caloEnergy) {
2315 LogTrace(
"PFAlgo|createCandidatesHCAL")
2316 <<
"In bad track rejection step dptRel = " << dptRel <<
" dptRel_DispVtx_ = " <<
dptRel_DispVtx_;
2317 LogTrace(
"PFAlgo|createCandidatesHCAL")
2318 <<
"The calo energy would be still smaller even without this track but it is attached to a NI";
2323 active[iTrack] =
false;
2324 totalChargedMomentum = wouldBeTotalChargedMomentum;
2325 LogTrace(
"PFAlgo|createCandidatesHCAL")
2326 <<
"\tElement " <<
elements[iTrack] <<
" rejected (dpt = " << -trk.first
2327 <<
" GeV/c, algo = " << trackref->algo() <<
")";
2333 corrFact = (caloEnergy - wouldBeTotalChargedMomentum) /
elements[trk.second.first].trackRef()->p();
2334 if (trackref->p() * corrFact < 0.05) {
2336 active[iTrack] =
false;
2338 totalChargedMomentum -= trackref->p() * (1. - corrFact);
2339 LogTrace(
"PFAlgo|createCandidatesHCAL")
2340 <<
"\tElement " <<
elements[iTrack] <<
" (dpt = " << -trk.first <<
" GeV/c, algo = " << trackref->algo()
2341 <<
") rescaled by " << corrFact <<
" Now the total charged momentum is " << totalChargedMomentum;
2349 caloResolution *= totalChargedMomentum;
2350 caloResolution =
std::sqrt(caloResolution * caloResolution + muonHCALError + muonECALError);
2356 totalChargedMomentum - caloEnergy >
nSigmaTRACK_ * caloResolution) {
2357 for (
auto const& trk : associatedTracks) {
2358 unsigned iTrack = trk.second.first;
2360 if (!active[iTrack])
2363 double dptRel = fabs(trk.first) / trackref->pt() * 100;
2370 active[iTrack] =
false;
2371 totalChargedMomentum -= trackref->p();
2373 LogTrace(
"PFAlgo|createCandidatesHCAL")
2374 <<
"\tElement " <<
elements[iTrack] <<
" rejected (dpt = " << -trk.first
2375 <<
" GeV/c, algo = " << trackref->algo() <<
")";
2382 caloResolution *= totalChargedMomentum;
2383 caloResolution =
std::sqrt(caloResolution * caloResolution + muonHCALError + muonECALError);
2387 for (
auto const& trk : associatedTracks) {
2388 unsigned iTrack = trk.second.first;
2389 if (!active[iTrack])
2396 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iTrack);
2397 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHcal);
2399 auto myEcals = associatedEcals.equal_range(iTrack);
2400 for (
auto ii = myEcals.first;
ii != myEcals.second; ++
ii) {
2401 unsigned iEcal =
ii->second.second;
2404 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iEcal);
2408 auto myHOs = associatedHOs.equal_range(iTrack);
2409 for (
auto ii = myHOs.first;
ii != myHOs.second; ++
ii) {
2410 unsigned iHO =
ii->second.second;
2413 (*pfCandidates_)[tmpi].addElementInBlock(blockref, iHO);
2417 if (iTrack == corrTrack) {
2420 (*pfCandidates_)[tmpi].rescaleMomentum(corrFact);
2423 chargedHadronsIndices.push_back(tmpi);
2424 chargedHadronsInBlock.push_back(iTrack);
2425 active[iTrack] =
false;
2427 hcalDP.push_back(
dp);
2430 sumpError2 +=
dp *
dp;
2434 double totalError =
sqrt(sumpError2 + caloResolution * caloResolution);
2437 LogTrace(
"PFAlgo|createCandidatesHCAL")
2438 <<
"\tCompare Calo Energy to total charged momentum " << endl
2439 <<
"\t\tsum p = " << totalChargedMomentum <<
" +- " <<
sqrt(sumpError2) << endl
2440 <<
"\t\tsum ecal = " << totalEcal << endl
2441 <<
"\t\tsum hcal = " << totalHcal << endl
2442 <<
"\t\t => Calo Energy = " << caloEnergy <<
" +- " << caloResolution << endl
2443 <<
"\t\t => Calo Energy- total charged momentum = " << caloEnergy - totalChargedMomentum <<
" +- "
2450 double nsigma =
nSigmaHCAL(totalChargedMomentum, hclusterref->positionREP().Eta());
2452 if (
abs(totalChargedMomentum - caloEnergy) < nsigma * totalError) {
2457 LogTrace(
"PFAlgo|createCandidatesHCAL")
2458 <<
"\t\tcase 1: COMPATIBLE "
2459 <<
"|Calo Energy- total charged momentum| = " <<
abs(caloEnergy - totalChargedMomentum) <<
" < " << nsigma
2460 <<
" x " << totalError;
2462 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\t\tmax DP/P = " << maxDPovP <<
" less than 0.1: do nothing ";
2464 LogTrace(
"PFAlgo|createCandidatesHCAL")
2465 <<
"\t\t\tmax DP/P = " << maxDPovP <<
" > 0.1: take weighted averages ";
2469 if (maxDPovP > 0.1) {
2472 int nrows = chargedHadronsIndices.size();
2473 TMatrixTSym<double>
a(nrows);
2475 TVectorD
check(nrows);
2476 double sigma2E = caloResolution * caloResolution;
2477 for (
int i = 0;
i < nrows;
i++) {
2478 double sigma2i = hcalDP[
i] * hcalDP[
i];
2479 LogTrace(
"PFAlgo|createCandidatesHCAL")
2480 <<
"\t\t\ttrack associated to hcal " <<
i <<
" P = " << hcalP[
i] <<
" +- " << hcalDP[
i];
2481 a(
i,
i) = 1. / sigma2i + 1. / sigma2E;
2482 b(
i) = hcalP[
i] / sigma2i + caloEnergy / sigma2E;
2483 for (
int j = 0;
j < nrows;
j++) {
2486 a(
i,
j) = 1. / sigma2E;
2491 TDecompChol decomp(
a);
2493 TVectorD
x = decomp.Solve(
b,
ok);
2497 for (
int i = 0;
i < nrows;
i++) {
2499 unsigned ich = chargedHadronsIndices[
i];
2500 double rescaleFactor =
x(
i) / hcalP[
i];
2501 if (rescaleFactor < 0.)
2503 (*pfCandidates_)[ich].rescaleMomentum(rescaleFactor);
2505 LogTrace(
"PFAlgo|createCandidatesHCAL")
2506 <<
"\t\t\told p " << hcalP[
i] <<
" new p " <<
x(
i) <<
" rescale " << rescaleFactor;
2509 edm::LogError(
"PFAlgo::createCandidatesHCAL") <<
"TDecompChol.Solve returned ok=false";
2516 else if (caloEnergy > totalChargedMomentum) {
2521 double eNeutralHadron = caloEnergy - totalChargedMomentum;
2522 double ePhoton = (caloEnergy - totalChargedMomentum) /
2528 if (!sortedTracks.empty()) {
2529 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tcase 2: NEUTRAL DETECTION " << caloEnergy <<
" > " << nsigma
2530 <<
"x" << totalError <<
" + " << totalChargedMomentum;
2531 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tneutral activity detected: " << endl
2532 <<
"\t\t\t photon = " << ePhoton << endl
2533 <<
"\t\t\tor neutral hadron = " << eNeutralHadron;
2535 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tphoton or hadron ?";
2538 if (sortedTracks.empty())
2539 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"\t\tno track -> hadron ";
2541 LogTrace(
"PFAlgo|createCandidatesHCAL")
2542 <<
"\t\t" << sortedTracks.size() <<
" tracks -> check if the excess is photonic or hadronic";
2547 unsigned maxiEcal = 9999;
2551 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"loop over sortedTracks.size()=" << sortedTracks.size();
2552 for (
auto const& trk : sortedTracks) {
2553 unsigned iTrack = trk.second;
2561 auto iae = associatedEcals.find(iTrack);
2563 if (iae == associatedEcals.end())
2567 unsigned iEcal = iae->second.second;
2575 double pTrack = trackRef->p();
2576 double eECAL = clusterRef->energy();
2577 double eECALOverpTrack = eECAL / pTrack;
2581 maxEcalRef = clusterRef;
2587 std::vector<reco::PFClusterRef> pivotalClusterRef;
2588 std::vector<unsigned> iPivotal;
2589 std::vector<double> particleEnergy, ecalEnergy, hcalEnergy, rawecalEnergy, rawhcalEnergy;
2590 std::vector<::math::XYZVector> particleDirection;
2594 if (ePhoton < totalEcal || eNeutralHadron - calibEcal < 1E-10) {
2595 if (!maxEcalRef.
isNull()) {
2597 mergedPhotonEnergy = ePhoton;
2601 if (!maxEcalRef.
isNull()) {
2603 mergedPhotonEnergy = totalEcalEGMCalib;
2606 mergedNeutralHadronEnergy = eNeutralHadron - calibEcal;
2609 if (mergedPhotonEnergy > 0) {
2619 sumEcalClusters =
sqrt(photonAtECAL.Mag2());
2622 const double clusterEnergyCalibrated =
2623 sqrt(std::get<1>(pae).Mag2()) *
2626 particleEnergy.push_back(mergedPhotonEnergy * clusterEnergyCalibrated / sumEcalClusters);
2627 particleDirection.push_back(std::get<1>(pae));
2628 ecalEnergy.push_back(mergedPhotonEnergy * clusterEnergyCalibrated / sumEcalClusters);
2629 hcalEnergy.push_back(0.);
2630 rawecalEnergy.push_back(totalEcal);
2631 rawhcalEnergy.push_back(0.);
2632 pivotalClusterRef.push_back(
elements[std::get<0>(pae)].clusterRef());
2633 iPivotal.push_back(std::get<0>(pae));
2637 if (mergedNeutralHadronEnergy > 1.0) {
2646 sumEcalClusters =
sqrt(hadronAtECAL.Mag2());
2649 const double clusterEnergyCalibrated =
2650 sqrt(std::get<1>(pae).Mag2()) *
2653 particleEnergy.push_back(mergedNeutralHadronEnergy * clusterEnergyCalibrated / sumEcalClusters);
2654 particleDirection.push_back(std::get<1>(pae));
2655 ecalEnergy.push_back(0.);
2656 hcalEnergy.push_back(mergedNeutralHadronEnergy * clusterEnergyCalibrated / sumEcalClusters);
2657 rawecalEnergy.push_back(0.);
2658 rawhcalEnergy.push_back(totalHcal);
2659 pivotalClusterRef.push_back(hclusterref);
2660 iPivotal.push_back(iHcal);
2668 for (
unsigned iPivot = 0; iPivot < iPivotal.size(); ++iPivot) {
2669 if (particleEnergy[iPivot] < 0.)
2671 <<
"ALARM = Negative energy for iPivot=" << iPivot <<
", " << particleEnergy[iPivot];
2673 const bool useDirection =
true;
2675 particleEnergy[iPivot],
2677 particleDirection[iPivot].
X(),
2678 particleDirection[iPivot].
Y(),
2679 particleDirection[iPivot].
Z())];
2681 neutral.setEcalEnergy(rawecalEnergy[iPivot], ecalEnergy[iPivot]);
2683 neutral.setHcalEnergy(rawhcalEnergy[iPivot], hcalEnergy[iPivot]);
2684 neutral.setHoEnergy(0., 0.);
2686 if (rawhcalEnergy[iPivot] == 0.) {
2687 neutral.setHcalEnergy(0., 0.);
2688 neutral.setHoEnergy(0., 0.);
2690 neutral.setHcalEnergy(
max(rawhcalEnergy[iPivot] - totalHO, 0.0),
2691 hcalEnergy[iPivot] *
max(1. - totalHO / rawhcalEnergy[iPivot], 0.));
2692 neutral.setHoEnergy(totalHO, totalHO * hcalEnergy[iPivot] / rawhcalEnergy[iPivot]);
2695 neutral.setPs1Energy(0.);
2696 neutral.setPs2Energy(0.);
2697 neutral.set_mva_nothing_gamma(-1.);
2700 neutral.addElementInBlock(blockref, iHcal);
2701 for (
unsigned iTrack : chargedHadronsInBlock) {
2702 neutral.addElementInBlock(blockref, iTrack);
2705 dynamic_cast<const reco::PFBlockElementTrack*>(&
elements[iTrack])->positionAtECALEntrance();
2706 neutral.setPositionAtECALEntrance(chargedPosition);
2708 auto myEcals = associatedEcals.equal_range(iTrack);
2709 for (
auto ii = myEcals.first;
ii != myEcals.second; ++
ii) {
2710 unsigned iEcal =
ii->second.second;
2713 neutral.addElementInBlock(blockref, iEcal);
2728 double totalHcalEnergyCalibrated =
std::max(calibHcal - mergedNeutralHadronEnergy, 0.);
2730 double totalEcalEnergyCalibrated =
std::max(calibEcal - mergedPhotonEnergy, 0.);
2735 double chargedHadronsTotalEnergy = 0;
2736 for (
unsigned index : chargedHadronsIndices) {
2741 for (
unsigned index : chargedHadronsIndices) {
2750 fraction * totalHcalEnergyCalibrated * (1. - totalHO / totalHcal));
2758 for (
auto const& ecalSatellite : ecalSatellites) {
2760 unsigned iEcal = std::get<0>(ecalSatellite.second);
2771 active[iEcal] =
false;
2774 std::multimap<double, unsigned> assTracks;
2778 double ecalClusterEnergyCalibrated =
2779 sqrt(std::get<1>(ecalSatellite.second).Mag2()) *
2781 ecalSatellite.second);
2783 cand.setEcalEnergy(eclusterref->energy(), ecalClusterEnergyCalibrated);
2784 cand.setHcalEnergy(0., 0.);
2785 cand.setHoEnergy(0., 0.);
2786 cand.setPs1Energy(associatedPSs[iEcal].
first);
2787 cand.setPs2Energy(associatedPSs[iEcal].
second);
2788 cand.addElementInBlock(blockref, iEcal);
2789 cand.addElementInBlock(blockref, sortedTracks.begin()->second);
2791 if (fabs(eclusterref->energy() -
sqrt(std::get<1>(ecalSatellite.second).Mag2())) > 1
e-3 ||
2792 fabs(eclusterref->correctedEnergy() - ecalClusterEnergyCalibrated) > 1
e-3)
2794 <<
"ecalCluster vs ecalSatellites look inconsistent (eCluster E, calibE, ecalSatellite E, calib E): "
2795 << eclusterref->energy() <<
" " << eclusterref->correctedEnergy() <<
" "
2796 <<
sqrt(std::get<1>(ecalSatellite.second).Mag2()) <<
" " << ecalClusterEnergyCalibrated;
2802 LogTrace(
"PFAlgo|createCandidatesHCAL") <<
"end of function PFAlgo::createCandidatesHCAL";
2808 std::vector<bool>& active,
2811 std::vector<bool>& deadArea) {
2813 LogTrace(
"PFAlgo|createCandidatesHCALUnlinked")
2814 <<
"start of function PFAlgo::createCandidatesHCALUnlinked, hcalIs.size()=" << inds.
hcalIs.size();
2818 for (
unsigned iHcal : inds.
hcalIs) {
2820 std::vector<unsigned> ecalRefs;
2821 std::vector<unsigned> hoRefs;
2825 if (!active[iHcal]) {
2826 LogTrace(
"PFAlgo|createCandidatesHCALUnlinked") <<
"not active " << iHcal;
2831 std::multimap<double, unsigned> ecalElems;
2835 float totalEcal = 0.;
2838 for (
auto const&
ecal : ecalElems) {
2839 unsigned iEcal =
ecal.second;
2840 double dist =
ecal.first;
2867 std::multimap<double, unsigned> hcalElems;
2870 const bool isClosest = std::none_of(hcalElems.begin(), hcalElems.end(), [&](
auto const&
hcal) {
2871 return active[
hcal.second] &&
hcal.first < dist;
2878 LogTrace(
"PFAlgo|createCandidatesHCALUnlinked")
2879 <<
"\telement " <<
elements[iEcal] <<
" linked with dist " << dist;
2880 LogTrace(
"PFAlgo|createCandidatesHCALUnlinked") <<
"Added to HCAL cluster to form a neutral hadron";
2887 double ecalEnergy = eclusterRef->energy();
2889 totalEcal += ecalEnergy;
2890 if (ecalEnergy > ecalMax) {
2891 ecalMax = ecalEnergy;
2892 eClusterRef = eclusterRef;
2895 ecalRefs.push_back(iEcal);
2896 active[iEcal] =
false;
2901 double totalHO = 0.;
2905 std::multimap<double, unsigned> hoElems;
2913 for (
auto const&
ho : hoElems) {
2914 unsigned iHO =
ho.second;
2915 double dist =
ho.first;
2927 std::multimap<double, unsigned> hcalElems;
2930 const bool isClosest = std::none_of(hcalElems.begin(), hcalElems.end(), [&](
auto const&
hcal) {
2931 return active[
hcal.second] &&
hcal.first < dist;
2939 LogTrace(
"PFAlgo|createCandidatesHCALUnlinked")
2940 <<
"\telement " <<
elements[iHO] <<
" linked with dist " << dist;
2941 LogTrace(
"PFAlgo|createCandidatesHCALUnlinked") <<
"Added to HCAL cluster to form a neutral hadron";
2949 hoclusterRef->energy();
2951 totalHO += hoEnergy;
2952 if (hoEnergy > hoMax) {
2954 hoClusterRef = hoclusterRef;
2958 hoRefs.push_back(iHO);
2959 active[iHO] =
false;
2968 double totalHcal = hclusterRef->energy();
2971 totalHcal += totalHO;
2974 double calibEcal = totalEcal > 0. ? totalEcal : 0.;
2975 double calibHcal =
std::max(0., totalHcal);
2977 calibEcal = totalEcal;
2980 -1., calibEcal, calibHcal, hclusterRef->positionREP().Eta(), hclusterRef->positionREP().Phi());
2985 cand.setEcalEnergy(totalEcal, calibEcal);
2987 cand.setHcalEnergy(totalHcal, calibHcal);
2988 cand.setHoEnergy(0., 0.);
2990 cand.setHcalEnergy(
max(totalHcal - totalHO, 0.0), calibHcal * (1. - totalHO / totalHcal));
2991 cand.setHoEnergy(totalHO, totalHO * calibHcal / totalHcal);
2993 cand.setPs1Energy(0.);
2994 cand.setPs2Energy(0.);
2995 cand.addElementInBlock(blockref, iHcal);
2996 for (
auto const& ec : ecalRefs)
2997 cand.addElementInBlock(blockref, ec);
2998 for (
auto const&
ho : hoRefs)
2999 cand.addElementInBlock(blockref,
ho);
3007 std::vector<bool>& active,
3010 std::vector<bool>& deadArea) {
3011 LogTrace(
"PFAlgo|createCandidatesECAL")
3012 <<
"start of function PFAlgo::createCandidatesECAL(), ecalIs.size()=" << inds.
ecalIs.size();
3018 for (
unsigned i = 0;
i < inds.
ecalIs.size();
i++) {
3019 unsigned iEcal = inds.
ecalIs[
i];
3021 LogTrace(
"PFAlgo|createCandidatesECAL") <<
"elements[" << iEcal <<
"]=" <<
elements[iEcal];
3023 if (!active[iEcal]) {
3024 LogTrace(
"PFAlgo|createCandidatesECAL") <<
"iEcal=" << iEcal <<
" not active";
3034 active[iEcal] =
false;
3036 float ecalEnergy = clusterref->correctedEnergy();
3038 double particleEnergy = ecalEnergy;
3042 cand.setEcalEnergy(clusterref->energy(), ecalEnergy);
3043 cand.setHcalEnergy(0., 0.);
3044 cand.setHoEnergy(0., 0.);
3045 cand.setPs1Energy(0.);
3046 cand.setPs2Energy(0.);
3047 cand.addElementInBlock(blockref, iEcal);
3050 LogTrace(
"PFAlgo|createCandidatesECAL") <<
"end of function PFALgo::createCandidatesECAL";
3054 std::list<reco::PFBlockRef>& hcalBlockRefs,
3055 std::list<reco::PFBlockRef>& ecalBlockRefs,
3060 LogTrace(
"PFAlgo|processBlock") <<
"start of function PFAlgo::processBlock, block=" <<
block;
3068 vector<bool> active(
elements.size(),
true);
3072 std::vector<reco::PFCandidate> tempElectronCandidates;
3073 tempElectronCandidates.clear();
3106 vector<bool> deadArea(
elements.size(),
false);
3115 if (!(inds.hfEmIs.empty() && inds.hfHadIs.empty())) {
3117 if (inds.hcalIs.empty() && inds.ecalIs.empty())
3120 <<
"Block contains HF clusters, and also contains ECAL or HCAL clusters. Continue.\n"
3129 LogTrace(
"PFAlgo|processBlock") <<
"end of function PFAlgo::processBlock";
3134 const auto* eltTrack = dynamic_cast<const reco::PFBlockElementTrack*>(&elt);
3144 double pz =
track.pz();
3147 LogTrace(
"PFAlgo|reconstructTrack") <<
"Reconstructing PF candidate from track of pT = " <<
track.pt()
3148 <<
" eta = " <<
track.eta() <<
" phi = " <<
track.phi() <<
" px = " <<
px
3149 <<
" py = " <<
py <<
" pz = " << pz <<
" energy = " <<
energy;
3157 <<
", pt=" << momentum.pt() <<
", eta=" << momentum.eta()
3158 <<
", phi=" << momentum.phi();
3163 pfCandidates_->back().setPositionAtECALEntrance(eltTrack->positionAtECALEntrance());
3175 if ((!
isMuon) && isFromDisp) {
3176 double dpt = trackRef->ptError();
3177 double dptRel = dpt / trackRef->pt() * 100;
3182 LogTrace(
"PFAlgo|reconstructTrack")
3183 <<
"Not refitted px = " <<
px <<
" py = " <<
py <<
" pz = " << pz <<
" energy = " <<
energy;
3187 reco::Track trackRefit = vRef->refittedTrack(trackRef);
3190 trackRefit.
px(), trackRefit.
py(), trackRefit.
pz(),
sqrt(trackRefit.
p() * trackRefit.
p() + 0.13957 * 0.13957));
3191 LogTrace(
"PFAlgo|reconstructTrack")
3192 <<
"Refitted px = " <<
px <<
" py = " <<
py <<
" pz = " << pz <<
" energy = " <<
energy;
3213 double particleEnergy,
3218 LogTrace(
"PFAlgo|reconstructCluster") <<
"start of function PFAlgo::reconstructCluster, cluster=" << cluster
3219 <<
"particleEnergy=" << particleEnergy <<
"useDirection=" << useDirection
3220 <<
"particleX=" << particleX <<
"particleY=" << particleY
3221 <<
"particleZ=" << particleZ;
3231 switch (cluster.
layer()) {
3254 cluster.
position().Y() - vertexPos.Y(),
3255 cluster.
position().Z() - vertexPos.Z());
3257 particleX *
factor - vertexPos.X(), particleY *
factor - vertexPos.Y(), particleZ *
factor - vertexPos.Z());
3262 clusterPos = useDirection ? particleDirection.Unit() : clusterPos.Unit();
3263 clusterPos *= particleEnergy;
3269 ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double>> momentum(
3270 clusterPos.X(), clusterPos.Y(), clusterPos.Z(),
mass);
3280 switch (cluster.
layer()) {
3301 <<
", pt=" <<
tmp.pt() <<
", eta=" <<
tmp.eta() <<
", phi=" <<
tmp.phi();
3324 std::array<double, 7> energyPerDepth;
3325 std::fill(energyPerDepth.begin(), energyPerDepth.end(), 0.0);
3327 const auto&
hit = *hitRefAndFrac.recHitRef();
3329 if (
hit.depth() == 0) {
3333 if (
hit.depth() < 1 ||
hit.depth() > 7) {
3334 throw cms::Exception(
"CorruptData") <<
"Bogus depth " <<
hit.depth() <<
" at detid " <<
hit.detId() <<
"\n";
3336 energyPerDepth[
hit.depth() - 1] += hitRefAndFrac.fraction() *
hit.energy();
3339 double sum = std::accumulate(energyPerDepth.begin(), energyPerDepth.end(), 0.);
3340 std::array<float, 7> depthFractions;
3342 for (
unsigned int i = 0;
i < depthFractions.size(); ++
i) {
3343 depthFractions[
i] = energyPerDepth[
i] / sum;
3346 std::fill(depthFractions.begin(), depthFractions.end(), 0.f);
3348 cand.setHcalDepthEnergyFractions(depthFractions);
3355 clusterEnergyHCAL =
std::max(clusterEnergyHCAL, 1.);
3357 double resol = fabs(
eta) < 1.48 ?
sqrt(1.02 * 1.02 / clusterEnergyHCAL + 0.065 * 0.065)
3358 :
sqrt(1.20 * 1.20 / clusterEnergyHCAL + 0.028 * 0.028);
3372 clusterEnergyHF =
std::max(clusterEnergyHF, 1.);
3396 out <<
"====== Particle Flow Algorithm ======= ";
3398 out <<
"nSigmaECAL_ " <<
algo.nSigmaECAL_ << endl;
3399 out <<
"nSigmaHCAL_ " <<
algo.nSigmaHCAL_ << endl;
3400 out <<
"nSigmaHFEM_ " <<
algo.nSigmaHFEM_ << endl;
3401 out <<
"nSigmaHFHAD_ " <<
algo.nSigmaHFHAD_ << endl;
3403 out <<
algo.calibration_ << endl;
3405 out <<
"reconstructed particles: " << endl;
3407 if (!
algo.pfCandidates_.get()) {
3408 out <<
"candidates already transfered" << endl;
3411 for (
auto const&
c : *
algo.pfCandidates_)
3422 std::vector<bool>& active,
3423 std::vector<double>& psEne) {
3430 std::multimap<double, unsigned> sortedPS;
3434 double totalPS = 0.;
3435 for (
auto const& ps : sortedPS) {
3437 unsigned iPS = ps.second;
3445 std::multimap<double, unsigned> sortedECAL;
3447 unsigned jEcal = sortedECAL.begin()->second;
3453 assert(pstype == psElementType);
3456 totalPS += psclusterref->energy();
3457 psEne[0] += psclusterref->energy();
3458 active[iPS] =
false;
3468 bool bPrimary = (
order.find(
"primary") != string::npos);
3469 bool bSecondary = (
order.find(
"secondary") != string::npos);
3470 bool bAll = (
order.find(
"all") != string::npos);
3475 if (bPrimary && isToDisp)
3477 if (bSecondary && isFromDisp)
3479 if (bAll && (isToDisp || isFromDisp))
3496 std::vector<unsigned int> pfCandidatesToBeRemoved;
3502 double met2 = metX * metX + metY * metY;
3507 double metXCor = metX;
3508 double metYCor = metY;
3509 double sumetCor = sumet;
3510 double met2Cor = met2;
3512 double deltaPhiPt = 100.;
3514 unsigned iCor = 1E9;
3518 double metReduc = -1.;
3532 const bool skip = std::any_of(
3533 pfCandidatesToBeRemoved.begin(), pfCandidatesToBeRemoved.end(), [&](
unsigned int j) {
return i ==
j; });
3544 double metXInt = metX - pfc.
px();
3545 double metYInt = metY - pfc.
py();
3546 double sumetInt = sumet - pfc.
pt();
3547 double met2Int = metXInt * metXInt + metYInt * metYInt;
3548 if (met2Int < met2Cor) {
3551 metReduc = (met2 - met2Int) / met2Int;
3553 sumetCor = sumetInt;
3554 significanceCor =
std::sqrt(met2Cor / sumetCor);
3561 pfCandidatesToBeRemoved.push_back(iCor);
3576 for (
unsigned int toRemove : pfCandidatesToBeRemoved) {
3577 edm::LogInfo(
"PFAlgo|postCleaning") <<
"Removed : " << (*pfCandidates_)[toRemove];
3579 (*pfCandidates_)[toRemove].rescaleMomentum(1E-6);
3589 if (cleanedHits.empty())
3596 std::vector<unsigned int> hitsToBeAdded;
3602 double met2 = metX * metX + metY * metY;
3603 double met2_Original = met2;
3607 double metXCor = metX;
3608 double metYCor = metY;
3609 double sumetCor = sumet;
3610 double met2Cor = met2;
3612 unsigned iCor = 1E9;
3616 double metReduc = -1.;
3618 for (
unsigned i = 0;
i < cleanedHits.size(); ++
i) {
3621 double px =
hit.energy() *
hit.position().
x() / length;
3622 double py =
hit.energy() *
hit.position().
y() / length;
3627 for (
unsigned int hitIdx : hitsToBeAdded) {
3637 double metXInt = metX +
px;
3638 double metYInt = metY +
py;
3639 double sumetInt = sumet +
pt;
3640 double met2Int = metXInt * metXInt + metYInt * metYInt;
3643 if (met2Int < met2Cor) {
3646 metReduc = (met2 - met2Int) / met2Int;
3648 sumetCor = sumetInt;
3657 hitsToBeAdded.push_back(iCor);
3670 LogTrace(
"PFAlgo|checkCleaning") << hitsToBeAdded.size() <<
" hits were re-added ";
3673 LogTrace(
"PFAlgo|checkCleaning") <<
"Added after cleaning check : ";
3674 for (
unsigned int hitIdx : hitsToBeAdded) {