9 #include "nlohmann/json.hpp" 18 #define ITCONF_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ 19 inline void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) { \ 20 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \ 22 inline void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) { \ 23 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \ 25 inline void to_json(nlohmann::ordered_json &nlohmann_json_j, const Type &nlohmann_json_t) { \ 26 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \ 28 inline void from_json(const nlohmann::ordered_json &nlohmann_json_j, Type &nlohmann_json_t) { \ 29 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \ 72 m_seed_partitioner_name,
73 m_pre_bkfit_filter_name,
74 m_post_bkfit_filter_name,
75 m_duplicate_cleaner_name,
76 m_default_track_scorer_name,
77 m_requires_seed_hit_sorting,
79 m_backward_drop_seed_hits,
80 m_backward_fit_min_hits,
110 std::map<std::string, clean_seeds_func> seed_cleaners;
111 std::map<std::string, partition_seeds_func> seed_partitioners;
112 std::map<std::string, filter_candidates_func> candidate_filters;
113 std::map<std::string, clean_duplicates_func> duplicate_cleaners;
114 std::map<std::string, track_score_func> track_scorers;
119 FuncCatalog &get_catalog() {
126 auto &fc = get_catalog(); \ 127 const std::lock_guard<std::mutex> lock(fc.catalog_mutex) 131 fc.seed_cleaners.insert({
name,
func});
135 fc.seed_partitioners.insert({
name,
func});
139 fc.candidate_filters.insert({
name,
func});
143 fc.duplicate_cleaners.insert({
name,
func});
147 fc.track_scorers.insert({
name,
func});
159 es +=
" '" +
name +
"' not found in function registry.";
160 throw std::runtime_error(es);
168 return resolve_func_name(fc.seed_cleaners,
name, __func__);
172 return resolve_func_name(fc.seed_partitioners,
name, __func__);
176 return resolve_func_name(fc.candidate_filters,
name, __func__);
180 return resolve_func_name(fc.duplicate_cleaners,
name, __func__);
184 return resolve_func_name(fc.track_scorers,
name, __func__);
204 dprintf(
" Set post_bkfit_filter for '%s' %s\n",
209 dprintf(
" Set duplicate_cleaner for '%s' %s\n",
239 s =
"ConfigJsonPatcher";
252 m_json = std::make_unique<nlohmann::json>();
256 template void ConfigJsonPatcher::load<IterationsInfo>(
const IterationsInfo &
o);
257 template void ConfigJsonPatcher::load<IterationConfig>(
const IterationConfig &
o);
269 auto &itc_arr = m_json->at(
"m_iterations");
270 for (
int i = 0;
i <
o.size(); ++
i) {
276 nlohmann::json::json_pointer jp(
path);
284 throw std::runtime_error(
"JSON stack empty on cd_up");
301 template <
typename T>
303 nlohmann::json::json_pointer jp(
path);
308 template void ConfigJsonPatcher::replace<double>(
const std::string &
path,
double val);
310 template <
typename T>
312 nlohmann::json::json_pointer jp(
path);
322 nlohmann::json::json_pointer jp(
path);
328 throw std::runtime_error(
exc_hdr(__func__) +
"null not expected");
330 if (
j.is_boolean() ||
j.is_number() ||
j.is_string()) {
331 throw std::runtime_error(
exc_hdr(__func__) +
"value not expected on this parsing level");
337 static const std::regex index_range_re(
"^\\[(\\d+)..(\\d+)\\]$", std::regex::optimize);
341 std::regex_search(
key,
m, index_range_re);
345 throw std::runtime_error(
exc_hdr(__func__) +
"array range encountered when current json is not an array");
346 int first = std::stoi(
m.str(1));
347 int last = std::stoi(
m.str(2));
352 if (
value.is_array()) {
353 for (
auto &el :
value)
360 }
else if (
value.is_array() ||
value.is_object()) {
366 }
else if (
value.is_number() ||
value.is_boolean() ||
value.is_string()) {
369 nlohmann::json::json_pointer jp(
s);
378 throw std::runtime_error(
exc_hdr(__func__) +
"unexpected value type");
381 }
else if (
j.is_array() &&
j.empty()) {
382 }
else if (
j.is_array()) {
395 static const std::regex index_re(
"^(?:\\[\\d+..\\d+\\]|\\d+(?:/.*)?)$", std::regex::optimize);
397 bool has_index =
false, has_plain =
false;
398 for (
int i = 0;
i < (
int)
j.size(); ++
i) {
402 throw std::runtime_error(
exc_hdr(__func__) +
"array elements expected to be objects");
404 for (nlohmann::json::const_iterator it = el.begin(); it != el.end(); ++it) {
405 if (std::regex_search(it.key(), index_re)) {
408 throw std::runtime_error(
exc_hdr(__func__) +
"indexed array entry following plain one");
412 throw std::runtime_error(
exc_hdr(__func__) +
"plain array entry following indexed one");
417 for (
auto &element :
j) {
418 n_replaced +=
replace(element);
422 throw std::runtime_error(
exc_hdr(__func__) +
"plain array detected when current is not an array");
424 throw std::runtime_error(
exc_hdr(__func__) +
"plain array of different size than at current pos");
427 for (
int i = 0;
i < (
int)
j.size(); ++
i) {
436 throw std::runtime_error(
exc_hdr(__func__) +
"unexpected json type");
463 void open_ofstream(std::ofstream &ofs,
const std::string &
fname,
const char *
pfx =
nullptr) {
467 snprintf(
m, 2048,
"%s%sError opening %s for write: %m",
pfx ?
pfx :
"",
pfx ?
" " :
"",
fname.c_str());
468 throw std::runtime_error(
m);
473 void open_ifstream(std::ifstream &ifs,
const std::string &
fname,
const char *
pfx =
nullptr) {
477 snprintf(
m, 2048,
"%s%sError opening %s for read: %m",
pfx ?
pfx :
"",
pfx ?
" " :
"",
fname.c_str());
478 throw std::runtime_error(
m);
483 bool skipws_ifstream(std::ifstream &ifs) {
484 while (std::isspace(ifs.peek()))
491 const std::vector<std::string> &
fnames,
500 open_ifstream(ifs,
fname, __func__);
503 printf(
"%s begin reading from file %s.\n", __func__,
fname.c_str());
506 int n_read = 0, n_tot_replaced = 0;
507 while (skipws_ifstream(ifs)) {
513 std::cout <<
" Read JSON entity " << n_read <<
" -- applying patch:\n";
520 std::cout <<
" Replaced " << n_replaced <<
" entries.\n";
523 n_tot_replaced += n_replaced;
527 printf(
"%s read %d JSON entities from file %s, replaced %d parameters.\n",
536 rep.inc_counts(1, n_read, n_tot_replaced);
539 if (
rep.n_replacements > 0) {
553 open_ifstream(ifs,
fname, __func__);
556 printf(
"%s begin reading from file %s.\n", __func__,
fname.c_str());
559 if (!skipws_ifstream(ifs))
560 throw std::runtime_error(
"empty file");
564 int track_algo =
j[
"m_track_algorithm"];
567 for (
int i = 0;
i < its_info.
size(); ++
i) {
568 if (its_info[
i].m_track_algorithm == track_algo) {
574 throw std::runtime_error(
"matching IterationConfig not found");
577 std::cout <<
" Read JSON entity, Iteration index is " << iii <<
" -- cloning and applying JSON patch:\n";
591 printf(
"%s read 1 JSON entity from file %s, replaced %d parameters.\n", __func__,
fname.c_str(), n_replaced);
596 rep.inc_counts(1, 1, n_replaced);
598 if (
rep.n_replacements > 0) {
605 return std::unique_ptr<IterationConfig>(icp);
610 open_ifstream(ifs,
fname, __func__);
613 printf(
"%s begin reading from file %s.\n", __func__,
fname.c_str());
616 if (!skipws_ifstream(ifs))
617 throw std::runtime_error(
"empty file");
623 std::cout <<
" Read JSON entity, iteration index is " <<
j[
"m_iteration_index"] <<
", track algorithm is " 624 <<
j[
"m_track_algorithm"] <<
". Instantiating IterationConfig object and over-laying it with JSON.\n";
631 return std::unique_ptr<IterationConfig>(icp);
640 bool include_iter_info_preamble) {
641 bool has_pct_d = fname_fmt.find(
"%d") != std::string::npos;
642 bool has_pct_s = fname_fmt.find(
"%s") != std::string::npos;
644 assert((has_pct_d || has_pct_s) &&
"JSON save filename-format must include a %d or %s substring");
645 assert(!(has_pct_d && has_pct_s) &&
"JSON save filename-format must include only one of %d or %s substrings");
647 for (
int ii = 0;
ii < its_info.
size(); ++
ii) {
652 snprintf(
fname, 1024, fname_fmt.c_str(),
ii);
657 open_ofstream(ofs,
fname, __func__);
659 if (include_iter_info_preamble) {
660 ofs <<
"{ \"m_iterations/" <<
ii <<
"\": ";
663 nlohmann::ordered_json
j;
669 if (include_iter_info_preamble) {
679 nlohmann::ordered_json
j = its_info;
695 std::cout <<
"Layer 43, m_select_max_dphi = " <<
j[
"/m_layer_configs/43/m_select_max_dphi"_json_pointer] <<
"\n";
698 { "op": "replace", "path": "/m_layer_configs/43/m_select_max_dphi", "value": 3.141 } 701 std::cout << "Layer 43, m_select_max_dphi = " <<
j[
"/m_layer_configs/43/m_select_max_dphi"_json_pointer] <<
"\n";
703 auto &jx =
j[
"/m_layer_configs/60"_json_pointer];
705 json::json_pointer jp(lojz);
711 printf(
"Layer 43 : m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
717 printf(
"Layer 60 : m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
727 auto &
x =
j[
"/m_layer_configs"_json_pointer];
728 std::cout <<
"Typename /m_layer_configs " <<
x.type_name() <<
"\n";
729 auto &y =
j[
"/m_layer_configs/143"_json_pointer];
730 std::cout <<
"Typename /m_layer_configs/143 " << y.type_name() <<
", is_null=" << y.is_null() <<
"\n";
740 cjp.
cd(
"/m_layer_configs/43/m_select_max_dphi");
741 std::cout <<
"Layer 43, m_select_max_dphi = " << cjp.
get(
"") <<
"\n";
745 std::cout <<
"Layer 43, m_select_max_dphi = " << cjp.
get(
"/m_layer_configs/43/m_select_max_dphi") <<
"\n";
748 std::cout <<
"Replacing layer 60 m_select_max_dphi with full path\n";
749 cjp.
replace(
"/m_layer_configs/60/m_select_max_dphi", 99.876);
752 std::cout <<
"Trying to replace an non-existent array entry\n";
753 cjp.
replace(
"/m_layer_configs/1460/m_select_max_dphi", 666.666);
755 std::cout <<
"Caugth exception: " << exc.what() <<
"\n";
758 std::cout <<
"Trying to replace an non-existent object entry\n";
759 cjp.
replace(
"/m_layer_configs/1/moo_select_max_dphi", 666.666);
761 std::cout <<
"Caugth exception: " << exc.what() <<
"\n";
764 std::cout <<
"Replacing m_select_max_dphi on layers 1 to 3 to 7.7\n";
765 cjp.
cd(
"/m_layer_configs");
766 cjp.
replace(1, 3,
"/m_select_max_dphi", 7.7);
774 printf(
"Layer 43: m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
780 printf(
"Layer 60: m_select_max_dphi = %f\n", it_cfg.
m_layer_configs[60].m_select_max_dphi);
781 for (
int i = 0;
i < 5; ++
i)
782 printf(
"Layer %2d: m_select_max_dphi = %f\n",
i, it_cfg.
m_layer_configs[
i].m_select_max_dphi);
788 auto &
j = cjp.
get(
"");
790 auto &
x =
j[
"/m_layer_configs"_json_pointer];
791 std::cout <<
"Typename /m_layer_configs " <<
x.type_name() <<
"\n";
792 auto &y =
j[
"/m_layer_configs/143"_json_pointer];
793 std::cout <<
"Typename /m_layer_configs/143 " << y.type_name() <<
", is_null=" << y.is_null() <<
"\n";
nlohmann::json * m_current
std::string m_pre_bkfit_filter_name
static void register_seed_partitioner(const std::string &name, partition_seeds_func func)
static void register_track_scorer(const std::string &name, track_score_func func)
void to_json(nlohmann::json &nlohmann_json_j, const mkfit::LayerControl &nlohmann_json_t)
std::string to_string(const V &value)
std::string dump(int indent=2)
std::string m_seed_cleaner_name
std::string m_seed_partitioner_name
static void register_duplicate_cleaner(const std::string &name, clean_duplicates_func func)
std::function< track_score_cf > track_score_func
clean_seeds_func m_seed_cleaner
void replace(const std::string &path, T val)
#define ITCONF_DEFINE_TYPE_NON_INTRUSIVE(Type,...)
static filter_candidates_func get_candidate_filter(const std::string &name)
void test_Direct(IterationConfig &it_cfg)
void patch_Files(IterationsInfo &its_info, const std::vector< std::string > &fnames, ConfigJsonPatcher::PatchReport *report=nullptr)
std::string exc_hdr(const char *func=nullptr) const
std::function< filter_candidates_cf > filter_candidates_func
std::vector< nlohmann::json * > m_json_stack
std::vector< IterationLayerConfig > m_layer_configs
static void register_seed_cleaner(const std::string &name, clean_seeds_func func)
static partition_seeds_func get_seed_partitioner(const std::string &name)
void setupStandardFunctionsFromNames()
std::string m_default_track_scorer_name
partition_seeds_func m_seed_partitioner
std::unique_ptr< IterationConfig > patchLoad_File(const IterationsInfo &its_info, const std::string &fname, ConfigJsonPatcher::PatchReport *report=nullptr)
nlohmann::json & get(const std::string &path)
std::string m_post_bkfit_filter_name
void cd(const std::string &path)
std::vector< std::string > m_path_stack
void save_Iterations(IterationsInfo &its_info, const std::string &fname_fmt, bool include_iter_info_preamble)
void test_Patcher(IterationConfig &it_cfg)
void from_json(const nlohmann::json &nlohmann_json_j, mkfit::LayerControl &nlohmann_json_t)
static const char * algoint_to_cstr(int algo)
filter_candidates_func m_post_bkfit_filter
static track_score_func get_track_scorer(const std::string &name)
static clean_duplicates_func get_duplicate_cleaner(const std::string &name)
clean_duplicates_func m_duplicate_cleaner
std::unique_ptr< IterationConfig > load_File(const std::string &fname)
void dump(IterationsInfo &its_info)
std::unique_ptr< nlohmann::json > m_json
void cd_up(const std::string &path="")
ConfigJsonPatcher(bool verbose=false)
track_score_func m_default_track_scorer
std::function< clean_seeds_cf > clean_seeds_func
static clean_seeds_func get_seed_cleaner(const std::string &name)
filter_candidates_func m_pre_bkfit_filter
void cd_top(const std::string &path="")
std::vector< SteeringParams > m_steering_params
std::function< clean_duplicates_cf > clean_duplicates_func
std::string m_duplicate_cleaner_name
static void register_candidate_filter(const std::string &name, filter_candidates_func func)
cont
load Luminosity info ##
std::function< partition_seeds_cf > partition_seeds_func
std::string get_abs_path() const