36 #include "Math/PxPyPzM4D.h" 37 #include "Math/LorentzVector.h" 38 #include "Math/DisplacementVector3D.h" 39 #include "Math/SMatrix.h" 40 #include "TDecompChol.h" 64 const std::shared_ptr<PFEnergyCalibration>& calibration,
65 const std::shared_ptr<PFEnergyCalibrationHF>& thepfEnergyCalibrationHF) {
83 string mvaWeightFileEleID,
85 const std::shared_ptr<PFSCEnergyCalibration>& thePFSCEnergyCalibration,
122 string err =
"PFAlgo: cannot open weight file '";
123 err += mvaWeightFileEleID;
125 throw invalid_argument( err );
164 e(0, 0) = 0.0015 * 0.0015;
165 e(1, 1) = 0.0015 * 0.0015;
172 FILE * filePhotonConvID = fopen(mvaWeightFileConvID.c_str(),
"r");
173 if (filePhotonConvID) {
174 fclose(filePhotonConvID);
177 string err =
"PFAlgo: cannot open weight file '";
178 err += mvaWeightFileConvID;
180 throw invalid_argument( err );
183 pfpho_ = std::make_unique<PFPhotonAlgo>(mvaWeightFileConvID,
223 pfpho_->setGBRForest(LCorrForestEB,LCorrForestEE,
224 GCorrForestBarrel, GCorrForestEndcapHr9,
225 GCorrForestEndcapLr9, PFEcalResolution);
236 assert (
muonHCAL_.size() == 2 && muonECAL_.size() == 2 && muonHO_.size() == 2);
240 assert ( factors45_.size() == 2 );
311 bool primaryVertexFound =
false;
312 nVtx_ = primaryVertices.size();
316 for(
auto const& vertex : primaryVertices)
318 if(vertex.isValid()&&(!vertex.isFake()))
321 primaryVertexFound =
true;
333 e(0, 0) = 0.0015 * 0.0015;
334 e(1, 1) = 0.0015 * 0.0015;
339 pfpho_->setPhotonPrimaryVtx(dummy);
379 cout<<
"*********************************************************"<<endl;
380 cout<<
"***** Particle flow algorithm *****"<<endl;
381 cout<<
"*********************************************************"<<endl;
385 std::list< reco::PFBlockRef > hcalBlockRefs;
386 std::list< reco::PFBlockRef > ecalBlockRefs;
387 std::list< reco::PFBlockRef > hoBlockRefs;
388 std::list< reco::PFBlockRef > otherBlockRefs;
390 for(
unsigned i=0;
i<blocks.size(); ++
i ) {
398 bool singleEcalOrHcal =
false;
399 if( elements.
size() == 1 ){
401 ecalBlockRefs.push_back( blockref );
402 singleEcalOrHcal =
true;
405 hcalBlockRefs.push_back( blockref );
406 singleEcalOrHcal =
true;
410 hoBlockRefs.push_back( blockref );
411 singleEcalOrHcal =
true;
415 if(!singleEcalOrHcal) {
416 otherBlockRefs.push_back( blockref );
421 cout<<
"# Ecal blocks: "<<ecalBlockRefs.size()
422 <<
", # Hcal blocks: "<<hcalBlockRefs.size()
423 <<
", # HO blocks: "<<hoBlockRefs.size()
424 <<
", # Other blocks: "<<otherBlockRefs.size()<<endl;
432 for(
auto const&
other : otherBlockRefs) {
437 std::list< reco::PFBlockRef >
empty;
441 for(
auto const&
hcal : hcalBlockRefs) {
442 if (
debug_ )
std::cout <<
"HCAL block number " << hblcks++ << std::endl;
448 for(
auto const&
ecal : ecalBlockRefs) {
449 if (
debug_ )
std::cout <<
"ECAL block number " << eblcks++ << std::endl;
466 std::list<reco::PFBlockRef>& hcalBlockRefs,
467 std::list<reco::PFBlockRef>& ecalBlockRefs,
PFEGammaFilters const* pfegamma ) {
470 assert(!blockref.
isNull() );
474 cout<<
"#########################################################"<<endl;
475 cout<<
"##### Process Block: #####"<<endl;
476 cout<<
"#########################################################"<<endl;
486 vector<bool> active( elements.
size(),
true );
491 std::vector<reco::PFCandidate> tempElectronCandidates;
492 tempElectronCandidates.clear();
496 const std::vector<reco::PFCandidate> PFElectCandidates_(
pfele_->getElectronCandidates());
497 for(
auto const&
ec : PFElectCandidates_) tempElectronCandidates.push_back(
ec);
506 pfele_->getAllElectronCandidates().begin(),
507 pfele_->getAllElectronCandidates().end());
510 pfele_->getElectronExtra().begin(),
511 pfele_->getElectronExtra().end());
517 cout<<endl<<
"--------------- entering PFPhotonAlgo ----------------"<<endl;
518 vector<PFCandidatePhotonExtra> pfPhotonExtraCand;
519 if (
pfpho_->isPhotonValidCandidate(blockref,
523 tempElectronCandidates
533 unsigned int extracand =0;
541 pfPhotonExtraCand.clear();
546 for(
auto const&
ec : tempElectronCandidates) {
549 tempElectronCandidates.clear();
557 bool egmLocalDebug =
debug_;
558 bool egmLocalBlockDebug =
false;
561 for(
unsigned int ieg=0 ; ieg < negmcandidates; ++ieg) {
566 PFCandidate::ElementsInBlocks::const_iterator iegfirst = theElements.begin();
567 bool sameBlock =
false;
568 bool isGoodElectron =
false;
569 bool isGoodPhoton =
false;
570 bool isPrimaryElectron =
false;
571 if(iegfirst->first == blockref)
576 cout <<
" I am in looping on EGamma Candidates: pt " << (*pfEgmRef).pt()
577 <<
" eta,phi " << (*pfEgmRef).eta() <<
", " << (*pfEgmRef).phi()
578 <<
" charge " << (*pfEgmRef).charge() << endl;
580 if((*pfEgmRef).gsfTrackRef().isNonnull()) {
585 isPrimaryElectron = pfegamma->
isElectron(*gedEleRef);
588 cout <<
"** Good Electron, pt " << gedEleRef->pt()
589 <<
" eta, phi " << gedEleRef->eta() <<
", " << gedEleRef->phi()
590 <<
" charge " << gedEleRef->charge()
591 <<
" isPrimary " << isPrimaryElectron
592 <<
" isoDr03 " << (gedEleRef->dr03TkSumPt() + gedEleRef->dr03EcalRecHitSumEt() + gedEleRef->dr03HcalTowerSumEt())
593 <<
" mva_isolated " << gedEleRef->mva_Isolated()
594 <<
" mva_e_pi " << gedEleRef->mva_e_pi()
601 if((*pfEgmRef).superClusterRef().isNonnull()) {
608 cout <<
"** Good Photon, pt " << gedPhoRef->pt()
609 <<
" eta, phi " << gedPhoRef->eta() <<
", " << gedPhoRef->phi() << endl;
615 if(isGoodElectron && isGoodPhoton) {
616 if(isPrimaryElectron)
617 isGoodPhoton =
false;
619 isGoodElectron =
false;
627 bool lockTracks =
false;
637 myPFElectron.
setCharge(gedEleRef->charge());
638 myPFElectron.
setP4(gedEleRef->p4());
643 cout <<
" PFAlgo: found an electron with NEW EGamma code " << endl;
644 cout <<
" myPFElectron: pt " << myPFElectron.
pt()
645 <<
" eta,phi " << myPFElectron.
eta() <<
", " <<myPFElectron.
phi()
646 <<
" mva " << myPFElectron.
mva_e_pi()
647 <<
" charge " << myPFElectron.
charge() << endl;
652 if(egmLocalBlockDebug)
653 cout <<
" THE BLOCK " << *blockref << endl;
654 for (
auto const& eb : theElements) {
655 active[eb.second] =
false;
656 if(egmLocalBlockDebug||(
debug_&&egmLocalDebug))
657 cout <<
" Elements used " << eb.second << endl;
663 for (
auto const& trk : extraTracks) {
664 if(egmLocalBlockDebug||(
debug_&&egmLocalDebug)) {
665 cout <<
" Extra locked track " << trk.second << endl;
667 active[trk.second] =
false;
676 cout <<
"PFAlgo: Electron DISCARDED, NOT SAFE FOR JETMET " << endl;
696 myPFPhoton.
setP4(gedPhoRef->p4());
698 cout <<
" PFAlgo: found a photon with NEW EGamma code " << endl;
699 cout <<
" myPFPhoton: pt " << myPFPhoton.
pt()
700 <<
" eta,phi " << myPFPhoton.
eta() <<
", " <<myPFPhoton.
phi()
701 <<
" charge " << myPFPhoton.
charge() << endl;
705 if(egmLocalBlockDebug)
706 cout <<
" THE BLOCK " << *blockref << endl;
707 for (
auto const& eb : theElements) {
708 active[eb.second] =
false;
709 if(egmLocalBlockDebug||(
debug_&&egmLocalDebug))
710 cout <<
" Elements used " << eb.second << endl;
724 for(
unsigned iEle=0; iEle<elements.
size(); iEle++) {
726 if(type==PFBlockElement::TRACK)
733 if(!elements[iEle].convRefs().
empty())active[iEle]=
false;
743 cout<<endl<<
"--------------- loop 1 ------------------"<<endl;
770 vector<unsigned> hcalIs;
771 vector<unsigned> hoIs;
772 vector<unsigned> ecalIs;
773 vector<unsigned> trackIs;
774 vector<unsigned> ps1Is;
775 vector<unsigned> ps2Is;
777 vector<unsigned> hfEmIs;
778 vector<unsigned> hfHadIs;
780 vector<bool> deadArea(elements.
size(),
false);
782 for(
unsigned iEle=0; iEle<elements.
size(); iEle++) {
785 if(
debug_ && type != PFBlockElement::BREM )
cout<<endl<<elements[iEle];
788 case PFBlockElement::TRACK:
789 if ( active[iEle] ) {
791 if(
debug_)
cout<<
"TRACK, stored index, continue"<<endl;
795 if ( active[iEle] ) {
796 ecalIs.push_back( iEle );
797 if(
debug_)
cout<<
"ECAL, stored index, continue"<<endl;
801 if ( active[iEle] ) {
803 if(
debug_)
cout<<
"HCAL DEAD AREA: remember and skip."<<endl;
804 active[iEle] =
false;
805 deadArea[iEle] =
true;
808 hcalIs.push_back( iEle );
809 if(
debug_)
cout<<
"HCAL, stored index, continue"<<endl;
814 if ( active[iEle] ) {
815 hoIs.push_back( iEle );
816 if(
debug_)
cout<<
"HO, stored index, continue"<<endl;
820 case PFBlockElement::HFEM:
821 if ( active[iEle] ) {
822 hfEmIs.push_back( iEle );
823 if(
debug_)
cout<<
"HFEM, stored index, continue"<<endl;
826 case PFBlockElement::HFHAD:
827 if ( active[iEle] ) {
828 hfHadIs.push_back( iEle );
829 if(
debug_)
cout<<
"HFHAD, stored index, continue"<<endl;
837 unsigned iTrack = iEle;
840 cout <<
"track " << iTrack <<
" has a valid muon reference. " << std::endl;
850 if (active[iTrack] &&
isFromSecInt(elements[iEle],
"primary")){
851 bool isPrimaryTrack = elements[iEle].displacedVertexRef(PFBlockElement::T_TO_DISP)->displacedVertexRef()->isTherePrimaryTracks();
852 if (isPrimaryTrack) {
853 if (
debug_)
cout <<
"Primary Track reconstructed alone" << endl;
856 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEle );
857 active[iTrack] =
false;
863 if ( !active[iTrack] )
864 cout <<
"Already used by electrons, muons, conversions" << endl;
869 if ( ! active[iTrack] )
continue;
872 assert( !trackRef.
isNull() );
875 cout <<
"PFAlgo:processBlock "<<
" "<<trackIs.size()<<
" "<<ecalIs.size()<<
" "<<hcalIs.size()<<
" "<<hoIs.size()<<endl;
882 std::multimap<double, unsigned> ecalElems;
883 block.associatedElements( iTrack, linkData,
888 std::multimap<double, unsigned> hcalElems;
889 block.associatedElements( iTrack, linkData,
895 std::cout <<
"\tTrack " << iTrack <<
" is linked to " << ecalElems.size() <<
" ecal and " << hcalElems.size() <<
" hcal elements" << std::endl;
896 for (
const auto & pair : ecalElems) {
897 std::cout <<
"ecal: dist " << pair.first <<
"\t elem " << pair.second << std::endl;
899 for (
const auto & pair : hcalElems) {
900 std::cout <<
"hcal: dist " << pair.first <<
"\t elem " << pair.second << (deadArea[pair.second] ?
" DEAD AREA MARKER" :
"") << std::endl;
915 bool hasDeadHcal =
false;
916 if (!hcalElems.empty() && deadArea[hcalElems.begin()->second]) {
928 bool goodTrackDeadHcal =
false;
936 if (!goodTrackDeadHcal &&
938 trackRef->hitPattern().pixelLayersWithMeasurement() >= 3 &&
939 trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS) == 0 &&
940 trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS) == 0 &&
941 trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS) <= (
942 trackRef->hitPattern().pixelLayersWithMeasurement() > 3 ?
949 goodTrackDeadHcal =
true;
953 if (
debug_)
cout <<
" track pt " << trackRef->pt() <<
" +- " << trackRef->ptError()
954 <<
" layers valid " << trackRef->hitPattern().trackerLayersWithMeasurement()
955 <<
", lost " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS)
956 <<
", lost outer " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS)
957 <<
", lost inner " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS)
958 <<
"(valid fraction " << trackRef->validFraction() <<
")" 959 <<
" chi2/ndf " << trackRef->normalizedChi2()
962 << (goodTrackDeadHcal ?
" passes " :
" fails ") <<
"quality cuts" << std::endl;
968 if ( hcalElems.empty() && !ecalElems.empty() && !hasDeadHcal) {
971 unsigned index = ecalElems.begin()->second;
972 std::multimap<double, unsigned> sortedTracks;
973 block.associatedElements( index, linkData,
977 if (
debug_ )
std::cout <<
"The closest ECAL cluster is linked to " << sortedTracks.size() <<
" tracks, with distance = " << ecalElems.begin()->first << std::endl;
980 for(
auto const& trk : sortedTracks) {
981 unsigned jTrack = trk.second;
984 if ( !active[jTrack] )
continue;
988 if ( jTrack == iTrack )
continue;
993 std::multimap<double, unsigned> sortedECAL;
994 block.associatedElements( jTrack, linkData,
998 if ( sortedECAL.begin()->second !=
index )
continue;
999 if (
debug_ )
std::cout <<
" track " << jTrack <<
" with closest ECAL identical " << std::endl;
1003 std::multimap<double, unsigned> sortedHCAL;
1004 block.associatedElements( jTrack, linkData,
1008 if ( sortedHCAL.empty() )
continue;
1009 if (
debug_ )
std::cout <<
" and with an HCAL cluster " << sortedHCAL.begin()->second << std::endl;
1013 block.setLink( iTrack,
1014 sortedHCAL.begin()->second,
1015 sortedECAL.begin()->first,
1017 PFBlock::LINKTEST_RECHIT );
1022 block.associatedElements( iTrack, linkData,
1027 if (
debug_ && !hcalElems.empty() )
1028 std::cout <<
"Track linked back to HCAL due to ECAL sharing with other tracks" << std::endl;
1038 std::multimap<double,unsigned> gsfElems;
1040 block.associatedElements( iTrack, linkData,
1046 if(hcalElems.empty() &&
debug_) {
1047 cout<<
"no hcal element connected to track "<<iTrack<<endl;
1053 bool hcalFound =
false;
1056 cout<<
"now looping on elements associated to the track"<<endl;
1060 for(
auto const&
ecal : ecalElems) {
1066 double dist =
ecal.first;
1067 cout<<
"\telement "<<elements[
index]<<
" linked with distance = "<< dist <<endl;
1068 if ( ! active[index] )
cout <<
"This ECAL is already used - skip it" << endl;
1073 if ( ! active[index] )
continue;
1079 if( !hcalElems.empty() &&
debug_)
1080 cout<<
"\t\tat least one hcal element connected to the track." 1081 <<
" Sparing Ecal cluster for the hcal loop"<<endl;
1089 if( hcalElems.empty() ) {
1092 std::cout <<
"Now deals with tracks linked to no HCAL clusters. Was HCal active? " << (!hasDeadHcal) << std::endl;
1099 std::cout << elements[iTrack] << std::endl;
1105 if ( thisIsAMuon ) trackMomentum = 0.;
1109 bool rejectFake =
false;
1110 if ( !thisIsAMuon && elements[iTrack].trackRef()->ptError() >
ptError_ ) {
1114 elements[iTrack].trackRef()->
eta());
1117 if ( !ecalElems.empty() ) {
1118 unsigned thisEcal = ecalElems.begin()->second;
1120 bool useCluster =
true;
1122 std::multimap<double, unsigned> sortedTracks;
1123 block.associatedElements( thisEcal, linkData,
1127 useCluster = (sortedTracks.begin()->second == iTrack);
1130 deficit -= clusterRef->energy();
1132 clusterRef->positionREP().Eta());
1137 bool isPrimary =
isFromSecInt(elements[iTrack],
"primary");
1139 if ( deficit >
nSigmaTRACK_*resol && !isPrimary && !goodTrackDeadHcal) {
1141 active[iTrack] =
false;
1143 std::cout << elements[iTrack] << std::endl
1144 <<
" deficit " << deficit <<
" > " <<
nSigmaTRACK_ <<
" x " << resol
1145 <<
" track pt " << trackRef->pt() <<
" +- " << trackRef->ptError()
1146 <<
" layers valid " << trackRef->hitPattern().trackerLayersWithMeasurement()
1147 <<
", lost " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS)
1148 <<
", lost outer " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_OUTER_HITS)
1149 <<
", lost inner " << trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::MISSING_INNER_HITS)
1150 <<
"(valid fraction " << trackRef->validFraction() <<
")" 1151 <<
" chi2/ndf " << trackRef->normalizedChi2()
1154 <<
"is probably a fake (1) --> lock the track" 1159 if ( rejectFake )
continue;
1164 std::vector<unsigned> tmpi;
1165 std::vector<unsigned> kTrack;
1168 double Dpt = trackRef->ptError();
1171 trackMomentum > 30. && Dpt > 0.5 &&
1173 && !goodTrackDeadHcal) ) {
1175 double dptRel = Dpt/trackRef->pt()*100;
1176 bool isPrimaryOrSecondary =
isFromSecInt(elements[iTrack],
"all");
1179 unsigned nHits = elements[iTrack].trackRef()->hitPattern().trackerLayersWithMeasurement();
1180 unsigned int NLostHit = trackRef->hitPattern().trackerLayersWithoutMeasurement(HitPattern::TRACK_HITS);
1183 std::cout <<
"A track (algo = " << trackRef->algo() <<
") with momentum " << trackMomentum
1184 <<
" / " << elements[iTrack].trackRef()->pt() <<
" +/- " << Dpt
1185 <<
" / " << elements[iTrack].trackRef()->eta()
1186 <<
" without any link to ECAL/HCAL and with " << nHits <<
" (" << NLostHit
1187 <<
") hits (lost hits) has been cleaned" << std::endl;
1188 active[iTrack] =
false;
1195 kTrack.push_back(iTrack);
1196 active[iTrack] =
false;
1199 if ( ecalElems.empty() ) {
1200 (*pfCandidates_)[tmpi[0]].setEcalEnergy( 0., 0. );
1201 (*pfCandidates_)[tmpi[0]].setHcalEnergy( 0., 0. );
1202 (*pfCandidates_)[tmpi[0]].setHoEnergy( 0., 0. );
1203 (*pfCandidates_)[tmpi[0]].setPs1Energy( 0 );
1204 (*pfCandidates_)[tmpi[0]].setPs2Energy( 0 );
1205 (*pfCandidates_)[tmpi[0]].addElementInBlock( blockref, kTrack[0] );
1210 const unsigned int thisEcal = ecalElems.begin()->second;
1212 if (
debug_ )
std::cout <<
" is associated to " << elements[thisEcal] << std::endl;
1216 if ( thisIsAMuon ) {
1217 (*pfCandidates_)[tmpi[0]].setEcalEnergy( clusterRef->energy(),
1219 (*pfCandidates_)[tmpi[0]].setHcalEnergy( 0., 0. );
1220 (*pfCandidates_)[tmpi[0]].setHoEnergy( 0., 0. );
1221 (*pfCandidates_)[tmpi[0]].setPs1Energy( 0 );
1222 (*pfCandidates_)[tmpi[0]].setPs2Energy( 0 );
1223 (*pfCandidates_)[tmpi[0]].addElementInBlock( blockref, kTrack[0] );
1226 double slopeEcal = 1.;
1227 bool connectedToEcal =
false;
1228 unsigned iEcal = 99999;
1229 double calibEcal = 0.;
1230 double calibHcal = 0.;
1231 double totalEcal = thisIsAMuon ? -
muonECAL_[0] : 0.;
1234 std::multimap<double, unsigned> sortedTracks;
1235 block.associatedElements( thisEcal, linkData,
1239 if (
debug_)
cout <<
"the closest ECAL cluster, id " << thisEcal <<
", has " << sortedTracks.size() <<
" associated tracks, now processing them. " << endl;
1241 if (hasDeadHcal && !sortedTracks.empty()) {
1243 if (
debug_)
cout <<
" the closest track to ECAL " << thisEcal <<
" is " << sortedTracks.begin()->second <<
" (distance " << sortedTracks.begin()->first <<
")" << endl;
1244 if (sortedTracks.begin()->second != iTrack) {
1245 if (
debug_)
cout <<
" the closest track to ECAL " << thisEcal <<
" is " << sortedTracks.begin()->second <<
" which is not the one being processed. Will skip ECAL linking for this track" << endl;
1246 (*pfCandidates_)[tmpi[0]].setEcalEnergy( 0., 0. );
1247 (*pfCandidates_)[tmpi[0]].setHcalEnergy( 0., 0. );
1248 (*pfCandidates_)[tmpi[0]].setHoEnergy( 0., 0. );
1249 (*pfCandidates_)[tmpi[0]].setPs1Energy( 0 );
1250 (*pfCandidates_)[tmpi[0]].setPs2Energy( 0 );
1251 (*pfCandidates_)[tmpi[0]].addElementInBlock( blockref, kTrack[0] );
1254 if (
debug_)
cout <<
" the closest track to ECAL " << thisEcal <<
" is " << sortedTracks.begin()->second <<
" which is the one being processed. Will skip ECAL linking for all other track" << endl;
1255 sortedTracks.clear();
1259 for(
auto const& trk : sortedTracks) {
1260 unsigned jTrack = trk.second;
1263 if ( !active[jTrack] )
continue;
1266 if ( jTrack == iTrack )
continue;
1274 std::multimap<double, unsigned> sortedECAL;
1275 block.associatedElements( jTrack, linkData,
1279 if ( sortedECAL.begin()->second != thisEcal )
continue;
1284 cout <<
" found track " << jTrack << (thatIsAMuon ?
" (muon) " :
" (non-muon)") <<
", with distance = " << sortedECAL.begin()->first << std::endl;
1289 bool rejectFake =
false;
1291 if ( !thatIsAMuon && trackRef->ptError() >
ptError_) {
1294 double deficit = trackMomentum + trackRef->p() - clusterRef->energy();
1296 clusterRef->positionREP().Eta());
1297 resol *= (trackMomentum+trackRef->p());
1298 if ( deficit >
nSigmaTRACK_*resol && !goodTrackDeadHcal) {
1300 kTrack.push_back(jTrack);
1301 active[jTrack] =
false;
1303 std::cout << elements[jTrack] << std::endl
1304 <<
"is probably a fake (2) --> lock the track" 1305 <<
"(trackMomentum = " << trackMomentum <<
", clusterEnergy = " << clusterRef->energy() <<
1306 ", deficit = " << deficit <<
" > " <<
nSigmaTRACK_ <<
" x " << resol <<
1307 " assuming neutralHadronEnergyResolution " <<
neutralHadronEnergyResolution(trackMomentum+trackRef->p(), clusterRef->positionREP().Eta()) <<
") " 1311 if ( rejectFake )
continue;
1317 if ( !thatIsAMuon ) {
1319 std::cout <<
"Track momentum increased from " << trackMomentum <<
" GeV ";
1320 trackMomentum += trackRef->p();
1322 std::cout <<
"to " << trackMomentum <<
" GeV." << std::endl;
1323 std::cout <<
"with " << elements[jTrack] << std::endl;
1327 totalEcal =
std::max(totalEcal, 0.);
1335 kTrack.push_back(jTrack);
1336 active[jTrack] =
false;
1338 if ( thatIsAMuon ) {
1339 (*pfCandidates_)[tmpi.back()].setEcalEnergy(clusterRef->energy(),
1341 (*pfCandidates_)[tmpi.back()].setHcalEnergy( 0., 0. );
1342 (*pfCandidates_)[tmpi.back()].setHoEnergy( 0., 0. );
1343 (*pfCandidates_)[tmpi.back()].setPs1Energy( 0 );
1344 (*pfCandidates_)[tmpi.back()].setPs2Energy( 0 );
1345 (*pfCandidates_)[tmpi.back()].addElementInBlock( blockref, kTrack.back() );
1350 if (
debug_ )
std::cout <<
"Loop over all associated ECAL clusters" << std::endl;
1352 for(
auto const&
ecal : ecalElems)
1360 if (
debug_ && ! active[index] )
std::cout <<
"is not active - ignore " << std::endl;
1361 if ( ! active[index] )
continue;
1364 block.associatedElements( index, linkData, sortedTracks,
1367 const bool skip = std::none_of(kTrack.begin(), kTrack.end(), [&](
unsigned iTrack){
1368 return sortedTracks.begin()->second == iTrack;
1371 if (
debug_ && skip )
std::cout <<
"is closer to another track - ignore " << std::endl;
1372 if ( skip )
continue;
1376 assert( !clusterRef.
isNull() );
1379 std::cout <<
"Ecal cluster with raw energy = " << clusterRef->energy()
1380 <<
" linked with distance = " <<
ecal.first << std::endl;
1393 vector<double> ps1Ene{0.};
1395 vector<double> ps2Ene{0.};
1399 const double ecalEnergy = clusterRef->energy();
1400 const double ecalEnergyCalibrated = clusterRef->correctedEnergy();
1401 if (
debug_ )
std::cout <<
"Corrected ECAL(+PS) energy = " << ecalEnergy << std::endl;
1405 totalEcal += ecalEnergy;
1406 const double previousCalibEcal = calibEcal;
1407 const double previousSlopeEcal = slopeEcal;
1408 calibEcal =
std::max(totalEcal,0.);
1410 calibration_->energyEmHad( trackMomentum,calibEcal,calibHcal,
1411 clusterRef->positionREP().Eta(),
1412 clusterRef->positionREP().Phi() );
1413 if ( totalEcal > 0.) slopeEcal = calibEcal/totalEcal;
1416 std::cout <<
"The total calibrated energy so far amounts to = " << calibEcal <<
" (slope = " << slopeEcal <<
")" << std::endl;
1420 if ( connectedToEcal && calibEcal - trackMomentum >= 0. ) {
1423 calibEcal = previousCalibEcal;
1424 slopeEcal = previousSlopeEcal;
1425 totalEcal = calibEcal/slopeEcal;
1429 active[
index] =
false;
1432 std::multimap<double, unsigned> assTracks;
1433 block.associatedElements( index, linkData,
1438 auto& ecalCand = (*pfCandidates_)[
reconstructCluster( *clusterRef, ecalEnergyCalibrated )];
1439 ecalCand.setEcalEnergy( clusterRef->energy(), ecalEnergyCalibrated );
1440 ecalCand.setHcalEnergy( 0., 0. );
1441 ecalCand.setHoEnergy( 0., 0. );
1442 ecalCand.setPs1Energy( ps1Ene[0] );
1443 ecalCand.setPs2Energy( ps2Ene[0] );
1444 ecalCand.addElementInBlock( blockref, index );
1446 if(!assTracks.empty()) {
1447 ecalCand.addElementInBlock( blockref, assTracks.begin()->second );
1458 connectedToEcal =
true;
1460 active[
index] =
false;
1461 for (
unsigned ic : tmpi) (*pfCandidates_)[ic].addElementInBlock( blockref, iEcal );
1465 bool bNeutralProduced =
false;
1468 if( connectedToEcal ) {
1510 neutralEnergy /= slopeEcal;
1512 (*pfCandidates_)[tmpj].setEcalEnergy( pivotalRef->energy(), neutralEnergy );
1513 (*pfCandidates_)[tmpj].setHcalEnergy( 0., 0. );
1514 (*pfCandidates_)[tmpj].setHoEnergy( 0., 0. );
1515 (*pfCandidates_)[tmpj].setPs1Energy( 0. );
1516 (*pfCandidates_)[tmpj].setPs2Energy( 0. );
1517 (*pfCandidates_)[tmpj].addElementInBlock(blockref, iEcal);
1518 bNeutralProduced =
true;
1519 for (
unsigned ic=0; ic<kTrack.size();++ic)
1520 (*
pfCandidates_)[tmpj].addElementInBlock( blockref, kTrack[ic] );
1524 for (
unsigned ic=0; ic<tmpi.size();++ic) {
1529 double fraction = trackMomentum > 0 ? (*pfCandidates_)[tmpi[ic]].trackRef()->p()/trackMomentum : 0;
1530 double ecalCal = bNeutralProduced ?
1531 (calibEcal-neutralEnergy*slopeEcal)*fraction : calibEcal*fraction;
1532 double ecalRaw = totalEcal*
fraction;
1534 if (
debug_)
cout <<
"The fraction after photon supression is " << fraction <<
" calibrated ecal = " << ecalCal << endl;
1536 (*pfCandidates_)[tmpi[ic]].setEcalEnergy( ecalRaw, ecalCal );
1537 (*pfCandidates_)[tmpi[ic]].setHcalEnergy( 0., 0. );
1538 (*pfCandidates_)[tmpi[ic]].setHoEnergy( 0., 0. );
1539 (*pfCandidates_)[tmpi[ic]].setPs1Energy( 0 );
1540 (*pfCandidates_)[tmpi[ic]].setPs2Energy( 0 );
1541 (*pfCandidates_)[tmpi[ic]].addElementInBlock( blockref, kTrack[ic] );
1547 for (
unsigned ic=0; ic<tmpi.size();++ic) {
1548 const PFCandidate& pfc = (*pfCandidates_)[tmpi[ic]];
1550 if ( eleInBlocks.empty() ) {
1551 if (
debug_ )
std::cout <<
"Single track / Fill element in block! " << std::endl;
1552 (*pfCandidates_)[tmpi[ic]].addElementInBlock( blockref, kTrack[ic] );
1561 for(
auto const&
hcal : hcalElems) {
1569 cout<<
"\telement "<<elements[
index]<<
" linked with distance "<< dist <<endl;
1578 cout<<
"\t\tclosest hcal cluster, doing nothing"<<endl;
1588 cout<<
"\t\tsecondary hcal cluster. unlinking"<<endl;
1589 block.setLink( iTrack, index, -1., linkData,
1590 PFBlock::LINKTEST_RECHIT );
1598 if( !(hfEmIs.empty() && hfHadIs.empty() ) ) {
1601 assert( hfEmIs.size() + hfHadIs.size() == elements.
size() );
1603 if( elements.
size() == 1 ) {
1606 double energyHF = 0.;
1607 double uncalibratedenergyHF = 0.;
1609 switch( clusterRef->layer() ) {
1612 energyHF = clusterRef->energy();
1613 uncalibratedenergyHF = energyHF;
1616 clusterRef->positionREP().Eta(),
1617 clusterRef->positionREP().Phi());
1620 (*pfCandidates_)[tmpi].setEcalEnergy( uncalibratedenergyHF, energyHF );
1621 (*pfCandidates_)[tmpi].setHcalEnergy( 0., 0.);
1622 (*pfCandidates_)[tmpi].setHoEnergy( 0., 0.);
1623 (*pfCandidates_)[tmpi].setPs1Energy( 0. );
1624 (*pfCandidates_)[tmpi].setPs2Energy( 0. );
1625 (*pfCandidates_)[tmpi].addElementInBlock( blockref, hfEmIs[0] );
1630 energyHF = clusterRef->energy();
1631 uncalibratedenergyHF = energyHF;
1634 clusterRef->positionREP().Eta(),
1635 clusterRef->positionREP().Phi());
1638 (*pfCandidates_)[tmpi].setHcalEnergy( uncalibratedenergyHF, energyHF );
1639 (*pfCandidates_)[tmpi].setEcalEnergy( 0., 0.);
1640 (*pfCandidates_)[tmpi].setHoEnergy( 0., 0.);
1641 (*pfCandidates_)[tmpi].setPs1Energy( 0. );
1642 (*pfCandidates_)[tmpi].setPs2Energy( 0. );
1643 (*pfCandidates_)[tmpi].addElementInBlock( blockref, hfHadIs[0] );
1650 else if( elements.
size() == 2 ) {
1659 cerr<<
"Error: 2 elements, but not 1 HFEM and 1 HFHAD"<<endl;
1666 double energyHfEm = cem->energy();
1667 double energyHfHad = chad->energy();
1668 double uncalibratedenergyHFEm = energyHfEm;
1669 double uncalibratedenergyHFHad = energyHfHad;
1674 c0->positionREP().Eta(),
1675 c0->positionREP().Phi());
1677 uncalibratedenergyHFHad,
1678 c1->positionREP().Eta(),
1679 c1->positionREP().Phi());
1682 cand.setEcalEnergy( uncalibratedenergyHFEm, energyHfEm );
1683 cand.setHcalEnergy( uncalibratedenergyHFHad, energyHfHad);
1684 cand.setHoEnergy( 0., 0.);
1685 cand.setPs1Energy( 0. );
1686 cand.setPs2Energy( 0. );
1687 cand.addElementInBlock( blockref, hfEmIs[0] );
1688 cand.addElementInBlock( blockref, hfHadIs[0] );
1694 cerr<<
"Warning: HF, but n elem different from 1 or 2"<<endl;
1705 cout<<endl<<
"--------------- loop hcal ---------------------"<<endl;
1714 for(
unsigned iHcal : hcalIs) {
1719 if(
debug_)
cout<<endl<<elements[iHcal]<<endl;
1725 std::multimap<double, unsigned> sortedTracks;
1726 block.associatedElements( iHcal, linkData,
1731 std::multimap< unsigned, std::pair<double, unsigned> > associatedEcals;
1733 std::map< unsigned, std::pair<double, double> > associatedPSs;
1735 std::multimap<double, std::pair<unsigned,bool> > associatedTracks;
1738 std::multimap<double,std::tuple<unsigned,::math::XYZVector,double> > ecalSatellites;
1739 std::tuple<unsigned,::math::XYZVector,double> fakeSatellite(iHcal,::
math::XYZVector(0.,0.,0.),1.);
1740 ecalSatellites.emplace(-1., fakeSatellite);
1742 std::multimap< unsigned, std::pair<double, unsigned> > associatedHOs;
1744 PFClusterRef hclusterref = elements[iHcal].clusterRef();
1745 assert(!hclusterref.
isNull() );
1755 if( sortedTracks.empty() ) {
1757 cout<<
"\tno associated tracks, keep for later"<<endl;
1762 active[iHcal] =
false;
1770 if(
debug_)
cout<<
"\t"<<sortedTracks.size()<<
" associated tracks:"<<endl;
1772 double totalChargedMomentum = 0;
1773 double sumpError2 = 0.;
1774 double totalHO = 0.;
1775 double totalEcal = 0.;
1776 double totalEcalEGMCalib = 0.;
1777 double totalHcal = hclusterref->energy();
1778 vector<double> hcalP;
1779 vector<double> hcalDP;
1780 vector<unsigned> tkIs;
1781 double maxDPovP = -9999.;
1784 vector< unsigned > chargedHadronsIndices;
1785 vector< unsigned > chargedHadronsInBlock;
1786 double mergedNeutralHadronEnergy = 0;
1787 double mergedPhotonEnergy = 0;
1788 double muonHCALEnergy = 0.;
1789 double muonECALEnergy = 0.;
1790 double muonHCALError = 0.;
1791 double muonECALError = 0.;
1796 std::vector<std::tuple<unsigned,::math::XYZVector,double> >
ecalClusters;
1797 double sumEcalClusters=0;
1799 hclusterref->position().Y(),
1800 hclusterref->position().Z());
1801 hadronDirection = hadronDirection.Unit();
1805 for(
auto const& trk : sortedTracks) {
1807 unsigned iTrack = trk.second;
1810 if ( !active[iTrack] )
continue;
1816 assert( !trackRef.
isNull() );
1821 ::math::XYZVector chargedDirection(chargedPosition.X(),chargedPosition.Y(),chargedPosition.Z());
1822 chargedDirection = chargedDirection.Unit();
1825 std::multimap<double, unsigned> sortedEcals;
1826 block.associatedElements( iTrack, linkData,
1831 if(
debug_)
cout<<
"\t\t\tnumber of Ecal elements linked to this track: " 1832 <<sortedEcals.size()<<endl;
1835 std::multimap<double, unsigned> sortedHOs;
1837 block.associatedElements( iTrack, linkData,
1844 cout<<
"PFAlgo : number of HO elements linked to this track: " 1845 <<sortedHOs.size()<<endl;
1853 bool thisIsALooseMuon =
false;
1861 if ( thisIsAMuon ) {
1863 std::cout <<
"\t\tThis track is identified as a muon - remove it from the stack" << std::endl;
1864 std::cout <<
"\t\t" << elements[iTrack] << std::endl;
1872 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iTrack );
1873 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHcal );
1879 bool letMuonEatCaloEnergy =
false;
1881 if(thisIsAnIsolatedMuon){
1883 double totalCaloEnergy = totalHcal / 1.30;
1885 if( !sortedEcals.empty() ) {
1886 iEcal = sortedEcals.begin()->second;
1887 PFClusterRef eclusterref = elements[iEcal].clusterRef();
1888 totalCaloEnergy += eclusterref->energy();
1894 if( !sortedHOs.empty() ) {
1895 iHO = sortedHOs.begin()->second;
1897 totalCaloEnergy += eclusterref->energy() / 1.30;
1903 if( (
pfCandidates_->back()).
p() > totalCaloEnergy ) letMuonEatCaloEnergy =
true;
1906 if(letMuonEatCaloEnergy) muonHcal = totalHcal;
1907 double muonEcal =0.;
1909 if( !sortedEcals.empty() ) {
1910 iEcal = sortedEcals.begin()->second;
1911 PFClusterRef eclusterref = elements[iEcal].clusterRef();
1912 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEcal);
1914 if(letMuonEatCaloEnergy) muonEcal = eclusterref->energy();
1916 if ( eclusterref->energy() - muonEcal < 0.2 ) active[iEcal] =
false;
1917 (*pfCandidates_)[tmpi].setEcalEnergy(eclusterref->energy(), muonEcal);
1922 if( !sortedHOs.empty() ) {
1923 iHO = sortedHOs.begin()->second;
1924 PFClusterRef hoclusterref = elements[iHO].clusterRef();
1925 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHO);
1927 if(letMuonEatCaloEnergy) muonHO = hoclusterref->energy();
1929 if ( hoclusterref->energy() - muonHO < 0.2 ) active[iHO] =
false;
1930 (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal, muonHcal);
1931 (*pfCandidates_)[tmpi].setHoEnergy(hoclusterref->energy(), muonHO);
1934 (*pfCandidates_)[tmpi].setHcalEnergy(totalHcal, muonHcal);
1938 if(letMuonEatCaloEnergy){
1939 muonHCALEnergy += totalHcal;
1940 if (
useHO_) muonHCALEnergy +=muonHO;
1941 muonHCALError += 0.;
1942 muonECALEnergy += muonEcal;
1943 muonECALError += 0.;
1944 photonAtECAL -= muonEcal*chargedDirection;
1945 hadronAtECAL -= totalHcal*chargedDirection;
1946 if ( !sortedEcals.empty() ) active[iEcal] =
false;
1947 active[iHcal] =
false;
1948 if (
useHO_ && !sortedHOs.empty() ) active[iHO] =
false;
1954 if ( muonHO > 0. ) {
1961 photonAtECAL -= muonECAL_[0]*chargedDirection;
1962 hadronAtECAL -= muonHCAL_[0]*chargedDirection;
1966 active[iTrack] =
false;
1973 if(
debug_)
cout<<
"\t\t"<<elements[iTrack]<<endl;
1981 if ( thisIsALooseMuon && !thisIsAMuon ) nMuons += 1;
1986 double Dpt = trackRef->ptError();
1989 bool isPrimaryOrSecondary =
isFromSecInt(elements[iTrack],
"all");
1991 if ( isPrimaryOrSecondary ) blowError = 1.;
1993 std::pair<unsigned,bool> tkmuon(iTrack,thisIsALooseMuon);
1994 associatedTracks.emplace(-Dpt*blowError, tkmuon);
1997 double Dp = trackRef->qoverpError()*trackMomentum*
trackMomentum;
1998 sumpError2 += Dp*Dp;
2000 bool connectedToEcal =
false;
2001 if( !sortedEcals.empty() )
2005 for (
auto const&
ecal : sortedEcals) {
2007 unsigned iEcal =
ecal.second;
2008 double dist =
ecal.first;
2011 if( !active[iEcal] ) {
2019 PFClusterRef eclusterref = elements[iEcal].clusterRef();
2020 assert(!eclusterref.
isNull() );
2023 std::multimap<double, unsigned> sortedTracksEcal;
2024 block.associatedElements( iEcal, linkData,
2028 unsigned jTrack = sortedTracksEcal.
begin()->second;
2029 if ( jTrack != iTrack )
continue;
2033 double distEcal = block.dist(jTrack,iEcal,linkData,
2040 float ecalEnergyCalibrated = eclusterref->correctedEnergy();
2041 float ecalEnergy = eclusterref->energy();
2043 eclusterref->position().Y(),
2044 eclusterref->position().Z());
2045 photonDirection = photonDirection.Unit();
2047 if ( !connectedToEcal ) {
2050 <<elements[iEcal]<<endl;
2052 connectedToEcal =
true;
2057 double ecalCalibFactor = (ecalEnergy>1E-9) ? ecalEnergyCalibrated/ecalEnergy : 1.;
2058 std::tuple<unsigned,::math::XYZVector,double> satellite(iEcal,ecalEnergy*photonDirection,ecalCalibFactor);
2059 ecalSatellites.emplace(-1., satellite);
2064 double ecalCalibFactor = (ecalEnergy>1E-9) ? ecalEnergyCalibrated/ecalEnergy : 1.;
2065 std::tuple<unsigned,::math::XYZVector,double> satellite(iEcal,ecalEnergy*photonDirection,ecalCalibFactor);
2066 ecalSatellites.emplace(dist, satellite);
2070 std::pair<double, unsigned> associatedEcal( distEcal, iEcal );
2071 associatedEcals.emplace(iTrack, associatedEcal);
2076 if(
useHO_ && !sortedHOs.empty() )
2080 for (
auto const&
ho : sortedHOs) {
2082 unsigned iHO =
ho.second;
2083 double distHO =
ho.first;
2086 if( !active[iHO] ) {
2094 PFClusterRef hoclusterref = elements[iHO].clusterRef();
2095 assert(!hoclusterref.
isNull() );
2098 std::multimap<double, unsigned> sortedTracksHO;
2099 block.associatedElements( iHO, linkData,
2103 unsigned jTrack = sortedTracksHO.
begin()->second;
2104 if ( jTrack != iTrack )
continue;
2112 totalHO += hoclusterref->energy();
2113 active[iHO] =
false;
2115 std::pair<double, unsigned> associatedHO( distHO, iHO );
2116 associatedHOs.emplace(iTrack, associatedHO);
2125 totalHcal += totalHO;
2129 double caloEnergy = 0.;
2130 double slopeEcal = 1.0;
2131 double calibEcal = 0.;
2132 double calibHcal = 0.;
2133 hadronDirection = hadronAtECAL.Unit();
2137 Caloresolution *= totalChargedMomentum;
2139 Caloresolution =
std::sqrt(Caloresolution*Caloresolution + muonHCALError + muonECALError);
2140 totalEcal -=
std::min(totalEcal,muonECALEnergy);
2141 totalEcalEGMCalib -=
std::min(totalEcalEGMCalib,muonECALEnergy);
2142 totalHcal -=
std::min(totalHcal,muonHCALEnergy);
2150 for(
auto const& ecalSatellite : ecalSatellites) {
2153 double previousCalibEcal = calibEcal;
2154 double previousCalibHcal = calibHcal;
2155 double previousCaloEnergy = caloEnergy;
2156 double previousSlopeEcal = slopeEcal;
2159 totalEcal +=
sqrt(std::get<1>(ecalSatellite.second).Mag2());
2160 totalEcalEGMCalib +=
sqrt(std::get<1>(ecalSatellite.second).Mag2())*std::get<2>(ecalSatellite.second);
2161 photonAtECAL += std::get<1>(ecalSatellite.second)*std::get<2>(ecalSatellite.second);
2162 calibEcal =
std::max(0.,totalEcal);
2163 calibHcal =
std::max(0.,totalHcal);
2164 hadronAtECAL = calibHcal * hadronDirection;
2166 calibration_->energyEmHad( totalChargedMomentum,calibEcal,calibHcal,
2167 hclusterref->positionREP().Eta(),
2168 hclusterref->positionREP().Phi() );
2169 caloEnergy = calibEcal+calibHcal;
2170 if ( totalEcal > 0.) slopeEcal = calibEcal/totalEcal;
2172 hadronAtECAL = calibHcal * hadronDirection;
2176 if ( ecalSatellite.first < 0. || caloEnergy - totalChargedMomentum <= 0. ) {
2177 if(
debug_)
cout<<
"\t\t\tactive, adding "<<std::get<1>(ecalSatellite.second)
2178 <<
" to ECAL energy, and locking"<<endl;
2179 active[std::get<0>(ecalSatellite.second)] =
false;
2180 double clusterEnergy=
sqrt(std::get<1>(ecalSatellite.second).Mag2())*std::get<2>(ecalSatellite.second);
2181 if(clusterEnergy>50) {
2182 ecalClusters.push_back(ecalSatellite.second);
2183 sumEcalClusters+=clusterEnergy;
2190 totalEcal -=
sqrt(std::get<1>(ecalSatellite.second).Mag2());
2191 totalEcalEGMCalib -=
sqrt(std::get<1>(ecalSatellite.second).Mag2())*std::get<2>(ecalSatellite.second);
2192 photonAtECAL -= std::get<1>(ecalSatellite.second)*std::get<2>(ecalSatellite.second);
2193 calibEcal = previousCalibEcal;
2194 calibHcal = previousCalibHcal;
2195 hadronAtECAL = previousHadronAtECAL;
2196 slopeEcal = previousSlopeEcal;
2197 caloEnergy = previousCaloEnergy;
2204 assert(caloEnergy>=0);
2219 if ( totalChargedMomentum - caloEnergy >
nSigmaTRACK_*Caloresolution ) {
2234 for(
auto const& trk : associatedTracks) {
2237 if ( !trk.second.second )
continue;
2239 const unsigned int iTrack = trk.second.first;
2241 if ( !active[iTrack] )
continue;
2243 const double trackMomentum = elements[trk.second.first].trackRef()->p();
2246 std::multimap<double, unsigned> sortedEcals;
2247 block.associatedElements( iTrack, linkData,
2251 std::multimap<double, unsigned> sortedHOs;
2252 block.associatedElements( iTrack, linkData,
2260 muon.addElementInBlock( blockref, iTrack );
2261 muon.addElementInBlock( blockref, iHcal );
2264 muon.setHcalEnergy(totalHcal,muonHcal);
2265 if( !sortedEcals.empty() ) {
2266 const unsigned int iEcal = sortedEcals.begin()->second;
2267 PFClusterRef eclusterref = elements[iEcal].clusterRef();
2268 muon.addElementInBlock( blockref, iEcal);
2270 muon.setEcalEnergy(eclusterref->energy(),muonEcal);
2272 if(
useHO_ && !sortedHOs.empty() ) {
2273 const unsigned int iHO = sortedHOs.begin()->second;
2274 PFClusterRef hoclusterref = elements[iHO].clusterRef();
2275 muon.addElementInBlock( blockref, iHO);
2277 muon.setHcalEnergy(
max(totalHcal-totalHO,0.0),muonHcal);
2278 muon.setHoEnergy(hoclusterref->energy(),muonHO);
2284 ::math::XYZVector chargedDirection(chargedPosition.X(), chargedPosition.Y(), chargedPosition.Z());
2285 chargedDirection = chargedDirection.Unit();
2288 if ( totalEcal > 0. ) calibEcal -=
std::min(calibEcal,
muonECAL_[0]*calibEcal/totalEcal);
2289 if ( totalHcal > 0. ) calibHcal -=
std::min(calibHcal,
muonHCAL_[0]*calibHcal/totalHcal);
2293 if ( totalHcal >
muonHCAL_[0] ) hadronAtECAL -=
muonHCAL_[0]*calibHcal/totalHcal * chargedDirection;
2294 caloEnergy = calibEcal + calibHcal;
2297 if ( muonHO > 0. ) {
2300 if ( totalHcal > 0. ) {
2301 calibHcal -=
std::min(calibHcal,muonHO_[0] * calibHcal/totalHcal);
2302 totalHcal -=
std::min(totalHcal,muonHO_[0]);
2307 active[iTrack] =
false;
2314 Caloresolution *= totalChargedMomentum;
2315 Caloresolution =
std::sqrt(Caloresolution*Caloresolution + muonHCALError + muonECALError);
2320 cout<<
"\tBefore Cleaning "<<endl;
2321 cout<<
"\tCompare Calo Energy to total charged momentum "<<endl;
2322 cout<<
"\t\tsum p = "<<totalChargedMomentum<<
" +- "<<
sqrt(sumpError2)<<endl;
2323 cout<<
"\t\tsum ecal = "<<totalEcal<<endl;
2324 cout<<
"\t\tsum hcal = "<<totalHcal<<endl;
2325 cout<<
"\t\t => Calo Energy = "<<caloEnergy<<
" +- "<<Caloresolution<<endl;
2326 cout<<
"\t\t => Calo Energy- total charged momentum = " 2327 <<caloEnergy-totalChargedMomentum<<
" +- "<<
sqrt(sumpError2 + Caloresolution*Caloresolution)<<endl;
2333 unsigned corrTrack = 10000000;
2334 double corrFact = 1.;
2338 for(
auto const& trk : associatedTracks)
2340 const unsigned iTrack = trk.second.first;
2342 if ( !active[iTrack] )
continue;
2343 const reco::TrackRef& trackref = elements[trk.second.first].trackRef();
2345 const double dptRel = fabs(trk.first)/trackref->pt()*100;
2346 const bool isSecondary =
isFromSecInt(elements[iTrack],
"secondary");
2347 const bool isPrimary =
isFromSecInt(elements[iTrack],
"primary");
2351 if ( fabs(trk.first) <
ptError_ )
break;
2353 const double wouldBeTotalChargedMomentum = totalChargedMomentum - trackref->p();
2357 if ( wouldBeTotalChargedMomentum > caloEnergy ) {
2358 if (
debug_ && isSecondary) {
2359 cout <<
"In bad track rejection step dptRel = " << dptRel <<
" dptRel_DispVtx_ = " <<
dptRel_DispVtx_ << endl;
2360 cout <<
"The calo energy would be still smaller even without this track but it is attached to a NI"<< endl;
2364 active[iTrack] =
false;
2365 totalChargedMomentum = wouldBeTotalChargedMomentum;
2367 std::cout <<
"\tElement " << elements[iTrack]
2368 <<
" rejected (Dpt = " << -trk.first
2369 <<
" GeV/c, algo = " << trackref->algo() <<
")" << std::endl;
2372 if(isPrimary)
break;
2374 corrFact = (caloEnergy - wouldBeTotalChargedMomentum)/elements[trk.second.first].trackRef()->p();
2375 if ( trackref->p()*corrFact < 0.05 ) {
2377 active[iTrack] =
false;
2379 totalChargedMomentum -= trackref->p()*(1.-corrFact);
2381 std::cout <<
"\tElement " << elements[iTrack]
2382 <<
" (Dpt = " << -trk.first
2383 <<
" GeV/c, algo = " << trackref->algo()
2384 <<
") rescaled by " << corrFact
2385 <<
" Now the total charged momentum is " << totalChargedMomentum << endl;
2393 Caloresolution *= totalChargedMomentum;
2394 Caloresolution =
std::sqrt(Caloresolution*Caloresolution + muonHCALError + muonECALError);
2400 sortedTracks.size() > 1 &&
2401 totalChargedMomentum - caloEnergy >
nSigmaTRACK_*Caloresolution ) {
2402 for(
auto const& trk : associatedTracks) {
2403 unsigned iTrack = trk.second.first;
2405 if ( !active[iTrack] )
continue;
2407 double dptRel = fabs(trk.first)/trackref->pt()*100;
2408 bool isPrimaryOrSecondary =
isFromSecInt(elements[iTrack],
"all");
2416 active[iTrack] =
false;
2417 totalChargedMomentum -= trackref->p();
2420 std::cout <<
"\tElement " << elements[iTrack]
2421 <<
" rejected (Dpt = " << -trk.first
2422 <<
" GeV/c, algo = " << trackref->algo() <<
")" << std::endl;
2431 Caloresolution *= totalChargedMomentum;
2432 Caloresolution =
std::sqrt(Caloresolution*Caloresolution + muonHCALError + muonECALError);
2436 for(
auto const& trk : associatedTracks) {
2437 unsigned iTrack = trk.second.first;
2438 if ( !active[iTrack] )
continue;
2441 double Dp = trackRef->qoverpError()*trackMomentum*
trackMomentum;
2445 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iTrack );
2446 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHcal );
2448 auto myEcals = associatedEcals.equal_range(iTrack);
2449 for (
auto ii=myEcals.first;
ii!=myEcals.second; ++
ii ) {
2450 unsigned iEcal =
ii->second.second;
2451 if ( active[iEcal] )
continue;
2452 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iEcal );
2456 auto myHOs = associatedHOs.equal_range(iTrack);
2457 for (
auto ii=myHOs.first;
ii!=myHOs.second; ++
ii ) {
2458 unsigned iHO =
ii->second.second;
2459 if ( active[iHO] )
continue;
2460 (*pfCandidates_)[tmpi].addElementInBlock( blockref, iHO );
2464 if ( iTrack == corrTrack ) {
2465 (*pfCandidates_)[tmpi].rescaleMomentum(corrFact);
2466 trackMomentum *= corrFact;
2468 chargedHadronsIndices.push_back( tmpi );
2469 chargedHadronsInBlock.push_back( iTrack );
2470 active[iTrack] =
false;
2471 hcalP.push_back(trackMomentum);
2472 hcalDP.push_back(Dp);
2473 if (Dp/trackMomentum > maxDPovP) maxDPovP = Dp/
trackMomentum;
2474 sumpError2 += Dp*Dp;
2478 double TotalError =
sqrt(sumpError2 + Caloresolution*Caloresolution);
2481 cout<<
"\tCompare Calo Energy to total charged momentum "<<endl;
2482 cout<<
"\t\tsum p = "<<totalChargedMomentum<<
" +- "<<
sqrt(sumpError2)<<endl;
2483 cout<<
"\t\tsum ecal = "<<totalEcal<<endl;
2484 cout<<
"\t\tsum hcal = "<<totalHcal<<endl;
2485 cout<<
"\t\t => Calo Energy = "<<caloEnergy<<
" +- "<<Caloresolution<<endl;
2486 cout<<
"\t\t => Calo Energy- total charged momentum = " 2487 <<caloEnergy-totalChargedMomentum<<
" +- "<<TotalError<<endl;
2494 double nsigma =
nSigmaHCAL(totalChargedMomentum,hclusterref->positionREP().Eta());
2496 if (
abs(totalChargedMomentum-caloEnergy)<nsigma*TotalError ) {
2502 cout<<
"\t\tcase 1: COMPATIBLE " 2503 <<
"|Calo Energy- total charged momentum| = " 2504 <<
abs(caloEnergy-totalChargedMomentum)
2505 <<
" < "<<nsigma<<
" x "<<TotalError<<endl;
2506 if (maxDPovP < 0.1 )
2507 cout<<
"\t\t\tmax DP/P = "<< maxDPovP
2508 <<
" less than 0.1: do nothing "<<endl;
2510 cout<<
"\t\t\tmax DP/P = "<< maxDPovP
2511 <<
" > 0.1: take weighted averages "<<endl;
2515 if (maxDPovP > 0.1) {
2519 int nrows = chargedHadronsIndices.size();
2520 TMatrixTSym<double>
a (nrows);
2522 TVectorD
check(nrows);
2523 double sigma2E = Caloresolution*Caloresolution;
2524 for(
int i=0;
i<nrows;
i++) {
2525 double sigma2i = hcalDP[
i]*hcalDP[
i];
2527 cout<<
"\t\t\ttrack associated to hcal "<<
i 2528 <<
" P = "<<hcalP[
i]<<
" +- " 2531 a(
i,
i) = 1./sigma2i + 1./sigma2E;
2532 b(
i) = hcalP[
i]/sigma2i + caloEnergy/sigma2E;
2533 for(
int j=0; j<nrows; j++) {
2535 a(
i,j) = 1./sigma2E;
2546 TDecompChol decomp(a);
2548 TVectorD
x = decomp.Solve(b, ok);
2552 for (
int i=0;
i<nrows;
i++){
2554 unsigned ich = chargedHadronsIndices[
i];
2555 double rescaleFactor =
x(
i)/hcalP[
i];
2556 (*pfCandidates_)[ich].rescaleMomentum( rescaleFactor );
2559 cout<<
"\t\t\told p "<<hcalP[
i]
2561 <<
" rescale "<<rescaleFactor<<endl;
2566 cerr<<
"not ok!"<<endl;
2573 else if( caloEnergy > totalChargedMomentum ) {
2592 double eNeutralHadron = caloEnergy - totalChargedMomentum;
2593 double ePhoton = (caloEnergy - totalChargedMomentum) / slopeEcal;
2598 if(!sortedTracks.empty() ){
2599 cout<<
"\t\tcase 2: NEUTRAL DETECTION " 2600 <<caloEnergy<<
" > "<<nsigma<<
"x"<<TotalError
2601 <<
" + "<<totalChargedMomentum<<endl;
2602 cout<<
"\t\tneutral activity detected: "<<endl
2603 <<
"\t\t\t photon = "<<ePhoton<<endl
2604 <<
"\t\t\tor neutral hadron = "<<eNeutralHadron<<endl;
2606 cout<<
"\t\tphoton or hadron ?"<<endl;}
2608 if(sortedTracks.empty() )
2609 cout<<
"\t\tno track -> hadron "<<endl;
2611 cout<<
"\t\t"<<sortedTracks.size()
2612 <<
" tracks -> check if the excess is photonic or hadronic"<<endl;
2616 double ratioMax = 0.;
2618 unsigned maxiEcal= 9999;
2622 for(
auto const& trk : sortedTracks) {
2624 unsigned iTrack = trk.second;
2630 assert( !trackRef.
isNull() );
2632 auto iae = associatedEcals.find(iTrack);
2634 if( iae == associatedEcals.end() )
continue;
2637 unsigned iEcal = iae->second.second;
2643 assert( !clusterRef.
isNull() );
2645 double pTrack = trackRef->p();
2646 double eECAL = clusterRef->energy();
2647 double eECALOverpTrack = eECAL / pTrack;
2649 if ( eECALOverpTrack > ratioMax ) {
2650 ratioMax = eECALOverpTrack;
2651 maxEcalRef = clusterRef;
2657 std::vector<reco::PFClusterRef> pivotalClusterRef;
2658 std::vector<unsigned> iPivotal;
2659 std::vector<double> particleEnergy, ecalEnergy, hcalEnergy, rawecalEnergy, rawhcalEnergy;
2660 std::vector<::math::XYZVector> particleDirection;
2664 if ( ePhoton < totalEcal || eNeutralHadron-calibEcal < 1E-10 ) {
2665 if ( !maxEcalRef.
isNull() ) {
2667 mergedPhotonEnergy = ePhoton;
2671 if ( !maxEcalRef.
isNull() ) {
2673 mergedPhotonEnergy = totalEcalEGMCalib;
2676 mergedNeutralHadronEnergy = eNeutralHadron-calibEcal;
2679 if ( mergedPhotonEnergy > 0 ) {
2683 if ( ecalClusters.size()<=1 ) {
2684 ecalClusters.clear();
2685 ecalClusters.emplace_back(maxiEcal, photonAtECAL, 1.);
2686 sumEcalClusters=
sqrt(photonAtECAL.Mag2());
2688 for(
auto const& pae : ecalClusters) {
2689 const double clusterEnergyCalibrated=
sqrt(std::get<1>(pae).Mag2())*std::get<2>(pae);
2690 particleEnergy.push_back(mergedPhotonEnergy*clusterEnergyCalibrated/sumEcalClusters);
2691 particleDirection.push_back(std::get<1>(pae));
2692 ecalEnergy.push_back(mergedPhotonEnergy*clusterEnergyCalibrated/sumEcalClusters);
2693 hcalEnergy.push_back(0.);
2694 rawecalEnergy.push_back(totalEcal);
2695 rawhcalEnergy.push_back(totalHcal);
2696 pivotalClusterRef.push_back(elements[std::get<0>(pae)].clusterRef());
2697 iPivotal.push_back(std::get<0>(pae));
2701 if ( mergedNeutralHadronEnergy > 1.0 ) {
2704 if ( ecalClusters.size()<=1 ) {
2705 ecalClusters.clear();
2706 ecalClusters.emplace_back(iHcal, hadronAtECAL, 1.);
2707 sumEcalClusters=
sqrt(hadronAtECAL.Mag2());
2709 for(
auto const& pae : ecalClusters) {
2710 const double clusterEnergyCalibrated=
sqrt(std::get<1>(pae).Mag2())*std::get<2>(pae);
2711 particleEnergy.push_back(mergedNeutralHadronEnergy*clusterEnergyCalibrated/sumEcalClusters);
2712 particleDirection.push_back(std::get<1>(pae));
2713 ecalEnergy.push_back(0.);
2714 hcalEnergy.push_back(mergedNeutralHadronEnergy*clusterEnergyCalibrated/sumEcalClusters);
2715 rawecalEnergy.push_back(totalEcal);
2716 rawhcalEnergy.push_back(totalHcal);
2717 pivotalClusterRef.push_back(hclusterref);
2718 iPivotal.push_back(iHcal);
2726 for (
unsigned iPivot=0; iPivot<iPivotal.size(); ++iPivot ) {
2728 if ( particleEnergy[iPivot] < 0. )
2729 std::cout <<
"ALARM = Negative energy ! " 2730 << particleEnergy[iPivot] << std::endl;
2732 const bool useDirection =
true;
2734 particleEnergy[iPivot],
2736 particleDirection[iPivot].
X(),
2737 particleDirection[iPivot].
Y(),
2738 particleDirection[iPivot].
Z() )];
2741 neutral.setEcalEnergy( rawecalEnergy[iPivot],ecalEnergy[iPivot] );
2743 neutral.setHcalEnergy( rawhcalEnergy[iPivot],hcalEnergy[iPivot] );
2744 neutral.setHoEnergy(0., 0.);
2746 neutral.setHcalEnergy(
max(rawhcalEnergy[iPivot]-totalHO,0.0),hcalEnergy[iPivot]*(1.-totalHO/rawhcalEnergy[iPivot]));
2747 neutral.setHoEnergy(totalHO, totalHO * hcalEnergy[iPivot]/rawhcalEnergy[iPivot]);
2749 neutral.setPs1Energy( 0. );
2750 neutral.setPs2Energy( 0. );
2751 neutral.set_mva_nothing_gamma( -1. );
2754 neutral.addElementInBlock( blockref, iHcal );
2755 for (
unsigned iTrack : chargedHadronsInBlock) {
2756 neutral.addElementInBlock( blockref, iTrack );
2762 auto myEcals = associatedEcals.equal_range(iTrack);
2763 for (
auto ii=myEcals.first;
ii!=myEcals.second; ++
ii ) {
2764 unsigned iEcal =
ii->second.second;
2765 if ( active[iEcal] )
continue;
2766 neutral.addElementInBlock( blockref, iEcal );
2778 double totalHcalEnergyCalibrated = calibHcal;
2779 double totalEcalEnergyCalibrated = calibEcal;
2794 totalHcalEnergyCalibrated -= mergedNeutralHadronEnergy;
2796 totalEcalEnergyCalibrated -= mergedPhotonEnergy;
2801 double chargedHadronsTotalEnergy = 0;
2802 for(
unsigned index : chargedHadronsIndices) {
2804 chargedHadronsTotalEnergy += chargedHadron.
energy();
2807 for(
unsigned index : chargedHadronsIndices) {
2809 float fraction = chargedHadron.
energy()/chargedHadronsTotalEnergy;
2812 chargedHadron.
setHcalEnergy( fraction * totalHcal, fraction * totalHcalEnergyCalibrated );
2815 chargedHadron.
setHcalEnergy( fraction *
max(totalHcal-totalHO,0.0), fraction * totalHcalEnergyCalibrated * (1.-totalHO/totalHcal) );
2816 chargedHadron.
setHoEnergy( fraction * totalHO, fraction * totalHO * totalHcalEnergyCalibrated / totalHcal );
2819 chargedHadron.
setEcalEnergy( fraction * totalEcal, fraction * totalEcalEnergyCalibrated );
2823 for(
auto const& ecalSatellite : ecalSatellites) {
2826 unsigned iEcal = std::get<0>(ecalSatellite.second);
2827 if ( !active[iEcal] )
continue;
2832 PFClusterRef eclusterref = elements[iEcal].clusterRef();
2833 assert(!eclusterref.
isNull() );
2836 active[iEcal] =
false;
2839 std::multimap<double, unsigned> assTracks;
2840 block.associatedElements( iEcal, linkData,
2846 double ecalClusterEnergyCalibrated =
sqrt(std::get<1>(ecalSatellite.second).Mag2()) * std::get<2>(ecalSatellite.second);
2848 cand.setEcalEnergy( eclusterref->energy(), ecalClusterEnergyCalibrated );
2849 cand.setHcalEnergy( 0., 0. );
2850 cand.setHoEnergy( 0., 0. );
2851 cand.setPs1Energy( associatedPSs[iEcal].
first );
2852 cand.setPs2Energy( associatedPSs[iEcal].
second );
2853 cand.addElementInBlock( blockref, iEcal );
2854 cand.addElementInBlock( blockref, sortedTracks.begin()->second) ;
2856 if ( fabs(eclusterref->energy() -
sqrt(std::get<1>(ecalSatellite.second).Mag2()))>1
e-3 || fabs(eclusterref->correctedEnergy() - ecalClusterEnergyCalibrated)>1
e-3 )
2857 edm::LogWarning(
"PFAlgo:processBlock") <<
"ecalCluster vs ecalSatellites look inconsistent (eCluster E, calibE, ecalSatellite E, calib E): " 2858 << eclusterref->energy() <<
" " << eclusterref->correctedEnergy() <<
" " 2859 <<
sqrt(std::get<1>(ecalSatellite.second).Mag2()) <<
" " << ecalClusterEnergyCalibrated;
2872 <<
"---- loop remaining hcal ------- "<<endl;
2878 for(
unsigned iHcal : hcalIs) {
2881 std::vector<unsigned> ecalRefs;
2882 std::vector<unsigned> hoRefs;
2885 cout<<endl<<elements[iHcal]<<
" ";
2888 if( !active[iHcal] ) {
2890 cout<<
"not active"<<endl;
2895 std::multimap<double, unsigned> ecalElems;
2896 block.associatedElements( iHcal, linkData,
2902 float totalEcal = 0.;
2905 for(
auto const&
ecal : ecalElems) {
2907 unsigned iEcal =
ecal.second;
2908 double dist =
ecal.first;
2913 if( !active[iEcal] )
continue;
2934 std::multimap<double, unsigned> hcalElems;
2935 block.associatedElements( iEcal, linkData,
2940 const bool isClosest = std::none_of(hcalElems.begin(), hcalElems.end(), [&](
auto const&
hcal){
2941 return active[
hcal.second] &&
hcal.first < dist;
2944 if (!isClosest)
continue;
2948 cout<<
"\telement "<<elements[iEcal]<<
" linked with dist "<< dist<<endl;
2949 cout<<
"Added to HCAL cluster to form a neutral hadron"<<endl;
2953 assert( !eclusterRef.
isNull() );
2956 double ecalEnergy = eclusterRef->energy();
2960 totalEcal += ecalEnergy;
2961 if ( ecalEnergy > ecalMax ) {
2962 ecalMax = ecalEnergy;
2963 eClusterRef = eclusterRef;
2966 ecalRefs.push_back(iEcal);
2967 active[iEcal] =
false;
2973 double totalHO = 0.;
2977 std::multimap<double, unsigned> hoElems;
2978 block.associatedElements( iHcal, linkData,
2988 for(
auto const&
ho : hoElems) {
2990 unsigned iHO =
ho.second;
2991 double dist =
ho.first;
2996 if( !active[iHO] )
continue;
3002 std::multimap<double, unsigned> hcalElems;
3003 block.associatedElements( iHO, linkData,
3008 const bool isClosest = std::none_of(hcalElems.begin(), hcalElems.end(), [&](
auto const&
hcal){
3009 return active[
hcal.second] &&
hcal.first < dist;
3012 if (!isClosest)
continue;
3015 cout<<
"\telement "<<elements[iHO]<<
" linked with dist "<< dist<<endl;
3016 cout<<
"Added to HCAL cluster to form a neutral hadron"<<endl;
3020 assert( !hoclusterRef.
isNull() );
3022 double hoEnergy = hoclusterRef->energy();
3024 totalHO += hoEnergy;
3025 if ( hoEnergy > hoMax ) {
3027 hoClusterRef = hoclusterRef;
3031 hoRefs.push_back(iHO);
3032 active[iHO] =
false;
3038 = elements[iHcal].clusterRef();
3039 assert( !hclusterRef.
isNull() );
3042 double totalHcal = hclusterRef->energy();
3044 if (
useHO_ ) totalHcal += totalHO;
3052 double calibEcal = totalEcal > 0. ? totalEcal : 0.;
3053 double calibHcal =
std::max(0.,totalHcal);
3057 calibEcal = totalEcal;
3060 hclusterRef->positionREP().Eta(),
3061 hclusterRef->positionREP().Phi());
3075 cand.setEcalEnergy( totalEcal, calibEcal );
3077 cand.setHcalEnergy( totalHcal, calibHcal );
3078 cand.setHoEnergy(0.,0.);
3080 cand.setHcalEnergy(
max(totalHcal-totalHO,0.0), calibHcal*(1.-totalHO/totalHcal));
3081 cand.setHoEnergy(totalHO,totalHO*calibHcal/totalHcal);
3083 cand.setPs1Energy( 0. );
3084 cand.setPs2Energy( 0. );
3085 cand.addElementInBlock( blockref, iHcal );
3086 for (
auto const&
ec : ecalRefs)
cand.addElementInBlock( blockref,
ec );
3087 for (
auto const&
ho : hoRefs)
cand.addElementInBlock( blockref,
ho );
3094 if(
debug_)
std::cout << std::endl << std::endl <<
"---- loop ecal------- " << std::endl;
3098 for(
unsigned i=0;
i<ecalIs.size();
i++) {
3099 unsigned iEcal = ecalIs[
i];
3102 cout<<endl<<elements[iEcal]<<
" ";
3104 if( ! active[iEcal] ) {
3106 cout<<
"not active"<<endl;
3113 PFClusterRef clusterref = elements[iEcal].clusterRef();
3114 assert(!clusterref.
isNull() );
3116 active[iEcal] =
false;
3118 float ecalEnergy = clusterref->correctedEnergy();
3120 double particleEnergy = ecalEnergy;
3124 cand.setEcalEnergy( clusterref->energy(),ecalEnergy );
3125 cand.setHcalEnergy( 0., 0. );
3126 cand.setHoEnergy( 0., 0. );
3127 cand.setPs1Energy( 0. );
3128 cand.setPs2Energy( 0. );
3129 cand.addElementInBlock( blockref, iEcal );
3146 double px = track.
px();
3147 double py = track.
py();
3148 double pz = track.
pz();
3149 double energy =
sqrt(track.
p()*track.
p() + 0.13957*0.13957);
3151 if (
debug_)
cout <<
"Reconstructing PF candidate from track of pT = " << track.
pt() <<
" eta = " << track.
eta() <<
" phi = " << track.
phi() <<
" px = " << px <<
" py = " << py <<
" pz = " << pz <<
" energy = " << energy << endl;
3164 pfCandidates_->back().setVertexSource( PFCandidate::kTrkVertex );
3166 pfCandidates_->back().setPositionAtECALEntrance( eltTrack->positionAtECALEntrance());
3179 if ((!isMuon) && isFromDisp) {
3180 double Dpt = trackRef->ptError();
3181 double dptRel = Dpt/trackRef->pt()*100;
3187 cout <<
"Not refitted px = " << px <<
" py = " << py <<
" pz = " << pz <<
" energy = " << energy << endl;
3190 reco::Track trackRefit = vRef->refittedTrack(trackRef);
3195 sqrt(trackRefit.
p()*trackRefit.
p() + 0.13957*0.13957));
3197 cout <<
"Refitted px = " << px <<
" py = " << py <<
" pz = " << pz <<
" energy = " << energy << endl;
3216 double particleEnergy,
3229 if ( useDirection ) {
3230 switch( cluster.
layer() ) {
3233 factor =
std::sqrt(cluster.
position().Perp2()/(particleX*particleX+particleY*particleY));
3239 factor = cluster.
position().Z()/particleZ;
3254 cluster.
position().Y()-vertexPos.Y(),
3255 cluster.
position().Z()-vertexPos.Z());
3257 particleY*factor-vertexPos.Y(),
3258 particleZ*factor-vertexPos.Z() );
3263 clusterPos = useDirection ? particleDirection.Unit() : clusterPos.Unit();
3264 clusterPos *= particleEnergy;
3270 ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> >
3271 momentum( clusterPos.X(), clusterPos.Y(), clusterPos.Z(),
mass);
3281 switch( cluster.
layer() ) {
3288 particleType = PFCandidate::h0;
3291 particleType = PFCandidate::h_HF;
3294 particleType = PFCandidate::egamma_HF;
3330 std::array<double,7> energyPerDepth;
3331 std::fill(energyPerDepth.begin(), energyPerDepth.end(), 0.0);
3333 const auto &
hit = *hitRefAndFrac.recHitRef();
3335 if (
hit.depth() == 0) {
3339 if (
hit.depth() < 1 ||
hit.depth() > 7) {
3340 throw cms::Exception(
"CorruptData") <<
"Bogus depth " <<
hit.depth() <<
" at detid " <<
hit.detId() <<
"\n";
3342 energyPerDepth[
hit.depth()-1] += hitRefAndFrac.fraction()*
hit.energy();
3345 double sum = std::accumulate(energyPerDepth.begin(), energyPerDepth.end(), 0.);
3346 std::array<float,7> depthFractions;
3348 for (
unsigned int i = 0;
i < depthFractions.size(); ++
i) {
3349 depthFractions[
i] = energyPerDepth[
i]/sum;
3352 std::fill(depthFractions.begin(), depthFractions.end(), 0.f);
3363 if ( clusterEnergyHCAL < 1. ) clusterEnergyHCAL = 1.;
3365 double resol = fabs(eta) < 1.48 ?
3366 sqrt (1.02*1.02/clusterEnergyHCAL + 0.065*0.065)
3368 sqrt (1.20*1.20/clusterEnergyHCAL + 0.028*0.028);
3376 double nS = fabs(eta) < 1.48 ?
3386 if(!out )
return out;
3388 out<<
"====== Particle Flow Algorithm ======= ";
3395 out<<
"reconstructed particles: "<<endl;
3399 if(!candidates.get() ) {
3400 out<<
"candidates already transfered"<<endl;
3426 std::vector<bool>& active,
3427 std::vector<double>& psEne) {
3435 std::multimap<double, unsigned> sortedPS;
3437 sortedPS, psElementType,
3441 double totalPS = 0.;
3442 for(
auto const& ps : sortedPS) {
3445 unsigned iPS = ps.second;
3449 if (!active[iPS])
continue;
3452 std::multimap<double, unsigned> sortedECAL;
3457 unsigned jEcal = sortedECAL.begin()->second;
3458 if ( jEcal != iEcal )
continue;
3462 assert( pstype == psElementType );
3463 PFClusterRef psclusterref = elements[iPS].clusterRef();
3464 assert(!psclusterref.
isNull() );
3465 totalPS += psclusterref->energy();
3466 psEne[0] += psclusterref->energy();
3467 active[iPS] =
false;
3482 bool bPrimary = (order.find(
"primary") != string::npos);
3483 bool bSecondary = (order.find(
"secondary") != string::npos);
3484 bool bAll = (order.find(
"all") != string::npos);
3489 if (bPrimary && isToDisp)
return true;
3490 if (bSecondary && isFromDisp )
return true;
3491 if (bAll && ( isToDisp || isFromDisp ) )
return true;
3520 std::vector<unsigned int> pfCandidatesToBeRemoved;
3526 double met2 = metX*metX+metY*metY;
3532 double metXCor = metX;
3533 double metYCor = metY;
3534 double sumetCor = sumet;
3535 double met2Cor = met2;
3537 double deltaPhiPt = 100.;
3539 unsigned iCor = 1E9;
3544 double metReduc = -1.;
3546 for(
unsigned i=0;
i<pfCandidates_->size(); ++
i) {
3557 const bool skip = std::any_of(pfCandidatesToBeRemoved.begin(), pfCandidatesToBeRemoved.end(),
3558 [&](
unsigned int j){
return i == j; });
3559 if ( skip )
continue;
3562 deltaPhi = std::acos((metX*pfc.
px()+metY*pfc.
py())/(pfc.
pt()*
std::sqrt(met2)));
3563 deltaPhiPt = deltaPhi*pfc.
pt();
3567 double metXInt = metX - pfc.
px();
3568 double metYInt = metY - pfc.
py();
3569 double sumetInt = sumet - pfc.
pt();
3570 double met2Int = metXInt*metXInt+metYInt*metYInt;
3571 if ( met2Int < met2Cor ) {
3574 metReduc = (met2-met2Int)/met2Int;
3576 sumetCor = sumetInt;
3577 significanceCor =
std::sqrt(met2Cor/sumetCor);
3584 pfCandidatesToBeRemoved.push_back(iCor);
3598 std::cout <<
"Significance reduction = " << significance <<
" -> " 3599 << significanceCor <<
" = " << significanceCor - significance
3601 for(
unsigned int toRemove : pfCandidatesToBeRemoved) {
3602 std::cout <<
"Removed : " << (*pfCandidates_)[toRemove] << std::endl;
3604 (*pfCandidates_)[toRemove].rescaleMomentum(1E-6);
3618 if ( cleanedHits.empty() )
return;
3624 std::vector<unsigned int> hitsToBeAdded;
3630 double met2 = metX*metX+metY*metY;
3631 double met2_Original = met2;
3635 double metXCor = metX;
3636 double metYCor = metY;
3637 double sumetCor = sumet;
3638 double met2Cor = met2;
3640 unsigned iCor = 1E9;
3645 double metReduc = -1.;
3647 for(
unsigned i=0;
i<cleanedHits.size(); ++
i) {
3656 for(
unsigned int hitIdx : hitsToBeAdded) {
3657 if (
i == hitIdx ) skip =
true;
3660 if ( skip )
continue;
3663 double metXInt = metX + px;
3664 double metYInt = metY + py;
3665 double sumetInt = sumet +
pt;
3666 double met2Int = metXInt*metXInt+metYInt*metYInt;
3669 if ( met2Int < met2Cor ) {
3672 metReduc = (met2-met2Int)/met2Int;
3674 sumetCor = sumetInt;
3683 hitsToBeAdded.push_back(iCor);
3697 std::cout << hitsToBeAdded.size() <<
" hits were re-added " << std::endl;
3701 std::cout <<
"Added after cleaning check : " << std::endl;
3703 for(
unsigned int hitIdx : hitsToBeAdded) {
3709 std::cout << pfCandidates_->back() <<
". time = " << hit.
time() << std::endl;
3730 cand.setPFElectronExtraRef(theRef);
3738 if(
cand.trackRef().isNonnull()) {
3741 return cand.trackRef() == extra.kfTrackRef();
3744 cand.set_mva_e_pi(it->mvaVariable(PFCandidateElectronExtra::MVA_MVA));
3746 cand.setPFElectronExtraRef(theRef);
3747 cand.setGsfTrackRef(it->gsfTrackRef());
3762 ele.setPFElectronExtraRef(theRef);
3774 if(
cand.superClusterRef().isNonnull()) {
3776 unsigned int pcextra = 0;
3778 if(
cand.superClusterRef() ==
photon.superClusterRef()) {
3780 cand.setPFPhotonExtraRef(theRef);
PFLayer::Layer layer() const
cluster layer, see PFLayer.h in this directory
sumPtTrackIsoForEgammaSC_barrel
double p() const
momentum vector magnitude
T getParameter(std::string const &) const
unsigned int nTrackIsoForEgammaSC_
edm::Ref< PFBlockCollection > PFBlockRef
persistent reference to PFCluster objects
Abstract base class for a PFBlock element (track, cluster...)
static bool isIsolatedMuon(const reco::PFBlockElement &elt)
const math::XYZPoint & position() const
cluster centroid position
bool isFromSecInt(const reco::PFBlockElement &eTrack, std::string order) const
float goodTrackDeadHcal_dxy_
std::vector< double > muonHCAL_
Variables for muons and fakes.
ParticleType
particle types
bool isNonnull() const
Checks for non-null.
T y() const
Cartesian y coordinate.
double eta() const final
momentum pseudorapidity
sumPtTrackIsoForEgammaSC_endcap
void setPFMuonAndFakeParameters(const edm::ParameterSet &pset)
T x() const
Cartesian x coordinate.
PFAlgo(bool debug)
constructor
void addMissingMuons(edm::Handle< reco::MuonCollection >, reco::PFCandidateCollection *cands)
double sumEtEcalIsoForEgammaSC_endcap_
void set_mva_nothing_gamma(float mva)
set mva for gamma detection
bool isMuon(const Candidate &part)
Particle flow cluster, see clustering algorithm in PFClusterAlgo.
edm::Ref< PFCandidatePhotonExtraCollection > PFCandidatePhotonExtraRef
persistent reference to a PFCandidatePhotonExtra
double coneEcalIsoForEgammaSC_
static bool isMuon(const reco::PFBlockElement &elt)
float time() const
timing for cleaned hits
std::unique_ptr< reco::PFCandidateCollection > pfCandidates_
unsigned reconstructCluster(const reco::PFCluster &cluster, double particleEnergy, bool useDirection=false, double particleX=0., double particleY=0., double particleZ=0.)
const std::unique_ptr< reco::PFCandidateCollection > & pfCandidates() const
double y() const
y coordinate
bool useProtectionsForJetMET_
std::unique_ptr< PFElectronAlgo > pfele_
double coneTrackIsoForEgammaSC_
float goodPixelTrackDeadHcal_minEta_
double px() const final
x coordinate of momentum vector
double nSigmaHCAL_
number of sigma to judge energy excess in HCAL
std::map< unsigned int, Link > LinkData
void setMuonHandle(const edm::Handle< reco::MuonCollection > &)
math::Error< dimension >::type Error
covariance error matrix (3x3)
void setVertex(const math::XYZPoint &p) override
void setInputsForCleaning(reco::VertexCollection const &)
std::vector< Variable::Flags > flags
double phi() const
azimuthal angle of momentum vector
double pt() const final
transverse momentum
std::shared_ptr< PFEnergyCalibrationHF > thepfEnergyCalibrationHF_
std::vector< Vertex > VertexCollection
collection of Vertex objects
const edm::OwnVector< reco::PFBlockElement > & elements() const
int charge() const final
electric charge
std::vector< PFRecHit > PFRecHitCollection
collection of PFRecHit objects
sumEtEcalIsoForEgammaSC_endcap
const edm::ValueMap< reco::PhotonRef > * valueMapGedPhotons_
void checkCleaning(const reco::PFRecHitCollection &cleanedHF)
Check HF Cleaning.
edm::Ref< PFCandidateElectronExtraCollection > PFCandidateElectronExtraRef
persistent reference to a PFCandidateElectronExtra
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< float > > XYZPointF
point in space with cartesian internal representation
double px() const
x coordinate of momentum vector
void setDisplacedVerticesParameters(bool rejectTracks_Bad, bool rejectTracks_Step45, bool usePFNuclearInteractions, bool usePFConversions, bool usePFDecays, double dptRel_DispVtx)
std::shared_ptr< PFEnergyCalibration > calibration_
double sumEtEcalIsoForEgammaSC_barrel_
float goodPixelTrackDeadHcal_dxy_
void setEGElectronCollection(const reco::GsfElectronCollection &egelectrons)
const Point & position() const
position
static bool isGlobalTightMuon(const reco::PFBlockElement &elt)
std::vector< GsfElectron > GsfElectronCollection
collection of GsfElectron objects
bool rejectTracks_Step45_
PositionType const & position() const
rechit cell centre x, y, z
std::vector< ElementInBlock > ElementsInBlocks
double minSignificanceReduction_
std::vector< double > factors45_
void setPFVertexParameters(bool useVertex, reco::VertexCollection const &primaryVertices)
bool isPhotonSafeForJetMET(const reco::Photon &, const reco::PFCandidate &) const
bool isElectron(const reco::GsfElectron &) const
PFLayer::Layer layer() const
rechit layer
RefToBase< value_type > refAt(size_type i) const
bool useEGammaSupercluster_
U second(std::pair< T, U > const &p)
void setCharge(Charge q) final
set electric charge
std::unique_ptr< reco::PFCandidateCollection > pfCleanedCandidates_
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
std::unique_ptr< PFPhotonAlgo > pfpho_
void set_mva_e_pi(float mvaNI)
bool isTimeValid() const
do we have a valid time information
bool usePFNuclearInteractions_
double eta() const
pseudorapidity of momentum vector
void setEGammaCollections(const edm::View< reco::PFCandidate > &pfEgammaCandidates, const edm::ValueMap< reco::GsfElectronRef > &valueMapGedElectrons, const edm::ValueMap< reco::PhotonRef > &valueMapGedPhotons)
Particle flow rechit (rechit + geometry and topology information). See clustering algorithm in PFClus...
void setBadHcalTrackParams(const edm::ParameterSet &pset)
void set_mva_Isolated(float mvaI)
T z() const
Cartesian z coordinate.
const edm::View< reco::PFCandidate > * pfEgammaCandidates_
void associatePSClusters(unsigned iEcal, reco::PFBlockElement::Type psElementType, const reco::PFBlock &block, const edm::OwnVector< reco::PFBlockElement > &elements, const reco::PFBlock::LinkData &linkData, std::vector< bool > &active, std::vector< double > &psEne)
Associate PS clusters to a given ECAL cluster, and return their energy.
std::string mvaWeightFileEleID_
Variables for PFElectrons.
void setParticleType(ParticleType type)
set Particle Type
double pt() const
track transverse momentum
void setPFEleParameters(double mvaEleCut, std::string mvaWeightFileEleID, bool usePFElectrons, const std::shared_ptr< PFSCEnergyCalibration > &thePFSCEnergyCalibration, const std::shared_ptr< PFEnergyCalibration > &thePFEnergyCalibration, double sumEtEcalIsoForEgammaSC_barrel, double sumEtEcalIsoForEgammaSC_endcap, double coneEcalIsoForEgammaSC, double sumPtTrackIsoForEgammaSC_barrel, double sumPtTrackIsoForEgammaSC_endcap, unsigned int nTrackIsoForEgammaSC, double coneTrackIsoForEgammaSC, bool applyCrackCorrections=false, bool usePFSCEleCalib=true, bool useEGElectrons=false, bool useEGammaSupercluster=true)
float goodTrackDeadHcal_validFr_
double energy() const final
energy
void setPFPhotonRegWeights(const GBRForest *LCorrForestEB, const GBRForest *LCorrForestEE, const GBRForest *GCorrForestBarrel, const GBRForest *GCorrForestEndcapHr9, const GBRForest *GCorrForestEndcapLr9, const GBRForest *PFEcalResolution)
Abs< T >::type abs(const T &t)
double z() const
z coordinate
reco::Vertex primaryVertex_
double nSigmaHCAL(double clusterEnergy, double clusterEta) const
edm::Handle< reco::MuonCollection > muonHandle_
std::vector< double > muonECAL_
void setPositionAtECALEntrance(float x, float y, float z)
set position at ECAL entrance
math::XYZPoint Point
point in the space
bool isElectronSafeForJetMET(const reco::GsfElectron &, const reco::PFCandidate &, const reco::Vertex &, bool &lockTracks) const
std::shared_ptr< PFEnergyCalibration > thePFEnergyCalibration()
return the pointer to the calibration function
bool passPhotonSelection(const reco::Photon &) const
float energy() const
rechit energy
void setParameters(double nSigmaECAL, double nSigmaHCAL, const std::shared_ptr< PFEnergyCalibration > &calibration, const std::shared_ptr< PFEnergyCalibrationHF > &thepfEnergyCalibrationHF)
sumEtEcalIsoForEgammaSC_barrel
void setPostHFCleaningParameters(bool postHFCleaning, double minHFCleaningPt, double minSignificance, double maxSignificance, double minSignificanceReduction, double maxDeltaPhiPt, double minDeltaMet)
void setPFPhotonParameters(bool usePFPhoton, std::string mvaWeightFileConvID, double mvaConvCut, bool useReg, std::string X0_Map, const std::shared_ptr< PFEnergyCalibration > &thePFEnergyCalibration, double sumPtTrackIsoForPhoton, double sumPtTrackIsoSlopeForPhoton)
std::vector< PFBlock > PFBlockCollection
collection of PFBlock objects
void processBlock(const reco::PFBlockRef &blockref, std::list< reco::PFBlockRef > &hcalBlockRefs, std::list< reco::PFBlockRef > &ecalBlockRefs, PFEGammaFilters const *pfegamma)
bool isNull() const
Checks for null.
int goodPixelTrackDeadHcal_maxLost3Hit_
std::shared_ptr< PFSCEnergyCalibration > thePFSCEnergyCalibration_
reco::PFBlockRef createBlockRef(const reco::PFBlockCollection &blocks, unsigned bi)
reco::PFCandidatePhotonExtraCollection pfPhotonExtra_
the extra photon collection
double pz() const
z coordinate of momentum vector
void setEcalEnergy(float eeRaw, float eeCorr)
set corrected Ecal energy
float mva_e_pi() const
mva for electron-pion discrimination
void setHcalDepthEnergyFractions(const std::array< float, 7 > &fracs)
set the fraction of hcal energy as function of depth (index 0..6 for depth 1..7)
std::unique_ptr< reco::PFCandidateCollection > pfPhotonCandidates_
the unfiltered photon collection
void reconstructParticles(const reco::PFBlockHandle &blockHandle, PFEGammaFilters const *pfegamma)
float goodPixelTrackDeadHcal_maxPt_
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
double x() const
x coordinate
unsigned reconstructTrack(const reco::PFBlockElement &elt, bool allowLoose=false)
int goodTrackDeadHcal_layers_
std::vector< double > muonHO_
float goodPixelTrackDeadHcal_ptErrRel_
XYZVectorD XYZVector
spatial vector with cartesian internal representation
void associatedElements(unsigned i, const LinkData &linkData, std::multimap< double, unsigned > &sortedAssociates, reco::PFBlockElement::Type type=PFBlockElement::NONE, LinkTest test=LINKTEST_RECHIT) const
static bool isLooseMuon(const reco::PFBlockElement &elt)
XYZPointD XYZPoint
point in space with cartesian internal representation
reco::PFBlockHandle blockHandle_
input block handle (full framework case)
double py() const final
y coordinate of momentum vector
virtual bool trackType(TrackType trType) const
bool passElectronSelection(const reco::GsfElectron &, const reco::PFCandidate &, const int &) const
void setHoEnergy(float eoRaw, float eoCorr)
set corrected Hcal energy
std::vector< std::vector< double > > tmp
Particle reconstructed by the particle flow algorithm.
reco::PFCandidateEGammaExtraRef egammaExtraRef() const
return a reference to the EGamma extra
PFMuonAlgo * getPFMuonAlgo()
bool useEGammaFilters_
Variables for NEW EGAMMA selection.
const std::vector< reco::PFRecHitFraction > & recHitFractions() const
vector of rechit fractions
void setPhotonExtraRef(const edm::OrphanHandle< reco::PFCandidatePhotonExtraCollection > &pf_extrah)
bool applyCrackCorrectionsElectrons_
int charge() const
track electric charge
float goodTrackDeadHcal_ptErrRel_
Variables for track cleaning in bad HCal areas.
sumPtTrackIsoSlopeForPhoton
double sumPtTrackIsoForEgammaSC_endcap_
std::unique_ptr< reco::PFCandidateCollection > pfElectronCandidates_
the unfiltered electron collection
int goodPixelTrackDeadHcal_maxLost4Hit_
float goodPixelTrackDeadHcal_chi2n_
virtual ParticleType particleId() const
math::XYZVector XYZVector
double neutralHadronEnergyResolution(double clusterEnergy, double clusterEta) const
todo: use PFClusterTools for this
void postClean(reco::PFCandidateCollection *)
reco::PFCandidateElectronExtraCollection pfElectronExtra_
the unfiltered electron collection
const ElementsInBlocks & elementsInBlocks() const
double phi() const final
momentum azimuthal angle
void setP4(const LorentzVector &p4) final
set 4-momentum
float goodTrackDeadHcal_chi2n_
double sumPtTrackIsoForEgammaSC_barrel_
float goodPixelTrackDeadHcal_dz_
void setHcalEnergy(float ehRaw, float ehCorr)
set corrected Hcal energy
void setHcalDepthInfo(reco::PFCandidate &cand, const reco::PFCluster &cluster) const
void setEGammaParameters(bool use_EGammaFilters, bool useProtectionsForJetMET)
double py() const
y coordinate of momentum vector
static bool isTrackerTightMuon(const reco::PFBlockElement &elt)
const edm::ValueMap< reco::GsfElectronRef > * valueMapGedElectrons_
friend std::ostream & operator<<(std::ostream &out, const PFAlgo &algo)
void setElectronExtraRef(const edm::OrphanHandle< reco::PFCandidateElectronExtraCollection > &extrah)
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
bool reconstructMuon(reco::PFCandidate &, const reco::MuonRef &, bool allowLoose=false)
double nSigmaECAL_
number of sigma to judge energy excess in ECAL