ATLAS Offline Software
Loading...
Searching...
No Matches
LArRodBlockPhysicsV5.cxx
Go to the documentation of this file.
1//Dear emacs, this is -*- c++ -*-
2
3/*
4 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5*/
6
7// Implementation of a LArRODBlockStructure class
8// This version contains LArDigits in fixed gain.
9// See .h file for more details.
10
11#include "GaudiKernel/MsgStream.h"
13//#include <cstdio>
17#include "GaudiKernel/Bootstrap.h"
18#include "GaudiKernel/ISvcLocator.h"
19#include <iostream>
20
21//#define LARBSDBGOUTPUT
22#ifdef LARBSDBGOUTPUT
23#define MYLEVEL (MSG::FATAL)
24#define LARBSDBG(text) logstr<<MYLEVEL<<text<<endmsg
25#else
26#define LARBSDBG(text)
27#endif
28
29//int mycheck_tot=0;
30//int mycheck_err=0;
31
32namespace {
33union ShortLong {
34 uint16_t s[2];
35 uint32_t l;
36};
37}
38
41 m_onlineHelper(nullptr)
42{
43 m_iHeadBlockSize=endtag/2; // The implicit cast rounds down to the right size
49 m_OffTimeCut=0; //FIXME: Nowhere set to a sensible value ???
51 // retrieve onlineHelper
52 SmartIF<StoreGateSvc> detStore{Gaudi::svcLocator()->service("DetectorStore")};
53 if (!detStore) {
54 std::cout << "Unable to locate DetectorStore" << std::endl;
55 std::abort();
56 }
57 StatusCode sc = detStore->retrieve(m_onlineHelper, "LArOnlineID");
58 if (sc.isFailure()) {
59 std::cout << "Could not get LArOnlineID helper !" << std::endl;
60 std::abort();
61 }
62}
63
64
84
86{
88 {
89 int off = -8;
90 int ns = getHeader16(NSamples) & 0xff;
91 if (m_requiredNSamples > 0 && m_requiredNSamples != ns) return false;
92 int radd = (ns+1)/2;
93 int dim1 = getHeader16(ResultsDim1);
94 int off1 = getHeader16(ResultsOff1);
95 int off2 = getHeader16(ResultsOff2);
96 int dim2 = getHeader16(ResultsDim2);
97 int off3 = getHeader16(RawDataBlkOff);
98 int dim3 = getHeader16(RawDataBlkDim);
99
100 if (off1 && dim1+off1+off<m_FebBlockSize) {
101 off1 += off;
102 if (dim1>=8)
103 m_GainPointer=reinterpret_cast<const uint32_t*>(m_FebBlock+off1);
104 if (dim1>=12)
105 m_MaskTimeQualityPointer=reinterpret_cast<const uint32_t*>(m_FebBlock+off1+8);
106 if (dim1>=16)
107 m_MaskDigitsPointer=reinterpret_cast<const uint32_t*>(m_FebBlock+off1+12);
108 if (dim1>=16+radd)
109 m_RaddPointer=reinterpret_cast<const uint16_t*>(m_FebBlock+off1+16);
110 if (dim1>=80+radd)
111 m_EnergyPointer=reinterpret_cast<const uint16_t*> (m_FebBlock+off1+16+radd);
112 if (dim1>=83+radd)
113 m_SumPointer=reinterpret_cast<const int32_t*>(m_FebBlock+off1+80+radd);
114 if (dim1>83+radd)
115 m_TimeQualityPointer=reinterpret_cast<const uint16_t*>(m_FebBlock+off1+83+radd);
116 off1 -= off;
117 }
118 if (off2 && dim2+off2+off<m_FebBlockSize) {
119 m_DigitsPointer=reinterpret_cast<const uint16_t*>(m_FebBlock+off2+off);
120 }
121 if (off3 && dim3+off3+off<m_FebBlockSize) {
122 m_RawDataPointer=reinterpret_cast<const uint16_t*>(m_FebBlock+off3+off);
123 }
124
125 // Check for offsets problems
126 uint32_t problem = 0;
127 int n1, n2;
128 int n1_tmp, n2_tmp;
129 int off1_tmp, dim1_tmp;
130 int off2_tmp, dim2_tmp;
131 int off3_tmp, dim3_tmp;
132 if(off1==0) {
133 n1 = n2 = 0;
134 n1_tmp = n2_tmp =0;
135 off1_tmp = dim1_tmp = 0;
136 off2_tmp = dim2_tmp = 0;
137 off3_tmp = dim3_tmp = 0;
138 }
139 else {
140 m_RaddPointer=reinterpret_cast<const uint16_t*>(m_FebBlock+26);
141 m_MaskTimeQualityPointer=reinterpret_cast<const uint32_t*>(m_FebBlock+18);
142 m_MaskDigitsPointer=reinterpret_cast<const uint32_t*>(m_FebBlock+22);
143 n1 = getNbSweetCells1();
144 n2 = getNbSweetCells2();
145 n1_tmp = getNbSweetCells1FromMask();
146 n2_tmp = getNbSweetCells2FromMask();
147 off1_tmp = 10-off;
148 dim1_tmp = 83+(ns+1)/2+n1;
149 if ( m_requiredNSamples > 0 )
150 dim1_tmp = 83 +(m_requiredNSamples+1)/2+n1;
151 off2_tmp = off1_tmp+dim1_tmp;
152 dim2_tmp = (n2*ns+1)/2;
153 off3_tmp = off2_tmp+dim2_tmp;
154 dim3_tmp = getNumberOfWords()-3-off3_tmp-off;
155 if(dim2_tmp==0) off2_tmp = 0;
156 if(dim3_tmp==0) off3_tmp = 0;
157 }
158
159 if(off1 != off1_tmp) problem=1;
160 if(dim1 != dim1_tmp) problem=2;
161 if(off2 != off2_tmp) problem=3;
162 if(dim2 != dim2_tmp) problem=4;
163 if(off3 != off3_tmp) problem=5;
164 if(dim3 != dim3_tmp) problem=6;
165 if(n1 != n1_tmp) problem=7;
166 if(n2 != n2_tmp) problem=8;
167 if (m_requiredNSamples > 0 &&
168 getHeader32(NGains) != (uint32_t)0x10000 + m_requiredNSamples) problem=9;
169 //if(getHeader32(NGains)!=0x10000 + (unsigned int)ns) problem=9;
170 //if(getHeader32(InFPGAFormat)!=1) problem=10;
171 //if(m_FebBlock[getNumberOfWords()-2]!=0x12345678) problem=11;
172
173 if(problem) { // Try to recompute offsets
174 std::cout << "LArByteStreamProblem " << problem << std::endl;
175 std::cout << "NSamples = " << std::dec << ns << std::endl;
176 std::cout << "getHeader32(NGains) = " << std::hex << getHeader32(NGains) << std::endl;
177 std::cout << "NWTot: " << std::hex << getNumberOfWords() << " n1=" << n1 << " (" << n1_tmp << ") n2=" << n2 << " (" << n2_tmp << ")" << std::endl;
178 std::cout << "Found 1: " << off1 << " " << dim1 << std::endl;
179 std::cout << "Found 2: " << off2 << " " << dim2 << std::endl;
180 std::cout << "Found 3: " << off3 << " " << dim3 << std::dec << std::endl;
181
182 if(n1==n1_tmp && n2==n2_tmp) { // Check consistency of cells above threshold
183 off1 = off1_tmp;
184 dim1 = dim1_tmp;
185 off2 = off2_tmp;
186 dim2 = dim2_tmp;
187 off3 = off3_tmp;
188 dim3 = dim3_tmp;
189 std::cout << "Recomputed 1: " << std::hex << off1 << " " << dim1 << std::endl;
190 std::cout << "Recomputed 2: " << off2 << " " << dim2 << std::endl;
191 std::cout << "Recomputed 3: " << off3 << " " << dim3 << std::dec << std::endl;
192
193 if (off1 && dim1+off1+off<m_FebBlockSize) {
194 off1 += off;
195 if (dim1>=8)
196 m_GainPointer=reinterpret_cast<const uint32_t*>(m_FebBlock+off1);
197 if (dim1>=12)
198 m_MaskTimeQualityPointer=reinterpret_cast<const uint32_t*>(m_FebBlock+off1+8);
199 if (dim1>=16)
200 m_MaskDigitsPointer=reinterpret_cast<const uint32_t*>(m_FebBlock+off1+12);
201 if (dim1>=16+radd)
202 m_RaddPointer=reinterpret_cast<const uint16_t*>(m_FebBlock+off1+16);
203 if (dim1>=80+radd)
204 m_EnergyPointer=reinterpret_cast<const uint16_t*> (m_FebBlock+off1+16+radd);
205 if (dim1>=83+radd)
206 m_SumPointer=reinterpret_cast<const int32_t*>(m_FebBlock+off1+80+radd);
207 if (dim1>83+radd)
208 m_TimeQualityPointer=reinterpret_cast<const uint16_t*>(m_FebBlock+off1+83+radd);
209 }
210 if (off2 && dim2+off2+off<m_FebBlockSize) {
211 m_DigitsPointer=reinterpret_cast<const uint16_t*>(m_FebBlock+off2+off);
212 }
213 if (off3 && dim3+off3+off<m_FebBlockSize) {
214 m_RawDataPointer=reinterpret_cast<const uint16_t*>(m_FebBlock+off3+off);
215 }
216 }
217 }
218
219 problem=0;
220 // Recheck offsets
221 if(off1< off2 && off1 + dim1 > off2) problem = 1;
222 if(off1< off3 && off1 + dim1 > off3) problem = 2;
223 if(off2< off1 && off2 + dim2 > off1) problem = 3;
224 if(off2< off3 && off2 + dim2 > off3) problem = 4;
225 if(off3< off1 && off3 + dim3 > off1) problem = 5;
226 if(off3< off2 && off3 + dim3 > off2) problem = 6;
227
228 if(problem) {
230 std::cout << "LArByteStreamProblem " << problem << std::endl;
231 std::cout << "Unrecoverable problem" << std::endl;
232 }
233
234 //uint32_t febId = getHeader32(FEBID);
235 //uint32_t onCheck = onlineCheckSum();
236 //uint32_t offCheck = offlineCheckSum();
237 //
238 //mycheck_tot++;
239 //if(onCheck!=offCheck)
240 //{
241 // mycheck_err++;
242 // std::cout << "FebID checksum " << std::hex << febId << std::endl;
243 // std::cout << "Online checksum " << std::hex << onCheck << " Offline checksum " << offCheck << std::dec << std::endl;
244 // std::cout << "Diff1 checksum " << std::hex << onCheck-offCheck << " Diff2 checksum " << offCheck-onCheck << std::dec << std::endl;
245 // double x=mycheck_err/((double) mycheck_tot)*100.0;
246 // std::cout << "Number of FEB in error: " << mycheck_err << " / " << mycheck_tot << " = " << x << " %" << std::endl;
247 //}
248
249 //
250 //if(febId==0x3b1b8000 || febId==0x398b0000 || febId==0x3a988000) {
251 //if(onCheck!=offCheck) {
252 // std::cout << "***********************************************************************"<< std::endl;
253 // std::cout << "Problem :" << problem << std::endl;
254 // std::cout << "Header values :"<< std::endl;
255 // std::cout << "************************************************************************"<< std::endl;
256 // std::cout << "FebBlockSize = " << m_FebBlockSize << std::endl;
257 // std::cout << "EnergyIndex = " << m_EnergyIndex << std::endl;
258 // std::cout << "TimeQualityIndex = " << m_TimeQualityIndex << std::endl;
259 // std::cout << "DigitsIndex = " << m_DigitsIndex << std::endl;
260 // std::cout << "DigitsChannel = " << m_DigitsChannel << std::endl;
261 // std::cout << "RawDataIndex = " << m_RawDataIndex << std::endl;
262 // std::cout << "GainPointer = " << m_GainPointer << std::endl;
263 // std::cout << "MaskTimeQualityPointer = " << m_MaskTimeQualityPointer << std::endl;
264 // std::cout << "MaskDigitsPointer = " << m_MaskDigitsPointer << std::endl;
265 // std::cout << "RaddPointer = " << m_RaddPointer << std::endl;
266 // std::cout << "EnergyPointer = " << m_EnergyPointer << std::endl;
267 // std::cout << "SumPointer = " << m_SumPointer << std::endl;
268 // std::cout << "TimeQualityPointer = " << m_TimeQualityPointer << std::endl;
269 // std::cout << "DigitsPointer = " << m_DigitsPointer << std::endl;
270 // std::cout << "RawDataPointer = " << m_RawDataPointer << std::endl;
271 // std::cout << "numberHotCell = " << std::dec << getNbSweetCells1() << " " << getNbSweetCells2() << std::endl;
272 // std::cout << "Fragment @ = 0x" << std::hex << m_FebBlock << std::endl;
273 // std::cout << "NWTot = " << std::dec << getNumberOfWords() << std::endl;
274 // std::cout << "FebID = 0x" << std::hex << getHeader32(FEBID) << std::endl;
275 // std::cout << "FebSN = 0x" << std::hex << getHeader32(FEB_SN) << std::endl;
276 // std::cout << "ResultsOff1 = 0x" << std::hex << getHeader16(ResultsOff1) << std::endl;
277 // std::cout << "ResultsDim1 = 0x" << std::hex << getHeader16(ResultsDim1) << std::endl;
278 // std::cout << "ResultsOff2 = 0x" << std::hex << getHeader16(ResultsOff2) << std::endl;
279 // std::cout << "ResultsDim2 = 0x" << std::hex << getHeader16(ResultsDim2) << std::endl;
280 // std::cout << "RawDataBlkOff = 0x" << std::hex << getHeader16(RawDataBlkOff) << std::endl;
281 // std::cout << "RawDataBlkDim = 0x" << std::hex << getHeader16(RawDataBlkDim) << std::endl;
282 // std::cout << "Event status = 0x" << std::hex << getStatus() << std::dec << std::endl;
283 // std::cout << "************************************************************************"<< std::dec << std::endl;
284 // int size = getNumberOfWords();
285 // for(int i=0;i<size;i++) {
286 // std::cout << std::hex << i << " : " << std::hex << m_FebBlock+i << " : " << std::hex << m_FebBlock[i] << std::endl;
287 // }
288 //}
289
290 }
291
292 return true;
293}
294
295int LArRodBlockPhysicsV5::getNextRawData(int& channelNumber, std::vector<short>& samples, uint32_t& gain)
296{
297#ifdef LARBSDBGOUTPUT
298 MsgStream logstr(Athena::getMessageSvc(), BlockType());
299 //Debug output
300 logstr << MYLEVEL << "Let s go in getNextRawData..." << endmsg;
301 logstr << MYLEVEL << "GetNextRawData for FEB 0x" << MSG::hex << (uint32_t)getHeader32(FEBID) << MSG::dec << endmsg;
302 logstr << MYLEVEL << "m_RawDataPointer=" << m_RawDataPointer << " m_RawDataIndex="<< m_RawDataIndex
303 << " m_channelsPerFEB=" << m_channelsPerFEB << endmsg;
304#endif
305
306 if (m_RawDataIndex>=m_channelsPerFEB) { //Already beyond maximal number of channels
307#ifdef LARBSDBGOUTPUT
308 logstr << MYLEVEL << "Maximum number of channels reached" << endmsg;
309#endif
310 return 0;
311 }
312 //const uint16_t block = getHeader16(m_RawDataOff);//Position of the raw FEB data block
313 if (!m_RawDataPointer) { //Block does not exist
314 // Try to get samples and gain from getNextDigits
315 return getNextDigits(channelNumber,samples,gain);
316 }
317
318 // Get next channel
319 unsigned rodChannelNumber=m_RawDataIndex; // Index of Channel in ROD-Block
320 channelNumber=((rodChannelNumber&0xe)<<2) + ((rodChannelNumber&0x1)<<6) + (rodChannelNumber>>4); //channel number of the FEB
321 //channelNumber=(rodChannelNumber>>4) + ((rodChannelNumber&0xf)<<3); //channel number of the FEB
322 uint32_t febgain;
323 const unsigned int nsamples = getHeader16(NSamples) & 0xff;
324 const unsigned int ngains = getHeader16(NGains);
325
326#ifdef LARBSDBGOUTPUT
327 logstr << MYLEVEL << "This FEB has " << nsamples << " samples" << endmsg;
328 logstr << MYLEVEL << "This FEB has " << ngains << " gains" << endmsg;
329#endif
330
331 if(ngains==0 || nsamples==0) return 0;
332 int s_size = nsamples+1;
333 int offset = (10+nsamples)&0xfffc;
334 int index;
335 index = s_size*m_RawDataIndex + offset;
336 uint16_t s[2];
337 //for(unsigned int i=0;i<nsamples+1;i++) {
338 // if(m_RawDataPointer[index+i]>>14) {
339 // std::cout << "Trying to decode strange raw data value: " << std::hex << m_RawDataPointer[index+i] << std::dec << std::endl;
340 // }
341 //}
342 if((nsamples+1)&0x7) {
343 s[0] = m_RawDataPointer[index++]>>2;
344 febgain = m_RawDataPointer[index++];
345 samples.push_back(s[0]);
346 for(unsigned int i=0;i<nsamples/2;i++) {
347 s[1] = m_RawDataPointer[index++]>>2;
348 s[0] = m_RawDataPointer[index++]>>2;
349 samples.push_back(s[0]);
350 samples.push_back(s[1]);
351 }
352 } // End of check for 5 samples
353 else {
354 if (!(m_RawDataIndex%2)) {
355 s[0] = m_RawDataPointer[index++]>>2;
356 febgain = m_RawDataPointer[index++];
357 samples.push_back(s[0]);
358 for(unsigned int i=0;i<nsamples/2;i++) {
359 s[1] = m_RawDataPointer[index++]>>2;
360 s[0] = m_RawDataPointer[index++]>>2;
361 samples.push_back(s[0]);
362 samples.push_back(s[1]);
363 }
364 } else {
365 for(unsigned int i=0;i<nsamples/2;i++) {
366 s[1] = m_RawDataPointer[index++]>>2;
367 s[0] = m_RawDataPointer[index++]>>2;
368 samples.push_back(s[0]);
369 samples.push_back(s[1]);
370 }
371 febgain = m_RawDataPointer[index++];
372 s[0] = m_RawDataPointer[index++]>>2;
373 samples.push_back(s[0]);
374 }
375 } // End of >5 check
376 gain=RawToOfflineGain(febgain);
377
378#ifdef LARBSDBGOUTPUT
379 logstr << MYLEVEL << " ===> ROD Channel = " << m_RawDataIndex << endmsg;
380 logstr << MYLEVEL << " ===> FEB Channel = " << channelNumber << endmsg;
381 logstr << MYLEVEL << " ===> Gain = " << gain << endmsg;
382 for(int i=0;i<nsamples;i++)
383 logstr << MYLEVEL << " ===> sample " << i << " = " << samples[i] << endmsg;
384 int n = m_RawDataIndex;
385 int32_t e,t,q;
386 uint32_t g;
388#endif
389 //std::cout << "Gain= " << gain << " Febgain=" << febgain << std::endl;
391 unsigned rearrangeFirstSample=0;
393 rearrangeFirstSample=m_rearrangeFirstSample; //Overwrite by jobOptions
394 else
395 rearrangeFirstSample=getFirstSampleIndex();
396 //std::cout << "FebConfig: "<< getFebConfig() << " FirstSampleIndex " << getFirstSampleIndex() <<std::endl;
397 if (rearrangeFirstSample && rearrangeFirstSample<samples.size()) //FIXME: Very ugly hack! See explanation in LArRodDecoder.h file
398 {//Change e.g. 3 0 1 2 4 to 0 1 2 3 4
399 short movedSample=samples[0];
400 for (unsigned i=1;i<=rearrangeFirstSample;i++)
401 samples[i-1]=samples[i];
402 samples[rearrangeFirstSample]=movedSample;
403 }
404#ifdef LARBSDBGOUTPUT
405 logstr << MYLEVEL << "GetNextRawData for FEB finished 0x" << MSG::hex << (uint32_t)getHeader32(FEBID) << MSG::dec << endmsg;
406#endif
407 return 1;
408}
409
410int LArRodBlockPhysicsV5::getNextDigits(int& channelNumber, std::vector<short>& samples, uint32_t& gain)
411{
412 //std::cout << " I am here !!!!!!!!!!!!!!!!!!!!!! " << std::endl;
413#ifdef LARBSDBGOUTPUT
414 MsgStream logstr(Athena::getMessageSvc(), BlockType());
415 //Debug output
416 logstr << MYLEVEL << "Let s go in getNextDigits..." << endmsg;
417 logstr << MYLEVEL << "GetNextDigits for FEB 0x" << MSG::hex << (uint32_t)getHeader32(FEBID) << MSG::dec << endmsg;
418 logstr << MYLEVEL << "m_DigitsPointer=" << m_DigitsPointer << " m_DigitsIndex="<< m_DigitsIndex
419 << " m_DigitsChannel="<< m_DigitsChannel
420 << " m_channelsPerFEB=" << m_channelsPerFEB << endmsg;
421#endif
422
423 if (m_DigitsChannel>=m_channelsPerFEB) { //Already beyond maximal number of channels
424#ifdef LARBSDBGOUTPUT
425 logstr << MYLEVEL << "Maximum number of channels reached" << endmsg;
426#endif
427 return 0;
428 }
429 //const uint16_t block = getHeader16(m_DigitsOff);//Position of the raw FEB data block
430 if (!m_DigitsPointer) { //Block does not exist
431#ifdef LARBSDBGOUTPUT
432 logstr << MYLEVEL << "No Digits Block in this FEB" << endmsg;
433#endif
434 return 0;
435 }
436 if (!m_MaskDigitsPointer) { //Block does not exist
437#ifdef LARBSDBGOUTPUT
438 logstr << MYLEVEL << "No Mask Digits Block in this FEB" << endmsg;
439#endif
440 return 0;
441 }
442
443 // Get Digits if the information is present according to summary block
444 uint32_t hasDigits;
445
446 hasDigits = (uint32_t) ((m_MaskDigitsPointer[m_DigitsChannel>>5] >> (m_DigitsChannel&0x1f)) &0x1);
447 // Increment channel number until digits are found
448 while(hasDigits==0) {
450 if (m_DigitsChannel>=m_channelsPerFEB) { //Already beyond maximal number of channels
451#ifdef LARBSDBGOUTPUT
452 logstr << MYLEVEL << "Maximum number of channels reached" << endmsg;
453#endif
454 return 0;
455 }
456 hasDigits = (uint32_t) ((m_MaskDigitsPointer[m_DigitsChannel>>5] >> (m_DigitsChannel&0x1f)) &0x1);
457 }
458
459 // Get next channel
460 unsigned rodChannelNumber=m_DigitsChannel; // Index of Channel in ROD-Block
461 channelNumber=((rodChannelNumber&0xe)<<2) + ((rodChannelNumber&0x1)<<6) + (rodChannelNumber>>4); //channel number of the FEB
462 //channelNumber=(rodChannelNumber>>4) + ((rodChannelNumber&0xf)<<3); //channel number of the FEB
463 const unsigned int nsamples = getHeader16(NSamples) & 0xff;
464
465 // gain in 2 bits of a 32 bits word
466 if(m_GainPointer) {
467 gain = (uint32_t) ((m_GainPointer[m_DigitsChannel>>4] >> (m_DigitsChannel&0xf)*2) & 0x3);
468 gain=RawToOfflineGain(gain);
469 } else gain=0xffffffff;
470
471#ifdef LARBSDBGOUTPUT
472 logstr << MYLEVEL << "This FEB has " << nsamples << " samples" << endmsg;
473#endif
474
475 if(nsamples==0) return 0;
476 int s_size = nsamples;
477 int index;
478 index = s_size*m_DigitsIndex;
479 //uint16_t s;
480 //for(unsigned int i=0;i<nsamples;i++) {
481 // s = m_DigitsPointer[index++]>>2;
482 // samples.push_back(s);
483 //}
484 //int ok=1;
485 //for(unsigned int i=0;i<nsamples;i++) {
486 // if(m_DigitsPointer[index+i]>>14 && m_DigitsIndex<getNbSweetCells2()-1) {
487 // std::cout << "Trying to decode strange digits value: " << std::hex << m_DigitsPointer[index+i] << std::dec << std::endl;
488 // ok=0;
489 // }
490 //}
491 if(m_DigitsIndex&0x1) {
492 samples.push_back(m_DigitsPointer[index-1]>>2);
493 samples.push_back(m_DigitsPointer[index+2]>>2);
494 samples.push_back(m_DigitsPointer[index+1]>>2);
495 samples.push_back(m_DigitsPointer[index+4]>>2);
496 samples.push_back(m_DigitsPointer[index+3]>>2);
497 if(nsamples==7) {
498 samples.push_back(m_DigitsPointer[index+6]>>2);
499 samples.push_back(m_DigitsPointer[index+5]>>2);
500 }
501 } else {
502 samples.push_back(m_DigitsPointer[index+1]>>2);
503 samples.push_back(m_DigitsPointer[index+0]>>2);
504 samples.push_back(m_DigitsPointer[index+3]>>2);
505 samples.push_back(m_DigitsPointer[index+2]>>2);
506 samples.push_back(m_DigitsPointer[index+5]>>2);
507 if(nsamples==7) {
508 samples.push_back(m_DigitsPointer[index+4]>>2);
509 samples.push_back(m_DigitsPointer[index+7]>>2);
510 }
511 }
512
513#ifdef LARBSDBGOUTPUT
514 logstr << MYLEVEL << " ===> ROD Channel = " << m_DigitsChannel << endmsg;
515 logstr << MYLEVEL << " ===> FEB Channel = " << channelNumber << endmsg;
516 logstr << MYLEVEL << " ===> Gain = " << gain << endmsg;
517 for(int i=0;i<nsamples;i++)
518 logstr << MYLEVEL << " ===> sample " << i << " = " << samples[i] << endmsg;
519#endif
520 //std::cout << "Gain= " << gain << " Febgain=" << febgain << std::endl;
523 unsigned rearrangeFirstSample=0;
525 rearrangeFirstSample=m_rearrangeFirstSample; //Overwrite by jobOptions
526 else
527 rearrangeFirstSample=getFirstSampleIndex();
528 //std::cout << "FebConfig: "<< getFebConfig() << " FirstSampleIndex " << getFirstSampleIndex() <<std::endl;
529 if (rearrangeFirstSample && rearrangeFirstSample<samples.size()) //FIXME: Very ugly hack! See explanation in LArRodDecoder.h file
530 {//Change e.g. 3 0 1 2 4 to 0 1 2 3 4
531 short movedSample=samples[0];
532 for (unsigned i=1;i<=rearrangeFirstSample;i++)
533 samples[i-1]=samples[i];
534 samples[rearrangeFirstSample]=movedSample;
535 }
536#ifdef LARBSDBGOUTPUT
537 logstr << MYLEVEL << "GetNextDigits for FEB finished 0x" << MSG::hex << (uint32_t)getHeader32(FEBID) << MSG::dec << endmsg;
538#endif
539 return 1;
540}
541
543{
544 if(!m_RaddPointer) return 0;
545 return m_RaddPointer[1]>>8;
546}
547
549{
550 if(!m_RaddPointer) return 0;
551 return m_RaddPointer[1] & 0xff;
552}
553
555{
556 if(!m_MaskTimeQualityPointer) return 0;
557 int n=0;
558 for(int i=0;i<4;i++)
559 for(int j=0;j<32;j++)
560 if((m_MaskTimeQualityPointer[i] >> j) &0x1) n++;
561 return n;
562}
563
565{
566 if(!m_MaskDigitsPointer) return 0;
567 int n=0;
568 for(int i=0;i<4;i++)
569 for(int j=0;j<32;j++)
570 if((m_MaskDigitsPointer[i] >> j) &0x1) n++;
571 return n;
572}
573
575{
576 return getHeader16(NSamples);
577}
578
580{
581 return getHeader16(NGains);
582}
583
585{
586 return getHeader16(ResultsDim1);
587}
588
590{
591 return getHeader16(ResultsDim2);
592}
593
595{
597}
598
599uint32_t LArRodBlockPhysicsV5::getRadd(uint32_t adc, uint32_t sample) const
600{
601 if(!m_RawDataPointer) {
602 if(!m_RaddPointer) return 0;
603 if(sample%2) sample+=2;
604 return m_RaddPointer[sample];
605 }
606 int index;
607 if(sample==0) index=6;
608 else if(sample & 0x1) index=7+sample-1;
609 else index=7+sample+1;
610 uint32_t x=m_RawDataPointer[index];
611 if(adc>=8) return x>>8;
612 return x&0xff;
613}
614
615uint16_t LArRodBlockPhysicsV5::getCtrl1(uint32_t /*adc*/) const
616{
617 if(!m_RawDataPointer) return 0;
618 int index=5;
619 uint16_t x=m_RawDataPointer[index];
620 return x;
621}
622
623uint16_t LArRodBlockPhysicsV5::getCtrl2(uint32_t /*adc*/) const
624{
625 if(!m_RawDataPointer) return 0;
626 int index=4;
627 uint16_t x=m_RawDataPointer[index];
628 return x;
629}
630
631uint16_t LArRodBlockPhysicsV5::getCtrl3(uint32_t /*adc*/) const
632{
633 if(!m_RawDataPointer) return 0;
634 int index=7;
635 uint16_t x=m_RawDataPointer[index];
636 return x;
637}
638
640{
641 if(getNumberOfWords()<EventStatus/2) return 0;
642 uint32_t x=getHeader32(EventStatus);
643 return x;
644}
645
646/*
647uint32_t LArRodBlockPhysicsV5::onlineCheckSum() const
648{
649 //int size = getNumberOfWords();
650 int index = getNumberOfWords()-1;
651 if(index<m_iHeadBlockSize) return 0;
652 uint32_t sum = m_FebBlock[index];
653 //for(int i=size-10;i<size;i++) {
654 // std::cout << i << " : " << std::hex << m_FebBlock+i << " : " << m_FebBlock[i] << std::endl;
655 //}
656 return sum;
657}
658
659uint32_t LArRodBlockPhysicsV5::offlineCheckSum() const
660{
661 int end = getNumberOfWords()-3;
662 //int start = 0; //m_iHeadBlockSize;
663 uint32_t sum = 0;
664 for(int i=0;i<end;i++) {
665 sum += m_FebBlock[i];
666 //std::cout << i << " : " << std::hex << sum << " : " << m_FebBlock[i] << std::endl;
667 }
668 return sum & 0x7fffffff;
669}
670*/
671
672// start of encoding methods
673void LArRodBlockPhysicsV5::initializeFragment(std::vector<uint32_t>& fragment ){
674 m_pRODblock=&fragment; //remember pointer to fragment
675 if (fragment.size()>m_iHeadBlockSize) { //Got filled fragment
676 unsigned int sizeRead=0;
677 //Store existing data in the FEB-Map
678 while (sizeRead<fragment.size()) {
679 std::vector<uint32_t>::iterator FebIter;
680 FebIter=fragment.begin()+sizeRead; //Store pointer to current Feb-Header
681 m_FebBlock=&(*FebIter); //Set m_FebBlock in order to use getHeader-functions.
682 uint32_t currFEBid=getHeader32(FEBID); //Get this FEB-ID
683 uint16_t currFebSize=getNumberOfWords(); //Size of this FEB-Block
684 if (FebIter+currFebSize>fragment.end()) {
685 fragment.clear(); //Clear existing vector
686 //*m_logstr << MSG::ERROR << "Got inconsistent ROD-Fragment!" << endmsg;
687 return;
688 }
689 m_mFebBlocks[currFEBid].assign(FebIter,FebIter+currFebSize); //Copy data from ROD-fragment into FEB-Block
690 sizeRead+=currFebSize+m_MiddleHeaderSize; //6 is the middle header size
691 //LARBSDBG("Found FEB-id " << currFEBid << " in existing ROD-Fragment");
692 } // end while
693 }
694 fragment.clear(); //Clear existing vector
695 return;
696
697}
698
699//For writing: Initalizes a single FEB-Block
701{
703 if (m_vFragment->size()<m_iHeadBlockSize) //Got empty or spoiled fragment
704 {
705 m_vFragment->resize(m_iHeadBlockSize,0); //Initialize FEB-Header
706 setHeader32(FEBID,id); //Set Feb ID
707 // At least 10 (head) + 16 (gain/sumblks) + 64 (energies)
708 m_vFragment->reserve(90);
709 }
710
711 m_SumBlkBlockE1.resize(4);
712 for(unsigned int i=0;i<4;i++) m_SumBlkBlockE1[i]=0x0;
713 m_SumBlkBlockE2.resize(4);
714 for(unsigned int i=0;i<4;i++) m_SumBlkBlockE2[i]=0x0;
715 m_GainBlock.resize(8);
716 for(unsigned int i=0;i<8;i++) m_GainBlock[i]=0x0;
717// m_RawDataBlock.resize(0);
718 m_TimeQualityBlock.resize(6);
719 for(unsigned int i=0;i<6;i++) m_TimeQualityBlock[i]=0x0;
720 m_EnergyBlockEncode.resize(128);
721 for(unsigned int i=0;i<128;i++) m_EnergyBlockEncode[i]=0x0;
722 m_DigitsEncode.clear();
723
725
726}
727
728void LArRodBlockPhysicsV5::setNextEnergy(const int channel, const int32_t energy,
729 const int32_t time, const int32_t quality, const uint32_t gain)
730{
731 //LARBSDBG("setNextEnergy-------------------->>>>>********************** format V4 ***********");
732 //LARBSDBG("Channel=" << channel << " energy =" << energy);
733 int rcNb=FebToRodChannel(channel);
734 //int rcNb=(channel);
735 //rcNb ist supposed to equal or bigger than m_EIndex.
736 //In the latter case, we fill up the missing channels with zero
737 if (rcNb<m_EnergyIndex) {
738 //*m_logstr << MSG::ERROR << "LArRODBlockStructure Error: Internal error. Channels not ordered correctly. rcNb=" << rcNb
739 // << " m_EnergyIndex=" << m_EnergyIndex << endmsg;
740 return;
741 }
742
743 //Fill up missing channels with zeros:
744 while (m_EnergyIndex<rcNb)
745 setNextEnergy((int16_t)0,(int16_t)32767,(int16_t)-32767,(uint32_t)0);
746
747 // transform 32 bits data into 16 bits data
748
749 uint16_t theenergy;
750 uint32_t abse,EncodedE;
751 int16_t thetime,thequality;
752 int32_t sign;
753
754 //Time is in 10 ps in ByteStream, hence the factor 10 to convert from ps
755 thetime = (int16_t) time/10;
756 thequality = (int16_t) quality;
757
758 sign=(energy>=0?1:-1); // get sign of energy
759 abse=(uint32_t)abs(energy);
760
761 EncodedE=abse; // range 0
762
763 if ((abse>8192)&&(abse<65536))
764 {
765 EncodedE=((abse>>3)|0x4000); // range 1 : drop last 3 bits and put range bits (bits 14 and 13 = 01)
766 }
767 else if ((abse>65535)&&(abse<524288))
768 {
769 EncodedE=((abse>>6)|0x8000); // range 2 : drop last 6 bits and put range bits (bits 14 and 13 = 10)
770 }
771 else if ((abse>524288))
772 {
773 EncodedE=((abse>>9)|0xc000); // range 3 : drop last 9 bits and put range bits (bits 14 and 13 = 11)
774 }
775
776 // treat sign now :
777
778 if (sign<0) EncodedE |= 0x2000;
779 theenergy = (uint16_t) EncodedE;
780
781
782 // Add data...
783
784 //LARBSDBG("setNextEnergy-------------------->>>>> Energy = "<< energy << " Encoded Energy =" << theenergy);
785
786 if (abse> m_EnergyThreshold1)
787 {
788 setNextEnergy(theenergy,thetime,thequality,gain);
789 }
790 else
791 {
792 setNextEnergy(theenergy,(int16_t)32767,(int16_t)-32767,gain);
793 }
794 return;
795}
796
797//Private function, expects channel number is rod-style ordering
798void LArRodBlockPhysicsV5::setNextEnergy(const uint16_t energy,const int16_t time, const int16_t quality, const uint32_t gain)
799{
800 if (m_EnergyIndex>=m_channelsPerFEB) //Use m_EIndex to count total number of channels
801 {//*m_logstr << MSG::ERROR << "LArRodBlockStructure Error: Attempt to write Energy for channel "
802 // << m_EnergyIndex << " channels into a FEB!" <<endmsg;
803 return;
804 }
805 //LARBSDBG("LArRodBlockStructure: Setting Energy for channel " << m_EnergyIndex << ". E=" << energy);
806
807 //LARBSDBG("In setNextEnergy-------------------->>>>> time = " << time << " quality=" << quality);
808
809 // Energy
810 int endianindex;
811 if (m_EnergyIndex & 0x1) endianindex = m_EnergyIndex-1;
812 else endianindex = m_EnergyIndex+1;
813 m_EnergyBlockEncode[endianindex] = energy;
814
815 // Find correct position
816
817 //LARBSDBG("Writing Raw data to E block. E=" << energy);
818
819 // update summary block
820 // Gain is composed of two bits per cell
821 uint16_t gain_idx=m_EnergyIndex>>4;
822 uint16_t gain_bit=(m_EnergyIndex&0xf)*2;
823 uint32_t gain1 = OfflineToRawGain(gain);
824 m_GainBlock[gain_idx] |= (gain1 << gain_bit);
825
826 // write Time and Chi2 for cells above HighEnergyCellCut threshold
827
828 if (quality!=-32767) // Do write Time and Chi2 information
829 {
830 // count the number of hot cells
832 // count the number of cells offtime
833 if (abs(time)>m_OffTimeCut) m_numberHotCellOffTime++;
834 uint16_t mask_idx=m_EnergyIndex>>5;
835 uint16_t mask_bit=(m_EnergyIndex&0x1f);
836 m_SumBlkBlockE1[mask_idx] |= (0x1 << mask_bit);
837
838 m_TimeQualityBlock.push_back(*((uint16_t*)&time));
839 m_TimeQualityBlock.push_back(*((uint16_t*)&quality));
840 }
841 m_EnergyIndex++; //Use m_EIndex to count the channels put in the Energy block
842
843}
844
845void LArRodBlockPhysicsV5::setRawData(const int chIdx, const std::vector<short>& samples , const uint32_t /* gain_not_used */ ){
846
847 // First of all, set the bits
848 int cchIdx = FebToRodChannel(chIdx);
849 uint16_t mask_idx=cchIdx>>5;
850 uint16_t mask_bit=(cchIdx&0x1f);
851 m_SumBlkBlockE2[mask_idx] |= (0x1 << mask_bit);
852 for(std::vector<short>::const_iterator i=samples.begin();i!=samples.end();++i){
853 m_DigitsEncode.push_back((*i)<<2);
854 }
855
856}
857
859{
860//Complete non-complete Energy block
862 setNextEnergy((uint16_t)0,(int16_t)32767,(int32_t)-32767,(uint32_t)0);//E=0,t=32767,q=-32767,G=0
863
864uint16_t n;
865//uint16_t BlockOffset;
866uint16_t nsamples=5;
867// checkSum value
868uint32_t sum=0;
869
870// Will Hardcode here for the moment FIXME. Minimal 1 sample
872setHeader16(NSamples,nsamples);
873// These will never be used form MC. Nice to put in here thought
874setHeader16(FEB_SN,0xfefe);
875setHeader16(FEB_SN_h,0xdede);
878
879// Gain block...
880n = m_GainBlock.size();
881//BlockOffset=0;
882//LARBSDBG("Checking Gain Block n=" << n << "BlockOffset=" << BlockOffset);
883//Check if Gain-Block exists and is not yet part of the fragment
884if (n)
885 {
886 //LARBSDBG(MSG::DEBUG << "In finalyseFEB-------------------->>>>> " << "Checking for Gain Block : length= " << n << " BlockOffset=" << BlockOffset);
887 for(unsigned int i=0;i<n;i++){
888 m_vFragment->push_back(m_GainBlock[i]);
889 sum+=m_GainBlock[i];
890 }
891 }
892
893 // Cells above energy threshold E1
894 n = m_SumBlkBlockE1.size();
895 //Check if Summary Block exists and is not yet part of the fragment
896 if (n)
897 {
898 //LARBSDBG("In finalizeFEB-------------------->>>>> " << "Checking for Summary Block : length= " << n << " BlockOffset=" << BlockOffset);
899 for (unsigned i=0;i<n;i++){
900 m_vFragment->push_back(m_SumBlkBlockE1[i]);
901 sum+=m_SumBlkBlockE1[i];
902 }
903 }
904
905 // Cells above energy threshold E2 (not included so far)
906 n = m_SumBlkBlockE2.size();
907 //Check if Summary Block exists and is not yet part of the fragment
908 //LARBSDBG("Checking for Summary Block n=" << n << "BlockOffset=" << BlockOffset);
909 if (n)
910 {
911 //LARBSDBG("In finalizeFEB-------------------->>>>> " << "Checking for Summary Block : length= " << n << " BlockOffset=" << BlockOffset);
912 for (unsigned i=0;i<n;i++){
913 m_vFragment->push_back(m_SumBlkBlockE2[i]);
914 sum+=m_SumBlkBlockE2[i];
915 }
916 }
917
918 // fill info from counters
919 // for moment just include 1 fake words (32 bits) to put radd
920 uint32_t radd_nANC=0x0;
921 // Second threshold missing (FIXME)
922 radd_nANC = ((m_numberHotCell<<8))+(m_DigitsEncode.size()/nsamples);
923 radd_nANC = (radd_nANC<<16);
924 m_vFragment->push_back(radd_nANC);
925 sum+=radd_nANC;
926 // Need to include radd nsamples-1
927 // No need to include in sum's for now
928 for( int i=0; i < (nsamples-1)/2; i++)
929 m_vFragment->push_back(0x0);
930
931
932 // Energy block...
933 n = 128 ; // Fixed size m_EnergyBlock.size();
934 //BlockOffset=getVectorHeader16(ResultsOff1);
935 // Block also include time, whenever necessary
936 int size_of_block=80+(nsamples+1)/2+(m_TimeQualityBlock.size())/2;
937 //LARBSDBG("Checking Energy Block n=" << n << "BlockOffset=" << BlockOffset);
938 //Check if Energy-Block exists and is not yet part of the fragment
939 if (n)
940 {
942 setHeader16(ResultsDim1,size_of_block);
943 //LARBSDBG("In finalyseFEB-------------------->>>>> " << "Checking for Energy Block : length= " << n << " BlockOffset=" << BlockOffset);
944 for(unsigned int i=0;i<n/2;i++) {
945 // WARNING witch one should be >>16 2*i or 2*i+1? To be tested
946 uint32_t Encode = m_EnergyBlockEncode[2*i]+(m_EnergyBlockEncode[2*i+1]<<16);
947 m_vFragment->push_back(Encode);
948 sum+=Encode;
949 }
950 }
951
952 // Magic numbers (3 or 6) for Ex, Ey and Ez
953 n = m_TimeQualityBlock.size();
954 //LARBSDBG("Checking Time and Quality Block n=" << n << "BlockOffset=" << BlockOffset);
955 //Check if Time and Quality Block exists and is not yet part of the fragment
956 if (n)
957 {
958 unsigned int imax = n/2;
959 for(unsigned int i=0;i<imax;i++){
960 ShortLong to_push{};
961 to_push.s[0] = m_TimeQualityBlock[i*2];
962 to_push.s[1] = m_TimeQualityBlock[i*2+1];
963 m_vFragment->push_back(to_push.l);
964 sum+=to_push.l;
965 }
966 }
967 // Now include digits
968 n = m_DigitsEncode.size();
969 if ( n ) {
970 // First make sure it is not and odd number to store
971 if ( m_DigitsEncode.size() & 0x1 ) m_DigitsEncode.push_back(0x0);
972 unsigned int imax=m_DigitsEncode.size()/2;
973 for(unsigned int i=0;i<imax;i++){
974 // Better by-swap
975 ShortLong to_push{};
976 to_push.s[1]=m_DigitsEncode[i*2];
977 to_push.s[0]=m_DigitsEncode[i*2+1];
978 m_vFragment->push_back(to_push.l);
979 sum+=to_push.l;
980 }
982 setHeader16(ResultsOff2,18+size_of_block);
983 } // End of check for format
984
985 // Need to add header to check sum
986 for(size_t ii=0;ii<endtag/2;ii++){
987 sum+=((*m_vFragment)[ii]);
988 }
989 // Three final magic words
990 m_vFragment->push_back(0x0); // For the moment
991 m_vFragment->push_back(0x12345678); // For the moment
992 //sum+=m_vFragment->size()+1;
993 m_vFragment->push_back(sum& 0x7fffffff);
994
996 return;
997
998}
999
1000
1002{
1003 FEBMAPTYPE::const_iterator feb_it_b=m_mFebBlocks.begin();
1004 FEBMAPTYPE::const_iterator feb_it_e=m_mFebBlocks.end();
1005 FEBMAPTYPE::const_iterator feb_it;
1006 for (feb_it=feb_it_b;feb_it!=feb_it_e;++feb_it) {
1007 if (feb_it!=feb_it_b) //Not first Feb
1008 m_pRODblock->resize( m_pRODblock->size()+m_MiddleHeaderSize);
1009
1010 //Add feb data to rod data block
1011 m_pRODblock->insert (m_pRODblock->end(),
1012 feb_it->second.begin(), feb_it->second.end());
1013 } //end for feb_it
1014
1015 m_mFebBlocks.clear();
1016 return;
1017}
1018
1019//Sort functions & ordering relation:
1020template<class RAWDATA>
1021bool LArRodBlockPhysicsV5::operator ()
1022 (const RAWDATA* ch1, const RAWDATA* ch2) const
1023{
1024 HWIdentifier id1 = ch1->channelID();
1025 HWIdentifier id2 = ch2->channelID();
1026
1027 HWIdentifier febId1= m_onlineHelper->feb_Id(id1);
1029
1030 if(febId1 == febId2 ){
1031 int cId1 = m_onlineHelper->channel(id1);
1032 int cId2 = m_onlineHelper->channel(id2);
1033 return FebToRodChannel(cId1) < FebToRodChannel(cId2);
1034 }
1035
1036 return febId1 < febId2 ;
1037}
1038
1039
1040#ifdef LARBSDBGOUTPUT
1041#undef LARBSDBGOUTPUT
1042#endif
1043#undef LARBSDBG
#define endmsg
static Double_t sc
HWIdentifier febId1
HWIdentifier febId2
HWIdentifier id2
#define MYLEVEL
int sign(int a)
int imax(int i, int j)
#define x
virtual uint16_t getRawDataSize() const
const LArOnlineID * m_onlineHelper
const uint32_t * m_GainPointer
std::vector< uint16_t > m_EnergyBlockEncode
unsigned short m_requiredNSamples
virtual uint16_t getResults2Size() const
virtual int getNextRawData(int &channelNumber, std::vector< short > &samples, uint32_t &gain)
virtual int FebToRodChannel(int ch) const
void initializeFragment(std::vector< uint32_t > &fragment)
virtual uint16_t getCtrl2(uint32_t adc) const
virtual uint16_t getNbSweetCells2() const
virtual uint16_t getCtrl1(uint32_t adc) const
virtual uint32_t getNumberOfSamples() const
std::vector< uint32_t > m_SumBlkBlockE1
uint16_t getNbSweetCells1FromMask() const
std::vector< uint32_t > m_SumBlkBlockE2
const uint16_t * m_RawDataPointer
const uint16_t * m_DigitsPointer
const uint32_t * m_MaskDigitsPointer
virtual uint32_t getRadd(uint32_t adc, uint32_t sample) const
virtual uint16_t getResults1Size() const
int getNextDigits(int &channelNumber, std::vector< short > &samples, uint32_t &gain)
uint16_t getNbSweetCells2FromMask() const
uint16_t getFirstSampleIndex() const
std::vector< uint32_t > m_GainBlock
const uint32_t * m_MaskTimeQualityPointer
const uint16_t * m_TimeQualityPointer
virtual uint16_t getCtrl3(uint32_t adc) const
virtual uint16_t getNbSweetCells1() const
virtual uint32_t getStatus() const
void initializeFEB(const uint32_t id)
const uint16_t * m_RaddPointer
void setNextEnergy(const int channel, const int32_t energy, const int32_t time, const int32_t quality, const uint32_t gain)
void setRawData(const int, const std::vector< short > &, const uint32_t)
const uint16_t * m_EnergyPointer
virtual uint32_t getNumberOfGains() const
std::vector< uint16_t > m_DigitsEncode
virtual int getNextEnergy(int &channelNumber, int32_t &energy, int32_t &time, int32_t &quality, uint32_t &gain)
std::vector< uint16_t > m_TimeQualityBlock
uint16_t getHeader16(const unsigned n) const
void setHeader32(const unsigned n, const uint32_t w)
uint32_t getHeader32(const unsigned n) const
void setHeader16(const unsigned n, const uint16_t w)
std::vector< uint32_t > * m_pRODblock
uint32_t OfflineToRawGain(const uint32_t gain) const
std::vector< uint32_t > * m_vFragment
uint32_t RawToOfflineGain(const uint32_t gain) const
uint32_t getNumberOfWords() const
singleton-like access to IMessageSvc via open function and helper
IMessageSvc * getMessageSvc(bool quiet=false)
@ LARNGAIN
Definition CaloGain.h:19
Definition index.py:1