ATLAS Offline Software
Loading...
Searching...
No Matches
LArRawDataReadingAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
11#include "eformat/Version.h"
12#include "eformat/index.h"
13
19
20#include "LArFebHeaderReader.h"
22
23LArRawDataReadingAlg::LArRawDataReadingAlg(const std::string& name, ISvcLocator* pSvcLocator) :
24 AthReentrantAlgorithm(name, pSvcLocator) {}
25
29
30 m_doDigits = !m_digitKey.empty();
31 ATH_CHECK(m_digitKey.initialize(m_doDigits));
32
35
36 ATH_CHECK(m_eventInfoKey.initialize() );
37
39 ATH_CHECK(detStore()->retrieve(m_onlineId,"LArOnlineID"));
40 return StatusCode::SUCCESS;
41}
42
43StatusCode LArRawDataReadingAlg::execute(const EventContext& ctx) const {
44 LArRawChannelContainer* rawChannels=nullptr;
45 LArDigitContainer* digits=nullptr;
46 LArFebHeaderContainer* febHeaders=nullptr;
47
48 if (m_doRawChannels) {
50 ATH_CHECK(rawChannelsHdl.record(std::make_unique<LArRawChannelContainer>()));
51 rawChannels=rawChannelsHdl.ptr();
52 rawChannels->reserve(182468); //Total number of LAr readout channels
53 }
54
55 if (m_doDigits) {
57 ATH_CHECK(digitsHdl.record(std::make_unique<LArDigitContainer>()));
58 digits=digitsHdl.ptr();
59 digits->reserve(1000); //Approximate number of Digits above threshold
60 }
61
62 if (m_doFebHeaders) {
64 ATH_CHECK(febHeadersHdl.record(std::make_unique<LArFebHeaderContainer>()));
65 febHeaders=febHeadersHdl.ptr();
66 febHeaders->reserve(1524); //Total number of LAr Front End Boards
67 }
68
69 //Get full events and filter out LAr ROBs
70 const RawEvent* fullEvent=m_robDataProviderSvc->getEvent(ctx);
71 std::map<eformat::SubDetectorGroup, std::vector<const uint32_t*> > rawEventTOC;
72 eformat::helper::build_toc(*fullEvent, rawEventTOC);
73 auto larRobs=rawEventTOC.find(eformat::LAR);
74 if (larRobs==rawEventTOC.end()) {
75 ATH_MSG_DEBUG("No LAr data found in this event. Recording empty LArRawChannelContainer");
76 return StatusCode::SUCCESS;
77 }
78
79
80 std::unique_ptr<LArRodBlockStructure> rodBlock;
81 uint16_t rodMinorVersion=0x0;
82 uint32_t rodBlockType=0x0;
83
84
85 for (const uint32_t* robPtr : larRobs->second) {
87 ATH_MSG_VERBOSE("Decoding ROB fragment 0x" << std::hex << rob.rob_source_id () << " with " << std::dec << rob.rod_fragment_size_word() << " ROB words");
88
89 if (rob.rod_fragment_size_word() <3) {
91 ATH_MSG_ERROR("Encountered corrupt ROD fragment, less than 3 words!");
92 return StatusCode::FAILURE;
93 }else {
94 continue;
95 }
96 } else if(rob.rob_source_id()& 0x1000 ){
97 //ATH_MSG_DEBUG(" skip Latome fragment with source ID "<< std::hex << rob.rob_source_id()
98 rodBlock=nullptr;
99 continue;
100 } else if(!(rob.rod_source_id()>>12& 0x0F) //0xnn0nnn must be
101 && !((rob.rod_source_id()>>20) == 4) ){ //0x4nnnnn must be
102
103 ATH_MSG_WARNING("Found not LAr fragment " << " event: "<<ctx.eventID().event_number());
105 ATH_MSG_WARNING("Rob source id.: 0x"<< std::hex << rob.rob_source_id () <<std::dec <<" ROD Source id: 0x"<<std::hex<<rob.rod_source_id()<<std::dec<<" Lvl1ID: "<<eventInfo->extendedLevel1ID());
106 continue;
107 }
108
109
110 eformat::helper::Version ver(rob.rod_version());
111 //(re-)init rodBlock only once per event or if (very unlikly or even impossible) some FEBs have a different firmware
112 if (rodBlock==nullptr || rodMinorVersion !=ver.minor_version() || rodBlockType!=(rob.rod_detev_type()&0xff)) {
113 rodMinorVersion=ver.minor_version();
114 rodBlockType=rob.rod_detev_type()&0xff;
115 ATH_MSG_VERBOSE("Found version " << rodMinorVersion << " of Rod Block Type " << rodBlockType);
116 if (rodBlockType==4) { //Physics mode
117 switch(rodMinorVersion) {
118 case 12: //Physics mode v6 09.03.2011 for LHC
119 rodBlock.reset(new LArRodBlockPhysicsV6);
120 break;
121 case 11: //Physics mode v5 16.06.2008 for LHC
122 case 10: //Physics mode v5 16.06.2008 for LHC
123 rodBlock.reset(new LArRodBlockPhysicsV5);
124 break;
125 default: // Unknown version of rod block type 4 (Physics mode)
126 if (m_failOnCorruption) {
127 ATH_MSG_ERROR("Found unsupported ROD Block version " << rodMinorVersion
128 << " of ROD block type " << rodBlockType << ". ROD Source id: 0x" <<std::hex<<rob.rod_source_id());
129 return StatusCode::FAILURE;
130 }
131 else {
132 ATH_MSG_WARNING("Found unsupported ROD Block version " << rodMinorVersion
133 << " of ROD block type " << rodBlockType << ". ROD Source id: 0x" <<std::hex<<rob.rod_source_id());
134 continue;
135 }
136 }// end switch(rodMinorVersion)
137 }//end rodBlockType==4 (physics mode)
138 else if (rodBlockType==2) { //Transparent mode
139 switch(rodMinorVersion) {
140 case 4:
142 break;
143 case 12:
144 rodBlock.reset(new LArRodBlockCalibrationV3);
145 break;
146 default:
147 ATH_MSG_WARNING("Found unsupported ROD Block version " << rodMinorVersion
148 << " of ROD block type " << rodBlockType);
149 return m_failOnCorruption ? StatusCode::FAILURE : StatusCode::SUCCESS;
150 }
151 }
152 }//End if need to re-init RodBlock
153
154 const uint32_t* pData=rob.rod_data();
155 const uint32_t nData=rob.rod_ndata();
156 if (nData==0) {
157 if (m_failOnCorruption) {
158 ATH_MSG_ERROR("ROD 0x"<<std::hex<<rob.rod_source_id() << std::dec << " reports data block size 0");
159 return StatusCode::FAILURE;
160 }
161 else {
162 ATH_MSG_WARNING("ROD 0x"<<std::hex<<rob.rod_source_id() << std::dec << " reports data block size 0");
163 continue; //Jump to next ROD
164 }
165 }
166
167 if (!rodBlock || !rodBlock->setFragment(pData,nData)) {
168 if (m_failOnCorruption) {
169 ATH_MSG_ERROR("Failed to assign fragment pointer to LArRodBlockStructure");
170 return StatusCode::FAILURE;
171 }
172 else {
173 ATH_MSG_WARNING("Failed to assign fragment pointer to LArRodBlockStructure");
174 continue; // Jump to next ROD
175 }
176 }
177
178 if(m_verifyChecksum) {
179 const uint32_t onsum = rodBlock->onlineCheckSum();
180 const uint32_t offsum = rodBlock->offlineCheckSum();
181 if(onsum!=offsum) {
182 if (m_failOnCorruption) {
183 ATH_MSG_ERROR("Checksum error:");
184 ATH_MSG_ERROR("online checksum = 0x" << MSG::hex << onsum);
185 ATH_MSG_ERROR("offline checksum = 0x" << MSG::hex << offsum << MSG::dec);
186 return StatusCode::FAILURE;
187 } else {
188 continue; //Jump to the next ROD-block
189 }
190 }
191 }
192
193 //Loop over FEBs in ROD:
194 do {
195 HWIdentifier fId(Identifier32(rodBlock->getFEBID()));
196 if (!m_onlineId->isValidId(fId)) {
197 if (m_failOnCorruption){
198 ATH_MSG_ERROR("Invalid FEB identifer 0x" << std::hex << fId.get_identifier32().get_compact());
199 return StatusCode::FAILURE;
200 } else {
201 ATH_MSG_WARNING("Invalid FEB identifer 0x" << std::hex << fId.get_identifier32().get_compact());
202 continue; //Jump to next FEB
203 }
204 }
205 const int NthisFebChannel=m_onlineId->channelInSlotMax(fId);
206
207 //Decode RawChanels (if requested)
208 if (m_doRawChannels) {
209 int32_t energy;
210 int32_t time;
211 int32_t quality;
212 uint32_t gain;
213 int fcNb;
214 while (rodBlock->getNextEnergy(fcNb,energy,time,quality,gain)) {
215 if (fcNb>=NthisFebChannel)
216 continue;
217
218 HWIdentifier cId = m_onlineId->channel_Id(fId,fcNb);
219 uint16_t iquality = 0;
220 uint16_t iprovenance = LArProv::DSPCALC; //0x1000
221 if (quality>0) {
222 iprovenance |= LArProv::QTPRESENT; //0x2000
223 iquality = (quality & 0xFFFF);
224 }
225 rawChannels->emplace_back(cId, energy, time, iquality, iprovenance, (CaloGain::CaloGain)gain);
226 }//end getNextEnergyLoop
227 }//end if m_doRawChannels
228
229 //Decode LArDigits (if requested)
230 if (m_doDigits) {
231 uint32_t gain;
232 int fcNb;
233 std::vector<short> samples;
234 while (rodBlock->getNextRawData(fcNb,samples,gain)) {
235 if (fcNb>=NthisFebChannel)
236 continue;
237 if (samples.size()==0) continue; // Ignore missing cells
238 HWIdentifier cId = m_onlineId->channel_Id(fId,fcNb);
239 digits->emplace_back(new LArDigit(cId, (CaloGain::CaloGain)gain, std::move(samples)));
240 samples.clear();
241 }//end getNextRawData loop
242 }//end if m_doDigits
243
244 //Decode FebHeaders (if requested)
245 if (m_doFebHeaders) {
246 std::unique_ptr<LArFebHeader> larFebHeader(new LArFebHeader(fId));
247 LArFebHeaderReader::fillFebHeader(larFebHeader.get(),rodBlock.get(),rob);
248 febHeaders->push_back(std::move(larFebHeader));
249 }//end if m_doFebHeaders
250
251 }while (rodBlock->nextFEB()); //Get NextFeb
252 } //end loop over ROBs
253 return StatusCode::SUCCESS;
254}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
OFFLINE_FRAGMENTS_NAMESPACE::FullEventFragment RawEvent
data type for reading raw event
Definition RawEvent.h:37
const ServiceHandle< StoreGateSvc > & detStore() const
An algorithm that can be simultaneously executed in multiple threads.
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
value_type emplace_back(value_type pElem)
Add an element to the end of the collection.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
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 class for LArDigit.
Liquid Argon digit base class.
Definition LArDigit.h:25
Container class for LArFebHeader.
Holds information from the FEB Header.
Container for LArRawChannel (IDC using LArRawChannelCollection)
LArRawDataReadingAlg(const std::string &name, ISvcLocator *pSvcLocator)
BooleanProperty m_failOnCorruption
SG::WriteHandleKey< LArRawChannelContainer > m_rawChannelKey
const LArOnlineID * m_onlineId
ServiceHandle< IROBDataProviderSvc > m_robDataProviderSvc
StatusCode initialize() override
SG::WriteHandleKey< LArFebHeaderContainer > m_febHeaderKey
BooleanProperty m_verifyChecksum
SG::WriteHandleKey< LArDigitContainer > m_digitKey
StatusCode execute(const EventContext &ctx) const override
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
This class provides decoding/encoding from/to ROD format.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
pointer_type ptr()
Dereference the pointer.
void fillFebHeader(LArFebHeader *lfh, const LArRodBlockStructure *bl, const ROBFragment &robFrag)
Fill info for one FEB Header.
eformat::ROBFragment< PointerType > ROBFragment
Definition RawEvent.h:27