ATLAS Offline Software
Loading...
Searching...
No Matches
MdtCalibJsonDumpAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
7#include "Acts/Utilities/Enumerate.hpp"
8#include <fstream>
9#include <ranges>
10#include <format>
12
13using namespace MuonCalib;
14
15namespace {
16 std::string whiteSpace(int n, const char space=' ') {
17 std::string spaces{};
18 spaces.assign(n, space);
19 return spaces;
20 }
21 std::string rangeString(std::vector<ushort>& numbers){
22 std::ranges::sort(numbers);
23
24 std::stringstream sstr{};
25 ushort low{numbers.front()}, high{numbers.front()};
26 for (const ushort n : numbers) {
27 if (high == n || high+1 == n) {
28 high = n;
29 continue;
30 }
32 if (low == high) {
33 sstr<<low;
34 } else if (low + 1!=high){
35 sstr<<low<<"-"<<high;
36 } else {
37 sstr<<low<<";"<<high;
38 }
39 sstr<<";";
40 low = high = n;
41 }
43 if (low == numbers.back()) {
44 sstr<<low;
45 } else if (low + 1 != high) {
46 sstr<<low<<"-"<<high;
47 } else {
48 sstr<<low<<";"<<high;
49
50 }
52 return sstr.str();
53 }
54}
55
56
57namespace Muon {
60 ATH_CHECK(m_readKey.initialize());
61 ATH_CHECK(m_idHelperSvc.retrieve());
62 if (m_rtJSON.value().empty() || m_t0JSON.value().empty()) {
63 ATH_MSG_FATAL("No output file has been given " << m_rtJSON<<" "<<m_t0JSON);
64 return StatusCode::FAILURE;
65 }
66 if (m_t0JSON.value() == m_rtJSON.value()){
67 ATH_MSG_FATAL("You can't dump the two streams into the same JSON "<<m_t0JSON<<" & "<<m_rtJSON);
68 return StatusCode::FAILURE;
69 }
70 ATH_CHECK(m_rtDumpTree.init(this));
71 ATH_CHECK(m_t0DumpTree.init(this));
72 ATH_MSG_INFO("Dump calibration constants in " << m_rtJSON);
73 return StatusCode::SUCCESS;
74 }
76 ATH_CHECK(m_rtDumpTree.write());
77 ATH_CHECK(m_t0DumpTree.write());
78 return StatusCode::SUCCESS;
79 }
80 StatusCode MdtCalibJsonDumpAlg::execute(const EventContext& ctx) {
81 SG::ReadCondHandle calibHandle{m_readKey, ctx};
82 ATH_CHECK(calibHandle.isValid());
83
84 if (std::ranges::find(m_seenIDs, calibHandle.getRange()) != m_seenIDs.end()) {
85 ATH_MSG_INFO("IOV "<<calibHandle.getRange()<<" has already been dumped");
86 return StatusCode::SUCCESS;
87 }
88 m_seenIDs.emplace_back(calibHandle.getRange());
89 const MdtIdHelper &idHelper{m_idHelperSvc->mdtIdHelper()};
90
91 T0Grouper t0Groups{};
92 const CalibParamSorter sorter{std::pow(0.1, m_precision +2)};
93 RtGrouper rtGroups{sorter};
94 unsigned int rtCounter{0}, t0Counter{0};
95 for (auto itr = idHelper.detectorElement_begin(); itr != idHelper.detectorElement_end(); ++itr) {
96 const Identifier &detId{*itr};
97 const MdtFullCalibData *calibData = calibHandle->getCalibData(detId, msgStream());
98 if (!calibData || !calibData->rtRelation) {
99 continue;
100 }
101 ++rtCounter;
102 ATH_MSG_VERBOSE("Group rt constants of "<<m_idHelperSvc->toStringDetEl(detId));
103 rtGroups[calibData->rtRelation.get()].insert(detId);
104 const int ml = idHelper.multilayer(detId);
105
106 T0PerChamb& chambT0{t0Groups.insert(std::make_pair(idHelper.elementID(detId), T0PerChamb{sorter})).first->second};
107
108 for (int layer = 1; layer <= idHelper.tubeLayerMax(detId); ++layer) {
109 for (int tube = 1; tube <= idHelper.tubeMax(detId); ++tube) {
110 bool valid{false};
111 const Identifier chId{idHelper.channelID(detId, ml, layer, tube, valid)};
112 if (!valid) {
113 continue;
114 }
115 const MuonCalib::MdtTubeCalibContainer::SingleTubeCalib* singleCalib = calibData->tubeCalib->getCalib(chId);
116 if (!singleCalib) {
117 continue;
118 }
119 chambT0[singleCalib].insert(chId);
120 ++t0Counter;
121 }
122 }
123 }
124 ATH_CHECK(dumpRtRelations(ctx, rtGroups, calibHandle.getRange()));
125 ATH_CHECK(dumpTubeT0s(ctx, t0Groups, calibHandle.getRange()));
126
127 unsigned t0GrpCounter{0};
128 for (const auto&[chId, t0Channels] : t0Groups) {
129 t0GrpCounter+=t0Channels.size();
130 }
131 if ((rtCounter == 0) or (t0Counter == 0)){
132 ATH_MSG_ERROR("MdtCalibJsonDumpAlg::execute: Counter is zero in numerator");
133 return StatusCode::FAILURE;
134 }
135 ATH_MSG_INFO(std::format("Grouped {:d} / {:d} ({:.2f}%) rt relations & {:d}/ {:d} ({:.2f}%) t0 calibration constants",
136 rtGroups.size(), rtCounter, (100.* rtGroups.size() / rtCounter),
137 t0GrpCounter, t0Counter,(100.*t0GrpCounter / t0Counter)));
138 return StatusCode::SUCCESS;
139 }
140 StatusCode MdtCalibJsonDumpAlg::dumpRtRelations(const EventContext& ctx, const RtGrouper& rtRelMap, const EventIDRange& eventRange) {
141 std::ofstream outFileRT{toString(eventRange) + m_rtJSON};
142 if (!outFileRT.good()) {
143 ATH_MSG_FATAL("Failed to write "<<m_rtJSON);
144 return StatusCode::FAILURE;
145 }
146 outFileRT<<"[\n";
147 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
148 nlohmann::json rtDump{};
149 for (const auto [counter, payload] : Acts::enumerate(rtRelMap)) {
150 outFileRT<<whiteSpace(m_whiteSpace)<<"{\n";
151 outFileRT<<whiteSpace(m_whiteSpace)<<" \"chambers\": [\n";
152 const MdtRtRelation* rtRel = payload.first;
153 const std::set<Identifier>& chambers = payload.second;
154
155 for (const auto [chCounter, chambId] : Acts::enumerate(chambers)) {
156 outFileRT<<whiteSpace(2*m_whiteSpace)<<"{"
157 <<std::format("\"station\": \"{:}\", \"eta\": {:2d}, \"phi\": {:1d}, \"ml\": {:1d}",
158 idHelper.stationNameString(idHelper.stationName(chambId)), idHelper.stationEta(chambId),
159 idHelper.stationPhi(chambId), idHelper.multilayer(chambId))<<"}";
160
161 m_rt_stName.push_back(idHelper.stationNameString(idHelper.stationName(chambId)));
162 m_rt_stEta.push_back(idHelper.stationEta(chambId));
163 m_rt_stPhi.push_back(idHelper.stationPhi(chambId));
164 m_rt_stMl.push_back(idHelper.multilayer(chambId));
165
166 if (chCounter +1 != chambers.size()) {
167 outFileRT<<",\n";
168 } else {
169 outFileRT<<"],\n";
170 }
171 }
173 outFileRT<<whiteSpace(m_whiteSpace+1)<<"\"rtRelation\": {\n";
174 outFileRT<<whiteSpace(2*m_whiteSpace)<<"\"type\": \""<<rtRel->rt()->name()<<"\",\n";
175 m_rt_type = rtRel->rt()->name();
176 m_rt_pars = rtRel->rt()->parameters();
177 outFileRT<<whiteSpace(2*m_whiteSpace)<<"\"params\": "<<dump(rtRel->rt()->parameters())<<"},\n";
179 if (rtRel->tr()->name() != "TrRelationLookUp") {
180 outFileRT<<whiteSpace(m_whiteSpace+1)<<"\"trRelation\": {\n";
181 outFileRT<<whiteSpace(2*m_whiteSpace)<<"\"type\": \""<<rtRel->tr()->name()<<"\",\n";
182 outFileRT<<whiteSpace(2*m_whiteSpace)<<"\"params\": "<<dump(rtRel->tr()->parameters())<<"},\n";
183 m_tr_type = rtRel->tr()->name();
184 m_tr_pars = rtRel->tr()->parameters();
185 }
187 outFileRT<<whiteSpace(m_whiteSpace+1)<<"\"rtReso\": {\n";
188 outFileRT<<whiteSpace(2*m_whiteSpace)<<"\"type\": \""<<rtRel->rtRes()->name()<<"\",\n";
189 outFileRT<<whiteSpace(2*m_whiteSpace)<<"\"params\": "<<dump(rtRel->rtRes()->parameters())<<"}\n";
190 m_rt_resoType = rtRel->rtRes()->name();
191 m_rt_resoPars = rtRel->rtRes()->parameters();
192 if (counter +1 != rtRelMap.size()) {
193 outFileRT<<whiteSpace(m_whiteSpace)<<"},\n";
194 } else {
195 outFileRT<<whiteSpace(m_whiteSpace)<<"}\n";
196 }
197 m_rt_iov_start = eventRange.start();
198 m_rt_iov_end = eventRange.stop();
199 ATH_CHECK(m_rtDumpTree.fill(ctx));
200 }
201 outFileRT<<"]\n";
202 return StatusCode::SUCCESS;
203 }
204 std::string MdtCalibJsonDumpAlg::dump(const std::vector<double>& values) const{
205 std::stringstream sstr{};
206 sstr<<"[";
207 for (const auto [count, v] : Acts::enumerate(values)) {
208 sstr<<dump(v);
209 if (count + 1 != values.size())sstr<<", ";
210 }
211 sstr<<"]";
212 return sstr.str();
213 }
214 std::string MdtCalibJsonDumpAlg::dump(const double v) const{
215 std::stringstream sstr{};
216 if (std::abs(v)< std::pow(0.1, m_precision + 1)) {
217 sstr<<0;
218 } else {
219 sstr<<std::setprecision(m_precision + std::max(std::floor(std::log10(std::abs(v))), 1.))<<v;
220 }
221 return sstr.str();
222 }
223 StatusCode MdtCalibJsonDumpAlg::dumpTubeT0s(const EventContext& ctx, const T0Grouper& t0Map, const EventIDRange& eventRange) {
224 std::ofstream outFileT0{toString(eventRange) + m_t0JSON};
225 if (!outFileT0.good()) {
226 ATH_MSG_FATAL("Failed to write "<<m_t0JSON);
227 return StatusCode::FAILURE;
228 }
229 outFileT0<<"[\n";
230 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
231 for (const auto [count, payload] : Acts::enumerate(t0Map)) {
232 outFileT0<<whiteSpace(m_whiteSpace)<<"{\n";
233 const Identifier& detId = payload.first;
234 const T0PerChamb& calibConstants = payload.second;
235
236 m_t0_stName = idHelper.stationNameString(idHelper.stationName(detId));
237 m_t0_stEta = idHelper.stationEta(detId);
238 m_t0_stPhi = idHelper.stationPhi(detId);
239
240 outFileT0<<whiteSpace(m_whiteSpace+1)
241 <<std::format("\"station\": \"{:}\", \"eta\": {:2d}, \"phi\": {:1d}, \"calibConstants\":[\n",
242 idHelper.stationNameString(idHelper.stationName(detId)),
243 idHelper.stationEta(detId), idHelper.stationPhi(detId));
244 for (const auto [calibCounter, calibPayload] : Acts::enumerate(calibConstants)) {
245 outFileT0<<whiteSpace(2*m_whiteSpace)<<"{\"t0\": "<<dump(calibPayload.first->t0)<<", ";
246 outFileT0<<"\"adc\": "<<dump(calibPayload.first->adcCal)<<", ";
247 outFileT0<<"\"code\": "<<dump(calibPayload.first->statusCode)<<", ";
248 outFileT0<<"\"tubes\": [";
249 Identifier refId = (*calibPayload.second.begin());
250
251 m_t0_t0= calibPayload.first->t0;
252 m_t0_adc = calibPayload.first->adcCal;
253 m_t0_code = calibPayload.first->statusCode;
254 std::vector<u_short> tubes{};
255 auto dumpTubeLayer = [&tubes, &outFileT0, &idHelper, &refId](const Identifier& newLayId) {
256 outFileT0<<std::format("{{\"ml\": {:1d}, \"tl\": {:1d}, \"no\": \"{:}\"}}",
257 idHelper.multilayer(refId), idHelper.tubeLayer(refId),
258 rangeString(tubes));
259 tubes.clear();
260 refId = newLayId;
261 };
262 for (const Identifier& tubeId : calibPayload.second){
263 const int ml = idHelper.multilayer(tubeId);
264 const int tl = idHelper.tubeLayer(tubeId);
265 m_t0_multiLayer.push_back(ml);
266 m_t0_tubeLayer.push_back(tl);
267 m_t0_tube.push_back(idHelper.tube(tubeId));
268 if (tl != idHelper.tubeLayer(refId) || ml != idHelper.multilayer(refId)) {
269 dumpTubeLayer(tubeId);
270 outFileT0<<", ";
271 }
272 tubes.push_back(idHelper.tube(tubeId));
273 }
274 dumpTubeLayer(refId);
275 outFileT0<<"]";
276 if (calibCounter +1 != calibConstants.size()){
277 outFileT0<<"},\n";
278 } else {
279 outFileT0<<"}]"<<std::endl;
280 }
281 }
282
283 if (count +1 != t0Map.size()){
284 outFileT0<<whiteSpace(m_whiteSpace)<<"},\n";
285 } else {
286 outFileT0<<whiteSpace(m_whiteSpace)<<"}"<<std::endl;
287 }
288 m_t0_iov_start = eventRange.start();
289 m_t0_iov_end = eventRange.stop();
290 ATH_CHECK(m_t0DumpTree.fill(ctx));
291 }
292 outFileT0<<"]\n";
293 return StatusCode::SUCCESS;
294 }
295 std::string MdtCalibJsonDumpAlg::toString(const EventIDRange& range) const {
296 if (m_savePerIOV){
297 std::stringstream sstr{};
298 sstr<<range;
299 std::string outStr{sstr.str()};
300 outStr.erase(std::remove_if(outStr.begin(),outStr.end(),
301 [](const unsigned char c){
302 return !std::isalnum(c) && c!='-' && c !='_';
303 }), outStr.end());
304 return outStr+"_";
305 }
306 return {};
307 }
308}
#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)
Obj * get()
Get (non-const) access to the underlying object.
int multilayer(const Identifier &id) const
Access to components of the ID.
Identifier elementID(int stationName, int stationEta, int stationPhi) const
static int tubeLayerMax()
int tubeMax() const
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int tubeLayer, int tube) const
const ParVec & parameters() const
Definition CalibFunc.h:40
virtual std::string name() const =0
class which holds calibration constants per rt-region
const ITrRelation * tr() const
t(r) relationship
const IRtResolution * rtRes() const
resolution
const IRtRelation * rt() const
rt relation
const SingleTubeCalib * getCalib(const Identifier &tubeId) const
return calibration constants of a single tube
int stationEta(const Identifier &id) const
const std::string & stationNameString(const Identifier &id) const
const_id_iterator detectorElement_begin() const
Iterators over full set of ids.
int stationPhi(const Identifier &id) const
int stationName(const Identifier &id) const
const_id_iterator detectorElement_end() const
std::map< const SingleTubeCalib *, std::set< Identifier >, CalibParamSorter > T0PerChamb
MuonVal::VectorBranch< double > & m_rt_resoPars
parameters of the rt resolution function
StatusCode dumpRtRelations(const EventContext &ctx, const RtGrouper &rtRelMap, const EventIDRange &eventRange)
writes the RT relations into the JSON & output root file
Gaudi::Property< std::string > m_rtJSON
MuonVal::ScalarBranch< short > & m_t0_stEta
std::string dump(const std::vector< double > &values) const
virtual StatusCode initialize() override final
MuonVal::ScalarBranch< std::string > & m_rt_type
string defining the type of the rt function
MuonVal::VectorBranch< unsigned short > & m_rt_stPhi
Station phi of the associated chamber.
Gaudi::Property< std::string > m_t0JSON
MuonVal::VectorBranch< unsigned short > & m_t0_tubeLayer
MuonVal::ScalarBranch< float > & m_t0_adc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
std::map< Identifier, T0PerChamb > T0Grouper
MuonCalib::CalibParamSorter CalibParamSorter
MuonVal::ScalarBranch< float > & m_t0_t0
MuonVal::EventIDBranch m_rt_iov_end
Data mebmers to save the IOV range (End point).
MuonVal::VectorBranch< double > & m_rt_pars
parameters of the rt-function
MuonVal::EventIDBranch m_t0_iov_start
Data mebmers to save the IOV range (Start point).
SG::ReadCondHandleKey< MuonCalib::MdtCalibDataContainer > m_readKey
MuonVal::ScalarBranch< std::string > & m_tr_type
String defining the type of the tr function.
std::vector< EventIDRange > m_seenIDs
std::map< const MuonCalib::MdtRtRelation *, std::set< Identifier >, CalibParamSorter > RtGrouper
Gaudi::Property< bool > m_savePerIOV
MuonVal::ScalarBranch< unsigned short > & m_t0_code
std::string toString(const EventIDRange &range) const
MuonVal::ScalarBranch< unsigned short > & m_t0_stPhi
MuonVal::MuonTesterTree m_rtDumpTree
MuonVal::VectorBranch< unsigned short > & m_rt_stMl
Multi layer of the associated chamber.
StatusCode dumpTubeT0s(const EventContext &ctx, const T0Grouper &t0Map, const EventIDRange &eventRange)
MuonVal::EventIDBranch m_rt_iov_start
Data mebmers to save the IOV range (Start point).
virtual StatusCode finalize() override final
MuonVal::VectorBranch< unsigned short > & m_t0_multiLayer
Gaudi::Property< unsigned > m_whiteSpace
MuonVal::ScalarBranch< std::string > & m_rt_resoType
string defining the type of the rt resolution function
MuonVal::VectorBranch< unsigned short > & m_t0_tube
virtual StatusCode execute(const EventContext &ctx) override final
Execute method.
MuonVal::VectorBranch< short > & m_rt_stEta
Station eta of the associated chambers.
MuonVal::VectorBranch< double > & m_tr_pars
parameters of the tr-function
Gaudi::Property< unsigned > m_precision
MuonVal::MuonTesterTree m_t0DumpTree
MuonVal::ScalarBranch< std::string > & m_t0_stName
MuonVal::EventIDBranch m_t0_iov_end
Data mebmers to save the IOV range (End point).
MuonVal::VectorBranch< std::string > & m_rt_stName
Station name string of the associated chambers.
const EventIDRange & getRange()
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:148
CscCalcPed - algorithm that finds the Cathode Strip Chamber pedestals from an RDO.
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
unsigned short ushort
-event-from-file
DataModel_detail::iterator< DVL > remove_if(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of remove_if for DataVector/List.
class which holds the full set of calibration constants for a given tube