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
77
86
87//For reading (to speed up the process)
89{//Set pointers to data blocks (pesuming, they exist)
91 {
93 {
95 m_RawDataPtr=reinterpret_cast<const uint16_t*>(m_RawDataFlagsPtr+m_NFlaggingWords);
96 m_GainPtr=reinterpret_cast<const uint32_t*>(m_RawDataFlagsPtr-2*m_NFlaggingWords);
97 }
98 else
99 {
101 m_RawDataPtr=reinterpret_cast<const uint16_t*>(m_RawDataFlagsPtr);
102 m_GainPtr=reinterpret_cast<const uint32_t*>(m_DummyBitMap);
103 }
105 {
107 m_LowEPtr=reinterpret_cast<const int16_t*>(m_FlagPtr+m_NFlaggingWords);
108 }
109 else
110 { //Bugfix, 9.8.2004, WL: Set pointer to dummy map to read FEB with only high energy block
112 m_LowEPtr=reinterpret_cast<const int16_t*>(m_FlagPtr);
113 }
115 m_HighEPtr=reinterpret_cast<const int32_t*>(m_FebBlock)+LE_getHeader16(HighEBlkOffset);
116 else
117 m_HighEPtr=NULL;
118 }
119 else
120 {
121 m_RawDataPtr=NULL;
122 m_RawDataFlagsPtr=NULL;
123 m_GainPtr=NULL;
124 m_FlagPtr=NULL;
125 m_LowEPtr=NULL;
126 m_HighEPtr=NULL;
127 }
128 return true;
129}
130
131
133{ uint16_t oldword=LE_getVectorHeader16(NGainNSamples);
134 LE_setHeader16(NGainNSamples,(oldword & 0xFF00) | n);
135}
136
138{ uint16_t oldword=LE_getVectorHeader16(NGainNSamples);
139 LE_setHeader16(NGainNSamples,(oldword & 0x00FF) | (n<<8));
140}
141
142
143void LArRodBlockPhysicsV2::setNextEnergy(const int channel, const int32_t energy,
144 const int32_t time, const int32_t quality, const uint32_t gain) {
145 int rcNb=FebToRodChannel(channel);
146 //rcNb ist supposed to equal or bigger than m_EIndex.
147 //In the latter case, we fill up the missing channels with zero
148 if (rcNb<m_EIndex) {
149 m_logstr << MSG::ERROR << "LArRODBlockStructure Error: Internal error. Channels not ordered correctly. rcNb=" << rcNb
150 << " m_EIndex=" << m_EIndex << endmsg;
151 return;
152 }
153 //Fill up missing channels with zeros:
154 while (m_EIndex<rcNb)
155 setNextEnergy(0,0,-1,0);
156 //Add data...
157 setNextEnergy(energy,time,quality,gain);
158 return;
159}
160//Private function, expects channel number is rod-style ordering
161void LArRodBlockPhysicsV2::setNextEnergy(const int32_t energy, const int32_t time, const int32_t quality, const uint32_t gain)
162{
163 if (m_EIndex>=m_channelsPerFEB) //Use m_EIndex to count total number of channels
164 {m_logstr << MSG::ERROR << "LArRodBlockStructure Error: Attempt to write Energy for channel "
165 << m_EIndex << " channels into a FEB!" <<endmsg;
166 return;
167 }
168 LARBSDBG("LArRodBlockStructure: Setting Energy for channel " << m_EIndex << ". E=" << energy);
169 if (quality<0 && energy<0x7FFE && gain==0) { //Write into Low Energy block
170 m_LowEIndex++; //Use m_LowEIndex to count the channels in the Low Energy block
171 ShortLong twoValues{};
172 twoValues.s[0]=0;
173 twoValues.s[1]=0;
174 if (m_LowEIndex%2==1) { //This is an odd number, simply add data at the bottom of the block
175 twoValues.s[0]=(int16_t)energy;
176 }
177 else { //Even number: Merging with previous block
178 uint32_t oneValue=m_LowEnergyBlock[m_LowEnergyBlock.size()-1]; //Take last element of vector
179 m_LowEnergyBlock.pop_back();
180 int16_t* valptr=reinterpret_cast<int16_t*>(&oneValue);
181 twoValues.s[0]=valptr[0];
182 twoValues.s[1]=(int16_t)energy;
183 }
184 LARBSDBG("Writing words: val0= " << twoValues.s[0] << " val1= " << twoValues.s[1]);
185 m_LowEnergyBlock.push_back(twoValues.l);
186 LARBSDBG("Writing Raw data to Low E block. E=" << energy);
187 }
188 else //Write into High Energy block
190 m_HighEnergyBlock.push_back(energy);
191 uint32_t t_sign;
192 uint32_t abs_time;
193 if (time<0)
194 t_sign=1;
195 else
196 t_sign=0;
197 abs_time=abs(time);
198 if (abs_time>0x1fff)
199 abs_time=0x1fff;
200 uint32_t gtQ = (gain << 30) | (t_sign<<29) | ((abs_time & 0x1fff)<<16) | (0xffff & quality);
201 m_HighEnergyBlock.push_back(gtQ);
202 LARBSDBG("Writing Raw data to High E block. E=" << energy << " Q=" << quality);
203 }
204 m_EIndex++;
205}
206
207
208void LArRodBlockPhysicsV2::setRawData(const int channel, const std::vector<short>& samples, const uint32_t gain) {
209 //Convert Feb to Rod Channel Number:
210 int rcNb=FebToRodChannel(channel);
211 if (rcNb>=m_channelsPerFEB)
212 {m_logstr << MSG::ERROR << "Attempt to write Energy for channel " << rcNb << " channels into a FEB!" << endmsg;
213 return;
214 }
215 unsigned int nsamples = LE_getVectorHeader16(NGainNSamples) & 0x00FF;
216 if(samples.size() != nsamples) {
217 m_logstr << MSG::ERROR << "Number of samples mismatch!\n";
218 m_logstr << " nsamples =" << nsamples;
219 m_logstr << " samples.size() =" << samples.size() << endmsg;
220 std::abort();
221 }
222
223 setBit(&m_RawDataBlock[0],rcNb);
224 //Samples have 12 bit and are shifted to the left by 2 bits.
225 // odd samples in high bits, even samples in low bits
226 if((nsamples/2)*2!=nsamples) { //odd number of samples - gain is alone
227 m_RawDataBlock.push_back((gain<<30) | samples[0]<<2);
228 for (unsigned int i=1;i<nsamples;i+=2)
229 m_RawDataBlock.push_back((samples[i+1]<<18) | samples[i]<<2);
230 }
231 else { //even number of samples - gain is packed with sample 0
232 m_RawDataBlock.push_back((gain<<30) | (samples[1]<<18) | samples[0]<<2);
233 for (unsigned int i=2;i<nsamples;i+=2)
234 m_RawDataBlock.push_back((samples[i+1]<<18) | samples[i]<<2);
235 }
236}
237
238
239//For writing: takes existing Fragment and splits it into Feb-Blocks
240void LArRodBlockPhysicsV2::initializeFragment(std::vector<uint32_t>& fragment)
241{
242 m_pRODblock=&fragment; //remember pointer to fragment
243 if (fragment.size()>m_iHeadBlockSize) { //Got filled fragment
244 unsigned int sizeRead=0;
245 //Store existing data in the FEB-Map
246 while (sizeRead<fragment.size()) {
247 std::vector<uint32_t>::iterator FebIter;
248 FebIter=fragment.begin()+sizeRead; //Store pointer to current Feb-Header
249 m_FebBlock=&(*FebIter); //Set m_FebBlock in order to use getHeader-functions.
250 uint32_t currFEBid=getHeader32(FEBID); //Get this FEB-ID
251 uint16_t currFebSize=getNumberOfWords(); //Size of this FEB-Block
252 if (FebIter+currFebSize>fragment.end()) {
253 fragment.clear(); //Clear existing vector
254 m_logstr << MSG::ERROR << "Got inconsistent ROD-Fragment!" << endmsg;
255 return;
256 }
257 m_mFebBlocks[currFEBid].assign(FebIter,FebIter+currFebSize); //Copy data from ROD-fragment into FEB-Block
258 sizeRead+=currFebSize+m_MiddleHeaderSize;//6 is the middle header size
259 LARBSDBG("Found FEB-id " << currFEBid << " in existing ROD-Fragment");
260 } // end while
261 }
262 fragment.clear(); //Clear existing vector
263 return;
264}
265
266//For writing: Initalizes a single FEB-Block
269 if (m_vFragment->size()<m_iHeadBlockSize) //Got empty or spoiled fragment
270 {m_vFragment->resize(m_iHeadBlockSize,0); //Initialize FEB-Header
271 setHeader32(FEBID,id); //Set Feb ID
272 }
273
277}
278
280{
281//Complete non-complete Energy block
283 setNextEnergy(0,0,-1,0);//E=0,t=0,q=-1,G=0
284 // Energies
285 unsigned int n;
286 uint16_t BlockOffset;
287 //Low energy block....
288 n = m_LowEnergyBlock.size();
290 //Check if Low Energy Block exists and is not yet part of the fragment
291 LARBSDBG("Checking Low Energy Block n=" << n << "BlockOffset=" << BlockOffset);
292 if (n>m_NFlaggingWords && !BlockOffset)
294 for (unsigned i=0;i<n;i++)
295 m_vFragment->push_back(m_LowEnergyBlock[i]);
296 }
297 //High energy block...
298 n = m_HighEnergyBlock.size();
300 LARBSDBG("Checking High Energy Block n=" << n << "BlockOffset=" << BlockOffset);
301 //Check if High Energy-Block exists and is not yet part of the fragment
302 if (n && !BlockOffset)
304 for(unsigned int i=0;i<n;i++)
305 m_vFragment->push_back(m_HighEnergyBlock[i]);
306 }
307
308 // Raw data
309 LARBSDBG("Checking Raw Data Block");
310 n = m_RawDataBlock.size();
312 LARBSDBG("Checking Raw Data Block. n=" << n << "BlockOffset=" << BlockOffset);
313 //Check if Raw Data block exists and is not yet part of the fragment
314 if (n>m_NFlaggingWords && !BlockOffset)
316 for(unsigned int i=0;i<n;i++)
317 m_vFragment->push_back(m_RawDataBlock[i]);
318 }
320 LARBSDBG("Offsets:" << std::endl
321 << "Raw Data: " << LE_getVectorHeader16(RawDataBlkOffset) << std::endl
322 <<"Low Energy: " << LE_getVectorHeader16(LowEBlkOffset)<< std::endl
323 << "High Energy: " << LE_getVectorHeader16(HighEBlkOffset)<< std::endl
324 << "Energy-index:" << m_EIndex << std::endl
325 << "Filled channels: " << m_ECounter << std::endl);
326 clearBlocks();
327 return;
328}
329
330
332{
333 FEBMAPTYPE::const_iterator feb_it_b=m_mFebBlocks.begin();
334 FEBMAPTYPE::const_iterator feb_it_e=m_mFebBlocks.end();
335 FEBMAPTYPE::const_iterator feb_it;
336 for (feb_it=feb_it_b;feb_it!=feb_it_e;++feb_it) {
337 if (feb_it!=feb_it_b) //Not first Feb
339
340 //Add feb data to rod data block
341 m_pRODblock->insert (m_pRODblock->end(),
342 feb_it->second.begin(), feb_it->second.end());
343 } //end for feb_it
344
345 m_mFebBlocks.clear();
346 return;
347}
348
349int LArRodBlockPhysicsV2::getNextRawData(int& channelNumber, std::vector<short>& samples, uint32_t& gain)
350{
351 LARBSDBG("in LArRodBlockPhysicsV2::getNextRawData.");
352 LARBSDBG("m_RawDataCounter=" << m_RawDataCounter << " m_RawDataIndex="<< m_RawDataIndex);
353 LARBSDBG("m_channelsPerFEB=" << m_channelsPerFEB);
354 if(m_FebBlockSize<=m_iHeadBlockSize) return 0;
356
357 const int flags=(int) LE_getHeader16(RawDataBlkOffset);
358 if (!flags)
359 return 0; //Block not existing
360 if (m_RawDataCounter>=m_channelsPerFEB) //Already beyond maximal number of channels
361 return 0;
362
363 LARBSDBG("Flags="<<flags);
364
365 while (!getBit(m_RawDataFlagsPtr,m_RawDataCounter)) //Look for next filled channel
367 LARBSDBG("RawDataCounter ist now " << m_RawDataCounter);
368 if (m_RawDataCounter>=m_channelsPerFEB) //No more channel available
369 return 0;
370 }
371 LARBSDBG("Found filled channel at positon " << m_RawDataCounter);
372 //Found next filled channel
373 channelNumber=m_RawDataCounter;
374 //channelNumber=(m_RawDataCounter>>4) + ((m_RawDataCounter&0xf)<<3); //Convert ROD to FEB channel ordering
375 unsigned int nsamples = LE_getHeader16(NGainNSamples) & 0x00FF;
376 LARBSDBG("This run has " << nsamples << " samples");
377 int index = m_RawDataIndex*nsamples;
378 LARBSDBG( "index="<<index);
380 LARBSDBG("In getnextRawData(). index= " << index);
381 gain=3-((m_GainPtr[channelNumber/16] >> (channelNumber%16)*2) & 0x3);
382 if(gain>=CaloGain::LARNGAIN) return 0;
383 for(unsigned int i=0;i<nsamples;i++) {
384 uint16_t x;
385 if((index+i)%2==0)
386 x=m_RawDataPtr[index+i+1];
387 else
388 x=m_RawDataPtr[index+i-1];
389 samples.push_back((short) (x & 0xfff));
390 }
392
393 if (m_rearrangeFirstSample && m_rearrangeFirstSample<samples.size()) //FIXME: Very ugly hack! See explanation in LArRodDecoder.h file
394 {//Change e.g. 3 0 1 2 4 to 0 1 2 3 4
395 short movedSample=samples[0];
396 for (unsigned i=1;i<=m_rearrangeFirstSample;i++)
397 samples[i-1]=samples[i];
398 samples[m_rearrangeFirstSample]=movedSample;
399 }
400
401 return 1;
402}
403
404
405//Sort functions & ordering relation:
406template<class RAWDATA>
407bool LArRodBlockPhysicsV2::operator ()
408 (const RAWDATA* ch1, const RAWDATA* ch2) const
409{
410 HWIdentifier id1 = ch1->channelID();
411 HWIdentifier id2 = ch2->channelID();
412
413 HWIdentifier febId1= m_onlineHelper->feb_Id(id1);
414 HWIdentifier febId2= m_onlineHelper->feb_Id(id2);
415
416 if(febId1 == febId2 ){
417 int cId1 = m_onlineHelper->channel(id1);
418 int cId2 = m_onlineHelper->channel(id2);
419 return FebToRodChannel(cId1) < FebToRodChannel(cId2);
420 }
421
422 return febId1 < febId2 ;
423}
424
425
426void LArRodBlockPhysicsV2::sortDataVector(std::vector<const LArRawChannel*>& vRC)
427{std::sort(vRC.begin(),vRC.end(),*this);}
428
429void LArRodBlockPhysicsV2::sortDataVector( std::vector<const LArDigit*>& vDigit)
430{std::sort(vDigit.begin(),vDigit.end(),*this);
431}
432
434{
435 return LE_getHeader16(NGainNSamples)&0xff;
436}
437
439{
440 return LE_getHeader16(NGainNSamples)>>8;
441}
442
443uint32_t LArRodBlockPhysicsV2::getRadd(uint32_t /*adc*/, uint32_t sample) const
444{
445 int index=LE_getHeader16(RawDataBlkOffset)-3+(sample+1)/2;
446 uint32_t x=m_FebBlock[index];
447 x=x&0xffff;
448 return x;
449}
450
451uint16_t LArRodBlockPhysicsV2::getCtrl1(uint32_t /*adc*/) const
452{
454 uint32_t x=m_FebBlock[index];
455 x=x>>16;
456 uint16_t ctrl=x;
457 return ctrl;
458}
459
460uint16_t LArRodBlockPhysicsV2::getCtrl2(uint32_t /*adc*/) const
461{
463 uint32_t x=m_FebBlock[index];
464 x=x&0xffff;
465 uint16_t ctrl=x;
466 return ctrl;
467}
468
469uint16_t LArRodBlockPhysicsV2::getCtrl3(uint32_t /*adc*/) const
470{
472 uint32_t x=m_FebBlock[index];
473 x=x>>16;
474 uint16_t ctrl=x;
475 return ctrl;
476}
477
479{
480 uint32_t x=getHeader32(Status2);
481 return x;
482}
#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