5 #include "nlohmann/json.hpp" 13 #define ITCONF_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ 14 inline void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) { \ 15 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \ 17 inline void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) { \ 18 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \ 20 inline void to_json(nlohmann::ordered_json &nlohmann_json_j, const Type &nlohmann_json_t) { \ 21 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \ 23 inline void from_json(const nlohmann::ordered_json &nlohmann_json_j, Type &nlohmann_json_t) { \ 24 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \ 90 m_requires_seed_hit_sorting,
91 m_requires_quality_filter,
92 m_requires_dupclean_tight,
94 m_backward_drop_seed_hits,
95 m_backward_fit_min_hits,
129 s =
"ConfigJsonPatcher";
142 m_json = std::make_unique<nlohmann::json>();
146 template void ConfigJsonPatcher::load<IterationsInfo>(
const IterationsInfo &
o);
147 template void ConfigJsonPatcher::load<IterationConfig>(
const IterationConfig &
o);
159 auto &itc_arr = m_json->at(
"m_iterations");
160 for (
int i = 0;
i <
o.size(); ++
i) {
166 nlohmann::json::json_pointer jp(
path);
174 throw std::runtime_error(
"JSON stack empty on cd_up");
191 template <
typename T>
193 nlohmann::json::json_pointer jp(
path);
198 template void ConfigJsonPatcher::replace<double>(
const std::string &
path,
double val);
200 template <
typename T>
202 nlohmann::json::json_pointer jp(
path);
212 nlohmann::json::json_pointer jp(
path);
218 throw std::runtime_error(
exc_hdr(__func__) +
"null not expected");
220 if (
j.is_boolean() ||
j.is_number() ||
j.is_string()) {
221 throw std::runtime_error(
exc_hdr(__func__) +
"value not expected on this parsing level");
227 static const std::regex index_range_re(
"^\\[(\\d+)..(\\d+)\\]$", std::regex::optimize);
231 std::regex_search(
key,
m, index_range_re);
235 throw std::runtime_error(
exc_hdr(__func__) +
"array range encountered when current json is not an array");
236 int first = std::stoi(
m.str(1));
237 int last = std::stoi(
m.str(2));
242 if (
value.is_array()) {
243 for (
auto &el :
value)
250 }
else if (
value.is_array() ||
value.is_object()) {
256 }
else if (
value.is_number() ||
value.is_boolean() ||
value.is_string()) {
259 nlohmann::json::json_pointer jp(
s);
268 throw std::runtime_error(
exc_hdr(__func__) +
"unexpected value type");
271 }
else if (
j.is_array() &&
j.empty()) {
272 }
else if (
j.is_array()) {
285 static const std::regex index_re(
"^(?:\\[\\d+..\\d+\\]|\\d+(?:/.*)?)$", std::regex::optimize);
287 bool has_index =
false, has_plain =
false;
288 for (
int i = 0;
i < (
int)
j.size(); ++
i) {
292 throw std::runtime_error(
exc_hdr(__func__) +
"array elements expected to be objects");
294 for (nlohmann::json::const_iterator it = el.begin(); it != el.end(); ++it) {
295 if (std::regex_search(it.key(), index_re)) {
298 throw std::runtime_error(
exc_hdr(__func__) +
"indexed array entry following plain one");
302 throw std::runtime_error(
exc_hdr(__func__) +
"plain array entry following indexed one");
307 for (
auto &element :
j) {
308 n_replaced +=
replace(element);
312 throw std::runtime_error(
exc_hdr(__func__) +
"plain array detected when current is not an array");
314 throw std::runtime_error(
exc_hdr(__func__) +
"plain array of different size than at current pos");
317 for (
int i = 0;
i < (
int)
j.size(); ++
i) {
326 throw std::runtime_error(
exc_hdr(__func__) +
"unexpected json type");
353 void open_ofstream(std::ofstream &ofs,
const std::string &
fname,
const char *
pfx =
nullptr) {
357 snprintf(
m, 2048,
"%s%sError opening %s for write: %m",
pfx ?
pfx :
"",
pfx ?
" " :
"",
fname.c_str());
358 throw std::runtime_error(
m);
363 void open_ifstream(std::ifstream &ifs,
const std::string &
fname,
const char *
pfx =
nullptr) {
367 snprintf(
m, 2048,
"%s%sError opening %s for read: %m",
pfx ?
pfx :
"",
pfx ?
" " :
"",
fname.c_str());
368 throw std::runtime_error(
m);
373 bool skipws_ifstream(std::ifstream &ifs) {
374 while (std::isspace(ifs.peek()))
381 const std::vector<std::string> &
fnames,
390 open_ifstream(ifs,
fname, __func__);
393 printf(
"%s begin reading from file %s.\n", __func__,
fname.c_str());
396 int n_read = 0, n_tot_replaced = 0;
397 while (skipws_ifstream(ifs)) {
403 std::cout <<
" Read JSON entity " << n_read <<
" -- applying patch:\n";
410 std::cout <<
" Replaced " << n_replaced <<
" entries.\n";
413 n_tot_replaced += n_replaced;
417 printf(
"%s read %d JSON entities from file %s, replaced %d parameters.\n",
426 rep.inc_counts(1, n_read, n_tot_replaced);
429 if (
rep.n_replacements > 0) {
443 open_ifstream(ifs,
fname, __func__);
446 printf(
"%s begin reading from file %s.\n", __func__,
fname.c_str());
449 if (!skipws_ifstream(ifs))
450 throw std::runtime_error(
"empty file");
454 int track_algo =
j[
"m_track_algorithm"];
457 for (
int i = 0;
i < its_info.
size(); ++
i) {
458 if (its_info[
i].m_track_algorithm == track_algo) {
464 throw std::runtime_error(
"matching IterationConfig not found");
467 std::cout <<
" Read JSON entity, Iteration index is " << iii <<
" -- cloning and applying JSON patch:\n";
481 printf(
"%s read 1 JSON entity from file %s, replaced %d parameters.\n", __func__,
fname.c_str(), n_replaced);
486 rep.inc_counts(1, 1, n_replaced);
488 if (
rep.n_replacements > 0) {
495 return std::unique_ptr<IterationConfig>(icp);
500 open_ifstream(ifs,
fname, __func__);
503 printf(
"%s begin reading from file %s.\n", __func__,
fname.c_str());
506 if (!skipws_ifstream(ifs))
507 throw std::runtime_error(
"empty file");
513 std::cout <<
" Read JSON entity, iteration index is " <<
j[
"m_iteration_index"] <<
", track algorithm is " 514 <<
j[
"m_track_algorithm"] <<
". Instantiating IterationConfig object and over-laying it with JSON.\n";
521 return std::unique_ptr<IterationConfig>(icp);
530 bool include_iter_info_preamble) {
531 bool has_pct_d = fname_fmt.find(
"%d") != std::string::npos;
532 bool has_pct_s = fname_fmt.find(
"%s") != std::string::npos;
534 assert((has_pct_d || has_pct_s) &&
"JSON save filename-format must include a %d or %s substring");
535 assert(!(has_pct_d && has_pct_s) &&
"JSON save filename-format must include only one of %d or %s substrings");
537 for (
int ii = 0;
ii < its_info.
size(); ++
ii) {
542 snprintf(
fname, 1024, fname_fmt.c_str(),
ii);
547 open_ofstream(ofs,
fname, __func__);
549 if (include_iter_info_preamble) {
550 ofs <<
"{ \"m_iterations/" <<
ii <<
"\": ";
553 nlohmann::ordered_json
j;
559 if (include_iter_info_preamble) {
569 nlohmann::ordered_json
j = its_info;
585 std::cout <<
"Layer 43, m_select_max_dphi = " <<
j[
"/m_layer_configs/43/m_select_max_dphi"_json_pointer] <<
"\n";
588 { "op": "replace", "path": "/m_layer_configs/43/m_select_max_dphi", "value": 3.141 } 591 std::cout << "Layer 43, m_select_max_dphi = " <<
j[
"/m_layer_configs/43/m_select_max_dphi"_json_pointer] <<
"\n";
593 auto &jx =
j[
"/m_layer_configs/60"_json_pointer];
595 json::json_pointer jp(lojz);
601 printf(
"Layer 43 : m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
607 printf(
"Layer 60 : m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
617 auto &
x =
j[
"/m_layer_configs"_json_pointer];
618 std::cout <<
"Typename /m_layer_configs " <<
x.type_name() <<
"\n";
619 auto &y =
j[
"/m_layer_configs/143"_json_pointer];
620 std::cout <<
"Typename /m_layer_configs/143 " << y.type_name() <<
", is_null=" << y.is_null() <<
"\n";
630 cjp.
cd(
"/m_layer_configs/43/m_select_max_dphi");
631 std::cout <<
"Layer 43, m_select_max_dphi = " << cjp.
get(
"") <<
"\n";
635 std::cout <<
"Layer 43, m_select_max_dphi = " << cjp.
get(
"/m_layer_configs/43/m_select_max_dphi") <<
"\n";
638 std::cout <<
"Replacing layer 60 m_select_max_dphi with full path\n";
639 cjp.
replace(
"/m_layer_configs/60/m_select_max_dphi", 99.876);
642 std::cout <<
"Trying to replace an non-existent array entry\n";
643 cjp.
replace(
"/m_layer_configs/1460/m_select_max_dphi", 666.666);
645 std::cout <<
"Caugth exception: " << exc.what() <<
"\n";
648 std::cout <<
"Trying to replace an non-existent object entry\n";
649 cjp.
replace(
"/m_layer_configs/1/moo_select_max_dphi", 666.666);
651 std::cout <<
"Caugth exception: " << exc.what() <<
"\n";
654 std::cout <<
"Replacing m_select_max_dphi on layers 1 to 3 to 7.7\n";
655 cjp.
cd(
"/m_layer_configs");
656 cjp.
replace(1, 3,
"/m_select_max_dphi", 7.7);
664 printf(
"Layer 43: m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
670 printf(
"Layer 60: m_select_max_dphi = %f\n", it_cfg.
m_layer_configs[60].m_select_max_dphi);
671 for (
int i = 0;
i < 5; ++
i)
672 printf(
"Layer %2d: m_select_max_dphi = %f\n",
i, it_cfg.
m_layer_configs[
i].m_select_max_dphi);
678 auto &
j = cjp.
get(
"");
680 auto &
x =
j[
"/m_layer_configs"_json_pointer];
681 std::cout <<
"Typename /m_layer_configs " <<
x.type_name() <<
"\n";
682 auto &y =
j[
"/m_layer_configs/143"_json_pointer];
683 std::cout <<
"Typename /m_layer_configs/143 " << y.type_name() <<
", is_null=" << y.is_null() <<
"\n";
nlohmann::json * m_current
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)
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
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)
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)
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="")
void cd_top(const std::string &path="")
std::vector< SteeringParams > m_steering_params
std::string get_abs_path() const