Skip to content

Commit

Permalink
- Changes to saving of IterationConfigs to several files:
Browse files Browse the repository at this point in the history
  - Add option of using %s in file-name-format that injects algorithm name.
  - Make writing of iteration-info index in JSON save files optional.
    Default now is not to write.
    This is to be used when loading a single IterationConfig.
```
void ConfigJson_Save_Iterations(IterationsInfo &its_info, const std::string &fname_fmt,
                                bool include_iter_info_preamble);
```

- Provide another version of JSON reading where a single iteration is loaded
  over an existing one. These are the two variants:
```
// Patch IterationsInfo from a vector of files.
// Assumes patch files include iteration-info preambles, i.e., they
// were saved with include_iter_info_preamble=true.
// If report is non-null counts are added to existing object.
void             ConfigJson_Patch_Files(IterationsInfo &its_info, const std::vector<std::string> &fnames,
                                       ConfigJsonPatcher::PatchReport *report=nullptr);

// Load a single iteration from JSON file.
// Searches for a match between m_algorithm in its_info and in JSON file to decide
// which IterationConfig it will load over.
// Assumes JSON file has been saved WITHOUT iteration-info preamble.
// Returns reference to the selected IterationConfig.
// If report is non-null counts are added to existing object.
IterationConfig& ConfigJson_Load_File(IterationsInfo &its_info, const std::string &fname,
                                      ConfigJsonPatcher::PatchReport *report=nullptr);
```

- Add new command-line options and remove 'patch' from most of the existing one:
```
JSON config patcher options:

  --json-load  <filename>  load iteration config from given JSON file (def: do not load)
                           can be specified multiple times for several files
  --json-patch <filename>  patch iteration config from given JSON file (def: do not patch)
                           can be specified multiple times for several files
  --json-save-iterations <fname-fmt> save per iteration json files
                           %d in fname-fmt gets replaced with iteration number
                           %s in fname-fmt get replaced with iteration algorithm name
                           exactly one of %d and %s must be specified
  --json-save-iterations-include-iter-info-preamble (def: false)
  --json-verbose     print each patch assignment as it is being made (def: false)
  --json-dump-before print iteration config before patching (def: false)
  --json-dump-after  print iteration config after  patching (def: false)
```

- When counting replacements of leaf config values only count assignments where value
  has actually changed.

- Use nlohmann::ordered_json when saving configs to JSON files and dumping to stdout.
  This preserves data-member definition order and makes these outputs more readable.
  • Loading branch information
osschar committed May 12, 2021
1 parent 6e5df91 commit 77861c5
Show file tree
Hide file tree
Showing 7 changed files with 229 additions and 67 deletions.
8 changes: 5 additions & 3 deletions Config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,13 @@ namespace Config
bool backwardFit = false;
bool includePCA = false;

bool json_patch_dump_before = false;
bool json_patch_dump_after = false;
bool json_patch_verbose = false;
bool json_dump_before = false;
bool json_dump_after = false;
bool json_verbose = false;
std::vector<std::string> json_patch_filenames;
std::vector<std::string> json_load_filenames;
std::string json_save_iters_fname_fmt;
bool json_save_iters_include_iter_info_preamble = false;

void RecalculateDependentConstants()
{
Expand Down
8 changes: 5 additions & 3 deletions Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,11 +399,13 @@ namespace Config

// ================================================================

extern bool json_patch_dump_before;
extern bool json_patch_dump_after;
extern bool json_patch_verbose;
extern bool json_dump_before;
extern bool json_dump_after;
extern bool json_verbose;
extern std::vector<std::string> json_patch_filenames;
extern std::vector<std::string> json_load_filenames;
extern std::string json_save_iters_fname_fmt;
extern bool json_save_iters_include_iter_info_preamble;

// ================================================================

Expand Down
19 changes: 19 additions & 0 deletions Track.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,25 @@ bool TrackBase::hasSillyValues(bool dump, bool fix, const char* pref)
return is_silly;
}

const char* TrackBase::algoint_to_cstr(int algo)
{
static const char* names[] = { "undefAlgorithm", "ctf", "duplicateMerge",
"cosmics", "initialStep", "lowPtTripletStep", "pixelPairStep", "detachedTripletStep",
"mixedTripletStep", "pixelLessStep", "tobTecStep", "jetCoreRegionalStep", "conversionStep",
"muonSeededStepInOut", "muonSeededStepOutIn", "outInEcalSeededConv", "inOutEcalSeededConv",
"nuclInter", "standAloneMuon", "globalMuon", "cosmicStandAloneMuon", "cosmicGlobalMuon",
"highPtTripletStep", "lowPtQuadStep", "detachedQuadStep", "reservedForUpgrades1",
"reservedForUpgrades2", "bTagGhostTracks", "beamhalo", "gsf", "hltPixel", "hltIter0",
"hltIter1", "hltIter2", "hltIter3", "hltIter4", "hltIterX", "hiRegitMuInitialStep",
"hiRegitMuLowPtTripletStep", "hiRegitMuPixelPairStep", "hiRegitMuDetachedTripletStep",
"hiRegitMuMixedTripletStep", "hiRegitMuPixelLessStep", "hiRegitMuTobTecStep",
"hiRegitMuMuonSeededStepInOut", "hiRegitMuMuonSeededStepOutIn", "algoSize" };

if (algo < 0 || algo >= (int) TrackAlgorithm::algoSize) return names[0];
return names[algo];
}


//==============================================================================
// Track
//==============================================================================
Expand Down
2 changes: 2 additions & 0 deletions Track.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,8 @@ class TrackBase
// bool isStopped() const { return status_.stopped; }
// void setStopped() { status_.stopped = true; }

static const char* algoint_to_cstr(int algo);

// ------------------------------------------------------------------------

protected:
Expand Down
158 changes: 119 additions & 39 deletions mkFit/IterationConfig.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "IterationConfig.h"
#include "Config.h"
#include "Track.h" // for TrackBase::algoint_to_cstr, sigh

#include "nlohmann/json.hpp"

Expand All @@ -8,11 +9,18 @@
#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.

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationLayerConfig,
ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationLayerConfig,
/* float */ m_select_min_dphi,
/* float */ m_select_max_dphi,
/* float */ m_select_min_dq,
Expand All @@ -31,7 +39,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationLayerConfig,
/* float */ c_c2_2
)

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationParams,
ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationParams,
/* int */ nlayers_per_seed,
/* int */ maxCandsPerSeed,
/* int */ maxHolesPerCand,
Expand All @@ -50,7 +58,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationParams,
/* float */ c_dzmax_el
)

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationConfig,
ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationConfig,
// /* int */ m_iteration_index,
/* int */ m_track_algorithm,
/* mkfit::IterationParams */ m_params,
Expand All @@ -63,7 +71,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationConfig,
// /* function<void(const TrackerInfo&,const TrackVec&,const EventOfHits&,IterationSeedPartition&)> */ m_partition_seeds
)

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationsInfo,
ITCONF_DEFINE_TYPE_NON_INTRUSIVE(mkfit::IterationsInfo,
/* vector<mkfit::IterationConfig> */ m_iterations
)

Expand Down Expand Up @@ -243,12 +251,18 @@ int ConfigJsonPatcher::replace(const nlohmann::json &j)
std::string s("/");
s += key;
nlohmann::json::json_pointer jp(s);
if (m_verbose)
if (m_current->at(jp) != value)
{
std::cout << " " << get_abs_path() << s << ": " << m_current->at(jp) << " -> " << value << "\n";
if (m_verbose)
std::cout << " " << get_abs_path() << s << ": " << m_current->at(jp) << " -> " << value << "\n";

m_current->at(jp) = value;
++n_replaced;
}
m_current->at(jp) = value;
++n_replaced;
// else {
// if (m_verbose)
// std::cout << " " << get_abs_path() << s << ": " << m_current->at(jp) << " -> unchanged\n";
// }
}
else
{
Expand Down Expand Up @@ -382,113 +396,179 @@ namespace
}
}

ConfigJsonPatcher::PatchReport
ConfigJson_Patch_File(IterationsInfo &its_info, const std::vector<std::string> &fnames)
void ConfigJson_Patch_Files(IterationsInfo &its_info, const std::vector<std::string> &fnames,
ConfigJsonPatcher::PatchReport *report)
{
using nlohmann::json;

ConfigJsonPatcher cjp(Config::json_patch_verbose);
ConfigJsonPatcher cjp(Config::json_verbose);
cjp.Load(its_info);

if (Config::json_patch_dump_before)
{
std::cout << cjp.dump(3) << "\n";
}

ConfigJsonPatcher::PatchReport report;
ConfigJsonPatcher::PatchReport rep;

for (auto &fname : fnames)
{
std::ifstream ifs;
open_ifstream(ifs, fname, __func__);

if (Config::json_patch_verbose)
if (Config::json_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))
{
json j;
nlohmann::json j;
ifs >> j;
++n_read;

if (Config::json_patch_verbose)
if (Config::json_verbose)
{
std::cout << " Read JSON entity " << n_read << " -- applying patch:\n";
// std::cout << j.dump(3) << "\n";
}

int n_replaced = cjp.replace(j);

if (Config::json_patch_verbose)
if (Config::json_verbose)
{
std::cout << " Replaced " << n_replaced << " entries.\n";
}
cjp.cd_top();
n_tot_replaced += n_replaced;
}

if (Config::json_patch_verbose)
if (Config::json_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();

report.inc_counts(1, n_read, n_tot_replaced);
rep.inc_counts(1, n_read, n_tot_replaced);
}

if (Config::json_patch_dump_after)
if (rep.n_replacements > 0)
{
std::cout << cjp.dump(3) << "\n";
cjp.Save(its_info);
}

if (report.n_replacements > 0)
if (report) report->inc_counts(rep);
}

IterationConfig& ConfigJson_Load_File(IterationsInfo &its_info, const std::string &fname,
ConfigJsonPatcher::PatchReport *report)
{
ConfigJsonPatcher::PatchReport rep;

std::ifstream ifs;
open_ifstream(ifs, fname, __func__);

if (Config::json_verbose)
{
cjp.Save(its_info);
printf("%s begin reading from file %s.\n", __func__, fname.c_str());
}

return report;
}
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 (Config::json_verbose)
{
std::cout << " Read JSON entity, Iteration index is " << iii << " -- applying patch:\n";
}

ConfigJsonPatcher cjp(Config::json_verbose);
cjp.Load(its_info[iii]);

int n_replaced = cjp.replace(j);

cjp.cd_top();

if (Config::json_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(its_info[iii]);
}

if (report) report->inc_counts(rep);

return its_info[iii];
}

// ============================================================================
// Save each IterationConfig into a separate json file
// ============================================================================

void ConfigJson_Save_Iterations(IterationsInfo &its_info, const std::string &fname_fmt)
void ConfigJson_Save_Iterations(IterationsInfo &its_info, const std::string &fname_fmt,
bool include_iter_info_preamble)
{
assert(fname_fmt.find("%d") != std::string::npos && "JSON save filename-format must include a %d substring");
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];
snprintf(fname, 1024, fname_fmt.c_str(), ii);
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__);

ofs << "{ \"m_iterations/" << ii << "\": ";

ofs << std::setprecision(5);
if (include_iter_info_preamble)
{
ofs << "{ \"m_iterations/" << ii << "\": ";
}

nlohmann::json j;
nlohmann::ordered_json j;
to_json(j, itconf);

ofs << std::setw(1);
ofs << j;

ofs << " }\n";
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
Expand Down
Loading

0 comments on commit 77861c5

Please sign in to comment.