ATLAS Offline Software
L1TriggerByteStreamDecoderAlg.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 #include "eformat/DetectorMask.h"
7 #include "eformat/SourceIdentifier.h"
8 #include "eformat/Problem.h"
9 #include <algorithm>
10 #include <charconv>
11 
12 namespace {
13  std::string u32toHexString(uint32_t num) {
14  std::string hexRobId("0x ");
15  std::to_chars(hexRobId.data()+2, hexRobId.data()+hexRobId.size(), num, 16);
16  hexRobId.resize(std::min(10ul,hexRobId.find(' ')));
17  return hexRobId;
18  }
20  struct FractionPerLBNMonitor {
21  FractionPerLBNMonitor(std::string&& name, EventIDBase::number_type lbn, float denom, const ToolHandle<GenericMonitoringTool>& monTool)
22  : errorFraction(Monitored::Scalar<float>{std::move(name), 0}),
23  errorFractionLBN(Monitored::Scalar<EventIDBase::number_type>{"LumiBlock", lbn}),
25  tool(monTool) {}
26  ~FractionPerLBNMonitor() {
27  if (denominator==0) {
28  errorFraction = 0;
29  } else {
30  errorFraction /= denominator;
31  }
32  Monitored::Group{tool, errorFraction, errorFractionLBN};
33  }
34  void operator++() {++errorFraction;}
35  Monitored::Scalar<float> errorFraction;
37  float denominator{1};
38  const ToolHandle<GenericMonitoringTool>& tool;
39  };
41  void printRobProblems(std::ostream& s, const IROBDataProviderSvc::ROBF* rob) {
42  std::vector<eformat::FragmentProblem> problems;
43  rob->problems(problems);
44  s << problems.size() << " problems: [";
45  bool firstProblem{true};
46  for (eformat::FragmentProblem problem : problems) {
47  if (firstProblem) {firstProblem=false;}
48  else {s << ", ";}
49  s << eformat::helper::FragmentProblemDictionary.string(problem);
50  }
51  s << "]";
52  }
53  std::string robIdsToString(const std::vector<uint32_t>& robIds) {
54  std::ostringstream ss;
55  bool first{true};
56  ss << "[";
57  for (const uint32_t robId : robIds) {
58  if (first) {first=false;}
59  else {ss << ", ";}
60  ss << "0x" << std::hex << robId << std::dec;
61  }
62  ss << "]";
63  return ss.str();
64  }
65 }
66 
67 // =============================================================================
68 // Standard constructor
69 // =============================================================================
71 : AthReentrantAlgorithm(name, svcLoc) {}
72 
73 // =============================================================================
74 // Implementation of AthReentrantAlgorithm::initialize
75 // =============================================================================
77  ATH_MSG_DEBUG("Initialising " << name());
78  ATH_CHECK(m_decoderTools.retrieve());
79  ATH_CHECK(m_robDataProviderSvc.retrieve());
80  if (!m_monTool.empty()) ATH_CHECK(m_monTool.retrieve());
82 
84 
85  // Build a list of unique ROB IDs to request in each event
86  for (const auto& decoderTool : m_decoderTools) {
87  const std::vector<uint32_t>& ids = decoderTool->robIds();
88  m_robIds.insert(m_robIds.end(), ids.begin(), ids.end());
89  }
90  std::sort(m_robIds.begin(),m_robIds.end());
91  m_robIds.erase(std::unique(m_robIds.begin(),m_robIds.end()), m_robIds.end());
92  ATH_MSG_INFO("Will request " << m_robIds.size() << " ROBs per event: " << robIdsToString(m_robIds));
93 
94  // Parse properties
95  m_maybeMissingRobs.insert(m_maybeMissingRobsProp.value().begin(), m_maybeMissingRobsProp.value().end());
96 
97  auto setRobCheckBehaviour = [this](const Gaudi::Property<std::string>& prop, ROBCheckBehaviour& out) -> StatusCode {
98  if (prop.value() == "None") {out=ROBCheckBehaviour::None;}
99  else if (prop.value() == "Warning") {out=ROBCheckBehaviour::Warning;}
100  else if (prop.value() == "Error") {out=ROBCheckBehaviour::Error;}
101  else if (prop.value() == "Fatal") {out=ROBCheckBehaviour::Fatal;}
102  else {
103  ATH_MSG_ERROR(prop.name() << " is set to \"" << prop.value()
104  << "\" but needs to be one of [\"None\", \"Warning\", \"Error\", \"Fatal\"]");
105  return StatusCode::FAILURE;
106  }
107  return StatusCode::SUCCESS;
108  };
109 
110  ATH_CHECK(setRobCheckBehaviour(m_robStatusCheckLevel,m_robStatusCheck));
111  ATH_CHECK(setRobCheckBehaviour(m_robFormatCheckLevel,m_robFormatCheck));
112 
113  return StatusCode::SUCCESS;
114 }
115 
116 // =============================================================================
117 // Implementation of AthReentrantAlgorithm::start
118 // =============================================================================
120  // Skip detector mask checks if ByteStreamMetaData not available
121  if (m_bsMetaDataContRHKey.key().empty()) {
122  return StatusCode::SUCCESS;
123  }
124 
125  // Get the detector mask
127  ATH_CHECK(bsmdc.isValid());
128  ATH_CHECK(!bsmdc->empty());
129  const ByteStreamMetadata* metadata = bsmdc->front();
130  const eformat::helper::DetectorMask detectorMask{metadata->getDetectorMask(), metadata->getDetectorMask2()};
131 
132  // Check if the requested ROBs should be expected to be present or may be missing
133  for (const uint32_t robId : m_robIds) {
134  const eformat::helper::SourceIdentifier sid{robId};
135  if (!detectorMask.is_set(sid.subdetector_id())) {
136  if (m_maybeMissingRobs.insert(robId).second) {
137  ATH_MSG_WARNING("ROB ID 0x" << MSG::hex << robId << MSG::dec << " was requested for decoding, "
138  << "but the SubDetector " << sid.human_detector() << " is disabled in "
139  << "the detector mask. Will not require this ROB ID to be present in every event.");
140  }
141  }
142  }
143 
144  return StatusCode::SUCCESS;
145 }
146 
147 // =============================================================================
148 // Implementation of AthReentrantAlgorithm::finalize
149 // =============================================================================
151  ATH_MSG_DEBUG("Finalising " << name());
152  ATH_CHECK(m_robDataProviderSvc.release());
153  ATH_CHECK(m_decoderTools.release());
154  return StatusCode::SUCCESS;
155 }
156 
157 // =============================================================================
158 // Implementation of AthReentrantAlgorithm::execute
159 // =============================================================================
160 StatusCode L1TriggerByteStreamDecoderAlg::execute(const EventContext& eventContext) const {
161  ATH_MSG_DEBUG("Executing " << name());
162  auto monTimeExec = Monitored::Timer<std::chrono::duration<float, std::milli>>("TIME_execute");
163 
164  // Retrieve the BS data for all tools in one request to parallelise DCM->ROS network requests
166  m_robDataProviderSvc->getROBData(eventContext, m_robIds, vrobf, name());
167 
168  // Filter ROB list for each tool and call the conversion
169  for (const auto& decoderTool : m_decoderTools) {
170  std::string toolName{decoderTool->name().substr(decoderTool->name().rfind('.')+1)};
171  auto monTimePrep = Monitored::Timer<std::chrono::duration<float, std::milli>>("TIME_prepareROBs_"+toolName);
172  IROBDataProviderSvc::VROBFRAG vrobfForTool;
173  ATH_CHECK(filterRobs(vrobf, vrobfForTool, decoderTool->robIds(), toolName, eventContext));
174  ATH_CHECK(checkRobs(vrobfForTool, toolName, eventContext));
175  monTimePrep.stop();
176  auto monTimeConv = Monitored::Timer<std::chrono::duration<float, std::milli>>("TIME_convert_"+toolName);
177  try {
178  ATH_CHECK(decoderTool->convertFromBS(vrobfForTool, eventContext));
179  } catch (const std::exception& ex) {
180  ATH_MSG_ERROR("Exception in " << toolName << "::convertFromBS: " << ex.what());
181  return StatusCode::FAILURE;
182  }
183  // Note: time histograms not filled if any ATH_CHECK above fails
184  Monitored::Group(m_monTool, monTimePrep, monTimeConv);
185  }
186 
187  Monitored::Group(m_monTool, monTimeExec);
188  return StatusCode::SUCCESS;
189 }
190 
191 // =============================================================================
194  const std::vector<uint32_t>& ids,
195  std::string_view toolName,
196  const EventContext& eventContext) const {
197  std::copy_if(in.cbegin(), in.cend(), std::back_inserter(out),
198  [&ids](const IROBDataProviderSvc::ROBF* rob){
199  return (std::find(ids.cbegin(),ids.cend(),rob->source_id()) != ids.cend());
200  });
201 
202  std::string missingFractionName{"MissingROBFraction_"};
203  missingFractionName.append(toolName);
204  FractionPerLBNMonitor monMissingFraction{std::move(missingFractionName), eventContext.eventID().lumi_block(), static_cast<float>(ids.size()), m_monTool};
205 
206  // Check if all ROBs were found and report errors if not
207  if (ids.size() != out.size()) {
208  bool fail{false};
209  for (const uint32_t id : ids) {
210  auto eqRobId = [&id](const IROBDataProviderSvc::ROBF* rob){return (rob->source_id() == id);};
211  if (std::find_if(out.cbegin(),out.cend(),eqRobId) == out.cend()) {
212  ++monMissingFraction;
213  std::string hexRobId = u32toHexString(id);
214  if (std::find(m_maybeMissingRobs.cbegin(),m_maybeMissingRobs.cend(),id) != m_maybeMissingRobs.cend()) {
215  ATH_MSG_DEBUG("Missing ROBFragment with ID " << hexRobId << " ("
216  << eformat::helper::SourceIdentifier(id).human() << ") requested by " << toolName
217  << " but it is allowed to be missing due to the detector mask or the "
218  << m_maybeMissingRobsProp.name() << " property");
219  Monitored::Scalar<std::string> monMissing{"MissingROBAllowed", hexRobId};
220  Monitored::Group{m_monTool, monMissing};
221  } else {
222  ATH_MSG_ERROR("Missing ROBFragment with ID " << hexRobId << " ("
223  << eformat::helper::SourceIdentifier(id).human() << ") requested by " << toolName);
224  fail = true;
225  Monitored::Scalar<std::string> monMissing{"MissingROB", hexRobId};
226  Monitored::Group{m_monTool, monMissing};
227  }
228  }
229  }
230  if (fail) {
231  return StatusCode::FAILURE;
232  }
233  }
234  ATH_MSG_DEBUG("Found " << out.size() << " out of " << ids.size() << " ROBFragments requested by " << toolName);
235  return StatusCode::SUCCESS;
236 }
237 
238 // =============================================================================
240  std::string_view toolName,
241  const EventContext& eventContext) const {
242  StatusCode sc{StatusCode::SUCCESS};
244  return sc;
245  }
246  std::string corruptedFractionName{"CorruptedROBFraction_"};
247  std::string errorFractionName{"ErroneousROBFraction_"};
248  corruptedFractionName.append(toolName);
249  errorFractionName.append(toolName);
250  FractionPerLBNMonitor monCorruptedFraction{std::move(corruptedFractionName), eventContext.eventID().lumi_block(), static_cast<float>(robs.size()), m_monTool};
251  FractionPerLBNMonitor monErrorFraction{std::move(errorFractionName), eventContext.eventID().lumi_block(), static_cast<float>(robs.size()), m_monTool};
252  auto printCheckMsg = [this](std::ostringstream& ss, ROBCheckBehaviour checkBehaviour, bool maybeMissing, StatusCode& sc) {
253  if (maybeMissing) {
254  ss << " but it is allowed due to the detector mask or the " << m_maybeMissingRobsProp.name() << " property";
255  ATH_MSG_DEBUG(ss.str());
256  }
257  else if (checkBehaviour==ROBCheckBehaviour::Warning) {ATH_MSG_WARNING(ss.str());}
258  else if (checkBehaviour==ROBCheckBehaviour::Error) {ATH_MSG_ERROR(ss.str());}
259  else if (checkBehaviour==ROBCheckBehaviour::Fatal) {
260  ATH_MSG_ERROR(ss.str());
261  sc = StatusCode::FAILURE;
262  }
263  };
264 
265  for (const IROBDataProviderSvc::ROBF* rob : robs) {
266  // Format check
267  if (m_robFormatCheck!=ROBCheckBehaviour::None && !rob->check_noex()) {
268  ++monCorruptedFraction;
269  const uint32_t id{rob->rob_source_id()}; // there's a small chance ID is also corrupted, but usually corruption affects latter words
270  std::string hexRobId = u32toHexString(id);
271  const bool maybeMissing{std::find(m_maybeMissingRobs.cbegin(),m_maybeMissingRobs.cend(),id) != m_maybeMissingRobs.cend()};
272 
273  Monitored::Scalar<std::string> monCorrupted{(maybeMissing ? "CorruptedROBAllowed" : "CorruptedROB"), hexRobId};
274  Monitored::Group{m_monTool, monCorrupted};
275 
276  std::ostringstream ss;
277  ss << "ROBFragment with ID " << hexRobId << " (" << eformat::helper::SourceIdentifier(id).human()
278  << ") requested by " << toolName << " has corrupted data with ";
279  printRobProblems(ss, rob);
280  printCheckMsg(ss, m_robFormatCheck, maybeMissing, sc);
281  }
282  // Status check
283  if (m_robStatusCheck!=ROBCheckBehaviour::None && rob->nstatus()>0 && rob->status()[0]!=0) {
284  ++monErrorFraction;
285  const uint32_t id{rob->rob_source_id()};
286  std::string hexRobId = u32toHexString(id);
287  const bool maybeMissing{std::find(m_maybeMissingRobs.cbegin(),m_maybeMissingRobs.cend(),id) != m_maybeMissingRobs.cend()};
288 
289  Monitored::Scalar<std::string> monErroneous{(maybeMissing ? "ErroneousROBAllowed" : "ErroneousROB"), hexRobId};
290  Monitored::Group{m_monTool, monErroneous};
291 
292  std::ostringstream ss;
293  ss << "ROBFragment with ID " << hexRobId << " (" << eformat::helper::SourceIdentifier(id).human()
294  << ") requested by " << toolName << " has non-zero status 0x" << std::hex << rob->status()[0] << std::dec;
295  printCheckMsg(ss, m_robStatusCheck, maybeMissing, sc);
296  }
297  }
298  return sc;
299 }
TrigDefs::Group
Group
Properties of a chain group.
Definition: GroupProperties.h:13
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
L1TriggerByteStreamDecoderAlg::L1TriggerByteStreamDecoderAlg
L1TriggerByteStreamDecoderAlg(const std::string &name, ISvcLocator *svcLoc)
Standard constructor.
Definition: L1TriggerByteStreamDecoderAlg.cxx:70
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
L1TriggerByteStreamDecoderAlg::execute
virtual StatusCode execute(const EventContext &eventContext) const override
Definition: L1TriggerByteStreamDecoderAlg.cxx:160
L1TriggerByteStreamDecoderAlg.h
L1TriggerByteStreamDecoderAlg::ROBCheckBehaviour::Warning
@ Warning
AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::renounce
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce(T &h)
Definition: AthCommonDataStore.h:380
L1TriggerByteStreamDecoderAlg::m_robStatusCheck
ROBCheckBehaviour m_robStatusCheck
Definition: L1TriggerByteStreamDecoderAlg.h:96
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
Monitored::Group
Group of local monitoring quantities and retain correlation when filling histograms
Definition: MonitoredGroup.h:54
AtlasMcWeight::number_type
unsigned int number_type
Definition: AtlasMcWeight.h:20
ByteStreamMetadata
This class is the StoreGate data object for bytestream metadata.
Definition: ByteStreamMetadata.h:25
L1TriggerByteStreamDecoderAlg::ROBCheckBehaviour::Error
@ Error
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
L1TriggerByteStreamDecoderAlg::m_bsMetaDataContRHKey
SG::ReadHandleKey< ByteStreamMetadataContainer > m_bsMetaDataContRHKey
StoreGate key for the ByteStreamMetadata container to retrieve detector mask.
Definition: L1TriggerByteStreamDecoderAlg.h:45
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
python.checkMetadata.metadata
metadata
Definition: checkMetadata.py:175
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:270
L1TriggerByteStreamDecoderAlg::m_monTool
ToolHandle< GenericMonitoringTool > m_monTool
Monitoring tool to create online histograms.
Definition: L1TriggerByteStreamDecoderAlg.h:40
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
L1TriggerByteStreamDecoderAlg::m_decoderTools
ToolHandleArray< IL1TriggerByteStreamTool > m_decoderTools
Tool performing the decoding work.
Definition: L1TriggerByteStreamDecoderAlg.h:34
L1TriggerByteStreamDecoderAlg::m_robStatusCheckLevel
Gaudi::Property< std::string > m_robStatusCheckLevel
Set behaviour for non-zero ROB status words.
Definition: L1TriggerByteStreamDecoderAlg.h:57
eformat::ROBFragment
Definition: L1CaloBsDecoderUtil.h:12
Monitored
Generic monitoring tool for athena components.
Definition: GenericMonitoringTool.h:30
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
python.HLT.CommonSequences.EventBuildingSequences.robs
robs
Definition: EventBuildingSequences.py:400
calibdata.exception
exception
Definition: calibdata.py:496
L1TriggerByteStreamDecoderAlg::initialize
virtual StatusCode initialize() override
Definition: L1TriggerByteStreamDecoderAlg.cxx:76
L1TriggerByteStreamDecoderAlg::finalize
virtual StatusCode finalize() override
Definition: L1TriggerByteStreamDecoderAlg.cxx:150
AnalysisUtils::copy_if
Out copy_if(In first, const In &last, Out res, const Pred &p)
Definition: IFilterUtils.h:30
L1TriggerByteStreamDecoderAlg::m_maybeMissingRobs
std::set< uint32_t > m_maybeMissingRobs
Set of ROB IDs allowed to be missing because they are disabled.
Definition: L1TriggerByteStreamDecoderAlg.h:93
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
IROBDataProviderSvc::VROBFRAG
std::vector< const ROBF * > VROBFRAG
Definition: IROBDataProviderSvc.h:29
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
L1TriggerByteStreamDecoderAlg::m_robDataProviderSvc
ServiceHandle< IROBDataProviderSvc > m_robDataProviderSvc
ROBDataProvider service handle.
Definition: L1TriggerByteStreamDecoderAlg.h:37
ReadTripsProbsFromCool.denominator
denominator
Definition: ReadTripsProbsFromCool.py:96
L1TriggerByteStreamDecoderAlg::m_robFormatCheckLevel
Gaudi::Property< std::string > m_robFormatCheckLevel
Set behaviour for corrupted ROB data.
Definition: L1TriggerByteStreamDecoderAlg.h:64
compute_lumi.denom
denom
Definition: compute_lumi.py:76
min
#define min(a, b)
Definition: cfImp.cxx:40
trigbs_pickEvents.num
num
Definition: trigbs_pickEvents.py:76
L1TriggerByteStreamDecoderAlg::start
virtual StatusCode start() override
Definition: L1TriggerByteStreamDecoderAlg.cxx:119
LVL1TGCTrigger::operator++
TGCHBChip operator++(TGCHBChip &rs, int)
Definition: TGCHighPtBoard.h:28
L1TriggerByteStreamDecoderAlg::ROBCheckBehaviour
ROBCheckBehaviour
The behaviour for non-zero ROB status words.
Definition: L1TriggerByteStreamDecoderAlg.h:95
L1TriggerByteStreamDecoderAlg::filterRobs
StatusCode filterRobs(const IROBDataProviderSvc::VROBFRAG &in, IROBDataProviderSvc::VROBFRAG &out, const std::vector< uint32_t > &ids, std::string_view toolName, const EventContext &eventContext) const
Copy over ROBFragment pointers from in to out for ROBs with IDs from the ids list.
Definition: L1TriggerByteStreamDecoderAlg.cxx:192
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:194
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
python.subdetectors.mmg.ids
ids
Definition: mmg.py:8
L1TriggerByteStreamDecoderAlg::m_robFormatCheck
ROBCheckBehaviour m_robFormatCheck
Definition: L1TriggerByteStreamDecoderAlg.h:97
AtlCoolConsole.tool
tool
Definition: AtlCoolConsole.py:453
L1TriggerByteStreamDecoderAlg::ROBCheckBehaviour::None
@ None
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
DeMoScan.first
bool first
Definition: DeMoScan.py:534
L1TriggerByteStreamDecoderAlg::m_robIds
std::vector< uint32_t > m_robIds
Vector of ROB IDs to request, filled from all decoder tools in initialize.
Definition: L1TriggerByteStreamDecoderAlg.h:91
L1TriggerByteStreamDecoderAlg::m_maybeMissingRobsProp
Gaudi::Property< std::vector< uint32_t > > m_maybeMissingRobsProp
Allow some ROBs to be missing.
Definition: L1TriggerByteStreamDecoderAlg.h:50
Monitored::Scalar
Declare a monitored scalar variable.
Definition: MonitoredScalar.h:34
L1TriggerByteStreamDecoderAlg::checkRobs
StatusCode checkRobs(const IROBDataProviderSvc::VROBFRAG &robs, std::string_view toolName, const EventContext &eventContext) const
Check ROB status word and report if different from zero.
Definition: L1TriggerByteStreamDecoderAlg.cxx:239
SG::AllowEmpty
@ AllowEmpty
Definition: StoreGate/StoreGate/VarHandleKey.h:30
readCCLHist.float
float
Definition: readCCLHist.py:83
Monitored::Timer
A monitored timer.
Definition: MonitoredTimer.h:32
L1TriggerByteStreamDecoderAlg::ROBCheckBehaviour::Fatal
@ Fatal
beamspotman.fail
def fail(message)
Definition: beamspotman.py:201
LB_AnalMapSplitter.lbn
lbn
Definition: LB_AnalMapSplitter.py:28