17#include "CoolKernel/IObject.h"
21#include <nlohmann/json.hpp>
28std::vector<float>
tokenize(
const std::string& pattern ) {
30 if (pattern ==
"None") {
34 std::vector< float >
result;
36 const char* cEnd=
c +
pattern.size();
41 float f=std::strtof(c,&end);
81 return StatusCode::SUCCESS;
92 auto lumi = std::make_unique<LuminosityCondData>();
100 EventIDRange range = EventIDRange(EventIDBase(eventinfo->runNumber(),
101 EventIDBase::UNDEFEVT,
102 eventinfo->timeStamp(),
103 eventinfo->timeStampNSOffset(),
104 eventinfo->lumiBlock()),
105 EventIDBase(eventinfo->runNumber(),
106 EventIDBase::UNDEFEVT,
107 eventinfo->timeStamp()+1,
108 eventinfo->timeStampNSOffset(),
109 eventinfo->lumiBlock()+1));
113 const float avgMu = eventinfo->averageInteractionsPerCrossing();
114 std::string sbunches;
117 bool foundInDigitization =
false;
122 if (digitizationFolder.
isValid()) {
124 const auto& attr = (**digitizationFolder)[std::string(
"BeamIntensityPattern")];
125 sbunches = attr.data<std::string>();
126 foundInDigitization =
true;
127 ATH_MSG_DEBUG(
"Read BeamIntensityPattern from Digitization folder");
128 }
catch (
const std::exception& e) {
129 ATH_MSG_DEBUG(
"Could not read from Digitization folder: " << e.what());
135 if (!foundInDigitization) {
138 if (bsMetadata.
isValid() && !bsMetadata->empty()) {
140 const std::vector<std::string>& freeStrings = metadata->getFreeMetaDataStrings();
143 for (
const std::string&
str : freeStrings) {
144 if (
str.starts_with(
"IOVMeta./Digitization/Parameters=")) {
146 size_t eqPos =
str.find(
'=');
147 if (eqPos != std::string::npos && eqPos + 1 <
str.size()) {
148 std::string jsonStr =
str.substr(eqPos + 1);
151 nlohmann::json iovMetadata = nlohmann::json::parse(jsonStr);
155 if (iovMetadata.contains(
"iovs") && iovMetadata[
"iovs"].is_array() && !iovMetadata[
"iovs"].empty()) {
156 const auto& firstIov = iovMetadata[
"iovs"][0];
157 if (firstIov.contains(
"attrs")) {
159 for (
const auto& chanItem : firstIov[
"attrs"].items()) {
160 const auto& chanAttrs = chanItem.value();
161 if (chanAttrs.contains(
"BeamIntensityPattern")) {
162 sbunches = chanAttrs[
"BeamIntensityPattern"].get<std::string>();
163 ATH_MSG_INFO(
"Read BeamIntensityPattern from ByteStream metadata");
167 if (!sbunches.empty())
break;
170 }
catch (
const std::exception& e) {
171 ATH_MSG_WARNING(
"Failed to parse IOV metadata from ByteStream: " << e.what());
178 if (sbunches.empty()) {
179 ATH_MSG_ERROR(
"Could not read BeamIntensityPattern from either Digitization folder or ByteStream metadata");
183 std::vector<float> bunchpattern = tokenize(sbunches);
186 ATH_MSG_ERROR(
"Decoding MC bunch structure failed, improper number of LHC BCIDs");
190 float totintensity = 0.;
191 for (
size_t i = 0; i < bunchpattern.size(); ++i) {
192 totintensity += bunchpattern[i];
196 lumi->setLbAverageInteractionsPerCrossing(avgMu);
197 lumi->setLbAverageLuminosity(totintensity*avgMu*
m_muToLumi);
198 lumi->setLbLuminosityPerBCIDVector(std::move(bunchpattern));
206 unsigned int preferredChannel;
207 unsigned int calibChannel;
208 const coral::Blob* bunchInstLumiBlob =
nullptr;
213 bunchInstLumiBlob) );
225 return StatusCode::SUCCESS;
246 unsigned int& preferredChannel,
247 unsigned int& calibChannel,
248 const coral::Blob*& bunchInstLumiBlob)
const
251 preferredChannel = 0;
253 bunchInstLumiBlob =
nullptr;
256 if (attrList.size() == 0 || attrList[
"Valid"].isNull()) {
258 return StatusCode::SUCCESS;
261 if (
msgLvl (MSG::DEBUG)) {
262 std::ostringstream attrStr1;
263 attrList.toOutputStream( attrStr1 );
269 if (attrList[
"LBAvInstLumi"].isNull() || attrList[
"LBAvEvtsPerBX"].isNull()) {
270 ATH_MSG_ERROR(
" NULL Luminosity information in database " );
271 return StatusCode::FAILURE;
275 uint32_t valid = attrList[
"Valid"].data<cool::UInt32>();
276 lumi.setLbAverageValid (valid);
280 ATH_MSG_INFO(
" Invalid LB Average luminosity ... set lumi to 0" );
282 return StatusCode::SUCCESS;
284 ATH_MSG_DEBUG(
" Invalid LB Average luminosity ... continuing because skipInvalid == FALSE" );
292 bool hasAlgorithmID =
false;
293 for (coral::AttributeList::const_iterator attr = attrList.begin();
294 attr != attrList.end(); ++attr) {
295 if (attr->specification().name() ==
"AlgorithmID") {
296 hasAlgorithmID =
true;
301 if (hasAlgorithmID) {
304 calibChannel = attrList[
"AlgorithmID"].data<cool::UInt32>();
308 preferredChannel = (valid >> 22);
309 calibChannel = preferredChannel;
317 float LBAvInstLumi = attrList[
"LBAvInstLumi"].data<cool::Float>();
318 float LBAvEvtsPerBX = attrList[
"LBAvEvtsPerBX"].data<cool::Float>();
321 if ( std::isnan (LBAvInstLumi) ) {
322 ATH_MSG_WARNING(
" Luminosity is not a number.. " << LBAvInstLumi <<
" ... set it to 0 " );
326 if ( std::isnan (LBAvEvtsPerBX) ) {
327 ATH_MSG_WARNING(
" Luminosity is not a number.. " << LBAvEvtsPerBX <<
" ... set it to 0 " );
331 lumi.setLbAverageLuminosity (LBAvInstLumi);
332 lumi.setLbAverageInteractionsPerCrossing (LBAvEvtsPerBX);
335 int perBcidValid = ((valid&0x3ff)/10) % 10;
337 return StatusCode::SUCCESS;
341 for (coral::AttributeList::const_iterator attr = attrList.begin();
342 attr != attrList.end(); ++attr)
344 if (attr->specification().name() ==
"BunchInstLumi") {
345 if (!attrList[
"BunchInstLumi"].isNull())
346 bunchInstLumiBlob = &attrList[
"BunchInstLumi"].data<coral::Blob>();
351 return StatusCode::SUCCESS;
368 const coral::Blob* bunchInstLumiBlob,
369 unsigned int preferredChannel,
370 unsigned int calibChannel,
374 if (lumi.lbAverageLuminosity() <= 0.) {
376 ATH_MSG_INFO(
"LBAvInstLumi is zero or negative in updatePerBunchLumi():"
377 << lumi.lbAverageLuminosity());
380 return StatusCode::SUCCESS;
390 else if (bunchInstLumiBlob !=
nullptr) {
403 << preferredChannel );
404 return StatusCode::SUCCESS;
419 unsigned int calibChannel,
430 float muToLumi = onlineLumiCalibration->getMuToLumi (calibChannel);
434 ATH_MSG_WARNING(
" Found muToLumi = " << muToLumi <<
" for channel " << calibChannel <<
". Try backup channel..." );
439 lumi.setMuToLumi (muToLumi);
443 int perBcidValid = ((lumi.lbAverageValid()&0x3ff)/10) % 10;
444 if ((lumi.lbAverageValid() & 0x03) || (perBcidValid > 0)) {
448 << lumi.lbAverageValid() <<
"!" );
449 return StatusCode::SUCCESS;
452 << lumi.lbAverageValid()
453 <<
" continuing because skipInvalid == FALSE" );
467 lumi.setMuToLumi (muToLumi);
470 ATH_MSG_DEBUG(
" Found muToLumi = " << muToLumi <<
" for channel "
473 return StatusCode::SUCCESS;
485 unsigned int preferredChannel,
488 ATH_MSG_DEBUG(
"starting updatePerBunchLumiRun2() for alg: " << preferredChannel );
491 if (bunchInstLumiBlob.size() == 0) {
493 return StatusCode::FAILURE;
498 static_cast<const uint8_t*
>(bunchInstLumiBlob.startingAddress());
499 unsigned int bss = ((*pchar) % 100) / 10;
500 unsigned int smod = ((*pchar) % 10);
503 ATH_MSG_DEBUG(
"BunchInstLumi blob found with storage mode " << smod
504 <<
" and byte storage size " << bss );
507 if (bss != 4 || smod != 1) {
508 ATH_MSG_ERROR(
"BunchInstLumi blob found with storage mode " << smod <<
" and byte storage size " << bss <<
" - Unknown!");
509 return StatusCode::FAILURE;
513 unsigned int bloblength = bss * nbcids + 1;
515 if (
static_cast<cool::UInt32
>(bunchInstLumiBlob.size()) != bloblength) {
517 << bunchInstLumiBlob.size() <<
"in storage mode" << smod
518 <<
", expecting " << bloblength <<
"!" );
519 return StatusCode::FAILURE;
526 std::vector<float> instLumi (nbcids);
527 for (
unsigned int i=0; i<nbcids; i++) {
532 if (
msgLvl (MSG::DEBUG)) {
533 for (
unsigned int i=0; i<nbcids; i++) {
538 lumi.setLbLuminosityPerBCIDVector (std::move (instLumi));
540 return StatusCode::SUCCESS;
552 unsigned int preferredChannel,
556 ATH_MSG_DEBUG(
"starting updatePerBunchLumiRun1() for alg: " << preferredChannel );
558 if (preferredChannel == 0) {
559 return StatusCode::SUCCESS;
564 ATH_MSG_DEBUG(
"OnlineLumiCalibrationInputKey.empty() is TRUE, skipping..." );
565 return StatusCode::SUCCESS;
568 ATH_MSG_DEBUG(
"BunchLumisInputKey.empty() is TRUE, skipping..." );
569 return StatusCode::SUCCESS;
572 ATH_MSG_DEBUG(
"BunchGroupTool.empty() is TRUE, skipping..." );
573 return StatusCode::SUCCESS;
576 ATH_MSG_DEBUG(
"FillParamsInputKey.empty() is TRUE, skipping..." );
577 return StatusCode::SUCCESS;
590 const std::vector<unsigned int>& luminousBunches = fillParams->luminousBunches();
591 ATH_MSG_DEBUG(
"N LuminousBunches:" << luminousBunches.size() );
594 const std::vector<float>& rawLumiVec = bunchLumis->rawLuminosity(preferredChannel);
595 if (rawLumiVec.empty()) {
597 return StatusCode::SUCCESS;
610 float muToLumi = onlineLumiCalibration->getMuToLumi (preferredChannel);
611 if (muToLumi <= 0.) {
612 ATH_MSG_ERROR(
" dont have calibration information for preferred channel "
613 << preferredChannel <<
"!" );
614 return StatusCode::FAILURE;
616 lumi.setMuToLumi (muToLumi);
619 for (
unsigned int bcid : luminousBunches) {
621 if (rawLumiVec.at(bcid) <= 0.) {
623 << rawLumiVec.at(bcid) <<
" -> skipping" );
628 if (!onlineLumiCalibration->calibrateLumi(preferredChannel,
632 ATH_MSG_DEBUG(
"Calibrate BCID " << bcid <<
" with raw " << rawLumiVec[bcid] <<
" -> calibration failed!" );
633 ATH_MSG_WARNING(
"Per-BCID calibration failed for bcid " << bcid <<
" with raw lumi = " << rawLumiVec[bcid] );
637 lumiSum += calLumiVec[bcid];
639 ATH_MSG_DEBUG(
"Calibrate BCID " << bcid <<
" with raw " << rawLumiVec[bcid] <<
" -> " << calLumiVec[bcid] );
643 float offlineOnlineRatio = 1.;
644 if (lumiSum > 0.) offlineOnlineRatio = lumi.lbAverageLuminosity() / lumiSum;
646 ATH_MSG_DEBUG(
" Offline/Online scale factor: " << lumi.lbAverageLuminosity()
647 <<
" / " << lumiSum <<
" = " << offlineOnlineRatio );
650 for (
unsigned int bcid : bunchGroup->bunchGroup (1)) {
652 if (calLumiVec[bcid] > 0.)
continue;
653 if (rawLumiVec[bcid] <= 0.)
continue;
656 if (!onlineLumiCalibration->calibrateLumi(preferredChannel,
662 <<
" with raw lumi = " << rawLumiVec[bcid] );
668 for (
float& bclumi : calLumiVec) {
669 bclumi *= offlineOnlineRatio;
672 lumi.setLbLuminosityPerBCIDVector (std::move (calLumiVec));
674 return StatusCode::SUCCESS;
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
This file defines the class for a collection of AttributeLists where each one is associated with a ch...
Conditions algorithm for luminosity data.
Handle class for reading from StoreGate.
bool msgLvl(const MSG::Level lvl) const
This class is a collection of AttributeLists where each one is associated with a channel number.
const AttributeList & attributeList(ChanNum chanNum) const
attribute list for a given channel number
static EventIDRange infiniteRunLB()
Produces an EventIDRange that is infinite in RunLumi and invalid in Time.
StatusCode updatePerBunchLumi(const EventContext &ctx, const coral::Blob *bunchInstLumiBlob, unsigned int preferredChannel, unsigned int calibChannel, SG::WriteCondHandle< LuminosityCondData > &wHdl, LuminosityCondData &lumi) const
Fill in per-bunch luminosity data.
Gaudi::Property< float > m_muToLumi
SG::WriteCondHandleKey< LuminosityCondData > m_luminosityOutputKey
Output conditions object.
SG::ReadCondHandleKey< BunchGroupCondData > m_bunchGroupInputKey
SG::ReadCondHandleKey< OnlineLumiCalibrationCondData > m_onlineLumiCalibrationInputKey
StatusCode updatePerBunchLumiRun1(const EventContext &ctx, unsigned int preferredChannel, SG::WriteCondHandle< LuminosityCondData > &wHdl, LuminosityCondData &lumi) const
Fill in per-bunch luminosity data, run 1.
Gaudi::Property< bool > m_isMC
virtual StatusCode execute(const EventContext &ctx) const override
Algorithm execute method.
SG::ReadDecorHandleKey< xAOD::EventInfo > m_averageMuKey
SG::ReadCondHandleKey< FillParamsCondData > m_fillParamsInputKey
StatusCode updateMuToLumi(const EventContext &ctx, unsigned int calibChannel, SG::WriteCondHandle< LuminosityCondData > &wHdl, LuminosityCondData &lumi, bool &isValid) const
Fill in mu-to-lumi calibration.
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
Gaudi::Property< unsigned long > m_lumiChannel
SG::ReadDecorHandleKey< xAOD::EventInfo > m_actualMuKey
Gaudi::Property< bool > m_skipInvalid
SG::ReadHandleKey< ByteStreamMetadataContainer > m_byteStreamMetadataKey
SG::ReadCondHandleKey< AthenaAttributeList > m_mcDigitizationInputKey
Gaudi::Property< bool > m_expectInvalid
SG::ReadCondHandleKey< BunchLumisCondData > m_bunchLumisInputKey
virtual StatusCode initialize() override
Gaudi initialize method.
StatusCode updateAvgLumi(const CondAttrListCollection &lumiData, LuminosityCondData &lumi, unsigned int &preferredChannel, unsigned int &calibChannel, const coral::Blob *&bunchInstLumiBlob) const
Unpack luminosity data from the attribute list.
StatusCode updatePerBunchLumiRun2(const coral::Blob &bunchInstLumiBlob, unsigned int preferredChannel, LuminosityCondData &lumi) const
Fill in per-bunch luminosity data, run 2 and later.
SG::ReadCondHandleKey< CondAttrListCollection > m_luminosityFolderInputKey
Gaudi::Property< unsigned long > m_calibBackupChannel
static constexpr unsigned int TOTAL_LHC_BCIDS
virtual bool isValid() override final
Can the handle be successfully dereferenced?
void addDependency(const EventIDRange &range)
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED
Read little-endian values through possibly unaligned pointers.
std::vector< std::string > tokenize(const std::string &the_str, std::string_view delimiters)
Splits the string into smaller substrings.
float get_unaligned_float(const uint8_t *ATH_RESTRICT &p)
Read a little-endian float value from a possibly unaligned pointer.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.