File indexing completed on 2024-04-06 12:28:18
0001 #include "RecoTracker/MkFitCore/interface/cms_common_macros.h"
0002 #include "RecoTracker/MkFitCore/interface/IterationConfig.h"
0003 #include "RecoTracker/MkFitCore/interface/Config.h"
0004 #include "RecoTracker/MkFitCore/interface/Track.h"
0005
0006
0007 #include "Debug.h"
0008
0009 #include "nlohmann/json.hpp"
0010
0011 #include <fstream>
0012 #include <mutex>
0013 #include <regex>
0014 #include <iostream>
0015 #include <iomanip>
0016
0017
0018 #define ITCONF_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
0019 inline void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) { \
0020 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
0021 } \
0022 inline void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) { \
0023 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \
0024 } \
0025 inline void to_json(nlohmann::ordered_json &nlohmann_json_j, const Type &nlohmann_json_t) { \
0026 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
0027 } \
0028 inline void from_json(const nlohmann::ordered_json &nlohmann_json_j, Type &nlohmann_json_t) { \
0029 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \
0030 }
0031
0032 namespace mkfit {
0033
0034
0035
0036 ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::LayerControl,
0037 m_layer)
0038
0039 ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::SteeringParams,
0040 m_layer_plan,
0041 m_track_scorer_name,
0042 m_region,
0043 m_fwd_search_pickup,
0044 m_bkw_fit_last,
0045 m_bkw_search_pickup)
0046
0047 ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationLayerConfig,
0048 m_layer,
0049 m_select_min_dphi,
0050 m_select_max_dphi,
0051 m_select_min_dq,
0052 m_select_max_dq,
0053 m_winpars_fwd,
0054 m_winpars_bkw)
0055
0056 ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationParams,
0057 nlayers_per_seed,
0058 maxCandsPerSeed,
0059 maxHolesPerCand,
0060 maxConsecHoles,
0061 chi2Cut_min,
0062 chi2CutOverlap,
0063 pTCutOverlap,
0064 recheckOverlap,
0065 useHitSelectionV2,
0066 minHitsQF,
0067 minPtCut,
0068 maxClusterSize)
0069
0070 ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationConfig,
0071 m_iteration_index,
0072 m_track_algorithm,
0073 m_seed_cleaner_name,
0074 m_seed_partitioner_name,
0075 m_pre_bkfit_filter_name,
0076 m_post_bkfit_filter_name,
0077 m_duplicate_cleaner_name,
0078 m_default_track_scorer_name,
0079 m_requires_seed_hit_sorting,
0080 m_backward_search,
0081 m_backward_drop_seed_hits,
0082 m_backward_fit_min_hits,
0083 sc_ptthr_hpt,
0084 sc_drmax_bh,
0085 sc_dzmax_bh,
0086 sc_drmax_eh,
0087 sc_dzmax_eh,
0088 sc_drmax_bl,
0089 sc_dzmax_bl,
0090 sc_drmax_el,
0091 sc_dzmax_el,
0092 dc_fracSharedHits,
0093 dc_drth_central,
0094 dc_drth_obarrel,
0095 dc_drth_forward,
0096 m_params,
0097 m_backward_params,
0098 m_n_regions,
0099 m_region_order,
0100 m_steering_params,
0101 m_layer_configs)
0102
0103 ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationsInfo,
0104 m_iterations)
0105
0106
0107
0108
0109
0110 namespace {
0111 struct FuncCatalog {
0112 std::map<std::string, clean_seeds_func> seed_cleaners;
0113 std::map<std::string, partition_seeds_func> seed_partitioners;
0114 std::map<std::string, filter_candidates_func> candidate_filters;
0115 std::map<std::string, clean_duplicates_func> duplicate_cleaners;
0116 std::map<std::string, track_score_func> track_scorers;
0117
0118 std::mutex catalog_mutex;
0119 };
0120
0121 FuncCatalog &get_catalog() {
0122 CMS_SA_ALLOW static FuncCatalog func_catalog;
0123 return func_catalog;
0124 }
0125 }
0126
0127 #define GET_FC \
0128 auto &fc = get_catalog(); \
0129 const std::lock_guard<std::mutex> lock(fc.catalog_mutex)
0130
0131 void IterationConfig::register_seed_cleaner(const std::string &name, clean_seeds_func func) {
0132 GET_FC;
0133 fc.seed_cleaners.insert({name, func});
0134 }
0135 void IterationConfig::register_seed_partitioner(const std::string &name, partition_seeds_func func) {
0136 GET_FC;
0137 fc.seed_partitioners.insert({name, func});
0138 }
0139 void IterationConfig::register_candidate_filter(const std::string &name, filter_candidates_func func) {
0140 GET_FC;
0141 fc.candidate_filters.insert({name, func});
0142 }
0143 void IterationConfig::register_duplicate_cleaner(const std::string &name, clean_duplicates_func func) {
0144 GET_FC;
0145 fc.duplicate_cleaners.insert({name, func});
0146 }
0147 void IterationConfig::register_track_scorer(const std::string &name, track_score_func func) {
0148 GET_FC;
0149 fc.track_scorers.insert({name, func});
0150 }
0151
0152 namespace {
0153 template <class T>
0154 typename T::mapped_type resolve_func_name(const T &cont, const std::string &name, const char *func) {
0155 if (name.empty()) {
0156 return nullptr;
0157 }
0158 auto ii = cont.find(name);
0159 if (ii == cont.end()) {
0160 std::string es(func);
0161 es += " '" + name + "' not found in function registry.";
0162 throw std::runtime_error(es);
0163 }
0164 return ii->second;
0165 }
0166 }
0167
0168 clean_seeds_func IterationConfig::get_seed_cleaner(const std::string &name) {
0169 GET_FC;
0170 return resolve_func_name(fc.seed_cleaners, name, __func__);
0171 }
0172 partition_seeds_func IterationConfig::get_seed_partitioner(const std::string &name) {
0173 GET_FC;
0174 return resolve_func_name(fc.seed_partitioners, name, __func__);
0175 }
0176 filter_candidates_func IterationConfig::get_candidate_filter(const std::string &name) {
0177 GET_FC;
0178 return resolve_func_name(fc.candidate_filters, name, __func__);
0179 }
0180 clean_duplicates_func IterationConfig::get_duplicate_cleaner(const std::string &name) {
0181 GET_FC;
0182 return resolve_func_name(fc.duplicate_cleaners, name, __func__);
0183 }
0184 track_score_func IterationConfig::get_track_scorer(const std::string &name) {
0185 GET_FC;
0186 return resolve_func_name(fc.track_scorers, name, __func__);
0187 }
0188
0189 #undef GET_FC
0190
0191
0192
0193 void IterationConfig::setupStandardFunctionsFromNames() {
0194 m_seed_cleaner = get_seed_cleaner(m_seed_cleaner_name);
0195 dprintf(" Set seed_cleaner for '%s' %s\n", m_seed_cleaner_name.c_str(), m_seed_cleaner ? "SET" : "NOT SET");
0196
0197 m_seed_partitioner = get_seed_partitioner(m_seed_partitioner_name);
0198 dprintf(
0199 " Set seed_partitioner for '%s' %s\n", m_seed_partitioner_name.c_str(), m_seed_partitioner ? "SET" : "NOT SET");
0200
0201 m_pre_bkfit_filter = get_candidate_filter(m_pre_bkfit_filter_name);
0202 dprintf(
0203 " Set pre_bkfit_filter for '%s' %s\n", m_pre_bkfit_filter_name.c_str(), m_pre_bkfit_filter ? "SET" : "NOT SET");
0204
0205 m_post_bkfit_filter = get_candidate_filter(m_post_bkfit_filter_name);
0206 dprintf(" Set post_bkfit_filter for '%s' %s\n",
0207 m_post_bkfit_filter_name.c_str(),
0208 m_post_bkfit_filter ? "SET" : "NOT SET");
0209
0210 m_duplicate_cleaner = get_duplicate_cleaner(m_duplicate_cleaner_name);
0211 dprintf(" Set duplicate_cleaner for '%s' %s\n",
0212 m_duplicate_cleaner_name.c_str(),
0213 m_duplicate_cleaner ? "SET" : "NOT SET");
0214
0215 m_default_track_scorer = get_track_scorer(m_default_track_scorer_name);
0216 for (auto &sp : m_steering_params) {
0217 sp.m_track_scorer =
0218 sp.m_track_scorer_name.empty() ? m_default_track_scorer : get_track_scorer(sp.m_track_scorer_name);
0219 }
0220 }
0221
0222
0223
0224
0225
0226 ConfigJsonPatcher::ConfigJsonPatcher(bool verbose) : m_verbose(verbose) {}
0227
0228 ConfigJsonPatcher::~ConfigJsonPatcher() = default;
0229
0230 std::string ConfigJsonPatcher::get_abs_path() const {
0231 std::string s;
0232 s.reserve(64);
0233 for (auto &p : m_path_stack)
0234 s += p;
0235 return s;
0236 }
0237
0238 std::string ConfigJsonPatcher::exc_hdr(const char *func) const {
0239 std::string s;
0240 s.reserve(128);
0241 s = "ConfigJsonPatcher";
0242 if (func) {
0243 s += "::";
0244 s += func;
0245 }
0246 s += " '";
0247 s += get_abs_path();
0248 s += "' ";
0249 return s;
0250 }
0251
0252 template <class T>
0253 void ConfigJsonPatcher::load(const T &o) {
0254 m_json = std::make_unique<nlohmann::json>();
0255 *m_json = o;
0256 cd_top();
0257 }
0258 template void ConfigJsonPatcher::load<IterationsInfo>(const IterationsInfo &o);
0259 template void ConfigJsonPatcher::load<IterationConfig>(const IterationConfig &o);
0260
0261 template <class T>
0262 void ConfigJsonPatcher::save(T &o) {
0263 from_json(*m_json, o);
0264 }
0265 template void ConfigJsonPatcher::save<IterationConfig>(IterationConfig &o);
0266
0267
0268
0269 template <>
0270 void ConfigJsonPatcher::save<IterationsInfo>(IterationsInfo &o) {
0271 auto &itc_arr = m_json->at("m_iterations");
0272 for (int i = 0; i < o.size(); ++i) {
0273 from_json(itc_arr[i], o[i]);
0274 }
0275 }
0276
0277 void ConfigJsonPatcher::cd(const std::string &path) {
0278 nlohmann::json::json_pointer jp(path);
0279 m_json_stack.push_back(m_current);
0280 m_path_stack.push_back(path);
0281 m_current = &m_current->at(jp);
0282 }
0283
0284 void ConfigJsonPatcher::cd_up(const std::string &path) {
0285 if (m_json_stack.empty())
0286 throw std::runtime_error("JSON stack empty on cd_up");
0287
0288 m_current = m_json_stack.back();
0289 m_json_stack.pop_back();
0290 m_path_stack.pop_back();
0291 if (!path.empty())
0292 cd(path);
0293 }
0294
0295 void ConfigJsonPatcher::cd_top(const std::string &path) {
0296 m_current = m_json.get();
0297 m_json_stack.clear();
0298 m_path_stack.clear();
0299 if (!path.empty())
0300 cd(path);
0301 }
0302
0303 template <typename T>
0304 void ConfigJsonPatcher::replace(const std::string &path, T val) {
0305 nlohmann::json::json_pointer jp(path);
0306 m_current->at(jp) = val;
0307 }
0308 template void ConfigJsonPatcher::replace<int>(const std::string &path, int val);
0309 template void ConfigJsonPatcher::replace<float>(const std::string &path, float val);
0310 template void ConfigJsonPatcher::replace<double>(const std::string &path, double val);
0311
0312 template <typename T>
0313 void ConfigJsonPatcher::replace(int first, int last, const std::string &path, T val) {
0314 nlohmann::json::json_pointer jp(path);
0315 for (int i = first; i <= last; ++i) {
0316 m_current->at(i).at(jp) = val;
0317 }
0318 }
0319 template void ConfigJsonPatcher::replace<int>(int first, int last, const std::string &path, int val);
0320 template void ConfigJsonPatcher::replace<float>(int first, int last, const std::string &path, float val);
0321 template void ConfigJsonPatcher::replace<double>(int first, int last, const std::string &path, double val);
0322
0323 nlohmann::json &ConfigJsonPatcher::get(const std::string &path) {
0324 nlohmann::json::json_pointer jp(path);
0325 return m_current->at(jp);
0326 }
0327
0328 int ConfigJsonPatcher::replace(const nlohmann::json &j) {
0329 if (j.is_null())
0330 throw std::runtime_error(exc_hdr(__func__) + "null not expected");
0331
0332 if (j.is_boolean() || j.is_number() || j.is_string()) {
0333 throw std::runtime_error(exc_hdr(__func__) + "value not expected on this parsing level");
0334 }
0335
0336 int n_replaced = 0;
0337
0338 if (j.is_object()) {
0339 static const std::regex index_range_re("^\\[(\\d+)..(\\d+)\\]$", std::regex::optimize);
0340
0341 for (auto &[key, value] : j.items()) {
0342 std::smatch m;
0343 std::regex_search(key, m, index_range_re);
0344
0345 if (m.size() == 3) {
0346 if (!m_current->is_array())
0347 throw std::runtime_error(exc_hdr(__func__) + "array range encountered when current json is not an array");
0348 int first = std::stoi(m.str(1));
0349 int last = std::stoi(m.str(2));
0350 for (int i = first; i <= last; ++i) {
0351 std::string s("/");
0352 s += std::to_string(i);
0353 cd(s);
0354 if (value.is_array()) {
0355 for (auto &el : value)
0356 n_replaced += replace(el);
0357 } else {
0358 n_replaced += replace(value);
0359 }
0360 cd_up();
0361 }
0362 } else if (value.is_array() || value.is_object()) {
0363 std::string s("/");
0364 s += key;
0365 cd(s);
0366 n_replaced += replace(value);
0367 cd_up();
0368 } else if (value.is_number() || value.is_boolean() || value.is_string()) {
0369 std::string s("/");
0370 s += key;
0371 nlohmann::json::json_pointer jp(s);
0372 if (m_current->at(jp) != value) {
0373 if (m_verbose)
0374 std::cout << " " << get_abs_path() << s << ": " << m_current->at(jp) << " -> " << value << "\n";
0375
0376 m_current->at(jp) = value;
0377 ++n_replaced;
0378 }
0379 } else {
0380 throw std::runtime_error(exc_hdr(__func__) + "unexpected value type");
0381 }
0382 }
0383 } else if (j.is_array() && j.empty()) {
0384 } else if (j.is_array()) {
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397 static const std::regex index_re("^(?:\\[\\d+..\\d+\\]|\\d+(?:/.*)?)$", std::regex::optimize);
0398
0399 bool has_index = false, has_plain = false;
0400 for (int i = 0; i < (int)j.size(); ++i) {
0401 const nlohmann::json &el = j[i];
0402
0403 if (!el.is_object())
0404 throw std::runtime_error(exc_hdr(__func__) + "array elements expected to be objects");
0405
0406 for (nlohmann::json::const_iterator it = el.begin(); it != el.end(); ++it) {
0407 if (std::regex_search(it.key(), index_re)) {
0408 has_index = true;
0409 if (has_plain)
0410 throw std::runtime_error(exc_hdr(__func__) + "indexed array entry following plain one");
0411 } else {
0412 has_plain = true;
0413 if (has_index)
0414 throw std::runtime_error(exc_hdr(__func__) + "plain array entry following indexed one");
0415 }
0416 }
0417 }
0418 if (has_index) {
0419 for (auto &element : j) {
0420 n_replaced += replace(element);
0421 }
0422 } else {
0423 if (m_current && !m_current->is_array())
0424 throw std::runtime_error(exc_hdr(__func__) + "plain array detected when current is not an array");
0425 if (m_current->size() != j.size())
0426 throw std::runtime_error(exc_hdr(__func__) + "plain array of different size than at current pos");
0427
0428 std::string s;
0429 for (int i = 0; i < (int)j.size(); ++i) {
0430 s = "/";
0431 s += std::to_string(i);
0432 cd(s);
0433 n_replaced += replace(j[i]);
0434 cd_up();
0435 }
0436 }
0437 } else {
0438 throw std::runtime_error(exc_hdr(__func__) + "unexpected json type");
0439 }
0440
0441 return n_replaced;
0442 }
0443
0444 std::string ConfigJsonPatcher::dump(int indent) { return m_json->dump(indent); }
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463 namespace {
0464
0465 void open_ofstream(std::ofstream &ofs, const std::string &fname, const char *pfx = nullptr) {
0466 ofs.open(fname, std::ofstream::trunc);
0467 if (!ofs) {
0468 char m[2048];
0469 snprintf(m, 2048, "%s%sError opening %s for write: %m", pfx ? pfx : "", pfx ? " " : "", fname.c_str());
0470 throw std::runtime_error(m);
0471 }
0472 }
0473
0474
0475 void open_ifstream(std::ifstream &ifs, const std::string &fname, const char *pfx = nullptr) {
0476 ifs.open(fname);
0477 if (!ifs) {
0478 char m[2048];
0479 snprintf(m, 2048, "%s%sError opening %s for read: %m", pfx ? pfx : "", pfx ? " " : "", fname.c_str());
0480 throw std::runtime_error(m);
0481 }
0482 }
0483
0484
0485 bool skipws_ifstream(std::ifstream &ifs) {
0486 while (std::isspace(ifs.peek()))
0487 ifs.get();
0488 return !ifs.eof();
0489 }
0490 }
0491
0492 void ConfigJson::patch_Files(IterationsInfo &its_info,
0493 const std::vector<std::string> &fnames,
0494 ConfigJsonPatcher::PatchReport *report) {
0495 ConfigJsonPatcher cjp(m_verbose);
0496 cjp.load(its_info);
0497
0498 ConfigJsonPatcher::PatchReport rep;
0499
0500 for (auto &fname : fnames) {
0501 std::ifstream ifs;
0502 open_ifstream(ifs, fname, __func__);
0503
0504 if (m_verbose) {
0505 printf("%s begin reading from file %s.\n", __func__, fname.c_str());
0506 }
0507
0508 int n_read = 0, n_tot_replaced = 0;
0509 while (skipws_ifstream(ifs)) {
0510 nlohmann::json j;
0511 ifs >> j;
0512 ++n_read;
0513
0514 if (m_verbose) {
0515 std::cout << " Read JSON entity " << n_read << " -- applying patch:\n";
0516
0517 }
0518
0519 int n_replaced = cjp.replace(j);
0520
0521 if (m_verbose) {
0522 std::cout << " Replaced " << n_replaced << " entries.\n";
0523 }
0524 cjp.cd_top();
0525 n_tot_replaced += n_replaced;
0526 }
0527
0528 if (m_verbose) {
0529 printf("%s read %d JSON entities from file %s, replaced %d parameters.\n",
0530 __func__,
0531 n_read,
0532 fname.c_str(),
0533 n_tot_replaced);
0534 }
0535
0536 ifs.close();
0537
0538 rep.inc_counts(1, n_read, n_tot_replaced);
0539 }
0540
0541 if (rep.n_replacements > 0) {
0542 cjp.save(its_info);
0543 }
0544
0545 if (report)
0546 report->inc_counts(rep);
0547 }
0548
0549 std::unique_ptr<IterationConfig> ConfigJson::patchLoad_File(const IterationsInfo &its_info,
0550 const std::string &fname,
0551 ConfigJsonPatcher::PatchReport *report) {
0552 ConfigJsonPatcher::PatchReport rep;
0553
0554 std::ifstream ifs;
0555 open_ifstream(ifs, fname, __func__);
0556
0557 if (m_verbose) {
0558 printf("%s begin reading from file %s.\n", __func__, fname.c_str());
0559 }
0560
0561 if (!skipws_ifstream(ifs))
0562 throw std::runtime_error("empty file");
0563
0564 nlohmann::json j;
0565 ifs >> j;
0566 int track_algo = j["m_track_algorithm"];
0567
0568 int iii = -1;
0569 for (int i = 0; i < its_info.size(); ++i) {
0570 if (its_info[i].m_track_algorithm == track_algo) {
0571 iii = i;
0572 break;
0573 }
0574 }
0575 if (iii == -1)
0576 throw std::runtime_error("matching IterationConfig not found");
0577
0578 if (m_verbose) {
0579 std::cout << " Read JSON entity, Iteration index is " << iii << " -- cloning and applying JSON patch:\n";
0580 }
0581
0582 IterationConfig *icp = new IterationConfig(its_info[iii]);
0583 IterationConfig &ic = *icp;
0584
0585 ConfigJsonPatcher cjp(m_verbose);
0586 cjp.load(ic);
0587
0588 int n_replaced = cjp.replace(j);
0589
0590 cjp.cd_top();
0591
0592 if (m_verbose) {
0593 printf("%s read 1 JSON entity from file %s, replaced %d parameters.\n", __func__, fname.c_str(), n_replaced);
0594 }
0595
0596 ifs.close();
0597
0598 rep.inc_counts(1, 1, n_replaced);
0599
0600 if (rep.n_replacements > 0) {
0601 cjp.save(ic);
0602 }
0603
0604 if (report)
0605 report->inc_counts(rep);
0606
0607 return std::unique_ptr<IterationConfig>(icp);
0608 }
0609
0610 std::unique_ptr<IterationConfig> ConfigJson::load_File(const std::string &fname) {
0611 std::ifstream ifs;
0612 open_ifstream(ifs, fname, __func__);
0613
0614 if (m_verbose) {
0615 printf("%s begin reading from file %s.\n", __func__, fname.c_str());
0616 }
0617
0618 if (!skipws_ifstream(ifs))
0619 throw std::runtime_error("empty file");
0620
0621 nlohmann::json j;
0622 ifs >> j;
0623
0624 if (m_verbose) {
0625 std::cout << " Read JSON entity, iteration index is " << j["m_iteration_index"] << ", track algorithm is "
0626 << j["m_track_algorithm"] << ". Instantiating IterationConfig object and over-laying it with JSON.\n";
0627 }
0628
0629 IterationConfig *icp = new IterationConfig();
0630
0631 from_json(j, *icp);
0632
0633 return std::unique_ptr<IterationConfig>(icp);
0634 }
0635
0636
0637
0638
0639
0640 void ConfigJson::save_Iterations(IterationsInfo &its_info,
0641 const std::string &fname_fmt,
0642 bool include_iter_info_preamble) {
0643 bool has_pct_d = fname_fmt.find("%d") != std::string::npos;
0644 bool has_pct_s = fname_fmt.find("%s") != std::string::npos;
0645
0646 assert((has_pct_d || has_pct_s) && "JSON save filename-format must include a %d or %s substring");
0647 assert(!(has_pct_d && has_pct_s) && "JSON save filename-format must include only one of %d or %s substrings");
0648
0649 for (int ii = 0; ii < its_info.size(); ++ii) {
0650 const IterationConfig &itconf = its_info[ii];
0651
0652 char fname[1024];
0653 if (has_pct_d)
0654 snprintf(fname, 1024, fname_fmt.c_str(), ii);
0655 else
0656 snprintf(fname, 1024, fname_fmt.c_str(), TrackBase::algoint_to_cstr(itconf.m_track_algorithm));
0657
0658 std::ofstream ofs;
0659 open_ofstream(ofs, fname, __func__);
0660
0661 if (include_iter_info_preamble) {
0662 ofs << "{ \"m_iterations/" << ii << "\": ";
0663 }
0664
0665 nlohmann::ordered_json j;
0666 to_json(j, itconf);
0667
0668 ofs << std::setw(1);
0669 ofs << j;
0670
0671 if (include_iter_info_preamble) {
0672 ofs << " }";
0673 }
0674
0675 ofs << "\n";
0676 ofs.close();
0677 }
0678 }
0679
0680 void ConfigJson::dump(IterationsInfo &its_info) {
0681 nlohmann::ordered_json j = its_info;
0682 std::cout << j.dump(3) << "\n";
0683 }
0684
0685
0686
0687
0688
0689 void ConfigJson::test_Direct(IterationConfig &it_cfg) {
0690 using nlohmann::json;
0691
0692 std::string lojz("/m_select_max_dphi");
0693
0694 json j = it_cfg;
0695 std::cout << j.dump(1) << "\n";
0696
0697 std::cout << "Layer 43, m_select_max_dphi = " << j["/m_layer_configs/43/m_select_max_dphi"_json_pointer] << "\n";
0698 std::cout << "Patching it to pi ...\n";
0699 json p = R"([
0700 { "op": "replace", "path": "/m_layer_configs/43/m_select_max_dphi", "value": 3.141 }
0701 ])"_json;
0702 j = j.patch(p);
0703 std::cout << "Layer 43, m_select_max_dphi = " << j["/m_layer_configs/43/m_select_max_dphi"_json_pointer] << "\n";
0704
0705 auto &jx = j["/m_layer_configs/60"_json_pointer];
0706
0707 json::json_pointer jp(lojz);
0708 jx[jp] = 99.876;
0709
0710
0711
0712 from_json(j, it_cfg);
0713 printf("Layer 43 : m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
0714 it_cfg.m_layer_configs[43].m_select_max_dphi,
0715 (int)it_cfg.m_layer_configs.size(),
0716 it_cfg.m_n_regions,
0717 (int)it_cfg.m_steering_params.size());
0718
0719 printf("Layer 60 : m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
0720 it_cfg.m_layer_configs[60].m_select_max_dphi,
0721 (int)it_cfg.m_layer_configs.size(),
0722 it_cfg.m_n_regions,
0723 (int)it_cfg.m_steering_params.size());
0724
0725
0726
0727
0728
0729 auto &x = j["/m_layer_configs"_json_pointer];
0730 std::cout << "Typename /m_layer_configs " << x.type_name() << "\n";
0731 auto &y = j["/m_layer_configs/143"_json_pointer];
0732 std::cout << "Typename /m_layer_configs/143 " << y.type_name() << ", is_null=" << y.is_null() << "\n";
0733 }
0734
0735 void ConfigJson::test_Patcher(IterationConfig &it_cfg) {
0736 ConfigJsonPatcher cjp;
0737 cjp.load(it_cfg);
0738
0739 std::cout << cjp.dump(1) << "\n";
0740
0741 {
0742 cjp.cd("/m_layer_configs/43/m_select_max_dphi");
0743 std::cout << "Layer 43, m_select_max_dphi = " << cjp.get("") << "\n";
0744 std::cout << "Setting it to pi ...\n";
0745 cjp.replace("", 3.141);
0746 cjp.cd_top();
0747 std::cout << "Layer 43, m_select_max_dphi = " << cjp.get("/m_layer_configs/43/m_select_max_dphi") << "\n";
0748 }
0749 {
0750 std::cout << "Replacing layer 60 m_select_max_dphi with full path\n";
0751 cjp.replace("/m_layer_configs/60/m_select_max_dphi", 99.876);
0752 }
0753 try {
0754 std::cout << "Trying to replace an non-existent array entry\n";
0755 cjp.replace("/m_layer_configs/1460/m_select_max_dphi", 666.666);
0756 } catch (std::exception &exc) {
0757 std::cout << "Caugth exception: " << exc.what() << "\n";
0758 }
0759 try {
0760 std::cout << "Trying to replace an non-existent object entry\n";
0761 cjp.replace("/m_layer_configs/1/moo_select_max_dphi", 666.666);
0762 } catch (std::exception &exc) {
0763 std::cout << "Caugth exception: " << exc.what() << "\n";
0764 }
0765 {
0766 std::cout << "Replacing m_select_max_dphi on layers 1 to 3 to 7.7\n";
0767 cjp.cd("/m_layer_configs");
0768 cjp.replace(1, 3, "/m_select_max_dphi", 7.7);
0769 cjp.cd_top();
0770 }
0771
0772
0773
0774 cjp.save(it_cfg);
0775
0776 printf("Layer 43: m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
0777 it_cfg.m_layer_configs[43].m_select_max_dphi,
0778 (int)it_cfg.m_layer_configs.size(),
0779 it_cfg.m_n_regions,
0780 (int)it_cfg.m_steering_params.size());
0781
0782 printf("Layer 60: m_select_max_dphi = %f\n", it_cfg.m_layer_configs[60].m_select_max_dphi);
0783 for (int i = 0; i < 5; ++i)
0784 printf("Layer %2d: m_select_max_dphi = %f\n", i, it_cfg.m_layer_configs[i].m_select_max_dphi);
0785
0786
0787
0788
0789
0790 auto &j = cjp.get("");
0791
0792 auto &x = j["/m_layer_configs"_json_pointer];
0793 std::cout << "Typename /m_layer_configs " << x.type_name() << "\n";
0794 auto &y = j["/m_layer_configs/143"_json_pointer];
0795 std::cout << "Typename /m_layer_configs/143 " << y.type_name() << ", is_null=" << y.is_null() << "\n";
0796 }
0797
0798 }