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__)) \ 83 m_seed_partitioner_name,
84 m_pre_bkfit_filter_name,
85 m_post_bkfit_filter_name,
86 m_duplicate_cleaner_name,
87 m_requires_seed_hit_sorting,
89 m_backward_drop_seed_hits,
90 m_backward_fit_min_hits,
120 std::map<std::string, IterationConfig::clean_seeds_func> seed_cleaners;
121 std::map<std::string, IterationConfig::partition_seeds_func> seed_partitioners;
122 std::map<std::string, IterationConfig::filter_candidates_func> candidate_filters;
123 std::map<std::string, IterationConfig::clean_duplicates_func> duplicate_cleaners;
128 FuncCatalog &get_catalog() {
135 auto &fc = get_catalog(); \ 136 const std::lock_guard<std::mutex> lock(fc.catalog_mutex) 140 fc.seed_cleaners.insert({
name,
func});
144 fc.seed_partitioners.insert({
name,
func});
148 fc.candidate_filters.insert({
name,
func});
152 fc.duplicate_cleaners.insert({
name,
func});
164 es +=
" '" +
name +
"' not found in function registry.";
165 throw std::runtime_error(es);
173 return resolve_func_name(fc.seed_cleaners,
name, __func__);
177 return resolve_func_name(fc.seed_partitioners,
name, __func__);
181 return resolve_func_name(fc.candidate_filters,
name, __func__);
185 return resolve_func_name(fc.duplicate_cleaners,
name, __func__);
205 dprintf(
" Set post_bkfit_filter for '%s' %s\n",
210 dprintf(
" Set duplicate_cleaner for '%s' %s\n",
235 s =
"ConfigJsonPatcher";
248 m_json = std::make_unique<nlohmann::json>();
252 template void ConfigJsonPatcher::load<IterationsInfo>(
const IterationsInfo &
o);
253 template void ConfigJsonPatcher::load<IterationConfig>(
const IterationConfig &
o);
265 auto &itc_arr = m_json->at(
"m_iterations");
266 for (
int i = 0;
i <
o.size(); ++
i) {
272 nlohmann::json::json_pointer jp(
path);
280 throw std::runtime_error(
"JSON stack empty on cd_up");
297 template <
typename T>
299 nlohmann::json::json_pointer jp(
path);
304 template void ConfigJsonPatcher::replace<double>(
const std::string &
path,
double val);
306 template <
typename T>
308 nlohmann::json::json_pointer jp(
path);
318 nlohmann::json::json_pointer jp(
path);
324 throw std::runtime_error(
exc_hdr(__func__) +
"null not expected");
326 if (
j.is_boolean() ||
j.is_number() ||
j.is_string()) {
327 throw std::runtime_error(
exc_hdr(__func__) +
"value not expected on this parsing level");
333 static const std::regex index_range_re(
"^\\[(\\d+)..(\\d+)\\]$", std::regex::optimize);
337 std::regex_search(
key,
m, index_range_re);
341 throw std::runtime_error(
exc_hdr(__func__) +
"array range encountered when current json is not an array");
342 int first = std::stoi(
m.str(1));
343 int last = std::stoi(
m.str(2));
348 if (
value.is_array()) {
349 for (
auto &el :
value)
356 }
else if (
value.is_array() ||
value.is_object()) {
362 }
else if (
value.is_number() ||
value.is_boolean() ||
value.is_string()) {
365 nlohmann::json::json_pointer jp(
s);
374 throw std::runtime_error(
exc_hdr(__func__) +
"unexpected value type");
377 }
else if (
j.is_array() &&
j.empty()) {
378 }
else if (
j.is_array()) {
391 static const std::regex index_re(
"^(?:\\[\\d+..\\d+\\]|\\d+(?:/.*)?)$", std::regex::optimize);
393 bool has_index =
false, has_plain =
false;
394 for (
int i = 0;
i < (
int)
j.size(); ++
i) {
398 throw std::runtime_error(
exc_hdr(__func__) +
"array elements expected to be objects");
400 for (nlohmann::json::const_iterator it = el.begin(); it != el.end(); ++it) {
401 if (std::regex_search(it.key(), index_re)) {
404 throw std::runtime_error(
exc_hdr(__func__) +
"indexed array entry following plain one");
408 throw std::runtime_error(
exc_hdr(__func__) +
"plain array entry following indexed one");
413 for (
auto &element :
j) {
414 n_replaced +=
replace(element);
418 throw std::runtime_error(
exc_hdr(__func__) +
"plain array detected when current is not an array");
420 throw std::runtime_error(
exc_hdr(__func__) +
"plain array of different size than at current pos");
423 for (
int i = 0;
i < (
int)
j.size(); ++
i) {
432 throw std::runtime_error(
exc_hdr(__func__) +
"unexpected json type");
459 void open_ofstream(std::ofstream &ofs,
const std::string &
fname,
const char *
pfx =
nullptr) {
463 snprintf(
m, 2048,
"%s%sError opening %s for write: %m",
pfx ?
pfx :
"",
pfx ?
" " :
"",
fname.c_str());
464 throw std::runtime_error(
m);
469 void open_ifstream(std::ifstream &ifs,
const std::string &
fname,
const char *
pfx =
nullptr) {
473 snprintf(
m, 2048,
"%s%sError opening %s for read: %m",
pfx ?
pfx :
"",
pfx ?
" " :
"",
fname.c_str());
474 throw std::runtime_error(
m);
479 bool skipws_ifstream(std::ifstream &ifs) {
480 while (std::isspace(ifs.peek()))
487 const std::vector<std::string> &
fnames,
496 open_ifstream(ifs,
fname, __func__);
499 printf(
"%s begin reading from file %s.\n", __func__,
fname.c_str());
502 int n_read = 0, n_tot_replaced = 0;
503 while (skipws_ifstream(ifs)) {
509 std::cout <<
" Read JSON entity " << n_read <<
" -- applying patch:\n";
516 std::cout <<
" Replaced " << n_replaced <<
" entries.\n";
519 n_tot_replaced += n_replaced;
523 printf(
"%s read %d JSON entities from file %s, replaced %d parameters.\n",
532 rep.inc_counts(1, n_read, n_tot_replaced);
535 if (
rep.n_replacements > 0) {
549 open_ifstream(ifs,
fname, __func__);
552 printf(
"%s begin reading from file %s.\n", __func__,
fname.c_str());
555 if (!skipws_ifstream(ifs))
556 throw std::runtime_error(
"empty file");
560 int track_algo =
j[
"m_track_algorithm"];
563 for (
int i = 0;
i < its_info.
size(); ++
i) {
564 if (its_info[
i].m_track_algorithm == track_algo) {
570 throw std::runtime_error(
"matching IterationConfig not found");
573 std::cout <<
" Read JSON entity, Iteration index is " << iii <<
" -- cloning and applying JSON patch:\n";
587 printf(
"%s read 1 JSON entity from file %s, replaced %d parameters.\n", __func__,
fname.c_str(), n_replaced);
592 rep.inc_counts(1, 1, n_replaced);
594 if (
rep.n_replacements > 0) {
601 return std::unique_ptr<IterationConfig>(icp);
606 open_ifstream(ifs,
fname, __func__);
609 printf(
"%s begin reading from file %s.\n", __func__,
fname.c_str());
612 if (!skipws_ifstream(ifs))
613 throw std::runtime_error(
"empty file");
619 std::cout <<
" Read JSON entity, iteration index is " <<
j[
"m_iteration_index"] <<
", track algorithm is " 620 <<
j[
"m_track_algorithm"] <<
". Instantiating IterationConfig object and over-laying it with JSON.\n";
627 return std::unique_ptr<IterationConfig>(icp);
636 bool include_iter_info_preamble) {
637 bool has_pct_d = fname_fmt.find(
"%d") != std::string::npos;
638 bool has_pct_s = fname_fmt.find(
"%s") != std::string::npos;
640 assert((has_pct_d || has_pct_s) &&
"JSON save filename-format must include a %d or %s substring");
641 assert(!(has_pct_d && has_pct_s) &&
"JSON save filename-format must include only one of %d or %s substrings");
643 for (
int ii = 0;
ii < its_info.
size(); ++
ii) {
648 snprintf(
fname, 1024, fname_fmt.c_str(),
ii);
653 open_ofstream(ofs,
fname, __func__);
655 if (include_iter_info_preamble) {
656 ofs <<
"{ \"m_iterations/" <<
ii <<
"\": ";
659 nlohmann::ordered_json
j;
665 if (include_iter_info_preamble) {
675 nlohmann::ordered_json
j = its_info;
691 std::cout <<
"Layer 43, m_select_max_dphi = " <<
j[
"/m_layer_configs/43/m_select_max_dphi"_json_pointer] <<
"\n";
694 { "op": "replace", "path": "/m_layer_configs/43/m_select_max_dphi", "value": 3.141 } 697 std::cout << "Layer 43, m_select_max_dphi = " <<
j[
"/m_layer_configs/43/m_select_max_dphi"_json_pointer] <<
"\n";
699 auto &jx =
j[
"/m_layer_configs/60"_json_pointer];
701 json::json_pointer jp(lojz);
707 printf(
"Layer 43 : m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
713 printf(
"Layer 60 : m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
723 auto &
x =
j[
"/m_layer_configs"_json_pointer];
724 std::cout <<
"Typename /m_layer_configs " <<
x.type_name() <<
"\n";
725 auto &y =
j[
"/m_layer_configs/143"_json_pointer];
726 std::cout <<
"Typename /m_layer_configs/143 " << y.type_name() <<
", is_null=" << y.is_null() <<
"\n";
736 cjp.
cd(
"/m_layer_configs/43/m_select_max_dphi");
737 std::cout <<
"Layer 43, m_select_max_dphi = " << cjp.
get(
"") <<
"\n";
741 std::cout <<
"Layer 43, m_select_max_dphi = " << cjp.
get(
"/m_layer_configs/43/m_select_max_dphi") <<
"\n";
744 std::cout <<
"Replacing layer 60 m_select_max_dphi with full path\n";
745 cjp.
replace(
"/m_layer_configs/60/m_select_max_dphi", 99.876);
748 std::cout <<
"Trying to replace an non-existent array entry\n";
749 cjp.
replace(
"/m_layer_configs/1460/m_select_max_dphi", 666.666);
751 std::cout <<
"Caugth exception: " << exc.what() <<
"\n";
754 std::cout <<
"Trying to replace an non-existent object entry\n";
755 cjp.
replace(
"/m_layer_configs/1/moo_select_max_dphi", 666.666);
757 std::cout <<
"Caugth exception: " << exc.what() <<
"\n";
760 std::cout <<
"Replacing m_select_max_dphi on layers 1 to 3 to 7.7\n";
761 cjp.
cd(
"/m_layer_configs");
762 cjp.
replace(1, 3,
"/m_select_max_dphi", 7.7);
770 printf(
"Layer 43: m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
776 printf(
"Layer 60: m_select_max_dphi = %f\n", it_cfg.
m_layer_configs[60].m_select_max_dphi);
777 for (
int i = 0;
i < 5; ++
i)
778 printf(
"Layer %2d: m_select_max_dphi = %f\n",
i, it_cfg.
m_layer_configs[
i].m_select_max_dphi);
784 auto &
j = cjp.
get(
"");
786 auto &
x =
j[
"/m_layer_configs"_json_pointer];
787 std::cout <<
"Typename /m_layer_configs " <<
x.type_name() <<
"\n";
788 auto &y =
j[
"/m_layer_configs/143"_json_pointer];
789 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 partition_seeds_func get_seed_partitioner(const std::string &name)
static clean_duplicates_func get_duplicate_cleaner(const std::string &name)
std::function< partition_seeds_cf > partition_seeds_func
static filter_candidates_func get_candidate_filter(const std::string &name)
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)
clean_seeds_func m_seed_cleaner
void replace(const std::string &path, T val)
#define ITCONF_DEFINE_TYPE_NON_INTRUSIVE(Type,...)
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::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)
void setupStandardFunctionsFromNames()
static clean_seeds_func get_seed_cleaner(const std::string &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
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)
std::function< clean_seeds_cf > clean_seeds_func
std::function< clean_duplicates_cf > clean_duplicates_func
filter_candidates_func m_pre_bkfit_filter
void cd_top(const std::string &path="")
std::vector< SteeringParams > m_steering_params
std::function< filter_candidates_cf > filter_candidates_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::string get_abs_path() const