ATLAS Offline Software
Loading...
Searching...
No Matches
EnhancedBiasWeighter.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// EnhancedBiasWeighter includes
7
9
10#include "TXMLEngine.h"
11#include "TObjString.h"
12#include "TDOMParser.h"
13#include "TXMLNode.h"
14#include "TXMLDocument.h"
15#include "TXMLAttr.h"
16
17#include <memory>
18#include <filesystem>
19
20namespace {
21 template <typename T>
22 T stringToNum(const std::string& i) {
23 T ret;
24 std::istringstream( i ) >> ret;
25 return ret;
26 }
27}
28
30 : asg::AsgTool( name ),
31 m_deadtime(1.),
34{}
35
37{
38 ATH_MSG_DEBUG ("Initializing " << name() << "...");
40
41 if (m_isMC) {
42
43 if (m_mcCrossSection == 0 || m_mcFilterEfficiency == 0) {
44 ATH_MSG_FATAL("For MC rates, a cross section and filter efficiency must be supplied.");
45 return StatusCode::FAILURE;
46 }
47 m_deadtime = 1.; // No deadtime for MC
48 m_pairedBunches = FULL_RING; // Assume full-ring
49 const double mcCrossSectionInSqCm = 1e-33 * m_mcCrossSection; // Convert nb -> cm^2
51 ATH_MSG_INFO ("Running over MC with xsec:" << m_mcCrossSection << " nb, filter efficiency:" << m_mcFilterEfficiency << ", k-factor:" << m_mcKFactor);
52
53 } else { // isData
54
55 if (m_runNumber == 0u) {
56 ATH_MSG_FATAL("calculateWeightingData is TRUE, but the RunNumber property has not been set. This must be set such that we can read in the correct data.");
57 return StatusCode::FAILURE;
58 }
59 ATH_MSG_INFO ("calculateWeightingData is TRUE. This job will read in EnhancedBias weighting data from CVMFS and COOL.");
62
63 } // end isData
64
65
66 return StatusCode::SUCCESS;
67}
68
70{
71 ATH_MSG_DEBUG ("Finalizing " << name() << "...");
72 return StatusCode::SUCCESS;
73}
74
76{
77 // Construct name
78 std::stringstream fileName;
79 const uint32_t runNumber = m_runNumber; // This is because Gaudi::Properties have special behaviour with the << operator
80 fileName << "EnhancedBiasWeights_" << runNumber << ".xml";
81 std::string weightingFile = (!m_weightsDirectory.empty()) ? findLocalFile(fileName.str()) : PathResolverFindCalibFile("TrigCostRootAnalysis/" + fileName.str() ); // Check standard area
82
83 ATH_MSG_DEBUG("Using weighting file " << weightingFile);
84
85 if (weightingFile.empty()) {
86 msg() << (m_errorOnMissingEBWeights ? MSG::ERROR : MSG::WARNING) << "Could not retrieve " << fileName.str() << ", cannot perform enhanced bias weighting." << endmsg;
87 return (m_errorOnMissingEBWeights ? StatusCode::FAILURE : StatusCode::SUCCESS);
88 }
89
90 std::unique_ptr<TXMLEngine> xml(new TXMLEngine() );
91 XMLDocPointer_t xmlDoc = xml->ParseFile( weightingFile.c_str() );
92
93 if (xmlDoc == nullptr) {
94 ATH_MSG_WARNING ("Could not parse " << fileName.str() << ", cannot perform enhanced bias weighting.");
95 return StatusCode::FAILURE;
96 }
97
98 // Navigate XML
99 const XMLNodePointer_t mainNode = xml->DocGetRootElement(xmlDoc);
100 if ( xml->GetNodeName(mainNode) != std::string("run") ) {
101 ATH_MSG_ERROR ("Canot parse XML. Expected 'run' node, got " << xml->GetNodeName(mainNode));
102 return StatusCode::FAILURE;
103 }
104 const XMLNodePointer_t weightsNode = xml->GetChild( mainNode );
105 const XMLNodePointer_t eventsNode = xml->GetNext( weightsNode );
106
107 XMLNodePointer_t weightNode = xml->GetChild( weightsNode );
108 XMLNodePointer_t eventNode = xml->GetChild( eventsNode );
109
110 while ( weightNode != 0 ) { // Loop over all weight elements
111 if ( xml->GetNodeName(weightNode) != std::string("weight") ) {
112 ATH_MSG_ERROR ("Canot parse XML. Expected 'weight' node, got " << xml->GetNodeName(weightNode));
113 return StatusCode::FAILURE;
114 }
115
116 const int32_t id = std::atoi(xml->GetAttr(weightNode, "id") );
117 const double weight = std::atof(xml->GetAttr(weightNode, "value") );
118 int32_t unbiased = 0;
119 if ( xml->HasAttr(weightNode, "unbiased") == true ) {
120 unbiased = std::atoi(xml->GetAttr(weightNode, "unbiased"));
121 }
122
123 m_idToWeightMap[id] = weight;
124 m_idToUnbiasedMap[id] = unbiased;
125
126 weightNode = xml->GetNext(weightNode);
127 }
128
129 while ( eventNode != 0 ) { // Loop over all event elements
130 if ( xml->GetNodeName(eventNode) != std::string("e") ) {
131 ATH_MSG_ERROR ("Canot parse XML. Expected 'e' (event) node, got " << xml->GetNodeName(eventNode));
132 return StatusCode::FAILURE;
133 }
134 const uint64_t eventNumber = std::strtoll(xml->GetAttr(eventNode, "n"), nullptr, 10); //Number
135 const int32_t eventWeightID = std::stoi(xml->GetAttr(eventNode, "w") ); //Weight ID
136
137 m_eventNumberToIdMap[eventNumber] = eventWeightID;
138
139 eventNode = xml->GetNext(eventNode);
140 }
141
142 ATH_MSG_INFO ("Loaded " << m_eventNumberToIdMap.size() << " event weights for run " << runNumber);
143 return StatusCode::SUCCESS;
144}
145
147{
148 // Fetch LB time from COOL for this run
149 const uint32_t runNumber = m_runNumber;
150 if (m_readLumiBlock.updateLumiBlocks(runNumber, msg()) == false) {
151 ATH_MSG_FATAL("Unable to load this runs luminosity values from COOL.");
152 return StatusCode::FAILURE;
153 }
154
155 // Read in number of events to expect
156 // Construct name
157 std::stringstream fileName;
158 fileName << "enhanced_bias_run_" << runNumber << ".xml";
159 std::string runFile = (!m_weightsDirectory.empty()) ? findLocalFile(fileName.str()) : PathResolverFindCalibFile("TrigCostRootAnalysis/" + fileName.str() ); // Check standard area
160
161 ATH_MSG_DEBUG("Using run file " << runFile);
162 if (runFile.empty()) {
163 msg() << (m_errorOnMissingEBWeights ? MSG::ERROR : MSG::WARNING) << "Could not retrieve " << fileName.str() << ", cannot perform enhanced bias weighting." << endmsg;
164 return (m_errorOnMissingEBWeights ? StatusCode::FAILURE : StatusCode::SUCCESS);
165 }
166
167 std::unique_ptr<TXMLEngine> xml(new TXMLEngine());
168 const XMLDocPointer_t xmlDoc = xml->ParseFile( runFile.c_str() );
169
170 if (xmlDoc == nullptr) {
171 ATH_MSG_FATAL ("Could not parse " << fileName.str() << ", cannot perform enhanced bias weighting.");
172 return StatusCode::FAILURE;
173 }
174
175 const XMLNodePointer_t mainNode = xml->DocGetRootElement(xmlDoc);
176 if ( xml->GetNodeName(mainNode) != std::string("trigger") ) {
177 ATH_MSG_ERROR ("Canot parse XML. Expected 'trigger' node, got " << xml->GetNodeName(mainNode));
178 return StatusCode::FAILURE;
179 }
180 XMLNodePointer_t listNode = xml->GetChild( mainNode );
181
182 while ( listNode != 0 ) { // Loop over all menu elements
183 const std::string listName = xml->GetNodeName(listNode);
184
185 if (listName == "lb_list") {
186
187 XMLNodePointer_t node = xml->GetChild( listNode );
188 while( node != 0) {
189 if ( xml->GetNodeName(node) != std::string("lb") ) {
190 ATH_MSG_ERROR ("Canot parse XML. Expected 'lb' node, got " << xml->GetNodeName(node));
191 return StatusCode::FAILURE;
192 }
193 const uint32_t lb = std::atoi( xml->GetAttr(node, "id") );
194 const double lumi = std::atof( xml->GetAttr(node, "lumi") );
195 const uint32_t nEvents = std::atoi( xml->GetNodeContent(node) );
196 const std::string flag = xml->HasAttr(node, "flag") ? xml->GetAttr(node, "flag") : "";
197
199 m_goodLB[lb] = (flag == "bad" ? 0 : 1);
200 m_lumiPerLB[lb] = lumi < 1e10 ? 1e30 * lumi : lumi;
201
202 if (xml->HasAttr(node, "deadtime")) {
203 // Deadtime is a weight factor, the weight will be multiplied by deadtime + 1
204 m_deadtimePerLB[lb] = 1. + std::atof( xml->GetAttr(node, "deadtime") );
205 }
206
207 node = xml->GetNext(node);
208 }
209
210 } else if (listName == "lumivalues") {
211
212 XMLNodePointer_t node = xml->GetChild( listNode );
213 while( node != 0) {
214 if ( xml->GetNodeName(node) == std::string("deadtime") ) {
215 m_deadtime = 1. + std::atof( xml->GetNodeContent(node) );
216 }
217 node = xml->GetNext(node);
218 }
219
220 } else if (listName == "bunchgroups") {
221
222 XMLNodePointer_t node = xml->GetChild( listNode );
223 while( node != 0) {
224 m_bunches.push_back( std::atoi( xml->GetNodeContent(node) ) );
225 if ( xml->GetNodeName(node) == std::string("bunchgroup") && xml->HasAttr(node, "name") &&
226 (std::string(xml->GetAttr(node, "name")) == "Paired" || std::string(xml->GetAttr(node, "name")) == "Filled")) {
227 m_pairedBunches = std::atoi( xml->GetNodeContent(node) );
228 }
229 node = xml->GetNext(node);
230 }
231
232 } else if (listName == "filters") {
233
234 ATH_MSG_DEBUG("Found filters section of enhanced bias XML. Unused by this application.");
235
236 } else {
237
238 ATH_MSG_INFO("Encountered unknown element in enhanced bias XML: " << listName << " ignoring it.");
239
240 }
241
242 listNode = xml->GetNext(listNode);
243 }
244
245 ATH_MSG_INFO ("Loaded " << m_eventsPerLB.size() << " EnhancedBias lumi block's info for run " << runNumber);
246 return StatusCode::SUCCESS;
247}
248
249std::unordered_map<std::string, ChainDetail> EnhancedBiasWeighter::parsePrescaleXML(const std::string& prescaleXML) const {
250 std::unordered_map<std::string, ChainDetail> result;
251
252 std::string xmlFile = PathResolverFindDataFile( prescaleXML );
253 if (xmlFile.empty()) {
254 ATH_MSG_ERROR ("Could not retrieve " << prescaleXML << ", place it somewhere PathResolver can find it (such as the current directory).");
255 return result;
256 }
257
258 std::unique_ptr<TXMLEngine> xml(new TXMLEngine());
259 const XMLDocPointer_t xmlDoc = xml->ParseFile( xmlFile.c_str() );
260
261 if (xmlDoc == nullptr) {
262 ATH_MSG_WARNING ("Could not parse " << prescaleXML << ", please check that it is valid XML.");
263 return result;
264 }
265
266 // Get access to main node
267 XMLNodePointer_t mainNode = xml->DocGetRootElement(xmlDoc);
268 if ( xml->GetNodeName(mainNode) != std::string("trigger") ) {
269 ATH_MSG_ERROR ("Canot parse XML. Expected 'trigger' node, got " << xml->GetNodeName(mainNode));
270 return result;
271 }
272 XMLNodePointer_t listNode = xml->GetChild( mainNode );
273
274
275 while ( listNode != nullptr) { // Loop over all menu elements
276 const std::string listName = xml->GetNodeName(listNode);
277
278 // if (_listName == "PredictionLumi") {
279 // Float_t predictionLumi = stringToFloat( xml->GetNodeContent(listNode) );
280 // }
281 if (listName != "level") { // Find the "level" item
282 listNode = xml->GetNext(listNode);
283 continue;
284 }
285
286 XMLNodePointer_t sigNode = xml->GetChild( listNode );
287 while( sigNode != nullptr) {
288 if (xml->GetNodeName(sigNode) != std::string("signature")) { // Find the "signature" items
289 sigNode = xml->GetNext(sigNode);
290 continue;
291 }
292
293 XMLNodePointer_t sigDetailsNode = xml->GetChild( sigNode );
294 std::string chainName;
295 while( sigDetailsNode != nullptr) {
296
297 if (xml->GetNodeContent(sigDetailsNode) == nullptr) {
298 sigDetailsNode = xml->GetNext(sigDetailsNode);
299 continue;
300 }
301
302 const std::string detail = xml->GetNodeName(sigDetailsNode);
303 if (detail == "sig_name") {
304 chainName = xml->GetNodeContent(sigDetailsNode);
305 result[chainName] = ChainDetail();
306 } else if (detail == "sig_counter") {
307 result[chainName].m_counter = std::stoi( xml->GetNodeContent(sigDetailsNode) );
308 } else if (detail == "prescale" || detail == "chain_prescale") { // This is an alternate name
309 result[chainName].m_prescale = std::stod( xml->GetNodeContent(sigDetailsNode) );
310 } else if (detail == "lower_chain_name") {
311 // Later processing here does not expect any spaces, so remove them now. Pure comma separated list
312 std::string lower = xml->GetNodeContent(sigDetailsNode);
313 while (lower.find(" ") != std::string::npos) lower.replace( lower.find(" "), 1, "");
314 result[chainName].m_lowerName = std::move(lower);
315 } else if (detail == "evts_passed") {
316 result[chainName].m_eventsPassed = std::stod( xml->GetNodeContent(sigDetailsNode) );
317 } else if (detail == "evts_passed_weighted") {
318 result[chainName].m_eventsPassedWeighted = std::stod( xml->GetNodeContent(sigDetailsNode) );
319 } else if (detail == "rate") {
320 result[chainName].m_rate = std::stod( xml->GetNodeContent(sigDetailsNode) );
321 } else if (detail == "rate_err") {
322 result[chainName].m_rateErr = std::stod( xml->GetNodeContent(sigDetailsNode) );
323 } else if (detail == "passthrough") {
324 result[chainName].m_passthroughPrescale = std::stod( xml->GetNodeContent(sigDetailsNode) );
325 } else if (detail == "rerun_prescale") {
326 result[chainName].m_rerunPrescale = std::stod( xml->GetNodeContent(sigDetailsNode) );
327 } else if (detail == "express_prescale") {
328 result[chainName].m_expressPrescale = std::stod( xml->GetNodeContent(sigDetailsNode) );
329 } else if (detail == "efficiency") {
330 result[chainName].m_efficiency = std::stod( xml->GetNodeContent(sigDetailsNode) );
331 } else if (detail == "efficiency_err") {
332 result[chainName].m_efficiencyErr = std::stod( xml->GetNodeContent(sigDetailsNode) );
333 } else if (detail == "prescaled_efficiency") {
334 result[chainName].m_prescaledEfficiency = std::stod( xml->GetNodeContent(sigDetailsNode) );
335 } else if (detail == "prescaled_efficiency_error") {
336 result[chainName].m_prescaledEfficiencyErr = std::stod( xml->GetNodeContent(sigDetailsNode) );
337 } else if (detail == "comment") {
338 result[chainName].m_comment = xml->GetNodeContent(sigDetailsNode);
339 } else {
340 ATH_MSG_DEBUG("Input prescales XML contains additional data which cannot be parsed at present:" << detail);
341 }
342
343 sigDetailsNode = xml->GetNext(sigDetailsNode);
344 }
345 sigNode = xml->GetNext(sigNode);
346 }
347 listNode = xml->GetNext(listNode);
348 }
349
350 return result;
351}
352
354{
355 const uint64_t eventNumber = eventInfo->eventNumber();
356
357 const auto mapIterator = m_eventNumberToIdMap.find(eventNumber);
358 if (mapIterator != m_eventNumberToIdMap.end()) {
359 return mapIterator->second;
360 }
361 // Unfortunately, earlier weighting XMLs have 32 bit signed event number. Hence we also have to try this option
362 const int32_t eventNumber32 = static_cast<int32_t>(eventNumber);
363 const auto mapIterator32 = m_eventNumberToIdMap.find(eventNumber32);
364 if (mapIterator32 != m_eventNumberToIdMap.end()) {
365 return mapIterator32->second;
366 } else {
367 ATH_MSG_ERROR( "Couldn't find enhanced bias info for event " << eventNumber);
368 return -1;
369 }
370}
371
372int32_t EnhancedBiasWeighter::getEventEBID(const EventContext& context) const
373{
374 const uint64_t eventNumber = context.eventID().event_number();
375
376 const auto mapIterator = m_eventNumberToIdMap.find(eventNumber);
377 if (mapIterator != m_eventNumberToIdMap.end()) {
378 return mapIterator->second;
379 }
380 // Unfortunately, earlier weighting XMLs have 32 bit signed event number. Hence we also have to try this option
381 const int32_t eventNumber32 = static_cast<int32_t>(eventNumber);
382 const auto mapIterator32 = m_eventNumberToIdMap.find(eventNumber32);
383 if (mapIterator32 != m_eventNumberToIdMap.end()) {
384 return mapIterator32->second;
385 } else {
386 ATH_MSG_ERROR( "Couldn't find enhanced bias info for event " << eventNumber);
387 return -1;
388 }
389}
390
392{
393 if (m_enforceEBGRL && !isGoodLB(eventInfo)) {
394 return 0;
395 }
396
397 ATH_CHECK( trackAverages(eventInfo), 0 );
398
400 return static_cast<double>(eventInfo->mcEventWeight(0)) * m_mcModifiedCrossSection * m_targetLumi;
401
402 } else if (m_isMC) {
403
405 return 1.;
406 }
407
408 const std::vector<float> weights = eventInfo->mcEventWeights();
409 if (!weights.empty()) {
410 return weights[0];
411 }
412 return 1.;
413
414 } else { // isData
415
416 int32_t ebID = getEventEBID(eventInfo);
417 const auto mapIterator = m_idToWeightMap.find(ebID);
418 if (mapIterator == m_idToWeightMap.end() ) {
419 ATH_MSG_ERROR( "Couldn't find enhanced bias weight for event with ID " << ebID);
420 return 0;
421 }
422 return mapIterator->second;
423
424 } // isData
425}
426
427
428double EnhancedBiasWeighter::getEBWeight(const EventContext& context) const
429{
430
431 if (m_enforceEBGRL && !isGoodLB(context)) {
432 return 0;
433 }
434
435 ATH_CHECK( trackAverages(context), 0 );
436
437 if (m_isMC) {
438
439 ATH_MSG_ERROR( "Cannot use EventContext based getEBWeight with MC. Needs full EventInfo.");
440 return 0.;
441
442 } else { // isData
443
444 int32_t ebID = getEventEBID(context);
445 const auto mapIterator = m_idToWeightMap.find(ebID);
446 if (mapIterator == m_idToWeightMap.end() ) {
447 ATH_MSG_ERROR( "Couldn't find enhanced bias weight for event with ID " << ebID);
448 return 0;
449 }
450 return mapIterator->second;
451
452 } // isData
453}
454
455
456StatusCode EnhancedBiasWeighter::trackAverages(const EventContext& context) const
457{
458 m_lumiAverage += getLBLumi(context);
459 return StatusCode::SUCCESS;
460}
461
462
463StatusCode EnhancedBiasWeighter::trackAverages(const xAOD::EventInfo* eventInfo) const
464{
465 m_muAverage += std::ceil( eventInfo->actualInteractionsPerCrossing() );
466 m_lumiAverage += getLBLumi(eventInfo);
467 return StatusCode::SUCCESS;
468}
469
474{
475 if (m_isMC) {
476
477 // Probability that a single pp interaction yields this MC process (ratio of xsec)
478 const double probOfProcess = m_mcModifiedCrossSection / m_inelasticCrossSection;
479 // Probability that a single bunch-crossing yeild this MC process. Binomial statistics (1 - Prob(exactly 0 interactions, given mu interactions)).
480 const double probOfBunchCrossing = 1. - std::pow( 1. - probOfProcess, std::ceil(eventInfo->actualInteractionsPerCrossing()) );
481 const double bunchCrossingRate = m_pairedBunches * LHC_FREQUENCY;
482 // How much wall-time does this event represent? This is the reciprocal of the rate, which is the % per crossing scaled by the crossing rate.
483 ATH_MSG_DEBUG("MC livetime debug: probOfProcess:" << probOfProcess << " probOfBunchCrossing:" << probOfBunchCrossing << " bunchCrossingRate:" << bunchCrossingRate << " time:" << (1. / (probOfBunchCrossing * bunchCrossingRate)));
484 return 1. / (probOfBunchCrossing * bunchCrossingRate);
485
486 } else {
487
488 uint32_t lumiBlock = eventInfo->lumiBlock();
489 std::lock_guard<std::mutex> scopeLock(m_mutex);
490
491 // Check the cache
492 const auto inCacheIterator = m_eventLivetime.find( lumiBlock );
493 if (inCacheIterator != m_eventLivetime.end()) return inCacheIterator->second;
494
495 // Else calculate
496 const auto mapIterator = m_eventsPerLB.find(lumiBlock);
497 if (mapIterator == m_eventsPerLB.end() ) {
499 ATH_MSG_ERROR( "Couldn't find LB info for LB: " << lumiBlock );
500 }
501 return 0;
502 }
503 const int32_t eventsInThisLB = mapIterator->second;
504 const double lbLength = m_readLumiBlock.getLumiBlockLength(lumiBlock, msg());
505 // This event is one in eventsInThisLB, so has an effective temporal contribution of:
506 double eventLivetime = 0;
507 if (eventsInThisLB > 0 && std::fabs(lbLength) > 1e-10) eventLivetime = (1. / static_cast<double>(eventsInThisLB)) * lbLength;
508 // Cache this (mutable)
509 m_eventLivetime[lumiBlock] = eventLivetime;
510 return eventLivetime;
511
512 } // isData
513}
514
515double EnhancedBiasWeighter::getEBLiveTime(const EventContext& context) const
516{
517 if (m_isMC) {
518
519 ATH_MSG_ERROR( "Cannot use EventContext based getEBLiveTime with MC. Needs full EventInfo.");
520 return 0.;
521
522 } else {
523
524 uint32_t lumiBlock = context.eventID().lumi_block();
525 std::lock_guard<std::mutex> scopeLock(m_mutex);
526
527 // Check the cache
528 const auto inCacheIterator = m_eventLivetime.find( lumiBlock );
529 if (inCacheIterator != m_eventLivetime.end()) return inCacheIterator->second;
530
531 // Else calculate
532 const auto mapIterator = m_eventsPerLB.find(lumiBlock);
533 if (mapIterator == m_eventsPerLB.end() ) {
535 ATH_MSG_ERROR( "Couldn't find LB info for LB: " << lumiBlock );
536 }
537 return 0.;
538 }
539 const int32_t eventsInThisLB = mapIterator->second;
540 const double lbLength = m_readLumiBlock.getLumiBlockLength(lumiBlock, msg());
541 // This event is one in eventsInThisLB, so has an effective temporal contribution of:
542 double eventLivetime = 0;
543 if (eventsInThisLB > 0 && std::fabs(lbLength) > 1e-10) eventLivetime = (1. / static_cast<double>(eventsInThisLB)) * lbLength;
544 // Cache this (mutable)
545 m_eventLivetime[lumiBlock] = eventLivetime;
546 return eventLivetime;
547
548 } // isData
549
550}
551
553 if (m_isMC) {
554 ATH_MSG_ERROR( "getLBLength Does not work for MC.");
555 return 0.;
556 } else {
557 uint32_t lumiBlock = eventInfo->lumiBlock();
558 const double lbLength = m_readLumiBlock.getLumiBlockLength(lumiBlock, msg());
559 return lbLength;
560 } // isData
561}
562
563
564
565double EnhancedBiasWeighter::getLBLength(const EventContext& context) const {
566 if (m_isMC) {
567 ATH_MSG_ERROR( "getLBLength Does not work for MC.");
568 return 0.;
569 } else {
570 uint32_t lumiBlock = context.eventID().lumi_block();
571 const double lbLength = m_readLumiBlock.getLumiBlockLength(lumiBlock, msg());
572 return lbLength;
573 } // isData
574}
575
576
578{
579 if (m_isMC) {
580
581 return true;
582
583 } else { //isData
584
585 int32_t ebID = getEventEBID(eventInfo);
586 const auto mapIterator = m_idToUnbiasedMap.find(ebID);
587 if (mapIterator == m_idToUnbiasedMap.end() ) {
588 ATH_MSG_ERROR("Couldn't find isUnbiased information for event with ID " << ebID);
589 return false;
590 }
591 return mapIterator->second;
592
593 } // isData
594}
595
597{
598 if (m_isMC) {
599
600 return true;
601
602 } else { // isData
603
604 uint32_t lumiBlock = eventInfo->lumiBlock();
605
606 const auto mapIterator = m_goodLB.find(lumiBlock);
607 if (mapIterator == m_goodLB.end() ) {
608 ATH_MSG_ERROR( "Couldn't find LB good/bad info for LB: " << lumiBlock );
609 return false;
610 }
611 return static_cast<bool>(mapIterator->second);
612
613 } // isData
614}
615
616bool EnhancedBiasWeighter::isGoodLB(const EventContext& context) const
617{
618 if (m_isMC) {
619
620 return true;
621
622 } else { // isData
623
624 uint32_t lumiBlock = context.eventID().lumi_block();
625
626 const auto mapIterator = m_goodLB.find(lumiBlock);
627 if (mapIterator == m_goodLB.end() ) {
628 ATH_MSG_ERROR( "Couldn't find LB good/bad info for LB: " << lumiBlock );
629 return false;
630 }
631 return static_cast<bool>(mapIterator->second);
632
633 } // isData
634}
635
637 return m_isMC;
638}
639
641 return m_runNumber;
642}
643
645{
646 if (m_isMC) {
647
648 const double mu = std::ceil( eventInfo->actualInteractionsPerCrossing() );
650
651 } else { // isData
652
653 uint32_t lumiBlock = eventInfo->lumiBlock();
654 const auto mapIterator = m_lumiPerLB.find(lumiBlock);
655 if (mapIterator == m_lumiPerLB.end() ) {
656 ATH_MSG_ERROR( "Couldn't find lumi info for LB: " << lumiBlock );
657 return 0.;
658 }
659 return mapIterator->second;
660
661 } // isData
662}
663
664double EnhancedBiasWeighter::getLBLumi(const EventContext& context) const
665{
666 if (m_isMC) {
667
668 ATH_MSG_ERROR( "Cannot use EventContext based getLBLumi with MC. Needs full EventInfo.");
669 return 0.;
670
671 } else { // isData
672
673 uint32_t lumiBlock = context.eventID().lumi_block();
674 const auto mapIterator = m_lumiPerLB.find(lumiBlock);
675 if (mapIterator == m_lumiPerLB.end() ) {
676 ATH_MSG_ERROR( "Couldn't find lumi info for LB: " << lumiBlock );
677 return 0.;
678 }
679 return mapIterator->second;
680
681 } // isData
682}
683
684double EnhancedBiasWeighter::getDeadtime(const int lumiblock) const
685{
686 if (m_isMC) {
687 return 1.;
688 }
689 else if (m_deadtimePerLB.count(lumiblock)) {
690 return m_deadtimePerLB.at(lumiblock);
691 }
692 return m_deadtime;
693}
694
696{
697 return m_pairedBunches;
698}
699
700StatusCode EnhancedBiasWeighter::getDistanceIntoTrain(const xAOD::EventInfo* eventInfo, uint32_t& distance, const EventContext& ctx) const
701{
702 if (!m_useBunchCrossingData) return StatusCode::SUCCESS;
703
705 ATH_CHECK( bunchCrossingTool.isValid() );
706 distance = bunchCrossingTool->distanceFromFront( eventInfo->bcid(), BunchCrossingCondData::BunchDistanceType::BunchCrossings );
707
708 return StatusCode::SUCCESS;
709}
710
712{
713 return m_lumiAverage.mean();
714}
715
717{
718 return m_muAverage.mean();
719}
720
721
722StatusCode EnhancedBiasWeighter::addBranches(const EventContext& ctx) const
723{
724 // Set up the decorator
725 static const SG::Decorator< double > decoratorEBWeight("EnhancedBiasWeight");
726 static const SG::Decorator< double > decoratorEBLivetime("EnhancedBiasLivetime");
727 static const SG::Decorator< double > decoratorLBLumi("LBLumi");
728 static const SG::Decorator< double > decoratorDeadtime("Deadtime");
729 static const SG::Decorator< uint32_t > decoratorBCIDDistanceFromFront("BCIDDistanceFromFront");
730 static const SG::Decorator< char > decoratorUnbiasedFlag("IsUnbiasedEventFlag");
731 static const SG::Decorator< char > decoratorGoodLBFlag("IsGoodLBFlag");
732
733 const xAOD::EventInfo* eventInfo(nullptr);
734 uint32_t distance = 0;
735 ATH_CHECK( evtStore()->retrieve(eventInfo, "EventInfo") ); // FIXME Use Handles
736 ATH_CHECK( getDistanceIntoTrain(eventInfo, distance, ctx) );
737
738 decoratorEBWeight(*eventInfo) = getEBWeight(eventInfo);
739 decoratorEBLivetime(*eventInfo) = getEBLiveTime(eventInfo);
740 decoratorLBLumi(*eventInfo) = getLBLumi(eventInfo);
741 decoratorUnbiasedFlag(*eventInfo) = isUnbiasedEvent(eventInfo);
742 decoratorGoodLBFlag(*eventInfo) = isGoodLB(eventInfo);
743 decoratorDeadtime(*eventInfo) = getDeadtime(eventInfo->lumiBlock());
744 decoratorBCIDDistanceFromFront(*eventInfo) = distance;
745
746 return StatusCode::SUCCESS;
747}
748
749
750std::string EnhancedBiasWeighter::findLocalFile (const std::string& fileName) const {
751
752 if (m_weightsDirectory.empty()) {
753 ATH_MSG_ERROR("Local directory for EB xml not set!");
754 return "";
755 }
756
757 std::string fullName = m_weightsDirectory+ "/" + fileName;
758
759 if (!std::filesystem::exists(fullName)) {
760 ATH_MSG_ERROR("File " << fullName << " not found!");
761 return "";
762 }
763
764 return fullName;
765}
#define endmsg
#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_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
std::string PathResolverFindDataFile(const std::string &logical_file_name)
ServiceHandle< StoreGateSvc > & evtStore()
@ BunchCrossings
Distance in units of 25 nanoseconds.
Gaudi::Property< bool > m_useBunchCrossingData
Gaudi::Property< std::string > m_weightsDirectory
static constexpr uint32_t FULL_RING
Number of bunches in a full ring.
virtual StatusCode getDistanceIntoTrain(const xAOD::EventInfo *eventInfo, uint32_t &distance, const EventContext &ctx) const override
std::vector< int32_t > m_bunches
Number of BCIDs in each bunch group.
ReadLumiBlock m_readLumiBlock
Cache lumi block lengths.
virtual double getEBWeight(const xAOD::EventInfo *eventInfo) const override
StatusCode loadWeights()
Read into memory from XML event weights for this EnhancedBias run.
virtual uint32_t getRunNumber() const override
virtual double getLBLength(const xAOD::EventInfo *eventInfo) const override
virtual uint32_t getPairedBunches() const override
virtual StatusCode initialize() override
Initialize is required by AsgTool base class.
virtual bool isUnbiasedEvent(const xAOD::EventInfo *eventInfo) const override
std::unordered_map< int32_t, uint8_t > m_idToUnbiasedMap
Map a weighting ID to a flag if this weight is from an unbiased (RD) trigger online.
Gaudi::Property< double > m_mcCrossSection
StatusCode trackAverages(const xAOD::EventInfo *eventInfo) const
Internal function to keep track of the mean instantaneous lumi & mean pileup of the EB/MC sample bein...
std::unordered_map< int32_t, double > m_idToWeightMap
Map a weighting ID to a Enhanced Bias event weight.
uint32_t m_pairedBunches
Online number of paired bunches.
EnhancedBiasWeighter(const std::string &name)
Gaudi::Property< double > m_mcKFactor
virtual double getDeadtime(const int lumiblock=-1) const override
Gaudi::Property< uint32_t > m_runNumber
int32_t getEventEBID(const xAOD::EventInfo *eventInfo) const
Gaudi::Property< bool > m_mcIgnoreGeneratorWeights
std::unordered_map< uint32_t, uint8_t > m_goodLB
Like a Good Run List flag for EnhancedBias runs.
StatusCode loadLumi()
Read into memory this EnhancedBias run's XML.
virtual double getBunchCrossingRate() const override
Gaudi::Property< bool > m_isMC
SG::ReadCondHandleKey< BunchCrossingCondData > m_bunchCrossingKey
Tool to get distance into bunch train.
virtual double getEBLiveTime(const xAOD::EventInfo *eventInfo) const override
std::unordered_map< uint64_t, int32_t > m_eventNumberToIdMap
Map event number to a weighting ID.
virtual StatusCode addBranches(const EventContext &ctx) const override
Decorate the AOD with EnhancedBias weighting quantities such that no CVMFS or DB access is required o...
Gaudi::Property< double > m_mcFilterEfficiency
std::unordered_map< uint32_t, double > m_deadtimePerLB
Map of average deadtime per LB.
virtual bool isMC() const override
static constexpr double LHC_FREQUENCY
virtual double getAverageLumi() const override
virtual double getAverageMu() const override
std::string findLocalFile(const std::string &fileName) const
virtual double getLBLumi(const xAOD::EventInfo *eventInfo) const override
Gaudi::Property< bool > m_doMultiSliceDiJet
virtual bool isGoodLB(const xAOD::EventInfo *eventInfo) const override
std::unordered_map< uint32_t, uint32_t > m_eventsPerLB
Map of how many EnhancedBias events were recorded per LB.
double m_deadtime
Online deadtime to correct for in rate prediction.
std::unordered_map< uint32_t, double > m_lumiPerLB
Map of instantaneous luminosity per LB.
Gaudi::Property< bool > m_enforceEBGRL
virtual std::unordered_map< std::string, ChainDetail > parsePrescaleXML(const std::string &prescaleXML) const override
Parse a presscale XML and return a ordered summary of its content To make most use of the XML parsing...
virtual StatusCode finalize() override
Gaudi::Property< bool > m_errorOnMissingEBWeights
Gaudi::Property< double > m_inelasticCrossSection
double m_mcModifiedCrossSection
Product of xsec, filter & kfactor.
Gaudi::Property< double > m_targetLumi
std::mutex m_mutex
Protection for above map.
Helper class to provide type-safe access to aux data.
Definition Decorator.h:59
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
Definition node.h:24
const std::vector< float > & mcEventWeights() const
The weights of all the MC events used in the simulation.
uint32_t lumiBlock() const
The current event's luminosity block number.
uint32_t bcid() const
The bunch crossing ID of the event.
float actualInteractionsPerCrossing() const
Average interactions per crossing for the current BCID - for in-time pile-up.
uint64_t eventNumber() const
The current event's event number.
float mcEventWeight(size_t i=0) const
The weight of one specific MC event used in the simulation.
const int nEvents
int lb
Definition globals.cxx:23
EventInfo_v1 EventInfo
Definition of the latest event info version.
Structure to encompass the data stored in a prescales XML generated by the RuleBook.
MsgStream & msg
Definition testRead.cxx:32