637 {
639 ATH_MSG_WARNING(
"Requested soft track element links, but no track selection tool supplied.");
640 }
642
643 if(
helper.map().empty()) {
644 ATH_MSG_WARNING(
"Incomplete association map received. Cannot rebuild MET.");
645 ATH_MSG_WARNING(
"Note: ColumnarMETMaker should only be run on events containing at least one PV");
646 return StatusCode::SUCCESS;
647 }
648
649 if(doJetJVT &&
m_JvtWP ==
"None"){
651 doJetJVT = false;
652 }
653
655 if(!metSoftClus && !metSoftTrk) {
656 ATH_MSG_WARNING(
"Neither soft cluster nor soft track term has been supplied!");
657 return StatusCode::SUCCESS;
658 }
659 static const SG::AuxElement::ConstAccessor<std::vector<ElementLink<IParticleContainer> > > acc_softConst("softConstituents");
660 std::optional<columnar::MetHelpers::ObjectWeightHandle<columnar::MutableMetDef,columnar::JetDef>> metSoftClusLinks;
661 if(metSoftClus) {
663 if(!coreSoftClus) {
664 ATH_MSG_ERROR(
"Soft cluster term provided without a core term!");
665 return StatusCode::FAILURE;
666 }
672
673
674
675 if(softConst && acc_softConst.isAvailable(*coreSoftClus.getXAODObject())) {
676 for(const auto& constit : acc_softConst(*coreSoftClus.getXAODObject())) {
677 softConst->push_back(*constit);
678 }
679 ATH_MSG_DEBUG(softConst->size() <<
" soft constituents from core term");
680 }
681 }
682 std::optional<columnar::MetHelpers::ObjectWeightHandle<columnar::MutableMetDef,columnar::JetDef>> metSoftTrkLinks;
683 if(metSoftTrk) {
685 if(!coreSoftTrk) {
686 ATH_MSG_ERROR(
"Soft track term provided without a core term!");
687 return StatusCode::FAILURE;
688 }
694 if(softConst && acc_softConst.isAvailable(*coreSoftTrk.getXAODObject()) && !
m_doPFlow && !
m_doSoftTruth) {
695 for(const auto& constit : acc_softConst(*coreSoftTrk.getXAODObject())) {
696 softConst->push_back(*constit);
697 }
698 ATH_MSG_DEBUG(softConst->size() <<
" soft constituents from trk core term");
699 }
700 }
701
702 columnar::MetHelpers::ObjectWeightHandle<columnar::MutableMetDef,columnar::JetDef> metJetWeights(*
this,
m_jetOutputMetWeightDecRegular,metJet,jets);
703
704
705
706
707
708
709
710
712 for(auto jet : jets) {
713 auto originalJet = jetsOriginals.getOriginal(jet);
714 auto assoc =
helper.getJetAssociation(originalJet);
717 continue;
718 }
719
721
725 }
726 else
727 ATH_MSG_ERROR(
"No nominal calibrated jet available for jet " << jet <<
". Cannot simplify overlap removal!");
728 }
730
732 bool JVT_reject(false);
733 bool isMuFSRJet(false);
734
735
737 JVT_reject = true;
738
739 if(doJetJVT) {
740
742 ATH_MSG_VERBOSE(
"Jet " << (JVT_reject ?
"fails" :
"passes") <<
" JVT selection");
743 }
744
745
747 bool hardJet(false);
749 bool caloverlap = false;
750 caloverlap = calvec.
ce()>0;
751 ATH_MSG_DEBUG(
"Jet " << jet <<
" is " << ( caloverlap ?
"" :
"non-") <<
"overlapping");
752
754 for(
const auto object :
m_assocAcc.objects(*assoc)) {
755
757 }
758 }
759
761 double constSF(1);
763 constjet =
m_assocAcc.getAlternateConstVec(*assoc);
764 } else {
769 calvec *= constSF;
770 }
771 double jpx = constjet.Px();
772 double jpy = constjet.Py();
773 double jpt = constjet.Pt();
774 double opx = jpx - calvec.
cpx();
775 double opy = jpy - calvec.
cpy();
776
779
781 if(!met_muonEloss) {
782 ATH_MSG_WARNING(
"Attempted to apply muon Eloss correction, but corresponding MET term does not exist!");
783 return StatusCode::FAILURE;
784 }
785 }
786
787 float total_eloss(0);
789 std::vector<columnar::MuonId> muons_in_jet;
790 std::vector<columnar::ElectronId> electrons_in_jet;
791 bool passJetForEl=false;
795 return StatusCode::FAILURE;
796 }
799 ATH_MSG_ERROR(
"Invalid element link to ghost muon! Quitting.");
800 return StatusCode::FAILURE;
801 }
802 muons_in_jet.push_back(*
static_cast<const xAOD::Muon*
>(*el));
803 }
804 }
805 for(
const auto obj :
m_assocAcc.objects(*assoc)) {
806 if(!obj) continue;
808 auto mu_test =
obj.tryGetVariant<columnar::MuonDef>().
value();
813 }
814 if(
helper.objSelected(mu_test)) {
815 muons_in_jet.push_back(mu_test);
817 }
818 }
820 auto el_test =
obj.tryGetVariant<columnar::ElectronDef>().
value();
824 }
825 if(
helper.objSelected(*assoc,el_test)){
827 electrons_in_jet.push_back(el_test);
829 }
830 }
831 }
832 }
835 float jet_ORtrk_sumpt =
helper.overlapTrkVec(*assoc).sumpt();
836 float jet_all_trk_pt = initialTrkMom.
sumpt();
837 float jet_unique_trk_pt = jet_all_trk_pt - jet_ORtrk_sumpt;
840 for(const auto& elec : electrons_in_jet) {
842 el_trkvec +=
m_assocAcc.trkVec(*assoc,&elec.getXAODObject());
843 }
844 float el_cal_pt = el_calvec.
cpt();
845 float el_trk_pt = el_trkvec.
cpt();
847 << " jetalltrk: " << jet_all_trk_pt
848 << " jetORtrk: " << jet_ORtrk_sumpt
849 << " electrk-jetORtrk: " << (el_trk_pt-jet_ORtrk_sumpt)
850 << " elec cal: " << el_cal_pt
851 << " jetalltrk-electrk: " << (jet_all_trk_pt-el_trk_pt)
852 << " jetalltrk-jetORtrk: " << (jet_all_trk_pt-jet_ORtrk_sumpt) );
853
854
855
856 if(el_trk_pt>1
e-9 && jet_unique_trk_pt>10.0e3) passJetForEl=
true;
857 }
858
859 for(auto mu_in_jet : muons_in_jet) {
860 float mu_Eloss =
acc_Eloss(mu_in_jet.getXAODObject());
861
862 if(!JVT_reject) {
864
865 float mu_id_pt = mu_in_jet.getXAODObject().trackParticle(xAOD::Muon::InnerDetectorTrackParticle) ? mu_in_jet.getXAODObject().trackParticle(xAOD::Muon::InnerDetectorTrackParticle)->pt() : 0.;
867
868
869 if(0.9999*mu_id_pt>jet_trk_sumpt)
870 jet_trk_sumpt+=mu_id_pt;
875 if(jet_from_muon) {
877 JVT_reject = true;
878 }
879 }
880
882
883 float mu_id_pt = mu_in_jet.getXAODObject().trackParticle(xAOD::Muon::InnerDetectorTrackParticle) ? mu_in_jet.getXAODObject().trackParticle(xAOD::Muon::InnerDetectorTrackParticle)->pt() : 0.;
885
886 if(0.9999*mu_id_pt>jet_trk_sumpt)
887 jet_trk_sumpt+=mu_id_pt;
889
890 float jet_psE = 0.;
895 } else {
896 ATH_MSG_ERROR(
"Jet PS fraction or sampling energy must be available to calculate MET with doSetMuonJetEMScale");
897 return StatusCode::FAILURE;
898 }
899
902 ATH_MSG_VERBOSE(
"Jet has trk sumpt " << jet_trk_sumpt <<
", trk N " << jet_trk_N <<
", PS E " << jet_psE <<
", width " <<
m_acc_width(jet) <<
", emfrac " <<
m_acc_emf(jet));
903
904 if(jet_from_muon) {
905 ATH_MSG_VERBOSE(
"Jet is from muon -- set to EM scale and subtract Eloss.");
906
907
908 ATH_MSG_VERBOSE(
"Jet e: " << constjet.E() <<
", mu Eloss: " << mu_Eloss);
909 float elosscorr = mu_Eloss >= constjet.e() ? 0. : 1.-mu_Eloss/constjet.e();
910
911
912 opx *= elosscorr;
913 opy *= elosscorr;
914 ATH_MSG_VERBOSE(
" Jet eloss factor " << elosscorr <<
", final pt: " << sqrt(opx*opx+opy*opy));
915
916 isMuFSRJet = true;
917 }
918 }
919 }
920
921 switch(mu_in_jet.getXAODObject().energyLossType()) {
922 using enum xAOD::Muon::EnergyLossType;
923 case Parametrized:
924 case MOP:
925 case Tail:
926 case FSRcandidate:
927 case NotIsolated:
928
929
930
931 total_eloss += mu_Eloss;
932 muons_selflags |= (1<<
m_assocAcc.findIndex(*assoc,mu_in_jet));
933 }
934 }
937
939
940 for(
size_t iKey = 0; iKey <
m_assocAcc.sizeCal(*assoc); iKey++) {
942 if(selector) mu_calovec +=
m_assocAcc.calVec(*assoc,iKey);
944 }
946 if(
m_muEloss) mu_calovec *= std::max<float>(0.,1-(total_eloss/mu_calovec.
ce()));
948
949
951 ATH_MSG_VERBOSE(
"Jet " << jet <<
" const pT after OR " << sqrt(opx*opx+opy*opy));
952 opx += mu_calovec.
cpx();
953 opy += mu_calovec.
cpy();
954 double opt = sqrt( opx*opx+opy*opy );
955 ATH_MSG_VERBOSE(
"Jet " << jet <<
" const pT diff after OR readding muon clusters " << opt-jpt);
956 double uniquefrac = 1. - (calvec.
ce() - mu_calovec.
ce()) / constjet.E();
957 ATH_MSG_VERBOSE(
"Jet constscale px, py, pt, E = " << jpx <<
", " << jpy <<
", " << jpt <<
", " << constjet.E() );
959 ATH_MSG_VERBOSE(
"Jet OR px, py, pt, E = " << opx <<
", " << opy <<
", " << opt <<
", " << constjet.E() - calvec.
ce() );
960
961 if(isMuFSRJet) {
962 if(!met_muonEloss){
963 ATH_MSG_ERROR(
"Attempted to apply muon Eloss correction, but corresponding MET term does not exist!");
964 return StatusCode::FAILURE;
965 }
967 continue;
968 }
969
970 if(selected && !JVT_reject) {
971 if(!caloverlap) {
972
973 hardJet = true;
974 if (!tracksForHardJets) {
977 else
979 }
980 }
982
983 hardJet = true;
984 if(!tracksForHardJets) {
988 else {
991 }
992 } else {
994 m_outputMetMomAcc.addParticle(metJet,uniquefrac*jpx,uniquefrac*jpy,uniquefrac*jpt);
995 else{
998 else
1000 }
1001 }
1002 }
1003 }
1004 }
1005
1006 if(hardJet){
1008 metJetWeights.emplace_back(jet, uniquefrac);
1009 } else {
1010 if(metSoftClus && !JVT_reject) {
1011
1014 metSoftClusLinks->emplace_back (jet, uniquefrac);
1016 }
1017
1018
1019
1020
1021
1022
1023 if(softConst) {
1024 for(size_t iConst=0; iConst<jet.getXAODObject().numConstituents(); ++iConst) {
1025 const IParticle* constit = jet.getXAODObject().rawConstituent(iConst);
1026 softConst->push_back(constit);
1027 }
1028 }
1029 }
1030 }
1031
1032 if(!metSoftTrk || (hardJet && !tracksForHardJets)) continue;
1033
1034
1035
1038 if(jettrkvec.
ce()>1
e-9) {
1039 jpx = jettrkvec.
cpx();
1040 jpy = jettrkvec.
cpy();
1041 jpt = jettrkvec.
sumpt();
1042 jettrkvec -= trkvec;
1043 opx = jettrkvec.
cpx();
1044 opy = jettrkvec.
cpy();
1046 ATH_MSG_VERBOSE(
"Jet track px, py, sumpt = " << jpx <<
", " << jpy <<
", " << jpt );
1047 ATH_MSG_VERBOSE(
"Jet OR px, py, sumpt = " << opx <<
", " << opy <<
", " << opt );
1048 } else {
1049 opx = opy =
opt = 0;
1051 }
1055
1056 if(!metSoftClus) {
1057 if (metSoftTrkLinks) metSoftTrkLinks->emplace_back (jet, uniquefrac);
1058 }
1059
1060
1061
1062
1063
1064
1066 std::vector<const IParticle*> jettracks;
1068 for(size_t iConst=0; iConst<jettracks.size(); ++iConst) {
1070 if (
acceptTrack(pTrk,pv)) softConst->push_back(pTrk);
1071 }
1072 }
1073 }
1074 }
1075
1076 ATH_MSG_DEBUG(
"Number of selected jets: " << metJetWeights.size());
1077
1078 if(metSoftTrk) {
1079 ATH_MSG_DEBUG(
"Number of softtrk jets: " << metSoftTrkLinks->size());
1080 }
1081
1082 if(metSoftClus) {
1083 ATH_MSG_DEBUG(
"Number of softclus jets: " << metSoftClusLinks->size());
1084 }
1085
1086 if(softConst)
ATH_MSG_DEBUG(softConst->size() <<
" soft constituents from core term + jets");
1087
1088 auto assoc =
helper.getMiscAssociation();
1089 if(!assoc) return StatusCode::SUCCESS;
1090
1091 if(metSoftTrk) {
1092
1093
1095 double opx = trkvec.
cpx();
1096 double opy = trkvec.
cpy();
1097 double osumpt = trkvec.
sumpt();
1098 ATH_MSG_VERBOSE(
"Misc track px, py, sumpt = " << opx <<
", " << opy <<
", " << osumpt );
1103 }
1104
1105 if(metSoftClus) {
1106
1107
1108 float total_eloss(0.);
1111 double opx = calvec.
cpx();
1112 double opy = calvec.
cpy();
1113 double osumpt = calvec.
sumpt();
1114 for(
const auto objId :
m_assocAcc.objects(*assoc)) {
1115 auto *
obj = objId.getXAODObject();
1119 if(
helper.objSelected(mu_test)) {
1121 switch(mu_test->energyLossType()) {
1122 using enum xAOD::Muon::EnergyLossType;
1123 case Parametrized:
1124 case MOP:
1125 case Tail:
1126 case FSRcandidate:
1127 case NotIsolated:
1128
1129
1130
1131 total_eloss += mu_Eloss;
1132 muons_selflags |= (1<<
m_assocAcc.findIndex(*assoc,mu_test));
1133 }
1135 }
1136 }
1139
1141
1142 for(
size_t iKey = 0; iKey <
m_assocAcc.sizeCal(*assoc); iKey++) {
1145 <<
" this calvec E: " <<
m_assocAcc.calVec(*assoc,iKey).ce());
1146 if(selector) mu_calovec +=
m_assocAcc.calVec(*assoc,iKey);
1147 }
1149 mu_calovec *= std::max<float>(0.,1-(total_eloss/mu_calovec.
ce()));
1150 opx += mu_calovec.
cpx();
1151 opy += mu_calovec.
cpy();
1152 osumpt += mu_calovec.
sumpt();
1153 }
1155
1156 ATH_MSG_VERBOSE(
"Misc cluster px, py, sumpt = " << opx <<
", " << opy <<
", " << osumpt );
1161 }
1162
1163 return StatusCode::SUCCESS;
1164 }
#define ATH_MSG_VERBOSE(x)
columnar::MetHelpers::MetMomentumAccessors< columnar::MutableMetDef > m_outputMetMomAcc
bool acceptTrack(const xAOD::TrackParticle *trk, const xAOD::Vertex *vx) const
columnar::JetAccessor< float > m_acc_width
columnar::JetAccessor< std::vector< int > > m_acc_trkN
columnar::MutableMetAccessor< std::string > m_outputMetNameAcc
columnar::JetAccessor< float > m_acc_emf
columnar::JetAccessor< std::vector< float > > m_acc_trksumpt
columnar::Met1Accessor< MissingETBase::Types::bitmask_t > m_inputMetSourceAcc
columnar::JetAccessor< std::vector< float > > m_acc_sampleE
columnar::JetAccessor< float > m_acc_psf
columnar::MetHelpers::ObjectWeightDecorator< columnar::MutableMetDef, columnar::JetDef > m_jetOutputMetWeightDecSoft
const xAOD::Vertex * getPV() const
columnar::MetHelpers::ObjectWeightDecorator< columnar::MutableMetDef, columnar::JetDef > m_jetOutputMetWeightDecRegular
columnar::MetHelpers::MetMomentumAccessors< columnar::Met1Def > m_inputMetMomAcc
columnar::ElectronAccessor< columnar::RetypeColumn< double, float > > m_electronPtAcc
columnar::MetHelpers::InputMomentumAccessors< columnar::JetDef > m_jetMomAcc
float ce() const
Returns .
float sumpt() const
Returns sum of component pt.
float cpt() const
Returns .
float cpx() const
Returns .
float cpy() const
Returns .
xAOD::MissingETAssociation_v1::ConstVec constvec_t
Type for constituent vector.
uint64_t bitmask_t
Type for status word bit mask.
OriginalObjectHandle(const asg::AsgTool &, ObjectRange< CI, CM >) -> OriginalObjectHandle< CI, CM >
OptObjectId< MutableMetDef > OptMutableMetId
static const SG::AuxElement::ConstAccessor< float > acc_Eloss("EnergyLoss")
static const SG::AuxElement::ConstAccessor< iplink_t > acc_nominalObject("nominalObjectLink")
static const SG::AuxElement::ConstAccessor< iplink_t > acc_originalObject("originalObjectLink")
static const SG::AuxElement::ConstAccessor< std::vector< iplink_t > > acc_ghostMuons("GhostMuon")
@ Photon
The object is a photon.
@ Muon
The object is a muon.
Jet_v1 Jet
Definition of the current "jet version".
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Muon_v1 Muon
Reference the current persistent version:
setBGCode setTAP setLVL2ErrorBits bool
Electron_v1 Electron
Definition of the current "egamma version".
ROOT::Math::LorentzVector< ROOT::Math::PtEtaPhiM4D< double > > JetFourMom_t
Base 4 Momentum type for Jet.
@ Central
Indicator for MET contribution from the central region.
static constexpr bool isXAOD
Whether this is the xAOD mode.