ATLAS Offline Software
Loading...
Searching...
No Matches
PixelCablingCondAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "GaudiKernel/EventIDRange.h"
8
9
11#include "Identifier/Identifier.h"
13#include "CoralBase/Blob.h"
14
15#include <iostream>
16#include <fstream>
17#include <sstream>
18#include <utility> //std::in_range
19
20PixelCablingCondAlg::PixelCablingCondAlg(const std::string& name, ISvcLocator* pSvcLocator):
21 ::AthCondAlgorithm(name, pSvcLocator)
22{
23}
24
26 ATH_MSG_DEBUG("PixelCablingCondAlg::initialize()");
27
28 ATH_CHECK(detStore()->retrieve(m_pixelID,"PixelID"));
29
30 ATH_CHECK(m_moduleDataKey.initialize());
31 ATH_CHECK(m_readoutspeedKey.initialize());
33
34 ATH_CHECK(m_writeKey.initialize());
35
36 return StatusCode::SUCCESS;
37}
38
39StatusCode PixelCablingCondAlg::execute(const EventContext& ctx) const {
40 ATH_MSG_DEBUG("PixelCablingCondAlg::execute()");
41
43 ATH_MSG_DEBUG("Conditions updates every event!!! This should be avoided once RegionSelectorTable is fixed!!");
44 if (writeHandle.isValid()) {
45 ATH_MSG_DEBUG("CondHandle " << writeHandle.fullKey() << " is already valid.. In theory this should not be called, but may happen if multiple concurrent events are being processed out of order.");
46 return StatusCode::SUCCESS;
47 }
48
49 // Construct the output Cond Object and fill it in
50 std::unique_ptr<PixelCablingCondData> writeCdo(std::make_unique<PixelCablingCondData>());
51
52 // Signed values
53 int barrel_ec{}, eta_module{};
54
55 // Unsigned 32 bit values
56 uint32_t layer_disk{}, phi_module{};
57 uint32_t robid{}, rodid{};
58 uint32_t sl_40_fmt{}, sl_40_link{}, sl_80_fmt{}, sl_80_link{};
59
60 // Unsigned 64-bit values
61 uint64_t onlineId = 0;
62 uint64_t linknumber = 0;
63
64 // Strings
65 std::string DCSname;
66 std::string line;
67
69 const PixelModuleData *moduleData = *moduleDataHandle;
70
71 // For debugging purposes
72 std::ofstream output_mapping_file_raw;
73 if (moduleData->getCablingMapToFile()) { output_mapping_file_raw.open("pixel_cabling_map_raw.txt"); }
74 std::ofstream output_mapping_file_interpreted;
75 if (moduleData->getCablingMapToFile()) { output_mapping_file_interpreted.open("pixel_cabling_map_interpreted.txt"); }
76
77 std::stringstream instr;
78 if (!m_readKey.empty()) {
80 const AthenaAttributeList* readCdo = *readHandle;
81 if (readCdo==nullptr) {
82 ATH_MSG_FATAL("Null pointer to the read conditions object");
83 return StatusCode::FAILURE;
84 }
85 writeHandle.addDependency(readHandle);
86
87 ATH_MSG_DEBUG("Size of AthenaAttributeList " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size());
88 ATH_MSG_DEBUG("Range of input is " << readHandle.getRange());
89
90 const coral::Blob& blob_cabling=(*readCdo)["CablingMapData"].data<coral::Blob>();
91 const char* p_cabling = static_cast<const char*>(blob_cabling.startingAddress());
92
93 unsigned int len_cabling = blob_cabling.size()/sizeof(char);
94 ATH_MSG_DEBUG("blob_cabling.size() = " << blob_cabling.size() << ", len_cabling = " << len_cabling);
95
96 instr.str(std::string(p_cabling,blob_cabling.size()));
97 }
98 else {
99 const std::string &cablingFilename = moduleData->getCablingMapFileName();
100 const std::string filename = PathResolverFindCalibFile(cablingFilename);
101 if (filename.empty()) {
102 ATH_MSG_FATAL("Mapping File: " << cablingFilename << " not found!");
103 return StatusCode::FAILURE;
104 }
105 std::ifstream fin(filename.c_str());
106 if (!fin) { return StatusCode::FAILURE; }
107 instr << fin.rdbuf();
108
109 writeHandle.addDependency(IOVInfiniteRange::infiniteRunLB()); //When reading from file, use infinite IOV
110 ATH_MSG_DEBUG("Refilled pixel cabling from file \"" << cablingFilename << "\"");
111 }
112
113 // Each entry in the mapping is sepated by a newline.
114 // Loop over all lines and parse the values
115 std::map<uint32_t,bool> rodReadoutMap = SG::ReadCondHandle<PixelReadoutSpeedData>(m_readoutspeedKey, ctx)->getReadoutMap();
116
117 while (instr.good() && getline(instr, line)) {
118
119 if (moduleData->getCablingMapToFile()) { output_mapping_file_raw << line << std::endl; }
120
121 // Skip empty lines and comments (i.e. starting with a hash or a space)
122 if (line.empty()) { continue; }
123 if (line[0]==' ' || line[0]=='#') { continue; }
124
125 // There are 11 columns, so there must be at least 21 characters in a valid line.
126 if (line.length()<21) { continue; }
127
128 // If reading from COOL, skip the datestamp
129 if (line.substr(line.length()-3,line.length())=="GMT") { continue; }
130
131 std::istringstream parse(line);
132 // coverity[tainted_data_argument]
133 parse >> barrel_ec >> layer_disk >> phi_module >> eta_module >> std::hex >> robid >> rodid >> sl_40_fmt >> sl_40_link >> sl_80_fmt >> sl_80_link >> DCSname;
134
135 // Debug
136 if (moduleData->getCablingMapToFile()) {
137 output_mapping_file_interpreted << barrel_ec << "\t" << layer_disk << "\t" << phi_module << "\t"
138 << eta_module << "\t" << std::hex << robid << "\t" << rodid << "\t"
139 << sl_40_fmt << "\t" << sl_40_link << "\t" << sl_80_fmt << "\t"
140 << sl_80_link << "\t" << DCSname << std::dec << std::endl;
141 }
142
143 // Get the offline ID for this module
144 // check layer_disk value is inside some very wide range
145 if (layer_disk>100){
146 ATH_MSG_ERROR("Value for layer_disk is insane: "<<layer_disk);
147 return StatusCode::FAILURE;
148 }
149 // Broad range check before passing to the wafer_id function (which takes ints)
150 if (!std::in_range<int>(layer_disk) || !std::in_range<int>(phi_module)) {
151 ATH_MSG_ERROR("Input value out of range for wafer_id arguments: "
152 << "layer_disk=" << layer_disk
153 << ", phi_module=" << phi_module);
154 return StatusCode::FAILURE;
155 }
156
157 Identifier offlineId = m_pixelID->wafer_id(barrel_ec,layer_disk,phi_module,eta_module);
158
159 // Set linknumber for IBL / DBM entries
160 if ((robid & 0xFFFFFF)>=0x140000) {
161 linknumber = sl_40_link | (sl_40_fmt<<4) | (sl_80_link<<8) | (sl_80_fmt<<12);
162 }
163 // Set linknumber for pixel entries
164 else {
165 bool readoutSpeed = false;
166 if (rodReadoutMap.find(rodid)!=rodReadoutMap.end()) { readoutSpeed=rodReadoutMap[rodid]; }
167
168 if (!readoutSpeed) { linknumber=(sl_40_link & 0xF) | ((sl_40_fmt & 0xF)<<4); }
169 else { linknumber=(sl_80_link & 0xF) | ((sl_80_fmt & 0xF)<<4); }
170 }
171
172 // Compute onlineId
173 onlineId = (robid & 0xFFFFFF) | (linknumber<<24);
174
175 IdentifierHash hashId;
176
177 // Do checks to verify consistency
178 IdContext cntxpixel = m_pixelID->wafer_context();
179 if (m_pixelID->get_hash(offlineId, hashId, &cntxpixel)) {
180 ATH_MSG_WARNING("Could not get hash from offlineId");
181 }
182
183 if (hashId>m_pixelID->wafer_hash_max()) {
184 ATH_MSG_ERROR("IdHash overflow! HashId is 0x" << std::hex << hashId);
185 ATH_MSG_ERROR("not mapped OfflineID: " << std::hex << offlineId << std::dec << " barrel_ec: " << barrel_ec
186 << " layer_disk: " << layer_disk << " phi_module: " << phi_module << " eta_module: " << eta_module);
187 ATH_MSG_ERROR("to OnlineID: 0x" << std::hex << onlineId << " robid: 0x" << robid << " rodid: 0x" << rodid << std::dec
188 << " link: 0x" << std::hex /*<< link*/ << " -> Linknumber: 0x" << linknumber << " HashId: 0x" << hashId << std::dec);
189
190 // Check if offlineId fail was caused by exceeding eta_module range
191 if (eta_module>m_pixelID->eta_module_max(offlineId) || eta_module<m_pixelID->eta_module_min(offlineId)) {
192 // eta_module_max == -999 indicates the module does not exist
193 if (m_pixelID->eta_module_max(offlineId)==-999 && m_pixelID->eta_module_min(offlineId)==-999) [[unlikely]]{
194 ATH_MSG_ERROR("Module does not exist in geometry");
195 }
196 else {
197 ATH_MSG_ERROR("eta_module range exceeded: Got eta_module = " << eta_module
198 << ", but allowed range is [" << m_pixelID->eta_module_min(offlineId)
199 << "," << m_pixelID->eta_module_max(offlineId) << "]");
200 ATH_MSG_ERROR("Input geometry tag may not be compatible with mapping file");
201 }
202 }
203 }
204 if (!std::in_range<int>(robid) || !std::in_range<int>(rodid)) [[unlikely]]{
205 ATH_MSG_ERROR("Input value out of range for add_entry_robrod arguments: "
206 << "robid=" << robid
207 << ", rodid=" << rodid);
208 return StatusCode::FAILURE;
209 }
210 // Fill the maps
211 writeCdo->add_entry_onoff(onlineId, offlineId);
212 writeCdo->add_entry_offon(offlineId, onlineId);
213 writeCdo->add_entry_offlineList(robid,offlineId);
214 writeCdo->add_entry_offrob(offlineId, robid);
215 writeCdo->add_entry_rodrob(rodid, robid);
216 writeCdo->add_entry_robrod(robid, rodid);
217 writeCdo->add_entry_DCSoffline(DCSname, offlineId);
218
219 // Debug messages
220 ATH_MSG_DEBUG("Mapped offlineID: " << std::hex << offlineId << " to onlineID: 0x" << onlineId
221 << ", robID: 0x" << robid << ", barrel_ec: " << std::dec << barrel_ec << ", layer_disk: " << layer_disk
222 << ", eta_module: " << eta_module << ", phi_module: " << phi_module << ", linknumber: 0x" << std::hex << linknumber);
223 }
224
225 if (moduleData->getCablingMapToFile()) {
226 output_mapping_file_raw.close();
227 output_mapping_file_interpreted.close();
228 }
229
230 ATH_MSG_DEBUG("Size of ROD readoutspeed map: " << rodReadoutMap.size());
231 writeCdo->set_readout_map(std::move(rodReadoutMap));
232
233 if (writeHandle.record(std::move(writeCdo)).isFailure()) {
234 ATH_MSG_FATAL("Could not record PixelCablingCondData " << writeHandle.key() << " with EventRange " << writeHandle.getRange() << " into Conditions Store");
235 return StatusCode::FAILURE;
236 }
237 ATH_MSG_DEBUG("recorded new CDO " << writeHandle.key() << " with range " << writeHandle.getRange() << " into Conditions Store");
238
239 return StatusCode::SUCCESS;
240}
241
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
const ServiceHandle< StoreGateSvc > & detStore() const
Base class for conditions algorithms.
An AttributeList represents a logical row of attributes in a metadata table.
static EventIDRange infiniteRunLB()
Produces an EventIDRange that is infinite in RunLumi and invalid in Time.
This class saves the "context" of an expanded identifier (ExpandedIdentifier) for compact or hash ver...
Definition IdContext.h:26
This is a "hash" representation of an Identifier.
SG::ReadCondHandleKey< AthenaAttributeList > m_readKey
virtual StatusCode initialize() override final
SG::ReadCondHandleKey< PixelModuleData > m_moduleDataKey
SG::ReadCondHandleKey< PixelReadoutSpeedData > m_readoutspeedKey
virtual StatusCode execute(const EventContext &ctx) const override final
SG::WriteCondHandleKey< PixelCablingCondData > m_writeKey
PixelCablingCondAlg(const std::string &name, ISvcLocator *pSvcLocator)
const PixelID * m_pixelID
const std::string & getCablingMapFileName() const
bool getCablingMapToFile() const
const DataObjID & fullKey() const
const EventIDRange & getRange()
const std::string & key() const
void addDependency(const EventIDRange &range)
const EventIDRange & getRange() const
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED
const DataObjID & fullKey() const
std::map< std::string, std::string > parse(const std::string &list)
#define unlikely(x)