ATLAS Offline Software
Loading...
Searching...
No Matches
LArRodDecoder.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 LArRodDecoder class
7#include "GaudiKernel/TypeNameString.h"
8#include "GaudiKernel/MsgStream.h"
9#include "GaudiKernel/Bootstrap.h"
10#include "GaudiKernel/ISvcLocator.h"
11#include "GaudiKernel/IToolSvc.h"
12
16#include <algorithm>
17#include <fstream>
18
22
23static const InterfaceID IID_ILArRodDecoder
24 ("LArRodDecoder", 1, 0);
25
26LArRodDecoder::LArRodDecoder ( const std::string& type, const std::string& name,const IInterface* parent )
27 : AthAlgTool(type,name,parent),
29 m_readtdc(false),
31 {
32 declareInterface< LArRodDecoder >( this );
33 declareProperty("IgnoreCheckFEBs",m_IgnoreCheckFEBs);
34 declareProperty("CellCorrections",m_LArCellCorrNames );
35 declareProperty("LArCellEthreshold",m_LArCellEthreshold );
36 declareProperty("ReadTDC",m_readtdc);
37 declareProperty("DelayScale",m_delayScale=(25./240.)*CLHEP::ns);
38 declareProperty("FebExchange", m_febExchange=0); //FIXME: Very ugly hack! See explanation in .h file
39 declareProperty("FebId1", m_febId1=0);
40 declareProperty("FebId2", m_febId2=0);
41 declareProperty("FirstSample", m_firstSample=0); //FIXME: Very ugly hack! See explanation in .h file
42
43 declareProperty("BEPreselection",m_vBEPreselection,"For channel-selection: Barrel=0, Endcap=1");
44 declareProperty("PosNegPreselection",m_vPosNegPreselection,"For channel-selection: C-Side:0, A-Side: 1");
45 declareProperty("FTNumPreselection",m_vFTPreselection,"For channel-selection: Feedthrough numbers (e.g. 0 - 31 for barrel)");
46 declareProperty("MultiDSPMode", m_MultiDSPMode=false);
47 declareProperty("CheckSum", m_CheckSum=false);
48 declareProperty("StatusMask", m_StatusMask=0x00000212);
49 declareProperty("RequiredPhysicsNSamples", m_requiredPhysicsNSamples = 0);
50}
51
52// destructor
56
57const InterfaceID& LArRodDecoder::interfaceID( )
58{ return IID_ILArRodDecoder; }
59
60StatusCode
61LArRodDecoder::initialize ATLAS_NOT_THREAD_SAFE ()
62{
63 // Before anything, access message service
64 m_StatusNMask = !m_StatusMask;
65
66 StatusCode sc = detStore()->retrieve(m_onlineHelper, "LArOnlineID");
67 if (sc.isFailure()) {
68 ATH_MSG_ERROR ("Could not get LArOnlineID helper !");
69 return sc;
70 }
71
72 ATH_CHECK( m_evt.initialize() );
73
74 std::vector<std::string>::const_iterator it = m_LArCellCorrNames.begin();
75 std::vector<std::string>::const_iterator it_end = m_LArCellCorrNames.end();
76 for(; it!=it_end;++it)
77 {
78 IAlgTool* tool;
79 CaloCellCorrection* corr;
80 Gaudi::Utils::TypeNameString li(*it);
81 if((toolSvc()->retrieveTool(li.type(), li.name(), tool)).isFailure() )
82 {
83 ATH_MSG_ERROR(" Can't get AlgTool for CaloCellCorrection ");
84 return StatusCode::FAILURE;
85 }
86
87 corr = dynamic_cast<CaloCellCorrection*> (tool);
88 if(!corr )
89 {
90 ATH_MSG_ERROR(" Can't d-cast to CaloCellCorrection* ");
91 return StatusCode::FAILURE;
92 }
93 m_LArCellCorrTools.push_back(corr);
94 }
95
96 //Build list of preselected Feedthroughs
97 if (m_vBEPreselection.size() && m_vPosNegPreselection.size() && m_vFTPreselection.size()) {
98 ATH_MSG_INFO("Building list of selected feedthroughs");
99 for (const unsigned BE : m_vBEPreselection) {
100 for (const unsigned PN : m_vPosNegPreselection) {
101 for (const unsigned FT : m_vFTPreselection) {
102 HWIdentifier finalFTId=m_onlineHelper->feedthrough_Id(BE,PN,FT);
103 unsigned int finalFTId32 = finalFTId.get_identifier32().get_compact();
104 ATH_MSG_INFO("Adding feedthrough Barrel/Endcap=" << BE << " pos/neg=" << PN << " FT=" << FT
105 << " (0x" << std::hex << finalFTId32 << std::dec << ")");
106 m_vFinalPreselection.push_back(finalFTId32);
107 }
108 }
109 }
110 std::sort(m_vFinalPreselection.begin(),m_vFinalPreselection.end());
111 }//end if something set
112 else {
113 if (m_vBEPreselection.size() || m_vPosNegPreselection.size() || m_vFTPreselection.size()) {
114 ATH_MSG_ERROR("Feedthrough preselection: jobOption inconsistency! ");
115 ATH_MSG_ERROR("Need to set all three jobOptions BEPreselection PNPreselecton and FTPreselection");
116 return StatusCode::FAILURE;
117 }
118 ATH_MSG_DEBUG("No feedthrough preselection by jobOptions.");
119 }
120 return sc;
121}
122
123
124//*******
125
126
128 const uint32_t* p, uint32_t n, LArRawChannelContainer& coll, CaloGain::CaloGain RequestedGain) const
129{
130 int32_t energy;
131 int32_t time;
132 int32_t quality;
133 uint32_t gain;
134 int fcNb;
135 HWIdentifier cId;
136 LArRodBlockStructure* BlStruct=prepareBlockStructure(robFrag, p, n, RequestedGain);
137 if (!BlStruct) return;
138
139 do {
140 HWIdentifier fId( Identifier32(BlStruct->getFEBID()) );
141 unsigned int fId32 = fId.get_identifier32().get_compact();
142 if (!m_onlineHelper->isValidId(fId)) {
143 ATH_MSG_WARNING("Invalid FEB identifer " << std::hex << fId32 << std::dec << ". Skipping");
144 continue;
145 }
146
147 if(m_febExchange) {
148 if (fId32 == m_febId1) {
150 fId32 = fId.get_identifier32().get_compact();
151 }
152 else if(fId32 == m_febId2) {
154 fId32 = fId.get_identifier32().get_compact();
155 }
156 }
157 if (!BlStruct->hasPhysicsBlock()) {
158 ATH_MSG_DEBUG("No Physics Data for this FEB - NULL event for FEBID 0x" << std::hex << BlStruct->getFEBID() << std::dec);
159 continue;
160 }
161
162 // RL 04.17.2008 skip check for some FEBs
163 int do_check=1;
164 std::vector<unsigned int>::const_iterator it_feb = m_IgnoreCheckFEBs.begin();
165 std::vector<unsigned int>::const_iterator it_feb_end = m_IgnoreCheckFEBs.end();
166 for(; it_feb!=it_feb_end;++it_feb)
167 if(fId==*it_feb) {
168 do_check=0;
169 break;
170 }
171 if(do_check) {
172 //WL 31.10.2007 //check RodStatus-word to catch corrupt events
173 if (BlStruct->getStatus() & m_StatusNMask) {
174 ATH_MSG_WARNING("RodStatus&0x" << std::hex << m_StatusNMask << " indicates corrupt data for FEB "<< std::hex << fId32 << std::dec <<". Ignored.");
175 continue;
176 }
177 }
178
179 // RL 05.11.2007 checksum
180 if(m_CheckSum) {
181 const uint32_t onsum = BlStruct->onlineCheckSum();
182 const uint32_t offsum = BlStruct->offlineCheckSum();
183 if(onsum!=offsum) {
184 ATH_MSG_WARNING("Checksum error:");
185 ATH_MSG_WARNING(" online checksum = " << MSG::hex << onsum);
186 ATH_MSG_WARNING(" offline checksum = " << MSG::hex << offsum);
187 continue;
188 }
189 }
190
191 if (m_vFTPreselection.size()) {
192 int ftId=m_onlineHelper->feedthrough_Id(fId).get_identifier32().get_compact();
193 if (!std::binary_search(m_vFTPreselection.begin(), m_vFTPreselection.end(),ftId)) {
194 ATH_MSG_DEBUG("Feedthrough with id " << std::hex << ftId << std::dec <<" not in preselection. Ignored.");
195 continue;
196 }
197 }
198 const int NthisFebChannel=m_onlineHelper->channelInSlotMax(fId);
199 while (BlStruct->getNextEnergy(fcNb,energy,time,quality,gain)) {
200 if (fcNb>=NthisFebChannel)
201 continue;
202 cId = m_onlineHelper->channel_Id(fId,fcNb);
203 uint16_t iquality = 0;
204 uint16_t iprovenance = 0x1000;
205 if (quality>0) {
206 iprovenance |= 0x2000;
207 iquality = (quality & 0xFFFF);
208 }
209 LArRawChannel chan(cId, energy, time, iquality, iprovenance, (CaloGain::CaloGain)gain);
210 coll.push_back(chan);
211 }
212 }
213 while (BlStruct->nextFEB()); //Get NextFeb
214}
215
216
218LArRodDecoder::prepareBlockStructure1 (const uint16_t rodMinorVersion, const uint32_t robBlockType) const
219{
220 const unsigned MAXMINOR = 12;
221 const unsigned MAXTYPE = 10;
222
223 if (rodMinorVersion > MAXMINOR || robBlockType > MAXTYPE) {
224 ATH_MSG_ERROR("Bad Rod block type " << robBlockType
225 << " / " << rodMinorVersion);
226 return nullptr;
227 }
228 std::vector<std::unique_ptr<LArRodBlockStructure> >& blstructs =
229 *m_blstructs.get();
230 unsigned int index = robBlockType * (MAXMINOR+1) + rodMinorVersion;
231 if (blstructs.empty()) {
232 blstructs.resize ((MAXMINOR+1)*(MAXTYPE+1));
233 }
234 if (!blstructs[index]) {
235 blstructs[index] = makeBlockStructure (robBlockType, rodMinorVersion);
236 }
237 if (!blstructs[index]) {
238 ATH_MSG_ERROR("Bad Rod block type " << robBlockType
239 << " / " << rodMinorVersion);
240 return nullptr;
241 }
242
243#ifndef NDEBUG
244 ATH_MSG_DEBUG("Found version " << rodMinorVersion << " of Rod block type " << robBlockType);
245#endif
246
247 return blstructs[index].get();
248}
249
250
253 const uint32_t* p, uint32_t n, const CaloGain::CaloGain RequestedGain) const
254{
255#ifndef NDEBUG
256 ATH_MSG_DEBUG("Prepare LArRodBlockStructure. Got a fragement of size " << n);
257#endif
258
259 //Get version and blocktype form header
260 eformat::helper::Version ver(robFrag.rod_version());
261 const uint16_t rodMinorVersion=ver.minor_version();
262 const uint32_t rodBlockType=robFrag.rod_detev_type()&0xff;
263 LArRodBlockStructure* BlStruct = prepareBlockStructure1 (rodMinorVersion, rodBlockType);
264 if (!BlStruct) {
265 return nullptr;
266 }
267
268 if (!BlStruct->setFragment(p,n)) {
269 constexpr int maxMess = 100;
270 static std::atomic<int> nMess = 1;
271 int thismess = nMess++;
272 if (thismess <= maxMess) {
273 ATH_MSG_ERROR("Could not set fragment (wrong number of samples in data ?) - container will not be filled");
274 if (thismess == maxMess)
275 ATH_MSG_ERROR("This message will not be repeated");
276 }
277 return NULL;
278 }
279#ifndef NDEBUG
280 ATH_MSG_VERBOSE("Set Fragment at address "<< &(p[0]) << " " << p[5]);
281#endif
282
283 BlStruct->setGain(RequestedGain); //Will be ignored if BlockStructure does not support fixed gains.
284 //FIXME: Very ugly hack! See explanation in LArRodDecoder.h
285 if (m_firstSample) {
286 BlStruct->setFirstSample(m_firstSample);
287 }
288 return BlStruct;
289}
290
291
292std::unique_ptr<LArRodBlockStructure>
293LArRodDecoder::makeBlockStructure (unsigned int rodBlockType,
294 unsigned int rodMinorVersion) const
295{
296 switch (rodBlockType) {
297 case 2:
298 break;
299
300 case 3:
301 // RodBlockType 3 = Test mode
302 //return std::make_unique<LArRodBlockTransparentV0<LArRodBlockHeaderTransparentV0> >(this->msgSvc().get());
303 break;
304
305 case 4:
306 // RodBlockType 4 = Physics mode
307 switch (rodMinorVersion) {
308 case 10: // Physics mode v5 16.06.2008 for LHC
309 case 11: // Physics mode v5 16.06.2008 for LHC
310 {
311 auto bl = std::make_unique<LArRodBlockPhysicsV5>(this->msgSvc().get());
313 bl->setRequiredNSamples(m_requiredPhysicsNSamples);
314 }
315 return bl;
316 }
317 case 12: // Physics mode v5 09.03.2011 for LHC
318 {
319 auto bl = std::make_unique<LArRodBlockPhysicsV6>(this->msgSvc().get());
321 bl->setRequiredNSamples(m_requiredPhysicsNSamples);
322 }
323 return bl;
324 }
325 default:
326 break;
327 }
328 break;
329
330 case 5:
331 // RodBlockType 5 = Physics simulation mode
332 // Physics mode v3 11.04.2005 for simulation
333 //return std::make_unique<LArRodBlockPhysicsV3>(this->msgSvc().get());
334 break;
335
336 case 6:
337 // RodBlockType 6 = Physics test mode
338 break;
339
340 case 7:
341 // RodBlockType 7 = Calibration mode
342 break;
343
344 case 10:
345 // RodBlockType 10 = Accumulated mode (used for pre-processed pedestal runs)
346 // Accumulated mode v3 10.06.2008
347 //return std::make_unique<LArRodBlockAccumulatedV3>(this->msgSvc().get());
348 break;
349
350 default:
351 break;
352 }
353
354 return std::unique_ptr<LArRodBlockStructure>();
355}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
static Double_t sc
StatusCode LArRodDecoder::initialize ATLAS_NOT_THREAD_SAFE()
Install fatal handler with default options.
static const InterfaceID IID_ILArRodDecoder("LArRodDecoder", 1, 0)
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
value_type get_compact() const
Get the compact id.
Identifier32 get_identifier32() const
Get the 32-bit version Identifier, will be invalid if >32 bits needed.
Container for LArRawChannel (IDC using LArRawChannelCollection).
Liquid Argon ROD output object base class.
bool setFragment(const uint32_t *p, uint32_t n)
virtual uint32_t hasPhysicsBlock() const
virtual int getNextEnergy(int &channelNumber, int32_t &energy, int32_t &time, int32_t &quality, uint32_t &gain)
virtual int setGain(const int GainValue)
virtual uint32_t offlineCheckSum() const
void setFirstSample(const int rearrangeFirstSample)
virtual uint32_t getStatus() const
virtual uint32_t onlineCheckSum() const
uint32_t m_StatusNMask
virtual ~LArRodDecoder()
Destructor.
std::vector< std::string > m_LArCellCorrNames
LArRodBlockStructure * prepareBlockStructure1(const uint16_t rodMinorVersion, const uint32_t robBlockType) const
std::vector< int > m_vFTPreselection
const LArOnlineID * m_onlineHelper
std::vector< unsigned int > m_IgnoreCheckFEBs
unsigned int m_febId1
std::unique_ptr< LArRodBlockStructure > makeBlockStructure(unsigned int rodBlockType, unsigned int rodMinorVersion) const
static const InterfaceID & interfaceID()
float m_LArCellEthreshold
unsigned short m_requiredPhysicsNSamples
std::vector< int > m_vBEPreselection
void fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment &robFrag, const uint32_t *p, uint32_t n, LArRawChannelContainer &coll, const CaloGain::CaloGain gain) const
unsigned int m_febId2
LArRodBlockStructure * prepareBlockStructure(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment &robFrag, const uint32_t *p, uint32_t n, const CaloGain::CaloGain RequestedGain) const
uint32_t m_StatusMask
std::vector< int > m_vPosNegPreselection
LArRodDecoder(const std::string &type, const std::string &name, const IInterface *parent)
Constructor Standard AlgTool constructor.
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:132
eformat::ROBFragment< PointerType > ROBFragment
Definition RawEvent.h:27
Definition index.py:1
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.