ATLAS Offline Software
TrigDecisionMakerMT.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 /**************************************************************************
6  **
7  ** File: TrigDecisionMakerMT.h
8  **
9  ** Description: - Re-entrant Algorithm-derived class to run after the MT Trigger to create the
10  ** xAOD::TrigDecision object. Based on TrigDecisionMaker.cxx
11  **
12  * @author Tim Martin <Tim.Martin@cern.ch> - University of Warwick
13  **
14  ** Created: 16 July 2018
15  **
16  **************************************************************************/
17 
18 #include "TrigDecisionMakerMT.h"
19 
22 #include "Lvl1ResultAccessTool.h"
23 
25 
26 #include <boost/dynamic_bitset.hpp>
27 
28 TrigDec::TrigDecisionMakerMT::TrigDecisionMakerMT(const std::string &name, ISvcLocator *pSvcLocator)
29  : ::AthReentrantAlgorithm(name, pSvcLocator)
30 {}
31 
33 
36 {
37 
38  bool resultObjectIsUsed = true;
39  if (!m_bitsMakerTool.empty()) {
40  ATH_MSG_INFO("TrigDecisionMakerMT is setting up to run after the Trigger in a job with POOL output. "
41  "The TriggerBitsMakerTool will be used directly to create the xAOD::TrigDecision.");
42  ATH_CHECK( m_bitsMakerTool.retrieve() );
43  resultObjectIsUsed = false;
44  } else {
45  ATH_MSG_INFO("TrigDecisionMakerMT is setting up to read the trigger bits from trigger bytestream. "
46  "The HLTResultMT object will be used as the source of the trigger bits.");
47  }
48  ATH_CHECK( m_hltResultKeyIn.initialize(resultObjectIsUsed) ); // If false, this removes the ReadHandle
49 
50  ATH_CHECK( m_bgKey.initialize() );
51  ATH_CHECK( m_HLTMenuKey.initialize() );
52 
53  ATH_CHECK( m_ROIBResultKeyIn.initialize() );
54  ATH_CHECK( m_EventInfoKeyIn.initialize() );
55 
56  ATH_CHECK( m_trigDecisionKeyOut.initialize() );
57 
58  ATH_CHECK( m_lvl1Tool.retrieve() );
59 
60  ATH_CHECK( m_CTPResultKeyIn.initialize( m_useEDMxAOD ) );
61  ATH_CHECK( m_l1ResultKeyOut.initialize( m_useEDMxAOD ) );
62 
63  return StatusCode::SUCCESS;
64 }
65 
68 {
69  // print out stats: used also to do regression tests
70  ATH_MSG_DEBUG ("=============================================");
71  ATH_MSG_DEBUG ("REGTEST Run summary:");
72  ATH_MSG_DEBUG ("REGTEST Events processed : " << m_nEvents);
73  ATH_MSG_DEBUG ("REGTEST Level 1 : passed = " << m_l1Passed);
74  ATH_MSG_DEBUG ("REGTEST HLT : passed = " << m_hltPassed);
75  ATH_MSG_DEBUG ("=============================================");
76 
77  return StatusCode::SUCCESS;
78 }
79 
81 TrigDec::TrigDecisionMakerMT::execute(const EventContext &context) const
82 {
83  using namespace TrigCompositeUtils;
84 
85  // increment event counter
86  m_nEvents++;
87 
88  std::unique_ptr<xAOD::TrigDecision> trigDec = std::make_unique<xAOD::TrigDecision>();
89  std::unique_ptr<xAOD::TrigDecisionAuxInfo> trigDecAux = std::make_unique<xAOD::TrigDecisionAuxInfo>();
90  trigDec->setStore(trigDecAux.get());
91 
92  SG::ReadHandle<TrigConf::HLTMenu> hltMenu(m_HLTMenuKey, context);
93  ATH_CHECK(hltMenu.isValid());
94  trigDec->setSMK(hltMenu->smk());
95 
96  if (m_doL1) {
97  const LVL1CTP::Lvl1Result* l1Result = nullptr;
98  ATH_CHECK(getL1Result(l1Result, context));
99 
100  trigDec->setTAV(l1Result->itemsAfterVeto());
101  trigDec->setTAP(l1Result->itemsAfterPrescale());
102  trigDec->setTBP(l1Result->itemsBeforePrescale());
103 
104  if (l1Result->isAccepted()) {
105  ++m_l1Passed;
106  }
107  }
108 
109  if (m_doHLT) {
110 
111  boost::dynamic_bitset<uint32_t> passRawBitset, prescaledBitset;
112 
113  if (m_bitsMakerTool.isSet()) {
114 
115  ATH_MSG_DEBUG ("MC Mode: Creating bits with TriggerBitsMakerTool");
116  ATH_CHECK(m_bitsMakerTool->getBits(passRawBitset, prescaledBitset, context));
117 
118  } else {
119 
120  ATH_MSG_DEBUG ("Data Mode: Reading bits from HLTResultMT");
121  SG::ReadHandle<HLT::HLTResultMT> hltResult = SG::makeHandle<HLT::HLTResultMT>(m_hltResultKeyIn, context);
122  ATH_CHECK(hltResult.isValid());
123 
124  passRawBitset = hltResult->getHltPassRawBits();
125  prescaledBitset = hltResult->getHltPrescaledBits();
126 
127  // Inspect error codes from event header
128  const std::vector<HLT::OnlineErrorCode> errorCodes = hltResult->getErrorCodes();
129  bool truncated = false;
130  uint32_t code = 0;
131  for (size_t i = 0; i < errorCodes.size(); ++i) {
132  truncated |= (errorCodes.at(i) == HLT::OnlineErrorCode::RESULT_TRUNCATION);
133  if (i == 0) {
134  code = static_cast<uint32_t>(errorCodes.at(0));
135  }
136  }
137 
138  // If the event header does not show any truncation check the individual HLT ROBs
139  // to cover the case of allowed result truncation (see ATR-27986).
140  //
141  // We only support one truncation status in the TrigDecision. So the convention is:
142  // 1) If the main HLT result is available, its status is reflected (e.g. Physics stream)
143  // 2) If not, we take the combined status of all other ROBs, but in practice there
144  // should only ever be one (TLA) ROB in a given stream.
145  if (!truncated) {
146  std::set<uint16_t> allModuleIds; // sorted(!) set of module IDs
147  for (const auto& itr : hltResult->getSerialisedData()) allModuleIds.insert(itr.first);
148 
149  for (uint16_t moduleId : allModuleIds) {
150  const std::vector<uint32_t>& status = hltResult->getRobStatus(moduleId);
151  if (status.size() > 1) { // status[0] is the generic eformat event status
152  truncated |= (status[1] == static_cast<uint32_t>(HLT::OnlineErrorCode::RESULT_TRUNCATION));
153  code |= status[1];
154  }
155  if (moduleId==0) break;
156  }
157  }
158 
159  trigDec->setEFErrorBits(code);
160  trigDec->setEFTruncated(truncated);
161  }
162 
163  ATH_MSG_DEBUG ("Number of HLT chains passed raw: " << passRawBitset.count());
164  ATH_MSG_DEBUG ("Number of HLT chains prescaled out: " << prescaledBitset.count());
165 
166  if (passRawBitset.any()) {
167  ++m_hltPassed;
168  }
169 
170  std::vector<uint32_t> passRaw, prescaled;
171 
172  passRaw.resize(passRawBitset.num_blocks());
173  prescaled.resize(prescaledBitset.num_blocks());
174 
175  boost::to_block_range(passRawBitset, passRaw.begin());
176  boost::to_block_range(prescaledBitset, prescaled.begin());
177 
178  // OFFLINE FIX TO P1 OPERATIONAL ISSUE 28th-31st July 2022
179  // [ATR-26036] These runs had an incomplete fix applied leading to incorrect prescale bits, prior runs in Run 3 had no presacled bits.
180  // Incorrect prescale bits will cause incorrect results from the Trig Decision Tool. Hence these need to be zeroed out (no prescale bits is better than wrong prescale bits)
181  static const std::set<unsigned> buggyPrescaleBitRuns = {429603, 429606, 429612, 429658, 429697, 429716};
182  const bool isBuggyPrescaleBitsRun = (std::find(buggyPrescaleBitRuns.begin(), buggyPrescaleBitRuns.end(), context.eventID().run_number()) != buggyPrescaleBitRuns.end());
183  if (isBuggyPrescaleBitsRun) {
184  ATH_MSG_DEBUG("T0 Trigger fix for 429603-429716 is deleting incorrect isPrescaled trigger bits decoded from the bytestream.");
185  for (size_t i = 0; i < prescaled.size(); ++i) {
186  prescaled.at(i) = 0;
187  }
188  }
189 
190  if (passRaw.size() != prescaled.size()) {
191  ATH_MSG_ERROR("Trigger bitsets are not all the same size! passRaw:"
192  << passRaw.size() << " prescaled:" << prescaled.size() );
193  return StatusCode::FAILURE;
194  }
195 
196  // Run 3 note: with only a two-level system, with no passthrough bit, no resurrection bit
197  // the raw-pass equates to the physics-pass.
198  trigDec->setEFPassedRaw(passRaw);
199  trigDec->setEFPassedPhysics(passRaw);
200  trigDec->setEFPrescaled(prescaled);
201 
202  }
203 
204  // get the bunch crossing id
205  const xAOD::EventInfo* eventInfo = SG::get(m_EventInfoKeyIn, context);
206  SG::ReadCondHandle<TrigConf::L1BunchGroupSet> bgkey(m_bgKey, context);
207  ATH_CHECK(bgkey.isValid());
208  const TrigConf::L1BunchGroupSet* l1bgs = *bgkey;
209  if (l1bgs) {
210  // We currently only support 8 bits/bunchgroups (ATR-24030)
211  trigDec->setBGCode( static_cast<char>(l1bgs->bgPattern(eventInfo->bcid())) );
212  }
213  else {
214  ATH_MSG_WARNING("Could not read " << m_bgKey);
215  }
216 
217  ATH_MSG_DEBUG ( "Run '" << eventInfo->runNumber()
218  << "'; Event '" << eventInfo->eventNumber()
219  << "'; BCID '" << eventInfo->bcid()
220  << "'; BG Code '" << trigDec->bgCode() << "'" ) ;
221 
222  ATH_MSG_DEBUG ("Decision object dump: " << *(trigDec.get()));
223  auto trigDecWriteHandle = SG::makeHandle( m_trigDecisionKeyOut, context );
224  ATH_CHECK( trigDecWriteHandle.record( std::move( trigDec ), std::move( trigDecAux ) ) );
225  ATH_MSG_DEBUG ("Recorded xAOD::TrigDecision to StoreGate with key = " << m_trigDecisionKeyOut.key());
226 
227  return StatusCode::SUCCESS;
228 }
229 
231 TrigDec::TrigDecisionMakerMT::getL1Result(const LVL1CTP::Lvl1Result *&result, const EventContext &context) const
232 {
233 
234  if (m_useEDMxAOD) {
235 
236  SG::ReadHandle<xAOD::CTPResult> ctpResult = SG::makeHandle<xAOD::CTPResult>(m_CTPResultKeyIn, context);
237  ATH_CHECK(ctpResult.isValid());
238 
239  // Fill TBP, TAP, TAV when creating the Lvl1Result
240  auto lvl1Result = std::make_unique<LVL1CTP::Lvl1Result>(true);
241 
242  // TBP words
243  const std::vector<uint32_t> ctpTBPWords = ctpResult->getTBPWords();
244  for (unsigned int iWord=0; iWord < ctpTBPWords.size(); ++iWord) {
245  lvl1Result->itemsBeforePrescale().push_back(ctpTBPWords[iWord]);
246  ATH_MSG_DEBUG( "TBP word #" << iWord << " is 0x" << std::hex << std::setw( 8 ) << std::setfill( '0' ) << ctpTBPWords[iWord] << std::dec);
247  }
248 
249  // TAP words
250  const std::vector<uint32_t> ctpTAPWords = ctpResult->getTAPWords();
251  for (unsigned int iWord=0; iWord < ctpTAPWords.size(); ++iWord) {
252  lvl1Result->itemsAfterPrescale().push_back(ctpTAPWords[iWord]);
253  ATH_MSG_DEBUG("TAP word #" << iWord << " is 0x" << std::hex << std::setw( 8 ) << std::setfill( '0' ) << ctpTAPWords[iWord] << std::dec);
254  }
255 
256  // TAV words
257  const std::vector<uint32_t> ctpTAVWords = ctpResult->getTAVWords();
258  for (unsigned int iWord = 0; iWord < ctpTAVWords.size(); ++iWord) {
259  lvl1Result->itemsAfterVeto().push_back(ctpTAVWords[iWord]);
260  ATH_MSG_DEBUG("TAV word #" << iWord << " is 0x" << std::hex << std::setw( 8 ) << std::setfill( '0' ) << ctpTAVWords[iWord] << std::dec);
261  }
262 
263  // make sure TBP, TAP, TAV all have 8 entries!
264  if (lvl1Result->itemsBeforePrescale().size() < 8) lvl1Result->itemsBeforePrescale().resize(8, 0);
265  if (lvl1Result->itemsAfterPrescale().size() < 8) lvl1Result->itemsAfterPrescale().resize(8, 0);
266  if (lvl1Result->itemsAfterVeto().size() < 8) lvl1Result->itemsAfterVeto().resize(8, 0);
267 
268  result = static_cast<const LVL1CTP::Lvl1Result*>(lvl1Result.get());
269  if (result == nullptr) {
270  ATH_MSG_ERROR ( "Could not construct L1 result from xAOD::CTPResult");
271  return StatusCode::FAILURE;
272  }
273 
274  ATH_CHECK(SG::makeHandle(m_l1ResultKeyOut, context).record( std::move(lvl1Result)), {});
275  ATH_MSG_INFO ( "Built LVL1CTP::Lvl1Result from valid xAOD::CTPResult.");
276 
277  } else {
278 
279  SG::ReadHandle<ROIB::RoIBResult> roIBResult = SG::makeHandle<ROIB::RoIBResult>(m_ROIBResultKeyIn, context);
280  ATH_CHECK(roIBResult.isValid());
281 
282  std::vector< std::unique_ptr<LVL1CTP::Lvl1Item> > itemConfig = m_lvl1Tool->makeLvl1ItemConfig(context);
283 
284  if (roIBResult->cTPResult().isComplete()) {
285  m_lvl1Tool->createL1Items(itemConfig, *roIBResult, &result);
286  ATH_MSG_DEBUG ( "Built LVL1CTP::Lvl1Result from valid ROIB::CTPResult.");
287  }
288 
289  if (result == nullptr) {
290  ATH_MSG_ERROR ( "Could not construct L1 result from roIBResult");
291  return StatusCode::FAILURE;
292  }
293 
294  }
295 
296  return StatusCode::SUCCESS;
297 }
xAOD::TrigDecision_v1::setSMK
void setSMK(uint32_t value)
Set the Super Master Key describing this object.
xAOD::TrigDecision_v1::setEFPassedPhysics
void setEFPassedPhysics(const std::vector< uint32_t > &value)
Set the EF physics decision bits.
get_generator_info.result
result
Definition: get_generator_info.py:21
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
xAOD::CTPResult_v1::getTAVWords
std::vector< uint32_t > getTAVWords(const int bunchPosition=-1) const
Get the TAV (Trigger After Veto) words.
Definition: CTPResult_v1.cxx:149
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
xAOD::EventInfo_v1::eventNumber
uint64_t eventNumber() const
The current event's event number.
TrigDecisionAuxInfo.h
TrigDec::TrigDecisionMakerMT::execute
virtual StatusCode execute(const EventContext &context) const override
Re-entrant execute to create the xAOD::TrigDecision.
Definition: TrigDecisionMakerMT.cxx:81
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
TrigConf::HLTMenu::smk
unsigned int smk() const
setter and getter for the supermasterkey
Definition: HLTMenu.cxx:41
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
xAOD::TrigDecision_v1::setEFTruncated
void setEFTruncated(bool value)
Set whether the EF result is truncated.
SG::ReadCondHandle::isValid
bool isValid()
Definition: ReadCondHandle.h:210
TrigDecisionMakerMT.h
xAOD::EventInfo_v1::runNumber
uint32_t runNumber() const
The current event's run number.
LVL1CTP::Lvl1Result::itemsBeforePrescale
const std::vector< uint32_t > & itemsBeforePrescale() const
Definition: Lvl1Result.h:55
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:74
Lvl1ResultAccessTool.h
LVL1CTP::Lvl1Result::itemsAfterVeto
const std::vector< uint32_t > & itemsAfterVeto() const
Definition: Lvl1Result.h:57
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:274
Lvl1Result.h
TrigDec::TrigDecisionMakerMT::~TrigDecisionMakerMT
~TrigDecisionMakerMT()
std deconstructor
Definition: TrigDecisionMakerMT.cxx:32
LVL1CTP::Lvl1Result::isAccepted
bool isAccepted() const
final LVL1 decision && isConfigured
Definition: Lvl1Result.cxx:19
HLT::HLTResultMT::getRobStatus
const std::vector< uint32_t > & getRobStatus(uint16_t moduleId) const
Status words for ROB with given moduleId.
Definition: HLTResultMT.cxx:226
HLT::HLTResultMT::getErrorCodes
const std::vector< HLT::OnlineErrorCode > getErrorCodes() const
Error codes getter (by value) - strips off the first bit-mask status word.
Definition: HLTResultMT.cxx:201
histSizes.code
code
Definition: histSizes.py:129
TrigDec::TrigDecisionMakerMT::finalize
virtual StatusCode finalize() override
std Gaudi finalize method -> print out statistics
Definition: TrigDecisionMakerMT.cxx:67
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
xAOD::uint16_t
setWord1 uint16_t
Definition: eFexEMRoI_v1.cxx:93
lumiFormat.i
int i
Definition: lumiFormat.py:85
SG::AuxElement::setStore
void setStore(const SG::IConstAuxStore *store)
Set the store associated with this object.
Definition: AuxElement.cxx:241
SG::get
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
Definition: ReadCondHandle.h:287
xAOD::TrigDecision_v1::setTAP
void setTAP(const std::vector< uint32_t > &value)
Set the Trigger After Prescale bits.
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
xAOD::TrigDecision_v1::setTBP
void setTBP(const std::vector< uint32_t > &value)
Set the Trigger Before Prescale bits.
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
xAOD::TrigDecision_v1::setTAV
void setTAV(const std::vector< uint32_t > &value)
Set the Trigger After Veto bits.
TrigDec::TrigDecisionMakerMT::getL1Result
StatusCode getL1Result(const LVL1CTP::Lvl1Result *&result, const EventContext &context) const
retrieve LVL1 result (called in execute)
Definition: TrigDecisionMakerMT.cxx:231
TrigConf::L1BunchGroupSet
L1 board configuration.
Definition: L1BunchGroupSet.h:71
TrigConf::L1BunchGroupSet::bgPattern
bgPattern_t bgPattern(size_t bcid) const
Return word with bit-pattern of fired bunchgroups for given bcid.
Definition: L1BunchGroupSet.cxx:138
xAOD::TrigDecision_v1::setEFErrorBits
void setEFErrorBits(uint32_t value)
Set a summary of all errors that happened during the EF execution.
TrigDec::TrigDecisionMakerMT::initialize
virtual StatusCode initialize() override
std Gaudi initialize method -> read-in trigger configuration
Definition: TrigDecisionMakerMT.cxx:35
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
ROIB::RoIBResult::cTPResult
const CTPResult & cTPResult() const
Gets the CTP part of the L1 RDO.
Definition: RoIBResult.cxx:60
OnlineErrorCode.h
LVL1CTP::Lvl1Result
Definition: Lvl1Result.h:32
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
HLT::HLTResultMT::getSerialisedData
const std::unordered_map< uint16_t, std::vector< uint32_t > > & getSerialisedData() const
Serialised data getter.
Definition: HLTResultMT.cxx:147
xAOD::EventInfo_v1
Class describing the basic event information.
Definition: EventInfo_v1.h:43
xAOD::TrigDecision_v1::setEFPrescaled
void setEFPrescaled(const std::vector< uint32_t > &value)
Set the EF prescaled bits.
xAOD::TrigDecision_v1::bgCode
char bgCode() const
Get the bunch group code of the current event.
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
xAOD::TrigDecision_v1::setEFPassedRaw
void setEFPassedRaw(const std::vector< uint32_t > &value)
Set the EF passed-raw bits.
TrigCompositeUtils
Definition: Event/xAOD/xAODTrigger/xAODTrigger/TrigComposite.h:19
xAOD::CTPResult_v1::getTAPWords
std::vector< uint32_t > getTAPWords(const int bunchPosition=-1) const
Get the TAP (Trigger After Prescale) words.
Definition: CTPResult_v1.cxx:144
HLT::HLTResultMT::getHltPrescaledBits
const boost::dynamic_bitset< uint32_t > & getHltPrescaledBits() const
Const-getter for HLT prescaled bits.
Definition: HLTResultMT.cxx:95
xAOD::TrigDecision_v1::setBGCode
void setBGCode(char value)
Set the bunch group code of the current event.
HLT::OnlineErrorCode::RESULT_TRUNCATION
@ RESULT_TRUNCATION
merge.status
status
Definition: merge.py:16
TrigDec::TrigDecisionMakerMT::TrigDecisionMakerMT
TrigDecisionMakerMT(const std::string &name, ISvcLocator *pSvcLocator)
std Gaudi Algorithm constructor
Definition: TrigDecisionMakerMT.cxx:28
xAOD::EventInfo_v1::bcid
uint32_t bcid() const
The bunch crossing ID of the event.
xAOD::CTPResult_v1::getTBPWords
std::vector< uint32_t > getTBPWords(const int bunchPosition=-1) const
Get the TBP (Trigger Before Prescale) words.
Definition: CTPResult_v1.cxx:139
LVL1CTP::Lvl1Result::itemsAfterPrescale
const std::vector< uint32_t > & itemsAfterPrescale() const
Definition: Lvl1Result.h:56
ROIB::CTPResult::isComplete
bool isComplete() const
returns true if object isValid() and data has the expected length
HLT::HLTResultMT::getHltPassRawBits
const boost::dynamic_bitset< uint32_t > & getHltPassRawBits() const
Const-getter for HLT pass raw bits.
Definition: HLTResultMT.cxx:90