ATLAS Offline Software
Loading...
Searching...
No Matches
RatesAnalysisAlg.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// RatesAnalysis includes
7
9
12#include "TrigConfData/L1Menu.h"
15//uncomment the line below to use the HistSvc for outputting trees and histograms
16#include "GaudiKernel/ITHistSvc.h"
17#include "TH1.h"
19#include <sstream>
20
21
22RatesAnalysisAlg::RatesAnalysisAlg( const std::string& name, ISvcLocator* pSvcLocator ) :
23 AthAnalysisAlgorithm( name, pSvcLocator ),
27 m_targetMu(0.),
29 m_targetLumi(0.),
30 m_runNumber(0.),
33 m_scalingHist(nullptr),
34 m_bcidHist(nullptr),
35 m_metadataTree(nullptr)
36{}
37
39
40StatusCode RatesAnalysisAlg::newScanTrigger(const std::string& name,
41 const double thresholdMin,
42 const double thresholdMax,
43 const uint32_t thresholdBins,
45 const double prescale,
46 const std::string& seedName,
47 const double seedPrecale,
48 const Method_t method,
49 const ExtrapStrat_t extrapolation) {
50
51 if (method != kMANUAL) {
52 ATH_MSG_ERROR("Sorry - ScanTriggers have to be implemented with the kMANUAL method for now.");
53 return StatusCode::FAILURE;
54 }
55
57 m_scanTriggers.emplace(name, std::make_unique<RatesScanTrigger>(name, msgSvc(), thresholdMin, thresholdMax, thresholdBins, behaviour, prescale, seedName, seedPrecale, e));
59 if (isRandomSeed(name, seedName)) newScanTrigger->setSeedsFromRandom(true);
60 ATH_MSG_DEBUG("newScanTrigger " << name << " added");
61 return StatusCode::SUCCESS;
62}
63
64
65StatusCode RatesAnalysisAlg::newScanTrigger(const std::string& name,
66 const std::vector<double>& thresholdBinEdges,
68 const double prescale,
69 const std::string& seedName,
70 const double seedPrecale,
71 const Method_t method,
72 const ExtrapStrat_t extrapolation) {
73
74 if (method != kMANUAL) {
75 ATH_MSG_ERROR("Sorry - ScanTriggers have to be implemented with the kMANUAL method for now.");
76 return StatusCode::FAILURE;
77 }
78
80
81 m_scanTriggers.emplace(name, std::make_unique<RatesScanTrigger>(name, msgSvc(), thresholdBinEdges, behaviour, prescale, seedName, seedPrecale, e));
83 if (isRandomSeed(name, seedName)) newScanTrigger->setSeedsFromRandom(true);
84 ATH_MSG_DEBUG("newScanTrigger " << name << " added");
85 return StatusCode::SUCCESS;
86}
87
88
89StatusCode RatesAnalysisAlg::newTrigger(const std::string& name,
90 const double prescale,
91 const double expressPrescale,
92 const std::string& seedName,
93 const double seedPrecale,
94 const std::string& groups,
95 const Method_t method,
96 const ExtrapStrat_t extrapolation) {
97
98 std::set<std::string> groupSet;
99 std::istringstream ss(groups);
100 while (ss) {
101 std::string group;
102 if (!std::getline(ss, group, ',')) break;
103 groupSet.insert(group);
104 }
105
106 return newTrigger(name, prescale, expressPrescale, seedName, seedPrecale, groupSet, method, extrapolation);
107}
108
109StatusCode RatesAnalysisAlg::newTrigger(const std::string& name,
110 const double prescale,
111 const double expressPrescale,
112 const std::string& seedName,
113 const double seedPrecale,
114 const std::set<std::string>& groups,
115 const Method_t method,
116 const ExtrapStrat_t extrapolation) {
117
118 if (m_eventCounter > 1) { // All triggers must be defined before we start looping over the sample
119 ATH_MSG_FATAL("Too late to call newTrigger. All emulated triggers must be registered during ratesInitialize().");
120 return StatusCode::FAILURE;
121 }
122 if (method == kEXISTING) ATH_CHECK( checkExistingTrigger(name, seedName) ); // Check this agrees with what is in the AOD
123
124 // Check if it already exists
125 if (m_triggers.count(name) == 1) {
126 ATH_MSG_WARNING("Trigger " << name << " is already registered.");
127 return StatusCode::SUCCESS;
128 }
129
130 const ExtrapStrat_t e = (m_enableLumiExtrapolation ? extrapolation : ExtrapStrat_t::kNONE);
131 m_triggers.emplace(name, std::make_unique<RatesTrigger>(name, msgSvc(), prescale, expressPrescale, seedName, seedPrecale, m_doHistograms, e));
132 RatesTrigger* newTriggerPtr = m_triggers.at(name).get();
133
134 if (isRandomSeed(name, seedName)) newTriggerPtr->setSeedsFromRandom(true);
135
136 // Only worthwhile doing the remainder if the trigger is not disabled. Otherwise will slow everything down
137 if (newTriggerPtr->getDisabled()) {
138 ATH_MSG_DEBUG("newTrigger " << name << " added (disabled)");
139 return StatusCode::SUCCESS;
140 }
141
142 if (method == kAUTO) {
143 m_autoTriggers.push_back(name);
144 } else if (method == kEXISTING) {
145 m_existingTriggers[name] = m_tdt->getChainGroup(name);
146 m_lowerTrigger[name] = seedName;
147 }
148
149 // Add this trigger to its groups
150 if (m_doTriggerGroups) {
151 for (const std::string& group : groups) {
152 // Ignore BW and PS groups
153 if (group.starts_with("BW") || group.starts_with("PS") || group.starts_with("STREAM:express")) continue;
154
155 const auto [it, inserted] = m_groups.try_emplace(group, std::make_unique<RatesGroup>(group, msgSvc(), m_doHistograms, m_enableLumiExtrapolation));
156 if (inserted) {
157 // As the group is formed from at least one active trigger - it must be active itself (counter example - CPS group of a PS=-1 trigger)
158 m_activeGroups.insert( it->second.get() );
159 }
160 it->second->addToGroup( newTriggerPtr );
161 // For CPS, we let the trigger know that it is special
162 if (isCPS(group)) {
163 if (newTriggerPtr->getCPSID() != 0) ATH_MSG_WARNING("Trigger " << name << " can only be in one coherent prescale group.");
164 newTriggerPtr->setCPS(group); // This changes the CPSID
165 const size_t CPSID = newTriggerPtr->getCPSID();
166 // Find the lowest prescale of any member in this CPS group
167 m_lowestPrescale.try_emplace(CPSID, FLT_MAX);
168 if (prescale < m_lowestPrescale[CPSID]) m_lowestPrescale[CPSID] = prescale;
169 }
170 }
171 }
172
173 // Add to total rates
174 const uint32_t level = getLevel(name);
175 if (m_doGlobalGroups) {
176 if (level == 2) m_globalGroups.at(m_l2GroupName)->addToGroup( newTriggerPtr );
177 else if (level == 1) m_globalGroups.at(m_l1GroupName)->addToGroup( newTriggerPtr );
178 }
179 // Add to express group - if express prescale is enabled
180 if (level == 2 && expressPrescale >= 1) {
181 if (m_doGlobalGroups) m_globalGroups.at(m_expressGroupName)->addToGroup( newTriggerPtr );
182 if (m_doExpressRates) m_expressTriggers.insert( newTriggerPtr );
183 }
184
185 ATH_MSG_DEBUG("newTrigger " << name << " added");
186 return StatusCode::SUCCESS;
187}
188
191 return addExisting(".*");
192}
193
194const std::unordered_map<std::string, std::unique_ptr<RatesTrigger>>& RatesAnalysisAlg::getTriggerMap() const {
195 return m_triggers;
196}
197
198StatusCode RatesAnalysisAlg::addExisting(const std::string& pattern) {
199 // Check we have the TDT
201
202 const auto& triggers = m_tdt->getListOfTriggers(pattern);
203 ATH_MSG_INFO("Read " << triggers.size() << " triggers from AOD.");
204
205 // Check if chain was disabled in athena job
206 const bool runWithPrescaleJSON = !m_prescalesJSON.value().empty();
207 const TrigConf::HLTPrescalesSet& hltPrescalesSet = m_configSvc->hltPrescalesSet(Gaudi::Hive::currentContext());
208 for( auto & p : hltPrescalesSet.data().get_child("prescales") ) {
209 if ((!m_prescalesJSON.value().count(p.first) && !runWithPrescaleJSON) || hltPrescalesSet.prescale(p.first).prescale < 0){
210 m_prescalesJSON[p.first]["prescale"] = (hltPrescalesSet.prescale(p.first).enabled ? hltPrescalesSet.prescale(p.first).prescale : -1);
211 m_prescalesJSON[p.first]["prescale_express"] = (hltPrescalesSet.prescale_express(p.first).enabled ? hltPrescalesSet.prescale_express(p.first).prescale : -1);
212 if (hltPrescalesSet.prescale(p.first).prescale < 0){
213 ATH_MSG_WARNING("Trigger " << p.first << " disabled in supplied AOD file. DISABLING");
214 }
215 }
216 }
217
218 const TrigConf::L1PrescalesSet& l1PrescalesSet = m_configSvc->l1PrescalesSet(Gaudi::Hive::currentContext());
219 for( auto & p : l1PrescalesSet.prescales() ) {
220 if ((!m_prescalesJSON.value().count(p.first) && !runWithPrescaleJSON) || p.second.prescale < 0){
221 m_prescalesJSON[p.first]["prescale"] = p.second.prescale;
222
223 if (p.second.prescale < 0){
224 ATH_MSG_WARNING("Trigger " << p.first << " disabled in supplied AOD file. DISABLING");
225 }
226 }
227 }
228
229 // Iterate over the triggers and add them
230 for (const auto& trigger : triggers) {
231 ATH_MSG_DEBUG("Considering " << trigger );
232 const bool isHLT = (getLevel(trigger) == 2);
233 const auto trigConf = (isHLT ? m_tdt->ExperimentalAndExpertMethods().getChainConfigurationDetails(trigger) : nullptr);
234 if (isHLT && !trigConf) {
235 ATH_MSG_ERROR("Problem with TDT trig conf - cannot get details for " << trigger << ", will be ignored.");
236 continue;
237 }
238 const std::string lowerName = (isHLT ? trigConf->lower_chain_name() : "");
239 std::set<std::string> groups = std::set<std::string>(); // To be filled later from the HLTMenu
240
241 if (isHLT) {
242 // If this is a HLT item, we require it to be seeded by at most one item. This allows us to use a factorising rates algorithm
243 if (lowerName.find(",") != std::string::npos) {
244 ATH_MSG_WARNING("Can not add " << trigger << " due to multiple L1 seeds." );
245 continue;
246 }
247
248 if (lowerName.empty()) {
249 ATH_MSG_WARNING("Can not add " << trigger << " due to multiple L1 seeds: L1All" );
250 continue;
251 }
252
253 // Check it also wasn't disabled in the reprocessing (e.g. auto prescaled out in a perf or tightperf menu)
254 if (trigConf->prescale() < 1.) { // Note this prescale is from ATHENA
255 ATH_MSG_DEBUG("Will not add " << trigger << ", it was disabled in the reprocessing.");
256 continue;
257 }
258
259 ATH_CHECK(m_configSvc.isValid());
260 const TrigConf::HLTMenu& hltMenu = m_configSvc->hltMenu(Gaudi::Hive::currentContext());
261
262 TrigConf::HLTMenu::const_iterator chain = std::find_if(hltMenu.begin(), hltMenu.end(), [&] (const TrigConf::Chain& c) {return c.name() == trigger;});
263 if (chain == hltMenu.end()){
264 ATH_MSG_WARNING("Chain " << trigger << " not found in the menu!");
265 continue;
266 }
267
268 std::vector<std::string> chainGroups = (*chain).groups();
269 std::vector<std::string> chainStreams = (*chain).streams();
270
271 ATH_MSG_DEBUG(" chain " << trigger << " has " << chainGroups.size() << " groups and " << chainStreams.size() << " streams");
272
273 groups.insert(chainGroups.begin(), chainGroups.end());
274 for (const std::string& stream : chainStreams){
275 groups.insert("STREAM:" + stream );
276 }
277 }
278
279 // Get the prescale, express prescale and lower prescale. Note these prescales are from SUPPLIED JSON.
280 double prescale = 1., expressPrescale = -1., lowerPrescale = 1.;
281 if (m_prescalesJSON.size() != 0) {
282 if (m_prescalesJSON.value().count(trigger) == 0) {
283 ATH_MSG_WARNING("Unable to find " << trigger << " in supplied JSON. DISABLING." );
284 prescale = 0.;
285 } else {
286 prescale = m_prescalesJSON[trigger]["prescale"];
287 expressPrescale = m_prescalesJSON[trigger]["prescale_express"];
288 }
289 if (isHLT) {
290 if (m_prescalesJSON.value().count(lowerName) == 0) {
291 ATH_MSG_WARNING("Unable to find " << trigger << "'s seed, " << lowerName << ", in supplied JSON. DISABLING." );
292 lowerPrescale = 0.;
293 } else {
294 lowerPrescale = m_prescalesJSON[lowerName]["prescale"];
295 }
296 }
297 }
298
299
300 // We now have all the info needed to add this trigger
301 ATH_MSG_DEBUG("Registering existing trigger " << trigger << " for automatic TDT based rates prediction." );
302 ATH_CHECK( newTrigger(trigger, prescale, expressPrescale, lowerName, lowerPrescale, groups, kEXISTING) );
303 }
304
305 for (const auto& trigger : m_prescalesJSON) {
306 if (trigger.second.at("prescale") > 0 && std::find(triggers.begin(), triggers.end(), trigger.first) == triggers.end()) {
307 ATH_MSG_WARNING( "Trigger " << trigger.first << " in supplied JSON is NOT AVAILABLE in the supplied AOD file.");
308 }
309 }
310
311 return StatusCode::SUCCESS;
312}
313
315 if (m_tdt.empty()){
316 ATH_MSG_ERROR("TriggerDecisionTool is not available!");
317 return StatusCode::FAILURE;
318 }
319 [[maybe_unused]] static std::atomic<bool> printed = [&]() {
320 ATH_MSG_INFO("TDT contains: " << m_tdt->getListOfTriggers().size() << " triggers, "
321 << m_tdt->getListOfStreams().size() << " streams and "
322 << m_tdt->getListOfGroups().size() << " groups.");
323 return true;
324 }();
325 return StatusCode::SUCCESS;
326}
327
328
329StatusCode RatesAnalysisAlg::checkExistingTrigger(const std::string& name, const std::string& seedName) {
331 const auto& triggers = m_tdt->getListOfTriggers(name);
332 if (triggers.size() != 1) {
333 ATH_MSG_FATAL("Unable to find existing trigger " << name << " in this AOD.");
334 return StatusCode::FAILURE;
335 }
336 if (getLevel(name) == 1) return StatusCode::SUCCESS;
337 // L1 items will crash if we call this on them.
338 const auto trigConf = m_tdt->ExperimentalAndExpertMethods().getChainConfigurationDetails(triggers.at(0));
339 if (trigConf->lower_chain_name() != seedName) {
340 ATH_MSG_FATAL("Tried to register an existing trigger '" << name << "' seeding from '" << seedName << "' but in this AOD it seeds from '" << trigConf->lower_chain_name() << "'");
341 return StatusCode::FAILURE;
342 }
343 return StatusCode::SUCCESS;
344}
345
346StatusCode RatesAnalysisAlg::setTriggerDesicison(const std::string& name, const bool triggerIsPassed, const bool triggerIsActive) {
347 // Currently - we call execute on setPassed, so the user would be unable to overwrite a decision set e.g. by the TDT.
348 // so for now we only accept positive decisions here.
349 if (triggerIsPassed || triggerIsActive) {
350 const auto iterator = m_triggers.find(name);
351 if (iterator == m_triggers.end()) {
352 ATH_MSG_ERROR("Cannot find trigger " << name << " did you call newTrigger for this in initialize?");
353 return StatusCode::FAILURE;
354 }
355 iterator->second->setPassedAndExecute(triggerIsPassed, triggerIsActive, m_weightingValues); // There is logic in the RatesTrigger to prevent multiple calls per event by accident.
356 m_activatedTriggers.insert( iterator->second.get() );
357 }
358 return StatusCode::SUCCESS;
359}
360
361
362StatusCode RatesAnalysisAlg::setTriggerDesicison(const std::string& name, const double threshold) {
363 const auto iterator = m_scanTriggers.find(name);
364 if (iterator == m_scanTriggers.end()) {
365 ATH_MSG_ERROR("Cannot find scan-trigger " << name << " did you call newScanTrigger for this in initialize?");
366 return StatusCode::FAILURE;
367 }
368 iterator->second->setPassedAndExecute(threshold, m_weightingValues); // There is logic in the RatesScanTrigger to prevent multiple calls per event by accident.
369 m_activatedTriggers.insert( static_cast<RatesTrigger*>(iterator->second.get()));
370 return StatusCode::SUCCESS;
371}
372
374 return StatusCode::SUCCESS;
375}
376
378 ATH_MSG_INFO ("Initializing " << name() << "...");
379
380 if (!m_tdt.empty()){
381 ATH_CHECK( m_tdt.retrieve() );
382 }
383
384 if(!m_configSvc.empty()) {
385 ATH_CHECK( m_configSvc.retrieve() );
386 }
387
388 ATH_CHECK( m_enhancedBiasRatesTool.retrieve() );
389 ATH_CHECK( m_additionalWeights.retrieve() );
390
391 ATH_CHECK( m_eventInfoKey.initialize());
394
396 ATH_MSG_ERROR("DoUniqueRates=True requires DoGlobalGroups=True");
397 return StatusCode::FAILURE;
398 }
399
401 return StatusCode::SUCCESS;
402}
403
405 // Let user add their triggers
406 ATH_MSG_INFO("Initializing User's Triggers (note: we are actually now in the event loop)");
407
408 if (m_doGlobalGroups) {
409 m_globalGroups.emplace(m_l1GroupName, std::make_unique<RatesGroup>(m_l1GroupName, msgSvc(), m_doHistograms, m_enableLumiExtrapolation));
410 m_globalGroups.emplace(m_l2GroupName, std::make_unique<RatesGroup>(m_l2GroupName, msgSvc(), m_doHistograms, m_enableLumiExtrapolation));
411 m_globalGroups.at(m_l2GroupName)->setDoCachedWeights( m_doUniqueRates ); // This extra sub-weight caching is only utilised by unique-rate groups
412 if (m_doExpressRates) {
413 m_globalGroups.emplace(m_expressGroupName, std::make_unique<RatesGroup>(m_expressGroupName, msgSvc(), m_doHistograms, m_enableLumiExtrapolation));
414 m_globalGroups.at(m_expressGroupName)->setExpressGroup( true );
415 }
416 }
417
418 // This runs the derived class's code to add whatever triggers are desired.
419 // Should be calling newTrigger(...), newScanTrigger(...) or addExisting(...), addAllExisting().
421
422 ATH_MSG_INFO("Computing coherent factors for coherent prescale groups.");
423 // Now we are not going to get any more chains - we can fill in the coherent prescale factors
424 for (const auto& trigger : m_triggers) {
425 const size_t CPSID = trigger.second->getCPSID();
426 if (CPSID != 0) trigger.second->setCoherentFactor( m_lowestPrescale.at(CPSID) );
427 }
428
430 ATH_MSG_INFO("Creating extra groups to calculate unique rates.");
431 const RatesGroup* l2GroupPtr = m_globalGroups.at(m_l2GroupName).get(); // The finalised list of all HLT chains
432 const RatesGroup* l1GroupPtr = m_globalGroups.at(m_l1GroupName).get(); // The finalised list of all L1 chains
433 for (const auto& trigger : m_triggers) {
434 const uint32_t level = getLevel(trigger.first);
435 m_uniqueGroups.emplace(trigger.first, std::make_unique<RatesGroup>(trigger.first, msgSvc(), false, m_enableLumiExtrapolation)); // Each trigger gets its own unique group. No hist needed
436 RatesTrigger* triggerPtr = m_triggers.at(trigger.first).get();
437 RatesGroup* uniqueGroupPtr = m_uniqueGroups.at(trigger.first).get();
438 triggerPtr->setUniqueGroup( uniqueGroupPtr ); // Create two-way links
439 uniqueGroupPtr->setUniqueTrigger( triggerPtr ); // Create two-way links
440 // Copy in the global rates topology and make note of the unique rates master group
441 if (level == 2) uniqueGroupPtr->duplicateChildren( l2GroupPtr );
442 else if (level == 1) uniqueGroupPtr->duplicateChildren( l1GroupPtr );
443 else continue;
444 // Remove this one chain from the group (a unique rate is the rate of the entire menu minus one chain)
445 uniqueGroupPtr->removeFromGroup( triggerPtr );
446 if (getLevel(trigger.first) == 2) {
447 // For HLT, we can be more computationally efficient by utilising cached info from the hlt group
448 // We remove from the group all other L1 seeds except for the one seeding our chain.
449 // This sub-weight is the only one which can change. The combined weight of all other L1 seeds
450 // can be cached by the master group and fetched from there.
451 uniqueGroupPtr->removeOtherL1( triggerPtr );
452 uniqueGroupPtr->setUseCachedWeights(true);
453 }
454 // Efficiency - if the trigger is disabled, no need to actually calculate anything for it.
455 if (trigger.second->getDisabled() == false) {
456 m_activeGroups.insert( uniqueGroupPtr ); // Add this to the event loop
457 }
458 }
459 }
460
461 ATH_MSG_INFO("Retrieving HLT chain's ID and Group from HLT menu.");
462
463 if(!m_configSvc.empty() && m_configSvc.isValid()) {
464 const TrigConf::HLTMenu& hltmenu = m_configSvc->hltMenu( Gaudi::Hive::currentContext() );
465
466 TrigConf::HLTMenu::const_iterator chain_itr = hltmenu.begin();
467 TrigConf::HLTMenu::const_iterator chain_end = hltmenu.end();
468
469 m_hltChainIDGroup.resize(hltmenu.size());
470 for (size_t i = 0; i < hltmenu.size(); i++) m_hltChainIDGroup.at(i).resize(3);
471
472 size_t c = 0;
473 for( ; chain_itr != chain_end; ++chain_itr ) {
474 std::string chainName = ( *chain_itr ).name() ;
475 unsigned int chainID = ( *chain_itr ).counter();
476 std::vector<std::string> chainGroups = ( *chain_itr ).groups();
477 for (std::string& stream : (*chain_itr).streams()){
478 chainGroups.push_back("STREAM:" + stream);
479 }
480 std::string singlechainGroups = "";
481 for (unsigned int j=0; j < chainGroups.size(); ++j){
482 if (j==0) singlechainGroups += chainGroups[j];
483 else singlechainGroups += ", "+chainGroups[j];
484 }
485
486 m_hltChainIDGroup.at(c).at(0) = chainName;
487 m_hltChainIDGroup.at(c).at(1) = std::to_string(chainID);
488 m_hltChainIDGroup.at(c).at(2) = singlechainGroups;
489 ++c;
490 }
491 }
492
493 ATH_MSG_INFO("Retrieving L1 item's ID from L1 menu.");
494
495 if(!m_configSvc.empty() && m_configSvc.isValid()) {
496 const TrigConf::L1Menu& l1menu = m_configSvc->l1Menu( Gaudi::Hive::currentContext() );
497
498 m_l1ItemID.resize(l1menu.size());
499 for (size_t i = 0; i < l1menu.size(); i++) {
500 // No groups for items
501 m_l1ItemID.at(i).resize(2);
502 }
503
504 TrigConf::L1Menu::const_iterator item_itr = l1menu.begin();
505 TrigConf::L1Menu::const_iterator item_end = l1menu.end();
506
507 size_t c = 0;
508 for( ; item_itr != item_end; ++item_itr ) {
509 m_l1ItemID.at(c).at(0) = (*item_itr).name();
510 m_l1ItemID.at(c).at(1) = std::to_string((*item_itr).ctpId());
511 ++c;
512 }
513 }
514
515 // Print all triggers
516 if (msgLevel(MSG::DEBUG)) {
517 if (m_triggers.size()) {
518 ATH_MSG_DEBUG("################## Configured to estimate rates for the following triggers:");
519 for (const auto& trigger : m_triggers) ATH_MSG_DEBUG(trigger.second->printConfig());
520 }
521 if (m_scanTriggers.size()) {
522 ATH_MSG_DEBUG("################## Configured to estimate rates for the following scan triggers:");
523 for (const auto& trigger : m_scanTriggers) ATH_MSG_DEBUG(trigger.second->printConfig());
524 }
525 if (m_groups.size()) {
526 ATH_MSG_DEBUG("################## Configured to estimate rates for the following groups of triggers:");
527 for (const auto& group : m_groups) ATH_MSG_DEBUG(group.second->printConfig());
528 }
529 if (m_globalGroups.size()) {
530 ATH_MSG_DEBUG("################## Configured to estimate rates for the following global groups of triggers:");
531 for (const auto& group : m_globalGroups) ATH_MSG_DEBUG(group.second->printConfig());
532 }
533 }
534 if (m_doHistograms) {
535 ATH_MSG_DEBUG("################## Registering normalisation histogram:");
536 m_scalingHist = new TH1D(std::format("normalisation{}",m_histogramSuffix.value()).c_str(),";;",3,0.,3.);
537 ATH_CHECK( histSvc()->regHist("/RATESTREAM/normalisation" + m_histogramSuffix, m_scalingHist) );
538 m_bcidHist = new TH1D("bcid",";BCID;Events",3565,-.5,3564.5);
539 ATH_CHECK( histSvc()->regHist("/RATESTREAM/bcid", m_bcidHist) );
540 ATH_MSG_DEBUG("################## Registering metadata tree histogram:");
541 ATH_CHECK( histSvc()->regTree("/RATESTREAM/metadata", std::make_unique<TTree>("metadata", "metadata")) );
542 ATH_CHECK( histSvc()->getTree("/RATESTREAM/metadata", m_metadataTree) );
543 if (m_triggers.size()) {
544 ATH_MSG_DEBUG("################## Registering trigger histograms:");
545 for (const auto& trigger : m_triggers) {
546 if (!trigger.second->doHistograms()) continue; // Not all may be doing histograming
547 std::string lvlSubdir = "";
548 if (trigger.second->getName().find("L1") == 0){
549 lvlSubdir = "Rate_ChainL1_HLT/";
550 } else if (trigger.second->getName().find("HLT") == 0) {
551 lvlSubdir = "Rate_ChainHLT_HLT/";
552 }
553 trigger.second->setDataName("data"+m_histogramSuffix);
554 ATH_CHECK( trigger.second->giveDataHist(histSvc(), std::string("/RATESTREAM/All/" + lvlSubdir + trigger.first + "/data")) );
555 trigger.second->setRateVsMuName("rateVsMu"+m_histogramSuffix);
556 ATH_CHECK( trigger.second->giveMuHist(histSvc(), std::string("/RATESTREAM/All/" + lvlSubdir + trigger.first + "/rateVsMu")) );
558 trigger.second->setRateVsTrainName("rateVsTrain"+m_histogramSuffix);
559 ATH_CHECK( trigger.second->giveTrainHist(histSvc(), std::string("/RATESTREAM/All/" + lvlSubdir + trigger.first + "/rateVsTrain")) );
560 } else trigger.second->clearTrainHist();
561 }
562 }
563 if (m_scanTriggers.size()) {
564 ATH_MSG_DEBUG("################## Registering scan trigger histograms:");
565 for (const auto& trigger : m_scanTriggers) {
566 trigger.second->setHistoName("rateVsThreshold"+m_histogramSuffix);
567 ATH_CHECK( trigger.second->giveThresholdHist(histSvc(), std::string("/RATESTREAM/ScanTriggers/" + trigger.first + "/rateVsThreshold" + m_histogramSuffix)) );
568 }
569 }
570 if (m_groups.size()) {
571 ATH_MSG_DEBUG("################## Registering group histograms:");
572 for (const auto& group : m_groups) {
573 if (!group.second->doHistograms()) continue;
574 std::string groupName = group.first;
575 std::replace( groupName.begin(), groupName.end(), ':', '_');
576 group.second->setDataName("data"+m_histogramSuffix);
577 ATH_CHECK( group.second->giveDataHist(histSvc(), std::string("/RATESTREAM/All/Rate_Group_HLT/" + groupName + "/data")) );
578 group.second->setRateVsMuName("rateVsMu"+m_histogramSuffix);
579 ATH_CHECK( group.second->giveMuHist(histSvc(), std::string("/RATESTREAM/All/Rate_Group_HLT/" + groupName + "/rateVsMu")) );
581 group.second->setRateVsTrainName("rateVsTrain"+m_histogramSuffix);
582 ATH_CHECK( group.second->giveTrainHist(histSvc(), std::string("/RATESTREAM/All/Rate_Group_HLT/" + groupName + "/rateVsTrain")) );
583 } else group.second->clearTrainHist();
584 }
585 }
586 if (m_globalGroups.size()) {
587 ATH_MSG_DEBUG("################## Registering global group histograms:");
588 for (const auto& group : m_globalGroups) {
589 if (!group.second->doHistograms()) continue;
590 group.second->setDataName("data"+m_histogramSuffix);
591 ATH_CHECK( group.second->giveDataHist(histSvc(), std::string("/RATESTREAM/All/Rate_Group_HLT/RATE_GLOBAL_" + group.first + "/data")) );
592 group.second->setRateVsMuName("rateVsMu"+m_histogramSuffix);
593 ATH_CHECK( group.second->giveMuHist(histSvc(), std::string("/RATESTREAM/All/Rate_Group_HLT/RATE_GLOBAL_" + group.first + "/rateVsMu")) );
595 group.second->setRateVsTrainName("rateVsTrain"+m_histogramSuffix);
596 ATH_CHECK( group.second->giveTrainHist(histSvc(), std::string("/RATESTREAM/All/Rate_Group_HLT/RATE_GLOBAL_" + group.first + "/rateVsTrain")) );
597 } else group.second->clearTrainHist();
598 }
599 }
600 }
601
602 // Has the user set a lumi extrapolation? If not - set a default
604
605 // We now know the final lumi scaling so we can set the bunch scaling
606 const uint32_t ebPairedBunches = m_enhancedBiasRatesTool->getPairedBunches();
607 ATH_MSG_INFO("Number of paired bunches in input file:" << m_enhancedBiasRatesTool->getPairedBunches());
608 m_weightingValues.m_bunchFactor = m_targetBunches / (double)ebPairedBunches;
609
610 return StatusCode::SUCCESS;
611}
612
613// HSTP filter from Jet/EtMiss
615
616 if (!m_doMultiSliceDiJet) {
617 return StatusCode::SUCCESS;
618 };
619
621 ATH_CHECK( truthHS_jets.isValid() );
623 ATH_CHECK( truthPU_jets.isValid() );
624
625 // Extract the pT of the leading jet that defines the hardness. The jet containers should always be pT sorted
626 const double pT_j1_truthPU = truthPU_jets->size() ? truthPU_jets->front()->pt() : 0; // Hardest PU truth jet
627 const double pT_j1_truthHS = truthHS_jets->size() ? truthHS_jets->front()->pt() : 5000; // In the rare case of no HS truth jets in the event, assume it is close to the 5 GeV threshold
628
629 // Now see if we pass the filter.
630 pass = pT_j1_truthHS > pT_j1_truthPU;
631 ATH_MSG_DEBUG("Hard Scatter (" << pT_j1_truthHS/1000. << " GeV) Harder Than Pileup (" << pT_j1_truthPU/1000. << " GeV) filter " << (pass ? "PASSES" : "FAILS"));
632 return StatusCode::SUCCESS;
633}
634
635StatusCode RatesAnalysisAlg::execute(const EventContext& ctx) {
636 ATH_MSG_VERBOSE("Executing " << name() << " on event " << m_eventCounter << "...");
637 if (m_eventCounter++ == 0) { // First time in execute loop - cannot access TDT before this.
639 if (!m_configSvc.empty() && m_configSvc.isValid()) {
640 m_metadataMasterKey = m_configSvc->masterKey();
641 m_metadataHLTPSK = m_configSvc->hltPrescaleKey();
642 m_metadataL1PSK = m_configSvc->lvl1PrescaleKey();
643
644 ATH_MSG_INFO("Cached metadata trigger keys: SMK="
646 << " L1PSK=" << m_metadataL1PSK
647 << " HLTPSK=" << m_metadataHLTPSK);
649 }
650 }
651 // Get event characteristics
653 ATH_CHECK( eventInfo.isValid() );
654 uint32_t distance = 0;
655 ATH_CHECK( m_enhancedBiasRatesTool->getDistanceIntoTrain(eventInfo.get(), distance, ctx) );
656 const bool isMC = m_enhancedBiasRatesTool->isMC();
657
658 // Get the weighting & scaling characteristics
659 m_weightingValues.m_enhancedBiasWeight = m_enhancedBiasRatesTool->getEBWeight(eventInfo.get());
660 m_weightingValues.m_eventMu = std::ceil(eventInfo->actualInteractionsPerCrossing()); // This always seems to be a half integer
661 m_weightingValues.m_eventLumi = m_enhancedBiasRatesTool->getLBLumi(eventInfo.get());
662 m_weightingValues.m_isUnbiased = m_enhancedBiasRatesTool->isUnbiasedEvent(eventInfo.get());
663 m_weightingValues.m_distanceInTrain = distance;
664 m_weightingValues.m_eventLiveTime = m_enhancedBiasRatesTool->getEBLiveTime(eventInfo.get());
665 if (m_useBunchCrossingData && m_vetoStartOfTrain > 0 && m_weightingValues.m_distanceInTrain < m_vetoStartOfTrain) return StatusCode::SUCCESS;
666
667 // Bunch factor doesn't change as a fn. of the run. Reminder: m_bunchFactor = m_targetBunches / (double)ebPairedBunches;
668 m_weightingValues.m_muFactor = (m_weightingValues.m_eventMu ? m_targetMu / m_weightingValues.m_eventMu : 0.0);
669 m_weightingValues.m_linearLumiFactor = m_targetLumi / m_weightingValues.m_eventLumi;
670 m_weightingValues.m_expoMuFactor = m_weightingValues.m_bunchFactor * exp( m_expoScalingFactor * (m_targetMu - m_weightingValues.m_eventMu) );
671
672 // Ignore zero weighted events. Typically these come from bad LB
673 if (RatesHistoBase::isZero(m_weightingValues.m_enhancedBiasWeight)) {
674 return StatusCode::SUCCESS;
675 }
676
677 // Apply any additional weights multiplicatively if required
678 if (!m_additionalWeights.empty()) {
679 for (const auto& addWeight : m_additionalWeights) {
680 double wt = 1.0;
681 ATH_CHECK(addWeight->getValue(wt));
682 ATH_MSG_DEBUG("Additional weight from [" << addWeight->name() << "], value = " << wt);
683 m_weightingValues.m_enhancedBiasWeight *= wt;
684 }
685 }
686
687 m_weightedEventCounter += m_weightingValues.m_enhancedBiasWeight;
688
689 double ratesDenominator = 0.0;
691 ratesDenominator = m_weightingValues.m_enhancedBiasWeight; // In multi-slice mode we only normalize to the weighted number of events
692 } else {
693 ratesDenominator = m_weightingValues.m_eventLiveTime; // Otherwise, we need to keep track of elapsed walltime as well
694 }
695 m_ratesDenominator += ratesDenominator;
696
697 if (m_doHistograms) {
698 m_bcidHist->Fill(eventInfo->bcid(), m_weightingValues.m_enhancedBiasWeight);
699 m_scalingHist->Fill(0.5, ratesDenominator); // Walltime
700 m_scalingHist->Fill(1.5, 1.); // Total events
701 m_scalingHist->Fill(2.5, m_weightingValues.m_enhancedBiasWeight ); // Total weighted events
702 }
703
704 // HSTP filter check
705 if (isMC) {
706 bool filterPass = true;
707 ATH_CHECK( pass_HstpFilter(filterPass) );
708 if (!filterPass) {return StatusCode::SUCCESS;}
709 }
710
711 // Do automated triggers
713
714 // Do TDT-controlled triggers
716
717 // Run user's code. Do manual triggers
719
720 // Execute groups
721 for (const auto& group : m_globalGroups) group.second->execute(m_weightingValues); // Physics, L1, express: Must execute before m_uniqueGroups (which are in active groups). Map.
722 for (const auto& group : m_activeGroups) group->execute(m_weightingValues); // Individual groups, CPS groups and active unique groups. Set.
723
724 // Reset triggers
725 for (const auto& trigger : m_activatedTriggers) trigger->reset();
726 m_activatedTriggers.clear();
727
728 // Some debug info
729 if (m_eventCounter % 1000 == 0) {
730 ATH_MSG_INFO( "Event " << m_eventCounter << " " << m_weightingValues.print() << " currentWallTime:" << m_ratesDenominator );
731 }
732
733 setFilterPassed(true, ctx); //if got here, assume that means algorithm passed
734 return StatusCode::SUCCESS;
735}
736
738 for (const auto& trigger : m_existingTriggers) {
739 const bool passed = trigger.second->isPassed();
740 // L1 chains are always active, HLT chains are active if their L1 passed.
741 const std::string& lower = m_lowerTrigger[trigger.first];
742 // Expect this find operation to fail for L1 chains (lower = "")
743 const std::unordered_map<std::string, const Trig::ChainGroup*>::const_iterator it = m_existingTriggers.find(lower);
744 const bool active = (it == m_existingTriggers.end() ? true : it->second->isPassed());
745 ATH_CHECK( setTriggerDesicison(trigger.first, passed, active) );
746 }
747 return StatusCode::SUCCESS;
748}
749
751 // TODO emulation code here
752 for (const auto& trigger : m_autoTriggers) {
753 ATH_MSG_WARNING("Cannot do rates for " << trigger << ". Automatic trigger emulation is not yet included, sorry :(");
754 }
755 return StatusCode::SUCCESS;
756}
757
759 ATH_MSG_INFO ("Finalizing " << name() << "...");
760
762 if (!m_doMultiSliceDiJet) { // Cannot estimate multi-slice rates before the merging stage
763 if (m_scanTriggers.size()) {
764 ATH_MSG_INFO("################## Computed Rate Scans for Threshold-Scan Items:");
765 for (const auto& trigger : m_scanTriggers) ATH_MSG_INFO(trigger.second->printRate(m_ratesDenominator));
766 }
767 if (m_triggers.size()) {
768 ATH_MSG_INFO("################## Computed Rate Estimations for Single Items:");
769 std::set<std::string> keys; // Used an unordered map for speed, but now we'd like the items in order
770 for (const auto& trigger : m_triggers) keys.insert(trigger.first);
771 for (const std::string& key : keys) ATH_MSG_INFO(m_triggers.at(key)->printRate(m_ratesDenominator));
772 }
773 if (m_expressTriggers.size()) {
774 ATH_MSG_INFO("################## Computed Express Rate Estimations for Single Items:");
775 for (const auto& trigger : m_expressTriggers) ATH_MSG_INFO(trigger->printExpressRate(m_ratesDenominator));
776 }
777 if (m_groups.size()) {
778 ATH_MSG_INFO("################## Computed Rate Estimations for Groups:");
779 for (const auto& group : m_groups) ATH_MSG_INFO(group.second->printRate(m_ratesDenominator));
780 }
781 if (m_globalGroups.size()) {
782 ATH_MSG_INFO("################## Computed Rate Estimations for Global Groups:");
783 for (const auto& group : m_globalGroups) ATH_MSG_INFO(group.second->printRate(m_ratesDenominator));
784 }
785 }
786 ATH_MSG_INFO("################## LHC Conditions and weighting information:");
788 printTarget();
790 ATH_MSG_INFO("##################");
792
793 return StatusCode::SUCCESS;
794}
795
796void RatesAnalysisAlg::setTargetLumiMu(const double lumi, const double mu) {
797 if (m_eventCounter > 1) { // All settings must be defined before we start looping over the sample
798 ATH_MSG_WARNING("Too late to call setTargetLumiMu. Do this during ratesInitialize().");
799 return;
800 }
801 m_targetLumi = lumi;
802 if (isZero(mu)) {
803 ATH_MSG_WARNING("Cannot have <mu> = 0. Setting to 1.");
804 m_targetMu = 1;
805 } else {
806 m_targetMu = mu;
807 }
810 ATH_MSG_WARNING("Un-physical number of bunches " << m_targetBunches << ", should be within 1 < N < " << EnhancedBiasWeighter::FULL_RING+1);
812 }
813 printTarget();
814}
815
816void RatesAnalysisAlg::setTargetLumiBunches(const double lumi, const int32_t bunches) {
817 if (m_eventCounter > 1) { // All settings must be defined before we start looping over the sample
818 ATH_MSG_WARNING("Too late to call setTargetLumiBunches. Do this during ratesInitialize().");
819 return;
820 }
821 m_targetLumi = lumi;
822 if (bunches == 0) {
823 ATH_MSG_WARNING("Cannot have bunches = 0. Setting to 1.");
824 m_targetBunches = 1;
825 } else {
826 m_targetBunches = bunches;
827 }
829 printTarget();
830}
831
832
833void RatesAnalysisAlg::setTargetMuBunches(const double mu, const int32_t bunches) {
834 if (m_eventCounter > 1) { // All settings must be defined before we start looping over the sample
835 ATH_MSG_WARNING("Too late to call setTargetMuBunches. Do this during ratesInitialize().");
836 return;
837 }
838 if (bunches == 0) {
839 ATH_MSG_WARNING("Cannot have paired bunches = 0. Setting to 1.");
840 m_targetBunches = 1;
841 } else {
842 m_targetBunches = bunches;
843 }
844 if (isZero(mu)) {
845 ATH_MSG_WARNING("Cannot have mu = 0. Setting to 1.");
846 m_targetMu = 1;
847 } else {
848 m_targetMu = mu;
849 }
851 printTarget();
852}
853
856 ATH_MSG_INFO("Calculating rates for a target L_inst. = " << m_targetLumi << " cm-2s-1, mu = " << m_targetMu << ", paired bunches = " << m_targetBunches);
857 } else {
858 ATH_MSG_INFO("Luminosity extrapolation is switched off. Input files will determin the paired bunches, L_inst. and mu profile.");
859 }
860}
861
863 ATH_MSG_INFO("Processed " << m_eventCounter << " raw events, " << m_weightedEventCounter << " weighted. Total LHC wall-time of " << m_ratesDenominator << " s.");
864}
865
867 ATH_MSG_INFO("Input " << (m_enhancedBiasRatesTool->isMC() ? "MC" : "EB Data")
868 << " with <L_inst.> = "
869 << m_enhancedBiasRatesTool->getAverageLumi()
870 << " cm-2s-1, <mu> = "
871 << m_enhancedBiasRatesTool->getAverageMu()
872 << ", paired bunches = "
873 << m_enhancedBiasRatesTool->getPairedBunches());
874}
875
876bool RatesAnalysisAlg::isCPS(const std::string& group) const {
877 return (group.find("CPS") != std::string::npos);
878}
879
880bool RatesAnalysisAlg::isRandomSeed(const std::string& me, const std::string& seed) const {
881 if (me.find("L1_RD") != std::string::npos) return true;
882 if (me.find("L1RD") != std::string::npos) return true;
883 if (seed.find("L1_RD") != std::string::npos) return true;
884 return false;
885}
886
887uint32_t RatesAnalysisAlg::getLevel(const std::string& name) const {
888 if (name.find("HLT_") != std::string::npos) return 2;
889 if (name.find("L1_") != std::string::npos) return 1;
890 return 2;
891}
892
894 if (!m_metadataTree) {
895 return;
896 }
897 m_runNumber = m_enhancedBiasRatesTool->getRunNumber();
898 m_metadataTree->Branch("runNumber", &m_runNumber);
899 m_metadataTree->Branch("targetMu", &m_targetMu);
900 m_metadataTree->Branch("targetBunches", &m_targetBunches);
901 m_metadataTree->Branch("targetLumi", &m_targetLumi);
902
903 double bunchCrossingRate = m_enhancedBiasRatesTool->getBunchCrossingRate();
904 m_metadataTree->Branch("bunchCrossingRate", &bunchCrossingRate);
905 int doMultiSliceDiJet = m_doMultiSliceDiJet;
906 m_metadataTree->Branch("multiSliceDiJet", &doMultiSliceDiJet);
907
908 std::vector<std::string> triggers;
909 std::vector<std::string> lowers;
910 std::vector<double> prescales;
911 std::vector<double> express;
912 triggers.reserve(m_triggers.size());
913 lowers.reserve(m_triggers.size());
914 prescales.reserve(m_triggers.size());
915 express.reserve(m_triggers.size());
916 for (const auto& trigger : m_triggers) {
917 triggers.push_back(trigger.first);
918 lowers.push_back(trigger.second->getSeedName());
919 prescales.push_back(trigger.second->getPrescale() );
920 express.push_back(trigger.second->getPrescale(true /*includeExpress*/) );
921 }
922 for (const auto& group : m_groups) {
923 triggers.push_back(group.first);
924 lowers.push_back("-");
925 prescales.push_back(-1);
926 express.push_back(-1);
927 }
928 for (const auto& group : m_globalGroups) {
929 triggers.push_back("RATE_GLOBAL_" + group.first);
930 lowers.push_back("-");
931 prescales.push_back(-1);
932 express.push_back(-1);
933 }
934 m_metadataTree->Branch("triggers", &triggers);
935 m_metadataTree->Branch("lowers", &lowers);
936 m_metadataTree->Branch("prescales", &prescales);
937 m_metadataTree->Branch("express", &express);
938 std::vector<int32_t> bunchGroups;
939 bunchGroups.reserve(16);
940
941 uint32_t masterKey = 0;
942 uint32_t hltPrescaleKey = 0;
943 uint32_t lvl1PrescaleKey = 0;
944
945 if(!m_enhancedBiasRatesTool->isMC()){
946 bunchGroups = m_enhancedBiasRatesTool->getBunchGroups();
947 }
948
950 masterKey = m_metadataMasterKey;
951 hltPrescaleKey = m_metadataHLTPSK;
952 lvl1PrescaleKey = m_metadataL1PSK;
953 }
954
955 if(!m_configSvc.empty() && m_configSvc.isValid() ){
956 if ((bunchGroups.size() == 0 || std::all_of(bunchGroups.begin(), bunchGroups.end(), [](int i) { return i==0; }) ) && (!m_enhancedBiasRatesTool->isMC())) {
957 const TrigConf::L1BunchGroupSet& bgs = m_configSvc->l1BunchGroupSet(Gaudi::Hive::currentContext());
958 for (size_t i = 0; i < bgs.maxNBunchGroups(); ++i ) {
959 bunchGroups.push_back(bgs.getBunchGroup(i)->size());
960 }
961 }
963 masterKey = m_configSvc->masterKey();
964 hltPrescaleKey = m_configSvc->hltPrescaleKey();
965 lvl1PrescaleKey = m_configSvc->lvl1PrescaleKey();
966 }
967 }
968
969
970 m_metadataTree->Branch("bunchGroups", &bunchGroups);
971
972 m_metadataTree->Branch("hltChainIDGroup", &m_hltChainIDGroup);
973 m_metadataTree->Branch("l1ItemID", &m_l1ItemID);
974
975 m_metadataTree->Branch("masterKey", &masterKey);
976 m_metadataTree->Branch("lvl1PrescaleKey", &lvl1PrescaleKey);
977 m_metadataTree->Branch("hltPrescaleKey", &hltPrescaleKey);
978 std::string atlasProject = std::getenv("AtlasProject");
979 std::string atlasVersion = std::getenv("AtlasVersion");
980 m_metadataTree->Branch("AtlasProject", &atlasProject);
981 m_metadataTree->Branch("AtlasVersion", &atlasVersion);
982 m_metadataTree->Fill();
983}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
bool passed(DecisionID id, const DecisionIDContainer &)
checks if required decision ID is in the set of IDs in the container
static Double_t ss
ExtrapStrat_t
Extrapolation strategy to apply to each emulated trigger.
@ kNONE
Do not scale this trigger for changes in luminosity.
void setFilterPassed(bool state) const
AthAnalysisAlgorithm(const std::string &name)
Constructor taking just a name.
const ServiceHandle< ITHistSvc > & histSvc() const
The standard THistSvc (for writing histograms and TTrees and more to a root file) Returns (kind of) a...
static constexpr uint32_t FULL_RING
Number of bunches in a full ring.
static constexpr double LHC_FREQUENCY
TH1D * m_bcidHist
Histogram of the BCIDs distribution of the processing.
Method_t
Method by which the trigger pass/fail decision is calculated.
@ kMANUAL
The pass/fail decision is evaluated by the user and supplied per event using setTriggerDesicison.
@ kAUTO
The pass/fail decision is automatically emulated per event based on decoding the trigger name.
@ kEXISTING
The pass/fail decision is taken from the Trigger Decision Tool for an existing trigger.
StatusCode executeTrigDecisionToolTriggers()
Internal call to get the pass/fail for all TDT triggers.
void setTargetLumiBunches(const double lumi, const int32_t bunches)
Set the target instantaneous luminosity and number of bunches.
std::unordered_map< std::string, std::unique_ptr< RatesGroup > > m_uniqueGroups
Groups used to obtain unique rates for chains.
const std::string m_l2GroupName
double m_targetBunches
How many bunches the prediction is targeting.
RatesAnalysisAlg(const std::string &name, ISvcLocator *pSvcLocator)
void printInputSummary() const
Print the input data instantaneous luminosity, mu and number of bunches.
virtual StatusCode ratesInitialize()=0
To be implemented by the user.
uint32_t m_runNumber
What is the RunNumber.
std::unordered_set< RatesTrigger * > m_activatedTriggers
Triggers which were changed & hence need to be reset at the event end.
ServiceHandle< TrigConf::ITrigConfigSvc > m_configSvc
void printStatistics() const
Print some extra statistics on events processed.
SG::ReadHandleKey< xAOD::JetContainer > m_truthHS_jets_RHKey
Gaudi::Property< bool > m_doHistograms
Gaudi::Property< bool > m_doUniqueRates
uint32_t getLevel(const std::string &name) const
String match to a trigger level.
Gaudi::Property< double > m_expoScalingFactor
uint32_t m_metadataHLTPSK
<smk read patched
SG::ReadHandleKey< xAOD::JetContainer > m_truthPU_jets_RHKey
StatusCode setTriggerDesicison(const std::string &name, const bool triggerIsPassed=true, const bool triggerIsActive=true)
Set the pass/fail decision for an item.
std::unordered_set< RatesTrigger * > m_expressTriggers
Triggers with non-zero express PS, used to print them at the end.
double m_ratesDenominator
How much walltime is seen by the algorithm.
double m_targetLumi
What instantaneous luminosity the prediction is targeting.
virtual StatusCode finalize()
Print rates.
Gaudi::Property< bool > m_doMultiSliceDiJet
double m_weightedEventCounter
Count how many weighted events were processed.
Gaudi::Property< bool > m_doExpressRates
ToolHandleArray< IAdditionalWeight > m_additionalWeights
std::unordered_map< size_t, double > m_lowestPrescale
Lowest prescale within a CPS group, key is the hash of the CPS group name.
TTree * m_metadataTree
Used to write out some metadata needed by post-processing (e.g.
void setTargetLumiMu(const double lumi, const double mu)
Set the target instantaneous luminosity and mu.
bool isRandomSeed(const std::string &me, const std::string &seed) const
String match random L1 items.
std::unordered_map< std::string, std::unique_ptr< RatesGroup > > m_globalGroups
Big (master) groups which do the OR of the whole menu.
std::vector< std::vector< std::string > > m_hltChainIDGroup
std::unordered_map< std::string, std::unique_ptr< RatesGroup > > m_groups
All regular and CPS groups.
std::unordered_map< std::string, const Trig::ChainGroup * > m_existingTriggers
Map of triggers which we ask the TDT ChainGroup for the pass/fail.
virtual StatusCode ratesFinalize()=0
To be implemented by the user.
Gaudi::Property< bool > m_useBunchCrossingData
Gaudi::Property< std::string > m_histogramSuffix
const std::unordered_map< std::string, std::unique_ptr< RatesTrigger > > & getTriggerMap() const
virtual StatusCode execute(const EventContext &ctx)
In first call - register all triggers.
StatusCode populateTriggers()
Register all triggers to emulate.
uint32_t m_metadataL1PSK
<hltpsk read patched
StatusCode pass_HstpFilter(bool &pass)
Boolean indicating if the event passes the HS-softer-than-PU (HSTP) filter.
const std::string m_expressGroupName
WeightingValuesSummary_t m_weightingValues
Possible weighting & lumi extrapolation values for the current event.
StatusCode checkExistingTrigger(const std::string &name, const std::string &seedName)
Internal function to check if a supplied HLT trigger and L1 seed match what is stored in the AOD conf...
void setTargetMuBunches(const double mu, const int32_t bunches)
Set the target mu and number of bunches.
StatusCode checkGotTDT()
Internal check that the TDT is fetched.
virtual StatusCode ratesExecute()=0
To be implemented by the user.
Gaudi::Property< bool > m_doTriggerGroups
virtual StatusCode initialize()
Get the trigger decision tool and set up global groups.
virtual StatusCode initialize_extra_content()
Initialization of additional payload for inherited classes.
std::vector< std::vector< std::string > > m_l1ItemID
std::unordered_map< std::string, std::string > m_lowerTrigger
Map of triggers lower chain, to tell if a HLT trigger ran or not.
std::unordered_set< RatesGroup * > m_activeGroups
All groups which are enabled (PS >= 1).
bool isCPS(const std::string &group) const
String match coherent prescale groups.
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
void setTargetLumi(const double lumi)
Set the target instantaneous luminosity.
Gaudi::Property< uint32_t > m_vetoStartOfTrain
ToolHandle< Trig::TrigDecisionTool > m_tdt
Gaudi::Property< double > m_inelasticCrossSection
StatusCode addExisting(const std::string &pattern)
Register some existing triggers based on wild-card match, e.g.
std::unordered_map< std::string, std::unique_ptr< RatesTrigger > > m_triggers
All individual triggers (L1 or HLT).
bool isZero(double v) const
Helper function for floating point subtraction.
bool m_metadataKeysCached
< l1psk read patched
std::vector< std::string > m_autoTriggers
List of triggers which it is up to us to the algorithm to work out the pass/fail for.
double m_targetMu
What pileup level the prediction is targeting.
StatusCode addAllExisting()
Register all existing triggers in the AOD into the rates algorithm.
void writeMetadata()
Write to outpute tree (if any) the metadata needed downstream.
const std::string m_l1GroupName
TH1D * m_scalingHist
< patched key read
void printTarget() const
Print the target instantaneous luminosity, mu and number of bunches.
StatusCode newTrigger(const std::string &name, const double prescale=1., const double expressPrescale=-1., const std::string &seedName="", const double seedPrecale=1., const std::string &groups="", const Method_t method=kMANUAL, const ExtrapStrat_t extrapolation=kLINEAR)
Version of newTrigger which accepts a set of group names rather than a comma separated string.
ToolHandle< IEnhancedBiasWeighter > m_enhancedBiasRatesTool
Gaudi::Property< bool > m_enableLumiExtrapolation
uint32_t m_eventCounter
Count how many events processed.
Gaudi::Property< bool > m_doGlobalGroups
Gaudi::Property< std::map< std::string, std::map< std::string, double > > > m_prescalesJSON
StatusCode newScanTrigger(const std::string &name, const double thresholdMin, const double thresholdMax, const uint32_t thresholdBins=100, const RatesScanTrigger::TriggerBehaviour_t behaviour=RatesScanTrigger::TriggerBehaviour_t::kTriggerBelowThreshold, const double prescale=1., const std::string &seedName="", const double seedPrecale=1., const Method_t method=kMANUAL, const ExtrapStrat_t extrapolation=kLINEAR)
Register a new threshold scan trigger which plots rate as a function of some dependent variable.
StatusCode executeTriggerEmulation()
Internal call to get the pass/fail for all automatically emulated triggers.
std::unordered_map< std::string, std::unique_ptr< RatesScanTrigger > > m_scanTriggers
All individual rates-scan triggers (L1 or HLT).
Used to calculate the rate for a group of RatesTrigger objects at L1 or the HLT.
Definition RatesGroup.h:29
void setUseCachedWeights(const bool i)
Set to use cached weights from the Master group (need ptr to m_masterGroup).
void removeFromGroup(const RatesTrigger *toRemove)
Remove a trigger from this group.
void duplicateChildren(const RatesGroup *toDuplicate)
Copy in triggers from another group.
void setUniqueTrigger(RatesTrigger *trigger)
Set trigger I am doing unique rates for.
void removeOtherL1(const RatesTrigger *toKeep)
Remove from the groups mapping all triggers which have a dissimilar seed to the supplied trigger.
static bool isZero(double v)
Used to calculate a rate scan as a function of some threshold value.
TriggerBehaviour_t
enum to describe if a trigger should activate for values >= or <= than the thresold
Used to calculate the rate for a single trigger at L1 or the HLT.
void setUniqueGroup(const RatesGroup *unique)
If I have a group which is calculating my unique rate.
void setSeedsFromRandom(const bool i)
Set if this trigger is to behave as if it seeds from a random L1 item.
void setCPS(const std::string &group)
If I'm in a CPS group, set the group name (I'll keep a copy of the hash).
bool getDisabled() const
If I or my seed were prescaled out.
size_t getCPSID() const
Get the hash of my CPS group name.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type get() const
Dereference the pointer, but don't cache anything.
const ptree & data() const
Access to the underlying data, if needed.
HLT menu configuration.
Definition HLTMenu.h:21
const_iterator end() const
End of the HLT chains list.
Definition HLTMenu.cxx:57
const_iterator begin() const
Begin of the HLT chains list.
Definition HLTMenu.cxx:51
ConstIter< ptree, Chain > const_iterator
Iterator over the HLT chains.
Definition HLTMenu.h:50
std::size_t size() const
Accessor to the number of HLT chains.
Definition HLTMenu.cxx:35
HLT menu configuration.
const HLTPrescale & prescale_express(const std::string &chainName) const
HLT prescales by chain names.
const HLTPrescale & prescale(const std::string &chainName) const
HLT prescales by chain names.
L1 board configuration.
constexpr std::size_t maxNBunchGroups() const
Maximum number of bunchgroups.
const std::shared_ptr< L1BunchGroup > & getBunchGroup(const std::string &name) const
Accessor to the bunchgroup by name.
L1 menu configuration.
Definition L1Menu.h:29
ConstIter< ptree, L1Item > const_iterator
Iterator over the L1 items.
Definition L1Menu.h:65
L1 menu configuration.
const std::map< std::string, L1Prescale > & prescales() const