ATLAS Offline Software
Loading...
Searching...
No Matches
TrigTauMonitorTandPAlgorithm.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#if __GNUC__ >= 16
6// Suppress false-positive warning seen with gcc16.
7# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
8#endif
9
12
13
14TrigTauMonitorTandPAlgorithm::TrigTauMonitorTandPAlgorithm(const std::string& name, ISvcLocator* pSvcLocator)
15 : TrigTauMonitorBaseAlgorithm(name, pSvcLocator)
16{}
17
18
21
22 ATH_CHECK( m_hltElectronKey.initialize() );
23 ATH_CHECK( m_hltMuonKey.initialize() );
24
25 ATH_CHECK( m_offlineElectronKey.initialize() );
26 ATH_CHECK( m_offlineMuonKey.initialize() );
27
28 return StatusCode::SUCCESS;
29}
30
31
32std::vector<const xAOD::Electron*> TrigTauMonitorTandPAlgorithm::getOfflineElectrons(const EventContext& ctx, const float threshold) const
33{
34 std::vector<const xAOD::Electron*> el_vec;
35
37 if(!electrons.isValid()) {
38 ATH_MSG_WARNING("Failed to retrieve offline Electrons");
39 return el_vec;
40 }
41
42 for(const xAOD::Electron* el : *electrons) {
43 // Threshold selection
44 if(el->p4().Pt()/Gaudi::Units::GeV < threshold) continue;
45
46 // Select offline electrons passing good quality cuts
47 if(!(el->passSelection("LHMedium") && el->isGoodOQ(xAOD::EgammaParameters::BADCLUSELECTRON))) continue;
48
49 el_vec.push_back(el);
50 }
51
52 return el_vec;
53}
54
55
56std::vector<const xAOD::Muon*> TrigTauMonitorTandPAlgorithm::getOfflineMuons(const EventContext& ctx, const float threshold) const
57{
58 std::vector<const xAOD::Muon*> mu_vec;
59
61 if(!muons.isValid()) {
62 ATH_MSG_WARNING("Failed to retrieve offline Muons");
63 return mu_vec;
64 }
65
66 for(const xAOD::Muon* mu : *muons) {
67 // Threshold selection
68 if(mu->p4().Pt()/Gaudi::Units::GeV < threshold) continue;
69
70 // Select offline muons passing good quality cuts (quality >= Medium, but the Enum indexes are reversed...)
71 if(!(mu->quality() <= xAOD::Muon::Quality::Medium && mu->passesIDCuts())) continue;
72
73 mu_vec.push_back(mu);
74 }
75
76 return mu_vec;
77}
78
79
80std::vector<const xAOD::Electron*> TrigTauMonitorTandPAlgorithm::getOnlineElectrons(const std::string& trigger) const
81{
82 std::vector<const xAOD::Electron*> el_vec;
83
85 for(auto &featLinkInfo : vec) {
86 const auto *feat = *(featLinkInfo.link);
87 if(!feat) continue;
88 el_vec.push_back(feat);
89 }
90
91 return el_vec;
92}
93
94
95std::vector<const xAOD::Muon*> TrigTauMonitorTandPAlgorithm::getOnlineMuons(const std::string& trigger) const
96{
97 std::vector<const xAOD::Muon*> mu_vec;
98
99 auto vec = m_trigDecTool->features<xAOD::MuonContainer>(trigger, TrigDefs::Physics, m_hltMuonKey.key());
100 for(auto &featLinkInfo : vec) {
101 const auto *feat = *(featLinkInfo.link);
102 if(!feat) continue;
103 mu_vec.push_back(feat);
104 }
105
106 return mu_vec;
107}
108
109
110StatusCode TrigTauMonitorTandPAlgorithm::processEvent(const EventContext& ctx) const
111{
112 constexpr float threshold_offset = 10.0;
113
114 // Offline taus
115 auto offline_taus_all = getOfflineTausAll(ctx, 0.0);
116 if(m_requireOfflineTaus && offline_taus_all.empty()) return StatusCode::SUCCESS;
117
118 for(const std::string& trigger : m_triggers) {
119 const TrigTauInfo& info = getTrigInfo(trigger);
120
121 if(!info.isHLTTandP()) {
122 ATH_MSG_WARNING("Chain \"" << trigger << "\" is not a Tag and Probe trigger. Skipping...");
123 continue;
124 }
125
126 const auto passBits = m_trigDecTool->isPassedBits(trigger);
127 const bool l1_accept_flag = passBits & TrigDefs::L1_isPassedAfterVeto;
128 const bool hlt_not_prescaled_flag = (passBits & TrigDefs::EF_prescaled) == 0;
129
130 // Offline tau requirement check
131 std::vector<const xAOD::TauJet*> offline_taus_with_id = classifyTausAll(ctx, offline_taus_all, 0, static_cast<TauID>(m_offline_tau_id.value()));
132 if(m_requireOfflineTaus && offline_taus_with_id.empty()) continue;
133
134 // Filter offline taus
135 std::vector<const xAOD::TauJet*> offline_taus = classifyTausAll(ctx, offline_taus_with_id, info.getHLTTauThreshold() - threshold_offset);
136
137 // Online taus
138 std::vector<const xAOD::TauJet*> hlt_taus = getOnlineTausAll(trigger, true);
139
140 if(info.hasHLTElectronLeg()) { // Electron channel
141 // Offline Electrons
142 std::vector<const xAOD::IParticle*> offline_electrons;
143 for(const xAOD::Electron* p : getOfflineElectrons(ctx, info.getHLTElecThreshold()+1)) offline_electrons.push_back(dynamic_cast<const xAOD::IParticle*>(p));
144
145 // Overlap removal: dR(Offline Tau, Offline Electron) > 0.2
146 for(int i = offline_taus.size()-1; i >= 0; i--) {
147 bool is_match = matchObjects(offline_taus.at(i), offline_electrons, 0.2);
148 if(is_match) offline_taus.erase(offline_taus.begin() + i);
149 }
150
151 // Online Electrons
152 std::vector<const xAOD::IParticle*> hlt_electrons;
153 for(const xAOD::Electron* p : getOnlineElectrons(trigger)) hlt_electrons.push_back(dynamic_cast<const xAOD::IParticle*>(p));
154
155 if(m_do_variable_plots) fillTagAndProbeVars(trigger, hlt_taus, hlt_electrons);
156 if(m_do_efficiency_plots && l1_accept_flag && hlt_not_prescaled_flag) fillTAndPHLTEfficiencies(ctx, trigger, offline_electrons, hlt_electrons, offline_taus, hlt_taus);
157
158 } else if(info.hasHLTMuonLeg()) { // Muon channel
159 // Offline Muons
160 std::vector<const xAOD::IParticle*> offline_muons;
161 for(const xAOD::Muon* p : getOfflineMuons(ctx, info.getHLTMuonThreshold()+1)) offline_muons.push_back(dynamic_cast<const xAOD::IParticle*>(p));
162
163 // Overlap removal: dR(Offline Tau, Offline Tau) > 0.2
164 for(int i = offline_taus.size()-1; i >= 0; i--) {
165 bool is_match = matchObjects(offline_taus.at(i), offline_muons, 0.2);
166 if(is_match) offline_taus.erase(offline_taus.begin() + i);
167 }
168
169 // Online Muons
170 std::vector<const xAOD::IParticle*> hlt_muons;
171 for(const xAOD::Muon* p : getOnlineMuons(trigger)) hlt_muons.push_back(dynamic_cast<const xAOD::IParticle*>(p));
172
173 if(m_do_variable_plots) fillTagAndProbeVars(trigger, hlt_taus, hlt_muons);
174 if(m_do_efficiency_plots && l1_accept_flag && hlt_not_prescaled_flag) fillTAndPHLTEfficiencies(ctx, trigger, offline_muons, hlt_muons, offline_taus, hlt_taus);
175 }
176 }
177
178 return StatusCode::SUCCESS;
179}
180
181
182void TrigTauMonitorTandPAlgorithm::fillTAndPHLTEfficiencies(const EventContext& ctx, const std::string& trigger, const std::vector<const xAOD::IParticle*>& offline_lep_vec, const std::vector<const xAOD::IParticle*>& online_lep_vec, const std::vector<const xAOD::TauJet*>& offline_tau_vec, const std::vector<const xAOD::TauJet*>& online_tau_vec) const
183{
184 ATH_MSG_DEBUG("Fill Tag and Probe HLT efficiencies: " << trigger);
185
186 // Require 1 offline taus and 1 online taus
187 if(online_tau_vec.size() != 1 || offline_tau_vec.size() != 1) return;
188 // ...and require 1 offline lepton and 1 online lepton
189 if(online_lep_vec.size() != 1 || offline_lep_vec.size() != 1) return;
190
191 auto monGroup = getGroup(trigger+"_TAndPHLT_Efficiency");
192
193 auto tauPt = Monitored::Scalar<float>("tauPt", 0.0);
194 auto tauEta = Monitored::Scalar<float>("tauEta", 0.0);
195 auto tauPhi = Monitored::Scalar<float>("tauPhi", 0.0);
196 auto dR = Monitored::Scalar<float>("dR", 0.0);
197 auto dEta = Monitored::Scalar<float>("dEta", 0.0);
198 auto dPhi = Monitored::Scalar<float>("dPhi", 0.0);
199 auto averageMu = Monitored::Scalar<float>("averageMu", 0.0);
200 auto HLT_match = Monitored::Scalar<bool>("HLT_pass", false);
201 auto HLT_match_highPt = Monitored::Scalar<bool>("HLT_pass_highPt", false);
202
203 // efficiency denominator : 1 offline tau, 1 online tau, 1 offline lepton, 1 online lepton
204 // efficiency numerator : hlt fires + offline and online tau matched + offline and online lepton matched
205 bool hlt_fires = m_trigDecTool->isPassed(trigger, TrigDefs::Physics);
206 bool tau1_match = matchObjects(offline_tau_vec[0], online_tau_vec, 0.2);
207 bool lep1_match = matchObjects(offline_lep_vec[0], online_lep_vec, 0.2);
208
209 tauPt = offline_tau_vec[0]->pt()/Gaudi::Units::GeV;
210 tauEta = offline_tau_vec[0]->eta();
211 tauPhi = offline_tau_vec[0]->phi();
212 dR = offline_tau_vec[0]->p4().DeltaR(offline_lep_vec[0]->p4());
213 dEta = std::abs(offline_tau_vec[0]->eta() - offline_lep_vec[0]->eta());
214 dPhi = offline_tau_vec[0]->p4().DeltaPhi(offline_lep_vec[0]->p4());
215 averageMu = lbAverageInteractionsPerCrossing(ctx);
216 HLT_match = hlt_fires && tau1_match && lep1_match;
217
218 fill(monGroup, tauPt, tauEta, tauPhi, dR, dEta, dPhi, averageMu, HLT_match);
219
220 bool is_highPt = tauPt > getTrigInfo(trigger).getHLTTauThreshold() + 20.0;
221 if(is_highPt) {
222 HLT_match_highPt = static_cast<bool>(HLT_match);
223 fill(monGroup, tauEta, tauPhi, HLT_match_highPt);
224 }
225
226
227 ATH_MSG_DEBUG("After fill Tag and Probe HLT efficiencies: " << trigger);
228}
229
230
231void TrigTauMonitorTandPAlgorithm::fillTagAndProbeVars(const std::string& trigger, const std::vector<const xAOD::TauJet*>& tau_vec, const std::vector<const xAOD::IParticle*>& lep_vec) const
232{
233 ATH_MSG_DEBUG("Fill Tag & Probe Variables: " << trigger);
234
235 auto monGroup = getGroup(trigger+"_TAndPVars");
236
237 // Require 1 tau and 1 lepton
238 if(tau_vec.empty() || lep_vec.empty()) return;
239
240 auto dR = Monitored::Scalar<float>("dR", 0.0);
241 auto dEta = Monitored::Scalar<float>("dEta", 0.0);
242 auto dPhi = Monitored::Scalar<float>("dPhi", 0.0);
243 auto dPt = Monitored::Scalar<float>("dPt", 0.0);
244
245 auto Pt = Monitored::Scalar<float>("Pt", 0.0);
246 auto Eta = Monitored::Scalar<float>("Eta", 0.0);
247 auto Phi = Monitored::Scalar<float>("Phi", 0.0);
248 auto M = Monitored::Scalar<float>("M", 0.0);
249
250 // Choose a pair with dR > 0.3 to fill the plot (there must be always at least one pair with dR > 0.3 if the trigger fires)
251 uint index_tau = 0;
252 uint index_lep = 0;
253
254 for(uint i=0; i < tau_vec.size(); i++) {
255 for(uint j=0; j< lep_vec.size(); j++) {
256 if(tau_vec[i]->p4().DeltaR(lep_vec[j]->p4()) >= 0.3) {
257 index_tau = i;
258 index_lep = j;
259 }
260 }
261 }
262
263 dR = tau_vec[index_tau]->p4().DeltaR(lep_vec[index_lep]->p4());
264 dEta = std::abs(tau_vec[index_tau]->eta() - lep_vec[index_lep]->eta());
265 dPhi = tau_vec[index_tau]->p4().DeltaPhi(lep_vec[index_lep]->p4());
266 dPt = std::abs((tau_vec[index_tau]->pt() - lep_vec[index_lep]->pt())/Gaudi::Units::GeV);
267
268 TLorentzVector diTau4V = tau_vec[index_tau]->p4() + lep_vec[index_lep]->p4();
269
270 Pt = diTau4V.Pt()/Gaudi::Units::GeV;
271 Eta = diTau4V.Eta();
272 Phi = diTau4V.Phi();
273 M = diTau4V.M()/Gaudi::Units::GeV;
274
275 fill(monGroup, dR, dEta, dPhi, dPt, Pt, Eta, Phi, M);
276
277 ATH_MSG_DEBUG("After fill Tag & Probe variables: " << trigger);
278}
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::vector< size_t > vec
unsigned int uint
const ToolHandle< GenericMonitoringTool > & getGroup(const std::string &name) const
Get a specific monitoring tool from the tool handle array.
PublicToolHandle< Trig::TrigDecisionTool > m_trigDecTool
Tool to tell whether a specific trigger is passed.
Declare a monitored scalar variable.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
float getHLTTauThreshold() const
Definition TrigTauInfo.h:26
Gaudi::Property< bool > m_do_efficiency_plots
virtual StatusCode initialize() override
initialize
double dR(const double eta1, const double phi1, const double eta2, const double phi2) const
TrigTauMonitorBaseAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
std::vector< const xAOD::TauJet * > getOfflineTausAll(const EventContext &ctx, const float threshold=20.0) const
bool matchObjects(const T1 *tau, const std::vector< const T2 * > &tau_vec, float threshold) const
Gaudi::Property< std::vector< std::string > > m_triggers
const TrigTauInfo & getTrigInfo(const std::string &trigger) const
std::vector< const xAOD::TauJet * > classifyTausAll(const EventContext &ctx, const std::vector< const xAOD::TauJet * > &taus, const float threshold=0.0, const TauID tau_id=TauID::None) const
std::vector< const xAOD::TauJet * > getOnlineTausAll(const std::string &trigger, bool include_0P=true, bool filter_legs=false) const
Gaudi::Property< bool > m_do_variable_plots
SG::ReadHandleKey< xAOD::MuonContainer > m_hltMuonKey
TrigTauMonitorTandPAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
virtual StatusCode processEvent(const EventContext &ctx) const override
SG::ReadHandleKey< xAOD::ElectronContainer > m_offlineElectronKey
void fillTAndPHLTEfficiencies(const EventContext &ctx, const std::string &trigger, const std::vector< const xAOD::IParticle * > &offline_lep_vec, const std::vector< const xAOD::IParticle * > &online_lep_vec, const std::vector< const xAOD::TauJet * > &offline_tau_vec, const std::vector< const xAOD::TauJet * > &online_tau_vec) const
Gaudi::Property< unsigned int > m_offline_tau_id
std::vector< const xAOD::Electron * > getOfflineElectrons(const EventContext &ctx, const float threshold=0.0) const
std::vector< const xAOD::Muon * > getOfflineMuons(const EventContext &ctx, const float threshold=0.0) const
SG::ReadHandleKey< xAOD::ElectronContainer > m_hltElectronKey
void fillTagAndProbeVars(const std::string &trigger, const std::vector< const xAOD::TauJet * > &tau_vec, const std::vector< const xAOD::IParticle * > &lep_vec) const
std::vector< const xAOD::Muon * > getOnlineMuons(const std::string &trigger) const
std::vector< const xAOD::Electron * > getOnlineElectrons(const std::string &trigger) const
SG::ReadHandleKey< xAOD::MuonContainer > m_offlineMuonKey
virtual StatusCode initialize() override
initialize
Class providing the definition of the 4-vector interface.
void fill(const ToolHandle< GenericMonitoringTool > &groupHandle, std::vector< std::reference_wrapper< Monitored::IMonitoredVariable > > &&variables) const
Fills a vector of variables to a group by reference.
virtual float lbAverageInteractionsPerCrossing(const EventContext &ctx) const
Calculate the average mu, i.e.
const uint32_t BADCLUSELECTRON
Definition EgammaDefs.h:116
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
Muon_v1 Muon
Reference the current persistent version:
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
Electron_v1 Electron
Definition of the current "egamma version".