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 }
81 const EventContext &ctx{Gaudi::Hive::currentContext()};
82 SG::ReadCondHandle calibHandle{m_readKey, ctx};
83 ATH_CHECK(calibHandle.isValid());
84
85 if (std::ranges::find(m_seenIDs, calibHandle.getRange()) != m_seenIDs.end()) {
86 ATH_MSG_INFO("IOV "<<calibHandle.getRange()<<" has already been dumped");
87 return StatusCode::SUCCESS;
88 }
89 m_seenIDs.emplace_back(calibHandle.getRange());
90 const MdtIdHelper &idHelper{m_idHelperSvc->mdtIdHelper()};
91
92 T0Grouper t0Groups{};
93 const CalibParamSorter sorter{std::pow(0.1, m_precision +2)};
94 RtGrouper rtGroups{sorter};
95 unsigned int rtCounter{0}, t0Counter{0};
96 for (auto itr = idHelper.detectorElement_begin(); itr != idHelper.detectorElement_end(); ++itr) {
97 const Identifier &detId{*itr};
98 const MdtFullCalibData *calibData = calibHandle->getCalibData(detId, msgStream());
99 if (!calibData || !calibData->rtRelation) {
100 continue;
101 }
102 ++rtCounter;
103 ATH_MSG_VERBOSE("Group rt constants of "<<m_idHelperSvc->toStringDetEl(detId));
104 rtGroups[calibData->rtRelation.get()].insert(detId);
105 const int ml = idHelper.multilayer(detId);
106
107 T0PerChamb& chambT0{t0Groups.insert(std::make_pair(idHelper.elementID(detId), T0PerChamb{sorter})).first->second};
108
109 for (int layer = 1; layer <= idHelper.tubeLayerMax(detId); ++layer) {
110 for (int tube = 1; tube <= idHelper.tubeMax(detId); ++tube) {
111 bool valid{false};
112 const Identifier chId{idHelper.channelID(detId, ml, layer, tube, valid)};
113 if (!valid) {
114 continue;
115 }
116 const MuonCalib::MdtTubeCalibContainer::SingleTubeCalib* singleCalib = calibData->tubeCalib->getCalib(chId);
117 if (!singleCalib) {
118 continue;
119 }
120 chambT0[singleCalib].insert(chId);
121 ++t0Counter;
122 }
123 }
124 }
125 ATH_CHECK(dumpRtRelations(ctx, rtGroups, calibHandle.getRange()));
126 ATH_CHECK(dumpTubeT0s(ctx, t0Groups, calibHandle.getRange()));
127
128 unsigned t0GrpCounter{0};
129 for (const auto&[chId, t0Channels] : t0Groups) {
130 t0GrpCounter+=t0Channels.size();
131 }
132 if ((rtCounter == 0) or (t0Counter == 0)){
133 ATH_MSG_ERROR("MdtCalibJsonDumpAlg::execute: Counter is zero in numerator");
134 return StatusCode::FAILURE;
135 }
136 ATH_MSG_INFO(std::format("Grouped {:d} / {:d} ({:.2f}%) rt relations & {:d}/ {:d} ({:.2f}%) t0 calibration constants",
137 rtGroups.size(), rtCounter, (100.* rtGroups.size() / rtCounter),
138 t0GrpCounter, t0Counter,(100.*t0GrpCounter / t0Counter)));
139 return StatusCode::SUCCESS;
140 }
141 StatusCode MdtCalibJsonDumpAlg::dumpRtRelations(const EventContext& ctx, const RtGrouper& rtRelMap, const EventIDRange& eventRange) {
142 std::ofstream outFileRT{toString(eventRange) + m_rtJSON};
143 if (!outFileRT.good()) {
144 ATH_MSG_FATAL("Failed to write "<<m_rtJSON);
145 return StatusCode::FAILURE;
146 }
147 outFileRT<<"[\n";
148 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
149 nlohmann::json rtDump{};
150 for (const auto [counter, payload] : Acts::enumerate(rtRelMap)) {
151 outFileRT<<whiteSpace(m_whiteSpace)<<"{\n";
152 outFileRT<<whiteSpace(m_whiteSpace)<<" \"chambers\": [\n";
153 const MdtRtRelation* rtRel = payload.first;
154 const std::set<Identifier>& chambers = payload.second;
155
156 for (const auto [chCounter, chambId] : Acts::enumerate(chambers)) {
157 outFileRT<<whiteSpace(2*m_whiteSpace)<<"{"
158 <<std::format("\"station\": \"{:}\", \"eta\": {:2d}, \"phi\": {:1d}, \"ml\": {:1d}",
159 idHelper.stationNameString(idHelper.stationName(chambId)), idHelper.stationEta(chambId),
160 idHelper.stationPhi(chambId), idHelper.multilayer(chambId))<<"}";
161
162 m_rt_stName.push_back(idHelper.stationNameString(idHelper.stationName(chambId)));
163 m_rt_stEta.push_back(idHelper.stationEta(chambId));
164 m_rt_stPhi.push_back(idHelper.stationPhi(chambId));
165 m_rt_stMl.push_back(idHelper.multilayer(chambId));
166
167 if (chCounter +1 != chambers.size()) {
168 outFileRT<<",\n";
169 } else {
170 outFileRT<<"],\n";
171 }
172 }
174 outFileRT<<whiteSpace(m_whiteSpace+1)<<"\"rtRelation\": {\n";
175 outFileRT<<whiteSpace(2*m_whiteSpace)<<"\"type\": \""<<rtRel->rt()->name()<<"\",\n";
176 m_rt_type = rtRel->rt()->name();
177 m_rt_pars = rtRel->rt()->parameters();
178 outFileRT<<whiteSpace(2*m_whiteSpace)<<"\"params\": "<<dump(rtRel->rt()->parameters())<<"},\n";
180 if (rtRel->tr()->name() != "TrRelationLookUp") {
181 outFileRT<<whiteSpace(m_whiteSpace+1)<<"\"trRelation\": {\n";
182 outFileRT<<whiteSpace(2*m_whiteSpace)<<"\"type\": \""<<rtRel->tr()->name()<<"\",\n";
183 outFileRT<<whiteSpace(2*m_whiteSpace)<<"\"params\": "<<dump(rtRel->tr()->parameters())<<"},\n";
184 m_tr_type = rtRel->tr()->name();
185 m_tr_pars = rtRel->tr()->parameters();
186 }
188 outFileRT<<whiteSpace(m_whiteSpace+1)<<"\"rtReso\": {\n";
189 outFileRT<<whiteSpace(2*m_whiteSpace)<<"\"type\": \""<<rtRel->rtRes()->name()<<"\",\n";
190 outFileRT<<whiteSpace(2*m_whiteSpace)<<"\"params\": "<<dump(rtRel->rtRes()->parameters())<<"}\n";
191 m_rt_resoType = rtRel->rtRes()->name();
192 m_rt_resoPars = rtRel->rtRes()->parameters();
193 if (counter +1 != rtRelMap.size()) {
194 outFileRT<<whiteSpace(m_whiteSpace)<<"},\n";
195 } else {
196 outFileRT<<whiteSpace(m_whiteSpace)<<"}\n";
197 }
198 m_rt_iov_start = eventRange.start();
199 m_rt_iov_end = eventRange.stop();
200 ATH_CHECK(m_rtDumpTree.fill(ctx));
201 }
202 outFileRT<<"]\n";
203 return StatusCode::SUCCESS;
204 }
205 std::string MdtCalibJsonDumpAlg::dump(const std::vector<double>& values) const{
206 std::stringstream sstr{};
207 sstr<<"[";
208 for (const auto [count, v] : Acts::enumerate(values)) {
209 sstr<<dump(v);
210 if (count + 1 != values.size())sstr<<", ";
211 }
212 sstr<<"]";
213 return sstr.str();
214 }
215 std::string MdtCalibJsonDumpAlg::dump(const double v) const{
216 std::stringstream sstr{};
217 if (std::abs(v)< std::pow(0.1, m_precision + 1)) {
218 sstr<<0;
219 } else {
220 sstr<<std::setprecision(m_precision + std::max(std::floor(std::log10(std::abs(v))), 1.))<<v;
221 }
222 return sstr.str();
223 }
224 StatusCode MdtCalibJsonDumpAlg::dumpTubeT0s(const EventContext& ctx, const T0Grouper& t0Map, const EventIDRange& eventRange) {
225 std::ofstream outFileT0{toString(eventRange) + m_t0JSON};
226 if (!outFileT0.good()) {
227 ATH_MSG_FATAL("Failed to write "<<m_t0JSON);
228 return StatusCode::FAILURE;
229 }
230 outFileT0<<"[\n";
231 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
232 for (const auto [count, payload] : Acts::enumerate(t0Map)) {
233 outFileT0<<whiteSpace(m_whiteSpace)<<"{\n";
234 const Identifier& detId = payload.first;
235 const T0PerChamb& calibConstants = payload.second;
236
237 m_t0_stName = idHelper.stationNameString(idHelper.stationName(detId));
238 m_t0_stEta = idHelper.stationEta(detId);
239 m_t0_stPhi = idHelper.stationPhi(detId);
240
241 outFileT0<<whiteSpace(m_whiteSpace+1)
242 <<std::format("\"station\": \"{:}\", \"eta\": {:2d}, \"phi\": {:1d}, \"calibConstants\":[\n",
243 idHelper.stationNameString(idHelper.stationName(detId)),
244 idHelper.stationEta(detId), idHelper.stationPhi(detId));
245 for (const auto [calibCounter, calibPayload] : Acts::enumerate(calibConstants)) {
246 outFileT0<<whiteSpace(2*m_whiteSpace)<<"{\"t0\": "<<dump(calibPayload.first->t0)<<", ";
247 outFileT0<<"\"adc\": "<<dump(calibPayload.first->adcCal)<<", ";
248 outFileT0<<"\"code\": "<<dump(calibPayload.first->statusCode)<<", ";
249 outFileT0<<"\"tubes\": [";
250 Identifier refId = (*calibPayload.second.begin());
251
252 m_t0_t0= calibPayload.first->t0;
253 m_t0_adc = calibPayload.first->adcCal;
254 m_t0_code = calibPayload.first->statusCode;
255 std::vector<u_short> tubes{};
256 auto dumpTubeLayer = [&tubes, &outFileT0, &idHelper, &refId](const Identifier& newLayId) {
257 outFileT0<<std::format("{{\"ml\": {:1d}, \"tl\": {:1d}, \"no\": \"{:}\"}}",
258 idHelper.multilayer(refId), idHelper.tubeLayer(refId),
259 rangeString(tubes));
260 tubes.clear();
261 refId = newLayId;
262 };
263 for (const Identifier& tubeId : calibPayload.second){
264 const int ml = idHelper.multilayer(tubeId);
265 const int tl = idHelper.tubeLayer(tubeId);
266 m_t0_multiLayer.push_back(ml);
267 m_t0_tubeLayer.push_back(tl);
268 m_t0_tube.push_back(idHelper.tube(tubeId));
269 if (tl != idHelper.tubeLayer(refId) || ml != idHelper.multilayer(refId)) {
270 dumpTubeLayer(tubeId);
271 outFileT0<<", ";
272 }
273 tubes.push_back(idHelper.tube(tubeId));
274 }
275 dumpTubeLayer(refId);
276 outFileT0<<"]";
277 if (calibCounter +1 != calibConstants.size()){
278 outFileT0<<"},\n";
279 } else {
280 outFileT0<<"}]"<<std::endl;
281 }
282 }
283
284 if (count +1 != t0Map.size()){
285 outFileT0<<whiteSpace(m_whiteSpace)<<"},\n";
286 } else {
287 outFileT0<<whiteSpace(m_whiteSpace)<<"}"<<std::endl;
288 }
289 m_t0_iov_start = eventRange.start();
290 m_t0_iov_end = eventRange.stop();
291 ATH_CHECK(m_t0DumpTree.fill(ctx));
292 }
293 outFileT0<<"]\n";
294 return StatusCode::SUCCESS;
295 }
296 std::string MdtCalibJsonDumpAlg::toString(const EventIDRange& range) const {
297 if (m_savePerIOV){
298 std::stringstream sstr{};
299 sstr<<range;
300 std::string outStr{sstr.str()};
301 outStr.erase(std::remove_if(outStr.begin(),outStr.end(),
302 [](const unsigned char c){
303 return !std::isalnum(c) && c!='-' && c !='_';
304 }), outStr.end());
305 return outStr+"_";
306 }
307 return {};
308 }
309}
#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_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
const std::string & stationNameString(const int &index) const
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::map< const SingleTubeCalib *, std::set< Identifier >, CalibParamSorter > T0PerChamb
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
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.
virtual StatusCode execute() override final
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:146
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