ATLAS Offline Software
eFexByteStreamTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 //***************************************************************************
6 // eFexByteStreamTool - description
7 // -------------------
8 // begin : 11 05 2022
9 // email : will@cern.ch
10 // ***************************************************************************/
11 
12 #include "eFexByteStreamTool.h"
13 #include "CxxUtils/span.h"
14 #include "eformat/SourceIdentifier.h"
15 #include "eformat/Status.h"
16 
25 
28 
29 namespace {
30  // Helper method for creating the containers
31  template<typename T, typename W>
33  std::map <std::pair<L1CaloRdoFexTob::TobSource, bool>, SG::WriteHandle<T>> &map,
34  L1CaloRdoFexTob::TobSource source, bool inTime, const SG::WriteHandleKey <T> &handle,
35  const EventContext &ctx) {
36  if (!handle.empty()) {
37  return map.emplace(std::make_pair(source, inTime),
38  SG::WriteHandle<T>(handle, ctx)).first->second.record(
39  std::make_unique<T>(), std::make_unique<W>());
40  }
41  return StatusCode::SUCCESS;
42  }
43 }
44 
46  const std::string& name,
47  const IInterface* parent)
48  : base_class(type, name, parent) {}
49 
51 
52  // Initialise eEM data handle keys
53  ATH_CHECK(m_eEMReadKey.initialize(!m_eEMReadKey.empty()));
54  ATH_CHECK(m_eEMWriteKey.initialize(!m_eEMWriteKey.empty()));
55 
56  // Initialise eTAU data handle keys
57  ATH_CHECK(m_eTAUReadKey.initialize(!m_eTAUReadKey.empty()));
58  ATH_CHECK(m_eTAUWriteKey.initialize(!m_eTAUWriteKey.empty()));
59 
60  // write keys for xTOBs
61  ATH_CHECK(m_eEMxWriteKey.initialize(!m_eEMxWriteKey.empty()));
62  ATH_CHECK(m_eTAUxWriteKey.initialize(!m_eTAUxWriteKey.empty()));
63 
64  // multislice TOBs
65  ATH_CHECK(m_eEMSliceWriteKey.initialize(!m_eEMSliceWriteKey.empty()));
67 
68  // Initialize eTower handle key
69  ATH_CHECK(m_eTowerWriteKey.initialize(!m_eTowerWriteKey.empty()));
70 
71  m_decoder = std::make_unique<L1CaloBsDecoderRun3>();
72 
73  // Initialize monitoring tool if not empty
74  if (!m_monTool.empty()) {
75  ATH_CHECK(m_monTool.retrieve());
76  m_decoder->setLogger( std::make_unique<MonitoredLogging>(m_monTool) );
77  ATH_MSG_INFO("Logging errors to " << m_monTool.name() << " monitoring tool");
78  }
79 
80 
81  return StatusCode::SUCCESS;
82 }
83 
84 void eFexByteStreamTool::MonitoredLogging::err(const std::string& location, const std::string& title, const std::string&) const {
85 
87  Monitored::Scalar("efexDecoderErrorLocation",std::string("lb=") + std::to_string(Gaudi::Hive::currentContext().eventID().lumi_block()) + "," + (location.empty() ? std::string("UNKNOWN") : location)),
88  Monitored::Scalar("efexDecoderErrorTitle",title.empty() ? std::string("UNKNOWN") : title)
89  );
90 
91  Monitored::Group(m_monTool, Monitored::Scalar("lbn",Gaudi::Hive::currentContext().eventID().lumi_block()),
92  Monitored::Scalar("decoderError",(title.empty() ? std::string("UNKNOWN") : title) + ":" + (location.empty() ? std::string("UNKNOWN") : location))
93  );
94 }
95 
96 // BS->xAOD conversion
97 StatusCode eFexByteStreamTool::convertFromBS(const std::vector<const ROBF*>& vrobf, const EventContext& ctx) const {
98 
99  // indices are source (tob or xtob) and bool for in/out of time
100  std::map<std::pair<L1CaloRdoFexTob::TobSource,bool>,SG::WriteHandle<xAOD::eFexEMRoIContainer>> eContainers;
101  std::map<std::pair<L1CaloRdoFexTob::TobSource,bool>,SG::WriteHandle<xAOD::eFexTauRoIContainer>> tContainers;
102 
103  bool multislice=false;
104 
105  if (!m_eEMWriteKey.empty()) {
106  ATH_CHECK(StatusCode(addContainer<xAOD::eFexEMRoIContainer, xAOD::eFexEMRoIAuxContainer>(
107  eContainers, L1CaloRdoFexTob::TobSource::EfexTob, false, m_eEMWriteKey, ctx)));
108  }
109  if (!m_eTAUWriteKey.empty()) {
110  ATH_CHECK(StatusCode(addContainer<xAOD::eFexTauRoIContainer, xAOD::eFexTauRoIAuxContainer>(
111  tContainers, L1CaloRdoFexTob::TobSource::EfexTob, false, m_eTAUWriteKey, ctx)));
112  }
113  if (!m_eEMxWriteKey.empty()) {
114  ATH_CHECK( StatusCode(addContainer<xAOD::eFexEMRoIContainer,xAOD::eFexEMRoIAuxContainer>(
115  eContainers,L1CaloRdoFexTob::TobSource::EfexXtob,false,m_eEMxWriteKey,ctx)) );
116  }
117  if (!m_eTAUxWriteKey.empty()) {
118  ATH_CHECK( StatusCode(addContainer<xAOD::eFexTauRoIContainer,xAOD::eFexTauRoIAuxContainer>(
119  tContainers,L1CaloRdoFexTob::TobSource::EfexXtob,false,m_eTAUxWriteKey,ctx)) );
120  }
121  if (!m_eEMSliceWriteKey.empty()) {
122  ATH_CHECK( StatusCode(addContainer<xAOD::eFexEMRoIContainer,xAOD::eFexEMRoIAuxContainer>(
123  eContainers,L1CaloRdoFexTob::TobSource::EfexXtob,true,m_eEMSliceWriteKey,ctx)) );
124  multislice=true;
125  }
126  if (!m_eTAUSliceWriteKey.empty()) {
127  ATH_CHECK( StatusCode(addContainer<xAOD::eFexTauRoIContainer,xAOD::eFexTauRoIAuxContainer>(
128  tContainers,L1CaloRdoFexTob::TobSource::EfexXtob,true,m_eTAUSliceWriteKey,ctx)) );
129  multislice=true;
130  }
131 
132 
134  if(!m_eTowerWriteKey.empty()) {
136  ATH_CHECK( eTowers.record(std::make_unique<xAOD::eFexTowerContainer>(),std::make_unique<xAOD::eFexTowerAuxContainer>()) );
137  }
138 
139  std::list<L1CaloRdoRodInfo> rodInfos;
140  std::list<L1CaloRdoEfexTob> efexTobs;
141  std::list<L1CaloRdoEfexTower> efexTowers;
143  std::map<std::tuple<int,int,int,int,int>,size_t> towerMap; // maps {crate,module,fpga,eta,phi} onto index in vector
144  for (const ROBF* rob : vrobf) {
145  // Iterate over ROD words and decode
146  ATH_MSG_DEBUG("Decoding " << rob->rod_ndata() << " ROD words from ROB 0x" << std::hex << rob->rob_source_id() << std::dec);
147  L1CaloBsDecoderUtil::decodeRodInfo( rob, rodInfos );
148 
149  if(rob->rod_ndata()==0) continue;
150 
151  CxxUtils::span data{rob->rod_data(), rob->rod_ndata()};
152  auto lastRod = rodInfos.end(); lastRod--;
153 
154  if ( (rob->rob_source_id() >> 16) == eformat::TDAQ_CALO_FEAT_EXTRACT_DAQ && !m_eTowerWriteKey.empty() ) {
155  // decoding raw input data
156  // tower et counts should be in order: PS, L1, L2, L3, Had
157  // towers with all et counts 0 will still be zero-suppressed
158  efexTowers.clear();
159  decoder.decodeEfexData(data.begin(), data.end(), efexTowers, lastRod );
160  for(auto& t : efexTowers) {
161  if (t.getLayer() != 0) continue; // do hadronic in next loop
162  towerMap[std::make_tuple(t.getCrate(),t.getModule(),t.getFpgaNumber(),t.getRegion().getEtaIndex(),t.getRegion().getPhiIndex())] = eTowers->size();
163  eTowers->push_back( std::make_unique<xAOD::eFexTower>() );
164  // in bytestream cell orders are L2,PS,L1,L3 so reorder to usual PS,L1,L2,L3 order
165  std::vector<uint16_t> counts(11,0); // defaults hadronic to 1025, which we will use to indicate absent
166  counts[0] = t.getSupercells().at(4);
167  for(size_t idx = 0;idx<4;idx++) {
168  counts[idx+1] = t.getSupercells().at(idx+5); // L1
169  counts[idx+5] = t.getSupercells().at(idx); // L2
170  }
171  counts[9] = t.getSupercells().at(9);
172 
173  eTowers->back()->initialize(t.getRegion().getEtaIndex()*0.1 + 0.05,2.*ROOT::Math::Pi()*(0.5 + t.getRegion().getPhiIndex() - 64*(t.getRegion().getPhiIndex()>=32))/64,
174  counts,
175  t.getModule() + t.getCrate()*12,
176  t.getFpgaNumber(),
177  t.getFlag(),0 /* hadronic status flag */);
178  }
179 
180  for(auto& t : efexTowers) {
181  if (t.getLayer() == 0) continue; // do hadronic towers now ... add to existing towers
182  size_t idx = eTowers->size();
183  if(auto itr = towerMap.find({t.getCrate(), t.getModule(), t.getFpgaNumber(),t.getRegion().getEtaIndex(),t.getRegion().getPhiIndex()}); itr != towerMap.end()) {
184  idx = itr->second;
185  } else {
186  // possible that ecal tower was zero-suppressed but hcal has energy, so create such a tower
187  towerMap[std::make_tuple(t.getCrate(),t.getModule(),t.getFpgaNumber(),t.getRegion().getEtaIndex(),t.getRegion().getPhiIndex())] = eTowers->size();
188  eTowers->push_back( std::make_unique<xAOD::eFexTower>() );
189  eTowers->back()->initialize(t.getRegion().getEtaIndex()*0.1 + 0.05,2.*ROOT::Math::Pi()*(0.5 + t.getRegion().getPhiIndex() - 64*(t.getRegion().getPhiIndex()>=32))/64,
190  std::vector<uint16_t>(11,1025), // use 1025 count to indicate missing
191  t.getModule() + t.getCrate()*12,t.getFpgaNumber(),0,t.getFlag());
192  }
193  auto tower = eTowers->at(idx);
194  tower->setHad_status(t.getFlag());
195  auto et_count = tower->et_count();
196  et_count.at(10) = t.getValue();
197  tower->setEt_count(et_count);
198  }
199 
200 
201 
202  } else if ( (rob->rob_source_id() >> 16) == eformat::TDAQ_CALO_FEAT_EXTRACT_ROI ) {
203  // decoding tobs
204  efexTobs.clear();
205  decoder.decodeEfexTobs(data.begin(), data.end(), efexTobs, lastRod);
206 
207  for (const L1CaloRdoEfexTob &tob: efexTobs) {
208  // loop over slices ... create separate tobs for each, where there's a word defined
209  for (size_t slice = 0; slice < tob.numSlices(); slice++) {
210  if (!multislice && int(slice) != tob.getL1aPos())
211  continue; // ignore out-of-time slices if multiSlice option = false
212  if (tob.getWord0(slice) == 0) continue; // this tob isn't in this slice
213  if (tob.getTobType() == L1CaloRdoFexTob::TobType::EM) {
214  auto cont = eContainers.find({tob.getTobSource(), int(slice) != tob.getL1aPos()});
215  if (cont == eContainers.end()) continue; // not writing this tob collection
216  cont->second->push_back(std::make_unique<xAOD::eFexEMRoI>());
217  if (tob.getTobSource() == L1CaloRdoFexTob::TobSource::EfexTob) {
218  cont->second->back()->initialize(tob.getModule(), tob.getCrate(), tob.getWord0(slice));
219  } else {
220  cont->second->back()->initialize(tob.getWord0(slice), tob.getWord1(slice));
221  }
222  } else if (tob.getTobType() == L1CaloRdoFexTob::TobType::Tau) {
223  auto cont = tContainers.find({tob.getTobSource(), int(slice) != tob.getL1aPos()});
224  if (cont == tContainers.end()) continue; // not writing this tob collection
225  cont->second->push_back(std::make_unique<xAOD::eFexTauRoI>());
226  if (tob.getTobSource() == L1CaloRdoFexTob::TobSource::EfexTob) {
227  cont->second->back()->initialize(tob.getModule(), tob.getCrate(), tob.getWord0(slice));
228  } else {
229  cont->second->back()->initialize(tob.getWord0(slice), tob.getWord1(slice));
230  }
231  }
232  } // timeslice loop
233  } // tob loop
234  } // tob data if block
235  } // fragment loop
236 
237  if(msgLevel(MSG::DEBUG)) {
238  std::stringstream msg;
239  for (auto&[k, v]: eContainers) {
240  msg << v->size() << " " << (k.second ? "out-of-time " : "in-time ") << "eg" <<
241  (k.first == L1CaloRdoFexTob::TobSource::EfexTob ? "" : "x") << "TOB, ";
242  }
243  for (auto&[k, v]: tContainers) {
244  msg << v->size() << " " << (k.second ? "out-of-time " : "in-time ") << "tau" <<
245  (k.first == L1CaloRdoFexTob::TobSource::EfexTob ? "" : "x") << "TOB, ";
246  }
247  ATH_MSG_DEBUG("Decoded: " << msg.str());
248  if (!m_eTowerWriteKey.empty()) {
249  ATH_MSG_DEBUG("Decoded: " << eTowers->size() << " eTowers");
250  }
251  }
252  // this is how to print the in-time em xTOBs:
253 // for(const auto& tob : *(eContainers[{L1CaloRdoFexTob::TobSource::EfexXtob,false}])) {
254 // std::cout << tob->eFexNumber() << "." << tob->fpga() << ": " << tob->fpgaEta() << " " << tob->fpgaPhi() << " " << tob->et() << " " << tob->etXTOB() << " " << tob->etTOB() << " " << std::endl;
255 // }
256 
257  return StatusCode::SUCCESS;
258 }
259 
260 StatusCode eFexByteStreamTool::convertToBS(std::vector<OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment*>& , const EventContext& ) {
261  // not supported yet
262  return StatusCode::FAILURE;
263 }
264 
eFexByteStreamTool::m_decoder
std::unique_ptr< L1CaloBsDecoderRun3 > m_decoder
Definition: eFexByteStreamTool.h:107
eFexByteStreamTool::m_monTool
ToolHandle< GenericMonitoringTool > m_monTool
Definition: eFexByteStreamTool.h:61
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
TrigDefs::Group
Group
Properties of a chain group.
Definition: GroupProperties.h:13
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
python.LArCondContChannels.decoder
decoder
def channelSelection(self, channelList, groupType): if groupType == self.SingleGroup: pass elif group...
Definition: LArCondContChannels.py:618
eFexEMRoIAuxContainer.h
eFexByteStreamTool::m_eTAUxWriteKey
SG::WriteHandleKey< xAOD::eFexTauRoIContainer > m_eTAUxWriteKey
Definition: eFexByteStreamTool.h:85
eFexByteStreamTool::m_eTAUSliceWriteKey
SG::WriteHandleKey< xAOD::eFexTauRoIContainer > m_eTAUSliceWriteKey
Definition: eFexByteStreamTool.h:91
eFexByteStreamTool::m_eTAUWriteKey
SG::WriteHandleKey< xAOD::eFexTauRoIContainer > m_eTAUWriteKey
Definition: eFexByteStreamTool.h:81
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
SG::VarHandleKey::empty
bool empty() const
Test if the key is blank.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:150
CxxUtils::span
Simplified version of the C++20 std::span.
Definition: span.h:67
eFexByteStreamTool.h
L1CaloRdoEfexTob
Definition: L1CaloRdoEfexTob.h:10
eFexByteStreamTool::initialize
virtual StatusCode initialize() override
Definition: eFexByteStreamTool.cxx:50
eFexByteStreamTool::convertFromBS
virtual StatusCode convertFromBS(const std::vector< const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment * > &vrobf, const EventContext &eventContext) const override
BS->xAOD conversion.
Definition: eFexByteStreamTool.cxx:97
ROBF
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment ROBF
Definition: ByteStreamMergeOutputSvc.cxx:16
eFexByteStreamTool::MonitoredLogging::err
virtual void err(const std::string &location, const std::string &title, const std::string &detail) const override
Definition: eFexByteStreamTool.cxx:84
SG::WriteHandleKey
Property holding a SG store/key/clid from which a WriteHandle is made.
Definition: StoreGate/StoreGate/WriteHandleKey.h:40
Ringer::EM
@ EM
Definition: CaloRingsDefs.h:19
perfmonmt-refit.slice
slice
Definition: perfmonmt-refit.py:52
eFexByteStreamTool::m_eTowerWriteKey
SG::WriteHandleKey< xAOD::eFexTowerContainer > m_eTowerWriteKey
Definition: eFexByteStreamTool.h:94
eFexByteStreamTool::m_eEMSliceWriteKey
SG::WriteHandleKey< xAOD::eFexEMRoIContainer > m_eEMSliceWriteKey
Definition: eFexByteStreamTool.h:89
span.h
Simplified version of the C++20 std::span.
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
eFexByteStreamTool::m_eEMxWriteKey
SG::WriteHandleKey< xAOD::eFexEMRoIContainer > m_eEMxWriteKey
Definition: eFexByteStreamTool.h:83
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
python.sizes.location
string location
Definition: sizes.py:11
L1CaloRdoEfexTower.h
covarianceTool.title
title
Definition: covarianceTool.py:542
test_pyathena.parent
parent
Definition: test_pyathena.py:15
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Analysis::addContainer
Int_t addContainer(Analysis::CalibrationDataContainer *cnt, TFile *file, const char *tagger, const char *jetAuthor, const char *OP, const char *flavour, const char *name=0, bool isReference=false)
eFexTowerAuxContainer.h
DataVector::back
const T * back() const
Access the last element in the collection as an rvalue.
L1CaloRdoFexTob::TobSource
TobSource
Definition: L1CaloRdoFexTob.h:15
L1CaloBsDecoderRun3.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment
eformat::ROBFragment< PointerType > ROBFragment
Definition: RawEvent.h:27
eFexByteStreamTool::m_eTAUReadKey
SG::ReadHandleKey< xAOD::eFexTauRoIContainer > m_eTAUReadKey
Definition: eFexByteStreamTool.h:100
python.PyAthena.v
v
Definition: PyAthena.py:157
L1CaloRdoRodInfo.h
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment
eformat::write::ROBFragment ROBFragment
Definition: RawEvent.h:33
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
WROBF
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment WROBF
Definition: eFexByteStreamTool.cxx:27
eFexByteStreamTool::MonitoredLogging::m_monTool
ToolHandle< GenericMonitoringTool > m_monTool
Definition: eFexByteStreamTool.h:69
DEBUG
#define DEBUG
Definition: page_access.h:11
L1CaloRdoEfexTob.h
eFexTauRoIAuxContainer.h
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
eFexByteStreamTool::m_eEMReadKey
SG::ReadHandleKey< xAOD::eFexEMRoIContainer > m_eEMReadKey
Definition: eFexByteStreamTool.h:98
xAODType::Tau
@ Tau
The object is a tau (jet)
Definition: ObjectType.h:49
DataVector::at
const T * at(size_type n) const
Access an element, as an rvalue.
Monitored::Scalar
Declare a monitored scalar variable.
Definition: MonitoredScalar.h:34
L1CaloBsDecoderUtil.h
eFexByteStreamTool::m_eEMWriteKey
SG::WriteHandleKey< xAOD::eFexEMRoIContainer > m_eEMWriteKey
Definition: eFexByteStreamTool.h:79
L1CaloBsDecoderUtil::decodeRodInfo
static void decodeRodInfo(const eformat::ROBFragment< const uint32_t * > *rod, std::list< L1CaloRdoRodInfo > &dat)
Definition: L1CaloBsDecoderUtil.cxx:22
eFexByteStreamTool::eFexByteStreamTool
eFexByteStreamTool(const std::string &type, const std::string &name, const IInterface *parent)
Definition: eFexByteStreamTool.cxx:45
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
L1CaloBsDecoderRun3
Definition: L1CaloBsDecoderRun3.h:23
eFexByteStreamTool::convertToBS
virtual StatusCode convertToBS(std::vector< OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment * > &vrobf, const EventContext &eventContext) override
xAOD->BS conversion
Definition: eFexByteStreamTool.cxx:260
fitman.k
k
Definition: fitman.py:528