Browse Source

Adds option to override config parameters with command line arguments

  - Also simplifies the THParams mechanism to use a single class,
  rather than the two used previously.
Caleb Fangmeier 6 years ago
parent
commit
043253ad4f
5 changed files with 173 additions and 115 deletions
  1. 38 12
      include/argparse.hpp
  2. 52 40
      include/config.hpp
  3. 2 3
      include/dataset.hpp
  4. 78 58
      root/include/root_container.hpp
  5. 3 2
      root/include/root_dataset.hpp

+ 38 - 12
include/argparse.hpp

@@ -33,33 +33,59 @@
  */
 #ifndef argparse_hpp
 #define argparse_hpp
+
 #include <algorithm>
 #include <string>
 #include <vector>
-namespace fv_util{
-class ArgParser{
+#include <regex>
+
+namespace fv_util {
+    std::regex int_re("[0-9]+");
+    std::regex float_re("([0-9]+\\.?[0-9]*)|([0-9]*\\.?[0-9]+)");
+
+    class ArgParser {
     private:
-        std::vector <std::string> tokens;
-        std::string empty_string;
+        std::vector<std::string> tokens;
     public:
-        ArgParser (int &argc, char **argv){
-            for (int i=1; i < argc; ++i)
+        ArgParser(int &argc, char **argv) {
+            for (int i = 1; i < argc; ++i)
                 this->tokens.push_back(std::string(argv[i]));
         }
+
         /// @author iain
-        const std::string& getCmdOption(const std::string &option) const{
+        const std::string get_cmd_option(const std::string &option) const {
             std::vector<std::string>::const_iterator itr;
-            itr =  std::find(this->tokens.begin(), this->tokens.end(), option);
-            if (itr != this->tokens.end() && ++itr != this->tokens.end()){
+            itr = std::find(this->tokens.begin(), this->tokens.end(), option);
+            if (itr != this->tokens.end() && ++itr != this->tokens.end()) {
                 return *itr;
             }
-            return empty_string;
+            return "";
         }
+
         /// @author iain
-        bool cmdOptionExists(const std::string &option) const{
+        bool cmd_option_exists(const std::string &option) const {
             return std::find(this->tokens.begin(), this->tokens.end(), option)
                    != this->tokens.end();
         }
-};
+
+        void update_config() {
+            for (const std::string& s : tokens) {
+                int split_pos = s.find("=");
+                if (split_pos == std::string::npos) continue;
+                std::string key = s.substr(0, split_pos);
+                std::string val_raw = s.substr(split_pos+1, std::string::npos);
+                std::smatch match;
+                if(std::regex_match(val_raw, match, int_re)) {
+                    int val = atoi(val_raw.c_str());
+                    the_config->update_key(key, val);
+                } else if (std::regex_match(val_raw, match, float_re)) {
+                    float val = atof(val_raw.c_str());
+                    the_config->update_key(key, val);
+                } else {
+                    the_config->update_key(key, val_raw);
+                }
+            }
+        }
+    };
 }
 #endif // argparse_hpp

+ 52 - 40
include/config.hpp

@@ -31,6 +31,7 @@
  */
 #ifndef config_hpp
 #define config_hpp
+
 #include <string>
 #include <fstream>
 #include <sstream>
@@ -38,21 +39,23 @@
 #include "yaml-cpp/yaml.h"
 
 namespace fv_util {
-struct DataFileDescriptor{
-    std::string filename;
-    std::string label;
-    std::string category;
-    int file_number;
-    int n_events;
-
-    DataFileDescriptor():filename(""), label(""),category(""),file_number(-1), n_events(-1){ }
-
-    DataFileDescriptor(const std::string filename, const std::string label, const std::string category, const int n_events)
-      :filename(filename), label(label),category(category),file_number(-1), n_events(n_events) { }
-
-    DataFileDescriptor(const std::string filename, const std::string label, const std::string category, const int file_number, const int n_events)
-      :filename(filename), label(label),category(category),file_number(file_number), n_events(n_events) { }
-};
+    struct DataFileDescriptor {
+        std::string filename;
+        std::string label;
+        std::string category;
+        int file_number;
+        int n_events;
+
+        DataFileDescriptor() : filename(""), label(""), category(""), file_number(-1), n_events(-1) {}
+
+        DataFileDescriptor(const std::string filename, const std::string label, const std::string category,
+                           const int n_events)
+                : filename(filename), label(label), category(category), file_number(-1), n_events(n_events) {}
+
+        DataFileDescriptor(const std::string filename, const std::string label, const std::string category,
+                           const int file_number, const int n_events)
+                : filename(filename), label(label), category(category), file_number(file_number), n_events(n_events) {}
+    };
 }
 
 namespace YAML {
@@ -83,25 +86,33 @@ namespace YAML {
 }
 
 namespace fv_util {
-class Config{
+
+    class Config {
     private:
         std::string input_filename;
         YAML::Node root;
     public:
-        Config ()
-          :root(), input_filename("") { }
-        Config (const Config& c)
-          :root(c.root), input_filename(c.input_filename) { }
-        Config (const std::string& input_filename)
-          :root(YAML::LoadFile(input_filename)),
-           input_filename(input_filename) { }
-
-        template <typename KEY_TYPE>
-        YAML::Node get(const KEY_TYPE& key) {
+        Config()
+                : root(), input_filename("") {}
+
+        Config(const Config &c)
+                : root(c.root), input_filename(c.input_filename) {}
+
+        Config(const std::string &input_filename)
+                : root(YAML::LoadFile(input_filename)),
+                  input_filename(input_filename) {}
+
+        template<typename KEY_TYPE>
+        YAML::Node get(const KEY_TYPE &key) {
             auto val = root[key];
             return val;
         }
 
+        template<typename T>
+        void update_key(const std::string &key, const T &val) {
+            root[key] = val;
+        }
+
         std::string as_string() {
             std::stringstream config;
             std::ifstream s(input_filename);
@@ -113,7 +124,7 @@ class Config{
 
         size_t get_max_events() {
             YAML::Node max_events = root["max-events"];
-            if(!max_events) {
+            if (!max_events) {
                 return 0;
             }
             return max_events.as<size_t>();
@@ -121,7 +132,7 @@ class Config{
 
         bool get_debug() {
             YAML::Node debug_node = root["debug"];
-            if(!debug_node) {
+            if (!debug_node) {
                 return false;
             }
             return debug_node.as<bool>();
@@ -129,7 +140,7 @@ class Config{
 
         std::string get_output_filename() {
             YAML::Node output_file = root["output-file"];
-            if(output_file) {
+            if (output_file) {
                 return output_file.as<std::string>();
             } else {
                 std::cout << "Must specify output-file in config file." << std::endl;
@@ -144,8 +155,8 @@ class Config{
                 source_file_key = root["source-file-key"].as<std::string>();
             }
             YAML::Node source_files_nd = root[source_file_key];
-            if(source_files_nd.IsSequence()) {
-                for (const auto& f : source_files_nd) {
+            if (source_files_nd.IsSequence()) {
+                for (const auto &f : source_files_nd) {
                     source_files.push_back(f.as<DataFileDescriptor>());
                 }
             } else {
@@ -153,15 +164,16 @@ class Config{
             }
             return source_files;
         }
-};
-
-Config* the_config = nullptr;
-bool debug_on = false;
-void init_config(const std::string& input_filename){
-    if(the_config) delete the_config;
-    the_config = new Config(input_filename);
-    debug_on = the_config->get_debug();
-}
+    };
+
+    Config *the_config = nullptr;
+    bool debug_on = false;
+
+    void init_config(const std::string &input_filename) {
+        if (the_config) delete the_config;
+        the_config = new Config(input_filename);
+        debug_on = the_config->get_debug();
+    }
 
 }
 #endif // config_hpp

+ 2 - 3
include/dataset.hpp

@@ -56,7 +56,6 @@ namespace fv {
             INFO(GenValue::summary());
         }
 
-        int max_events;
         timeval start_time;
 
         void print_status() {
@@ -91,6 +90,7 @@ namespace fv {
 
     protected:
         std::map<std::string, GenContainer *> containers;
+        long max_events;
 
         virtual int get_events() = 0;
 
@@ -117,8 +117,7 @@ namespace fv {
         bool next(bool verbose=true) {
             int current_event = get_current_event();
             if (current_event == 0) gettimeofday(&start_time, nullptr);
-            if (verbose and (((current_event + 1) % 500) == 0 or current_event+1 == max_events)) print_status();
-            if (max_events && current_event + 1 >= max_events) return false;
+            if (verbose and (((current_event + 1) % 500) == 0 or current_event+1 == get_events())) print_status();
             GenValue::reset();
             return load_next();
         }

+ 78 - 58
root/include/root_container.hpp

@@ -90,27 +90,33 @@ namespace fv_root_util {
 namespace fv_root {
     using namespace fv;
 
-    struct TH1Params {
+    struct THParams {
         std::string label_x;
-        int nbins;
-        double low;
-        double high;
+        int nbins_x;
+        double low_x;
+        double high_x;
         std::string label_y;
+        int nbins_y;
+        double low_y;
+        double high_y;
 
-        static TH1Params lookup(const std::string &&param_key) {
+        static THParams lookup(const std::string &&param_key) {
             auto hist_params = fv_util::the_config->get("hist-params");
             if (!hist_params[param_key]) {
-                CRITICAL(
-                        "Key \"" << param_key << "\" does not exist under hist-params in supplied config file. Add it!",
-                        true);
+                CRITICAL("Key \"" << param_key
+                                  << "\" does not exist under hist-params in supplied config file. Add it!",
+                         true);
             } else {
                 auto params = hist_params[param_key];
-                return TH1Params({params["label_x"].as<std::string>(),
-                                  params["nbins"].as<int>(),
-                                  params["low"].as<double>(),
-                                  params["high"].as<double>(),
-                                  params["label_y"].as<std::string>()
-                                 });
+                return THParams({params["label_x"].as<std::string>(""),
+                                 params["nbins_x"].as<int>(20),
+                                 params["low_x"].as<double>(0),
+                                 params["high_x"].as<double>(1),
+                                 params["label_y"].as<std::string>(""),
+                                 params["nbins_y"].as<int>(20),
+                                 params["low_y"].as<double>(0),
+                                 params["high_y"].as<double>(1)
+                                });
 
             }
         }
@@ -120,18 +126,18 @@ namespace fv_root {
     class ContainerTH1 : public Container<TH1, V> {
     protected:
         std::string title;
-        TH1Params params;
+        THParams params;
 
     public:
-        ContainerTH1(const std::string &name, const std::string &title, const TH1Params &params)
+        ContainerTH1(const std::string &name, const std::string &title, const THParams &params)
                 : Container<TH1, V>(name), title(title), params(params) {
             this->container = new TH1D(this->get_name().c_str(), this->title.c_str(),
-                                       params.nbins, params.low, params.high);
+                                       params.nbins_x, params.low_x, params.high_x);
             this->container->SetXTitle(params.label_x.c_str());
             this->container->SetYTitle(params.label_y.c_str());
         }
 
-        ContainerTH1(const std::string &name, const TH1Params &params)
+        ContainerTH1(const std::string &name, const THParams &params)
                 : ContainerTH1<V>(name, name, params) { }
 
         void fill(const V &v) {
@@ -157,45 +163,13 @@ namespace fv_root {
         }
     };
 
-    struct TH2Params {
-        std::string label_x;
-        int nbins_x;
-        double low_x;
-        double high_x;
-        std::string label_y;
-        int nbins_y;
-        double low_y;
-        double high_y;
-
-        static TH2Params lookup(const std::string &&param_key) {
-            auto hist_params = fv_util::the_config->get("hist-params");
-            if (!hist_params[param_key]) {
-                CRITICAL(
-                        "Key \"" << param_key << "\" does not exist under hist-params in supplied config file. Add it!",
-                        true);
-            } else {
-                auto params = hist_params[param_key];
-                return TH2Params({params["label_x"].as<std::string>(),
-                                  params["nbins_x"].as<int>(),
-                                  params["low_x"].as<double>(),
-                                  params["high_x"].as<double>(),
-                                  params["label_y"].as<std::string>(),
-                                  params["nbins_y"].as<int>(),
-                                  params["low_y"].as<double>(),
-                                  params["high_y"].as<double>()
-                                 });
-
-            }
-        }
-    };
-
     template<typename V>
     class ContainerTH2 : public Container<TH2, V> {
     private:
         std::string title;
-        TH2Params params;
+        THParams params;
     public:
-        ContainerTH2(const std::string &name, const std::string &title, TH2Params params)
+        ContainerTH2(const std::string &name, const std::string &title, THParams params)
                 : Container<TH2, V>(name), title(title), params(params) {
             this->container = new TH2D(this->get_name().c_str(), this->title.c_str(),
                                        params.nbins_x, params.low_x, params.high_x,
@@ -204,7 +178,7 @@ namespace fv_root {
             this->container->SetYTitle(params.label_y.c_str());
         }
 
-        ContainerTH2(const std::string &name, const TH2Params &params)
+        ContainerTH2(const std::string &name, const THParams &params)
                 : ContainerTH2<V>(name, name, params) { }
 
         void fill(const V& x, const V& y) {
@@ -306,14 +280,14 @@ namespace fv_root {
         TH1F den;
         TH1F eff;
 
-        TH1Params params;
+        THParams params;
 
     public:
-        EfficiencyContainer(const std::string &name, TH1Params params)
+        EfficiencyContainer(const std::string &name, THParams params)
                 : Container<TH1F, V>(name),
-                  num{(name + "_num").c_str(), (name + "_num").c_str(), params.nbins, params.low, params.high},
-                  den{(name + "_den").c_str(), (name + "_den").c_str(), params.nbins, params.low, params.high},
-                  eff{name.c_str(), name.c_str(), params.nbins, params.low, params.high}, params(params) {
+                  num{(name + "_num").c_str(), (name + "_num").c_str(), params.nbins_x, params.low_x, params.high_x},
+                  den{(name + "_den").c_str(), (name + "_den").c_str(), params.nbins_x, params.low_x, params.high_x},
+                  eff{name.c_str(), name.c_str(), params.nbins_x, params.low_x, params.high_x}, params(params) {
             num.SetXTitle(params.label_x.c_str());
             num.SetYTitle(params.label_y.c_str());
             den.SetXTitle(params.label_x.c_str());
@@ -341,5 +315,51 @@ namespace fv_root {
         }
     };
 
+    template<typename V>
+    class EfficiencyContainer2D : public Container<TH2F, V> {
+    private:
+        TH2F num;
+        TH2F den;
+        TH2F eff;
+
+        THParams params;
+
+    public:
+        EfficiencyContainer2D(const std::string &name, THParams params)
+                : Container<TH2F, V>(name),
+                  num{(name + "_num").c_str(), (name + "_num").c_str(),
+                      params.nbins_x, params.low_x, params.high_x, params.nbins_y, params.low_y, params.high_y},
+                  den{(name + "_den").c_str(), (name + "_den").c_str(),
+                      params.nbins_x, params.low_x, params.high_x, params.nbins_y, params.low_y, params.high_y},
+                  eff{name.c_str(), name.c_str(),
+                      params.nbins_x, params.low_x, params.high_x, params.nbins_y, params.low_y, params.high_y},
+                  params(params) {
+            num.SetXTitle(params.label_x.c_str());
+            num.SetYTitle(params.label_y.c_str());
+            den.SetXTitle(params.label_x.c_str());
+            den.SetYTitle(params.label_y.c_str());
+            eff.SetXTitle(params.label_x.c_str());
+            eff.SetYTitle(params.label_y.c_str());
+            this->container = &eff;
+        }
+
+        TH2F *get_container() {
+            eff.Sumw2();
+            eff.Divide(&num, &den, 1, 1, "B");
+            return this->container;
+        }
+
+        void save_as(const std::string &fname, const SaveOption &option = SaveOption::PNG) {
+            fv_root_util::save_as(this->get_container(), fname, option);
+            fv_root_util::save_as(&num, fname, option);
+            fv_root_util::save_as(&den, fname, option);
+        }
+
+        void fill(const V& x,const V& y, bool pass) {
+            den.Fill(x, y);
+            if (pass) num.Fill(x, y);
+        }
+    };
+
 }
 #endif // root_container_hpp

+ 3 - 2
root/include/root_dataset.hpp

@@ -60,7 +60,8 @@ namespace fv_root {
         long nentries;
 
         int get_events() {
-            return nentries;
+            if (this->max_events) return std::min(this->max_events, nentries);
+            else return nentries;
         }
 
         int get_current_event() {
@@ -74,7 +75,7 @@ namespace fv_root {
         }
 
         bool load_next() {
-            if (next_entry >= nentries) return false;
+            if (next_entry >= get_events()) return false;
             tree_obj->LoadTree(next_entry);
             tree_obj->GetEntry(next_entry);
             ++next_entry;