ATLAS Offline Software
Loading...
Searching...
No Matches
MdtROD_Decoder.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// The data format is described in ATL-DAQ-2003-023 / ATL-COM-MUON-2003-011
6// https://cds.cern.ch/record/685552
7// http://www.nikhef.nl/pub/experiments/atlas/daq/mrod/mrodprr/daq-2003-023.pdf
8
9#include "MdtROD_Decoder.h"
10
11#include <algorithm>
12
13#include "eformat/Issue.h"
14
15using eformat::helper::SourceIdentifier;
16
17static const InterfaceID IID_IMdtROD_Decoder("MdtROD_Decoder", 1, 0);
18
21MdtROD_Decoder::MdtROD_Decoder(const std::string& type, const std::string& name, const IInterface* parent) :
22 AthAlgTool(type, name, parent) {
23 declareInterface<MdtROD_Decoder>(this);
24
25 declareProperty("SpecialROBNumber", m_specialROBNumber = -1);
26}
27
28const InterfaceID& MdtROD_Decoder::interfaceID() { return IID_IMdtROD_Decoder; }
29
31 ATH_CHECK(m_idHelperSvc.retrieve());
32
33 // Here the mapping service has to be initialized
34 m_hid2re = std::make_unique<MDT_Hid2RESrcID>();
35 ATH_CHECK(m_hid2re->set(&m_idHelperSvc->mdtIdHelper()));
36 ATH_CHECK(m_readKey.initialize());
37
38 return StatusCode::SUCCESS;
39}
40
42 if (m_nCache > 0 || m_nNotCache > 0) {
43 const float cacheFraction = ((float)m_nCache) / ((float)(m_nCache + m_nNotCache));
44 ATH_MSG_INFO("Fraction of fills that use the cache = " << cacheFraction);
45 }
46
47 return StatusCode::SUCCESS;
48}
49
51#define WARNING_WITH_LINE(msg) ATH_MSG_WARNING(__func__ << "():" << __LINE__<< " " << msg)
52 // m_debug = (m_log.level() <= MSG::DEBUG); // use to control if output debug info.
53 // decoding classes
54 MdtCsmReadOut csmReadOut;
55 MdtAmtReadOut amtReadOut;
56 MdtHptdcReadOut hptdcReadOut;
57
58 ATH_MSG_DEBUG("fillCollection: starting");
59 uint32_t wordPos = 0;
60
61 // Check the ROB and ROD fragment for lenght and version consistency. E.P.
62
63 try {
64 robFrag.check();
65 } catch (const eformat::Issue& ex) {
66 WARNING_WITH_LINE(ex.what());
67 return StatusCode::FAILURE; // error in fragment - we search for no collection
68 }
69
70 // Check the ROB status word for truncation or corruption E.P.
71
72 uint32_t nstat = robFrag.nstatus();
73
74 if (nstat) {
75 const uint32_t* it{nullptr};
76 robFrag.status(it);
77
78 if (*it) {
79 WARNING_WITH_LINE("Error in ROB status word: 0x" << std::hex << *it << std::dec);
80
81 // the status word analysis in case of eformat version > 3.0
82 // if ( (robFrag.version() >> 16) > 0x0300 ) {
83
84 // various checks to be defined
85
86 //}
87 return StatusCode::FAILURE;
88 }
89 }
90
91 // here go the checks on the ROD header
92
93 const unsigned int size = robFrag.rod_ndata(); // Think this is right - it was size() before. Ed. // Yes it is... Enrico
94
95 // FIXME - Removed debug output for the moment. EJWM
96 // if (m_debug) log << MSG::DEBUG
97 // << "Collection identifier : " << csmOfflineId.getString() << endmsg;
98 //
99 // if (m_debug) log << MSG::DEBUG
100 // << "**********Decoder dumping the words******** " << endmsg;
101 // if (size > 0) {
102 // log << MSG::DEBUG << "The size of this ROD-read is " << size << endmsg;
103 // for (unsigned int i=0; i < size; i++)
104 // if (m_debug) log << MSG::DEBUG << "word " << i
105 // << " = " << MSG::hex << robFrag[i] << MSG::dec << endmsg;
106 // }
107 // else {
108 // if (m_debug) log << MSG::DEBUG << " Buffer size 0 ! "
109 // << endmsg;
110 // return;
111 // }
112
113 leading_amt_map leadingHitMap{};
114
115 // Decode the SourceId from the ROD Header
116 SourceIdentifier sid(robFrag.rod_source_id());
117
118 MuonMDT_CablingMap::CablingData cabling_data{};
119 cabling_data.subdetectorId = sid.subdetector_id();
120 cabling_data.mrod = sid.module_id();
121
122 // Get the first word of a buffer:
124 robFrag.rod_data(vint);
125
126 ATH_MSG_DEBUG("**********Decoder dumping the words******** ");
127
128 if (size > 0) {
129 ATH_MSG_DEBUG("The size of this ROD-read is ");
130 for (unsigned int i = 0; i < size; i++) ATH_MSG_DEBUG("word " << i << " = " << MSG::hex << vint[i] << MSG::dec);
131 } else {
132 WARNING_WITH_LINE("Buffer size 0 ! ");
133 return StatusCode::FAILURE;
134 }
135
136 csmReadOut.decodeWord(vint[wordPos]);
137
138 if (csmReadOut.is_BOB()) {
139 ATH_MSG_DEBUG("Found the beginning of buffer ");
140 // Check that Lvl1d matches the one from the ROD header
141 ATH_MSG_DEBUG("Level 1 Id : " << csmReadOut.lvl1Id());
142 } else {
143 ATH_MSG_WARNING(" Beginning of block not found ! ");
144 ATH_MSG_WARNING(" Subdetector, ROD ID: 0x" << MSG::hex << cabling_data.subdetectorId << MSG::dec << ", 0x" << cabling_data.mrod
145 << MSG::dec);
146 }
147
148 if (size < 2) {
149 WARNING_WITH_LINE("Too few ROD words: " << size);
150 return StatusCode::FAILURE;
151 }
152 ++wordPos;
153 csmReadOut.decodeWord(vint[wordPos]);
154 if (csmReadOut.is_EOB()) {
155 ATH_MSG_WARNING("No CSM data ROD ID: 0x" << MSG::hex << cabling_data.subdetectorId <<
156 ", 0x" << static_cast<unsigned int>(cabling_data.mrod) << MSG::dec);
157 return StatusCode::SUCCESS;
158 }
159
161 const MuonMDT_CablingMap* readCdo{*readHandle};
162 if (!readCdo) {
163 WARNING_WITH_LINE("Null pointer to the read conditions object");
164 return StatusCode::FAILURE;
165 }
166 auto& msg = msgStream();
167 while (!csmReadOut.is_EOB()) {
168 while ((!csmReadOut.is_BOL()) && (!csmReadOut.is_EOB())) {
169 wordPos += 1;
170 if (wordPos >= size) {
171 WARNING_WITH_LINE("failure: data corrupted");
172 return StatusCode::FAILURE;
173 }
174 csmReadOut.decodeWord(vint[wordPos]);
175 }
176
177 if (csmReadOut.is_BOL()) {
178 ATH_MSG_DEBUG("Found the Beginnning of Link ");
179 } else if (csmReadOut.is_EOB()) {
180 WARNING_WITH_LINE(" failure: collection not found");
181 return StatusCode::FAILURE;
182 }
183
184 // uint16_t subdetId = 0x61;
185 // uint16_t mrodId = csmReadOut.mrodId();
186
187 cabling_data.csm = csmReadOut.csmId();
188
189 // Get the offline identifier from the MDT cabling service
190 // TDC and Tube identifier are dummy, only the chamber map is needed here
191
192 ATH_MSG_DEBUG("subdetId : " << cabling_data.subdetectorId << " "
193 << "mrodId : " << cabling_data.mrod << " "
194 << "csmId : " << cabling_data.csm);
195
196 cabling_data.tdcId = 0xff;
197 cabling_data.channelId = 0xff;
198
199 Identifier moduleId{0};
200 IdentifierHash idHash{0};
201 bool cab = readCdo->getOfflineId(cabling_data, msg) && readCdo->getMultiLayerCode(cabling_data, moduleId, idHash, msg);
202
203 ATH_MSG_DEBUG("getOfflineIdfromOnlineID result: " << cabling_data);
204
205 if (!cab) {
206 ATH_MSG_WARNING("Cabling not understood");
207 ATH_MSG_WARNING("Skip decoding of CSM link, subdetId : " << MSG::hex << std::showbase << cabling_data.subdetectorId << " "
208 << "mrodId : " << cabling_data.mrod << " " << MSG::dec
209 << "csmId : " << cabling_data.csm);
210 // assert(false);
211 // continue; // Go to next link instead of crashing (here or later) E.P.
212
213 // In case of failure this produce an infinite loop because
214 // you do not decode the next word before doing "continue".
215 // I commented it out.
216
217 // The previous implementation was ok, the bad BOL was simply
218 // skipped. This means that you skip decoding this chamber.
219
220 // I'm not sure how you can recover this error. I think you
221 // simple have to store the error condition in the
222 // StatusCode word returned to the client.
223 // } else if (!isValid) {
224 // ATH_MSG_DEBUG("Offline identifier returned by MdtIdHelper is not valid");
225 // ATH_MSG_DEBUG("Skip decoding of CSM link, subdetId : "
226 // << MSG::hex << std::showbase << subdetId << " "
227 // << "mrodId : " << mrodId << " " << MSG::dec
228 // << "csmId : " << csmId);
229
230 } else {
231 // EJWM Removed: if ( moduleId == csmOfflineId)
232 // Can't see how to keep that in here now, and also not really sure what the point of it is
233 // Might be wrong though - job for experts to look into.
234 // FIXME
235
236 const bool isHpTdc = m_idHelperSvc->hasHPTDC(moduleId);
237
238 // Create MdtCsm and try to get it from the cache via the IDC_WriteHandle
239 std::unique_ptr<MdtCsm> collection{nullptr};
241 if (lock.alreadyPresent()) {
242 ATH_MSG_DEBUG("collections already found, do not convert");
243 ++m_nCache;
244 } else {
245 ATH_MSG_DEBUG(" Collection ID = " << m_idHelperSvc->toString(moduleId) << " does not exist, create it ");
246 collection = std::make_unique<MdtCsm>(moduleId, idHash);
247 ++m_nNotCache;
248 }
249
250 // Set values (keep Identifier and IdentifierHash the same though)
251 if (collection)
252 collection->set_values(collection->identify(), collection->identifyHash(), cabling_data.subdetectorId, cabling_data.mrod,
253 cabling_data.csm);
254
255 wordPos += 1;
256 if (wordPos >= size) {
257 WARNING_WITH_LINE("failure: data corrupted");
258 return StatusCode::FAILURE;
259 }
260 csmReadOut.decodeWord(vint[wordPos]);
261 if (!csmReadOut.is_TLP()) { ATH_MSG_DEBUG("failure: TDC Link Present not found "); }
262
263 // Loop on the TDCs blocks, if present
264 wordPos += 1;
265 if (wordPos >= size) {
266 WARNING_WITH_LINE("failure: data corrupted");
267 return StatusCode::FAILURE;
268 }
269 isHpTdc ? hptdcReadOut.decodeWord(vint[wordPos]) : amtReadOut.decodeWord(vint[wordPos]);
270 csmReadOut.decodeWord(vint[wordPos]);
271 while (!csmReadOut.is_TWC()) {
272 uint16_t tdcNum = isHpTdc ? hptdcReadOut.tdcId() : amtReadOut.tdcId();
273
274 ATH_MSG_DEBUG(" Decoding data from TDC number : " << tdcNum);
275
276 // increase word count by one
277 wordPos += 1;
278 if (wordPos >= size) {
279 WARNING_WITH_LINE("failure: data corrupted");
280 return StatusCode::FAILURE;
281 }
282
283 isHpTdc ? hptdcReadOut.decodeWord(vint[wordPos]) : amtReadOut.decodeWord(vint[wordPos]);
284
285 std::unique_ptr<MdtAmtHit> amtHit{nullptr};
286 // Loop on the TDC data words and create the corresponding
287 // RDO's
288 while (!((isHpTdc ? hptdcReadOut.is_EOT() : amtReadOut.is_EOT()) ||
289 (isHpTdc ? hptdcReadOut.is_BOT() : amtReadOut.is_BOT()) ||
290 (isHpTdc ? csmReadOut.is_TWC() : amtReadOut.is_TWC()))) {
291 isHpTdc ? hptdcReadOut.decodeWord(vint[wordPos]) : amtReadOut.decodeWord(vint[wordPos]);
292 int tdcCounts;
293 uint16_t chanNum;
294 // decode the tdc channel number
295
296 // Check whether this channel has already been
297 // created for this CSM
298
299 if ((isHpTdc ? hptdcReadOut.is_TSM() : amtReadOut.is_TSM()) &&
300 (isHpTdc ? hptdcReadOut.isLeading() : amtReadOut.isLeading()) && collection) {
301 chanNum = isHpTdc ? hptdcReadOut.channel() : amtReadOut.channel();
302
303 amtHit = std::make_unique<MdtAmtHit>(tdcNum, chanNum);
304 amtHit->setValues((isHpTdc ? hptdcReadOut.coarse() : amtReadOut.coarse()),
305 (isHpTdc ? hptdcReadOut.fine() : amtReadOut.fine()), 0);
306 amtHit->addData(vint[wordPos]);
307 leadingHitMap.insert(std::make_pair(chanNum, std::move(amtHit)));
308 } else if ((isHpTdc ? hptdcReadOut.is_TSM() : amtReadOut.is_TSM()) &&
309 !(isHpTdc ? hptdcReadOut.isLeading() : amtReadOut.isLeading()) && collection) {
310 chanNum = isHpTdc ? hptdcReadOut.channel() : amtReadOut.channel();
311 leading_amt_map::iterator chanPosition = leadingHitMap.find(chanNum);
312
313 if (chanPosition != leadingHitMap.end()) {
314 // get the amt hit corresponding to the first data word
315 amtHit = std::move(chanPosition->second);
316 uint16_t coarse = amtHit->coarse();
317 uint16_t fine = amtHit->fine();
318 int tdcCountsFirst = coarse * 32 + fine;
319
320 // get the tdc counts of the current data word
321 tdcCounts =
322 isHpTdc ? hptdcReadOut.coarse() * 32 + hptdcReadOut.fine() : amtReadOut.coarse() * 32 + amtReadOut.fine();
323 int width = tdcCounts - tdcCountsFirst;
324
325 amtHit->setValues(coarse, fine, width);
326 amtHit->addData(vint[wordPos]);
327 collection->push_back(std::move(amtHit));
328
329 // delete the channel from the map
330 leadingHitMap.erase(chanPosition);
331 } else {
332 ATH_MSG_DEBUG("failure: corresponding leading edge not found for the trailing edge tdc: " << tdcNum << " chan: "
333 << chanNum);
334 }
335
336 } else if ((isHpTdc ? hptdcReadOut.is_TCM() : amtReadOut.is_TCM()) && collection) {
337 uint16_t chanNum = isHpTdc ? hptdcReadOut.channel() : amtReadOut.channel();
338
339 amtHit = std::make_unique<MdtAmtHit>(tdcNum, chanNum);
340 amtHit->setValues((isHpTdc ? hptdcReadOut.coarse() : amtReadOut.coarse()),
341 (isHpTdc ? hptdcReadOut.fine() : amtReadOut.fine()),
342 (isHpTdc ? hptdcReadOut.width() : amtReadOut.width()));
343 amtHit->addData(vint[wordPos]);
344 collection->push_back(std::move(amtHit));
345 }
346
347 // increase word count by one
348 wordPos += 1;
349 if (wordPos >= size) {
350 WARNING_WITH_LINE("failure: data corrupted");
351 return StatusCode::FAILURE;
352 }
353
354 isHpTdc ? hptdcReadOut.decodeWord(vint[wordPos]) : amtReadOut.decodeWord(vint[wordPos]);
355
356 if (isHpTdc) csmReadOut.decodeWord(vint[wordPos]);
357
358 } // End of loop on AMTs
359
360 if (collection) {
361 for (auto& itHit : leadingHitMap) { collection->push_back(std::move(itHit.second)); }
362 }
363 leadingHitMap.clear();
364
365 // increase the decoding position only if it's end of TDC
366 // i.e. not operating in TDC trailer suppression mode
367 if ((isHpTdc ? hptdcReadOut.is_EOT() : amtReadOut.is_EOT())) {
368 wordPos += 1;
369 if (wordPos >= size) {
370 WARNING_WITH_LINE("failure: data corrupted");
371 return StatusCode::FAILURE;
372 }
373 }
374 csmReadOut.decodeWord(vint[wordPos]);
375 isHpTdc ? hptdcReadOut.decodeWord(vint[wordPos]) : amtReadOut.decodeWord(vint[wordPos]);
376 } // End of loop on TDCs
377 if (collection) ATH_CHECK(lock.addOrDelete(std::move(collection)));
378 // Collection has been found, go out
379 // return;
380 } // Check for the chamber offline id = collection offline id
381 wordPos += 1;
382 if (wordPos >= size) {
383 WARNING_WITH_LINE("Data corrupted");
384 return StatusCode::FAILURE;
385 }
386 csmReadOut.decodeWord(vint[wordPos]);
387 }
388 return StatusCode::SUCCESS;
389}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static const InterfaceID IID_IMdtROD_Decoder("MdtROD_Decoder", 1, 0)
#define WARNING_WITH_LINE(msg)
const double width
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
MsgStream & msg() const
StatusCode addOrDelete(std::unique_ptr< T > ptr)
IDC_WriteHandle getWriteHandle(IdentifierHash hash)
This is a "hash" representation of an Identifier.
uint16_t coarse()
uint16_t tdcId()
uint16_t channel()
uint16_t width()
void decodeWord(uint32_t dataWord)
uint16_t fine()
This container provides acces to the MDT RDOs.
bool is_TWC() const
bool is_BOB() const
bool is_EOB() const
uint16_t csmId() const
bool is_TLP() const
void decodeWord(uint32_t dataWord)
bool is_BOL() const
uint32_t lvl1Id() const
uint16_t coarse() const
bool isLeading() const
uint16_t width() const
bool is_TCM() const
uint16_t tdcId() const
bool is_TSM() const
bool is_BOT() const
uint16_t fine() const
uint16_t channel() const
void decodeWord(uint32_t dataWord)
bool is_EOT() const
std::unique_ptr< MDT_Hid2RESrcID > m_hid2re
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
int m_specialROBNumber
TMP special ROB number for sector13 runs.
MdtROD_Decoder(const std::string &type, const std::string &name, const IInterface *parent)
constructor
virtual StatusCode finalize() override
StatusCode fillCollections(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment &robFrag, MdtCsmContainer &rdoIDC) const
virtual StatusCode initialize() override
static const InterfaceID & interfaceID()
AlgTool InterfaceID.
SG::ReadCondHandleKey< MuonMDT_CablingMap > m_readKey
std::map< uint16_t, std::unique_ptr< MdtAmtHit > > leading_amt_map
MdtCablingData CablingData
bool getOfflineId(CablingData &cabling_data, MsgStream &log) const
return the offline id given the online id
bool getMultiLayerCode(const CablingData &map_data, Identifier &multiLayer, IdentifierHash &mdtHashId, MsgStream &log) const
Transforms the identifier to an IdentifierHash corresponding to the multilayer In this case,...
const DataType * PointerType
Definition RawEvent.h:25
eformat::ROBFragment< PointerType > ROBFragment
Definition RawEvent.h:27