ATLAS Offline Software
Loading...
Searching...
No Matches
LArRodBlockPhysicsV0.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Implementation of the LArRODBlockStructure_3 class
6// This version contains LArRawChannels (=E,t,Q)
7// and LArDigits (=5 time samples)
8// See .h file for more details.
9
14#include "GaudiKernel/Bootstrap.h"
15#include "GaudiKernel/ISvcLocator.h"
16#include "GaudiKernel/IToolSvc.h"
17#include <stdlib.h>
18#include <cstdio>
19#include <iostream>
20
21#ifdef LARBSDBGOUTPUT
22#define LARBSDBG(text) m_logstr<<MSG::DEBUG<<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
34const uint32_t LArRodBlockPhysicsV0::m_DummyBitMap[4]={0xffffffff,0xffffffff,0xffffffff,0xffffffff};
35
38{
39 // retrieve onlineHelper
40 const LArOnlineID* online_id;
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(online_id, "LArOnlineID");
47 if (sc.isFailure()) {
48 m_logstr << MSG::FATAL << "Could not get LArOnlineID helper !" << endmsg;
49 std::abort();
50 }
51 else {
52 m_onlineHelper=online_id;
53 m_logstr << MSG::DEBUG << " Found the LArOnlineID helper. " << endmsg;
54 }
55
56 m_iHeadBlockSize=endtag/2; // The implicit cast rounds down to the right size
59 m_vFragment=NULL;
60 m_FebBlock=NULL;
61 m_pRODblock=NULL;
62 m_FlagPtr=NULL;
63 m_HighEPtr=NULL;
64 m_LowEPtr=NULL;
65}
66
67// clear temporary block vectors
74
84
85//For reading (to speed up the process)
87{ //Set pointers to data blocks (presuming, they exist)
89 {
91 {
93 m_LowEPtr=reinterpret_cast<const int16_t*>(m_FlagPtr+m_NFlaggingWords);
94 }
95 else
96 {
97 //Bugfix, 9.8.2004, WL: Set pointer to dummy map to read FEB with only high energy block
99 m_LowEPtr=reinterpret_cast<const int16_t*>(m_FlagPtr);
100 }
103 else
104 m_HighEPtr=NULL;
105 }
106 else
107 {
108 m_FlagPtr=NULL;
109 m_LowEPtr=NULL;
110 m_HighEPtr=NULL;
111 }
112 return true;
113}
114
116{
117 uint16_t oldword=LE_getVectorHeader16(NGainNSamples);
118 LE_setHeader16(NGainNSamples,(oldword & 0xFF00) | n);
119}
120
122{
123 uint16_t oldword=LE_getVectorHeader16(NGainNSamples);
124 LE_setHeader16(NGainNSamples,(oldword & 0x00FF) | (n<<8));
125}
126
127
128void LArRodBlockPhysicsV0::setNextEnergy(const int channel, const int32_t energy,
129 const int32_t time, const int32_t quality, const uint32_t gain) {
130 int rcNb=FebToRodChannel(channel);
131 //rcNb ist supposed to equal or bigger than m_EIndex.
132 //In the latter case, we fill up the missing channels with zero
133 if (rcNb<m_EIndex) {
134 m_logstr << MSG::ERROR << "LArRODBlockStructure Error: Internal error. Channels not ordered correctly. rcNb=" << rcNb
135 << " m_EIndex=" << m_EIndex << endmsg;
136 return;
137 }
138 //Fill up missing channels with zeros:
139 while (m_EIndex<rcNb)
140 setNextEnergy(0,0,-1,0);
141 //Add data...
142 setNextEnergy(energy,time,quality,gain);
143 return;
144}
145
146
147//Private function, expects channel number is rod-style ordering
148void LArRodBlockPhysicsV0::setNextEnergy(const int32_t energy, const int32_t time, const int32_t quality, const uint32_t gain)
149{
150 if (m_EIndex>=m_channelsPerFEB) //Use m_EIndex to count total number of channels
151 {
152 m_logstr << MSG::ERROR << "LArRodBlockStructure Error: Attempt to write Energy for channel "
153 << m_EIndex << " channels into a FEB!" <<endmsg;
154 return;
155 }
156 LARBSDBG("LArRodBlockStructure: Setting Energy for channel " << m_EIndex << ". E=" << energy);
157 if (quality<0 && energy<0x7FFE && gain==0) { //Write into Low Energy block
158 m_LowEIndex++; //Use m_LowEIndex to count the channels in the Low Energy block
159 ShortLong twoValues{};
160 twoValues.s[0]=0;
161 twoValues.s[1]=0;
162 if (m_LowEIndex%2==1) { //This is an odd number, simply add data at the bottom of the block
163 twoValues.s[0]=(int16_t)energy;
164 }
165 else { //Even number: Merging with previous block
166 uint32_t oneValue=m_LowEnergyBlock[m_LowEnergyBlock.size()-1]; //Take last element of vector
167 m_LowEnergyBlock.pop_back();
168 int16_t* valptr=reinterpret_cast<int16_t*>(&oneValue);
169 twoValues.s[0]=valptr[0];
170 twoValues.s[1]=(int16_t)energy;
171 }
172 LARBSDBG("Writing words: val0= " << twoValues.s[0] << " val1= " << twoValues.s[1]);
173 m_LowEnergyBlock.push_back(twoValues.l);
174 LARBSDBG("Writing Raw data to Low E block. E=" << energy);
175 }
176 else //Write into High Energy block
177 {
179 m_HighEnergyBlock.push_back(*((uint32_t*)(&energy)));
180 uint32_t t_sign;
181 uint32_t abs_time;
182 if (time<0)
183 t_sign=1;
184 else
185 t_sign=0;
186 abs_time=abs(time);
187 if (abs_time>0x1fff)
188 abs_time=0x1fff;
189 uint32_t gtQ = (gain << 30) | (t_sign<<29) | ((abs_time & 0x1fff)<<16) | (0xffff & quality);
190 m_HighEnergyBlock.push_back(gtQ);
191 LARBSDBG("Writing Raw data to High E block. E=" << energy << " Q=" << quality);
192 }
193 m_EIndex++;
194}
195
196
197void LArRodBlockPhysicsV0::setRawData(const int channel, const std::vector<short>& samples, const uint32_t gain) {
198 //Convert Feb to Rod Channel Number:
199 int rcNb=FebToRodChannel(channel);
200 if (rcNb>=m_channelsPerFEB)
201 {
202 m_logstr << MSG::ERROR << "Attempt to write Energy for channel " << rcNb << " channels into a FEB!" << endmsg;
203 return;
204 }
205 unsigned int nsamples = LE_getVectorHeader16(NGainNSamples) & 0x00FF;
206 if(samples.size() != nsamples) {
207 m_logstr << MSG::ERROR << "Number of samples mismatch!\n";
208 m_logstr << " nsamples =" << nsamples;
209 m_logstr << " samples.size() =" << samples.size() << endmsg;
210 std::abort();
211 }
212
213 setBit(&m_RawDataBlock[0],rcNb);
214 //Samples have 12 bit and are shifted to the left by 2 bits.
215 // odd samples in high bits, even samples in low bits
216 if((nsamples/2)*2!=nsamples) { //odd number of samples - gain is alone
217 m_RawDataBlock.push_back((gain<<30) | samples[0]<<2);
218 for (unsigned int i=1;i<nsamples;i+=2)
219 m_RawDataBlock.push_back((samples[i+1]<<18) | samples[i]<<2);
220 }
221 else { //even number of samples - gain is packed with sample 0
222 m_RawDataBlock.push_back((gain<<30) | (samples[1]<<18) | samples[0]<<2);
223 for (unsigned int i=2;i<nsamples;i+=2)
224 m_RawDataBlock.push_back((samples[i+1]<<18) | samples[i]<<2);
225 }
226}
227
228
229//For writing: takes existing Fragment and splits it into Feb-Blocks
230void LArRodBlockPhysicsV0::initializeFragment(std::vector<uint32_t>& fragment)
231{
232 m_pRODblock=&fragment; //remember pointer to fragment
233 if (fragment.size()>m_iHeadBlockSize) { //Got filled fragment
234 unsigned int sizeRead=0;
235 //Store existing data in the FEB-Map
236 while (sizeRead<fragment.size()) {
237 std::vector<uint32_t>::iterator FebIter;
238 FebIter=fragment.begin()+sizeRead; //Store pointer to current Feb-Header
239 m_FebBlock=&(*FebIter); //Set m_FebBlock in order to use getHeader-functions.
240 uint32_t currFEBid=getHeader32(FEBID); //Get this FEB-ID
241 uint16_t currFebSize=getNumberOfWords(); //Size of this FEB-Block
242 if (FebIter+currFebSize>fragment.end()) {
243 fragment.clear(); //Clear existing vector
244 m_logstr << MSG::ERROR << "Got inconsistent ROD-Fragment!" << endmsg;
245 return;
246 }
247 m_mFebBlocks[currFEBid].assign(FebIter,FebIter+currFebSize); //Copy data from ROD-fragment into FEB-Block
248 sizeRead+=currFebSize+m_MiddleHeaderSize;//6 is the middle header size
249 LARBSDBG("Found FEB-id " << currFEBid << " in existing ROD-Fragment");
250 } // end while
251 }
252 fragment.clear(); //Clear existing vector
253 return;
254}
255
256//For writing: Initalizes a single FEB-Block
258{
260 if (m_vFragment->size()<m_iHeadBlockSize) //Got empty or spoiled fragment
261 {m_vFragment->resize(m_iHeadBlockSize,0); //Initialize FEB-Header
262 setHeader32(FEBID,id); //Set Feb ID
263 }
264
268}
269
271{
272 //Complete non-complete Energy block
274 setNextEnergy(0,0,-1,0);//E=0,t=0,q=-1,G=0
275 // Energies
276 unsigned int n;
277 uint16_t BlockOffset;
278 //Low energy block....
279 n = m_LowEnergyBlock.size();
281 //Check if Low Energy Block exists and is not yet part of the fragment
282 LARBSDBG("Checking Low Energy Block n=" << n << "BlockOffset=" << BlockOffset);
283 if (n>m_NFlaggingWords && !BlockOffset)
284 {
286 for (unsigned i=0;i<n;i++)
287 m_vFragment->push_back(m_LowEnergyBlock[i]);
288 }
289 //High energy block...
290 n = m_HighEnergyBlock.size();
292 LARBSDBG("Checking High Energy Block n=" << n << "BlockOffset=" << BlockOffset);
293 //Check if High Energy-Block exists and is not yet part of the fragment
294 if (n && !BlockOffset)
295 {
297 for(unsigned int i=0;i<n;i++)
298 m_vFragment->push_back(m_HighEnergyBlock[i]);
299 }
300
301 // Raw data
302 LARBSDBG("Checking Raw Data Block");
303 n = m_RawDataBlock.size();
305 LARBSDBG("Checking Raw Data Block. n=" << n << "BlockOffset=" << BlockOffset);
306 //Check if Raw Data block exists and is not yet part of the fragment
307 if (n>m_NFlaggingWords && !BlockOffset)
308 {
310 for(unsigned int i=0;i<n;i++)
311 m_vFragment->push_back(m_RawDataBlock[i]);
312 }
314 LARBSDBG("Offsets:" << std::endl
315 << "Raw Data: " << LE_getVectorHeader16(RawDataBlkOffset) << std::endl
316 <<"Low Energy: " << LE_getVectorHeader16(LowEBlkOffset)<< std::endl
317 << "High Energy: " << LE_getVectorHeader16(HighEBlkOffset)<< std::endl
318 << "Energy-index:" << m_EIndex << std::endl
319 << "Filled channels: " << m_ECounter << std::endl);
320 clearBlocks();
321}
322
323
325{
326 FEBMAPTYPE::const_iterator feb_it_b=m_mFebBlocks.begin();
327 FEBMAPTYPE::const_iterator feb_it_e=m_mFebBlocks.end();
328 FEBMAPTYPE::const_iterator feb_it;
329 for (feb_it=feb_it_b;feb_it!=feb_it_e;++feb_it) {
330 if (feb_it!=feb_it_b) //Not first Feb
332
333 //Add feb data to rod data block
334 m_pRODblock->insert (m_pRODblock->end(),
335 feb_it->second.begin(), feb_it->second.end());
336 } //end for feb_it
337
338 m_mFebBlocks.clear();
339}
340
341int LArRodBlockPhysicsV0::getNextRawData(int& channelNumber, std::vector<short>& samples, uint32_t& gain)
342{
343 LARBSDBG("in LArRodBlockPhysicsV0::getNextRawData.");
344 LARBSDBG("m_RawDataCounter=" << m_RawDataCounter << " m_RawDataIndex="<< m_RawDataIndex);
345 LARBSDBG("m_channelsPerFEB=" << m_channelsPerFEB);
346 const int flags=(int) LE_getHeader16(RawDataBlkOffset);
347 if (!flags)
348 return 0; //Block not existing
349 if (m_RawDataCounter>=m_channelsPerFEB) //Already beyond maximal number of channels
350 return 0;
351
352 LARBSDBG("Flags="<<flags);
353 while (!getBit(m_FebBlock+flags,m_RawDataCounter)) //Look for next filled channel
354 {
356 LARBSDBG("RawDataCounter ist now " << m_RawDataCounter);
357 if (m_RawDataCounter>=m_channelsPerFEB) //No more channel availible
358 return 0;
359 }
360 LARBSDBG("Found filled channel at positon " << m_RawDataCounter);
361 //Found next filled channel
362 channelNumber=(m_RawDataCounter>>4) + ((m_RawDataCounter&0xf)<<3); //Convert ROD to FEB channel ordering
363 unsigned int nsamples = LE_getHeader16(NGainNSamples) & 0x00FF;
364 LARBSDBG("This run has " << nsamples << " samples");
365 int index = flags+m_NFlaggingWords+m_RawDataIndex*((int) (nsamples+1)/2);
366 LARBSDBG( "index="<<index);
368 LARBSDBG("In getnextRawData(). index= " << index);
369 if((nsamples/2)*2!=nsamples) { //odd number of samples
370 const uint32_t& x = m_FebBlock[index];
371 gain = x >> 30;
372 samples.push_back((short) (x>>2 & 0xfff));
373 for(unsigned int i=1;i<=(nsamples-1)/2;i++) {
374 const uint32_t& x = m_FebBlock[index+i];
375 samples.push_back((short) (x>>2 & 0xfff));
376 samples.push_back((short) (x>>18));
377 }
378 }
379 else { //even number of samples
380 const uint32_t& x = m_FebBlock[index];
381 gain = x >> 30;
382 samples.push_back((short) (x>>2 & 0xfff));
383
384 samples.push_back((short) ((x>>18) & 0xfff));
385
386 for (unsigned int i=1;i<nsamples/2;i++) {
387 const uint32_t& x = m_FebBlock[index+i];
388 samples.push_back((short) (x>>2 & 0xfff));
389 samples.push_back((short) (x >> 18));
390 }
391 } //end even numer of sample
393 return 1;
394}
395
396
397//Sort functions & ordering relation:
398template<class RAWDATA>
399bool LArRodBlockPhysicsV0::operator ()
400 (const RAWDATA* ch1, const RAWDATA* ch2) const
401{
402 HWIdentifier id1 = ch1->channelID();
403 HWIdentifier id2 = ch2->channelID();
404
405 HWIdentifier febId1= m_onlineHelper->feb_Id(id1);
406 HWIdentifier febId2= m_onlineHelper->feb_Id(id2);
407
408 if(febId1 == febId2 ){
409 int cId1 = m_onlineHelper->channel(id1);
410 int cId2 = m_onlineHelper->channel(id2);
411 return FebToRodChannel(cId1) < FebToRodChannel(cId2);
412 }
413
414 return febId1 < febId2 ;
415}
416
417
418void LArRodBlockPhysicsV0::sortDataVector(std::vector<const LArRawChannel*>& vRC)
419{
420 std::sort(vRC.begin(),vRC.end(),*this);
421}
422
423void LArRodBlockPhysicsV0::sortDataVector( std::vector<const LArDigit*>& vDigit)
424{
425 std::sort(vDigit.begin(),vDigit.end(),*this);
426}
#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_RawDataBlock
virtual int getNextRawData(int &channelNumber, std::vector< short > &samples, uint32_t &gain)
virtual void setRawData(const int channel, const std::vector< short > &samples, const uint32_t gain)
LArRodBlockPhysicsV0(IMessageSvc *msgSvc)
virtual void initializeFEB(const uint32_t id)
virtual void setNumberOfSamples(const uint8_t n)
int FebToRodChannel(int ch) const
static std::string BlockType()
static const uint32_t m_DummyBitMap[4]
virtual void setNextEnergy(const int channel, const int32_t energy, const int32_t time, const int32_t quality, const uint32_t gain)
virtual void sortDataVector(std::vector< const LArRawChannel * > &)
const LArOnlineID * m_onlineHelper
virtual void initializeFragment(std::vector< uint32_t > &fragment)
virtual void setNumberOfGains(const uint8_t n)
std::vector< uint32_t > m_LowEnergyBlock
std::vector< uint32_t > m_HighEnergyBlock
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
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