ATLAS Offline Software
Loading...
Searching...
No Matches
AFP_ByteStream2RawCnv.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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::vector<std::vector<uint16_t>> picoTDC1_channels, picoTDC2_channels;
124 std::vector<bool> picoTDC_hasTrigger;
125 std::vector<int> ToF_links;
126
127 const uint32_t size = robFrag->rod_ndata();
128 for (unsigned i = 0; i < size; i++) {
129 uint32_t the_word=vint[i];
130 uint32_t the_link=m_wordReadout->link(the_word);
131
132 if (m_wordReadout->isHeader(the_word)) {
133 AFP_RawCollectionHead* collectionHead = nullptr;
134 if ( isLinkToF (the_link) ) {
135 // prepare collection for time-of-flight
136 collectionToF = getCollectionToF(//m_wordReadout->link(), robFrag->rob_source_id(),
137 rawContainer);
138 collectionHead = collectionToF;
139
140
141 picoTDC1_channels.emplace_back();
142 picoTDC2_channels.emplace_back();
143 picoTDC_hasTrigger.push_back(false);
144 ToF_links.push_back(the_link);
145 }
146 else if ( isLinkSi (the_link) ) {
147 // prepare collection for silicon detector
148 collectionSi = getCollectionSi(//m_wordReadout->link(), robFrag->rob_source_id(),
149 rawContainer);
150 collectionHead = collectionSi;
151 }
152 else {
153 ATH_MSG_ERROR("Unidentified value of link="<<the_link<<" for header record.");
154 return StatusCode::FAILURE;
155 }
156
157 if (!collectionHead) {
158 ATH_MSG_WARNING("nullptr returned by getCollection(link = "
159 << the_link << ", robID = " << robFrag->rob_source_id() <<")");
160 return StatusCode::SUCCESS;
161 }
162
163 // set head collection informaiton
164 collectionHead->setLvl1Id(m_wordReadout->getBits(the_word, 14, 10));
165 collectionHead->setLink(the_link);
166 collectionHead->setFrontendFlag(m_wordReadout->getBits(the_word, 15, 15));
167 collectionHead->setBcId(m_wordReadout->getBits(the_word, 9, 0));
168 collectionHead->setRobId(robFrag->rob_source_id());
169 }
170 else if (m_wordReadout->isData(the_word)) {
171 // fill time-of-flight collection
172 if ( isLinkToF (the_link) ) {
173
174 // check if collection is available
175 if ( !collectionToF ) {
176 ATH_MSG_WARNING("No ToF collection available to fill data.");
177 return StatusCode::SUCCESS;
178 }
179
180 uint32_t bit23=m_wordReadout->getBits(the_word, 23, 23);
181 if(!bit23)
182 {
183 // HPTDC 2017
184 uint32_t bits22_21=m_wordReadout->getBits(the_word, 22, 21);
185 if(bits22_21==2)
186 {
187 // ToF measurement
188 AFP_ToFRawData& ToFData = collectionToF->newDataRecord();
189 ToFData.setHeader( m_wordReadout->getBits(the_word, 23, 21) );
190 ToFData.setEdge( m_wordReadout->getBits(the_word, 20, 20) );
191 ToFData.setChannel( m_wordReadout->getBits(the_word, 19, 16) );
192 ToFData.setPulseLength( m_wordReadout->getBits(the_word, 15, 10) );
193 ToFData.setTime( m_wordReadout->getBits(the_word, 9, 0) );
194
195 setDataHeader (the_word, &ToFData);
196 }
197 else
198 {
199 ATH_MSG_DEBUG("This is not a ToF measurement, bit23 = "<<bit23<<", bits22_21 "<<bits22_21<<", ignoring word = "<<the_word);
200 }
201 }
202 else
203 {
204 // picoTDC
205
206 uint32_t bits19_22=m_wordReadout->getBits(the_word, 22, 19);
207
208 if(bits19_22==0 || bits19_22==1)
209 {
210 // picoTDC #1 (==0) or picoTDC #2 (==1)
211 uint16_t channel=m_wordReadout->getBits(the_word, 18, 13);
212
213 // find entry with the same channel number
214 auto ToFData_itr=std::find_if( collectionToF->begin(), collectionToF->end(),
215 [&](const AFP_ToFRawData& entry){return entry.channel()==channel;});
216
217 if(ToFData_itr==collectionToF->end())
218 {
219 // create a new entry if such channel number doesn't exist
220 auto& ToFData = collectionToF->newDataRecord();
221
222 ToFData.setHeader( bit23 );
223 ToFData.setEdge( 0 );
224 ToFData.setChannel( m_wordReadout->getBits(the_word, 18, 13) );
225 ToFData.setPulseLength( 0 );
226 ToFData.setTime( 0 );
227 setDataHeader (the_word, &ToFData);
228
229 ToFData_itr = std::prev(collectionToF->end());
230 }
231
232 if(!bits19_22)
233 {
234 // picoTDC #1
235 if(ToFData_itr->time() !=0 )
236 {
237 ATH_MSG_WARNING("trying to set time to "<<m_wordReadout->getBits(the_word, 12, 0)<<", but it is already set to = "<<ToFData_itr->time()<<", will not overwrite");
238 }
239 else
240 {
241 ToFData_itr->setTime( m_wordReadout->getBits(the_word, 12, 0) );
242 picoTDC1_channels.back().push_back(channel);
243 }
244 }
245 else
246 {
247 // picoTDC #2
248 if(ToFData_itr->pulseLength() !=0 )
249 {
250 ATH_MSG_WARNING("trying to set pulseLength to "<<m_wordReadout->getBits(the_word, 12, 0)<<", but it is already set to = "<<ToFData_itr->pulseLength()<<", will not overwrite");
251 }
252 else
253 {
254 ToFData_itr->setPulseLength( m_wordReadout->getBits(the_word, 12, 0) );
255 picoTDC2_channels.back().push_back(channel);
256 }
257 }
258 }
259 else if(bits19_22==4)
260 {
261 // check if there's already some other trigger word
262 auto ToFData_itr=std::find_if( collectionToF->begin(), collectionToF->end(),
263 [&](const AFP_ToFRawData& e){return e.isTrigger();});
264 if(ToFData_itr!=collectionToF->end())
265 {
266 // there shouldn't be any other trigger word
267 ATH_MSG_WARNING("already found a trigger word with delayedTrigger = "<<ToFData_itr->delayedTrigger()<<" and triggerPattern = "<<ToFData_itr->triggerPattern()<<", will ignore new word with delayedTrigger = "<<m_wordReadout->getBits(the_word, 18,16)<<" and triggerPattern = "<<m_wordReadout->getBits(the_word, 15, 0));
268 }
269 else
270 {
271 // if there isn't any other trigger word, create a new entry
272 auto& ToFData = collectionToF->newDataRecord();
273
274 ToFData.setHeader( bit23 );
275 ToFData.setEdge( 0 );
276 ToFData.setTrigger(); // mark this entry as a trigger entry; must be done before setting delayedTrigger or triggerPattern
277 ToFData.setDelayedTrigger( m_wordReadout->getBits(the_word, 18,16) );
278 ToFData.setTriggerPattern( m_wordReadout->getBits(the_word, 15, 0) );
279 picoTDC_hasTrigger.back()=true;
280 }
281 }
282 else
283 {
284 ATH_MSG_WARNING("unknown pattern in bits 19-22 = "<<bits19_22<<", ignoring word = "<<the_word);
285 }
286 }
287 }
288 else if ( isLinkSi (the_link) ) {
289 // fill silicon detector collection
290
291 // check if collection is available
292 if ( !collectionSi ) {
293 ATH_MSG_WARNING("No silicon detector collection available to fill data.");
294 return StatusCode::SUCCESS;
295 }
296
297 // check first silicon hit information
298 if (m_wordReadout->getBits(the_word, 7, 4) != s_siNoHitMarker) {
299 AFP_SiRawData& siData = collectionSi->newDataRecord();
300 siData.setColumn (m_wordReadout->getBits(the_word, 23, 17));
301 siData.setRow (m_wordReadout->getBits(the_word, 16, 8));
302 siData.setTimeOverThreshold (m_wordReadout->getBits(the_word, 7, 4));
303
304 setDataHeader (the_word, &siData);
305 }
306
307 // check second silicon hit information
308 if (m_wordReadout->getBits(the_word, 3, 0) != s_siNoHitMarker) {
309 AFP_SiRawData& siData = collectionSi->newDataRecord();
310 siData.setColumn (m_wordReadout->getBits(the_word, 23, 17));
311 siData.setRow (m_wordReadout->getBits(the_word, 16, 8) + 1);
312 siData.setTimeOverThreshold (m_wordReadout->getBits(the_word, 3, 0));
313
314 setDataHeader (the_word, &siData);
315 }
316 }
317 else {
318 ATH_MSG_ERROR("Not recognised value of link="<<the_link<<" for data record.");
319 return StatusCode::FAILURE;
320 }
321
322 } // end is data
323 } // end of loop
324
325 // in case of picoTDC, check we always have both words
326 for(unsigned int i=0;i<picoTDC1_channels.size();++i)
327 {
328 if(!picoTDC1_channels.at(i).empty() || !picoTDC2_channels.at(i).empty())
329 {
330 for(auto ch1 : picoTDC1_channels.at(i))
331 {
332 if(std::find(picoTDC2_channels.at(i).begin(),picoTDC2_channels.at(i).end(),ch1) == picoTDC2_channels.at(i).end())
333 {
334 ATH_MSG_WARNING("Cannot find channel "<<ch1<<" from picoTDC #1 in picoTDC #2 in ToF collections with link nr. "<<ToF_links.at(i)<<", pulseLength is very probably not set");
335 }
336 }
337 for(auto ch2 : picoTDC2_channels.at(i))
338 {
339 if(std::find(picoTDC1_channels.at(i).begin(),picoTDC1_channels.at(i).end(),ch2) == picoTDC1_channels.at(i).end())
340 {
341 ATH_MSG_WARNING("Cannot find channel "<<ch2<<" from picoTDC #2 in picoTDC #1 in ToF collections with link nr. "<<ToF_links.at(i)<<", time is very probably not set");
342 }
343 }
344
345 if(!picoTDC_hasTrigger.at(i))
346 {
347 ATH_MSG_WARNING("Cannot find trigger word in ToF collections with link nr. "<<ToF_links.at(i));
348 }
349 }
350 }
351
352 return StatusCode::SUCCESS;
353}
354
356AFP_ByteStream2RawCnv::getCollectionSi(//const unsigned int link, const unsigned int robId,
358
359 if (!container) {
360 ATH_MSG_WARNING("NULL pointer passed in argument: container. NULL pointer returned.");
361 return nullptr;
362 }
363
364 // Code below is commented, because it was impossible to
365 // reconstruct several bunch crossings in one event with it. In
366 // standard data taking only one bunch crossing is saved and this
367 // protection should not be necessary. However in case of big
368 // readout problems the code may be needed, that is why it stays
369 // commented here.
370
371 // for (const AFP_SiRawCollection& collection : container->collectionsSi())
372 // if (collection.link() == link && collection.robId() == robId)
373 // 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?)");
374
375 AFP_SiRawCollection& newCollection = container->newCollectionSi();
376 return &newCollection;
377}
378
380AFP_ByteStream2RawCnv::getCollectionToF(// const unsigned int link, const unsigned int robId,
382
383 if (!container) {
384 ATH_MSG_WARNING("NULL pointer passed in argument: container. NULL pointer returned.");
385 return nullptr;
386 }
387
388 // Code below is commented, because it was impossible to
389 // reconstruct several bunch crossings in one event with it. In
390 // standard data taking only one bunch crossing is saved and this
391 // protection should not be necessary. However in case of big
392 // readout problems the code may be needed, that is why it stays
393 // commented here.
394
395 // for (const AFP_ToFRawCollection& collection : container->collectionsToF())
396 // if (collection.link() == link && collection.robId() == robId)
397 // 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?)");
398
399 AFP_ToFRawCollection& newCollection = container->newCollectionToF();
400 return &newCollection;
401}
402
403void AFP_ByteStream2RawCnv::setDataHeader (uint32_t the_word, AFP_RawDataCommonHead* dataHead) const
404{
405 dataHead->setLink (m_wordReadout->link(the_word));
406 dataHead->setHitDiscConfig (m_wordReadout->getBits(the_word, 29, 28));
407}
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)
std::list< RAWDATA_T >::iterator begin()
Returns iterators to the beginning and end of the list.
RAWDATA_T & newDataRecord()
Creates a new empty data record in the collection and returns reference to it.
std::list< RAWDATA_T >::iterator end()
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