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