ATLAS Offline Software
Loading...
Searching...
No Matches
MdtAsBuiltCondAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4#include "MdtAsBuiltCondAlg.h"
5
6#include <fstream>
12#include "GeoModelKernel/throwExcept.h"
13#include <format>
14#include <string_view>
15
16namespace Muon{
18 ATH_CHECK(m_readKey.initialize(m_readFromJSON.value().empty()));
19 ATH_CHECK(m_writeKey.initialize());
20 ATH_CHECK(m_idHelperSvc.retrieve());
21 if (!m_readFromJSON.value().empty()){
22 ATH_MSG_INFO("Load Mdt as built parameters from JSON "<<m_readFromJSON);
23 } else {
24 ATH_MSG_INFO("Load Mdt as-built from COOL <"<<m_readKey.key()<<">");
25 }
26 return StatusCode::SUCCESS;
27}
28
29StatusCode MdtAsBuiltCondAlg::execute(const EventContext& ctx) const {
30 SG::WriteCondHandle writeHandle{m_writeKey, ctx};
31 if (writeHandle.isValid()) {
32 ATH_MSG_DEBUG("CondHandle " << writeHandle.fullKey() << " is already valid."
33 << ". In theory this should not be called, but may happen"
34 << " if multiple concurrent events are being processed out of order.");
35 return StatusCode::SUCCESS;
36 }
37 writeHandle.addDependency(EventIDRange(IOVInfiniteRange::infiniteTime()));
38 auto writeCdo{std::make_unique<MdtAsBuiltContainer>()};
39
41 if (!m_readFromJSON.value().empty()) {
42 std::ifstream inStream{PathResolverFindCalibFile(m_readFromJSON)};
43 if (!inStream.good()) {
44 ATH_MSG_FATAL("No such file or directory");
45 return StatusCode::FAILURE;
46 }
47 nlohmann::json lines;
48 inStream >> lines;
49 ATH_CHECK(parseDataFromJSON(lines, *writeCdo));
50 }
51 if (!m_readKey.empty()) {
52 SG::ReadCondHandle readHandle{m_readKey, ctx};
53 if (!readHandle.isValid()){
54 ATH_MSG_FATAL("Failed to retrieve "<<m_readKey.fullKey());
55 return StatusCode::FAILURE;
56 }
57 writeHandle.addDependency(readHandle);
58
59 for (CondAttrListCollection::const_iterator itr = readHandle->begin(); itr != readHandle->end(); ++itr) {
60 const coral::AttributeList& atr = itr->second;
61 const std::string data{*(static_cast<const std::string*>((atr["data"]).addressOfData()))};
62 nlohmann::json lines;
63 if (m_newFormat2020) {
64 nlohmann::json j = nlohmann::json::parse(data);
65 lines = j["corrections"];
66 } else {
68 }
69 ATH_CHECK(parseDataFromJSON(lines, *writeCdo));
70 }
71 }
72 ATH_CHECK(writeHandle.record(std::move(writeCdo)));
73 ATH_MSG_INFO("Saved successfully Mdt as built "<<m_writeKey.fullKey()<<" with validity range "<<writeHandle.getRange());
74 return StatusCode::SUCCESS;
75}
76
77StatusCode MdtAsBuiltCondAlg::parseDataFromJSON(const nlohmann::json& lines,
78 MdtAsBuiltContainer& asBuilt) const{
79
80 // loop over corrections ------------------------
81 for (auto& corr : lines.items()) {
82 nlohmann::json line = corr.value();
84 const std::string stationType = line["typ"];
85 const int stationPhi = line["jff"];
86 const int stationEta = line["jzz"];
87 bool is_valid{false};
88 const Identifier id = m_idHelperSvc->mdtIdHelper().elementID(stationType, stationEta, stationPhi, is_valid);
89 if (!is_valid) {
90 ATH_MSG_FATAL("The AMDB identifier "<<stationType<<", "<<stationEta<<", "<<stationPhi<<" does not seem to be a MDT one");
91 return StatusCode::FAILURE;
92 }
93 MdtAsBuiltPar xPar{};
95 xPar.setAmdbId(stationType, stationEta, stationPhi, 0);
96 xPar.setIdentifier(id);
97 using multilayer_t = MdtAsBuiltPar::multilayer_t;
98 using tubeSide_t = MdtAsBuiltPar::tubeSide_t;
99 for (const multilayer_t ml : {multilayer_t::ML1, multilayer_t::ML2}){
100 for (const tubeSide_t side : {tubeSide_t::POS, tubeSide_t::NEG}){
101 const std::string prefix = std::format("Ml{}{}TubeSide",
102 static_cast<unsigned>(ml) + 1,
103 side == tubeSide_t::POS ? "Pos" : "Neg");
104 auto getValue = [&prefix, &line, this](std::string_view val) -> float {
105 std::string itrName{prefix};
106 itrName.append(val);
107 if (line.find(itrName) == line.end()) {
108 ATH_MSG_ERROR("JSON does not contain " << itrName);
109 THROW_EXCEPTION("Bad JSON key");
110 }
111 return line[itrName];
112 };
113 xPar.setAlignmentParameters(ml, side, getValue("y0"), getValue("z0"),
114 getValue("alpha"), getValue("ypitch"),
115 getValue("zpitch"),getValue("stagg"));
116 }
117 }
118 auto itr_pair = asBuilt.insert(xPar);
119 if (!itr_pair.second){
120 ATH_MSG_FATAL("Failed to insert "<<xPar<<" because the place in memory is already occupied by "
121 <<(*itr_pair.first));
122 return StatusCode::FAILURE;
123 }
124 ATH_MSG_VERBOSE("Added "<<(*itr_pair.first)<<" to the container");
125 }
126 return StatusCode::SUCCESS;
127}
128
129StatusCode MdtAsBuiltCondAlg::legacyFormatToJSON(const std::string& data,
130 nlohmann::json& jsonDump) const {
131
132 // Parse corrections
133 constexpr std::string_view delimiter{"\n"};
134 auto lines = CxxUtils::tokenize(data, delimiter);
135 unsigned int nLines{0};
136 for (const std::string& blobline : lines) {
137 ++nLines;
138 constexpr std::string_view delimiter{":"};
139 auto tokens = CxxUtils::tokenize(blobline, delimiter);
140 // Check if tokens is not empty
141 if (tokens.empty()) {
142 ATH_MSG_FATAL("Empty string retrieved from DB in folder " << m_readKey.fullKey());
143 return StatusCode::FAILURE;
144 }
145 const std::string_view &type = tokens[0];
146 // Parse line
147 if (type[0] == '#') {
148 // skip it
149 continue;
150 }
151
152 if (type.compare(0, 4, "Corr") == 0) {
153 nlohmann::json newLine;
154 ATH_CHECK(setFromAscii(std::string(blobline), newLine));
155 jsonDump.push_back(newLine);
156 }
157 }
158 ATH_MSG_VERBOSE("Decoded "<<nLines<<" new ascii lines");
159 return StatusCode::SUCCESS;
160}
161
162
163StatusCode MdtAsBuiltCondAlg::setFromAscii(const std::string& asciiData,
164 nlohmann::json& newChannel) const {
165 std::istringstream in(asciiData);
166
167 std::string tok;
168 if (!((in >> tok) && (tok == "Corr:"))) {
169 ATH_MSG_FATAL(__FILE__<<":"<<__LINE__<<" Failed to parse line "<<asciiData);
170 return StatusCode::FAILURE;
171 }
172 std::string typ{};
173 int jff{0}, jzz{0};
174 if (!(in >> typ >> jff >> jzz)) {
175 ATH_MSG_FATAL(__FILE__<<":"<<__LINE__<<" Failed to parse line "<<asciiData);
176 return StatusCode::FAILURE;
177 }
178 newChannel["typ"] = typ;
179 newChannel["jff"] = jff;
180 newChannel["jzz"] = jzz;
181 using multilayer_t = MdtAsBuiltPar::multilayer_t;
182 using tubeSide_t = MdtAsBuiltPar::tubeSide_t;
183 std::array<int, static_cast<unsigned>(multilayer_t::NMLTYPES)> stagg{};
184 if (!(in >> stagg[static_cast<unsigned>(multilayer_t::ML1)]
185 >> stagg[static_cast<unsigned>(multilayer_t::ML2)])) {
186 ATH_MSG_FATAL(__FILE__<<":"<<__LINE__<<" Failed to parse line "<<asciiData);
187 return StatusCode::FAILURE;
188 }
189 for (const multilayer_t ml : {multilayer_t::ML1, multilayer_t::ML2}){
190 for (const tubeSide_t side : {tubeSide_t::POS, tubeSide_t::NEG}){
191 const std::string prefix = std::format("Ml{}{}TubeSide",
192 static_cast<unsigned>(ml) + 1, side == tubeSide_t::POS ? "Pos" : "Neg");
193 auto dumpValue = [&prefix, &newChannel](std::string_view field, const float val) {
194 std::string key{prefix};
195 key.append(field);
196 newChannel[key] = val;
197 } ;
198
199 float y0{0.f}, z0{0.f}, alpha{0.f}, ypitch{0.f}, zpitch{0.f};
200 if (!(in >> y0 >> z0 >> alpha >> ypitch >> zpitch)){
201 ATH_MSG_FATAL(__FILE__<<":"<<__LINE__<<" Failed to parse line "<<asciiData);
202 return StatusCode::FAILURE;
203 }
204 dumpValue("y0", y0);
205 dumpValue("z0", z0);
206 dumpValue("alpha", alpha);
207 dumpValue("ypitch", ypitch);
208 dumpValue("zpitch", zpitch);
209 dumpValue("stagg", stagg[static_cast<unsigned int>(ml)]);
210 }
211 }
212 return StatusCode::SUCCESS;
213}
214}
#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_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
std::set< MdtAsBuiltPar, std::less<> > MdtAsBuiltContainer
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
ChanAttrListMap::const_iterator const_iterator
static EventIDRange infiniteTime()
Produces an EventIDRange that is inifinite in Time and invalid in RunLumi.
Container classifier the MDT as-built parameters See parameter description in http://atlas-muon-align...
multilayer_t
MDT multi-layer index.
void setAlignmentParameters(multilayer_t iML, tubeSide_t iTubeSide, float y0, float z0, float alpha, float ypitch, float zpitch, int stagg)
Set the alignment parameters for a ML and a tube side.
tubeSide_t
MDT tube side.
void setIdentifier(const Identifier &id)
Setters and getters for the Athena Identifier.
void setAmdbId(const std::string &stName, int stEta, int stPhi, int stJob)
AMDB identifiers. They're often not the same as the ATLAS ones (TGCs).
virtual StatusCode execute(const EventContext &ctx) const override
StatusCode setFromAscii(const std::string &asciiData, nlohmann::json &newChannel) const
Gaudi::Property< std::string > m_readFromJSON
Load the alignment parameters from a JSON file.
StatusCode parseDataFromJSON(const nlohmann::json &lines, MdtAsBuiltContainer &asBuilt) const
SG::WriteCondHandleKey< MdtAsBuiltContainer > m_writeKey
StatusCode legacyFormatToJSON(const std::string &bloblines, nlohmann::json &lines) const
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
SG::ReadCondHandleKey< CondAttrListCollection > m_readKey
Gaudi::Property< bool > m_newFormat2020
virtual StatusCode initialize() override
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
static const std::string delimiter("/")
std::vector< std::string > tokenize(std::string_view the_str, std::string_view delimiters)
Splits the string into smaller substrings.
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10