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