Browse Source

Removes value aliases (not useful) and fixes EfficiencyContainer

Caleb Fangmeier 6 years ago
parent
commit
99b71fec50
4 changed files with 156 additions and 116 deletions
  1. 0 2
      include/container.hpp
  2. 29 80
      include/value.hpp
  3. 16 34
      root/include/root_container.hpp
  4. 111 0
      tools/generate_class.py

+ 0 - 2
include/container.hpp

@@ -135,8 +135,6 @@ namespace fv {
         virtual H *get_container() {
             return container;
         }
-
-        virtual void fill(const V&) = 0;
     };
 
 /**

+ 29 - 80
include/value.hpp

@@ -63,8 +63,18 @@
  */
 namespace fv {
 
+    class GenValue;  // Forward declaration
     template<typename T>
-    class Value;
+    class Value;  // Forward declaration
+
+    /**
+     * A static mapping containing all created Value objects.
+     * Every value object must have a unique name, and this name is used as
+     * a key in values to that object. This is used to enable more dynamic
+     * creation of objects as well as avoiding the uneccesary passing of
+     * pointers.
+     */
+    std::map<std::pair<const std::type_index, const std::string>, GenValue *> values;
 
 /**
  * A type-agnostic value.
@@ -72,10 +82,6 @@ namespace fv {
  * it is possible to handle collections of them. GenValue also provides the
  * rest of the type-independent interface to Value.
  */
-    class GenValue;
-
-    typedef std::map<std::string, GenValue *> ValueSet;
-
     class GenValue {
     private:
         /**
@@ -98,34 +104,11 @@ namespace fv {
             this->value_valid = false;
         }
 
-        /**
-         * A static mapping containing all created Value objects.
-         * Every value object must have a unique name, and this name is used as
-         * a key in values to that object. This is used to enable more dynamic
-         * creation of objects as well as avoiding the uneccesary passing of
-         * pointers.
-         */
-        inline static std::map<std::pair<const std::type_index, const std::string>, GenValue *> values;
-
-        /**
-         * Composite value names are typically nested. This makes complex
-         * values have rather unwieldy names. Therefore, one can declare
-         * aliases which allow for more human-usable names to be used. When a
-         * value is requested by name, an alias with that value takes precidence
-         * over a name with that value.
-         */
-        inline static std::map<std::pair<const std::type_index, const std::string>, GenValue *> aliases;
-
     public:
-        GenValue(const std::type_index &&ti, const std::string &name, const std::string &alias)
+        GenValue(const std::type_index &&ti, const std::string &name)
                 : name(name), value_valid(false) {
-            if (alias != "")
-                INFO("Registered value: \"" << name << "\" with alias: \"" << alias << "\"");
-            else
-                INFO("Registered value: \"" << name);
+            INFO("Registered value: \"" << name);
             values[std::make_pair(ti, name)] = this;
-            if (alias != "")
-                GenValue::alias(ti, alias, this);
         }
 
         const std::string &get_name() {
@@ -144,24 +127,7 @@ namespace fv {
         static Value<T> *get_value(const std::string &name) {
             const std::type_index &ti = typeid(T);
             auto lookup_id = std::make_pair(ti, name);
-            if (aliases[lookup_id] != nullptr)
-                return (Value<T> *) aliases[lookup_id];
-            else
-                return (Value<T> *) values[lookup_id];
-        }
-
-
-        static void alias(const std::type_index &ti, const std::string &name, GenValue *value) {
-            auto lookup_id = std::make_pair(ti, name);
-            if (aliases[lookup_id] != nullptr) {
-                WARNING("WARNING: alias \"" << name << "\" overrides previous entry.");
-            }
-            aliases[lookup_id] = value;
-        }
-
-        template<typename T>
-        static void alias(const std::string &name, Value<T> *value) {
-            alias(typeid(T), name, value);
+            return (Value<T> *) values[lookup_id];
         }
 
         static std::string summary() {
@@ -173,21 +139,6 @@ namespace fv {
                 if (value == nullptr) continue;
                 ss << "\tVALUE::\"" << key.second << "\" at address " << value << std::endl;
             }
-            ss << "And these aliases:" << std::endl;
-            for (auto item : aliases) {
-                auto &key = item.first;
-                auto &value = item.second;
-                std::string orig("VOID");
-                if (value == nullptr) continue;
-                for (auto v_item : values) {
-                    auto &v_value = v_item.second;
-                    if (v_value == value) {
-                        orig = v_value->get_name();
-                        break;
-                    }
-                }
-                ss << "\tALIAS::\"" << key.second << "\" referring to \"" << orig << "\"" << std::endl;
-            }
             return ss.str();
         }
 
@@ -212,8 +163,8 @@ namespace fv {
     template<typename T>
     class Value : public GenValue {
     public:
-        Value(const std::string &name, const std::string &alias = "")
-                : GenValue(typeid(T), name, alias) {}
+        Value(const std::string &name)
+                : GenValue(typeid(T), name) {}
 
         /** Calculate, if necessary, and return the value held by this object.
          */
@@ -221,7 +172,7 @@ namespace fv {
 
         /** Alias to get
          */
-        virtual T &operator() () = 0;
+        virtual T &operator()() = 0;
     };
 
 
@@ -240,9 +191,8 @@ namespace fv {
         T *val_ref;
 
     public:
-        ObservedValue(const std::string &name, T *val_ref, const std::string &alias = "")
-                : Value<T>(name, alias),
-                  val_ref(val_ref) {}
+        ObservedValue(const std::string &name, T *val_ref)
+                : Value<T>(name), val_ref(val_ref) {}
 
         static std::string fmt_name(const std::string &name) {
             return name;
@@ -258,7 +208,7 @@ namespace fv {
             return *val_ref;
         }
 
-        T &operator() (){
+        T &operator()() {
             return this->get();
         }
     };
@@ -295,8 +245,8 @@ namespace fv {
         virtual void update_value() = 0;
 
     public:
-        DerivedValue(const std::string &name, const std::string &alias = "")
-                : Value<T>(name, alias) {}
+        DerivedValue(const std::string &name)
+                : Value<T>(name) {}
 
         T &get() {
             if (!this->value_valid) {
@@ -309,7 +259,7 @@ namespace fv {
             return value;
         }
 
-        T &operator() () {
+        T &operator()() {
             return this->get();
         }
     };
@@ -325,8 +275,8 @@ namespace fv {
         void update_value() {}
 
     public:
-        PointerValue(const std::string &name, T *ptr, const std::string alias = "")
-                : DerivedValue<T *>(name, alias) {
+        PointerValue(const std::string &name, T *ptr)
+                : DerivedValue<T *>(name) {
             this->value = ptr;
         }
     };
@@ -348,8 +298,8 @@ namespace fv {
         }
 
     public:
-        ObjectValue(const std::string &name, T **ptr, const std::string alias = "")
-                : DerivedValue<T>(name, alias),
+        ObjectValue(const std::string &name, T **ptr)
+                : DerivedValue<T>(name),
                   obj_pointer(ptr) {}
     };
 
@@ -367,11 +317,10 @@ namespace fv {
             return "const::" + name;
         }
 
-        ConstantValue(const std::string &name, T const_value, const std::string alias = "")
-                : DerivedValue<T>(fmt_name(name), alias) {
+        ConstantValue(const std::string &name, T const_value)
+                : DerivedValue<T>(fmt_name(name)) {
             this->value = const_value;
         }
     };
-
 }
 #endif // value_hpp

+ 16 - 34
root/include/root_container.hpp

@@ -309,42 +309,21 @@ namespace fv_root {
     };
 
 
-    template<typename T>
-    class EfficiencyContainer : public Container<TH1F, std::vector<T>> {
+    template<typename V>
+    class EfficiencyContainer : public Container<TH1F, V> {
     private:
-        std::function<bool(T)> *selector;  // Selects whether object is up for consideration
-        std::function<bool(T)> *predicate; // Says whether the object passes the efficiency criteria
-        std::function<float(T)> *get_val;  // Returns a floating point value from the object that is actually
-        // used in the histogram
-        bool write_num_den;
         TH1F num;
         TH1F den;
         TH1F eff;
 
         TH1Params params;
 
-        void _fill() {
-            for (auto &obj : this->value->get_value()) {
-                if (selector == nullptr or (*selector)(obj)) {
-                    float val = (*get_val)(obj);
-                    den.Fill(val);
-                    if ((*predicate)(obj)) {
-                        num.Fill(val);
-                    }
-                }
-            }
-        }
-
     public:
-        EfficiencyContainer(const std::string &name, Value<std::vector<T>> *value, TH1Params params,
-                            std::function<bool(T)> *selector, std::function<bool(T)> *predicate,
-                            std::function<float(T)> *get_val, bool write_num_den = false)
-                : Container<TH1F, std::vector<T>>(name, value),
+        EfficiencyContainer(const std::string &name, TH1Params 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},
-                  selector(selector), predicate(predicate), get_val(get_val), params(params),
-                  write_num_den(write_num_den) {
+                  eff{name.c_str(), name.c_str(), params.nbins, params.low, params.high}, params(params) {
             num.SetXTitle(params.label_x.c_str());
             num.SetYTitle(params.label_y.c_str());
             den.SetXTitle(params.label_x.c_str());
@@ -360,16 +339,19 @@ namespace fv_root {
             return this->container;
         }
 
-        GenContainer *clone_as(const std::string &new_name) {
-            return new EfficiencyContainer<T>(new_name, this->value, this->params, selector, predicate, get_val);
-        }
-
         void save_as(const std::string &fname, const SaveOption &option = SaveOption::PNG) {
             fv_root_util::save_as(this->get_container(), fname, option);
-            if (write_num_den) {
-                fv_root_util::save_as(&num, fname, option);
-                fv_root_util::save_as(&den, fname, option);
-            }
+            fv_root_util::save_as(&num, fname, option);
+            fv_root_util::save_as(&den, fname, option);
+        }
+
+        void fill(const V& v, bool pass) {
+            den.Fill(v);
+            if (pass) num.Fill(v);
+        }
+
+        GenContainer *clone_as(const std::string &new_name) {
+            return new EfficiencyContainer<V>(new_name, this->params);
         }
     };
 

+ 111 - 0
tools/generate_class.py

@@ -0,0 +1,111 @@
+#!/usr/bin/env python3
+
+
+def generate_collection_class(obj_name, obj_attrs):
+    src = []
+
+    src += f'''\
+struct {obj_name};
+
+class {obj_name}Collection {{
+  public:
+    class iter {{
+      public:
+        iter(const {obj_name}Collection* collection, size_t idx)
+          :collection(collection), idx(idx) {{ }}
+        iter operator++() {{ ++idx; return *this; }}
+        bool operator!=(const iter & other) {{ return idx != other.idx; }}
+        const {obj_name} operator*() const;
+      private:
+        const {obj_name}Collection* collection;
+        size_t idx;
+    }};
+
+'''.splitlines()
+
+    for field in obj_attrs['fields']:
+        name = field['name']
+        type_ = field['type']
+        src.append(f'    Value<vector<{type_}>>* val_{name};')
+
+    src.append(f'\n    {obj_name}Collection() {{ }}\n')
+
+    src.append('    void init(TrackingDataSet& tds){')
+    for field in obj_attrs['fields']:
+        name = field['name']
+        type_ = field['type']
+        prefix = obj_attrs['treename_prefix']+'_'
+        src.append(f'        val_{name} = tds.track_branch_obj<vector<{type_}>>("{prefix}{name}");')
+    src.append('    }\n')
+    first_obj_name = list(obj_attrs['fields'])[0]['name']
+    src.append(f'    size_t size() const {{ return (*val_{first_obj_name})().size();}}\n')
+    src.append(f'    const {obj_name} operator[](size_t) const;')
+    src.append('    iter begin() const { return iter(this, 0); }')
+    src.append('    iter end() const { return iter(this, size()); }')
+    src.append('};')
+
+    src += f'''
+struct {obj_name} {{
+    const {obj_name}Collection* collection;
+    const size_t idx;
+    {obj_name}(const {obj_name}Collection* collection, const size_t idx)
+      :collection(collection), idx(idx) {{ }}\n
+'''.splitlines()
+
+    for field in obj_attrs['fields']:
+        name = field['name']
+        type_ = field['type']
+        src.append(f'    const {type_}& {name}() const {{return (*collection->val_{name})().at(idx);}}')
+    src.append('};')
+
+    src.append(f'''
+const {obj_name} {obj_name}Collection::iter::operator*() const {{
+    return {{collection, idx}};
+}}
+const {obj_name} {obj_name}Collection::operator[](size_t idx) const {{
+    return {{this, idx}};
+}}
+''')
+    return '\n'.join(src)
+
+
+def generate_header(input_filename, output_filename):
+    from datetime import datetime
+
+    return f'''\
+/** {output_filename} created on {datetime.now()} by generate_class.py
+ * AVOID EDITING THIS FILE BY HAND!! Instead edit {input_filename} and re-run
+ * generate_class.py
+ */
+#include "filval.hpp"
+#include "root_filval.hpp"
+
+#include<cmath>
+
+#include "TrackingNtuple.h"
+
+using namespace std;
+using namespace fv;
+using namespace fv_root;
+
+typedef TreeDataSet<TrackingNtuple> TrackingDataSet;
+'''
+
+
+if __name__ == '__main__':
+    import argparse
+    import yaml
+    parser = argparse.ArgumentParser()
+    add = parser.add_argument
+    add('input_file', help='An input YAML file defining the objects to generate')
+
+    args = parser.parse_args()
+    classes = []
+    with open(args.input_file) as fi:
+        for obj, attrs in yaml.load(fi).items():
+            classes.append(generate_collection_class(obj, attrs))
+    output_filename = args.input_file.replace('.yaml', '.hpp')
+    with open(output_filename, 'w') as fo:
+        fo.write(generate_header(args.input_file, output_filename))
+        for class_ in classes:
+            fo.write(class_)