ATLAS Offline Software
Loading...
Searching...
No Matches
LArRodBlockPhysicsV2.cxx
Go to the documentation of this file.
1
2/*
3 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
4*/
5
6// Implementation of the LArRODBlockStructure_3 class
7// This version contains LArRawChannels (=E,t,Q)
8// and LArDigits (=5 time samples)
9// See .h file for more details.
10
15#include "GaudiKernel/Bootstrap.h"
16#include "GaudiKernel/ISvcLocator.h"
17#include "GaudiKernel/IToolSvc.h"
18#include <stdlib.h>
19#include <cstdio>
20#include <iostream>
21
22#ifdef LARBSDBGOUTPUT
23#define LARBSDBG(text) m_logstr<<MSG::DEBUG<<text<<endmsg
24#else
25#define LARBSDBG(text)
26#endif
27
28namespace {
29union ShortLong {
30 uint16_t s[2];
31 uint32_t l;
32};
33}
34
36
39{
40 // retrieve onlineHelper
41 const LArOnlineID* online_id;
42 SmartIF<StoreGateSvc> detStore{Gaudi::svcLocator()->service("DetectorStore")};
43 if (!detStore) {
44 m_logstr << MSG::ERROR << "Unable to locate DetectorStore" << endmsg;
45 std::abort();
46 }
47 StatusCode sc = detStore->retrieve(online_id, "LArOnlineID");
48 if (sc.isFailure()) {
49 m_logstr << MSG::FATAL << "Could not get LArOnlineID helper !" << endmsg;
50 std::abort();
51 }
52 else {
53 m_onlineHelper=online_id;
54 m_logstr << MSG::DEBUG << " Found the LArOnlineID helper. " << endmsg;
55 }
56
57 m_iHeadBlockSize=endtag/2; // The implicit cast rounds down to the right size
60 m_vFragment=NULL;
61 m_FebBlock=NULL;
62 m_pRODblock=NULL;
63 m_FlagPtr=NULL;
64 m_GainPtr=NULL;
65 m_HighEPtr=NULL;
66 m_LowEPtr=NULL;
68 m_RawDataPtr=NULL;
69}
70
71// clear temporary block vectors
78
88
89//For reading (to speed up the process)
91{
92 //Set pointers to data blocks (pesuming, they exist)
94 {
96 {
98 m_RawDataPtr=reinterpret_cast<const uint16_t*>(m_RawDataFlagsPtr+m_NFlaggingWords);
99 m_GainPtr=reinterpret_cast<const uint32_t*>(m_RawDataFlagsPtr-2*m_NFlaggingWords);
100 }
101 else
102 {
104 m_RawDataPtr=reinterpret_cast<const uint16_t*>(m_RawDataFlagsPtr);
105 m_GainPtr=reinterpret_cast<const uint32_t*>(m_DummyBitMap);
106 }
108 {
110 m_LowEPtr=reinterpret_cast<const int16_t*>(m_FlagPtr+m_NFlaggingWords);
111 }
112 else
113 { //Bugfix, 9.8.2004, WL: Set pointer to dummy map to read FEB with only high energy block
115 m_LowEPtr=reinterpret_cast<const int16_t*>(m_FlagPtr);
116 }
118 m_HighEPtr=reinterpret_cast<const int32_t*>(m_FebBlock)+LE_getHeader16(HighEBlkOffset);
119 else
120 m_HighEPtr=NULL;
121 }
122 else
123 {
124 m_RawDataPtr=NULL;
126 m_GainPtr=NULL;
127 m_FlagPtr=NULL;
128 m_LowEPtr=NULL;
129 m_HighEPtr=NULL;
130 }
131 return true;
132}
133
134
136{
137 uint16_t oldword=LE_getVectorHeader16(NGainNSamples);
138 LE_setHeader16(NGainNSamples,(oldword & 0xFF00) | n);
139}
140
142{
143 uint16_t oldword=LE_getVectorHeader16(NGainNSamples);
144 LE_setHeader16(NGainNSamples,(oldword & 0x00FF) | (n<<8));
145}
146
147
148void LArRodBlockPhysicsV2::setNextEnergy(const int channel, const int32_t energy,
149 const int32_t time, const int32_t quality, const uint32_t gain) {
150 int rcNb=FebToRodChannel(channel);
151 //rcNb ist supposed to equal or bigger than m_EIndex.
152 //In the latter case, we fill up the missing channels with zero
153 if (rcNb<m_EIndex) {
154 m_logstr << MSG::ERROR << "LArRODBlockStructure Error: Internal error. Channels not ordered correctly. rcNb=" << rcNb
155 << " m_EIndex=" << m_EIndex << endmsg;
156 return;
157 }
158 //Fill up missing channels with zeros:
159 while (m_EIndex<rcNb)
160 setNextEnergy(0,0,-1,0);
161 //Add data...
162 setNextEnergy(energy,time,quality,gain);
163}
164
165//Private function, expects channel number is rod-style ordering
166void LArRodBlockPhysicsV2::setNextEnergy(const int32_t energy, const int32_t time, const int32_t quality, const uint32_t gain)
167{
168 if (m_EIndex>=m_channelsPerFEB) //Use m_EIndex to count total number of channels
169 {
170 m_logstr << MSG::ERROR << "LArRodBlockStructure Error: Attempt to write Energy for channel "
171 << m_EIndex << " channels into a FEB!" <<endmsg;
172 return;
173 }
174 LARBSDBG("LArRodBlockStructure: Setting Energy for channel " << m_EIndex << ". E=" << energy);
175 if (quality<0 && energy<0x7FFE && gain==0) { //Write into Low Energy block
176 m_LowEIndex++; //Use m_LowEIndex to count the channels in the Low Energy block
177 ShortLong twoValues{};
178 twoValues.s[0]=0;
179 twoValues.s[1]=0;
180 if (m_LowEIndex%2==1) { //This is an odd number, simply add data at the bottom of the block
181 twoValues.s[0]=(int16_t)energy;
182 }
183 else { //Even number: Merging with previous block
184 uint32_t oneValue=m_LowEnergyBlock[m_LowEnergyBlock.size()-1]; //Take last element of vector
185 m_LowEnergyBlock.pop_back();
186 int16_t* valptr=reinterpret_cast<int16_t*>(&oneValue);
187 twoValues.s[0]=valptr[0];
188 twoValues.s[1]=(int16_t)energy;
189 }
190 LARBSDBG("Writing words: val0= " << twoValues.s[0] << " val1= " << twoValues.s[1]);
191 m_LowEnergyBlock.push_back(twoValues.l);
192 LARBSDBG("Writing Raw data to Low E block. E=" << energy);
193 }
194 else //Write into High Energy block
195 {
197 m_HighEnergyBlock.push_back(energy);
198 uint32_t t_sign;
199 uint32_t abs_time;
200 if (time<0)
201 t_sign=1;
202 else
203 t_sign=0;
204 abs_time=abs(time);
205 if (abs_time>0x1fff)
206 abs_time=0x1fff;
207 uint32_t gtQ = (gain << 30) | (t_sign<<29) | ((abs_time & 0x1fff)<<16) | (0xffff & quality);
208 m_HighEnergyBlock.push_back(gtQ);
209 LARBSDBG("Writing Raw data to High E block. E=" << energy << " Q=" << quality);
210 }
211 m_EIndex++;
212}
213
214
215void LArRodBlockPhysicsV2::setRawData(const int channel, const std::vector<short>& samples, const uint32_t gain) {
216 //Convert Feb to Rod Channel Number:
217 int rcNb=FebToRodChannel(channel);
218 if (rcNb>=m_channelsPerFEB)
219 {m_logstr << MSG::ERROR << "Attempt to write Energy for channel " << rcNb << " channels into a FEB!" << endmsg;
220 return;
221 }
222 unsigned int nsamples = LE_getVectorHeader16(NGainNSamples) & 0x00FF;
223 if(samples.size() != nsamples) {
224 m_logstr << MSG::ERROR << "Number of samples mismatch!\n";
225 m_logstr << " nsamples =" << nsamples;
226 m_logstr << " samples.size() =" << samples.size() << endmsg;
227 std::abort();
228 }
229
230 setBit(&m_RawDataBlock[0],rcNb);
231 //Samples have 12 bit and are shifted to the left by 2 bits.
232 // odd samples in high bits, even samples in low bits
233 if((nsamples/2)*2!=nsamples) { //odd number of samples - gain is alone
234 m_RawDataBlock.push_back((gain<<30) | samples[0]<<2);
235 for (unsigned int i=1;i<nsamples;i+=2)
236 m_RawDataBlock.push_back((samples[i+1]<<18) | samples[i]<<2);
237 }
238 else { //even number of samples - gain is packed with sample 0
239 m_RawDataBlock.push_back((gain<<30) | (samples[1]<<18) | samples[0]<<2);
240 for (unsigned int i=2;i<nsamples;i+=2)
241 m_RawDataBlock.push_back((samples[i+1]<<18) | samples[i]<<2);
242 }
243}
244
245
246//For writing: takes existing Fragment and splits it into Feb-Blocks
247void LArRodBlockPhysicsV2::initializeFragment(std::vector<uint32_t>& fragment)
248{
249 m_pRODblock=&fragment; //remember pointer to fragment
250 if (fragment.size()>m_iHeadBlockSize) { //Got filled fragment
251 unsigned int sizeRead=0;
252 //Store existing data in the FEB-Map
253 while (sizeRead<fragment.size()) {
254 std::vector<uint32_t>::iterator FebIter;
255 FebIter=fragment.begin()+sizeRead; //Store pointer to current Feb-Header
256 m_FebBlock=&(*FebIter); //Set m_FebBlock in order to use getHeader-functions.
257 uint32_t currFEBid=getHeader32(FEBID); //Get this FEB-ID
258 uint16_t currFebSize=getNumberOfWords(); //Size of this FEB-Block
259 if (FebIter+currFebSize>fragment.end()) {
260 fragment.clear(); //Clear existing vector
261 m_logstr << MSG::ERROR << "Got inconsistent ROD-Fragment!" << endmsg;
262 return;
263 }
264 m_mFebBlocks[currFEBid].assign(FebIter,FebIter+currFebSize); //Copy data from ROD-fragment into FEB-Block
265 sizeRead+=currFebSize+m_MiddleHeaderSize;//6 is the middle header size
266 LARBSDBG("Found FEB-id " << currFEBid << " in existing ROD-Fragment");
267 } // end while
268 }
269 fragment.clear(); //Clear existing vector
270 return;
271}
272
273//For writing: Initalizes a single FEB-Block
275{
277 if (m_vFragment->size()<m_iHeadBlockSize) //Got empty or spoiled fragment
278 {
279 m_vFragment->resize(m_iHeadBlockSize,0); //Initialize FEB-Header
280 setHeader32(FEBID,id); //Set Feb ID
281 }
282
286}
287
289{
290 //Complete non-complete Energy block
292 setNextEnergy(0,0,-1,0);//E=0,t=0,q=-1,G=0
293 // Energies
294 unsigned int n;
295 uint16_t BlockOffset;
296 //Low energy block....
297 n = m_LowEnergyBlock.size();
299 //Check if Low Energy Block exists and is not yet part of the fragment
300 LARBSDBG("Checking Low Energy Block n=" << n << "BlockOffset=" << BlockOffset);
301 if (n>m_NFlaggingWords && !BlockOffset)
302 {
304 for (unsigned i=0;i<n;i++)
305 m_vFragment->push_back(m_LowEnergyBlock[i]);
306 }
307 //High energy block...
308 n = m_HighEnergyBlock.size();
310 LARBSDBG("Checking High Energy Block n=" << n << "BlockOffset=" << BlockOffset);
311 //Check if High Energy-Block exists and is not yet part of the fragment
312 if (n && !BlockOffset)
313 {
315 for(unsigned int i=0;i<n;i++)
316 m_vFragment->push_back(m_HighEnergyBlock[i]);
317 }
318
319 // Raw data
320 LARBSDBG("Checking Raw Data Block");
321 n = m_RawDataBlock.size();
323 LARBSDBG("Checking Raw Data Block. n=" << n << "BlockOffset=" << BlockOffset);
324 //Check if Raw Data block exists and is not yet part of the fragment
325 if (n>m_NFlaggingWords && !BlockOffset)
326 {
328 for(unsigned int i=0;i<n;i++)
329 m_vFragment->push_back(m_RawDataBlock[i]);
330 }
332 LARBSDBG("Offsets:" << std::endl
333 << "Raw Data: " << LE_getVectorHeader16(RawDataBlkOffset) << std::endl
334 <<"Low Energy: " << LE_getVectorHeader16(LowEBlkOffset)<< std::endl
335 << "High Energy: " << LE_getVectorHeader16(HighEBlkOffset)<< std::endl
336 << "Energy-index:" << m_EIndex << std::endl
337 << "Filled channels: " << m_ECounter << std::endl);
338 clearBlocks();
339}
340
341
343{
344 FEBMAPTYPE::const_iterator feb_it_b=m_mFebBlocks.begin();
345 FEBMAPTYPE::const_iterator feb_it_e=m_mFebBlocks.end();
346 FEBMAPTYPE::const_iterator feb_it;
347 for (feb_it=feb_it_b;feb_it!=feb_it_e;++feb_it) {
348 if (feb_it!=feb_it_b) //Not first Feb
350
351 //Add feb data to rod data block
352 m_pRODblock->insert (m_pRODblock->end(),
353 feb_it->second.begin(), feb_it->second.end());
354 } //end for feb_it
355
356 m_mFebBlocks.clear();
357}
358
359int LArRodBlockPhysicsV2::getNextRawData(int& channelNumber, std::vector<short>& samples, uint32_t& gain)
360{
361 LARBSDBG("in LArRodBlockPhysicsV2::getNextRawData.");
362 LARBSDBG("m_RawDataCounter=" << m_RawDataCounter << " m_RawDataIndex="<< m_RawDataIndex);
363 LARBSDBG("m_channelsPerFEB=" << m_channelsPerFEB);
364 if(m_FebBlockSize<=m_iHeadBlockSize) return 0;
366
367 const int flags=(int) LE_getHeader16(RawDataBlkOffset);
368 if (!flags)
369 return 0; //Block not existing
370 if (m_RawDataCounter>=m_channelsPerFEB) //Already beyond maximal number of channels
371 return 0;
372
373 LARBSDBG("Flags="<<flags);
374
375 while (!getBit(m_RawDataFlagsPtr,m_RawDataCounter)) //Look for next filled channel
376 {
378 LARBSDBG("RawDataCounter ist now " << m_RawDataCounter);
379 if (m_RawDataCounter>=m_channelsPerFEB) //No more channel available
380 return 0;
381 }
382 LARBSDBG("Found filled channel at positon " << m_RawDataCounter);
383 //Found next filled channel
384 channelNumber=m_RawDataCounter;
385 //channelNumber=(m_RawDataCounter>>4) + ((m_RawDataCounter&0xf)<<3); //Convert ROD to FEB channel ordering
386 unsigned int nsamples = LE_getHeader16(NGainNSamples) & 0x00FF;
387 LARBSDBG("This run has " << nsamples << " samples");
388 int index = m_RawDataIndex*nsamples;
389 LARBSDBG( "index="<<index);
391 LARBSDBG("In getnextRawData(). index= " << index);
392 gain=3-((m_GainPtr[channelNumber/16] >> (channelNumber%16)*2) & 0x3);
393 if(gain>=CaloGain::LARNGAIN) return 0;
394 for(unsigned int i=0;i<nsamples;i++) {
395 uint16_t x;
396 if((index+i)%2==0)
397 x=m_RawDataPtr[index+i+1];
398 else
399 x=m_RawDataPtr[index+i-1];
400 samples.push_back((short) (x & 0xfff));
401 }
403
404 if (m_rearrangeFirstSample && m_rearrangeFirstSample<samples.size()) //FIXME: Very ugly hack! See explanation in LArRodDecoder.h file
405 {//Change e.g. 3 0 1 2 4 to 0 1 2 3 4
406 short movedSample=samples[0];
407 for (unsigned i=1;i<=m_rearrangeFirstSample;i++)
408 samples[i-1]=samples[i];
409 samples[m_rearrangeFirstSample]=movedSample;
410 }
411
412 return 1;
413}
414
415
416//Sort functions & ordering relation:
417template<class RAWDATA>
418bool LArRodBlockPhysicsV2::operator ()
419 (const RAWDATA* ch1, const RAWDATA* ch2) const
420{
421 HWIdentifier id1 = ch1->channelID();
422 HWIdentifier id2 = ch2->channelID();
423
424 HWIdentifier febId1= m_onlineHelper->feb_Id(id1);
425 HWIdentifier febId2= m_onlineHelper->feb_Id(id2);
426
427 if(febId1 == febId2 ){
428 int cId1 = m_onlineHelper->channel(id1);
429 int cId2 = m_onlineHelper->channel(id2);
430 return FebToRodChannel(cId1) < FebToRodChannel(cId2);
431 }
432
433 return febId1 < febId2 ;
434}
435
436
437void LArRodBlockPhysicsV2::sortDataVector(std::vector<const LArRawChannel*>& vRC)
438{
439 std::sort(vRC.begin(),vRC.end(),*this);
440}
441
442void LArRodBlockPhysicsV2::sortDataVector( std::vector<const LArDigit*>& vDigit)
443{
444 std::sort(vDigit.begin(),vDigit.end(),*this);
445}
446
448{
449 return LE_getHeader16(NGainNSamples)&0xff;
450}
451
453{
454 return LE_getHeader16(NGainNSamples)>>8;
455}
456
457uint32_t LArRodBlockPhysicsV2::getRadd(uint32_t /*adc*/, uint32_t sample) const
458{
459 int index=LE_getHeader16(RawDataBlkOffset)-3+(sample+1)/2;
460 uint32_t x=m_FebBlock[index];
461 x=x&0xffff;
462 return x;
463}
464
465uint16_t LArRodBlockPhysicsV2::getCtrl1(uint32_t /*adc*/) const
466{
468 uint32_t x=m_FebBlock[index];
469 x=x>>16;
470 uint16_t ctrl=x;
471 return ctrl;
472}
473
474uint16_t LArRodBlockPhysicsV2::getCtrl2(uint32_t /*adc*/) const
475{
477 uint32_t x=m_FebBlock[index];
478 x=x&0xffff;
479 uint16_t ctrl=x;
480 return ctrl;
481}
482
483uint16_t LArRodBlockPhysicsV2::getCtrl3(uint32_t /*adc*/) const
484{
486 uint32_t x=m_FebBlock[index];
487 x=x>>16;
488 uint16_t ctrl=x;
489 return ctrl;
490}
491
493{
494 uint32_t x=getHeader32(Status2);
495 return x;
496}
#define endmsg
static Double_t sc
#define LARBSDBG(text)
This class provides decoding/encoding from/to ROD format.
#define x
std::vector< uint32_t > m_LowEnergyBlock
std::vector< uint32_t > m_HighEnergyBlock
std::vector< uint32_t > m_RawDataBlock
static std::string BlockType()
virtual int getNextRawData(int &channelNumber, std::vector< short > &samples, uint32_t &gain)
virtual void setNumberOfSamples(const uint8_t n)
virtual void setNumberOfGains(const uint8_t n)
virtual uint32_t getStatus() const
virtual uint16_t getCtrl2(uint32_t adc) const
virtual uint32_t getNumberOfSamples() const
LArRodBlockPhysicsV2(IMessageSvc *msgSvc)
const uint16_t * m_RawDataPtr
virtual void initializeFragment(std::vector< uint32_t > &fragment)
virtual void setNextEnergy(const int channel, const int32_t energy, const int32_t time, const int32_t quality, const uint32_t gain)
const LArOnlineID * m_onlineHelper
virtual void setRawData(const int channel, const std::vector< short > &samples, const uint32_t gain)
virtual uint32_t getNumberOfGains() const
virtual uint16_t getCtrl1(uint32_t adc) const
const uint32_t * m_RawDataFlagsPtr
virtual uint32_t getRadd(uint32_t adc, uint32_t sample) const
virtual void sortDataVector(std::vector< const LArRawChannel * > &)
static const uint32_t m_DummyBitMap[4]
virtual uint16_t getCtrl3(uint32_t adc) const
int FebToRodChannel(int ch) const
virtual void initializeFEB(const uint32_t id)
int getBit(const uint32_t *const p, const unsigned chan) const
void setHeader32(const unsigned n, const uint32_t w)
uint16_t LE_getVectorHeader16(const unsigned n) const
void LE_setHeader16(const unsigned n, const uint16_t w)
uint32_t getHeader32(const unsigned n) const
void setBit(uint32_t *const p, const unsigned chan)
std::vector< uint32_t > * m_pRODblock
LArRodBlockStructure(IMessageSvc *msgSvc, const std::string &blockType)
std::vector< uint32_t > * m_vFragment
uint16_t LE_getHeader16(const unsigned n) const
uint32_t getNumberOfWords() const
@ LARNGAIN
Definition CaloGain.h:19
Definition index.py:1
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
setEventNumber uint32_t