Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-02-21 23:14:16

0001 #include "RecoTracker/MkFitCore/interface/IterationConfig.h"
0002 #include "RecoTracker/MkFitCore/interface/Config.h"
0003 #include "RecoTracker/MkFitCore/interface/Track.h"
0004 
0005 #include "nlohmann/json.hpp"
0006 
0007 #include <fstream>
0008 #include <regex>
0009 #include <iostream>
0010 #include <iomanip>
0011 
0012 // Redefine to also support ordered_json ... we want to keep variable order in JSON save files.
0013 #define ITCONF_DEFINE_TYPE_NON_INTRUSIVE(Type, ...)                                             \
0014   inline void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) {           \
0015     NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__))                    \
0016   }                                                                                             \
0017   inline void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) {         \
0018     NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__))                  \
0019   }                                                                                             \
0020   inline void to_json(nlohmann::ordered_json &nlohmann_json_j, const Type &nlohmann_json_t) {   \
0021     NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__))                    \
0022   }                                                                                             \
0023   inline void from_json(const nlohmann::ordered_json &nlohmann_json_j, Type &nlohmann_json_t) { \
0024     NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__))                  \
0025   }
0026 
0027 namespace mkfit {
0028 
0029   // Begin AUTO code, some members commented out.
0030 
0031   ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::LayerControl,
0032                                    /* int   */ m_layer)
0033 
0034   ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::SteeringParams,
0035                                    /* std::vector<LayerControl> */ m_layer_plan,
0036                                    /* int */ m_region,
0037                                    /* int */ m_fwd_search_pickup,
0038                                    /* int */ m_bkw_fit_last,
0039                                    /* int */ m_bkw_search_pickup
0040 
0041   )
0042 
0043   ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationLayerConfig,
0044                                    /* float */ m_select_min_dphi,
0045                                    /* float */ m_select_max_dphi,
0046                                    /* float */ m_select_min_dq,
0047                                    /* float */ m_select_max_dq,
0048                                    /* float */ c_dp_sf,
0049                                    /* float */ c_dp_0,
0050                                    /* float */ c_dp_1,
0051                                    /* float */ c_dp_2,
0052                                    /* float */ c_dq_sf,
0053                                    /* float */ c_dq_0,
0054                                    /* float */ c_dq_1,
0055                                    /* float */ c_dq_2,
0056                                    /* float */ c_c2_sf,
0057                                    /* float */ c_c2_0,
0058                                    /* float */ c_c2_1,
0059                                    /* float */ c_c2_2)
0060 
0061   ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationParams,
0062                                    /* int */ nlayers_per_seed,
0063                                    /* int */ maxCandsPerSeed,
0064                                    /* int */ maxHolesPerCand,
0065                                    /* int */ maxConsecHoles,
0066                                    /* float */ chi2Cut_min,
0067                                    /* float */ chi2CutOverlap,
0068                                    /* float */ pTCutOverlap,
0069                                    /* float */ c_ptthr_hpt,
0070                                    /* float */ c_drmax_bh,
0071                                    /* float */ c_dzmax_bh,
0072                                    /* float */ c_drmax_eh,
0073                                    /* float */ c_dzmax_eh,
0074                                    /* float */ c_drmax_bl,
0075                                    /* float */ c_dzmax_bl,
0076                                    /* float */ c_drmax_el,
0077                                    /* float */ c_dzmax_el,
0078                                    /* int */ minHitsQF,
0079                                    /* float */ fracSharedHits,
0080                                    /* float */ drth_central,
0081                                    /* float */ drth_obarrel,
0082                                    /* float */ drth_forward
0083 
0084   )
0085 
0086   ITCONF_DEFINE_TYPE_NON_INTRUSIVE(
0087       mkfit::IterationConfig,
0088       /* int */ m_iteration_index,
0089       /* int */ m_track_algorithm,
0090       /* bool */ m_requires_seed_hit_sorting,
0091       /* bool */ m_requires_quality_filter,
0092       /* bool */ m_requires_dupclean_tight,
0093       /* bool */ m_backward_search,
0094       /* bool */ m_backward_drop_seed_hits,
0095       /* int */ m_backward_fit_min_hits,
0096       /* mkfit::IterationParams */ m_params,
0097       /* mkfit::IterationParams */ m_backward_params,
0098       /* int */ m_n_regions,
0099       /* vector<int> */ m_region_order,
0100       /* vector<mkfit::SteeringParams> */ m_steering_params,
0101       /* vector<mkfit::IterationLayerConfig> */ m_layer_configs
0102       // /* function<void(const TrackerInfo&,const TrackVec&,const EventOfHits&,IterationSeedPartition&)> */   m_partition_seeds
0103   )
0104 
0105   ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationsInfo,
0106                                    /* vector<mkfit::IterationConfig> */ m_iterations)
0107 
0108   // End AUTO code.
0109 
0110   // ============================================================================
0111   // ConfigJsonPatcher
0112   // ============================================================================
0113 
0114   ConfigJsonPatcher::ConfigJsonPatcher(bool verbose) : m_verbose(verbose) {}
0115 
0116   ConfigJsonPatcher::~ConfigJsonPatcher() = default;
0117 
0118   std::string ConfigJsonPatcher::get_abs_path() const {
0119     std::string s;
0120     s.reserve(64);
0121     for (auto &p : m_path_stack)
0122       s += p;
0123     return s;
0124   }
0125 
0126   std::string ConfigJsonPatcher::exc_hdr(const char *func) const {
0127     std::string s;
0128     s.reserve(128);
0129     s = "ConfigJsonPatcher";
0130     if (func) {
0131       s += "::";
0132       s += func;
0133     }
0134     s += " '";
0135     s += get_abs_path();
0136     s += "' ";
0137     return s;
0138   }
0139 
0140   template <class T>
0141   void ConfigJsonPatcher::load(const T &o) {
0142     m_json = std::make_unique<nlohmann::json>();
0143     *m_json = o;
0144     cd_top();
0145   }
0146   template void ConfigJsonPatcher::load<IterationsInfo>(const IterationsInfo &o);
0147   template void ConfigJsonPatcher::load<IterationConfig>(const IterationConfig &o);
0148 
0149   template <class T>
0150   void ConfigJsonPatcher::save(T &o) {
0151     from_json(*m_json, o);
0152   }
0153   template void ConfigJsonPatcher::save<IterationConfig>(IterationConfig &o);
0154 
0155   // Must not bork the IterationConfig elements of IterationsInfo ... default
0156   // deserializator apparently reinitializes the vectors with defaults c-tors.
0157   template <>
0158   void ConfigJsonPatcher::save<IterationsInfo>(IterationsInfo &o) {
0159     auto &itc_arr = m_json->at("m_iterations");
0160     for (int i = 0; i < o.size(); ++i) {
0161       from_json(itc_arr[i], o[i]);
0162     }
0163   }
0164 
0165   void ConfigJsonPatcher::cd(const std::string &path) {
0166     nlohmann::json::json_pointer jp(path);
0167     m_json_stack.push_back(m_current);
0168     m_path_stack.push_back(path);
0169     m_current = &m_current->at(jp);
0170   }
0171 
0172   void ConfigJsonPatcher::cd_up(const std::string &path) {
0173     if (m_json_stack.empty())
0174       throw std::runtime_error("JSON stack empty on cd_up");
0175 
0176     m_current = m_json_stack.back();
0177     m_json_stack.pop_back();
0178     m_path_stack.pop_back();
0179     if (!path.empty())
0180       cd(path);
0181   }
0182 
0183   void ConfigJsonPatcher::cd_top(const std::string &path) {
0184     m_current = m_json.get();
0185     m_json_stack.clear();
0186     m_path_stack.clear();
0187     if (!path.empty())
0188       cd(path);
0189   }
0190 
0191   template <typename T>
0192   void ConfigJsonPatcher::replace(const std::string &path, T val) {
0193     nlohmann::json::json_pointer jp(path);
0194     m_current->at(jp) = val;
0195   }
0196   template void ConfigJsonPatcher::replace<int>(const std::string &path, int val);
0197   template void ConfigJsonPatcher::replace<float>(const std::string &path, float val);
0198   template void ConfigJsonPatcher::replace<double>(const std::string &path, double val);
0199 
0200   template <typename T>
0201   void ConfigJsonPatcher::replace(int first, int last, const std::string &path, T val) {
0202     nlohmann::json::json_pointer jp(path);
0203     for (int i = first; i <= last; ++i) {
0204       m_current->at(i).at(jp) = val;
0205     }
0206   }
0207   template void ConfigJsonPatcher::replace<int>(int first, int last, const std::string &path, int val);
0208   template void ConfigJsonPatcher::replace<float>(int first, int last, const std::string &path, float val);
0209   template void ConfigJsonPatcher::replace<double>(int first, int last, const std::string &path, double val);
0210 
0211   nlohmann::json &ConfigJsonPatcher::get(const std::string &path) {
0212     nlohmann::json::json_pointer jp(path);
0213     return m_current->at(jp);
0214   }
0215 
0216   int ConfigJsonPatcher::replace(const nlohmann::json &j) {
0217     if (j.is_null())
0218       throw std::runtime_error(exc_hdr(__func__) + "null not expected");
0219 
0220     if (j.is_boolean() || j.is_number() || j.is_string()) {
0221       throw std::runtime_error(exc_hdr(__func__) + "value not expected on this parsing level");
0222     }
0223 
0224     int n_replaced = 0;
0225 
0226     if (j.is_object()) {
0227       static const std::regex index_range_re("^\\[(\\d+)..(\\d+)\\]$", std::regex::optimize);
0228 
0229       for (auto &[key, value] : j.items()) {
0230         std::smatch m;
0231         std::regex_search(key, m, index_range_re);
0232 
0233         if (m.size() == 3) {
0234           if (!m_current->is_array())
0235             throw std::runtime_error(exc_hdr(__func__) + "array range encountered when current json is not an array");
0236           int first = std::stoi(m.str(1));
0237           int last = std::stoi(m.str(2));
0238           for (int i = first; i <= last; ++i) {
0239             std::string s("/");
0240             s += std::to_string(i);
0241             cd(s);
0242             if (value.is_array()) {
0243               for (auto &el : value)
0244                 n_replaced += replace(el);
0245             } else {
0246               n_replaced += replace(value);
0247             }
0248             cd_up();
0249           }
0250         } else if (value.is_array() || value.is_object()) {
0251           std::string s("/");
0252           s += key;
0253           cd(s);
0254           n_replaced += replace(value);
0255           cd_up();
0256         } else if (value.is_number() || value.is_boolean() || value.is_string()) {
0257           std::string s("/");
0258           s += key;
0259           nlohmann::json::json_pointer jp(s);
0260           if (m_current->at(jp) != value) {
0261             if (m_verbose)
0262               std::cout << "  " << get_abs_path() << s << ": " << m_current->at(jp) << " -> " << value << "\n";
0263 
0264             m_current->at(jp) = value;
0265             ++n_replaced;
0266           }
0267         } else {
0268           throw std::runtime_error(exc_hdr(__func__) + "unexpected value type");
0269         }
0270       }
0271     } else if (j.is_array() && j.empty()) {
0272     } else if (j.is_array()) {
0273       // Arrays are somewhat tricky.
0274       // At the moment all elements are expected to be objects.
0275       //    This means arrays of basic types are not supported (like layer index arrays).
0276       //    Should not be too hard to add support for this.
0277       // Now, the objects in the array can be of two kinds:
0278       // a) Their keys can be json_pointer strings starting with numbers or ranges [i_low..i_high].
0279       // b) They can be actual elements of the array. In this case we require the length of
0280       //    the array to be equal to existing length in the configuration.
0281       // It is not allowed for these two kinds to mix.
0282 
0283       // Determine the kind of array: json_ptr or object
0284 
0285       static const std::regex index_re("^(?:\\[\\d+..\\d+\\]|\\d+(?:/.*)?)$", std::regex::optimize);
0286 
0287       bool has_index = false, has_plain = false;
0288       for (int i = 0; i < (int)j.size(); ++i) {
0289         const nlohmann::json &el = j[i];
0290 
0291         if (!el.is_object())
0292           throw std::runtime_error(exc_hdr(__func__) + "array elements expected to be objects");
0293 
0294         for (nlohmann::json::const_iterator it = el.begin(); it != el.end(); ++it) {
0295           if (std::regex_search(it.key(), index_re)) {
0296             has_index = true;
0297             if (has_plain)
0298               throw std::runtime_error(exc_hdr(__func__) + "indexed array entry following plain one");
0299           } else {
0300             has_plain = true;
0301             if (has_index)
0302               throw std::runtime_error(exc_hdr(__func__) + "plain array entry following indexed one");
0303           }
0304         }
0305       }
0306       if (has_index) {
0307         for (auto &element : j) {
0308           n_replaced += replace(element);
0309         }
0310       } else {
0311         if (m_current && !m_current->is_array())
0312           throw std::runtime_error(exc_hdr(__func__) + "plain array detected when current is not an array");
0313         if (m_current->size() != j.size())
0314           throw std::runtime_error(exc_hdr(__func__) + "plain array of different size than at current pos");
0315 
0316         std::string s;
0317         for (int i = 0; i < (int)j.size(); ++i) {
0318           s = "/";
0319           s += std::to_string(i);
0320           cd(s);
0321           n_replaced += replace(j[i]);
0322           cd_up();
0323         }
0324       }
0325     } else {
0326       throw std::runtime_error(exc_hdr(__func__) + "unexpected json type");
0327     }
0328 
0329     return n_replaced;
0330   }
0331 
0332   std::string ConfigJsonPatcher::dump(int indent) { return m_json->dump(indent); }
0333 
0334   // ============================================================================
0335   // patch_File steering function
0336   // ============================================================================
0337   /*
0338     See example JSON patcher input: "mkFit/config-parse/test.json"
0339 
0340     The file can contain several valid JSON dumps in sequence.
0341 
0342     '/' character can be used to descend more than one level at a time.
0343 
0344     A number can be used to specify an array index. This can be combined with
0345     the '/' syntax.
0346 
0347     "[first,last]" key (as string) can be used to denote a range of array
0348     elements. Such a key must not be combined with a '/' syntax.
0349 */
0350 
0351   namespace {
0352     // Open file for writing, throw exception on failure.
0353     void open_ofstream(std::ofstream &ofs, const std::string &fname, const char *pfx = nullptr) {
0354       ofs.open(fname, std::ofstream::trunc);
0355       if (!ofs) {
0356         char m[2048];
0357         snprintf(m, 2048, "%s%sError opening %s for write: %m", pfx ? pfx : "", pfx ? " " : "", fname.c_str());
0358         throw std::runtime_error(m);
0359       }
0360     }
0361 
0362     // Open file for reading, throw exception on failure.
0363     void open_ifstream(std::ifstream &ifs, const std::string &fname, const char *pfx = nullptr) {
0364       ifs.open(fname);
0365       if (!ifs) {
0366         char m[2048];
0367         snprintf(m, 2048, "%s%sError opening %s for read: %m", pfx ? pfx : "", pfx ? " " : "", fname.c_str());
0368         throw std::runtime_error(m);
0369       }
0370     }
0371 
0372     // Skip white-space, return true if more characters are available, false if eof.
0373     bool skipws_ifstream(std::ifstream &ifs) {
0374       while (std::isspace(ifs.peek()))
0375         ifs.get();
0376       return !ifs.eof();
0377     }
0378   }  // namespace
0379 
0380   void ConfigJson::patch_Files(IterationsInfo &its_info,
0381                                const std::vector<std::string> &fnames,
0382                                ConfigJsonPatcher::PatchReport *report) {
0383     ConfigJsonPatcher cjp(m_verbose);
0384     cjp.load(its_info);
0385 
0386     ConfigJsonPatcher::PatchReport rep;
0387 
0388     for (auto &fname : fnames) {
0389       std::ifstream ifs;
0390       open_ifstream(ifs, fname, __func__);
0391 
0392       if (m_verbose) {
0393         printf("%s begin reading from file %s.\n", __func__, fname.c_str());
0394       }
0395 
0396       int n_read = 0, n_tot_replaced = 0;
0397       while (skipws_ifstream(ifs)) {
0398         nlohmann::json j;
0399         ifs >> j;
0400         ++n_read;
0401 
0402         if (m_verbose) {
0403           std::cout << " Read JSON entity " << n_read << " -- applying patch:\n";
0404           // std::cout << j.dump(3) << "\n";
0405         }
0406 
0407         int n_replaced = cjp.replace(j);
0408 
0409         if (m_verbose) {
0410           std::cout << " Replaced " << n_replaced << " entries.\n";
0411         }
0412         cjp.cd_top();
0413         n_tot_replaced += n_replaced;
0414       }
0415 
0416       if (m_verbose) {
0417         printf("%s read %d JSON entities from file %s, replaced %d parameters.\n",
0418                __func__,
0419                n_read,
0420                fname.c_str(),
0421                n_tot_replaced);
0422       }
0423 
0424       ifs.close();
0425 
0426       rep.inc_counts(1, n_read, n_tot_replaced);
0427     }
0428 
0429     if (rep.n_replacements > 0) {
0430       cjp.save(its_info);
0431     }
0432 
0433     if (report)
0434       report->inc_counts(rep);
0435   }
0436 
0437   std::unique_ptr<IterationConfig> ConfigJson::patchLoad_File(const IterationsInfo &its_info,
0438                                                               const std::string &fname,
0439                                                               ConfigJsonPatcher::PatchReport *report) {
0440     ConfigJsonPatcher::PatchReport rep;
0441 
0442     std::ifstream ifs;
0443     open_ifstream(ifs, fname, __func__);
0444 
0445     if (m_verbose) {
0446       printf("%s begin reading from file %s.\n", __func__, fname.c_str());
0447     }
0448 
0449     if (!skipws_ifstream(ifs))
0450       throw std::runtime_error("empty file");
0451 
0452     nlohmann::json j;
0453     ifs >> j;
0454     int track_algo = j["m_track_algorithm"];
0455 
0456     int iii = -1;
0457     for (int i = 0; i < its_info.size(); ++i) {
0458       if (its_info[i].m_track_algorithm == track_algo) {
0459         iii = i;
0460         break;
0461       }
0462     }
0463     if (iii == -1)
0464       throw std::runtime_error("matching IterationConfig not found");
0465 
0466     if (m_verbose) {
0467       std::cout << " Read JSON entity, Iteration index is " << iii << " -- cloning and applying JSON patch:\n";
0468     }
0469 
0470     IterationConfig *icp = new IterationConfig(its_info[iii]);
0471     IterationConfig &ic = *icp;
0472 
0473     ConfigJsonPatcher cjp(m_verbose);
0474     cjp.load(ic);
0475 
0476     int n_replaced = cjp.replace(j);
0477 
0478     cjp.cd_top();
0479 
0480     if (m_verbose) {
0481       printf("%s read 1 JSON entity from file %s, replaced %d parameters.\n", __func__, fname.c_str(), n_replaced);
0482     }
0483 
0484     ifs.close();
0485 
0486     rep.inc_counts(1, 1, n_replaced);
0487 
0488     if (rep.n_replacements > 0) {
0489       cjp.save(ic);
0490     }
0491 
0492     if (report)
0493       report->inc_counts(rep);
0494 
0495     return std::unique_ptr<IterationConfig>(icp);
0496   }
0497 
0498   std::unique_ptr<IterationConfig> ConfigJson::load_File(const std::string &fname) {
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     if (!skipws_ifstream(ifs))
0507       throw std::runtime_error("empty file");
0508 
0509     nlohmann::json j;
0510     ifs >> j;
0511 
0512     if (m_verbose) {
0513       std::cout << " Read JSON entity, iteration index is " << j["m_iteration_index"] << ", track algorithm is "
0514                 << j["m_track_algorithm"] << ". Instantiating IterationConfig object and over-laying it with JSON.\n";
0515     }
0516 
0517     IterationConfig *icp = new IterationConfig();
0518 
0519     from_json(j, *icp);
0520 
0521     return std::unique_ptr<IterationConfig>(icp);
0522   }
0523 
0524   // ============================================================================
0525   // Save each IterationConfig into a separate json file
0526   // ============================================================================
0527 
0528   void ConfigJson::save_Iterations(IterationsInfo &its_info,
0529                                    const std::string &fname_fmt,
0530                                    bool include_iter_info_preamble) {
0531     bool has_pct_d = fname_fmt.find("%d") != std::string::npos;
0532     bool has_pct_s = fname_fmt.find("%s") != std::string::npos;
0533 
0534     assert((has_pct_d || has_pct_s) && "JSON save filename-format must include a %d or %s substring");
0535     assert(!(has_pct_d && has_pct_s) && "JSON save filename-format must include only one of %d or %s substrings");
0536 
0537     for (int ii = 0; ii < its_info.size(); ++ii) {
0538       const IterationConfig &itconf = its_info[ii];
0539 
0540       char fname[1024];
0541       if (has_pct_d)
0542         snprintf(fname, 1024, fname_fmt.c_str(), ii);
0543       else
0544         snprintf(fname, 1024, fname_fmt.c_str(), TrackBase::algoint_to_cstr(itconf.m_track_algorithm));
0545 
0546       std::ofstream ofs;
0547       open_ofstream(ofs, fname, __func__);
0548 
0549       if (include_iter_info_preamble) {
0550         ofs << "{ \"m_iterations/" << ii << "\": ";
0551       }
0552 
0553       nlohmann::ordered_json j;
0554       to_json(j, itconf);
0555 
0556       ofs << std::setw(1);
0557       ofs << j;
0558 
0559       if (include_iter_info_preamble) {
0560         ofs << " }";
0561       }
0562 
0563       ofs << "\n";
0564       ofs.close();
0565     }
0566   }
0567 
0568   void ConfigJson::dump(IterationsInfo &its_info) {
0569     nlohmann::ordered_json j = its_info;
0570     std::cout << j.dump(3) << "\n";
0571   }
0572 
0573   // ============================================================================
0574   // Tests for ConfigJson stuff
0575   // ============================================================================
0576 
0577   void ConfigJson::test_Direct(IterationConfig &it_cfg) {
0578     using nlohmann::json;
0579 
0580     std::string lojz("/m_select_max_dphi");
0581 
0582     json j = it_cfg;
0583     std::cout << j.dump(1) << "\n";
0584 
0585     std::cout << "Layer 43, m_select_max_dphi = " << j["/m_layer_configs/43/m_select_max_dphi"_json_pointer] << "\n";
0586     std::cout << "Patching it to pi ...\n";
0587     json p = R"([
0588         { "op": "replace", "path": "/m_layer_configs/43/m_select_max_dphi", "value": 3.141 }
0589     ])"_json;
0590     j = j.patch(p);
0591     std::cout << "Layer 43, m_select_max_dphi = " << j["/m_layer_configs/43/m_select_max_dphi"_json_pointer] << "\n";
0592 
0593     auto &jx = j["/m_layer_configs/60"_json_pointer];
0594     // jx["m_select_max_dphi"] = 99.876;
0595     json::json_pointer jp(lojz);
0596     jx[jp] = 99.876;
0597 
0598     // try loading it back, see what happens to vector m_layer_configs.
0599 
0600     from_json(j, it_cfg);
0601     printf("Layer 43 : m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
0602            it_cfg.m_layer_configs[43].m_select_max_dphi,
0603            (int)it_cfg.m_layer_configs.size(),
0604            it_cfg.m_n_regions,
0605            (int)it_cfg.m_steering_params.size());
0606 
0607     printf("Layer 60 : m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
0608            it_cfg.m_layer_configs[60].m_select_max_dphi,
0609            (int)it_cfg.m_layer_configs.size(),
0610            it_cfg.m_n_regions,
0611            (int)it_cfg.m_steering_params.size());
0612 
0613     // try accessing something that does not exist
0614 
0615     // std::cout << "Non-existent path " << j["/m_layer_configs/143/m_select_max_dphi"_json_pointer] << "\n";
0616 
0617     auto &x = j["/m_layer_configs"_json_pointer];
0618     std::cout << "Typename /m_layer_configs " << x.type_name() << "\n";
0619     auto &y = j["/m_layer_configs/143"_json_pointer];
0620     std::cout << "Typename /m_layer_configs/143 " << y.type_name() << ", is_null=" << y.is_null() << "\n";
0621   }
0622 
0623   void ConfigJson::test_Patcher(IterationConfig &it_cfg) {
0624     ConfigJsonPatcher cjp;
0625     cjp.load(it_cfg);
0626 
0627     std::cout << cjp.dump(1) << "\n";
0628 
0629     {
0630       cjp.cd("/m_layer_configs/43/m_select_max_dphi");
0631       std::cout << "Layer 43, m_select_max_dphi = " << cjp.get("") << "\n";
0632       std::cout << "Setting it to pi ...\n";
0633       cjp.replace("", 3.141);
0634       cjp.cd_top();
0635       std::cout << "Layer 43, m_select_max_dphi = " << cjp.get("/m_layer_configs/43/m_select_max_dphi") << "\n";
0636     }
0637     {
0638       std::cout << "Replacing layer 60 m_select_max_dphi with full path\n";
0639       cjp.replace("/m_layer_configs/60/m_select_max_dphi", 99.876);
0640     }
0641     try {
0642       std::cout << "Trying to replace an non-existent array entry\n";
0643       cjp.replace("/m_layer_configs/1460/m_select_max_dphi", 666.666);
0644     } catch (std::exception &exc) {
0645       std::cout << "Caugth exception: " << exc.what() << "\n";
0646     }
0647     try {
0648       std::cout << "Trying to replace an non-existent object entry\n";
0649       cjp.replace("/m_layer_configs/1/moo_select_max_dphi", 666.666);
0650     } catch (std::exception &exc) {
0651       std::cout << "Caugth exception: " << exc.what() << "\n";
0652     }
0653     {
0654       std::cout << "Replacing m_select_max_dphi on layers 1 to 3 to 7.7\n";
0655       cjp.cd("/m_layer_configs");
0656       cjp.replace(1, 3, "/m_select_max_dphi", 7.7);
0657       cjp.cd_top();
0658     }
0659 
0660     // try getting it back into c++, see what happens to vector m_layer_configs.
0661 
0662     cjp.save(it_cfg);
0663 
0664     printf("Layer 43: m_select_max_dphi = %f, size_of_layer_vec=%d, m_n_regions=%d, size_of_steering_params=%d\n",
0665            it_cfg.m_layer_configs[43].m_select_max_dphi,
0666            (int)it_cfg.m_layer_configs.size(),
0667            it_cfg.m_n_regions,
0668            (int)it_cfg.m_steering_params.size());
0669 
0670     printf("Layer 60: m_select_max_dphi = %f\n", it_cfg.m_layer_configs[60].m_select_max_dphi);
0671     for (int i = 0; i < 5; ++i)
0672       printf("Layer %2d: m_select_max_dphi = %f\n", i, it_cfg.m_layer_configs[i].m_select_max_dphi);
0673 
0674     // try accessing something that does not exist
0675 
0676     // std::cout << "Non-existent path " << j["/m_layer_configs/143/m_select_max_dphi"_json_pointer] << "\n";
0677 
0678     auto &j = cjp.get("");
0679 
0680     auto &x = j["/m_layer_configs"_json_pointer];
0681     std::cout << "Typename /m_layer_configs " << x.type_name() << "\n";
0682     auto &y = j["/m_layer_configs/143"_json_pointer];
0683     std::cout << "Typename /m_layer_configs/143 " << y.type_name() << ", is_null=" << y.is_null() << "\n";
0684   }
0685 
0686 }  // namespace mkfit