ATLAS Offline Software
Loading...
Searching...
No Matches
AFP_ByteStream2RawCnv.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// AFP_ByteStream2RawCnv includes
7
10
13
14#include <vector>
15#include <algorithm> //std::find_if
16#include <iterator> //std::prev
17
19 static const InterfaceID IID_IAFP_ByteStream2RawCnv("AFP_ByteStream2RawCnv", 1, 0);
20 return IID_IAFP_ByteStream2RawCnv;
21}
22
24 const std::string &name,
25 const IInterface *parent)
26 : AthAlgTool(type, name, parent),
27 m_robDataProvider("ROBDataProviderSvc", name)
28{
29 declareInterface<AFP_ByteStream2RawCnv>(this);
30}
31
33
35 ATH_MSG_INFO("Initializing " << name() << "...");
36
37 StatusCode sc = AthAlgTool::initialize();
38 ATH_MSG_DEBUG("AFP_ByteStream2RawCnv::initialize");
39 if (sc.isFailure()) {
40 ATH_MSG_WARNING("Failed to initialize");
41 return StatusCode::SUCCESS;
42 }
43
44 if (m_robDataProvider.retrieve().isFailure()) {
45 ATH_MSG_WARNING("Failed to retrieve service " << m_robDataProvider
46 << "...");
47 return StatusCode::SUCCESS;
48 } else {
49 ATH_MSG_DEBUG("Retrieved service " << m_robDataProvider << "...");
50 }
51
52 if (m_wordReadout.retrieve().isFailure()) {
53 ATH_MSG_WARNING("Failed to retrieve service " << m_wordReadout
54 << "...");
55 return StatusCode::SUCCESS;
56 } else {
57 ATH_MSG_DEBUG("Retrieved service " << m_wordReadout << "...");
58 }
59
60 return StatusCode::SUCCESS;
61}
62
64 ATH_MSG_DEBUG("AFP_ByteStream2RawCnv: finalizing ");
65
66 return StatusCode::SUCCESS;
67}
68
70 ATH_MSG_DEBUG("AFP_ByteStream2RawCnv::fillColelction rob_source_id: in decimal="<<std::dec<<robFrag->rob_source_id()<<", in hex=0x"<<std::hex<<robFrag->rob_source_id()<<std::dec);
71
72 try {
73 robFrag->check();
74 } catch (...) {
75 ATH_MSG_WARNING("An exception occurred");
76 return StatusCode::SUCCESS;
77 }
78
79 const uint32_t nStat = robFrag->nstatus();
80 if (nStat) {
81 const uint32_t *it;
82 robFrag->status(it);
83 if (*it) {
84 ATH_MSG_WARNING(" Error in ROB status word: 0x");
85 return StatusCode::SUCCESS;
86 }
87 }
88
89 if (!rawContainer) {
90 ATH_MSG_WARNING("NULL pointer passed in rawContainer argument.");
91 return StatusCode::SUCCESS;
92 }
93
94 // --- end of check input parameters ---
95
97 robFrag->rod_data(vint);
98
99 if (robFrag->rod_nstatus() <= 0) {
100 ATH_MSG_WARNING("Buffer size <= 0!");
101 return StatusCode::SUCCESS;
102 }
103
104 const eformat::FullEventFragment<const uint32_t*> *event = m_robDataProvider->getEvent(Gaudi::Hive::currentContext());
105
106 // this information will be present only in offline reconstruction
107 // not be at HLT; however the remaining AFP information will be
108 // present both online and offline
109 if (event) {
110 // set information about event in the RawContainer
111 rawContainer->setTimeStamp(event->bc_time_seconds());
112 rawContainer->setTimeStampNS(event->bc_time_nanoseconds());
113 rawContainer->setBCId(event->bc_id());
114 rawContainer->setLumiBlock(event->lumi_block());
115 rawContainer->setLvl1Id(event->lvl1_id());
116 }
117
118
119 // fill container with collections
120 AFP_SiRawCollection *collectionSi = nullptr;
121 AFP_ToFRawCollection *collectionToF = nullptr;
122
123 std::array<uint32_t, 16> picoTDC_data = {};
124
125 const uint32_t size = robFrag->rod_ndata();
126 for (unsigned i = 0; i < size; i++) {
127 uint32_t the_word=vint[i];
128 uint32_t the_link=m_wordReadout->link(the_word);
129
130 if (m_wordReadout->isHeader(the_word)) {
131 AFP_RawCollectionHead* collectionHead = nullptr;
132 if ( isLinkToF (the_link) ) {
133 // prepare collection for time-of-flight
134 collectionToF = getCollectionToF(//m_wordReadout->link(), robFrag->rob_source_id(),
135 rawContainer);
136 collectionHead = collectionToF;
137 }
138 else if ( isLinkSi (the_link) ) {
139 // prepare collection for silicon detector
140 collectionSi = getCollectionSi(//m_wordReadout->link(), robFrag->rob_source_id(),
141 rawContainer);
142 collectionHead = collectionSi;
143 }
144 else {
145 ATH_MSG_ERROR("Unidentified value of link="<<the_link<<" for header record.");
146 return StatusCode::FAILURE;
147 }
148
149 if (!collectionHead) {
150 ATH_MSG_WARNING("nullptr returned by getCollection(link = "
151 << the_link << ", robID = " << robFrag->rob_source_id() <<")");
152 return StatusCode::SUCCESS;
153 }
154
155 // set head collection informaiton
156 collectionHead->setLvl1Id(m_wordReadout->getBits(the_word, 14, 10));
157 collectionHead->setLink(the_link);
158 collectionHead->setFrontendFlag(m_wordReadout->getBits(the_word, 15, 15));
159 collectionHead->setBcId(m_wordReadout->getBits(the_word, 9, 0));
160 collectionHead->setRobId(robFrag->rob_source_id());
161 }
162 else if (m_wordReadout->isData(the_word)) {
163 // fill time-of-flight collection
164 if ( isLinkToF (the_link) ) {
165
166 // check if collection is available
167 if ( !collectionToF ) {
168 ATH_MSG_WARNING("No ToF collection available to fill data.");
169 return StatusCode::SUCCESS;
170 }
171
172 uint32_t bit23=m_wordReadout->getBits(the_word, 23, 23);
173 if(!bit23)
174 {
175 // HPTDC 2017
176 uint32_t bits22_21=m_wordReadout->getBits(the_word, 22, 21);
177 if(bits22_21==2)
178 {
179 // ToF measurement
180 AFP_ToFRawData& ToFData = collectionToF->newDataRecord();
181 ToFData.setHeader( m_wordReadout->getBits(the_word, 23, 21) );
182 ToFData.setEdge( m_wordReadout->getBits(the_word, 20, 20) );
183 ToFData.setChannel( m_wordReadout->getBits(the_word, 19, 16) );
184 ToFData.setPulseLength( m_wordReadout->getBits(the_word, 15, 10) );
185 ToFData.setTime( m_wordReadout->getBits(the_word, 9, 0) << 3 );
186
187 setDataHeader (the_word, &ToFData);
188 }
189 else
190 {
191 ATH_MSG_DEBUG("This is not a ToF measurement, bit23 = "<<bit23<<", bits22_21 "<<bits22_21<<", ignoring word = "<<the_word);
192 }
193 }
194 else
195 {
196 uint32_t bits23_22=m_wordReadout->getBits(the_word, 23, 22);
197 if (bits23_22==0b10) {
198 // picoTDC
199
200 uint32_t bits21_20=m_wordReadout->getBits(the_word, 21, 20);
201 if (bits21_20==0b10) {
202 // ToF measurement
203 uint32_t channel=m_wordReadout->getBits(the_word, 17, 14);
204 uint32_t bit18=m_wordReadout->getBits(the_word, 18, 18);
205 if (bit18==0) {
206 // Fine
207 if (picoTDC_data[channel] == 0) {
208 picoTDC_data[channel] = the_word;
209 } else {
210 if (m_wordReadout->getBits(picoTDC_data[channel], 18, 18) == 1) {
211 uint32_t fine_word = the_word;
212 uint32_t coarse_word = picoTDC_data[channel];
213
214 AFP_ToFRawData& ToFData = collectionToF->newDataRecord();
215 ToFData.setHeader( m_wordReadout->getBits(the_word, 23, 20) );
216 ToFData.setEdge( m_wordReadout->getBits(fine_word, 13, 13) );
217 ToFData.setChannel( channel );
218 ToFData.setPulseLength( m_wordReadout->getBits(coarse_word, 7, 0) );
219 ToFData.setTime( (m_wordReadout->getBits(coarse_word, 13, 8) << 13) | m_wordReadout->getBits(fine_word, 12, 0) );
220
221 setDataHeader (the_word, &ToFData);
222
223 picoTDC_data[channel] = 0;
224 } else {
225 ATH_MSG_WARNING("Fine time word for channel "<<channel<<" is already set to "<<picoTDC_data[channel]<<", cannot set it to "<<the_word<<", will not overwrite");
226 }
227 }
228 } else {
229 // Coarse time + pulse length
230 if (picoTDC_data[channel] == 0) {
231 picoTDC_data[channel] = the_word;
232 } else {
233 if (m_wordReadout->getBits(picoTDC_data[channel], 18, 18) == 0) {
234 uint32_t fine_word = picoTDC_data[channel];
235 uint32_t coarse_word = the_word;
236
237 AFP_ToFRawData& ToFData = collectionToF->newDataRecord();
238 ToFData.setHeader( m_wordReadout->getBits(the_word, 23, 20) );
239 ToFData.setEdge( m_wordReadout->getBits(fine_word, 13, 13) );
240 ToFData.setChannel( channel );
241 ToFData.setPulseLength( m_wordReadout->getBits(coarse_word, 7, 0) );
242 ToFData.setTime( (m_wordReadout->getBits(coarse_word, 13, 8) << 13) | m_wordReadout->getBits(fine_word, 12, 0) );
243
244 setDataHeader (the_word, &ToFData);
245
246 picoTDC_data[channel] = 0;
247 } else {
248 ATH_MSG_WARNING("Coarse time word for channel "<<channel<<" is already set to "<<picoTDC_data[channel]<<", cannot set it to "<<the_word<<", will not overwrite");
249 }
250 }
251 }
252 }
253 else {
254 ATH_MSG_DEBUG("This is not a ToF measurement, bits23_22 = "<<bits23_22<<", bits21_20 "<<bits21_20<<", ignoring word = "<<the_word);
255 }
256 }
257 else {
258 ATH_MSG_WARNING("Unexpected pattern in bits 22-23 = "<<bits23_22<<", ignoring word = "<<the_word);
259 }
260 }
261 }
262 else if ( isLinkSi (the_link) ) {
263 // fill silicon detector collection
264
265 // check if collection is available
266 if ( !collectionSi ) {
267 ATH_MSG_WARNING("No silicon detector collection available to fill data.");
268 return StatusCode::SUCCESS;
269 }
270
271 // check first silicon hit information
272 if (m_wordReadout->getBits(the_word, 7, 4) != s_siNoHitMarker) {
273 AFP_SiRawData& siData = collectionSi->newDataRecord();
274 siData.setColumn (m_wordReadout->getBits(the_word, 23, 17));
275 siData.setRow (m_wordReadout->getBits(the_word, 16, 8));
276 siData.setTimeOverThreshold (m_wordReadout->getBits(the_word, 7, 4));
277
278 setDataHeader (the_word, &siData);
279 }
280
281 // check second silicon hit information
282 if (m_wordReadout->getBits(the_word, 3, 0) != s_siNoHitMarker) {
283 AFP_SiRawData& siData = collectionSi->newDataRecord();
284 siData.setColumn (m_wordReadout->getBits(the_word, 23, 17));
285 siData.setRow (m_wordReadout->getBits(the_word, 16, 8) + 1);
286 siData.setTimeOverThreshold (m_wordReadout->getBits(the_word, 3, 0));
287
288 setDataHeader (the_word, &siData);
289 }
290 }
291 else {
292 ATH_MSG_ERROR("Not recognised value of link="<<the_link<<" for data record.");
293 return StatusCode::FAILURE;
294 }
295
296 } // end is data
297 } // end of loop
298
299 // in case of picoTDC, check we always have both words
300 for (std::size_t channel=0;channel<picoTDC_data.size();++channel) {
301 uint32_t word = picoTDC_data[channel];
302 if (word != 0) {
303 if (m_wordReadout->getBits(word, 18, 18) == 0) {
304 ATH_MSG_WARNING("Incomplete picoTDC data for channel "<<channel<<", fine word "<<word<<" could not be paired");
305 } else {
306 ATH_MSG_WARNING("Incomplete picoTDC data for channel "<<channel<<", coarse word "<<word<<" could not be paired");
307 }
308 }
309 }
310
311 return StatusCode::SUCCESS;
312}
313
315AFP_ByteStream2RawCnv::getCollectionSi(//const unsigned int link, const unsigned int robId,
317
318 if (!container) {
319 ATH_MSG_WARNING("NULL pointer passed in argument: container. NULL pointer returned.");
320 return nullptr;
321 }
322
323 // Code below is commented, because it was impossible to
324 // reconstruct several bunch crossings in one event with it. In
325 // standard data taking only one bunch crossing is saved and this
326 // protection should not be necessary. However in case of big
327 // readout problems the code may be needed, that is why it stays
328 // commented here.
329
330 // for (const AFP_SiRawCollection& collection : container->collectionsSi())
331 // if (collection.link() == link && collection.robId() == robId)
332 // ATH_MSG_WARNING("Silicon collection link="<<link<<" robId="<<robId<<" already in container, although it should not be there. Anyway creating new collection. (Reading several BCX?)");
333
334 AFP_SiRawCollection& newCollection = container->newCollectionSi();
335 return &newCollection;
336}
337
339AFP_ByteStream2RawCnv::getCollectionToF(// const unsigned int link, const unsigned int robId,
341
342 if (!container) {
343 ATH_MSG_WARNING("NULL pointer passed in argument: container. NULL pointer returned.");
344 return nullptr;
345 }
346
347 // Code below is commented, because it was impossible to
348 // reconstruct several bunch crossings in one event with it. In
349 // standard data taking only one bunch crossing is saved and this
350 // protection should not be necessary. However in case of big
351 // readout problems the code may be needed, that is why it stays
352 // commented here.
353
354 // for (const AFP_ToFRawCollection& collection : container->collectionsToF())
355 // if (collection.link() == link && collection.robId() == robId)
356 // ATH_MSG_WARNING("ToF collection link="<<link<<" robId="<<robId<<" already in container, although it should not be there. Anyway creating new collection (Reading several BCX?)");
357
358 AFP_ToFRawCollection& newCollection = container->newCollectionToF();
359 return &newCollection;
360}
361
362void AFP_ByteStream2RawCnv::setDataHeader (uint32_t the_word, AFP_RawDataCommonHead* dataHead) const
363{
364 dataHead->setLink (m_wordReadout->link(the_word));
365 dataHead->setHitDiscConfig (m_wordReadout->getBits(the_word, 29, 28));
366}
AFP_RawCollection< AFP_SiRawData > AFP_SiRawCollection
Class representing collection of silicon detector data.
AFP_RawCollection< AFP_ToFRawData > AFP_ToFRawCollection
AFP_ToFRawData_v2 AFP_ToFRawData
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t sc
AFP_ToFRawCollection * getCollectionToF(AFP_RawContainer *container) const
Adds new time-of-flight collection to AFP_RawContainer.
static const uint32_t s_siNoHitMarker
ServiceHandle< IROBDataProviderSvc > m_robDataProvider
ToolHandle< AFP_WordReadOut > m_wordReadout
void setDataHeader(uint32_t the_word, AFP_RawDataCommonHead *dataHead) const
Sets data header information for given argument based on m_wordReadout.
bool isLinkSi(const unsigned int link) const
returns true if provided link corresponds to silicon detector information
bool isLinkToF(const unsigned int link) const
returns true if provided link corresponds to time-of-flight information
virtual StatusCode finalize()
AFP_ByteStream2RawCnv(const std::string &type, const std::string &name, const IInterface *parent)
AFP_SiRawCollection * getCollectionSi(AFP_RawContainer *container) const
Adds new silicon collection to AFP_RawContainer.
virtual StatusCode initialize()
static const InterfaceID & interfaceID()
StatusCode fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment *robFrag, AFP_RawContainer *rawContainer) const
Fills rawContainer with collections from ROBFragment.
virtual ~AFP_ByteStream2RawCnv()
Does nothing.
Class represnting header record in bytestream.
void setLvl1Id(const uint16_t lvl1Id)
void setBcId(const uint16_t bcId)
void setLink(const uint16_t link)
void setFrontendFlag(const uint32_t flag)
void setRobId(const uint32_t robId)
RAWDATA_T & newDataRecord()
Creates a new empty data record in the collection and returns reference to it.
void setLvl1Id(const uint32_t lvl1ID)
void setTimeStamp(const uint32_t timeStamp)
void setTimeStampNS(const uint32_t timeStampNS)
void setBCId(const uint32_t bcId)
void setLumiBlock(const uint32_t lumiBlock)
Base class representing first 8 bits in a record in bytestream.
void setLink(const uint16_t outlink)
void setHitDiscConfig(const uint16_t hitDiscConfig)
Class representing data record for silicon detectors.
void setTimeOverThreshold(const uint16_t timeOverThreshold)
void setColumn(const uint16_t column)
void setRow(const uint32_t row)
void setChannel(const uint16_t channel)
void setHeader(const uint16_t header)
void setEdge(const uint16_t edge)
void setPulseLength(const uint32_t pulseLength)
void setTime(const uint32_t time)
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
const DataType * PointerType
Definition RawEvent.h:25
eformat::ROBFragment< PointerType > ROBFragment
Definition RawEvent.h:27