/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
RecoTracker/MkFitCore/src/IterationConfig.cc
798 строк
29 KB
Matevz Tadel
Add bool IterationParams::useHitSelectionV2, when true use MkFinder::selectHitIndicesV2().
14 дек 2023, 23:28
14 дек 2023, 23:28
fc82e45
Код
Авторство
О чём код?
#include "RecoTracker/MkFitCore/interface/cms_common_macros.h" #include "RecoTracker/MkFitCore/interface/IterationConfig.h" #include "RecoTracker/MkFitCore/interface/Config.h" #include "RecoTracker/MkFitCore/interface/Track.h" //#define DEBUG #include "Debug.h" #include "nlohmann/json.hpp" #include <fstream> #include <mutex> #include <regex> #include <iostream> #include <iomanip> // Redefine to also support ordered_json ... we want to keep variable order in JSON save files. #define ITCONF_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ inline void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) { \ NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \ } \ inline void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) { \ NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \ } \ inline void to_json(nlohmann::ordered_json &nlohmann_json_j, const Type &nlohmann_json_t) { \ NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \ } \ inline void from_json(const nlohmann::ordered_json &nlohmann_json_j, Type &nlohmann_json_t) { \ NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \ } namespace mkfit { // Begin AUTO code, some members commented out. ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::LayerControl, /* int */ m_layer) ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::SteeringParams, /* std::vector<LayerControl> */ m_layer_plan, /* std::string */ m_track_scorer_name, /* int */ m_region, /* int */ m_fwd_search_pickup, /* int */ m_bkw_fit_last, /* int */ m_bkw_search_pickup) ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationLayerConfig, /* int */ m_layer, /* float */ m_select_min_dphi, /* float */ m_select_max_dphi, /* float */ m_select_min_dq, /* float */ m_select_max_dq, /* std::vector<float> */ m_winpars_fwd, /* std::vector<float> */ m_winpars_bkw) ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationParams, /* int */ nlayers_per_seed, /* int */ maxCandsPerSeed, /* int */ maxHolesPerCand, /* int */ maxConsecHoles, /* float */ chi2Cut_min, /* float */ chi2CutOverlap, /* float */ pTCutOverlap, /* bool */ recheckOverlap, /* bool */ useHitSelectionV2, /* int */ minHitsQF, /* float */ minPtCut, /* unsigned int */ maxClusterSize) ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationConfig, /* int */ m_iteration_index, /* int */ m_track_algorithm, /* std::string */ m_seed_cleaner_name, /* std::string */ m_seed_partitioner_name, /* std::string */ m_pre_bkfit_filter_name, /* std::string */ m_post_bkfit_filter_name, /* std::string */ m_duplicate_cleaner_name, /* std::string */ m_default_track_scorer_name, /* bool */ m_requires_seed_hit_sorting, /* bool */ m_backward_search, /* bool */ m_backward_drop_seed_hits, /* int */ m_backward_fit_min_hits, /* float */ sc_ptthr_hpt, /* float */ sc_drmax_bh, /* float */ sc_dzmax_bh, /* float */ sc_drmax_eh, /* float */ sc_dzmax_eh, /* float */ sc_drmax_bl, /* float */ sc_dzmax_bl, /* float */ sc_drmax_el, /* float */ sc_dzmax_el, /* float */ dc_fracSharedHits, /* float */ dc_drth_central, /* float */ dc_drth_obarrel, /* float */ dc_drth_forward, /* mkfit::IterationParams */ m_params, /* mkfit::IterationParams */ m_backward_params, /* int */ m_n_regions, /* vector<int> */ m_region_order, /* vector<mkfit::SteeringParams> */ m_steering_params, /* vector<mkfit::IterationLayerConfig> */ m_layer_configs) ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationsInfo, /* vector<mkfit::IterationConfig> */ m_iterations) // End AUTO code. // Begin IterationConfig function catalogs namespace { struct FuncCatalog { std::map<std::string, clean_seeds_func> seed_cleaners; std::map<std::string, partition_seeds_func> seed_partitioners; std::map<std::string, filter_candidates_func> candidate_filters; std::map<std::string, clean_duplicates_func> duplicate_cleaners; std::map<std::string, track_score_func> track_scorers; std::mutex catalog_mutex; }; FuncCatalog &get_catalog() { CMS_SA_ALLOW static FuncCatalog func_catalog; return func_catalog; } } // namespace #define GET_FC \ auto &fc = get_catalog(); \ const std::lock_guard<std::mutex> lock(fc.catalog_mutex) void IterationConfig::register_seed_cleaner(const std::string &name, clean_seeds_func func) { GET_FC; fc.seed_cleaners.insert({name, func}); } void IterationConfig::register_seed_partitioner(const std::string &name, partition_seeds_func func) { GET_FC; fc.seed_partitioners.insert({name, func}); } void IterationConfig::register_candidate_filter(const std::string &name, filter_candidates_func func) { GET_FC; fc.candidate_filters.insert({name, func}); } void IterationConfig::register_duplicate_cleaner(const std::string &name, clean_duplicates_func func) { GET_FC; fc.duplicate_cleaners.insert({name, func}); } void IterationConfig::register_track_scorer(const std::string &name, track_score_func func) { GET_FC; fc.track_scorers.insert({name, func}); } namespace { template <class T> typename T::mapped_type resolve_func_name(const T &cont, const std::string &name, const char *func) { if (name.empty()) { return nullptr; } auto ii = cont.find(name); if (ii == cont.end()) { std::string es(func); es += " '" + name + "' not found in function registry."; throw std::runtime_error(es); } return ii->second; } } // namespace clean_seeds_func IterationConfig::get_seed_cleaner(const std::string &name) { GET_FC; return resolve_func_name(fc.seed_cleaners, name, __func__); } partition_seeds_func IterationConfig::get_seed_partitioner(const std::string &name) { GET_FC; return resolve_func_name(fc.seed_partitioners, name, __func__); } filter_candidates_func IterationConfig::get_candidate_filter(const std::string &name) { GET_FC; return resolve_func_name(fc.candidate_filters, name, __func__); } clean_duplicates_func IterationConfig::get_duplicate_cleaner(const std::string &name) { GET_FC; return resolve_func_name(fc.duplicate_cleaners, name, __func__); } track_score_func IterationConfig::get_track_scorer(const std::string &name) { GET_FC; return resolve_func_name(fc.track_scorers, name, __func__); } #undef GET_FC // End IterationConfig function catalogs void IterationConfig::setupStandardFunctionsFromNames() { m_seed_cleaner = get_seed_cleaner(m_seed_cleaner_name); dprintf(" Set seed_cleaner for '%s' %s\n", m_seed_cleaner_name.c_str(), m_seed_cleaner ? "SET" : "NOT SET"); m_seed_partitioner = get_seed_partitioner(m_seed_partitioner_name); dprintf( " Set seed_partitioner for '%s' %s\n", m_seed_partitioner_name.c_str(), m_seed_partitioner ? "SET" : "NOT SET"); m_pre_bkfit_filter = get_candidate_filter(m_pre_bkfit_filter_name); dprintf( " Set pre_bkfit_filter for '%s' %s\n", m_pre_bkfit_filter_name.c_str(), m_pre_bkfit_filter ? "SET" : "NOT SET"); m_post_bkfit_filter = get_candidate_filter(m_post_bkfit_filter_name); dprintf(" Set post_bkfit_filter for '%s' %s\n", m_post_bkfit_filter_name.c_str(), m_post_bkfit_filter ? "SET" : "NOT SET"); m_duplicate_cleaner = get_duplicate_cleaner(m_duplicate_cleaner_name); dprintf(" Set duplicate_cleaner for '%s' %s\n", m_duplicate_cleaner_name.c_str(), m_duplicate_cleaner ? "SET" : "NOT SET"); m_default_track_scorer = get_track_scorer(m_default_track_scorer_name); for (auto &sp : m_steering_params) { sp.m_track_scorer = sp.m_track_scorer_name.empty() ? m_default_track_scorer : get_track_scorer(sp.m_track_scorer_name); } } // ============================================================================ // ConfigJsonPatcher // ============================================================================ ConfigJsonPatcher::ConfigJsonPatcher(bool verbose) : m_verbose(verbose) {} ConfigJsonPatcher::~ConfigJsonPatcher() = default; std::string ConfigJsonPatcher::get_abs_path() const { std::string s; s.reserve(64); for (auto &p : m_path_stack) s += p; return s; } std::string ConfigJsonPatcher::exc_hdr(const char *func) const { std::string s; s.reserve(128); s = "ConfigJsonPatcher"; if (func) { s += "::"; s += func; } s += " '"; s += get_abs_path(); s += "' "; return s; } template <class T> void ConfigJsonPatcher::load(const T &o) { m_json = std::make_unique<nlohmann::json>(); *m_json = o; cd_top(); } template void ConfigJsonPatcher::load<IterationsInfo>(const IterationsInfo &o); template void ConfigJsonPatcher::load<IterationConfig>(const IterationConfig &o); template <class T> void ConfigJsonPatcher::save(T &o) { from_json(*m_json, o); } template void ConfigJsonPatcher::save<IterationConfig>(IterationConfig &o); // Must not bork the IterationConfig elements of IterationsInfo ... default // deserializator apparently reinitializes the vectors with defaults c-tors. template <> void ConfigJsonPatcher::save<IterationsInfo>(IterationsInfo &o) { auto &itc_arr = m_json->at("m_iterations"); for (int i = 0; i < o.size(); ++i) { from_json(itc_arr[i], o[i]); } } void ConfigJsonPatcher::cd(const std::string &path) { nlohmann::json::json_pointer jp(path); m_json_stack.push_back(m_current); m_path_stack.push_back(path); m_current = &m_current->at(jp); } void ConfigJsonPatcher::cd_up(const std::string &path) { if (m_json_stack.empty()) throw std::runtime_error("JSON stack empty on cd_up"); m_current = m_json_stack.back(); m_json_stack.pop_back(); m_path_stack.pop_back(); if (!path.empty()) cd(path); } void ConfigJsonPatcher::cd_top(const std::string &path) { m_current = m_json.get(); m_json_stack.clear(); m_path_stack.clear(); if (!path.empty()) cd(path); } template <typename T> void ConfigJsonPatcher::replace(const std::string &path, T val) { nlohmann::json::json_pointer jp(path); m_current->at(jp) = val; } template void ConfigJsonPatcher::replace<int>(const std::string &path, int val); template void ConfigJsonPatcher::replace<float>(const std::string &path, float val); template void ConfigJsonPatcher::replace<double>(const std::string &path, double val); template <typename T> void ConfigJsonPatcher::replace(int first, int last, const std::string &path, T val) { nlohmann::json::json_pointer jp(path); for (int i = first; i <= last; ++i) { m_current->at(i).at(jp) = val; } } template void ConfigJsonPatcher::replace<int>(int first, int last, const std::string &path, int val); template void ConfigJsonPatcher::replace<float>(int first, int last, const std::string &path, float val); template void ConfigJsonPatcher::replace<double>(int first, int last, const std::string &path, double val); nlohmann::json &ConfigJsonPatcher::get(const std::string &path) { nlohmann::json::json_pointer jp(path); return m_current->at(jp); } int ConfigJsonPatcher::replace(const nlohmann::json &j) { if (j.is_null()) throw std::runtime_error(exc_hdr(__func__) + "null not expected"); if (j.is_boolean() || j.is_number() || j.is_string()) { throw std::runtime_error(exc_hdr(__func__) + "value not expected on this parsing level"); } int n_replaced = 0; if (j.is_object()) { static const std::regex index_range_re("^\\[(\\d+)..(\\d+)\\]$", std::regex::optimize); for (auto &[key, value] : j.items()) { std::smatch m; std::regex_search(key, m, index_range_re); if (m.size() == 3) { if (!m_current->is_array()) throw std::runtime_error(exc_hdr(__func__) + "array range encountered when current json is not an array"); int first = std::stoi(m.str(1)); int last = std::stoi(m.str(2)); for (int i = first; i <= last; ++i) { std::string s("/"); s += std::to_string(i); cd(s); if (value.is_array()) { for (auto &el : value) n_replaced += replace(el); } else { n_replaced += replace(value); } cd_up(); } } else if (value.is_array() || value.is_object()) { std::string s("/"); s += key; cd(s); n_replaced += replace(value); cd_up(); } else if (value.is_number() || value.is_boolean() || value.is_string()) { std::string s("/"); s += key; nlohmann::json::json_pointer jp(s); if (m_current->at(jp) != value) { if (m_verbose) std::cout << " " << get_abs_path() << s << ": " << m_current->at(jp) << " -> " << value << "\n"; m_current->at(jp) = value; ++n_replaced; } } else { throw std::runtime_error(exc_hdr(__func__) + "unexpected value type"); } } } else if (j.is_array() && j.empty()) { } else if (j.is_array()) { // Arrays are somewhat tricky. // At the moment all elements are expected to be objects. // This means arrays of basic types are not supported (like layer index arrays). // Should not be too hard to add support for this. // Now, the objects in the array can be of two kinds: // a) Their keys can be json_pointer strings starting with numbers or ranges [i_low..i_high]. // b) They can be actual elements of the array. In this case we require the length of // the array to be equal to existing length in the configuration. // It is not allowed for these two kinds to mix. // Determine the kind of array: json_ptr or object static const std::regex index_re("^(?:\\[\\d+..\\d+\\]|\\d+(?:/.*)?)$", std::regex::optimize); bool has_index = false, has_plain = false; for (int i = 0; i < (int)j.size(); ++i) { const nlohmann::json &el = j[i]; if (!el.is_object()) throw std::runtime_error(exc_hdr(__func__) + "array elements expected to be objects"); for (nlohmann::json::const_iterator it = el.begin(); it != el.end(); ++it) { if (std::regex_search(it.key(), index_re)) { has_index = true; if (has_plain) throw std::runtime_error(exc_hdr(__func__) + "indexed array entry following plain one"); } else { has_plain = true; if (has_index) throw std::runtime_error(exc_hdr(__func__) + "plain array entry following indexed one"); } } } if (has_index) { for (auto &element : j) { n_replaced += replace(element); } } else { if (m_current && !m_current->is_array()) throw std::runtime_error(exc_hdr(__func__) + "plain array detected when current is not an array"); if (m_current->size() != j.size()) throw std::runtime_error(exc_hdr(__func__) + "plain array of different size than at current pos"); std::string s; for (int i = 0; i < (int)j.size(); ++i) { s = "/"; s += std::to_string(i); cd(s); n_replaced += replace(j[i]); cd_up(); } } } else { throw std::runtime_error(exc_hdr(__func__) + "unexpected json type"); } return n_replaced; } std::string ConfigJsonPatcher::dump(int indent) { return m_json->dump(indent); } // ============================================================================ // patch_File steering function // ============================================================================ /* See example JSON patcher input: "mkFit/config-parse/test.json" The file can contain several valid JSON dumps in sequence. '/' character can be used to descend more than one level at a time. A number can be used to specify an array index. This can be combined with the '/' syntax. "[first,last]" key (as string) can be used to denote a range of array elements. Such a key must not be combined with a '/' syntax. */ namespace { // Open file for writing, throw exception on failure. void open_ofstream(std::ofstream &ofs, const std::string &fname, const char *pfx = nullptr) { ofs.open(fname, std::ofstream::trunc); if (!ofs) { char m[2048]; snprintf(m, 2048, "%s%sError opening %s for write: %m", pfx ? pfx : "", pfx ? " " : "", fname.c_str()); throw std::runtime_error(m); } } // Open file for reading, throw exception on failure. void open_ifstream(std::ifstream &ifs, const std::string &fname, const char *pfx = nullptr) { ifs.open(fname); if (!ifs) { char m[2048]; snprintf(m, 2048, "%s%sError opening %s for read: %m", pfx ? pfx : "", pfx ? " " : "", fname.c_str()); throw std::runtime_error(m); } } // Skip white-space, return true if more characters are available, false if eof. bool skipws_ifstream(std::ifstream &ifs) { while (std::isspace(ifs.peek())) ifs.get(); return !ifs.eof(); } } // namespace void ConfigJson::patch_Files(IterationsInfo &its_info, const std::vector<std::string> &fnames, ConfigJsonPatcher::PatchReport *report) { ConfigJsonPatcher cjp(m_verbose); cjp.load(its_info); ConfigJsonPatcher::PatchReport rep; for (auto &fname : fnames) { std::ifstream ifs; open_ifstream(ifs, fname, __func__); if (m_verbose) { printf("%s begin reading from file %s.\n", __func__, fname.c_str()); } int n_read = 0, n_tot_replaced = 0; while (skipws_ifstream(ifs)) { nlohmann::json j; ifs >> j; ++n_read; if (m_verbose) { std::cout << " Read JSON entity " << n_read << " -- applying patch:\n"; // std::cout << j.dump(3) << "\n"; } int n_replaced = cjp.replace(j); if (m_verbose) { std::cout << " Replaced " << n_replaced << " entries.\n"; } cjp.cd_top(); n_tot_replaced += n_replaced; } if (m_verbose) { printf("%s read %d JSON entities from file %s, replaced %d parameters.\n", __func__, n_read, fname.c_str(), n_tot_replaced); } ifs.close(); rep.inc_counts(1, n_read, n_tot_replaced); } if (rep.n_replacements > 0) { cjp.save(its_info); } if (report) report->inc_counts(rep); } std::unique_ptr<IterationConfig> ConfigJson::patchLoad_File(const IterationsInfo &its_info, const std::string &fname, ConfigJsonPatcher::PatchReport *report) { ConfigJsonPatcher::PatchReport rep; std::ifstream ifs; open_ifstream(ifs, fname, __func__); if (m_verbose) { printf("%s begin reading from file %s.\n", __func__, fname.c_str()); } if (!skipws_ifstream(ifs)) throw std::runtime_error("empty file"); nlohmann::json j; ifs >> j; int track_algo = j["m_track_algorithm"]; int iii = -1; for (int i = 0; i < its_info.size(); ++i) { if (its_info[i].m_track_algorithm == track_algo) { iii = i; break; } } if (iii == -1) throw std::runtime_error("matching IterationConfig not found"); if (m_verbose) { std::cout << " Read JSON entity, Iteration index is " << iii << " -- cloning and applying JSON patch:\n"; } IterationConfig *icp = new IterationConfig(its_info[iii]); IterationConfig &ic = *icp; ConfigJsonPatcher cjp(m_verbose); cjp.load(ic); int n_replaced = cjp.replace(j); cjp.cd_top(); if (m_verbose) { printf("%s read 1 JSON entity from file %s, replaced %d parameters.\n", __func__, fname.c_str(), n_replaced); } ifs.close(); rep.inc_counts(1, 1, n_replaced); if (rep.n_replacements > 0) { cjp.save(ic); } if (report) report->inc_counts(rep); return std::unique_ptr<IterationConfig>(icp); } std::unique_ptr<IterationConfig> ConfigJson::load_File(const std::string &fname) { std::ifstream ifs; open_ifstream(ifs, fname, __func__); if (m_verbose) { printf("%s begin reading from file %s.\n", __func__, fname.c_str()); } if (!skipws_ifstream(ifs)) throw std::runtime_error("empty file"); nlohmann::json j; ifs >> j; if (m_verbose) { std::cout << " Read JSON entity, iteration index is " << j["m_iteration_index"] << ", track algorithm is " << j["m_track_algorithm"] << ". Instantiating IterationConfig object and over-laying it with JSON.\n"; } IterationConfig *icp = new IterationConfig(); from_json(j, *icp); return std::unique_ptr<IterationConfig>(icp); } // ============================================================================ // Save each IterationConfig into a separate json file // ============================================================================ void ConfigJson::save_Iterations(IterationsInfo &its_info, const std::string &fname_fmt, bool include_iter_info_preamble) { bool has_pct_d = fname_fmt.find("%d") != std::string::npos; bool has_pct_s = fname_fmt.find("%s") != std::string::npos; assert((has_pct_d || has_pct_s) && "JSON save filename-format must include a %d or %s substring"); assert(!(has_pct_d && has_pct_s) && "JSON save filename-format must include only one of %d or %s substrings"); for (int ii = 0; ii < its_info.size(); ++ii) { const IterationConfig &itconf = its_info[ii]; char fname[1024]; if (has_pct_d) snprintf(fname, 1024, fname_fmt.c_str(), ii); else snprintf(fname, 1024, fname_fmt.c_str(), TrackBase::algoint_to_cstr(itconf.m_track_algorithm)); std::ofstream ofs; open_ofstream(ofs, fname, __func__); if (include_iter_info_preamble) { ofs << "{ \"m_iterations/" << ii << "\": "; } nlohmann::ordered_json j; to_json(j, itconf); ofs << std::setw(1); ofs << j; if (include_iter_info_preamble) { ofs << " }"; } ofs << "\n"; ofs.close(); } } void ConfigJson::dump(IterationsInfo &its_info) { nlohmann::ordered_json j = its_info; std::cout << j.dump(3) << "\n"; } // ============================================================================ // Tests for ConfigJson stuff // ============================================================================ void ConfigJson::test_Direct(IterationConfig &it_cfg) { using nlohmann::json; std::string lojz("/m_select_max_dphi"); json j = it_cfg; std::cout << j.dump(1) << "\n"; std::cout << "Layer 43, m_select_max_dphi = " << j["/m_layer_configs/43/m_select_max_dphi"_json_pointer] << "\n"; std::cout << "Patching it to pi ...\n"; json p = R"([ { "op": "replace", "path": "/m_layer_configs/43/m_select_max_dphi", "value": 3.141 } ])"_json; j = j.patch(p); std::cout << "Layer 43, m_select_max_dphi = " << j["/m_layer_configs/43/m_select_max_dphi"_json_pointer] << "\n"; auto &jx = j["/m_layer_configs/60"_json_pointer]; // jx["m_select_max_dphi"] = 99.876; json::json_pointer jp(lojz); jx[jp] = 99.876; // try loading it back, see what happens to vector m_layer_configs. from_json(j, it_cfg); printf("Layer 43 : m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n", it_cfg.m_layer_configs[43].m_select_max_dphi, (int)it_cfg.m_layer_configs.size(), it_cfg.m_n_regions, (int)it_cfg.m_steering_params.size()); printf("Layer 60 : m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n", it_cfg.m_layer_configs[60].m_select_max_dphi, (int)it_cfg.m_layer_configs.size(), it_cfg.m_n_regions, (int)it_cfg.m_steering_params.size()); // try accessing something that does not exist // std::cout << "Non-existent path " << j["/m_layer_configs/143/m_select_max_dphi"_json_pointer] << "\n"; auto &x = j["/m_layer_configs"_json_pointer]; std::cout << "Typename /m_layer_configs " << x.type_name() << "\n"; auto &y = j["/m_layer_configs/143"_json_pointer]; std::cout << "Typename /m_layer_configs/143 " << y.type_name() << ", is_null=" << y.is_null() << "\n"; } void ConfigJson::test_Patcher(IterationConfig &it_cfg) { ConfigJsonPatcher cjp; cjp.load(it_cfg); std::cout << cjp.dump(1) << "\n"; { cjp.cd("/m_layer_configs/43/m_select_max_dphi"); std::cout << "Layer 43, m_select_max_dphi = " << cjp.get("") << "\n"; std::cout << "Setting it to pi ...\n"; cjp.replace("", 3.141); cjp.cd_top(); std::cout << "Layer 43, m_select_max_dphi = " << cjp.get("/m_layer_configs/43/m_select_max_dphi") << "\n"; } { std::cout << "Replacing layer 60 m_select_max_dphi with full path\n"; cjp.replace("/m_layer_configs/60/m_select_max_dphi", 99.876); } try { std::cout << "Trying to replace an non-existent array entry\n"; cjp.replace("/m_layer_configs/1460/m_select_max_dphi", 666.666); } catch (std::exception &exc) { std::cout << "Caugth exception: " << exc.what() << "\n"; } try { std::cout << "Trying to replace an non-existent object entry\n"; cjp.replace("/m_layer_configs/1/moo_select_max_dphi", 666.666); } catch (std::exception &exc) { std::cout << "Caugth exception: " << exc.what() << "\n"; } { std::cout << "Replacing m_select_max_dphi on layers 1 to 3 to 7.7\n"; cjp.cd("/m_layer_configs"); cjp.replace(1, 3, "/m_select_max_dphi", 7.7); cjp.cd_top(); } // try getting it back into c++, see what happens to vector m_layer_configs. cjp.save(it_cfg); printf("Layer 43: m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n", it_cfg.m_layer_configs[43].m_select_max_dphi, (int)it_cfg.m_layer_configs.size(), it_cfg.m_n_regions, (int)it_cfg.m_steering_params.size()); printf("Layer 60: m_select_max_dphi = %f\n", it_cfg.m_layer_configs[60].m_select_max_dphi); for (int i = 0; i < 5; ++i) printf("Layer %2d: m_select_max_dphi = %f\n", i, it_cfg.m_layer_configs[i].m_select_max_dphi); // try accessing something that does not exist // std::cout << "Non-existent path " << j["/m_layer_configs/143/m_select_max_dphi"_json_pointer] << "\n"; auto &j = cjp.get(""); auto &x = j["/m_layer_configs"_json_pointer]; std::cout << "Typename /m_layer_configs " << x.type_name() << "\n"; auto &y = j["/m_layer_configs/143"_json_pointer]; std::cout << "Typename /m_layer_configs/143 " << y.type_name() << ", is_null=" << y.is_null() << "\n"; } } // namespace mkfit