90 m_PVkey(
"PrimaryVertices"),
91 m_acc_jetRejectionDec(nullptr),
129 "EXPERIMENTAL: whether to use simplified OR based on nominal jets "
130 "and for jet-related systematics only. "
131 "WARNING: this property is strictly for doing physics studies of the feasibility "
132 "of this OR scheme, it should not be used in a regular analysis");
166 ATH_MSG_INFO(
"Custom jet selection configured. *** FOR EXPERT USE ONLY ***");
173 ATH_MSG_INFO(
"Jet selection for hadronic recoil calculation is configured.");
181 ATH_MSG_ERROR(
"Error: No available jet selection found! Please update JetSelection in METMaker. Choose one: Loose, Tight (recommended), Tighter, Tenacious" );
182 return StatusCode::FAILURE;
211 ATH_MSG_INFO(
"Requesting simplified overlap removal procedure in MET calculation");
214 return StatusCode::SUCCESS;
242 ATH_MSG_WARNING(
"Incorrect use of rebuildMET -- use rebuildJetMET for RefJet term");
243 return StatusCode::FAILURE;
246 return StatusCode::FAILURE;
250 if(
fillMET(
met,metCont, metKey , metSource) != StatusCode::SUCCESS) {
251 ATH_MSG_ERROR(
"failed to fill MET term \"" << metKey <<
"\"");
252 return StatusCode::FAILURE;
258 if(
fillMET(met_muEloss,metCont,
"MuonEloss",
261 return StatusCode::FAILURE;
274 bool removeOverlap =
true;
275 if(!collection->
empty()) {
279 removeOverlap =
false;
293 if(!
met || !collection) {
295 <<
"MET (" <<
met <<
") or "
296 <<
"collection (" << collection <<
").");
297 return StatusCode::FAILURE;
301 ATH_MSG_ERROR(
"MET Association Helper isn't associated with a MissingETAssociationMap!");
302 return StatusCode::FAILURE;
305 ATH_MSG_WARNING(
"Incomplete association map received. Cannot rebuild MET.");
306 ATH_MSG_WARNING(
"Note: METMaker should only be run on events containing at least one PV");
307 return StatusCode::SUCCESS;
310 dec_constitObjLinks(*
met) = std::vector<iplink_t>(0);
311 dec_constitObjWeights(*
met) = std::vector<float>(0);
312 std::vector<iplink_t>& uniqueLinks = dec_constitObjLinks(*
met);
313 std::vector<float>& uniqueWeights = dec_constitObjWeights(*
met);
314 uniqueLinks.reserve(collection->
size());
315 uniqueWeights.reserve(collection->
size());
326 collectionSgKey =
getKey(collection);
327 if(collectionSgKey == 0) {
330 return StatusCode::FAILURE;
334 if(collection->
empty())
return StatusCode::SUCCESS;
336 bool originalInputs = !acc_originalObject.isAvailable(*collection->
front());
339 if(isShallowCopy && originalInputs) {
340 ATH_MSG_WARNING(
"Shallow copy provided without \"originalObjectLinks\" decoration! "
341 <<
"Overlap removal cannot be done. "
342 <<
"Will not compute this term.");
343 ATH_MSG_WARNING(
"Please apply xAOD::setOriginalObjectLink() from xAODBase/IParticleHelpers.h");
344 return StatusCode::SUCCESS;
347 for(
const auto *
const obj : *collection) {
349 bool selected =
false;
350 if(!originalInputs) { orig = *acc_originalObject(*
obj); }
353 std::string
message =
"Object is not in association map. Did you make a deep copy but fail to set the \"originalObjectLinks\" decoration? "
354 "If not, Please apply xAOD::setOriginalObjectLink() from xAODBase/IParticleHelpers.h";
364 if(collectionSgKey == 0) {
370 uniqueLinks.emplace_back( objLink );
371 uniqueWeights.emplace_back( 0. );
372 message =
"Missing an electron from the MET map. Included as a track in the soft term. pT: " +
std::to_string(
obj->pt()/1
e3) +
" GeV";
380 ATH_MSG_ERROR(
"Missing an object: " << orig->
type() <<
" pT: " <<
obj->pt()/1
e3 <<
" GeV, may be duplicated in the soft term.");
388 <<
" is " << ( selected ?
"non-" :
"") <<
"overlapping");
393 std::vector<size_t>
indices = assoc->overlapIndices(orig);
394 std::vector<const xAOD::IParticle*> allObjects = assoc->objects();
397 if(!thisObj)
continue;
400 helper.setObjSelectionFlag(assoc, thisObj,
true);
407 for (
size_t i = 0;
i < assocs.size();
i++) {
408 std::vector<size_t>
ind = assocs[
i]->overlapIndices(orig);
409 std::vector<const xAOD::IParticle*> allObjects = assocs[
i]->objects();
410 for (
size_t indi = 0; indi <
ind.size(); indi++)
if (allObjects[
ind[indi]]) {
412 &&
helper.objSelected(assocs[
i],
ind[indi])) {
432 if(collectionSgKey == 0) {
439 uniqueLinks.push_back( objLink );
440 uniqueWeights.push_back( 1. );
444 return StatusCode::SUCCESS;
448 const std::string& softKey,
455 ATH_MSG_VERBOSE(
"Rebuild jet term: " << metJetKey <<
" and soft term: " << softKey);
459 ATH_MSG_ERROR(
"failed to fill MET term \"" << metJetKey <<
"\"");
460 return StatusCode::FAILURE;
463 const MissingET *coreSoftClus(
nullptr), *coreSoftTrk(
nullptr);
464 MissingET *metSoftClus(
nullptr), *metSoftTrk(
nullptr);
466 const MissingET* coreSoft = (*metCoreCont)[softKey+
"Core"];
469 return StatusCode::FAILURE;
472 coreSoftTrk = coreSoft;
474 metSoftTrk =
nullptr;
475 if(
fillMET(metSoftTrk,metCont, softKey , coreSoftTrk->
source() ) != StatusCode::SUCCESS) {
476 ATH_MSG_ERROR(
"failed to fill MET term \"" << softKey <<
"\"");
477 return StatusCode::FAILURE;
480 coreSoftClus = coreSoft;
482 metSoftClus =
nullptr;
483 if(
fillMET(metSoftClus, metCont, softKey , coreSoftClus->source() ) != StatusCode::SUCCESS) {
484 ATH_MSG_ERROR(
"failed to fill MET term \"" << softKey <<
"\"");
485 return StatusCode::FAILURE;
490 metSoftClus, coreSoftClus,
491 metSoftTrk, coreSoftTrk,
496 const std::string& softKey,
503 ATH_MSG_VERBOSE(
"Rebuild jet term: " << metJetKey <<
" and soft term: " << softKey);
507 ATH_MSG_ERROR(
"failed to fill MET term \"" << metJetKey <<
"\"");
508 return StatusCode::FAILURE;
514 const MissingET* coreSoft = (*metCoreCont)[softKey+
"Core"];
517 return StatusCode::FAILURE;
519 coreSoftTrk = coreSoft;
521 metSoftTrk =
nullptr;
522 if(
fillMET(metSoftTrk , metCont, softKey , coreSoftTrk->
source()) != StatusCode::SUCCESS) {
523 ATH_MSG_ERROR(
"failed to fill MET term \"" << softKey <<
"\"");
524 return StatusCode::FAILURE;
528 metSoftTrk, coreSoftTrk,
533 const std::string& softClusKey,
534 const std::string& softTrkKey,
545 ATH_MSG_ERROR(
"failed to fill MET term \"" << metJetKey <<
"\"");
546 return StatusCode::FAILURE;
549 const MissingET* coreSoftClus = (*metCoreCont)[softClusKey+
"Core"];
551 const MissingET* coreSoftTrk = (*metCoreCont)[softTrkKey+
"Core"];
553 ATH_MSG_WARNING(
"Invalid cluster soft term key supplied: " << softClusKey);
554 return StatusCode::FAILURE;
557 ATH_MSG_WARNING(
"Invalid track soft term key supplied: " << softTrkKey);
558 return StatusCode::FAILURE;
561 if(
fillMET(metSoftClus, metCont, softClusKey, coreSoftClus->
source()) != StatusCode::SUCCESS) {
562 ATH_MSG_ERROR(
"failed to fill MET term \"" << softClusKey <<
"\"");
563 return StatusCode::FAILURE;
567 if(
fillMET(metSoftTrk, metCont, softTrkKey, coreSoftTrk->
source()) != StatusCode::SUCCESS) {
568 ATH_MSG_ERROR(
"failed to fill MET term \"" << softTrkKey <<
"\"");
569 return StatusCode::FAILURE;
573 metSoftClus, coreSoftClus,
574 metSoftTrk, coreSoftTrk,
586 bool tracksForHardJets,
587 std::vector<const xAOD::IParticle*>* softConst) {
588 if(!metJet || !
jets) {
590 <<
"MET (" << metJet <<
") or "
591 <<
"jet collection (" <<
jets <<
").");
592 return StatusCode::FAILURE;
596 ATH_MSG_ERROR(
"MET Association Helper isn't associated with a MissingETAssociationMap!");
597 return StatusCode::FAILURE;
600 ATH_MSG_WARNING(
"Requested soft track element links, but no track selection tool supplied.");
605 ATH_MSG_WARNING(
"Incomplete association map received. Cannot rebuild MET.");
606 ATH_MSG_WARNING(
"Note: METMaker should only be run on events containing at least one PV");
607 return StatusCode::SUCCESS;
610 if(doJetJVT &&
m_JvtWP ==
"None"){
616 if(!metSoftClus && !metSoftTrk) {
617 ATH_MSG_WARNING(
"Neither soft cluster nor soft track term has been supplied!");
618 return StatusCode::SUCCESS;
622 dec_constitObjLinks(*metSoftClus) = std::vector<iplink_t>(0);
624 ATH_MSG_ERROR(
"Soft cluster term provided without a core term!");
625 return StatusCode::FAILURE;
629 <<
", mpy " << coreSoftClus->
mpy()
630 <<
" sumet " << coreSoftClus->
sumet());
631 *metSoftClus += *coreSoftClus;
635 if(softConst && acc_softConst.
isAvailable(*coreSoftClus)) {
636 for(
const auto& constit : acc_softConst(*coreSoftClus)) {
637 softConst->push_back(*constit);
639 ATH_MSG_DEBUG(softConst->size() <<
" soft constituents from core term");
643 dec_constitObjLinks(*metSoftTrk) = std::vector<iplink_t>(0);
645 ATH_MSG_ERROR(
"Soft track term provided without a core term!");
646 return StatusCode::FAILURE;
650 <<
", mpy " << coreSoftTrk->
mpy()
651 <<
" sumet " << coreSoftTrk->
sumet());
652 *metSoftTrk += *coreSoftTrk;
654 for(
const auto& constit : acc_softConst(*coreSoftTrk)) {
655 softConst->push_back(*constit);
657 ATH_MSG_DEBUG(softConst->size() <<
" soft constituents from trk core term");
661 dec_constitObjLinks(*metJet) = std::vector<iplink_t>(0);
662 dec_constitObjWeights(*metJet) = std::vector<float>(0);
663 std::vector<iplink_t>& uniqueLinks = dec_constitObjLinks(*metJet);
664 std::vector<float>& uniqueWeights = dec_constitObjWeights(*metJet);
665 uniqueLinks.reserve(
jets->size());
666 uniqueWeights.reserve(
jets->size());
667 std::vector<iplink_t> softJetLinks;
668 std::vector<float> softJetWeights;
669 bool originalInputs =
jets->empty() ? false : !acc_originalObject.isAvailable(*
jets->front());
682 return StatusCode::FAILURE;
694 if(!assoc || assoc->
isMisc()){
701 if (acc_nominalObject.isAvailable(*
jet)){
707 ATH_MSG_ERROR(
"No nominal calibrated jet available for jet " <<
jet->index() <<
". Cannot simplify overlap removal!");
712 bool JVT_reject(
false);
713 bool isMuFSRJet(
false);
722 ATH_MSG_VERBOSE(
"Jet " << (JVT_reject ?
"fails" :
"passes") <<
" JVT selection");
729 bool caloverlap =
false;
730 caloverlap = calvec.
ce()>0;
731 ATH_MSG_DEBUG(
"Jet " <<
jet->index() <<
" is " << ( caloverlap ?
"" :
"non-") <<
"overlapping");
734 for(
const auto&
object : assoc->
objects()) {
751 double jpx = constjet.Px();
752 double jpy = constjet.Py();
753 double jpt = constjet.Pt();
754 double opx = jpx - calvec.
cpx();
755 double opy = jpy - calvec.
cpy();
761 met_muonEloss = (*metCont)[
"MuonEloss"];
763 ATH_MSG_WARNING(
"Attempted to apply muon Eloss correction, but corresponding MET term does not exist!");
764 return StatusCode::FAILURE;
768 float total_eloss(0);
770 std::vector<const xAOD::Muon*> muons_in_jet;
771 std::vector<const xAOD::Electron*> electrons_in_jet;
772 bool passJetForEl=
false;
774 if(!acc_ghostMuons.isAvailable(*
jet)){
776 return StatusCode::FAILURE;
778 for(
const auto&
el : acc_ghostMuons(*
jet)) {
780 ATH_MSG_ERROR(
"Invalid element link to ghost muon! Quitting.");
781 return StatusCode::FAILURE;
783 muons_in_jet.push_back(
static_cast<const xAOD::Muon*
>(*
el));
792 if(acc_originalObject.isAvailable(*mu_test)) mu_test =
static_cast<const xAOD::Muon*
>(*acc_originalObject(*mu_test));
794 muons_in_jet.push_back(mu_test);
801 if(acc_originalObject.isAvailable(*el_test)) el_test =
static_cast<const xAOD::Electron*
>(*acc_originalObject(*el_test));
802 if(
helper.objSelected(assoc,el_test)){
803 if(el_test->
pt()>90.0e3) {
804 electrons_in_jet.push_back(el_test);
813 float jet_all_trk_pt = initialTrkMom.
sumpt();
814 float jet_unique_trk_pt = jet_all_trk_pt - jet_ORtrk_sumpt;
817 for(
const auto& elec : electrons_in_jet) {
818 el_calvec += assoc->
calVec(elec);
819 el_trkvec += assoc->
trkVec(elec);
821 float el_cal_pt = el_calvec.
cpt();
822 float el_trk_pt = el_trkvec.
cpt();
824 <<
" jetalltrk: " << jet_all_trk_pt
825 <<
" jetORtrk: " << jet_ORtrk_sumpt
826 <<
" electrk-jetORtrk: " << (el_trk_pt-jet_ORtrk_sumpt)
827 <<
" elec cal: " << el_cal_pt
828 <<
" jetalltrk-electrk: " << (jet_all_trk_pt-el_trk_pt)
829 <<
" jetalltrk-jetORtrk: " << (jet_all_trk_pt-jet_ORtrk_sumpt) );
833 if(el_trk_pt>1
e-9 && jet_unique_trk_pt>10.0
e3) passJetForEl=
true;
836 for(
const xAOD::Muon* mu_in_jet : muons_in_jet) {
837 if (!mu_in_jet)
continue;
838 float mu_Eloss = acc_Eloss(*mu_in_jet);
843 float mu_id_pt = mu_in_jet->trackParticle(xAOD::Muon::InnerDetectorTrackParticle) ? mu_in_jet->trackParticle(xAOD::Muon::InnerDetectorTrackParticle)->pt() : 0.;
844 float jet_trk_sumpt = acc_trksumpt.isAvailable(*
jet) && this->
getPV() ? acc_trksumpt(*
jet)[this->
getPV()->
index()] : 0.;
847 if(0.9999*mu_id_pt>jet_trk_sumpt)
848 jet_trk_sumpt+=mu_id_pt;
849 float jet_trk_N = acc_trkN.isAvailable(*
jet) && this->
getPV() ? acc_trkN(*
jet)[this->
getPV()->
index()] : 0.;
851 ATH_MSG_VERBOSE(
"Jet has pt " <<
jet->pt() <<
", trk sumpt " << jet_trk_sumpt <<
", trk N " << jet_trk_N);
861 float mu_id_pt = mu_in_jet->trackParticle(xAOD::Muon::InnerDetectorTrackParticle) ? mu_in_jet->trackParticle(xAOD::Muon::InnerDetectorTrackParticle)->pt() : 0.;
862 float jet_trk_sumpt = acc_trksumpt.isAvailable(*
jet) && this->
getPV() ? acc_trksumpt(*
jet)[this->
getPV()->
index()] : 0.;
864 if(0.9999*mu_id_pt>jet_trk_sumpt)
865 jet_trk_sumpt+=mu_id_pt;
866 float jet_trk_N = acc_trkN.isAvailable(*
jet) && this->
getPV() ? acc_trkN(*
jet)[this->
getPV()->
index()] : 0.;
869 if (acc_psf.isAvailable(*
jet)){
870 jet_psE = acc_psf(*
jet);
871 }
else if (acc_sampleE.isAvailable(*
jet)){
872 jet_psE = acc_sampleE(*
jet)[0] + acc_sampleE(*
jet)[4];
874 ATH_MSG_ERROR(
"Jet PS fraction or sampling energy must be available to calculate MET with doSetMuonJetEMScale");
875 return StatusCode::FAILURE;
880 ATH_MSG_VERBOSE(
"Jet has trk sumpt " << jet_trk_sumpt <<
", trk N " << jet_trk_N <<
", PS E " << jet_psE <<
", width " << acc_width(*
jet) <<
", emfrac " << acc_emf(*
jet));
883 ATH_MSG_VERBOSE(
"Jet is from muon -- set to EM scale and subtract Eloss.");
886 ATH_MSG_VERBOSE(
"Jet e: " << constjet.E() <<
", mu Eloss: " << mu_Eloss);
887 float elosscorr = mu_Eloss >= constjet.e() ? 0. : 1.-mu_Eloss/constjet.e();
892 ATH_MSG_VERBOSE(
" Jet eloss factor " << elosscorr <<
", final pt: " << sqrt(opx*opx+opy*opy));
899 switch(mu_in_jet->energyLossType()) {
900 case xAOD::Muon::Parametrized:
901 case xAOD::Muon::MOP:
902 case xAOD::Muon::Tail:
903 case xAOD::Muon::FSRcandidate:
904 case xAOD::Muon::NotIsolated:
908 total_eloss += mu_Eloss;
909 muons_selflags |= (1<<assoc->
findIndex(mu_in_jet));
917 for(
size_t iKey = 0; iKey < assoc->sizeCal(); iKey++) {
923 if(
m_muEloss) mu_calovec *= std::max<float>(0.,1-(total_eloss/mu_calovec.
ce()));
928 ATH_MSG_VERBOSE(
"Jet " <<
jet->index() <<
" const pT after OR " << sqrt(opx*opx+opy*opy));
929 opx += mu_calovec.
cpx();
930 opy += mu_calovec.
cpy();
931 double opt = sqrt( opx*opx+opy*opy );
932 ATH_MSG_VERBOSE(
"Jet " <<
jet->index() <<
" const pT diff after OR readding muon clusters " <<
opt-jpt);
933 double uniquefrac = 1. - (calvec.
ce() - mu_calovec.
ce()) / constjet.E();
934 ATH_MSG_VERBOSE(
"Jet constscale px, py, pt, E = " << jpx <<
", " << jpy <<
", " << jpt <<
", " << constjet.E() );
936 ATH_MSG_VERBOSE(
"Jet OR px, py, pt, E = " << opx <<
", " << opy <<
", " <<
opt <<
", " << constjet.E() - calvec.
ce() );
940 ATH_MSG_ERROR(
"Attempted to apply muon Eloss correction, but corresponding MET term does not exist!");
941 return StatusCode::FAILURE;
943 met_muonEloss->
add(opx,opy,
opt);
947 if(selected && !JVT_reject) {
951 if (!tracksForHardJets) {
953 metJet->
add(jpx,jpy,jpt);
961 if(!tracksForHardJets) {
966 double jesF =
jet->pt() / jpt;
967 metJet->
add(opx*jesF,opy*jesF,
opt*jesF);
971 metJet->
add(uniquefrac*jpx,uniquefrac*jpy,uniquefrac*jpt);
976 metJet->
add(uniquefrac*
jet->px(),uniquefrac*
jet->py(),uniquefrac*
jet->pt());
995 uniqueLinks.push_back( jetLink );
996 uniqueWeights.push_back( uniquefrac );
998 if(metSoftClus && !JVT_reject) {
1002 softJetLinks.push_back( jetLink );
1003 softJetWeights.push_back( uniquefrac );
1004 metSoftClus->
add(opx,opy,
opt);
1013 for(
size_t iConst=0; iConst<
jet->numConstituents(); ++iConst) {
1014 const IParticle* constit =
jet->rawConstituent(iConst);
1015 softConst->push_back(constit);
1021 if(!metSoftTrk || (hardJet && !tracksForHardJets))
continue;
1027 if(jettrkvec.
ce()>1
e-9) {
1028 jpx = jettrkvec.
cpx();
1029 jpy = jettrkvec.
cpy();
1030 jpt = jettrkvec.
sumpt();
1031 jettrkvec -= trkvec;
1032 opx = jettrkvec.
cpx();
1033 opy = jettrkvec.
cpy();
1035 ATH_MSG_VERBOSE(
"Jet track px, py, sumpt = " << jpx <<
", " << jpy <<
", " << jpt );
1038 opx = opy =
opt = 0;
1041 if (hardJet) metJet->
add(opx,opy,
opt);
1043 metSoftTrk->
add(opx,opy,
opt);
1046 softJetLinks.push_back( jetLink );
1047 softJetWeights.push_back( uniquefrac );
1056 std::vector<const IParticle*> jettracks;
1058 for(
size_t iConst=0; iConst<jettracks.size(); ++iConst) {
1066 ATH_MSG_DEBUG(
"Number of selected jets: " << dec_constitObjLinks(*metJet).size());
1069 dec_constitObjLinks(*metSoftTrk) = softJetLinks;
1070 ATH_MSG_DEBUG(
"Number of softtrk jets: " << dec_constitObjLinks(*metSoftTrk).size());
1074 dec_constitObjLinks(*metSoftClus) = softJetLinks;
1075 ATH_MSG_DEBUG(
"Number of softclus jets: " << dec_constitObjLinks(*metSoftClus).size());
1078 if(softConst)
ATH_MSG_DEBUG(softConst->size() <<
" soft constituents from core term + jets");
1081 if(!assoc)
return StatusCode::SUCCESS;
1087 double opx = trkvec.
cpx();
1088 double opy = trkvec.
cpy();
1089 double osumpt = trkvec.
sumpt();
1090 ATH_MSG_VERBOSE(
"Misc track px, py, sumpt = " << opx <<
", " << opy <<
", " << osumpt );
1091 metSoftTrk->
add(opx,opy,osumpt);
1093 <<
", mpy " << metSoftTrk->
mpy()
1094 <<
" sumet " << metSoftTrk->
sumet());
1100 float total_eloss(0.);
1103 double opx = calvec.
cpx();
1104 double opy = calvec.
cpy();
1105 double osumpt = calvec.
sumpt();
1109 if(acc_originalObject.isAvailable(*mu_test)) mu_test =
static_cast<const xAOD::Muon*
>(*acc_originalObject(*mu_test));
1111 float mu_Eloss = acc_Eloss(*mu_test);
1113 case xAOD::Muon::Parametrized:
1114 case xAOD::Muon::MOP:
1115 case xAOD::Muon::Tail:
1116 case xAOD::Muon::FSRcandidate:
1117 case xAOD::Muon::NotIsolated:
1121 total_eloss += mu_Eloss;
1122 muons_selflags |= (1<<assoc->
findIndex(mu_test));
1132 for(
size_t iKey = 0; iKey < assoc->sizeCal(); iKey++) {
1135 <<
" this calvec E: " << assoc->
calVec(iKey).
ce());
1139 mu_calovec *= std::max<float>(0.,1-(total_eloss/mu_calovec.
ce()));
1140 opx += mu_calovec.
cpx();
1141 opy += mu_calovec.
cpy();
1142 osumpt += mu_calovec.
sumpt();
1146 ATH_MSG_VERBOSE(
"Misc cluster px, py, sumpt = " << opx <<
", " << opy <<
", " << osumpt );
1147 metSoftClus->
add(opx,opy,osumpt);
1149 <<
", mpy " << metSoftClus->
mpy()
1150 <<
" sumet " << metSoftClus->
sumet());
1153 return StatusCode::SUCCESS;
1171 if(
fillMET(
met,metCont,
"Invisibles" , invisSource) != StatusCode::SUCCESS) {
1173 return StatusCode::FAILURE;
1180 return static_cast<bool>(
m_trkseltool->accept( *trk, vx ));
1188 ATH_MSG_WARNING(
"Unable to retrieve primary vertex container PrimaryVertices");
1191 ATH_MSG_DEBUG(
"Successfully retrieved primary vertex container");