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