ATLAS Offline Software
MdtCalibJsonDumpAlg.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 #include "MdtCalibJsonDumpAlg.h"
7 #include "Acts/Utilities/Enumerate.hpp"
8 #include <fstream>
9 #include <ranges>
10 #include <format>
11 #include <CxxUtils/StringUtils.h>
12 
13 using namespace MuonCalib;
14 
15 namespace {
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 
57 namespace Muon {
58  MdtCalibJsonDumpAlg::~MdtCalibJsonDumpAlg() = default;
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 }
python.tests.PyTestsLib.finalize
def finalize(self)
_info( "content of StoreGate..." ) self.sg.dump()
Definition: PyTestsLib.py:50
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
vtune_athena.format
format
Definition: vtune_athena.py:14
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
json
nlohmann::json json
Definition: HistogramDef.cxx:9
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
MuonCalib::CalibParamSorter
Helper struct to group Mdt calibration constants which are equivalent within the target precision.
Definition: CalibParamSorter.h:12
initialize
void initialize()
Definition: run_EoverP.cxx:894
MuonCalib::MdtFullCalibData::rtRelation
RtRelationPtr rtRelation
Definition: MdtFullCalibData.h:21
StringUtils.h
Muon::MdtCalibJsonDumpAlg::T0Grouper
std::map< Identifier, T0PerChamb > T0Grouper
Definition: MdtCalibJsonDumpAlg.h:33
postInclude.sorter
sorter
Definition: postInclude.SortInput.py:23
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
MuonCalib::MdtTubeCalibContainer::getCalib
const SingleTubeCalib * getCalib(const Identifier &tubeId) const
return calibration constants of a single tube
Definition: MdtTubeCalibContainer.h:35
Muon
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
Definition: TrackSystemController.h:45
MuonCalib::MdtFullCalibData
class which holds the full set of calibration constants for a given tube
Definition: MdtFullCalibData.h:15
MuonCalib::MdtRtRelation
class which holds calibration constants per rt-region
Definition: MdtRtRelation.h:19
MuonCalib::MdtRtRelation::rtRes
const IRtResolution * rtRes() const
resolution
Definition: MdtRtRelation.h:24
XMLtoHeader.count
count
Definition: XMLtoHeader.py:84
ReadCondHandle.h
python.Bindings.values
values
Definition: Control/AthenaPython/python/Bindings.py:808
run_Egamma1_LArStrip_Fex.dump
dump
Definition: run_Egamma1_LArStrip_Fex.py:87
LArG4FSStartPointFilterLegacy.execute
execute
Definition: LArG4FSStartPointFilterLegacy.py:20
Muon::MdtCalibJsonDumpAlg::T0PerChamb
std::map< const SingleTubeCalib *, std::set< Identifier >, CalibParamSorter > T0PerChamb
Definition: MdtCalibJsonDumpAlg.h:32
calibdata.valid
list valid
Definition: calibdata.py:44
MuonCalib::CalibFunc::name
virtual std::string name() const =0
MuonCalib::MdtFullCalibData::tubeCalib
TubeContainerPtr tubeCalib
Definition: MdtFullCalibData.h:22
detail::ushort
unsigned short ushort
Definition: PrimitiveHelpers.h:44
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
beamspotman.n
n
Definition: beamspotman.py:727
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
MdtCalibJsonDumpAlg.h
MdtIdHelper
Definition: MdtIdHelper.h:61
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:194
MuonCalib
CscCalcPed - algorithm that finds the Cathode Strip Chamber pedestals from an RDO.
Definition: CscCalcPed.cxx:22
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
MuonCalib::MdtRtRelation::tr
const ITrRelation * tr() const
t(r) relationship
Definition: MdtRtRelation.h:25
integrator_readDb.outStr
outStr
Definition: integrator_readDb.py:47
GeoModel::TransientConstSharedPtr::get
Obj * get()
Get (non-const) access to the underlying object.
Definition: TransientConstSharedPtr.h:19
PixelModuleFeMask_create_db.payload
string payload
Definition: PixelModuleFeMask_create_db.py:69
python.PyAthena.v
v
Definition: PyAthena.py:154
MuonCalib::MdtRtRelation::rt
const IRtRelation * rt() const
rt relation
Definition: MdtRtRelation.h:23
MuonCalib::CalibFunc::parameters
const ParVec & parameters() const
Definition: CalibFunc.h:40
Muon::MdtCalibJsonDumpAlg::RtGrouper
std::map< const MuonCalib::MdtRtRelation *, std::set< Identifier >, CalibParamSorter > RtGrouper
Definition: MdtCalibJsonDumpAlg.h:31
MuonCalib::MdtTubeCalibContainer::SingleTubeCalib
Definition: MdtTubeCalibContainer.h:19
IdentifierByDetElSorter.h
dqt_zlumi_alleff_HIST.tl
tl
Definition: dqt_zlumi_alleff_HIST.py:73
test_pyathena.counter
counter
Definition: test_pyathena.py:15
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
python.compressB64.c
def c
Definition: compressB64.py:93
calibdata.tube
tube
Definition: calibdata.py:30
Identifier
Definition: IdentifierFieldParser.cxx:14