90 m_PVkey(
"PrimaryVertices"),
91 m_acc_jetRejectionDec(nullptr),
128 "EXPERIMENTAL: whether to use simplified OR based on nominal jets "
129 "and for jet-related systematics only. "
130 "WARNING: this property is strictly for doing physics studies of the feasibility "
131 "of this OR scheme, it should not be used in a regular analysis");
165 ATH_MSG_INFO(
"Custom jet selection configured. *** FOR EXPERT USE ONLY ***");
172 ATH_MSG_INFO(
"Jet selection for hadronic recoil calculation is configured.");
180 ATH_MSG_ERROR(
"Error: No available jet selection found! Please update JetSelection in METMaker. Choose one: Loose, Tight (recommended), Tighter, Tenacious" );
181 return StatusCode::FAILURE;
210 ATH_MSG_INFO(
"Requesting simplified overlap removal procedure in MET calculation");
213 return StatusCode::SUCCESS;
241 ATH_MSG_WARNING(
"Incorrect use of rebuildMET -- use rebuildJetMET for RefJet term");
242 return StatusCode::FAILURE;
245 return StatusCode::FAILURE;
249 if(
fillMET(
met,metCont, metKey , metSource) != StatusCode::SUCCESS) {
250 ATH_MSG_ERROR(
"failed to fill MET term \"" << metKey <<
"\"");
251 return StatusCode::FAILURE;
257 if(
fillMET(met_muEloss,metCont,
"MuonEloss",
260 return StatusCode::FAILURE;
273 bool removeOverlap =
true;
274 if(!collection->
empty()) {
278 removeOverlap =
false;
292 if(!
met || !collection) {
294 <<
"MET (" <<
met <<
") or "
295 <<
"collection (" << collection <<
").");
296 return StatusCode::FAILURE;
300 ATH_MSG_ERROR(
"MET Association Helper isn't associated with a MissingETAssociationMap!");
301 return StatusCode::FAILURE;
304 ATH_MSG_WARNING(
"Incomplete association map received. Cannot rebuild MET.");
305 ATH_MSG_WARNING(
"Note: METMaker should only be run on events containing at least one PV");
306 return StatusCode::SUCCESS;
309 dec_constitObjLinks(*
met) = std::vector<iplink_t>(0);
310 dec_constitObjWeights(*
met) = std::vector<float>(0);
311 std::vector<iplink_t>& uniqueLinks = dec_constitObjLinks(*
met);
312 std::vector<float>& uniqueWeights = dec_constitObjWeights(*
met);
313 uniqueLinks.reserve(collection->
size());
314 uniqueWeights.reserve(collection->
size());
325 collectionSgKey =
getKey(collection);
326 if(collectionSgKey == 0) {
329 return StatusCode::FAILURE;
333 if(collection->
empty())
return StatusCode::SUCCESS;
335 bool originalInputs = !acc_originalObject.isAvailable(*collection->
front());
338 if(isShallowCopy && originalInputs) {
339 ATH_MSG_WARNING(
"Shallow copy provided without \"originalObjectLinks\" decoration! "
340 <<
"Overlap removal cannot be done. "
341 <<
"Will not compute this term.");
342 ATH_MSG_WARNING(
"Please apply xAOD::setOriginalObjectLink() from xAODBase/IParticleHelpers.h");
343 return StatusCode::SUCCESS;
346 for(
const auto *
const obj : *collection) {
348 bool selected =
false;
349 if(!originalInputs) { orig = *acc_originalObject(*
obj); }
352 std::string
message =
"Object is not in association map. Did you make a deep copy but fail to set the \"originalObjectLinks\" decoration? "
353 "If not, Please apply xAOD::setOriginalObjectLink() from xAODBase/IParticleHelpers.h";
363 if(collectionSgKey == 0) {
369 uniqueLinks.emplace_back( objLink );
370 uniqueWeights.emplace_back( 0. );
371 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";
379 ATH_MSG_ERROR(
"Missing an object: " << orig->
type() <<
" pT: " <<
obj->pt()/1
e3 <<
" GeV, may be duplicated in the soft term.");
387 <<
" is " << ( selected ?
"non-" :
"") <<
"overlapping");
392 std::vector<size_t>
indices = assoc->overlapIndices(orig);
393 std::vector<const xAOD::IParticle*> allObjects = assoc->objects();
396 if(!thisObj)
continue;
399 helper.setObjSelectionFlag(assoc, thisObj,
true);
406 for (
size_t i = 0;
i < assocs.size();
i++) {
407 std::vector<size_t> ind = assocs[
i]->overlapIndices(orig);
408 std::vector<const xAOD::IParticle*> allObjects = assocs[
i]->objects();
409 for (
size_t indi = 0; indi < ind.size(); indi++)
if (allObjects[ind[indi]]) {
411 &&
helper.objSelected(assocs[
i], ind[indi])) {
431 if(collectionSgKey == 0) {
438 uniqueLinks.push_back( objLink );
439 uniqueWeights.push_back( 1. );
443 return StatusCode::SUCCESS;
447 const std::string& softKey,
454 ATH_MSG_VERBOSE(
"Rebuild jet term: " << metJetKey <<
" and soft term: " << softKey);
458 ATH_MSG_ERROR(
"failed to fill MET term \"" << metJetKey <<
"\"");
459 return StatusCode::FAILURE;
462 const MissingET *coreSoftClus(
nullptr), *coreSoftTrk(
nullptr);
463 MissingET *metSoftClus(
nullptr), *metSoftTrk(
nullptr);
465 const MissingET* coreSoft = (*metCoreCont)[softKey+
"Core"];
468 return StatusCode::FAILURE;
471 coreSoftTrk = coreSoft;
473 metSoftTrk =
nullptr;
474 if(
fillMET(metSoftTrk,metCont, softKey , coreSoftTrk->
source() ) != StatusCode::SUCCESS) {
475 ATH_MSG_ERROR(
"failed to fill MET term \"" << softKey <<
"\"");
476 return StatusCode::FAILURE;
479 coreSoftClus = coreSoft;
481 metSoftClus =
nullptr;
482 if(
fillMET(metSoftClus, metCont, softKey , coreSoftClus->source() ) != StatusCode::SUCCESS) {
483 ATH_MSG_ERROR(
"failed to fill MET term \"" << softKey <<
"\"");
484 return StatusCode::FAILURE;
489 metSoftClus, coreSoftClus,
490 metSoftTrk, coreSoftTrk,
495 const std::string& softKey,
502 ATH_MSG_VERBOSE(
"Rebuild jet term: " << metJetKey <<
" and soft term: " << softKey);
506 ATH_MSG_ERROR(
"failed to fill MET term \"" << metJetKey <<
"\"");
507 return StatusCode::FAILURE;
513 const MissingET* coreSoft = (*metCoreCont)[softKey+
"Core"];
516 return StatusCode::FAILURE;
518 coreSoftTrk = coreSoft;
520 metSoftTrk =
nullptr;
521 if(
fillMET(metSoftTrk , metCont, softKey , coreSoftTrk->
source()) != StatusCode::SUCCESS) {
522 ATH_MSG_ERROR(
"failed to fill MET term \"" << softKey <<
"\"");
523 return StatusCode::FAILURE;
527 metSoftTrk, coreSoftTrk,
532 const std::string& softClusKey,
533 const std::string& softTrkKey,
544 ATH_MSG_ERROR(
"failed to fill MET term \"" << metJetKey <<
"\"");
545 return StatusCode::FAILURE;
548 const MissingET* coreSoftClus = (*metCoreCont)[softClusKey+
"Core"];
550 const MissingET* coreSoftTrk = (*metCoreCont)[softTrkKey+
"Core"];
552 ATH_MSG_WARNING(
"Invalid cluster soft term key supplied: " << softClusKey);
553 return StatusCode::FAILURE;
556 ATH_MSG_WARNING(
"Invalid track soft term key supplied: " << softTrkKey);
557 return StatusCode::FAILURE;
560 if(
fillMET(metSoftClus, metCont, softClusKey, coreSoftClus->
source()) != StatusCode::SUCCESS) {
561 ATH_MSG_ERROR(
"failed to fill MET term \"" << softClusKey <<
"\"");
562 return StatusCode::FAILURE;
566 if(
fillMET(metSoftTrk, metCont, softTrkKey, coreSoftTrk->
source()) != StatusCode::SUCCESS) {
567 ATH_MSG_ERROR(
"failed to fill MET term \"" << softTrkKey <<
"\"");
568 return StatusCode::FAILURE;
572 metSoftClus, coreSoftClus,
573 metSoftTrk, coreSoftTrk,
585 bool tracksForHardJets,
586 std::vector<const xAOD::IParticle*>* softConst)
const {
587 if(!metJet || !
jets) {
589 <<
"MET (" << metJet <<
") or "
590 <<
"jet collection (" <<
jets <<
").");
591 return StatusCode::FAILURE;
595 ATH_MSG_ERROR(
"MET Association Helper isn't associated with a MissingETAssociationMap!");
596 return StatusCode::FAILURE;
599 ATH_MSG_WARNING(
"Requested soft track element links, but no track selection tool supplied.");
604 ATH_MSG_WARNING(
"Incomplete association map received. Cannot rebuild MET.");
605 ATH_MSG_WARNING(
"Note: METMaker should only be run on events containing at least one PV");
606 return StatusCode::SUCCESS;
609 if(doJetJVT &&
m_JvtWP ==
"None"){
615 if(!metSoftClus && !metSoftTrk) {
616 ATH_MSG_WARNING(
"Neither soft cluster nor soft track term has been supplied!");
617 return StatusCode::SUCCESS;
621 dec_constitObjLinks(*metSoftClus) = std::vector<iplink_t>(0);
623 ATH_MSG_ERROR(
"Soft cluster term provided without a core term!");
624 return StatusCode::FAILURE;
628 <<
", mpy " << coreSoftClus->
mpy()
629 <<
" sumet " << coreSoftClus->
sumet());
630 *metSoftClus += *coreSoftClus;
634 if(softConst && acc_softConst.
isAvailable(*coreSoftClus)) {
635 for(
const auto& constit : acc_softConst(*coreSoftClus)) {
636 softConst->push_back(*constit);
638 ATH_MSG_DEBUG(softConst->size() <<
" soft constituents from core term");
642 dec_constitObjLinks(*metSoftTrk) = std::vector<iplink_t>(0);
644 ATH_MSG_ERROR(
"Soft track term provided without a core term!");
645 return StatusCode::FAILURE;
649 <<
", mpy " << coreSoftTrk->
mpy()
650 <<
" sumet " << coreSoftTrk->
sumet());
651 *metSoftTrk += *coreSoftTrk;
653 for(
const auto& constit : acc_softConst(*coreSoftTrk)) {
654 softConst->push_back(*constit);
656 ATH_MSG_DEBUG(softConst->size() <<
" soft constituents from trk core term");
660 dec_constitObjLinks(*metJet) = std::vector<iplink_t>(0);
661 dec_constitObjWeights(*metJet) = std::vector<float>(0);
662 std::vector<iplink_t>& uniqueLinks = dec_constitObjLinks(*metJet);
663 std::vector<float>& uniqueWeights = dec_constitObjWeights(*metJet);
664 uniqueLinks.reserve(
jets->size());
665 uniqueWeights.reserve(
jets->size());
666 std::vector<iplink_t> softJetLinks;
667 std::vector<float> softJetWeights;
668 bool originalInputs =
jets->empty() ? false : !acc_originalObject.isAvailable(*
jets->front());
681 return StatusCode::FAILURE;
693 if(!assoc || assoc->
isMisc()){
700 if (acc_nominalObject.isAvailable(*
jet)){
706 ATH_MSG_ERROR(
"No nominal calibrated jet available for jet " <<
jet->index() <<
". Cannot simplify overlap removal!");
711 bool JVT_reject(
false);
712 bool isMuFSRJet(
false);
721 ATH_MSG_VERBOSE(
"Jet " << (JVT_reject ?
"fails" :
"passes") <<
" JVT selection");
728 bool caloverlap =
false;
729 caloverlap = calvec.
ce()>0;
730 ATH_MSG_DEBUG(
"Jet " <<
jet->index() <<
" is " << ( caloverlap ?
"" :
"non-") <<
"overlapping");
733 for(
const auto&
object : assoc->
objects()) {
750 double jpx = constjet.Px();
751 double jpy = constjet.Py();
752 double jpt = constjet.Pt();
753 double opx = jpx - calvec.
cpx();
754 double opy = jpy - calvec.
cpy();
760 met_muonEloss = (*metCont)[
"MuonEloss"];
762 ATH_MSG_WARNING(
"Attempted to apply muon Eloss correction, but corresponding MET term does not exist!");
763 return StatusCode::FAILURE;
767 float total_eloss(0);
769 std::vector<const xAOD::Muon*> muons_in_jet;
770 std::vector<const xAOD::Electron*> electrons_in_jet;
771 bool passJetForEl=
false;
773 if(!acc_ghostMuons.isAvailable(*
jet)){
775 return StatusCode::FAILURE;
777 for(
const auto&
el : acc_ghostMuons(*
jet)) {
779 ATH_MSG_ERROR(
"Invalid element link to ghost muon! Quitting.");
780 return StatusCode::FAILURE;
782 muons_in_jet.push_back(
static_cast<const xAOD::Muon*
>(*
el));
791 if(acc_originalObject.isAvailable(*mu_test)) mu_test =
static_cast<const xAOD::Muon*
>(*acc_originalObject(*mu_test));
793 muons_in_jet.push_back(mu_test);
800 if(acc_originalObject.isAvailable(*el_test)) el_test =
static_cast<const xAOD::Electron*
>(*acc_originalObject(*el_test));
801 if(
helper.objSelected(assoc,el_test)){
802 if(el_test->
pt()>90.0e3) {
803 electrons_in_jet.push_back(el_test);
812 float jet_all_trk_pt = initialTrkMom.
sumpt();
813 float jet_unique_trk_pt = jet_all_trk_pt - jet_ORtrk_sumpt;
816 for(
const auto& elec : electrons_in_jet) {
817 el_calvec += assoc->
calVec(elec);
818 el_trkvec += assoc->
trkVec(elec);
820 float el_cal_pt = el_calvec.
cpt();
821 float el_trk_pt = el_trkvec.
cpt();
823 <<
" jetalltrk: " << jet_all_trk_pt
824 <<
" jetORtrk: " << jet_ORtrk_sumpt
825 <<
" electrk-jetORtrk: " << (el_trk_pt-jet_ORtrk_sumpt)
826 <<
" elec cal: " << el_cal_pt
827 <<
" jetalltrk-electrk: " << (jet_all_trk_pt-el_trk_pt)
828 <<
" jetalltrk-jetORtrk: " << (jet_all_trk_pt-jet_ORtrk_sumpt) );
832 if(el_trk_pt>1
e-9 && jet_unique_trk_pt>10.0
e3) passJetForEl=
true;
835 for(
const xAOD::Muon* mu_in_jet : muons_in_jet) {
836 if (!mu_in_jet)
continue;
837 float mu_Eloss = acc_Eloss(*mu_in_jet);
842 float mu_id_pt = mu_in_jet->trackParticle(xAOD::Muon::InnerDetectorTrackParticle) ? mu_in_jet->trackParticle(xAOD::Muon::InnerDetectorTrackParticle)->pt() : 0.;
843 float jet_trk_sumpt = acc_trksumpt.isAvailable(*
jet) && this->
getPV() ? acc_trksumpt(*
jet)[this->
getPV()->
index()] : 0.;
846 if(0.9999*mu_id_pt>jet_trk_sumpt)
847 jet_trk_sumpt+=mu_id_pt;
848 float jet_trk_N = acc_trkN.isAvailable(*
jet) && this->
getPV() ? acc_trkN(*
jet)[this->
getPV()->
index()] : 0.;
850 ATH_MSG_VERBOSE(
"Jet has pt " <<
jet->pt() <<
", trk sumpt " << jet_trk_sumpt <<
", trk N " << jet_trk_N);
860 float mu_id_pt = mu_in_jet->trackParticle(xAOD::Muon::InnerDetectorTrackParticle) ? mu_in_jet->trackParticle(xAOD::Muon::InnerDetectorTrackParticle)->pt() : 0.;
861 float jet_trk_sumpt = acc_trksumpt.isAvailable(*
jet) && this->
getPV() ? acc_trksumpt(*
jet)[this->
getPV()->
index()] : 0.;
863 if(0.9999*mu_id_pt>jet_trk_sumpt)
864 jet_trk_sumpt+=mu_id_pt;
865 float jet_trk_N = acc_trkN.isAvailable(*
jet) && this->
getPV() ? acc_trkN(*
jet)[this->
getPV()->
index()] : 0.;
868 if (acc_psf.isAvailable(*
jet)){
869 jet_psE = acc_psf(*
jet);
870 }
else if (acc_sampleE.isAvailable(*
jet)){
871 jet_psE = acc_sampleE(*
jet)[0] + acc_sampleE(*
jet)[4];
873 ATH_MSG_ERROR(
"Jet PS fraction or sampling energy must be available to calculate MET with doSetMuonJetEMScale");
874 return StatusCode::FAILURE;
879 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));
882 ATH_MSG_VERBOSE(
"Jet is from muon -- set to EM scale and subtract Eloss.");
885 ATH_MSG_VERBOSE(
"Jet e: " << constjet.E() <<
", mu Eloss: " << mu_Eloss);
886 float elosscorr = mu_Eloss >= constjet.e() ? 0. : 1.-mu_Eloss/constjet.e();
891 ATH_MSG_VERBOSE(
" Jet eloss factor " << elosscorr <<
", final pt: " << sqrt(opx*opx+opy*opy));
898 switch(mu_in_jet->energyLossType()) {
899 case xAOD::Muon::Parametrized:
900 case xAOD::Muon::MOP:
901 case xAOD::Muon::Tail:
902 case xAOD::Muon::FSRcandidate:
903 case xAOD::Muon::NotIsolated:
907 total_eloss += mu_Eloss;
908 muons_selflags |= (1<<assoc->
findIndex(mu_in_jet));
916 for(
size_t iKey = 0; iKey < assoc->sizeCal(); iKey++) {
922 if(
m_muEloss) mu_calovec *= std::max<float>(0.,1-(total_eloss/mu_calovec.
ce()));
927 ATH_MSG_VERBOSE(
"Jet " <<
jet->index() <<
" const pT after OR " << sqrt(opx*opx+opy*opy));
928 opx += mu_calovec.
cpx();
929 opy += mu_calovec.
cpy();
930 double opt = sqrt( opx*opx+opy*opy );
931 ATH_MSG_VERBOSE(
"Jet " <<
jet->index() <<
" const pT diff after OR readding muon clusters " <<
opt-jpt);
932 double uniquefrac = 1. - (calvec.
ce() - mu_calovec.
ce()) / constjet.E();
933 ATH_MSG_VERBOSE(
"Jet constscale px, py, pt, E = " << jpx <<
", " << jpy <<
", " << jpt <<
", " << constjet.E() );
935 ATH_MSG_VERBOSE(
"Jet OR px, py, pt, E = " << opx <<
", " << opy <<
", " <<
opt <<
", " << constjet.E() - calvec.
ce() );
939 ATH_MSG_ERROR(
"Attempted to apply muon Eloss correction, but corresponding MET term does not exist!");
940 return StatusCode::FAILURE;
942 met_muonEloss->
add(opx,opy,
opt);
946 if(selected && !JVT_reject) {
950 if (!tracksForHardJets) {
952 metJet->
add(jpx,jpy,jpt);
960 if(!tracksForHardJets) {
965 double jesF =
jet->pt() / jpt;
966 metJet->
add(opx*jesF,opy*jesF,
opt*jesF);
970 metJet->
add(uniquefrac*jpx,uniquefrac*jpy,uniquefrac*jpt);
975 metJet->
add(uniquefrac*
jet->px(),uniquefrac*
jet->py(),uniquefrac*
jet->pt());
994 uniqueLinks.push_back( jetLink );
995 uniqueWeights.push_back( uniquefrac );
997 if(metSoftClus && !JVT_reject) {
1001 softJetLinks.push_back( jetLink );
1002 softJetWeights.push_back( uniquefrac );
1003 metSoftClus->
add(opx,opy,
opt);
1012 for(
size_t iConst=0; iConst<
jet->numConstituents(); ++iConst) {
1013 const IParticle* constit =
jet->rawConstituent(iConst);
1014 softConst->push_back(constit);
1020 if(!metSoftTrk || (hardJet && !tracksForHardJets))
continue;
1026 if(jettrkvec.
ce()>1
e-9) {
1027 jpx = jettrkvec.
cpx();
1028 jpy = jettrkvec.
cpy();
1029 jpt = jettrkvec.
sumpt();
1030 jettrkvec -= trkvec;
1031 opx = jettrkvec.
cpx();
1032 opy = jettrkvec.
cpy();
1034 ATH_MSG_VERBOSE(
"Jet track px, py, sumpt = " << jpx <<
", " << jpy <<
", " << jpt );
1037 opx = opy =
opt = 0;
1040 if (hardJet) metJet->
add(opx,opy,
opt);
1042 metSoftTrk->
add(opx,opy,
opt);
1045 softJetLinks.push_back( jetLink );
1046 softJetWeights.push_back( uniquefrac );
1055 std::vector<const IParticle*> jettracks;
1057 for(
size_t iConst=0; iConst<jettracks.size(); ++iConst) {
1065 ATH_MSG_DEBUG(
"Number of selected jets: " << dec_constitObjLinks(*metJet).size());
1068 dec_constitObjLinks(*metSoftTrk) = softJetLinks;
1069 ATH_MSG_DEBUG(
"Number of softtrk jets: " << dec_constitObjLinks(*metSoftTrk).size());
1073 dec_constitObjLinks(*metSoftClus) = softJetLinks;
1074 ATH_MSG_DEBUG(
"Number of softclus jets: " << dec_constitObjLinks(*metSoftClus).size());
1077 if(softConst)
ATH_MSG_DEBUG(softConst->size() <<
" soft constituents from core term + jets");
1080 if(!assoc)
return StatusCode::SUCCESS;
1086 double opx = trkvec.
cpx();
1087 double opy = trkvec.
cpy();
1088 double osumpt = trkvec.
sumpt();
1089 ATH_MSG_VERBOSE(
"Misc track px, py, sumpt = " << opx <<
", " << opy <<
", " << osumpt );
1090 metSoftTrk->
add(opx,opy,osumpt);
1092 <<
", mpy " << metSoftTrk->
mpy()
1093 <<
" sumet " << metSoftTrk->
sumet());
1099 float total_eloss(0.);
1102 double opx = calvec.
cpx();
1103 double opy = calvec.
cpy();
1104 double osumpt = calvec.
sumpt();
1108 if(acc_originalObject.isAvailable(*mu_test)) mu_test =
static_cast<const xAOD::Muon*
>(*acc_originalObject(*mu_test));
1110 float mu_Eloss = acc_Eloss(*mu_test);
1112 case xAOD::Muon::Parametrized:
1113 case xAOD::Muon::MOP:
1114 case xAOD::Muon::Tail:
1115 case xAOD::Muon::FSRcandidate:
1116 case xAOD::Muon::NotIsolated:
1120 total_eloss += mu_Eloss;
1121 muons_selflags |= (1<<assoc->
findIndex(mu_test));
1131 for(
size_t iKey = 0; iKey < assoc->sizeCal(); iKey++) {
1134 <<
" this calvec E: " << assoc->
calVec(iKey).
ce());
1138 mu_calovec *= std::max<float>(0.,1-(total_eloss/mu_calovec.
ce()));
1139 opx += mu_calovec.
cpx();
1140 opy += mu_calovec.
cpy();
1141 osumpt += mu_calovec.
sumpt();
1145 ATH_MSG_VERBOSE(
"Misc cluster px, py, sumpt = " << opx <<
", " << opy <<
", " << osumpt );
1146 metSoftClus->
add(opx,opy,osumpt);
1148 <<
", mpy " << metSoftClus->
mpy()
1149 <<
" sumet " << metSoftClus->
sumet());
1152 return StatusCode::SUCCESS;
1160 bool doJetJVT)
const {
1170 if(
fillMET(
met,metCont,
"Invisibles" , invisSource) != StatusCode::SUCCESS) {
1172 return StatusCode::FAILURE;
1179 return static_cast<bool>(
m_trkseltool->accept( *trk, vx ));
1187 ATH_MSG_WARNING(
"Unable to retrieve primary vertex container PrimaryVertices");
1190 ATH_MSG_DEBUG(
"Successfully retrieved primary vertex container");