Browse Source

Makes name generation for most values automatic.

  - These names can get rather long so aliasing has been built in to more
    easily refer to values by rememberable names. This includes having names
    for "Function" objects, a newly added class that pairs std::function
    objects with a name.
  - Also cleans up implementation of TH* wrappers.
Caleb Fangmeier 7 years ago
parent
commit
83508afe68
9 changed files with 352 additions and 205 deletions
  1. 1 0
      .gitignore
  2. 4 1
      Makefile
  3. 1 77
      MiniTreeDataSet.hpp
  4. 86 5
      TTTT_Analysis.cpp
  5. 37 9
      filval/container.hpp
  6. 6 1
      filval/dataset.hpp
  7. 0 3
      filval/filter.hpp
  8. 155 68
      filval/value.hpp
  9. 62 41
      filval_root/container.hpp

+ 1 - 0
.gitignore

@@ -6,6 +6,7 @@ __pycache__/
 *.d
 *.so
 *.pcm
+tags
 
 # output data files
 *.root

+ 4 - 1
Makefile

@@ -1,5 +1,5 @@
 CC=clang++
-CFLAGS=`root-config --libs --cflags` -Wall --std=c++1z -ferror-limit=4
+CFLAGS=`root-config --libs --cflags` -Wall --std=c++1z -ferror-limit=2
 CFLAGS_DEBUG=$(CFLAGS) -g3 -O0
 INCLUDEDIR=-I.
 
@@ -7,3 +7,6 @@ TTTT_Analysis: TTTT_Analysis.cpp
 		clear
 		$(CC) -o main TTTT_Analysis.cpp $(CFLAGS_DEBUG) $(INCLUDEDIR)
 		# $(CC) -o main TTTT_Analysis.cpp $(CFLAGS) $(INCLUDEDIR)
+
+ctags: 
+	ctags *.cpp *.hpp filval/*.hpp filval_root/*.hpp

+ 1 - 77
MiniTreeDataSet.hpp

@@ -30,68 +30,9 @@ class MiniTreeDataSet : public DataSet,
             return next_entry-1;
         }
 
-        void enable_branches(){
-            fChain->SetBranchStatus("*", false);
-            track_branch<int>("nJet");
-            track_branch<int>("nLepGood");
-            track_branch_ptr<float>("LepGood_pt");
-            track_branch_ptr<float>("LepGood_eta");
-            track_branch_ptr<float>("LepGood_phi");
-            track_branch_ptr<float>("LepGood_mass");
-        }
     public:
         MiniTreeDataSet(TTree *tree)
           :MiniTree(tree){
-            enable_branches();
-            auto lookup = [](const string& name){ return GenValue::get_value(name);};
-            auto lookup_filter = [](const string& name){ return dynamic_cast<Filter*>(GenValue::get_value(name));};
-            auto mean = [](vector<float> v){
-                    int n = 0;
-                    float sum = 0;
-                    for (float e : v){
-                        n++;
-                        sum += e;
-                    }
-                    return n>0 ? sum / n : 0;
-                    };
-
-            auto pt_wrapper  = new WrapperVector<float>("LepGood_pt_vec", "nLepGood", "LepGood_pt");
-            auto eta_wrapper = new WrapperVector<float>("LepGood_eta_vec", "nLepGood", "LepGood_eta");
-            auto phi_wrapper = new WrapperVector<float>("LepGood_phi_vec", "nLepGood", "LepGood_phi");
-            auto m_wrapper   = new WrapperVector<float>("LepGood_mass_vec", "nLepGood", "LepGood_mass");
-
-            auto get_energy = [](float pt, float eta, float phi, float m){
-                TLorentzVector t;
-                t.SetPtEtaPhiM(pt, eta, phi, m);
-                return t.E();
-            };
-            new ZipMapFour<float, float>("lepton_energy", get_energy, pt_wrapper, eta_wrapper, phi_wrapper, m_wrapper);
-
-            new Reduce<float>("avg_lepton_energy", mean , "lepton_energy");
-
-
-            new Filter("nLepGood>=3", [nLepGood=lookup("nLepGood")](){
-                    return dynamic_cast<Value<int>*>(nLepGood)->get_value() >=3;});
-
-            new Filter("nLepGood<=4", [nLepGood=lookup("nLepGood")](){
-                    return dynamic_cast<Value<int>*>(nLepGood)->get_value() <=4;});
-            new RangeFilter<int>("3<=nLepGood<5", dynamic_cast<Value<int>*>(lookup("nLepGood")), 3, 5);
-
-
-            add_container(new ContainerTH1I("nLepGood", "Lepton Multiplicity", 10, 0, 10, lookup("nLepGood")));
-
-            add_container(new ContainerTH1I("nLepGood2", "Lepton Multiplicity", 10, 0, 10, lookup("nLepGood")));
-            containers.at("nLepGood2")->add_filter(lookup_filter("3<=nLepGood<5"));
-
-            add_container(new ContainerTH1I("nLepGood3", "Lepton Multiplicity", 10, 0, 10, lookup("nLepGood")));
-            containers.at("nLepGood3")->add_filter(!(*lookup_filter("3<=nLepGood<5")));
-
-            new Pair<int, int>("(nLepGood,nJet)", "nLepGood", "nJet");
-            add_container(new ContainerTGraph("nLepvsnJet", lookup("(nLepGood,nJet)")));
-
-            add_container(new ContainerTH1F("avg_lepton_energy", "Average Lepton Energy", 50, 0, 500, lookup("avg_lepton_energy")));
-            add_container(new ContainerTH1F("max_lepton_energy", "Maximum Lepton Energy", 50, 0, 500, lookup("max_lepton_energy")));
-
             next_entry = 0;
             nentries = fChain->GetEntriesFast();
           }
@@ -113,28 +54,11 @@ class MiniTreeDataSet : public DataSet,
             cout << "Registering pointer branch \"" << bname
                 << "\" with address " << bref
                 << " and type " << typeid(bref).name() << endl;
-            return new ConstantValue<T*>(bname, bref);
+            return new PointerValue<T>(bname, bref);
         }
 
         void register_container(GenContainer* container){
             containers[container->get_name()] = container;
         }
-        /* void process(){ */
-        /*     cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl; */
-        /*     cout << "In process" << endl; */
-        /*     cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl; */
-        /*     auto x = dynamic_cast<ConstantValue<float*>*>(values["LepGood_pt"]); */
-        /*     cout << x->get_value() << endl; */
-        /*     /1* foo(); *1/ */
-        /*     while( load_next() ){ */
-        /*         /1* foo(); *1/ */
-        /*         cout << x->get_value() << endl; */
-        /*         GenValue::reset(); */
-        /*         for(auto con : containers) */
-        /*             con.second->fill(); */
-        /*         /1* foo(); *1/ */
-        /*     } */
-        /* } */
-
 };
 #endif // minitreedataset_h

+ 86 - 5
TTTT_Analysis.cpp

@@ -8,6 +8,7 @@
 
 #include "filval/filval.hpp"
 #include "filval_root/filval_root.hpp"
+#include "log.hpp"
 
 #include "MiniTreeDataSet.hpp"
 
@@ -15,7 +16,6 @@ using namespace std;
 using namespace filval;
 using namespace filval::root;
 
-
 void print_pair(Pair<double, double> dp){
     pair<double, double> p = dp.get_value();
     cout << "(" << p.first << ", " << p.second << ")\n";
@@ -28,13 +28,13 @@ void test1(){
     ObservedValue<double> x_val("x", &x);
     ObservedValue<double> y_val("y", &y);
 
-    Pair<double, double> dp("(x,y)", &x_val, &y_val);
+    Pair<double, double> dp(&x_val, &y_val);
     print_pair(dp);
     x = 2;
     y = 2;
     print_pair(dp);
 
-    ContainerVector<double> cont(&x_val, "cont");
+    ContainerVector<double> cont("cont", &x_val);
     x = 12;
     cont.fill();
     x = 2;
@@ -49,7 +49,7 @@ void test1(){
 void test2(){
     double x = 12;
     ObservedValue<double> x_val("x", &x);
-    ContainerTH1D hist("h1", "Hist", 20, 0, 20, &x_val);
+    ContainerTH1D hist("h1", "Hist", &x_val, 20, 0, 20);
     hist.fill();
     hist.fill();
     hist.fill();
@@ -108,7 +108,88 @@ void test3(){
     f->Close();
     delete f;
 }
+GenValue* lookup(const string& name){
+    return GenValue::get_value(name);
+}
+Filter* lookup_filter(const string& name){
+    return dynamic_cast<Filter*>(GenValue::get_value(name));
+}
+
+void enable_branches(MiniTreeDataSet* mt){
+    mt->fChain->SetBranchStatus("*", false);
+    mt->track_branch<int>("nJet");
+    mt->track_branch<int>("nLepGood");
+    mt->track_branch_ptr<float>("LepGood_pt");
+    mt->track_branch_ptr<float>("LepGood_eta");
+    mt->track_branch_ptr<float>("LepGood_phi");
+    mt->track_branch_ptr<float>("LepGood_mass");
+}
+
+void declare_values(MiniTreeDataSet* mt){
+    auto mean = Function<float(vector<float>)>("mean", [](vector<float> v){
+            int n = 0;
+            float sum = 0;
+            for (float e : v){
+                n++;
+                sum += e;
+            }
+            return n>0 ? sum / n : 0;
+            });
+
+    auto pt_wrapper  = new WrapperVector<float>("nLepGood", "LepGood_pt");
+    auto eta_wrapper = new WrapperVector<float>("nLepGood", "LepGood_eta");
+    auto phi_wrapper = new WrapperVector<float>("nLepGood", "LepGood_phi");
+    auto m_wrapper   = new WrapperVector<float>("nLepGood", "LepGood_mass");
+
+    auto get_energy = Function<float(float,float,float,float)>("get_energy", [](float pt, float eta, float phi, float m){
+        TLorentzVector t;
+        t.SetPtEtaPhiM(pt, eta, phi, m);
+        return t.E();
+    });
+    auto lepton_energy = new ZipMapFour<float, float>(get_energy, pt_wrapper, eta_wrapper, phi_wrapper, m_wrapper);
+    GenValue::alias("lepton_energy", lepton_energy);
+
+    GenValue::alias("avg_lepton_energy", new Reduce<float>(mean , "lepton_energy"));
+    GenValue::alias("max_lepton_energy", new Max<float>("lepton_energy"));
+
+
+    new Filter("nLepGood>=3", [nLepGood=lookup("nLepGood")](){
+            return dynamic_cast<Value<int>*>(nLepGood)->get_value() >=3;});
+
+    new Filter("nLepGood<=4", [nLepGood=lookup("nLepGood")](){
+            return dynamic_cast<Value<int>*>(nLepGood)->get_value() <=4;});
+    new RangeFilter<int>("3<=nLepGood<5", dynamic_cast<Value<int>*>(lookup("nLepGood")), 3, 5);
+}
+
+void declare_containers(MiniTreeDataSet* mt){
+    mt->add_container(new ContainerTH1I("nLepGood", "Lepton Multiplicity", lookup("nLepGood"), 10, 0, 10));
+
+    mt->add_container(new ContainerTH1I("nLepGood2", "Lepton Multiplicity", lookup("nLepGood"), 10, 0, 10));
+    mt->get_container("nLepGood2")->add_filter(lookup_filter("3<=nLepGood<5"));
+
+    mt->add_container(new ContainerTH1I("nLepGood3", "Lepton Multiplicity", lookup("nLepGood"), 10, 0, 10));
+    mt->get_container("nLepGood3")->add_filter(!(*lookup_filter("3<=nLepGood<5")));
+
+    mt->add_container(new ContainerTGraph("nLepvsnJet", new Pair<int, int>("nLepGood", "nJet") ));
+
+    mt->add_container(new ContainerTH1F("avg_lepton_energy", "Average Lepton Energy", lookup("avg_lepton_energy"), 50, 0, 500));
+    mt->add_container(new ContainerTH1F("max_lepton_energy", "Maximum Lepton Energy", lookup("max_lepton_energy"), 50, 0, 500));
+
+}
+
+void run_analysis(){
+    TFile *f = TFile::Open("./data/TTTT_ext_treeProducerSusyMultilepton_tree.root");
+    TTree *tree = (TTree*) f->Get("tree");
+    MiniTreeDataSet mt(tree);
+    enable_branches(&mt);
+    declare_values(&mt);
+    declare_containers(&mt);
+    mt.process();
+}
+
 
 int main(int argc, const char* argv[]){
-    test3();
+    clog.rdbuf(new Log("mylog.txt"));
+    /* run_analysis(); */
+    clog << "hello log again" << endl;
 }

+ 37 - 9
filval/container.hpp

@@ -13,19 +13,23 @@ class GenContainer{
     protected:
         virtual void _fill() = 0;
     public:
+        GenContainer(const std::string name, const std::string& desc)
+          :name(name),desc(desc) { }
+
         GenContainer(const std::string name)
-          :name(name){ }
+          :GenContainer(name,"N/A"){ }
+
         void add_filter(GenValue* filter){
             filters.push_back(dynamic_cast<Filter*>(filter));
         }
+
         void fill(){
             for (auto filter : filters){
-                if (!filter->get_value()){
-                    return;
-                }
+                if (!filter->get_value()) return;
             }
             _fill();
         }
+
         void set_description(const std::string& description){
             desc = description;
         }
@@ -40,7 +44,7 @@ class Container : public GenContainer{
     protected:
         H* container;
     public:
-        Container(H* container, const std::string name)
+        Container(const std::string& name, H* container)
           :GenContainer(name),
            container(container){ }
         virtual H* get_container(){
@@ -58,15 +62,39 @@ class ContainerVector : public Container<std::vector<T> >{
             this->container->push_back(value->get_value());
         }
     public:
-        ContainerVector(std::vector<T> *container, Value<T>* value, const std::string name)
-          :Container<std::vector<T> >(container, name),
+        ContainerVector(const std::string& name, std::vector<T> *container, Value<T>* value)
+          :Container<std::vector<T> >(name, container),
            value(value){ }
-        ContainerVector(Value<T>* value, const std::string name)
-          :Container<std::vector<T> >(NULL, name),
+        ContainerVector(const std::string& name, Value<T>* value)
+          :Container<std::vector<T> >(name, NULL),
            value(value){
             this->container = new std::vector<T>();
         }
 };
 
+template <typename T>
+class ContainerMean : public Container<T>{
+    private:
+        Value<T>* value;
+        int count;
+        T sum;
+
+        void _fill(){
+            count++;
+            sum += value->get_value();
+        }
+    public:
+        ContainerMean(const std::string& name, Value<T>* value)
+          :Container<std::vector<T> >(name, NULL),
+           value(value){
+            this->container = new T();
+        }
+
+        T* get_container(){
+            *(this->container) = sum/count;
+            return (this->container);
+        }
+};
+
 }
 #endif // container_hpp

+ 6 - 1
filval/dataset.hpp

@@ -38,7 +38,12 @@ class DataSet{
             containers[container->get_name()] = container;
         }
         GenContainer* get_container(std::string container_name){
-            return containers.at(container_name);
+            GenContainer* c = containers[container_name];
+            if (c == NULL){
+                std::cout << "Request for container \"" << container_name << "\" failed. Doesn't exist." << std::endl;
+                exit(-1);
+            }
+            return c;
         }
 };
 }

+ 0 - 3
filval/filter.hpp

@@ -31,10 +31,7 @@ class Filter : public DerivedValue<bool>{
         }
 
         Filter* operator!(){
-            std::cout << std::string("!") << std::endl;
-            std::cout << this << this->get_name() << std::endl;
             auto new_name = std::string("!(") + this->get_name() + std::string(")");
-            std::cout << new_name << std::endl;
             return new Filter(new_name, [this](){return !this->get_value();});
         }
 };

+ 155 - 68
filval/value.hpp

@@ -55,12 +55,44 @@
  */
 namespace filval{
 
-/** 
+/**
+ * In order to enable proper provenance tracking, and at the same time keep
+ * the ability to embed functions into values, the Function class should be
+ * used. It is simply a wrapper around a std::function that also has a name.
+ * This name is used when generating the name of values that use the function.
+ * A function name is automatically prepended with "func::" to explicitly state
+ * that the value is the result of a computation encoded within the function
+ * object, and not from some other Value object. Unfortunately, it is up to the
+ * user to find where that function is defined in the source code to inspect
+ * what it is doing. But hopefully this isn't too onerous by just using grep.
+ */
+template<typename> class Function; // undefined
+template <typename R, typename... ArgTypes>
+class Function<R(ArgTypes...)> {
+    std::string name;
+    std::function<R(ArgTypes...)> f;
+
+    public:
+        Function(const std::string& name, std::function<R(ArgTypes...)> f)
+          :name("func::"+name),f(f){ }
+
+    std::string& get_name(){
+        return name;
+    }
+
+    R operator()(ArgTypes ...args){
+        return f(args...);
+    }
+};
+
+/**
  * A type-agnostic value.
  * It is necessary to create a type-agnostic parent class to Value so that
  * 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:
         /**
@@ -85,30 +117,71 @@ class GenValue{
          * pointers.
          */
         inline static std::map<const std::string, GenValue*> values;
+        inline static std::map<const std::string, GenValue*> aliases;
     public:
         GenValue(const std::string& name)
           :name(name) {
             values[name] = this;
         }
+
         const std::string& get_name(){
             return name;
         }
+
         static void reset(){
             for (auto val : values){
                 val.second->_reset();
             }
         }
+
         static GenValue* get_value(const std::string& name){
-            return values.at(name);
+            if (aliases[name] != NULL)
+                return aliases[name];
+            else if (values[name] != NULL)
+                return values[name];
+            else{
+                std::cout << "ERROR: Could not find alias or value \"" << name << "\"" << std::endl;
+                std::cout << "I'll tell you the ones I know about." << std::endl;
+                summary();
+                std::cout << "Aborting... :(" << std::endl;
+                exit(-1);
+            }
+        }
+
+        static void alias(const std::string& name, GenValue* value){
+            if (aliases[name] != NULL){
+                std::cout << "WARNING: alias \"" << name << "\" overrides previous entry." << std::endl;
+            }
+            aliases[name] = value;
         }
+
+        static GenValue* alias(const std::string& name){
+            if (values[name] != NULL){
+                std::cout << "WARNING: alias \"" << name << "\" does not exist." << std::endl;
+            }
+            return aliases[name];
+        }
+
         static void summary(){
             std::cout << "The following values have been created: " << std::endl;
             for (auto value : values){
+                if (value.second == NULL) continue;
                 std::cout << "\t\"" << value.first << "\" at address " << value.second << std::endl;
             }
+            std::cout << "And these aliases:" << std::endl;
+            for (auto alias : aliases){
+                std::string orig("VOID");
+                if (alias.second == NULL) continue;
+                for (auto value : values){
+                    if (alias.second == value.second){
+                        orig = value.second->get_name();
+                        break;
+                    }
+                }
+                std::cout << "\t\"" << alias.first << "\" referring to \"" << orig << "\"" << std::endl;
+            }
         }
 };
-typedef std::map<std::string, GenValue*> ValueSet;
 
 
 /**
@@ -230,13 +303,12 @@ class WrapperVector : public DerivedValue<std::vector<T> >{
         }
 
     public:
-        WrapperVector(const std::string& name, Value<int>* _size, Value<T*>* _data)
-          :DerivedValue<std::vector<T> >(name),
-           size(_size), data(_data){ }
+        WrapperVector(Value<int>* size, Value<T*>* data)
+          :DerivedValue<std::vector<T> >("vectorOf("+size->get_name()+","+data->get_name()+")"),
+           size(size), data(data){ }
 
-        WrapperVector(const std::string& name, const std::string &label_size, const std::string &label_data)
-          :WrapperVector(name,
-                         dynamic_cast<Value<int>*>(GenValue::values.at(label_size)),
+        WrapperVector(const std::string &label_size, const std::string &label_data)
+          :WrapperVector(dynamic_cast<Value<int>*>(GenValue::values.at(label_size)),
                          dynamic_cast<Value<T*>*>(GenValue::values.at(label_data))) { }
 };
 
@@ -252,12 +324,11 @@ class Pair : public DerivedValue<std::pair<T1, T2> >{
             this->value.second = value_pair.second->get_value();
         }
     public:
-        Pair(const std::string name, Value<T1> *value1, Value<T2> *value2)
-          :DerivedValue<std::pair<T1, T2> >(name),
+        Pair(Value<T1> *value1, Value<T2> *value2)
+          :DerivedValue<std::pair<T1, T2> >("pair("+value1->get_name()+","+value2->get_name()+")"),
            value_pair(value1, value2){ }
-        Pair(const std::string& name, const std::string& label1, const std::string& label2)
-          :Pair(name,
-                dynamic_cast<Value<T1>*>(GenValue::values.at(label1)),
+        Pair(const std::string& label1, const std::string& label2)
+          :Pair(dynamic_cast<Value<T1>*>(GenValue::values.at(label1)),
                 dynamic_cast<Value<T1>*>(GenValue::values.at(label2))){ }
 };
 
@@ -277,7 +348,7 @@ class Pair : public DerivedValue<std::pair<T1, T2> >{
 template <typename R, typename T>
 class ZipMapFour : public DerivedValue<std::vector<R> >{
     private:
-        std::function<R(T, T, T, T)> f;
+        Function<R(T, T, T, T)> f;
         Value<std::vector<T> >* v1;
         Value<std::vector<T> >* v2;
         Value<std::vector<T> >* v3;
@@ -298,17 +369,16 @@ class ZipMapFour : public DerivedValue<std::vector<R> >{
         }
 
     public:
-        ZipMapFour(const std::string& name, std::function<R(T, T, T, T)> f,
+        ZipMapFour(Function<R(T, T, T, T)> f,
                    Value<std::vector<T> >* v1, Value<std::vector<T> >* v2,
                    Value<std::vector<T> >* v3, Value<std::vector<T> >* v4)
-          :DerivedValue<std::vector<R> >(name),
+          :DerivedValue<std::vector<R> >("zipmap("+f.get_name()+":"+v1->get_name()+","+v2->get_name()+","+v3->get_name()+","+v4->get_name()+")"),
            f(f), v1(v1), v2(v2), v3(v3), v4(v4) { }
 
-        ZipMapFour(const std::string& name,
-                   std::function<R(T, T, T, T)> f,
+        ZipMapFour(Function<R(T, T, T, T)> f,
                    const std::string &label1, const std::string &label2,
                    const std::string &label3, const std::string &label4)
-          :ZipMapFour(name, f,
+          :ZipMapFour(f,
                       dynamic_cast<Value<std::vector<T> >*>(GenValue::values.at(label1)),
                       dynamic_cast<Value<std::vector<T> >*>(GenValue::values.at(label2)),
                       dynamic_cast<Value<std::vector<T> >*>(GenValue::values.at(label3)),
@@ -324,18 +394,18 @@ class ZipMapFour : public DerivedValue<std::vector<R> >{
 template <typename T>
 class Reduce : public DerivedValue<T>{
     private:
-        std::function<T(std::vector<T>)> reduce;
+        Function<T(std::vector<T>)> reduce;
         Value<std::vector<T> >* v;
         void update_value(){
             this->value = reduce(v->get_value());
         }
     public:
-        Reduce(const std::string& name, std::function<T(std::vector<T>)> reduce, Value<std::vector<T> >* v)
-          :DerivedValue<T>(name),
+        Reduce(Function<T(std::vector<T>)> reduce, Value<std::vector<T> >* v)
+          :DerivedValue<T>("reduceWith("+reduce.get_name()+":"+v->get_name()+")"),
            reduce(reduce), v(v) { }
 
-        Reduce(const std::string& name, std::function<T(std::vector<T>)> reduce, const std::string& v_name)
-          :Reduce(name, reduce, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name))) { }
+        Reduce(Function<T(std::vector<T>)> reduce, const std::string& v_name)
+          :Reduce(reduce, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name))) { }
 };
 
 /**
@@ -344,8 +414,10 @@ class Reduce : public DerivedValue<T>{
 template <typename T>
 class Max : public Reduce<T>{
     public:
-        Max(const std::string& name, const std::string& v_name)
-          :Reduce<T>(name, [](std::vector<T> vec){ return std::max(vec.begin(), vec.end());}, v_name) { }
+        Max(const std::string& v_name)
+          :Reduce<T>(Function<T(std::vector<T>)>("max", [](std::vector<T> vec){ 
+                         return *std::max_element(vec.begin(), vec.end());}),
+                     v_name) { }
 };
 
 /**
@@ -354,8 +426,10 @@ class Max : public Reduce<T>{
 template <typename T>
 class Min : public Reduce<T>{
     public:
-        Min(const std::string& name, const std::string& v_name)
-          :Reduce<T>(name, [](std::vector<T> vec){ return std::min(vec.begin(), vec.end());}, v_name) { }
+        Min(const std::string& v_name)
+          :Reduce<T>(Function<T(std::vector<T>)>("min", [](std::vector<T> vec){ 
+                         return *std::min_element(vec.begin(), vec.end());}),
+                     v_name) { }
 };
 
 /**
@@ -364,12 +438,11 @@ class Min : public Reduce<T>{
 template <typename T>
 class Mean : public Reduce<T>{
     public:
-        Mean(const std::string& name, const std::string& v_name)
-          :Reduce<T>(name,
-                     [](std::vector<T> vec){
+        Mean(const std::string& v_name)
+          :Reduce<T>(Function<T(std::vector<T>)>("mean", [](std::vector<T> vec){
                         int n = 0; T sum = 0;
                         for (T e : vec){ n++; sum += e; }
-                        return n>0 ? sum / n : 0; },
+                        return n>0 ? sum / n : 0; }),
                      v_name) { }
 };
 
@@ -379,8 +452,9 @@ class Mean : public Reduce<T>{
 template <typename T>
 class ElementOf : public Reduce<T>{
     public:
-        ElementOf(const std::string& name, Value<int>* index, const std::string& v_name)
-          :Reduce<T>(name, [index](std::vector<T> vec){return vec[index->get_value()];}, v_name) { }
+        ElementOf(Value<int>* index, const std::string& v_name)
+          :Reduce<T>(Function<T(std::vector<T>)>("elementOf", [index](std::vector<T> vec){return vec[index->get_value()];}),
+                     v_name) { }
         ElementOf(const std::string& name, int index, const std::string& v_name)
           :Reduce<T>(name, [index](std::vector<T> vec){return vec[index];}, v_name) { }
 };
@@ -393,18 +467,18 @@ class ElementOf : public Reduce<T>{
 template <typename T>
 class ReduceIndex : public DerivedValue<std::pair<T, int> >{
     private:
-        std::function<std::pair<T,int>(std::vector<T>)> reduce;
+        Function<std::pair<T,int>(std::vector<T>)> reduce;
         Value<std::vector<T> >* v;
         void update_value(){
             this->value = reduce(v->get_value());
         }
     public:
-        ReduceIndex(const std::string& name, std::function<std::pair<T,int>(std::vector<T>)> reduce, Value<std::vector<T> >* v)
-          :DerivedValue<T>(name),
+        ReduceIndex(Function<std::pair<T,int>(std::vector<T>)> reduce, Value<std::vector<T> >* v)
+          :DerivedValue<T>("reduceIndexWith("+reduce.get_name()+":"+v->get_name()+")"),
            reduce(reduce), v(v) { }
 
-        ReduceIndex(const std::string& name, std::function<std::pair<T,int>(std::vector<T>)> reduce, const std::string& v_name)
-          :ReduceIndex(name, reduce, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name))) { }
+        ReduceIndex(Function<std::pair<T,int>(std::vector<T>)> reduce, const std::string& v_name)
+          :ReduceIndex(reduce, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name))) { }
 };
 
 /**
@@ -413,11 +487,10 @@ class ReduceIndex : public DerivedValue<std::pair<T, int> >{
 template <typename T>
 class MaxIndex : public ReduceIndex<T>{
     public:
-        MaxIndex(const std::string& name, const std::string& v_name)
-          :ReduceIndex<T>(name,
-                          [](std::vector<T> vec){ 
+        MaxIndex(const std::string& v_name)
+          :ReduceIndex<T>(Function<T(std::vector<T>)>("maxIndex", [](std::vector<T> vec){ 
                               auto elptr = std::max_element(vec.begin(), vec.end());
-                              return std::pair<T,int>(*elptr, int(elptr-vec.begin()));},
+                              return std::pair<T,int>(*elptr, int(elptr-vec.begin()));}),
                           v_name) { }
 };
 
@@ -427,11 +500,10 @@ class MaxIndex : public ReduceIndex<T>{
 template <typename T>
 class MinIndex : public ReduceIndex<T>{
     public:
-        MinIndex(const std::string& name, const std::string& v_name)
-          :ReduceIndex<T>(name,
-                          [](std::vector<T> vec){ 
+        MinIndex(const std::string& v_name)
+          :ReduceIndex<T>(Function<T(std::vector<T>)>("minIndex", [](std::vector<T> vec){ 
                               auto elptr = std::min_element(vec.begin(), vec.end());
-                              return std::pair<T,int>(*elptr, int(elptr-vec.begin()));},
+                              return std::pair<T,int>(*elptr, int(elptr-vec.begin()));}),
                           v_name) { }
 };
 
@@ -439,22 +511,22 @@ class MinIndex : public ReduceIndex<T>{
 /**
  * A variadic 
  */
-template <typename R, typename... T>
-class MultiFunc : public DerivedValue<R>{
-    private:
-        std::function<R(T...)> f;
-        std::tuple<T...> value_tuple;
-
-        void update_value(){
-            this->value = f(value_tuple);
-        }
-
-    public:
-        MultiFunc(const std::string& name, std::function<R(std::tuple<T...>)> f, T... varargs)
-          :DerivedValue<R>(name),
-           f(f),
-           value_tuple(varargs...){ }
-};
+/* template <typename R, typename... T> */
+/* class MultiFunc : public DerivedValue<R>{ */
+/*     private: */
+/*         Function<R(T...)> f; */
+/*         std::tuple<T...> value_tuple; */
+
+/*         void update_value(){ */
+/*             this->value = f(value_tuple); */
+/*         } */
+
+/*     public: */
+/*         MultiFunc(const std::string& name, Function<R(std::tuple<T...>)> f, T... varargs) */
+/*           :DerivedValue<R>(name), */
+/*            f(f), */
+/*            value_tuple(varargs...){ } */
+/* }; */
 
 /**
  * A generic value owning only a function object.
@@ -464,16 +536,31 @@ class MultiFunc : public DerivedValue<R>{
 template <typename T>
 class BoundValue : public DerivedValue<T>{
     protected:
-        std::function<T()> f;
+        Function<T()> f;
         void update_value(){
             this->value = f();
         }
     public:
-        BoundValue(const std::string& name, std::function<T()> f)
-          :DerivedValue<T>(name),
+        BoundValue(Function<T()> f)
+          :DerivedValue<T>(f.get_name()+"(<bound>)"),
            f(f) { }
 };
 
+/**
+ * A Value of a pointer. The pointer is constant, however the data the pointer
+ * points to is variable.
+ */
+template <typename T>
+class PointerValue : public DerivedValue<T*>{
+    protected:
+        void update_value(){ }
+    public:
+        PointerValue(const std::string& name, T* ptr)
+          :DerivedValue<T*>(name){ 
+            this->value = ptr;
+        }
+};
+
 /**
  * A Value which always returns the same value, supplied in the constructor.
  */
@@ -486,7 +573,7 @@ class ConstantValue : public DerivedValue<T>{
         }
     public:
         ConstantValue(const std::string& name, T const_value)
-            :DerivedValue<T>(name),
+            :DerivedValue<T>("const::"+name),
              const_value(const_value) { }
 };
 }

+ 62 - 41
filval_root/container.hpp

@@ -13,40 +13,45 @@ template <typename T>
 class ContainerTH1 : public Container<TH1>{
     private:
         void _fill(){
+            if (container == NULL){
+                init_TH1();
+            }
             container->Fill(value->get_value());
         }
     protected:
+        std::string title;
+        int nbins;
+        T low;
+        T high;
         Value<T> *value;
-        ContainerTH1(TH1* container, const std::string &name, Value<T> *value)
-          :Container<TH1>(container, name),
-           value(value){ }
+        virtual void init_TH1() = 0;
+    public:
+        explicit ContainerTH1(const std::string &name, const std::string& title, GenValue *value,
+                     int nbins, T low, T high)
+          :Container<TH1>(name, NULL),
+           title(title), nbins(nbins), low(low), high(high),
+           value(dynamic_cast<Value<T>*>(value)) { }
 };
 
 class ContainerTH1D : public ContainerTH1<double>{
-    public:
-        ContainerTH1D(const std::string& name, const std::string& title,
-                      int nbins, double low, double high, GenValue* value)
-          :ContainerTH1<double>(NULL, name, dynamic_cast<Value<double>*>(value)){
-               this->container = new TH1D(name.c_str(), title.c_str(), nbins, low, high);
-        }
+    using ContainerTH1::ContainerTH1;
+    void init_TH1(){
+        this->container = new TH1D(this->get_name().c_str(), title.c_str(), nbins, low, high);
+    }
 };
 
 class ContainerTH1F : public ContainerTH1<float>{
-    public:
-        ContainerTH1F(const std::string& name, const std::string& title,
-                      int nbins, float low, float high, GenValue* value)
-          :ContainerTH1<float>(NULL, name, dynamic_cast<Value<float>*>(value)){
-               this->container = new TH1D(name.c_str(), title.c_str(), nbins, low, high);
-        }
+    using ContainerTH1::ContainerTH1;
+    void init_TH1(){
+        this->container = new TH1F(this->get_name().c_str(), title.c_str(), nbins, low, high);
+    }
 };
 
 class ContainerTH1I : public ContainerTH1<int>{
-    public:
-        ContainerTH1I(const std::string& name, const std::string& title,
-                      int nbins, int low, int high, GenValue* value)
-          :ContainerTH1<int>(NULL, name, dynamic_cast<Value<int>*>(value)){
-               this->container = new TH1I(name.c_str(), title.c_str(), nbins, low, high);
-        }
+    using ContainerTH1::ContainerTH1;
+    void init_TH1(){
+        this->container = new TH1I(this->get_name().c_str(), title.c_str(), nbins, low, high);
+    }
 };
 
 
@@ -54,38 +59,55 @@ template <typename T>
 class ContainerTH2 : public Container<TH2>{
     private:
         void _fill(){
+            if (container == NULL){
+                init_TH2();
+            }
             std::pair<T, T> val = value->get_value();
             container->Fill(val.first, val.second);
         }
     protected:
+        std::string title;
+        int nbins_x;
+        int nbins_y;
+        T low_x;
+        T low_y;
+        T high_x;
+        T high_y;
         Value<std::pair<T, T> > *value;
-        ContainerTH2(TH2* container, const std::string &name, Value<std::pair<T, T> > *value)
-          :Container<TH2>(container, name),
-           value(value){ }
-};
-
-class ContainerTH2D : public ContainerTH2<double>{
+        virtual void init_TH2() = 0;
     public:
-        ContainerTH2D(const std::string& name, const std::string& title,
+        explicit ContainerTH2(const std::string& name, const std::string& title,
                       int nbins_x, double low_x, double high_x,
                       int nbins_y, double low_y, double high_y,
                       GenValue* value)
-          :ContainerTH2<double>(NULL, name, dynamic_cast<Value<std::pair<double, double> >*>(value)){
-               this->container = new TH2D(name.c_str(), title.c_str(), nbins_x, low_x, high_x, nbins_y, low_y, high_y);
-        }
+          :Container<TH2>(name, NULL),
+           nbins_x(nbins_x), low_x(low_x), high_x(high_x),
+           nbins_y(nbins_y), low_y(low_y), high_y(high_y),
+           value(dynamic_cast<Value<T>*>(value)) { }
+};
+
+class ContainerTH2D : public ContainerTH2<double>{
+    using ContainerTH2::ContainerTH2;
+    void init_TH2(){
+        this->container = new TH2D(this->get_name().c_str(), title.c_str(), nbins_x, low_x, high_x, nbins_y, low_y, high_y);
+    }
+};
+
+class ContainerTH2F : public ContainerTH2<float>{
+    using ContainerTH2::ContainerTH2;
+    void init_TH2(){
+        this->container = new TH2F(this->get_name().c_str(), title.c_str(), nbins_x, low_x, high_x, nbins_y, low_y, high_y);
+    }
 };
 
 class ContainerTH2I : public ContainerTH2<int>{
-    public:
-        ContainerTH2I(const std::string& name, const std::string& title,
-                      int nbins_x, int low_x, int high_x,
-                      int nbins_y, int low_y, int high_y,
-                      GenValue* value)
-          :ContainerTH2<int>(NULL, name, dynamic_cast<Value<std::pair<int, int> >*>(value)){
-               this->container = new TH2I(name.c_str(), title.c_str(), nbins_x, low_x, high_x, nbins_y, low_y, high_y);
-        }
+    using ContainerTH2::ContainerTH2;
+    void init_TH2(){
+        this->container = new TH2I(this->get_name().c_str(), title.c_str(), nbins_x, low_x, high_x, nbins_y, low_y, high_y);
+    }
 };
 
+
 class ContainerTGraph : public Container<TGraph>{
     private:
         Value<std::pair<int, int> > *value;
@@ -96,12 +118,11 @@ class ContainerTGraph : public Container<TGraph>{
             auto val = value->get_value();
             x_data.push_back(val.first);
             y_data.push_back(val.second);
-            /* std::cout << x_data.size() << std::endl; */
             data_modified = true;
         }
     public:
         ContainerTGraph(const std::string &name, GenValue* value)
-          :Container<TGraph>(new TGraph(), name),
+          :Container<TGraph>(name, new TGraph()),
            value(dynamic_cast<Value<std::pair<int, int> >*>(value)),
            data_modified(false){ }