10#include "TXMLEngine.h"
11#include "TObjString.h"
12#include "TDOMParser.h"
14#include "TXMLDocument.h"
22 T stringToNum(
const std::string& i) {
24 std::istringstream( i ) >> ret;
44 ATH_MSG_FATAL(
"For MC rates, a cross section and filter efficiency must be supplied.");
45 return StatusCode::FAILURE;
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;
59 ATH_MSG_INFO (
"calculateWeightingData is TRUE. This job will read in EnhancedBias weighting data from CVMFS and COOL.");
66 return StatusCode::SUCCESS;
72 return StatusCode::SUCCESS;
78 std::stringstream fileName;
80 fileName <<
"EnhancedBiasWeights_" << runNumber <<
".xml";
85 if (weightingFile.empty()) {
90 std::unique_ptr<TXMLEngine> xml(
new TXMLEngine() );
91 XMLDocPointer_t xmlDoc = xml->ParseFile( weightingFile.c_str() );
93 if (xmlDoc ==
nullptr) {
94 ATH_MSG_WARNING (
"Could not parse " << fileName.str() <<
", cannot perform enhanced bias weighting.");
95 return StatusCode::FAILURE;
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;
104 const XMLNodePointer_t weightsNode = xml->GetChild( mainNode );
105 const XMLNodePointer_t eventsNode = xml->GetNext( weightsNode );
107 XMLNodePointer_t weightNode = xml->GetChild( weightsNode );
108 XMLNodePointer_t eventNode = xml->GetChild( eventsNode );
110 while ( weightNode != 0 ) {
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;
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"));
126 weightNode = xml->GetNext(weightNode);
129 while ( eventNode != 0 ) {
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;
134 const uint64_t eventNumber = std::strtoll(xml->GetAttr(eventNode,
"n"),
nullptr, 10);
135 const int32_t eventWeightID = std::stoi(xml->GetAttr(eventNode,
"w") );
139 eventNode = xml->GetNext(eventNode);
143 return StatusCode::SUCCESS;
151 ATH_MSG_FATAL(
"Unable to load this runs luminosity values from COOL.");
152 return StatusCode::FAILURE;
157 std::stringstream fileName;
158 fileName <<
"enhanced_bias_run_" << runNumber <<
".xml";
162 if (runFile.empty()) {
167 std::unique_ptr<TXMLEngine> xml(
new TXMLEngine());
168 const XMLDocPointer_t xmlDoc = xml->ParseFile( runFile.c_str() );
170 if (xmlDoc ==
nullptr) {
171 ATH_MSG_FATAL (
"Could not parse " << fileName.str() <<
", cannot perform enhanced bias weighting.");
172 return StatusCode::FAILURE;
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;
180 XMLNodePointer_t listNode = xml->GetChild( mainNode );
182 while ( listNode != 0 ) {
183 const std::string listName = xml->GetNodeName(listNode);
185 if (listName ==
"lb_list") {
187 XMLNodePointer_t
node = xml->GetChild( listNode );
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;
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") :
"";
202 if (xml->HasAttr(
node,
"deadtime")) {
210 }
else if (listName ==
"lumivalues") {
212 XMLNodePointer_t
node = xml->GetChild( listNode );
214 if ( xml->GetNodeName(
node) == std::string(
"deadtime") ) {
220 }
else if (listName ==
"bunchgroups") {
222 XMLNodePointer_t
node = xml->GetChild( listNode );
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")) {
232 }
else if (listName ==
"filters") {
234 ATH_MSG_DEBUG(
"Found filters section of enhanced bias XML. Unused by this application.");
238 ATH_MSG_INFO(
"Encountered unknown element in enhanced bias XML: " << listName <<
" ignoring it.");
242 listNode = xml->GetNext(listNode);
246 return StatusCode::SUCCESS;
250 std::unordered_map<std::string, ChainDetail>
result;
253 if (xmlFile.empty()) {
254 ATH_MSG_ERROR (
"Could not retrieve " << prescaleXML <<
", place it somewhere PathResolver can find it (such as the current directory).");
258 std::unique_ptr<TXMLEngine> xml(
new TXMLEngine());
259 const XMLDocPointer_t xmlDoc = xml->ParseFile( xmlFile.c_str() );
261 if (xmlDoc ==
nullptr) {
262 ATH_MSG_WARNING (
"Could not parse " << prescaleXML <<
", please check that it is valid XML.");
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));
272 XMLNodePointer_t listNode = xml->GetChild( mainNode );
275 while ( listNode !=
nullptr) {
276 const std::string listName = xml->GetNodeName(listNode);
281 if (listName !=
"level") {
282 listNode = xml->GetNext(listNode);
286 XMLNodePointer_t sigNode = xml->GetChild( listNode );
287 while( sigNode !=
nullptr) {
288 if (xml->GetNodeName(sigNode) != std::string(
"signature")) {
289 sigNode = xml->GetNext(sigNode);
293 XMLNodePointer_t sigDetailsNode = xml->GetChild( sigNode );
294 std::string chainName;
295 while( sigDetailsNode !=
nullptr) {
297 if (xml->GetNodeContent(sigDetailsNode) ==
nullptr) {
298 sigDetailsNode = xml->GetNext(sigDetailsNode);
302 const std::string
detail = xml->GetNodeName(sigDetailsNode);
303 if (
detail ==
"sig_name") {
304 chainName = xml->GetNodeContent(sigDetailsNode);
306 }
else if (
detail ==
"sig_counter") {
307 result[chainName].m_counter = std::stoi( xml->GetNodeContent(sigDetailsNode) );
308 }
else if (
detail ==
"prescale" ||
detail ==
"chain_prescale") {
309 result[chainName].m_prescale = std::stod( xml->GetNodeContent(sigDetailsNode) );
310 }
else if (
detail ==
"lower_chain_name") {
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);
340 ATH_MSG_DEBUG(
"Input prescales XML contains additional data which cannot be parsed at present:" <<
detail);
343 sigDetailsNode = xml->GetNext(sigDetailsNode);
345 sigNode = xml->GetNext(sigNode);
347 listNode = xml->GetNext(listNode);
355 const uint64_t eventNumber = eventInfo->
eventNumber();
359 return mapIterator->second;
362 const int32_t eventNumber32 =
static_cast<int32_t
>(eventNumber);
365 return mapIterator32->second;
367 ATH_MSG_ERROR(
"Couldn't find enhanced bias info for event " << eventNumber);
374 const uint64_t eventNumber = context.eventID().event_number();
378 return mapIterator->second;
381 const int32_t eventNumber32 =
static_cast<int32_t
>(eventNumber);
384 return mapIterator32->second;
386 ATH_MSG_ERROR(
"Couldn't find enhanced bias info for event " << eventNumber);
419 ATH_MSG_ERROR(
"Couldn't find enhanced bias weight for event with ID " << ebID);
422 return mapIterator->second;
439 ATH_MSG_ERROR(
"Cannot use EventContext based getEBWeight with MC. Needs full EventInfo.");
447 ATH_MSG_ERROR(
"Couldn't find enhanced bias weight for event with ID " << ebID);
450 return mapIterator->second;
459 return StatusCode::SUCCESS;
467 return StatusCode::SUCCESS;
483 ATH_MSG_DEBUG(
"MC livetime debug: probOfProcess:" << probOfProcess <<
" probOfBunchCrossing:" << probOfBunchCrossing <<
" bunchCrossingRate:" << bunchCrossingRate <<
" time:" << (1. / (probOfBunchCrossing * bunchCrossingRate)));
484 return 1. / (probOfBunchCrossing * bunchCrossingRate);
488 uint32_t lumiBlock = eventInfo->
lumiBlock();
489 std::lock_guard<std::mutex> scopeLock(
m_mutex);
492 const auto inCacheIterator = m_eventLivetime.find( lumiBlock );
493 if (inCacheIterator != m_eventLivetime.end())
return inCacheIterator->second;
499 ATH_MSG_ERROR(
"Couldn't find LB info for LB: " << lumiBlock );
503 const int32_t eventsInThisLB = mapIterator->second;
506 double eventLivetime = 0;
507 if (eventsInThisLB > 0 && std::fabs(lbLength) > 1e-10) eventLivetime = (1. /
static_cast<double>(eventsInThisLB)) * lbLength;
509 m_eventLivetime[lumiBlock] = eventLivetime;
510 return eventLivetime;
519 ATH_MSG_ERROR(
"Cannot use EventContext based getEBLiveTime with MC. Needs full EventInfo.");
524 uint32_t lumiBlock = context.eventID().lumi_block();
525 std::lock_guard<std::mutex> scopeLock(
m_mutex);
528 const auto inCacheIterator = m_eventLivetime.find( lumiBlock );
529 if (inCacheIterator != m_eventLivetime.end())
return inCacheIterator->second;
535 ATH_MSG_ERROR(
"Couldn't find LB info for LB: " << lumiBlock );
539 const int32_t eventsInThisLB = mapIterator->second;
542 double eventLivetime = 0;
543 if (eventsInThisLB > 0 && std::fabs(lbLength) > 1e-10) eventLivetime = (1. /
static_cast<double>(eventsInThisLB)) * lbLength;
545 m_eventLivetime[lumiBlock] = eventLivetime;
546 return eventLivetime;
557 uint32_t lumiBlock = eventInfo->
lumiBlock();
570 uint32_t lumiBlock = context.eventID().lumi_block();
588 ATH_MSG_ERROR(
"Couldn't find isUnbiased information for event with ID " << ebID);
591 return mapIterator->second;
604 uint32_t lumiBlock = eventInfo->
lumiBlock();
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 );
611 return static_cast<bool>(mapIterator->second);
624 uint32_t lumiBlock = context.eventID().lumi_block();
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 );
631 return static_cast<bool>(mapIterator->second);
653 uint32_t lumiBlock = eventInfo->
lumiBlock();
654 const auto mapIterator =
m_lumiPerLB.find(lumiBlock);
656 ATH_MSG_ERROR(
"Couldn't find lumi info for LB: " << lumiBlock );
659 return mapIterator->second;
668 ATH_MSG_ERROR(
"Cannot use EventContext based getLBLumi with MC. Needs full EventInfo.");
673 uint32_t lumiBlock = context.eventID().lumi_block();
674 const auto mapIterator =
m_lumiPerLB.find(lumiBlock);
676 ATH_MSG_ERROR(
"Couldn't find lumi info for LB: " << lumiBlock );
679 return mapIterator->second;
708 return StatusCode::SUCCESS;
713 return m_lumiAverage.mean();
718 return m_muAverage.mean();
734 uint32_t distance = 0;
738 decoratorEBWeight(*eventInfo) =
getEBWeight(eventInfo);
740 decoratorLBLumi(*eventInfo) =
getLBLumi(eventInfo);
742 decoratorGoodLBFlag(*eventInfo) =
isGoodLB(eventInfo);
744 decoratorBCIDDistanceFromFront(*eventInfo) = distance;
746 return StatusCode::SUCCESS;
759 if (!std::filesystem::exists(fullName)) {
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(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.
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.
EventInfo_v1 EventInfo
Definition of the latest event info version.
Structure to encompass the data stored in a prescales XML generated by the RuleBook.