BmnRoot 26.10.0-210-gc52d34b0
Software framework of the BM@N experiment
Loading...
Searching...
No Matches
comment_ids.C
Go to the documentation of this file.
1/*
2 BM@N alignment routine
3 BM@N experiment at NICA complex, JINR, 2026
4
5 Department: Math & Soft Group of HEP lab
6 Author: Claude (Opus 5.5)
7 Supervisor: Igor Polev, polev@jinr.int
8
9 comment_ids macro
10 Adds the text form of the detector IDs to every entry of a Run9
11 constraints or presigmas file that names some, and rewrites the file in place.
12
13 Usage:
14 root -l -b -q 'comment_ids.C("/home/igor/bmnroot/align_new/cfg/constraints/cnstr_r9-flat_lin3.json")'
15*/
16
17// headers below are for IDE syntax to work and they will be
18// turned off during execution in ROOT macro mode
19#ifndef __CLING__
20#include "BmnRun9DM.h"
21
22#include <algorithm>
23#include <fstream>
24#include <functional>
25#include <string>
26#include <vector>
27#endif
28
29#include "fairlogger/Logger.h"
30
31#include <nlohmann/json.hpp> // not in the BmnAligner dictionary, so the interpreter needs it too
32
33/*
34 * An entry names detector IDs in an "ID" array (typed NodeEqual constraint),
35 * in the DetectorID coefficients of a plain constraint, or in the DetectorID
36 * of a presigma. Each ID is listed once, in file order, as one string
37 * "<ID> = <BmnDetectorModel::DecodeID text>". DecodeID pads its fields to a
38 * fixed width, so the strings of an entry line up as a table.
39 *
40 * The list goes into ID_KEY, an array of strings placed right after the key
41 * holding the IDs: ID, Coefficients or DetectorID. The loaders accept and
42 * ignore ID_KEY in every entry (see BmnAlignConfig::LoadConstraints). A
43 * rerun replaces the list, so an ID edited in the file gets its new text.
44 *
45 * DecodeID reads only the bits of the ID, so BmnRun9DM decodes the IDs of
46 * every Run9 model, whatever elements the model keeps.
47 *
48 * The file is written back in the layout of the cfg files: one key per
49 * line; Coefficients and ID_KEY one item per line; any other value on the
50 * line of its key. ordered_json keeps the keys in file order.
51 */
52namespace
53{
54const std::string ID_KEY{"IDComment"};
55}
56
57/**
58 * @brief Add the text form of its detector IDs to every entry that names some.
59 *
60 * @param jsonPath constraints or presigmas file, rewritten in place
61 *
62 * @return 0 on success (also when the file names no ID and is left as it is),
63 * -1 if the file cannot be read, parsed or written
64 */
65int comment_ids(const char* jsonPath)
66{
67 using json = nlohmann::ordered_json;
68
69 json entries;
70 {
71 std::ifstream ifs(jsonPath);
72 if (!ifs.good()) {
73 LOG(error) << " <!> comment_ids: cannot open " << jsonPath;
74 return -1;
75 }
76 try {
77 ifs >> entries;
78 } catch (const std::exception& e) {
79 LOG(error) << " <!> comment_ids: cannot parse " << jsonPath << ": " << e.what();
80 return -1;
81 }
82 }
83 if (!entries.is_array()
84 || std::any_of(entries.begin(), entries.end(), [](const json& e) { return !e.is_object(); }))
85 {
86 LOG(error) << " <!> comment_ids: " << jsonPath << " is not an array of objects";
87 return -1;
88 }
89
90 const BmnRun9DM model; // DecodeID() needs no Init()
91 Int_t annotated{0};
92 for (json& entry : entries) {
93 std::vector<Int_t> ids;
94 auto take = [&ids](const json& id) {
95 if (id.is_number_integer() && std::find(ids.begin(), ids.end(), id.get<Int_t>()) == ids.end())
96 ids.push_back(id.get<Int_t>());
97 };
98 if (entry.contains("ID") && entry["ID"].is_array())
99 for (const json& id : entry["ID"])
100 take(id);
101 if (entry.contains("DetectorID"))
102 take(entry["DetectorID"]);
103 if (entry.contains("Coefficients") && entry["Coefficients"].is_array())
104 for (const json& coef : entry["Coefficients"])
105 if (coef.is_object() && coef.contains("DetectorID"))
106 take(coef["DetectorID"]);
107 if (ids.empty())
108 continue;
109
110 json lines = json::array();
111 for (const Int_t id : ids)
112 lines.push_back(std::string(Form("%9d = %s", id, model.DecodeID(id).c_str())));
113 const std::string anchor{entry.contains("ID") ? "ID"
114 : entry.contains("Coefficients") ? "Coefficients"
115 : "DetectorID"};
116 // CAUTION: no braces here - "json x {y}" makes the array [y], not a copy of y
117 json rebuilt = json::object();
118 for (auto it = entry.begin(); it != entry.end(); ++it) {
119 if (it.key() == ID_KEY)
120 continue; // left by an earlier run, replaced below
121 rebuilt[it.key()] = it.value();
122 if (it.key() == anchor)
123 rebuilt[ID_KEY] = lines;
124 }
125 entry = rebuilt;
126 annotated++;
127 }
128 if (!annotated) {
129 LOG(info) << " " << jsonPath << " names no detector ID, left as it is";
130 return 0;
131 }
132
133 std::function<std::string(const json&)> inline_ = [&inline_](const json& v) -> std::string {
134 if (!v.is_array() && !v.is_object())
135 return v.dump();
136 std::string items;
137 for (auto it = v.begin(); it != v.end(); ++it)
138 items += (items.empty() ? "" : ", ") + (v.is_object() ? json(it.key()).dump() + ": " : std::string())
139 + inline_(it.value());
140 return v.is_array() ? "[" + items + "]" : "{" + items + "}";
141 };
142 std::string text{"[\n"};
143 for (std::size_t e = 0; e < entries.size(); e++) {
144 const json& entry{entries[e]};
145 std::size_t key{0};
146 text += " {\n";
147 for (auto it = entry.begin(); it != entry.end(); ++it, ++key) {
148 std::string value;
149 if ((it.key() == "Coefficients" || it.key() == ID_KEY) && it.value().is_array()) {
150 value = "[\n";
151 for (std::size_t c = 0; c < it.value().size(); c++)
152 value += " " + inline_(it.value()[c]) + (c + 1 < it.value().size() ? ",\n" : "\n");
153 value += " ]";
154 } else
155 value = inline_(it.value());
156 text += " " + json(it.key()).dump() + ": " + value + (key + 1 < entry.size() ? ",\n" : "\n");
157 }
158 text += e + 1 < entries.size() ? " },\n" : " }\n";
159 }
160 text += "]\n";
161
162 std::ofstream ofs(jsonPath);
163 if (!ofs.good() || !(ofs << text)) {
164 LOG(error) << " <!> comment_ids: cannot write " << jsonPath;
165 return -1;
166 }
167 LOG(info) << " " << jsonPath << " : " << annotated << " entrie(s) got their detector IDs in " << ID_KEY;
168 return 0;
169}
__m128 v
Definition P4_F32vec4.h:1
int Int_t
char * Form(const char *fmt,...)
virtual std::string DecodeID(Int_t id) const override
Definition BmnRun9DM.h:203
int comment_ids(const char *jsonPath)
Add the text form of its detector IDs to every entry that names some.
Definition comment_ids.C:65