ATLAS Offline Software
Loading...
Searching...
No Matches
AlignmentErrorDbAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
7#include <GaudiKernel/EventIDRange.h>
8#include <format>
9#include <fstream>
10#include <iterator>
11
12namespace Muon{
14 ATH_MSG_DEBUG("initialize " << name());
15 ATH_CHECK(m_readKey.initialize());
16 ATH_CHECK(m_writeKey.initialize());
17 ATH_CHECK(m_idHelperSvc.retrieve());
18 ATH_CHECK(m_idTool.retrieve());
19 return StatusCode::SUCCESS;
20}
21
22StatusCode AlignmentErrorDbAlg::execute(const EventContext& ctx) const {
23 ATH_MSG_DEBUG("execute " << name());
24
25 // Write Cond Handle
26
27 SG::WriteCondHandle writeHandle{m_writeKey, ctx};
28 if (writeHandle.isValid()) {
29 ATH_MSG_DEBUG("CondHandle " << writeHandle.fullKey() << " is already valid."
30 << ". In theory this should not be called, but may happen"
31 << " if multiple concurrent events are being processed out of order.");
32 return StatusCode::SUCCESS;
33 }
34 auto writeCdo{std::make_unique<MuonAlignmentErrorData>()};
35
36 std::string clobContent;
37 EventIDRange rangeW;
38 std::tie(clobContent, rangeW) = m_clobFileOverride.value().empty() ? getDbClobContent(ctx) : getFileClobContent();
39
40 if (clobContent.empty()) {
41 ATH_MSG_ERROR("Cannot retrieve alignment error CLOB");
42 return StatusCode::FAILURE;
43 }
44
45 std::istringstream indata(clobContent);
46 if (!indata) {
47 ATH_MSG_ERROR("Alignment error configuration invalid");
48 return StatusCode::FAILURE;
49 }
50
51 ATH_MSG_DEBUG("***********************************");
52 ATH_MSG_DEBUG("PARSING LIST OF DEVIATIONS...");
53
54 std::string line;
55 std::vector<MuonAlignmentErrorData::MuonAlignmentErrorRule> MuonAlignmentErrorRuleVec;
57 while (getline(indata, line)) {
58 // READING COMMENTS
59 if (line.compare(0, 1,"#") == 0) {
60 // ATH_MSG_DEBUG("Reading a commented line saying " << line);
61 continue;
62 }
63
64 // READING FROM INPUT FILE: //
65 std::string flag("");
66 std::string name_sstring("");
67 std::string multilayer_sstring("");
68 double translation(0.);
69 double rotation(0.);
70
71 // GET INPUT FILE VERSION
72 if (line.compare(0, 7, "version") == 0) {
73 std::string clobVersion;
74 std::istringstream(line) >> flag >> clobVersion;
75 ATH_MSG_INFO("*****************************************");
76 ATH_MSG_INFO("Input file version " << clobVersion);
77 ATH_MSG_INFO("*****************************************");
78 writeCdo->setClobVersion(std::move(clobVersion));
79 continue;
80 }
81
82 // get the flag has_nsw_hits
83 if (line.compare(0, 12, "has_nsw_hits") == 0) {
84 bool hasNswHits{false};
85 std::istringstream(line) >> flag >> hasNswHits;
86 writeCdo->setHasNswHits(hasNswHits);
87 continue;
88 }
89
90 // A FLAG CHARACTERIZING THE TYPE OF ERROR
91 // A REGULAR EXPRESSION FOR THE STATION NAME (EX: BIL.*) //
92 // TWO DOUBLES FOR THE TRANSLATION AND ROTATION DEVIATIONS //
93 if (std::istringstream(line) >> flag >> name_sstring >> multilayer_sstring >> translation >> rotation) {
94 ATH_MSG_DEBUG(flag << " " << name_sstring << " " << multilayer_sstring << " " << translation << " " << rotation);
95
96 // SAVING THE STATION DEVIATIONS IN THE STRUCT //
97 aDev.stationName = name_sstring;
98 aDev.multilayer = multilayer_sstring;
99 aDev.translation = translation;
100 aDev.rotation = rotation;
101
102 // FILLING THE VECTOR OF STRUCT CONTAINING THE STATION DEVIATIONS //
103 MuonAlignmentErrorRuleVec.emplace_back(std::move(aDev));
104
105 } // check stream is not at the end
106
107 } // end of loop on input file lines
108
109 std::vector<MuonAlignmentErrorData::MuonAlignmentErrorRuleCache> MuonAlignmentErrorRuleCacheVec;
111
112 // Check the presence of detector elements in current reco and generate multimap to deviationVec
113 if (writeCdo->hasNswHits() == 1){
114 ATH_MSG_DEBUG("CLOB HAS NSW errors");
115 if(m_idHelperSvc->hasSTGC()){
116 ATH_MSG_DEBUG("HAS STGC");
117 generateMap(m_idHelperSvc->stgcIdHelper(), m_idTool, aDev_cache, MuonAlignmentErrorRuleVec);
118 }
119 if(m_idHelperSvc->hasMM()){
120 ATH_MSG_DEBUG("HAS MM");
121 generateMap(m_idHelperSvc->mmIdHelper(), m_idTool, aDev_cache, MuonAlignmentErrorRuleVec);
122 }
123 }
124 if (m_idHelperSvc->hasMDT()){
125 ATH_MSG_DEBUG("HAS MDT");
126 generateMap(m_idHelperSvc->mdtIdHelper(), m_idTool, aDev_cache, MuonAlignmentErrorRuleVec);
127 }
128 if (m_idHelperSvc->hasRPC()){
129 ATH_MSG_DEBUG("HAS RPC");
130 generateMap(m_idHelperSvc->rpcIdHelper(), m_idTool, aDev_cache, MuonAlignmentErrorRuleVec);
131 }
132 if (m_idHelperSvc->hasTGC()){
133 ATH_MSG_DEBUG("HAS TGC");
134 generateMap(m_idHelperSvc->tgcIdHelper(), m_idTool, aDev_cache, MuonAlignmentErrorRuleVec);
135 }
136 if (m_idHelperSvc->hasCSC()){
137 ATH_MSG_DEBUG("HAS CSC");
138 generateMap(m_idHelperSvc->cscIdHelper(), m_idTool, aDev_cache, MuonAlignmentErrorRuleVec);
139 }
140
141 MuonAlignmentErrorRuleCacheVec.emplace_back(std::move(aDev_cache));
142 if (MuonAlignmentErrorRuleVec.empty()) {
143 ATH_MSG_WARNING("Could not read any alignment error configuration");
144 return StatusCode::FAILURE;
145 }
146
147 writeCdo->setAlignmentErrorRules(std::move(MuonAlignmentErrorRuleVec));
148 writeCdo->setMuonAlignmentErrorRuleCache(std::move(MuonAlignmentErrorRuleCacheVec));
149
150 if (writeHandle.record(rangeW, std::move(writeCdo)).isFailure()) {
151 ATH_MSG_FATAL("Could not record MuonAlignmentErrorData " << writeHandle.key() << " with EventRange " << rangeW
152 << " into Conditions Store");
153 return StatusCode::FAILURE;
154 }
155 ATH_MSG_INFO("recorded new " << writeHandle.key() << " with range " << rangeW << " into Conditions Store");
156
157 return StatusCode::SUCCESS;
158}
159
160inline void AlignmentErrorDbAlg::generateMap(const auto & helper_obj, const auto & idTool,
162 std::vector<MuonAlignmentErrorData::MuonAlignmentErrorRule>& devVec) const {
163
164 for(auto itr = helper_obj.detectorElement_begin(); itr!= helper_obj.detectorElement_end(); ++itr){
165 // GATHERING INFORMATION TO PUT TOGETHER THE STATION NAME //
166 MuonCalib::MuonFixedLongId calibId = idTool->idToFixedLongId(*itr);
167 if (!calibId.isValid()) continue;
168 int multilayer = 1;
169 if (calibId.is_mdt()) {
170 multilayer = calibId.mdtMultilayer();
171 } else if (calibId.is_mmg()) {
172 multilayer = calibId.mmgMultilayer();
173 } else if (calibId.is_stg()) {
174 multilayer = calibId.stgMultilayer();
175 }
176 std::string multilayerName = std::to_string(multilayer);
177 std::string alignStationName = hardwareName(calibId);
179 // try to regexp-match the station name and the multilayer name then fill multimap
180 for (auto& iDev : devVec){
181 if (!boost::regex_match(alignStationName, iDev.stationName)) {
182 ++i;
183 continue;
184 }
185 if (!boost::regex_match(multilayerName, iDev.multilayer)) {
186 ++i;
187 continue;
188 }
189 adev_new.id_rule_map.insert({*itr, i});
190 ++i;
191 }
192 }
193}
194
195std::tuple<std::string, EventIDRange> AlignmentErrorDbAlg::getDbClobContent(const EventContext& ctx) const {
196 // Read Cond Handle
197 SG::ReadCondHandle readCdo{m_readKey, ctx};
198 if (!readCdo.isValid()) {
199 ATH_MSG_ERROR("Null pointer to the read conditions object");
200 return {};
201 }
202
203 EventIDRange rangeW;
204 if (!readCdo.range(rangeW)) {
205 ATH_MSG_ERROR("Failed to retrieve validity range for " << m_readKey.key());
206 return {};
207 }
208
209 ATH_MSG_INFO("Size of CondAttrListCollection " << m_readKey.fullKey() << " readCdo->size()= " << readCdo->size());
210 ATH_MSG_INFO("Range of input is " << rangeW);
211
212 // like MuonAlignmentErrorDbTool::loadAlignmentError() after retrieving atrc (readCdo)
213
214 std::string clobContent, dbClobVersion;
216 for (itr = readCdo->begin(); itr != readCdo->end(); ++itr) {
217 const coral::AttributeList& atr = itr->second;
218 clobContent = *(static_cast<const std::string*>((atr["syserrors"]).addressOfData()));
219 dbClobVersion = *(static_cast<const std::string*>((atr["version"]).addressOfData()));
220 }
221 return std::make_tuple(std::move(clobContent), rangeW);
222}
223
224std::tuple<std::string, EventIDRange> AlignmentErrorDbAlg::getFileClobContent() const {
225 ATH_MSG_INFO("Retrieving alignment error CLOB from file override " << m_clobFileOverride.value());
226
227 std::ifstream in(m_clobFileOverride.value());
228 if (!in) {
229 ATH_MSG_ERROR("Failed to read CLOB file " << m_clobFileOverride.value());
230 return std::make_tuple(std::string(), EventIDRange());
231 }
232 return std::make_tuple(std::string(std::istreambuf_iterator<char>(in), {}), IOVInfiniteRange::infiniteTime());
233}
234
235// RECOGNIZE STATION NAME //
237
239 using StationName = MuonCalib::MuonFixedLongId::StationName;
240
241 // The only exception that cannot be caught by hardwareEta() above
242 if (sector(calibId)==13) {
243 if (calibId.eta()== 7 && calibId.stationName()==StationName::BOL) return "BOE1A13"; // BOE1A13 not BOL7A13
244 if (calibId.eta()==-7 && calibId.stationName()==StationName::BOL) return "BOE1C13"; // BOE1C13 not BOL7C13
245 if (calibId.eta()== 8 && calibId.stationName()==StationName::BOL) return "BOE2A13"; // BOE2A13 not BOL8A13
246 if (calibId.eta()==-8 && calibId.stationName()==StationName::BOL) return "BOE2C13"; // BOE2C13 not BOL8C13
247 }
248
249 std::string ret = std::format("{}{}{}{}", calibId.stationNameString(), std::abs(hardwareEta(calibId)), side(calibId), sectorString(calibId) );
250 return ret;
251}
252
253inline std::string_view AlignmentErrorDbAlg::side(MuonCalib::MuonFixedLongId calibId) const {
254 return calibId.eta()>0 ? "A" : calibId.eta()<0 ? "C" : "B";
255}
256
258 int sec = sector(calibId);
259 if (sec<0 || sec > 99) {
260 throw std::runtime_error("Unhandled sector number");
261 }
262 return std::to_string(sec/10) + std::to_string(sec%10);
263}
264
266 if (calibId.is_tgc()) {
267 // TGC sector convention is special
268 return calibId.phi();
269 } else {
270 return isSmallSector(calibId) ? 2*calibId.phi() : 2*calibId.phi()-1;
271 }
272}
273
275 using StationName = MuonCalib::MuonFixedLongId::StationName;
276 switch (calibId.stationName()) {
277 case StationName::BIS:
278 case StationName::BMS:
279 case StationName::BOS:
280 case StationName::BEE:
281 case StationName::BMF:
282 case StationName::BOF:
283 case StationName::BOG:
284 case StationName::EES:
285 case StationName::EMS:
286 case StationName::EOS:
287 case StationName::EIS:
288 case StationName::CSS:
289 case StationName::BMG:
290 case StationName::MMS:
291 case StationName::STS:
292 return true;
293 default:
294 return false;
295 }
296}
297
299 using StationName = MuonCalib::MuonFixedLongId::StationName;
300 switch (calibId.stationName()) {
301 case StationName::BML:
302 {
303 if (sector(calibId)==13) {
304 switch (calibId.eta()) {
305 case 4: return 5;
306 case 5: return 6;
307 case 6: return 7;
308 case -4: return -5;
309 case -5: return -6;
310 case -6: return -7;
311 }
312 }
313 return calibId.eta();
314 }
315 case StationName::BOL:
316 {
317 // In sector 13, the BOE chambers are coded as BOL, with eta=7
318 if (sector(calibId)==13) {
319 if (calibId.eta()== 7) return 1; // BOE1A13 not BOL7A13
320 if (calibId.eta()==-7) return -1; // BOE1C13 not BOL7C13
321 }
322 return calibId.eta();
323 }
324 case StationName::BOF:
325 // In sectors 12 and 14 BOF1, BOF3, BOF5 are coded with eta=1,2,3
326 return calibId.eta()>0 ? calibId.eta()*2-1 : calibId.eta()*2+1;
327 case StationName::BOG:
328 // In sectors 12 and 14, BOG2, BOG4, BOG6 are coded with eta=1,2,3
329 return calibId.eta()*2;
330 case StationName::EIL:
331 {
332 if ((sector(calibId) == 1) || (sector(calibId) == 9)) {
333 switch (calibId.eta()) {
334 // In sectors 1 and 9 the small chamber is called EIL5, although it comes inward wrt EIL4, so athena indices need to be swapped
335 case 4: return 5;
336 case 5: return 4;
337 case -4: return -5;
338 case -5: return -4;
339 }
340 }
341 return calibId.eta();
342 }
343 case StationName::EEL:
344 {
345 // In sector 5, special EEL chamber called EEL2X05, while athena eta = 1
346 if ((sector(calibId) == 5) && (calibId.eta() == 1)) return 2;
347 if ((sector(calibId) == 5) && (calibId.eta() == -1)) return -2;
348 return calibId.eta();
349 }
350 default: return calibId.eta();
351 }
352}
353}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
ChanAttrListMap::const_iterator const_iterator
static EventIDRange infiniteTime()
Produces an EventIDRange that is inifinite in Time and invalid in RunLumi.
int stgMultilayer() const
Stg specific:
StationName
an enum with the station names
std::string_view stationNameString() const
StationName stationName() const
int mdtMultilayer() const
Mdt specific:
int mmgMultilayer() const
Mmg specific:
bool isValid() const
check validity of the identifier.
std::string sectorString(MuonCalib::MuonFixedLongId calibId) const
ToolHandle< MuonCalib::IIdToFixedIdTool > m_idTool
SG::WriteCondHandleKey< MuonAlignmentErrorData > m_writeKey
bool isSmallSector(MuonCalib::MuonFixedLongId calibId) const
int sector(MuonCalib::MuonFixedLongId calibId) const
StatusCode initialize() override
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
StatusCode execute(const EventContext &ctx) const override
SG::ReadCondHandleKey< CondAttrListCollection > m_readKey
int hardwareEta(MuonCalib::MuonFixedLongId calibId) const
std::string hardwareName(MuonCalib::MuonFixedLongId calibId) const
std::tuple< std::string, EventIDRange > getDbClobContent(const EventContext &ctx) const
std::tuple< std::string, EventIDRange > getFileClobContent() const
std::string_view side(MuonCalib::MuonFixedLongId calibId) const
void generateMap(const auto &helper_obj, const auto &idTool, MuonAlignmentErrorData::MuonAlignmentErrorRuleCache &adev_new, std::vector< MuonAlignmentErrorData::MuonAlignmentErrorRule > &devVec) const
Gaudi::Property< std::string > m_clobFileOverride
bool range(EventIDRange &r)
const std::string & key() const
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED
const DataObjID & fullKey() const
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
std::unordered_multimap< Identifier, MuonAlignmentErrorRuleIndex > id_rule_map
For each multilayer identifier, cache the indices of the affecting rules.