ATLAS Offline Software
Loading...
Searching...
No Matches
HLTCalo_L2CaloEMClustersMonitor.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
10
11template <typename T> struct clus_kin {
12 double et;
13 double eta;
14 double phi;
16};
17
18HLTCalo_L2CaloEMClustersMonitor::HLTCalo_L2CaloEMClustersMonitor( const std::string& name, ISvcLocator* pSvcLocator )
19 : AthMonitorAlgorithm(name,pSvcLocator)
20{
21 declareProperty("HLTContainer", m_HLT_cont_key = "HLT_FastCaloEMClusters");
22 declareProperty("OFFContainer", m_OFF_cont_key = "egammaClusters");
23 declareProperty("MonGroupName", m_mongroup_name = "TrigCaloMonitor");
24 declareProperty("HLTChainsT0", m_hltChainsT0 = "All");
25 declareProperty("OFFTypes", m_OFF_types);
26 declareProperty("HLThighET", m_HLT_high_et = 10000.0);
27 declareProperty("HLTMinET", m_HLT_min_et = -1.0);
28 declareProperty("OFFMinET", m_OFF_min_et = -1.0);
29 declareProperty("MaxDeltaR", m_max_delta_r = 0.04);
30}
31
32
40
41
42StatusCode HLTCalo_L2CaloEMClustersMonitor::fillHistograms( const EventContext& ctx ) const {
43 using namespace Monitored;
44
45 // Protect against noise bursts
47 ATH_CHECK(thisEvent.isValid());
48 if ( thisEvent->isEventFlagBitSet(xAOD::EventInfo::LAr,LArEventBitInfo::NOISEBURSTVETO))
49 return StatusCode::SUCCESS;
50
51 // Get HLT cluster collections
53 if (! hltCluster_readHandle.isValid() ) {
54 ATH_MSG_ERROR("evtStore() does not contain a cluster Collection with key " << m_HLT_cont_key);
55 return StatusCode::FAILURE;
56 }
57
58 // Get OFF cluster collections
60 if (! offCluster_readHandle.isValid() ) {
61 ATH_MSG_ERROR("evtStore() does not contain a cluster Collection with key " << m_OFF_cont_key);
62 return StatusCode::FAILURE;
63 }
64
65 // Bunch crossing
66 int bcid = ctx.eventID().bunch_crossing_id();
67 auto HLT_bc = Monitored::Scalar<int>("HLT_bc",-1);
68
70 if (!bcidHdl.isValid()) {
71 ATH_MSG_ERROR( "Unable to retrieve BunchCrossing conditions object" );
72 return StatusCode::FAILURE;
73 }
74 const BunchCrossingCondData* bcData=*bcidHdl;
76
77
78
80 // Cache expensive et, eta and phi //
81 // calculations for the clusters //
83
84 // prepare HLT clusters
85 std::vector<clus_kin<const xAOD::TrigEMCluster*> > vec_hlt_clusters;
86 std::vector<const xAOD::TrigEMCluster*> accepted_hlt_clusters = ifStepPassed(m_hltChainsT0);
87
88 // For monitoring all hlt clusters
89 if(m_hltChainsT0 == "All"){
90 for (const auto hlt_cluster : *hltCluster_readHandle) {
91 auto hlt_clus_et = hlt_cluster->et();
92 if (hlt_clus_et < m_HLT_min_et) continue;
93 vec_hlt_clusters.push_back({hlt_clus_et*0.001, hlt_cluster->eta(), hlt_cluster->phi(), hlt_cluster});
94 }
95 }
96 // For monitoring signature specific clusters
97 else if (accepted_hlt_clusters.size()>0){
98 for (const auto* hlt_cluster : accepted_hlt_clusters) {
99 auto hlt_clus_et = hlt_cluster->et();
100 if (hlt_clus_et < m_HLT_min_et) continue;
101 vec_hlt_clusters.push_back({hlt_clus_et*0.001, hlt_cluster->eta(), hlt_cluster->phi(), hlt_cluster});
102 }
103 }
104 // prepare OFF clusters
105 std::vector<clus_kin<const xAOD::CaloCluster*> > vec_off_clusters;
106 for (const auto off_cluster : *offCluster_readHandle) {
107 auto off_clus_et = off_cluster->et();
108 if (off_clus_et < m_OFF_min_et) continue;
109
110 bool OFF_type_match = false;
111
112 for (unsigned int n = 0; n < m_OFF_types.size(); ++n) {
113 if (off_cluster->clusterSize() == m_OFF_types[n]) { OFF_type_match = true; break; }
114 }
115
116 if (!m_OFF_types.empty() && !OFF_type_match) continue;
117
118 vec_off_clusters.push_back({off_clus_et*0.001, off_cluster->eta(), off_cluster->phi(), off_cluster});
119 }
120
122 // HLT CLUSTERS //
124
125 unsigned int n_hlt_clusters = 0;
126 unsigned int n_hlt_barrel_high_et_clusters = 0;
127 unsigned int n_hlt_clusters_no_match = 0;
128 unsigned int n_hlt_clusters_with_match = 0;
129
130 // All HLT clusters
131 auto HLT_num = Monitored::Scalar<int>("HLT_num",0);
132 auto HLT_et = Monitored::Collection("HLT_et", vec_hlt_clusters, &clus_kin<const xAOD::TrigEMCluster*>::et);
133 auto HLT_eta = Monitored::Collection("HLT_eta", vec_hlt_clusters, &clus_kin<const xAOD::TrigEMCluster*>::eta);
134 auto HLT_phi = Monitored::Collection("HLT_phi", vec_hlt_clusters, &clus_kin<const xAOD::TrigEMCluster*>::phi);
135 auto HLT_size = Monitored::Collection("HLT_size", vec_hlt_clusters, []( const clus_kin<const xAOD::TrigEMCluster*>& clus) { return clus.parent->nCells(); } );
136
137 // HLT cut masks
138 std::vector<char> vec_hlt_barrel_high_et, vec_hlt_no_off_match, vec_hlt_with_off_match;
139 auto HLT_barrel_high_et = Monitored::Collection("HLT_barrel_high_et", vec_hlt_barrel_high_et);
140 auto HLT_no_OFF_match = Monitored::Collection("HLT_no_OFF_match", vec_hlt_no_off_match);
141 auto HLT_with_OFF_match = Monitored::Collection("HLT_with_OFF_match", vec_hlt_with_off_match);
142
143 auto HLT_barrel_high_et_num = Monitored::Scalar<int>("HLT_barrel_high_et_num",0);
144 auto HLT_no_OFF_match_num = Monitored::Scalar<int>("HLT_no_OFF_match_num",0);
145 auto HLT_with_OFF_match_num = Monitored::Scalar<int>("HLT_with_OFF_match_num",0);
146
147 // HLT clusters vs. OFF clusters
148 std::vector<float> vec_hlt_vs_off_minimum_delta_r, vec_hlt_vs_off_delta_eta, vec_hlt_vs_off_delta_phi, vec_hlt_vs_off_resolution, vec_off_match_et;
149
150 auto HLT_matched_fraction = Monitored::Scalar<float>("HLT_matched_fraction", 0.0);
151 auto HLT_vs_OFF_minimum_delta_r = Monitored::Collection("HLT_vs_OFF_minimum_delta_r", vec_hlt_vs_off_minimum_delta_r);
152 auto HLT_vs_OFF_minimum_delta_eta = Monitored::Collection("HLT_vs_OFF_minimum_delta_eta", vec_hlt_vs_off_delta_eta);
153 auto HLT_vs_OFF_minimum_delta_phi = Monitored::Collection("HLT_vs_OFF_minimum_delta_phi", vec_hlt_vs_off_delta_phi);
154 auto HLT_vs_OFF_resolution = Monitored::Collection("HLT_vs_OFF_resolution", vec_hlt_vs_off_resolution);
155 auto OFF_match_et = Monitored::Collection("OFF_match_et", vec_off_match_et);
156
157 const clus_kin<const xAOD::CaloCluster*> *off_match = nullptr; // For matching
158
159 // Loop over HLT clusters
160
161 for (const auto& hlt_cluster : vec_hlt_clusters) {
162
163 ++n_hlt_clusters;
164
165 // high-ET clusters
166 if (hlt_cluster.et > (m_HLT_high_et*0.001) && fabs(hlt_cluster.eta) < 2.5) {
167
168 ++n_hlt_barrel_high_et_clusters;
169
170 vec_hlt_barrel_high_et.push_back(1);
171 }
172 else vec_hlt_barrel_high_et.push_back(0);
173
174 // matching HLT clusters to OFF clusters
175
176 float min_delta_r = 999999.9;
177
178 for (const auto& off_cluster : vec_off_clusters) {
179
180 float delta_r = calculateDeltaR(m_max_delta_r, hlt_cluster.eta, hlt_cluster.phi, off_cluster.eta, off_cluster.phi);
181
182 if (delta_r < min_delta_r) {
183
184 min_delta_r = delta_r;
185 off_match = &off_cluster;
186 }
187
188 } // End loop over OFF clusters
189
190 vec_hlt_vs_off_minimum_delta_r.push_back(min_delta_r);
191
192 // No OFF match
193 if (min_delta_r >= m_max_delta_r) {
194
195 ++n_hlt_clusters_no_match;
196
197 vec_off_match_et.push_back(0.);
198 vec_hlt_vs_off_resolution.push_back(0.);
199 vec_hlt_vs_off_delta_eta.push_back(0.);
200 vec_hlt_vs_off_delta_phi.push_back(0.);
201
202 vec_hlt_no_off_match.push_back(1);
203 vec_hlt_with_off_match.push_back(0);
204 }
205
206 // With OFF match
207 else {
208
209 ++n_hlt_clusters_with_match;
210
211 vec_off_match_et.push_back(off_match->et);
212 vec_hlt_vs_off_resolution.push_back(((off_match->et - hlt_cluster.et) / off_match->et) * 100);
213 vec_hlt_vs_off_delta_eta.push_back(off_match->eta - hlt_cluster.eta);
214 vec_hlt_vs_off_delta_phi.push_back(std::abs(CxxUtils::deltaPhi(off_match->phi, hlt_cluster.phi)));
215
216 vec_hlt_no_off_match.push_back(0);
217 vec_hlt_with_off_match.push_back(1);
218 }
219
220 } // End loop over HLT clusters
221
222 HLT_num = n_hlt_clusters;
223 HLT_barrel_high_et_num = n_hlt_barrel_high_et_clusters;
224 HLT_no_OFF_match_num = n_hlt_clusters_no_match;
225 HLT_with_OFF_match_num = n_hlt_clusters_with_match;
226 if (n_hlt_clusters>0) {
227 HLT_matched_fraction = static_cast<float>(n_hlt_clusters_with_match) / n_hlt_clusters;
228 }
229
231 // OFF CLUSTERS //
233
234 unsigned int n_off_clusters = 0;
235 unsigned int n_off_clusters_no_match = 0;
236 unsigned int n_off_clusters_with_match = 0;
237
238 // OFF cluster
239 auto OFF_num = Monitored::Scalar<int>("OFF_num",0);
240 auto OFF_et = Monitored::Collection("OFF_et", vec_off_clusters, &clus_kin<const xAOD::CaloCluster*>::et);
241 auto OFF_eta = Monitored::Collection("OFF_eta", vec_off_clusters, &clus_kin<const xAOD::CaloCluster*>::eta);
242 auto OFF_phi = Monitored::Collection("OFF_phi", vec_off_clusters, &clus_kin<const xAOD::CaloCluster*>::phi);
243 auto OFF_type = Monitored::Collection("OFF_type", vec_off_clusters, []( const clus_kin<const xAOD::CaloCluster*>& clus) { return clus.parent->clusterSize(); } );
244
245 // cut masks
246 std::vector<char> vec_off_no_hlt_match, vec_off_with_hlt_match;
247 auto OFF_no_HLT_match = Monitored::Collection("OFF_no_HLT_match", vec_off_no_hlt_match);
248 auto OFF_with_HLT_match = Monitored::Collection("OFF_with_HLT_match", vec_off_with_hlt_match);
249
250 auto OFF_no_HLT_match_num = Monitored::Scalar<int>("OFF_no_HLT_match_num",0);
251 auto OFF_with_HLT_match_num = Monitored::Scalar<int>("OFF_with_HLT_match_num",0);
252
253 // OFF clusters vs. HLT clusters
254 std::vector<float> vec_off_vs_hlt_minimum_delta_r, vec_off_vs_hlt_delta_eta, vec_off_vs_hlt_delta_phi, vec_off_vs_hlt_resolution, vec_hlt_match_et;
255
256 auto OFF_matched_fraction = Monitored::Scalar<float>("OFF_matched_fraction", 0.0);
257 auto OFF_vs_HLT_minimum_delta_r = Monitored::Collection("OFF_vs_HLT_minimum_delta_r", vec_off_vs_hlt_minimum_delta_r);
258 auto OFF_vs_HLT_minimum_delta_eta = Monitored::Collection("OFF_vs_HLT_minimum_delta_eta", vec_off_vs_hlt_delta_eta);
259 auto OFF_vs_HLT_minimum_delta_phi = Monitored::Collection("OFF_vs_HLT_minimum_delta_phi", vec_off_vs_hlt_delta_phi);
260 auto OFF_vs_HLT_resolution = Monitored::Collection("OFF_vs_HLT_resolution", vec_off_vs_hlt_resolution);
261 auto HLT_match_et = Monitored::Collection("HLT_match_et", vec_hlt_match_et);
262
263 const clus_kin<const xAOD::TrigEMCluster*> *hlt_match = nullptr; // For matching
264
265 // Loop over OFF clusters
266
267 for (const auto& off_cluster : vec_off_clusters) {
268
269 ++n_off_clusters;
270
271 // matching HLT clusters to OFF clusters
272
273 float min_delta_r = 999999.9;
274
275 for (const auto& hlt_cluster : vec_hlt_clusters) {
276
277 float delta_r = calculateDeltaR(m_max_delta_r, off_cluster.eta, off_cluster.phi, hlt_cluster.eta, hlt_cluster.phi);
278
279 if (delta_r < min_delta_r) {
280
281 min_delta_r = delta_r;
282 hlt_match = &hlt_cluster; // avoid HLT double counts?
283 }
284
285 } // End loop over HLT clusters
286
287 vec_off_vs_hlt_minimum_delta_r.push_back(min_delta_r);
288
289 // No HLT match
290 if (min_delta_r >= m_max_delta_r) {
291
292 ++n_off_clusters_no_match;
293
294 vec_hlt_match_et.push_back(0.);
295
296 vec_off_vs_hlt_resolution.push_back(0.);
297 vec_off_vs_hlt_delta_eta.push_back(0.);
298 vec_off_vs_hlt_delta_phi.push_back(0.);
299
300 vec_off_no_hlt_match.push_back(1);
301 vec_off_with_hlt_match.push_back(0);
302 }
303
304 // With HLT match
305 else {
306
307 ++n_off_clusters_with_match;
308
309 vec_hlt_match_et.push_back(hlt_match->et);
310
311 vec_off_vs_hlt_resolution.push_back(((off_cluster.et - hlt_match->et) / off_cluster.et) * 100);
312 vec_off_vs_hlt_delta_eta.push_back(off_cluster.eta - hlt_match->eta);
313 vec_off_vs_hlt_delta_phi.push_back(std::abs(CxxUtils::deltaPhi(off_cluster.phi, hlt_match->phi)));
314
315 vec_off_no_hlt_match.push_back(0);
316 vec_off_with_hlt_match.push_back(1);
317 }
318
319 } // End loop over OFF clusters
320
321 OFF_num = n_off_clusters;
322 OFF_no_HLT_match_num = n_off_clusters_no_match;
323 OFF_with_HLT_match_num = n_off_clusters_with_match;
324 if (n_off_clusters>0) {
325 OFF_matched_fraction = static_cast<float>(n_off_clusters_with_match) / n_off_clusters;
326 }
327
328 if(m_hltChainsT0 == "All") {
329 ATH_MSG_DEBUG("Filling for : "<<m_hltChainsT0);
331 // HLT clusters
332 HLT_num, HLT_et, HLT_eta, HLT_phi, HLT_size, HLT_barrel_high_et_num, HLT_bc,
333
334 // HLT cutmasks
335 HLT_barrel_high_et, HLT_no_OFF_match, HLT_with_OFF_match,
336
337 // OFF clusters
338 OFF_num, OFF_et, OFF_eta, OFF_phi, OFF_type,
339
340 // OFF cutmasks
341 OFF_no_HLT_match, OFF_with_HLT_match,
342
343 // HLT matched to OFF
344 HLT_matched_fraction, HLT_no_OFF_match_num, HLT_vs_OFF_minimum_delta_r, HLT_with_OFF_match_num,
345 OFF_match_et, HLT_vs_OFF_resolution, HLT_vs_OFF_minimum_delta_eta, HLT_vs_OFF_minimum_delta_phi,
346
347 // OFF matched to OFF
348 OFF_matched_fraction, OFF_no_HLT_match_num, OFF_vs_HLT_minimum_delta_r, OFF_with_HLT_match_num,
349 HLT_match_et, OFF_vs_HLT_resolution, OFF_vs_HLT_minimum_delta_eta, OFF_vs_HLT_minimum_delta_phi
350 );
351 }
352 else if(accepted_hlt_clusters.size()>0){
353 ATH_MSG_DEBUG("Filling for : "<<m_hltChainsT0);
355 // HLT clusters
356 HLT_num, HLT_et, HLT_eta, HLT_phi, HLT_size, HLT_barrel_high_et_num, HLT_bc,
357
358 // HLT cutmasks
359 HLT_barrel_high_et, HLT_no_OFF_match, HLT_with_OFF_match,
360
361 // OFF clusters
362 OFF_num, OFF_et, OFF_eta, OFF_phi, OFF_type,
363
364 // OFF cutmasks
365 OFF_no_HLT_match, OFF_with_HLT_match,
366
367 // HLT matched to OFF
368 HLT_matched_fraction, HLT_no_OFF_match_num, HLT_vs_OFF_minimum_delta_r, HLT_with_OFF_match_num,
369 OFF_match_et, HLT_vs_OFF_resolution, HLT_vs_OFF_minimum_delta_eta, HLT_vs_OFF_minimum_delta_phi,
370
371 // OFF matched to OFF
372 OFF_matched_fraction, OFF_no_HLT_match_num, OFF_vs_HLT_minimum_delta_r, OFF_with_HLT_match_num,
373 HLT_match_et, OFF_vs_HLT_resolution, OFF_vs_HLT_minimum_delta_eta, OFF_vs_HLT_minimum_delta_phi
374 );
375 }
376 return StatusCode::SUCCESS;
377}
378
379
380float HLTCalo_L2CaloEMClustersMonitor::calculateDeltaR( float max_deltar, float eta_1, float phi_1, float eta_2, float phi_2 ) const {
381 // reject the match as early as possible to avoid the expensive delta r calculation
382 if (fabs(eta_1-eta_2) > max_deltar) return 99.9;
383 double DeltaPhi = std::abs(CxxUtils::deltaPhi(phi_1, phi_2));
384 if (DeltaPhi > max_deltar) return 99.9;
385 return sqrt( ((eta_1-eta_2)*(eta_1-eta_2)) + (DeltaPhi*DeltaPhi) );
386}
387
388std::vector<const xAOD::TrigEMCluster*> HLTCalo_L2CaloEMClustersMonitor::ifStepPassed(const std::string& chain) const{
389 Trig::FeatureRequestDescriptor featureRequestDescriptor;
390 featureRequestDescriptor.setChainGroup(chain);
391 featureRequestDescriptor.setCondition(TrigDefs::includeFailedDecisions);
392 std::vector<TrigCompositeUtils::LinkInfo<xAOD::TrigEMClusterContainer>> fVec = getTrigDecisionTool()->features<xAOD::TrigEMClusterContainer>(featureRequestDescriptor);
393 std::vector<const xAOD::TrigEMCluster*> clustersToMonitorForChain;
396 clustersToMonitorForChain.push_back( *(f.link) );
397 }
398 }
399 ATH_MSG_DEBUG("clustersToMonitorForChain.size(): "<<clustersToMonitorForChain.size());
400 for(auto &p: clustersToMonitorForChain)
401 ATH_MSG_DEBUG("clustersToMonitorForChain->et(): "<<p->et());
402 return clustersToMonitorForChain;
403}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading a decoration on an object.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
virtual StatusCode initialize() override
initialize
const ToolHandle< Trig::TrigDecisionTool > & getTrigDecisionTool() const
Get the trigger decision tool member.
SG::ReadHandle< xAOD::EventInfo > GetEventInfo(const EventContext &) const
Return a ReadHandle for an EventInfo object (get run/event numbers, etc.)
AthMonitorAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
int distanceFromFront(const bcid_type bcid, const BunchDistanceType type=NanoSec) const
The distance of the specific bunch crossing from the front of the train.
@ BunchCrossings
Distance in units of 25 nanoseconds.
float calculateDeltaR(float max_deltar, float eta_1, float phi_1, float eta_2, float phi_2) const
SG::ReadCondHandleKey< BunchCrossingCondData > m_bunchCrossingKey
HLTCalo_L2CaloEMClustersMonitor(const std::string &name, ISvcLocator *pSvcLocator)
SG::ReadHandleKey< xAOD::TrigEMClusterContainer > m_HLT_cont_key
SG::ReadDecorHandleKey< xAOD::EventInfo > m_eventInfoDecorKey
virtual StatusCode fillHistograms(const EventContext &ctx) const override
adds event to the monitoring histograms
std::vector< const xAOD::TrigEMCluster * > ifStepPassed(const std::string &chain) const
virtual StatusCode initialize() override
initialize
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_OFF_cont_key
Declare a monitored scalar variable.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
FeatureRequestDescriptor & setCondition(const unsigned int condition)
Set the Condition: TrigDefs::Physics - (default), only returns features from paths through the naviga...
FeatureRequestDescriptor & setChainGroup(const std::string &chainGroupName)
Set the desired Chain or Chain Group.
@ LAr
The LAr calorimeter.
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.
T deltaPhi(T phiA, T phiB)
Return difference phiA - phiB in range [-pi, pi].
Definition phihelper.h:42
Generic monitoring tool for athena components.
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
@ ACTIVE
The link was still active for one-or-more of the HLT Chains requested in the TDT.
Definition ActiveState.h:20
static const unsigned int includeFailedDecisions
Run3 synonym of alsoDeactivateTEs.
TrigEMClusterContainer_v1 TrigEMClusterContainer
Define the latest version of the trigger EM cluster container.
Helper for azimuthal angle calculations.
Helper to keep a Decision object, ElementLink and ActiveState (with respect to some requested ChainGr...
Definition LinkInfo.h:22