ATLAS Offline Software
Loading...
Searching...
No Matches
RatesAnalysisAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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
390 ATH_CHECK( m_eventInfoKey.initialize());
393
395 ATH_MSG_ERROR("DoUniqueRates=True requires DoGlobalGroups=True");
396 return StatusCode::FAILURE;
397 }
398
400 return StatusCode::SUCCESS;
401}
402
404 // Let user add their triggers
405 ATH_MSG_INFO("Initializing User's Triggers (note: we are actually now in the event loop)");
406
407 if (m_doGlobalGroups) {
408 m_globalGroups.emplace(m_l1GroupName, std::make_unique<RatesGroup>(m_l1GroupName, msgSvc(), m_doHistograms, m_enableLumiExtrapolation));
409 m_globalGroups.emplace(m_l2GroupName, std::make_unique<RatesGroup>(m_l2GroupName, msgSvc(), m_doHistograms, m_enableLumiExtrapolation));
410 m_globalGroups.at(m_l2GroupName)->setDoCachedWeights( m_doUniqueRates ); // This extra sub-weight caching is only utilised by unique-rate groups
411 if (m_doExpressRates) {
412 m_globalGroups.emplace(m_expressGroupName, std::make_unique<RatesGroup>(m_expressGroupName, msgSvc(), m_doHistograms, m_enableLumiExtrapolation));
413 m_globalGroups.at(m_expressGroupName)->setExpressGroup( true );
414 }
415 }
416
417 // This runs the derived class's code to add whatever triggers are desired.
418 // Should be calling newTrigger(...), newScanTrigger(...) or addExisting(...), addAllExisting().
420
421 ATH_MSG_INFO("Computing coherent factors for coherent prescale groups.");
422 // Now we are not going to get any more chains - we can fill in the coherent prescale factors
423 for (const auto& trigger : m_triggers) {
424 const size_t CPSID = trigger.second->getCPSID();
425 if (CPSID != 0) trigger.second->setCoherentFactor( m_lowestPrescale.at(CPSID) );
426 }
427
429 ATH_MSG_INFO("Creating extra groups to calculate unique rates.");
430 const RatesGroup* l2GroupPtr = m_globalGroups.at(m_l2GroupName).get(); // The finalised list of all HLT chains
431 const RatesGroup* l1GroupPtr = m_globalGroups.at(m_l1GroupName).get(); // The finalised list of all L1 chains
432 for (const auto& trigger : m_triggers) {
433 const uint32_t level = getLevel(trigger.first);
434 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
435 RatesTrigger* triggerPtr = m_triggers.at(trigger.first).get();
436 RatesGroup* uniqueGroupPtr = m_uniqueGroups.at(trigger.first).get();
437 triggerPtr->setUniqueGroup( uniqueGroupPtr ); // Create two-way links
438 uniqueGroupPtr->setUniqueTrigger( triggerPtr ); // Create two-way links
439 // Copy in the global rates topology and make note of the unique rates master group
440 if (level == 2) uniqueGroupPtr->duplicateChildren( l2GroupPtr );
441 else if (level == 1) uniqueGroupPtr->duplicateChildren( l1GroupPtr );
442 else continue;
443 // Remove this one chain from the group (a unique rate is the rate of the entire menu minus one chain)
444 uniqueGroupPtr->removeFromGroup( triggerPtr );
445 if (getLevel(trigger.first) == 2) {
446 // For HLT, we can be more computationally efficient by utilising cached info from the hlt group
447 // We remove from the group all other L1 seeds except for the one seeding our chain.
448 // This sub-weight is the only one which can change. The combined weight of all other L1 seeds
449 // can be cached by the master group and fetched from there.
450 uniqueGroupPtr->removeOtherL1( triggerPtr );
451 uniqueGroupPtr->setUseCachedWeights(true);
452 }
453 // Efficiency - if the trigger is disabled, no need to actually calculate anything for it.
454 if (trigger.second->getDisabled() == false) {
455 m_activeGroups.insert( uniqueGroupPtr ); // Add this to the event loop
456 }
457 }
458 }
459
460 ATH_MSG_INFO("Retrieving HLT chain's ID and Group from HLT menu.");
461
462 if(!m_configSvc.empty() && m_configSvc.isValid()) {
463 const TrigConf::HLTMenu& hltmenu = m_configSvc->hltMenu( Gaudi::Hive::currentContext() );
464
465 TrigConf::HLTMenu::const_iterator chain_itr = hltmenu.begin();
466 TrigConf::HLTMenu::const_iterator chain_end = hltmenu.end();
467
468 m_hltChainIDGroup.resize(hltmenu.size());
469 for (size_t i = 0; i < hltmenu.size(); i++) m_hltChainIDGroup.at(i).resize(3);
470
471 size_t c = 0;
472 for( ; chain_itr != chain_end; ++chain_itr ) {
473 std::string chainName = ( *chain_itr ).name() ;
474 unsigned int chainID = ( *chain_itr ).counter();
475 std::vector<std::string> chainGroups = ( *chain_itr ).groups();
476 for (std::string& stream : (*chain_itr).streams()){
477 chainGroups.push_back("STREAM:" + stream);
478 }
479 std::string singlechainGroups = "";
480 for (unsigned int j=0; j < chainGroups.size(); ++j){
481 if (j==0) singlechainGroups += chainGroups[j];
482 else singlechainGroups += ", "+chainGroups[j];
483 }
484
485 m_hltChainIDGroup.at(c).at(0) = chainName;
486 m_hltChainIDGroup.at(c).at(1) = std::to_string(chainID);
487 m_hltChainIDGroup.at(c).at(2) = singlechainGroups;
488 ++c;
489 }
490 }
491
492 ATH_MSG_INFO("Retrieving L1 item's ID from L1 menu.");
493
494 if(!m_configSvc.empty() && m_configSvc.isValid()) {
495 const TrigConf::L1Menu& l1menu = m_configSvc->l1Menu( Gaudi::Hive::currentContext() );
496
497 m_l1ItemID.resize(l1menu.size());
498 for (size_t i = 0; i < l1menu.size(); i++) {
499 // No groups for items
500 m_l1ItemID.at(i).resize(2);
501 }
502
503 TrigConf::L1Menu::const_iterator item_itr = l1menu.begin();
504 TrigConf::L1Menu::const_iterator item_end = l1menu.end();
505
506 size_t c = 0;
507 for( ; item_itr != item_end; ++item_itr ) {
508 m_l1ItemID.at(c).at(0) = (*item_itr).name();
509 m_l1ItemID.at(c).at(1) = std::to_string((*item_itr).ctpId());
510 ++c;
511 }
512 }
513
514 // Print all triggers
515 if (msgLevel(MSG::DEBUG)) {
516 if (m_triggers.size()) {
517 ATH_MSG_DEBUG("################## Configured to estimate rates for the following triggers:");
518 for (const auto& trigger : m_triggers) ATH_MSG_DEBUG(trigger.second->printConfig());
519 }
520 if (m_scanTriggers.size()) {
521 ATH_MSG_DEBUG("################## Configured to estimate rates for the following scan triggers:");
522 for (const auto& trigger : m_scanTriggers) ATH_MSG_DEBUG(trigger.second->printConfig());
523 }
524 if (m_groups.size()) {
525 ATH_MSG_DEBUG("################## Configured to estimate rates for the following groups of triggers:");
526 for (const auto& group : m_groups) ATH_MSG_DEBUG(group.second->printConfig());
527 }
528 if (m_globalGroups.size()) {
529 ATH_MSG_DEBUG("################## Configured to estimate rates for the following global groups of triggers:");
530 for (const auto& group : m_globalGroups) ATH_MSG_DEBUG(group.second->printConfig());
531 }
532 }
533 if (m_doHistograms) {
534 ATH_MSG_DEBUG("################## Registering normalisation histogram:");
535 m_scalingHist = new TH1D(std::format("normalisation{}",m_histogramSuffix.value()).c_str(),";;",3,0.,3.);
536 ATH_CHECK( histSvc()->regHist("/RATESTREAM/normalisation" + m_histogramSuffix, m_scalingHist) );
537 m_bcidHist = new TH1D("bcid",";BCID;Events",3565,-.5,3564.5);
538 ATH_CHECK( histSvc()->regHist("/RATESTREAM/bcid", m_bcidHist) );
539 ATH_MSG_DEBUG("################## Registering metadata tree histogram:");
540 ATH_CHECK( histSvc()->regTree("/RATESTREAM/metadata", std::make_unique<TTree>("metadata", "metadata")) );
541 ATH_CHECK( histSvc()->getTree("/RATESTREAM/metadata", m_metadataTree) );
542 if (m_triggers.size()) {
543 ATH_MSG_DEBUG("################## Registering trigger histograms:");
544 for (const auto& trigger : m_triggers) {
545 if (!trigger.second->doHistograms()) continue; // Not all may be doing histograming
546 std::string lvlSubdir = "";
547 if (trigger.second->getName().find("L1") == 0){
548 lvlSubdir = "Rate_ChainL1_HLT/";
549 } else if (trigger.second->getName().find("HLT") == 0) {
550 lvlSubdir = "Rate_ChainHLT_HLT/";
551 }
552 trigger.second->setDataName("data"+m_histogramSuffix);
553 ATH_CHECK( trigger.second->giveDataHist(histSvc(), std::string("/RATESTREAM/All/" + lvlSubdir + trigger.first + "/data")) );
554 trigger.second->setRateVsMuName("rateVsMu"+m_histogramSuffix);
555 ATH_CHECK( trigger.second->giveMuHist(histSvc(), std::string("/RATESTREAM/All/" + lvlSubdir + trigger.first + "/rateVsMu")) );
557 trigger.second->setRateVsTrainName("rateVsTrain"+m_histogramSuffix);
558 ATH_CHECK( trigger.second->giveTrainHist(histSvc(), std::string("/RATESTREAM/All/" + lvlSubdir + trigger.first + "/rateVsTrain")) );
559 } else trigger.second->clearTrainHist();
560 }
561 }
562 if (m_scanTriggers.size()) {
563 ATH_MSG_DEBUG("################## Registering scan trigger histograms:");
564 for (const auto& trigger : m_scanTriggers) {
565 trigger.second->setHistoName("rateVsThreshold"+m_histogramSuffix);
566 ATH_CHECK( trigger.second->giveThresholdHist(histSvc(), std::string("/RATESTREAM/ScanTriggers/" + trigger.first + "/rateVsThreshold" + m_histogramSuffix)) );
567 }
568 }
569 if (m_groups.size()) {
570 ATH_MSG_DEBUG("################## Registering group histograms:");
571 for (const auto& group : m_groups) {
572 if (!group.second->doHistograms()) continue;
573 std::string groupName = group.first;
574 std::replace( groupName.begin(), groupName.end(), ':', '_');
575 group.second->setDataName("data"+m_histogramSuffix);
576 ATH_CHECK( group.second->giveDataHist(histSvc(), std::string("/RATESTREAM/All/Rate_Group_HLT/" + groupName + "/data")) );
577 group.second->setRateVsMuName("rateVsMu"+m_histogramSuffix);
578 ATH_CHECK( group.second->giveMuHist(histSvc(), std::string("/RATESTREAM/All/Rate_Group_HLT/" + groupName + "/rateVsMu")) );
580 group.second->setRateVsTrainName("rateVsTrain"+m_histogramSuffix);
581 ATH_CHECK( group.second->giveTrainHist(histSvc(), std::string("/RATESTREAM/All/Rate_Group_HLT/" + groupName + "/rateVsTrain")) );
582 } else group.second->clearTrainHist();
583 }
584 }
585 if (m_globalGroups.size()) {
586 ATH_MSG_DEBUG("################## Registering global group histograms:");
587 for (const auto& group : m_globalGroups) {
588 if (!group.second->doHistograms()) continue;
589 group.second->setDataName("data"+m_histogramSuffix);
590 ATH_CHECK( group.second->giveDataHist(histSvc(), std::string("/RATESTREAM/All/Rate_Group_HLT/RATE_GLOBAL_" + group.first + "/data")) );
591 group.second->setRateVsMuName("rateVsMu"+m_histogramSuffix);
592 ATH_CHECK( group.second->giveMuHist(histSvc(), std::string("/RATESTREAM/All/Rate_Group_HLT/RATE_GLOBAL_" + group.first + "/rateVsMu")) );
594 group.second->setRateVsTrainName("rateVsTrain"+m_histogramSuffix);
595 ATH_CHECK( group.second->giveTrainHist(histSvc(), std::string("/RATESTREAM/All/Rate_Group_HLT/RATE_GLOBAL_" + group.first + "/rateVsTrain")) );
596 } else group.second->clearTrainHist();
597 }
598 }
599 }
600
601 // Has the user set a lumi extrapolation? If not - set a default
603
604 // We now know the final lumi scaling so we can set the bunch scaling
605 const uint32_t ebPairedBunches = m_enhancedBiasRatesTool->getPairedBunches();
606 ATH_MSG_INFO("Number of paired bunches in input file:" << m_enhancedBiasRatesTool->getPairedBunches());
607 m_weightingValues.m_bunchFactor = m_targetBunches / (double)ebPairedBunches;
608
609 return StatusCode::SUCCESS;
610}
611
612// HSTP filter from Jet/EtMiss
614
615 if (!m_doMultiSliceDiJet) {
616 return StatusCode::SUCCESS;
617 };
618
620 ATH_CHECK( truthHS_jets.isValid() );
622 ATH_CHECK( truthPU_jets.isValid() );
623
624 // Extract the pT of the leading jet that defines the hardness. The jet containers should always be pT sorted
625 const double pT_j1_truthPU = truthPU_jets->size() ? truthPU_jets->front()->pt() : 0; // Hardest PU truth jet
626 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
627
628 // Now see if we pass the filter.
629 pass = pT_j1_truthHS > pT_j1_truthPU;
630 ATH_MSG_DEBUG("Hard Scatter (" << pT_j1_truthHS/1000. << " GeV) Harder Than Pileup (" << pT_j1_truthPU/1000. << " GeV) filter " << (pass ? "PASSES" : "FAILS"));
631 return StatusCode::SUCCESS;
632}
633
635 ATH_MSG_VERBOSE("Executing " << name() << " on event " << m_eventCounter << "...");
636 if (m_eventCounter++ == 0) { // First time in execute loop - cannot access TDT before this.
638 }
639 const EventContext& ctx = Gaudi::Hive::currentContext();
640 // Get event characteristics
642 ATH_CHECK( eventInfo.isValid() );
643 uint32_t distance = 0;
644 ATH_CHECK( m_enhancedBiasRatesTool->getDistanceIntoTrain(eventInfo.get(), distance, ctx) );
645 const bool isMC = m_enhancedBiasRatesTool->isMC();
646
647 // Get the weighting & scaling characteristics
648 m_weightingValues.m_enhancedBiasWeight = m_enhancedBiasRatesTool->getEBWeight(eventInfo.get());
649 m_weightingValues.m_eventMu = std::ceil(eventInfo->actualInteractionsPerCrossing()); // This always seems to be a half integer
650 m_weightingValues.m_eventLumi = m_enhancedBiasRatesTool->getLBLumi(eventInfo.get());
651 m_weightingValues.m_isUnbiased = m_enhancedBiasRatesTool->isUnbiasedEvent(eventInfo.get());
652 m_weightingValues.m_distanceInTrain = distance;
653 m_weightingValues.m_eventLiveTime = m_enhancedBiasRatesTool->getEBLiveTime(eventInfo.get());
654 if (m_useBunchCrossingData && m_vetoStartOfTrain > 0 && m_weightingValues.m_distanceInTrain < m_vetoStartOfTrain) return StatusCode::SUCCESS;
655
656 // Bunch factor doesn't change as a fn. of the run. Reminder: m_bunchFactor = m_targetBunches / (double)ebPairedBunches;
657 m_weightingValues.m_muFactor = (m_weightingValues.m_eventMu ? m_targetMu / m_weightingValues.m_eventMu : 0.0);
658 m_weightingValues.m_linearLumiFactor = m_targetLumi / m_weightingValues.m_eventLumi;
659 m_weightingValues.m_expoMuFactor = m_weightingValues.m_bunchFactor * exp( m_expoScalingFactor * (m_targetMu - m_weightingValues.m_eventMu) );
660
661 // Ignore zero weighted events. Typically these come from bad LB
662 if (RatesHistoBase::isZero(m_weightingValues.m_enhancedBiasWeight)) {
663 return StatusCode::SUCCESS;
664 }
665
666 const double weightedEvents = (isMC ? eventInfo->mcEventWeight() : m_weightingValues.m_enhancedBiasWeight);
667 m_weightedEventCounter += weightedEvents;
668
669 double ratesDenominator = 0.0;
671 ratesDenominator = eventInfo->mcEventWeight(); // In multi-slice mode we only normalize to the weighted number of events
672 } else {
673 ratesDenominator = m_weightingValues.m_eventLiveTime * (isMC ? eventInfo->mcEventWeight() : 1.0); // Otherwise, we need to keep track of elapsed walltime as well
674 }
675 m_ratesDenominator += ratesDenominator;
676
677 if (m_doHistograms) {
678 m_bcidHist->Fill(eventInfo->bcid(), m_weightingValues.m_enhancedBiasWeight);
679 m_scalingHist->Fill(0.5, ratesDenominator); // Walltime
680 m_scalingHist->Fill(1.5, 1.); // Total events
681 m_scalingHist->Fill(2.5, weightedEvents ); // Total weighted events
682 }
683
684 // HSTP filter check
685 if (isMC) {
686 bool filterPass = true;
687 ATH_CHECK( pass_HstpFilter(filterPass) );
688 if (!filterPass) {return StatusCode::SUCCESS;}
689 }
690
691 // Do automated triggers
693
694 // Do TDT-controlled triggers
696
697 // Run user's code. Do manual triggers
699
700 // Execute groups
701 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.
702 for (const auto& group : m_activeGroups) group->execute(m_weightingValues); // Individual groups, CPS groups and active unique groups. Set.
703
704 // Reset triggers
705 for (const auto& trigger : m_activatedTriggers) trigger->reset();
706 m_activatedTriggers.clear();
707
708 // Some debug info
709 if (m_eventCounter % 1000 == 0) {
710 ATH_MSG_INFO( "Event " << m_eventCounter << " " << m_weightingValues.print() << " currentWallTime:" << m_ratesDenominator );
711 }
712
713 setFilterPassed(true); //if got here, assume that means algorithm passed
714 return StatusCode::SUCCESS;
715}
716
718 for (const auto& trigger : m_existingTriggers) {
719 const bool passed = trigger.second->isPassed();
720 // L1 chains are always active, HLT chains are active if their L1 passed.
721 const std::string& lower = m_lowerTrigger[trigger.first];
722 // Expect this find operation to fail for L1 chains (lower = "")
723 const std::unordered_map<std::string, const Trig::ChainGroup*>::const_iterator it = m_existingTriggers.find(lower);
724 const bool active = (it == m_existingTriggers.end() ? true : it->second->isPassed());
725 ATH_CHECK( setTriggerDesicison(trigger.first, passed, active) );
726 }
727 return StatusCode::SUCCESS;
728}
729
731 // TODO emulation code here
732 for (const auto& trigger : m_autoTriggers) {
733 ATH_MSG_WARNING("Cannot do rates for " << trigger << ". Automatic trigger emulation is not yet included, sorry :(");
734 }
735 return StatusCode::SUCCESS;
736}
737
739 ATH_MSG_INFO ("Finalizing " << name() << "...");
740
742 if (!m_doMultiSliceDiJet) { // Cannot estimate multi-slice rates before the merging stage
743 if (m_scanTriggers.size()) {
744 ATH_MSG_INFO("################## Computed Rate Scans for Threshold-Scan Items:");
745 for (const auto& trigger : m_scanTriggers) ATH_MSG_INFO(trigger.second->printRate(m_ratesDenominator));
746 }
747 if (m_triggers.size()) {
748 ATH_MSG_INFO("################## Computed Rate Estimations for Single Items:");
749 std::set<std::string> keys; // Used an unordered map for speed, but now we'd like the items in order
750 for (const auto& trigger : m_triggers) keys.insert(trigger.first);
751 for (const std::string& key : keys) ATH_MSG_INFO(m_triggers.at(key)->printRate(m_ratesDenominator));
752 }
753 if (m_expressTriggers.size()) {
754 ATH_MSG_INFO("################## Computed Express Rate Estimations for Single Items:");
755 for (const auto& trigger : m_expressTriggers) ATH_MSG_INFO(trigger->printExpressRate(m_ratesDenominator));
756 }
757 if (m_groups.size()) {
758 ATH_MSG_INFO("################## Computed Rate Estimations for Groups:");
759 for (const auto& group : m_groups) ATH_MSG_INFO(group.second->printRate(m_ratesDenominator));
760 }
761 if (m_globalGroups.size()) {
762 ATH_MSG_INFO("################## Computed Rate Estimations for Global Groups:");
763 for (const auto& group : m_globalGroups) ATH_MSG_INFO(group.second->printRate(m_ratesDenominator));
764 }
765 }
766 ATH_MSG_INFO("################## LHC Conditions and weighting information:");
768 printTarget();
770 ATH_MSG_INFO("##################");
772
773 return StatusCode::SUCCESS;
774}
775
776void RatesAnalysisAlg::setTargetLumiMu(const double lumi, const double mu) {
777 if (m_eventCounter > 1) { // All settings must be defined before we start looping over the sample
778 ATH_MSG_WARNING("Too late to call setTargetLumiMu. Do this during ratesInitialize().");
779 return;
780 }
781 m_targetLumi = lumi;
782 if (isZero(mu)) {
783 ATH_MSG_WARNING("Cannot have <mu> = 0. Setting to 1.");
784 m_targetMu = 1;
785 } else {
786 m_targetMu = mu;
787 }
790 ATH_MSG_WARNING("Un-physical number of bunches " << m_targetBunches << ", should be within 1 < N < " << EnhancedBiasWeighter::FULL_RING+1);
792 }
793 printTarget();
794}
795
796void RatesAnalysisAlg::setTargetLumiBunches(const double lumi, const int32_t bunches) {
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 setTargetLumiBunches. Do this during ratesInitialize().");
799 return;
800 }
801 m_targetLumi = lumi;
802 if (bunches == 0) {
803 ATH_MSG_WARNING("Cannot have bunches = 0. Setting to 1.");
804 m_targetBunches = 1;
805 } else {
806 m_targetBunches = bunches;
807 }
809 printTarget();
810}
811
812
813void RatesAnalysisAlg::setTargetMuBunches(const double mu, const int32_t bunches) {
814 if (m_eventCounter > 1) { // All settings must be defined before we start looping over the sample
815 ATH_MSG_WARNING("Too late to call setTargetMuBunches. Do this during ratesInitialize().");
816 return;
817 }
818 if (bunches == 0) {
819 ATH_MSG_WARNING("Cannot have paired bunches = 0. Setting to 1.");
820 m_targetBunches = 1;
821 } else {
822 m_targetBunches = bunches;
823 }
824 if (isZero(mu)) {
825 ATH_MSG_WARNING("Cannot have mu = 0. Setting to 1.");
826 m_targetMu = 1;
827 } else {
828 m_targetMu = mu;
829 }
831 printTarget();
832}
833
836 ATH_MSG_INFO("Calculating rates for a target L_inst. = " << m_targetLumi << " cm-2s-1, mu = " << m_targetMu << ", paired bunches = " << m_targetBunches);
837 } else {
838 ATH_MSG_INFO("Luminosity extrapolation is switched off. Input files will determin the paired bunches, L_inst. and mu profile.");
839 }
840}
841
843 ATH_MSG_INFO("Processed " << m_eventCounter << " raw events, " << m_weightedEventCounter << " weighted. Total LHC wall-time of " << m_ratesDenominator << " s.");
844}
845
847 ATH_MSG_INFO("Input " << (m_enhancedBiasRatesTool->isMC() ? "MC" : "EB Data")
848 << " with <L_inst.> = "
849 << m_enhancedBiasRatesTool->getAverageLumi()
850 << " cm-2s-1, <mu> = "
851 << m_enhancedBiasRatesTool->getAverageMu()
852 << ", paired bunches = "
853 << m_enhancedBiasRatesTool->getPairedBunches());
854}
855
856bool RatesAnalysisAlg::isCPS(const std::string& group) const {
857 return (group.find("CPS") != std::string::npos);
858}
859
860bool RatesAnalysisAlg::isRandomSeed(const std::string& me, const std::string& seed) const {
861 if (me.find("L1_RD") != std::string::npos) return true;
862 if (me.find("L1RD") != std::string::npos) return true;
863 if (seed.find("L1_RD") != std::string::npos) return true;
864 return false;
865}
866
867uint32_t RatesAnalysisAlg::getLevel(const std::string& name) const {
868 if (name.find("HLT_") != std::string::npos) return 2;
869 if (name.find("L1_") != std::string::npos) return 1;
870 return 2;
871}
872
874 if (!m_metadataTree) {
875 return;
876 }
877 m_runNumber = m_enhancedBiasRatesTool->getRunNumber();
878 m_metadataTree->Branch("runNumber", &m_runNumber);
879 m_metadataTree->Branch("targetMu", &m_targetMu);
880 m_metadataTree->Branch("targetBunches", &m_targetBunches);
881 m_metadataTree->Branch("targetLumi", &m_targetLumi);
882
883 double bunchCrossingRate = m_enhancedBiasRatesTool->getBunchCrossingRate();
884 m_metadataTree->Branch("bunchCrossingRate", &bunchCrossingRate);
885 int doMultiSliceDiJet = m_doMultiSliceDiJet;
886 m_metadataTree->Branch("multiSliceDiJet", &doMultiSliceDiJet);
887
888 std::vector<std::string> triggers;
889 std::vector<std::string> lowers;
890 std::vector<double> prescales;
891 std::vector<double> express;
892 triggers.reserve(m_triggers.size());
893 lowers.reserve(m_triggers.size());
894 prescales.reserve(m_triggers.size());
895 express.reserve(m_triggers.size());
896 for (const auto& trigger : m_triggers) {
897 triggers.push_back(trigger.first);
898 lowers.push_back(trigger.second->getSeedName());
899 prescales.push_back(trigger.second->getPrescale() );
900 express.push_back(trigger.second->getPrescale(true /*includeExpress*/) );
901 }
902 for (const auto& group : m_groups) {
903 triggers.push_back(group.first);
904 lowers.push_back("-");
905 prescales.push_back(-1);
906 express.push_back(-1);
907 }
908 for (const auto& group : m_globalGroups) {
909 triggers.push_back("RATE_GLOBAL_" + group.first);
910 lowers.push_back("-");
911 prescales.push_back(-1);
912 express.push_back(-1);
913 }
914 m_metadataTree->Branch("triggers", &triggers);
915 m_metadataTree->Branch("lowers", &lowers);
916 m_metadataTree->Branch("prescales", &prescales);
917 m_metadataTree->Branch("express", &express);
918 std::vector<int32_t> bunchGroups;
919 bunchGroups.reserve(16);
920
921 uint32_t masterKey = 0;
922 uint32_t hltPrescaleKey = 0;
923 uint32_t lvl1PrescaleKey = 0;
924
925 if(!m_enhancedBiasRatesTool->isMC()){
926 bunchGroups = m_enhancedBiasRatesTool->getBunchGroups();
927 }
928 if(!m_configSvc.empty() && m_configSvc.isValid() ){
929 if ((bunchGroups.size() == 0 || std::all_of(bunchGroups.begin(), bunchGroups.end(), [](int i) { return i==0; }) ) && (!m_enhancedBiasRatesTool->isMC())) {
930 const TrigConf::L1BunchGroupSet& bgs = m_configSvc->l1BunchGroupSet(Gaudi::Hive::currentContext());
931 for (size_t i = 0; i < bgs.maxNBunchGroups(); ++i ) {
932 bunchGroups.push_back(bgs.getBunchGroup(i)->size());
933 }
934 }
935 masterKey = m_configSvc->masterKey();
936 hltPrescaleKey = m_configSvc->hltPrescaleKey();
937 lvl1PrescaleKey = m_configSvc->lvl1PrescaleKey();
938 }
939
940
941 m_metadataTree->Branch("bunchGroups", &bunchGroups);
942
943 m_metadataTree->Branch("hltChainIDGroup", &m_hltChainIDGroup);
944 m_metadataTree->Branch("l1ItemID", &m_l1ItemID);
945
946 m_metadataTree->Branch("masterKey", &masterKey);
947 m_metadataTree->Branch("lvl1PrescaleKey", &lvl1PrescaleKey);
948 m_metadataTree->Branch("hltPrescaleKey", &hltPrescaleKey);
949 std::string atlasProject = std::getenv("AtlasProject");
950 std::string atlasVersion = std::getenv("AtlasVersion");
951 m_metadataTree->Branch("AtlasProject", &atlasProject);
952 m_metadataTree->Branch("AtlasVersion", &atlasVersion);
953 m_metadataTree->Fill();
954}
#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.
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
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
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()
In first call - register all triggers.
StatusCode populateTriggers()
Register all triggers to emulate.
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.
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
One-bin histogram to store the normalisation of the sample, for use in later combinations.
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:28
ConstIter< ptree, L1Item > const_iterator
Iterator over the L1 items.
Definition L1Menu.h:64
L1 menu configuration.
const std::map< std::string, L1Prescale > & prescales() const