Преглед изворни кода

Implements some sane Value objects for dealing with observed arrays in incoming data

Caleb Fangmeier пре 7 година
родитељ
комит
8d2cdb6164
11 измењених фајлова са 391 додато и 153 уклоњено
  1. 9 0
      Makefile
  2. 16 0
      MiniTree.hpp
  3. 85 11
      MiniTreeDataSet.hpp
  4. 24 4
      TTTT_Analysis.cpp
  5. 2 2
      filval/container.hpp
  6. 12 4
      filval/dataset.hpp
  7. 20 73
      filval/filter.hpp
  8. 154 44
      filval/value.hpp
  9. 9 0
      filval_root/container.hpp
  10. 27 0
      filval_root/filter.hpp
  11. 33 15
      filval_root/value.hpp

+ 9 - 0
Makefile

@@ -0,0 +1,9 @@
+CC=clang++
+CFLAGS=`root-config --libs --cflags` -Wall
+CFLAGS_DEBUG=$(CFLAGS) -g3 -O0
+INCLUDEDIR=-I.
+
+TTTT_Analysis: TTTT_Analysis.cpp
+		clear
+		$(CC) -o main TTTT_Analysis.cpp $(CFLAGS_DEBUG) $(INCLUDEDIR)
+		# $(CC) -o main TTTT_Analysis.cpp $(CFLAGS) $(INCLUDEDIR)

+ 16 - 0
MiniTree.hpp

@@ -8,6 +8,7 @@
 #ifndef minitree_h
 #define minitree_h
 
+#include <iostream>
 #include <TROOT.h>
 #include <TChain.h>
 #include <TFile.h>
@@ -2184,6 +2185,20 @@ public :
    virtual void     Loop();
    virtual Bool_t   Notify();
    virtual void     Show(Long64_t entry = -1);
+
+   void foo(){
+       std::cout << "IN FOO" << std::endl;
+       float* ptr = (float*) LepGood_pt;
+       std::cout << LepGood_pt << std::endl;
+       std::cout << *LepGood_pt << std::endl;
+       std::cout << "OUT FOO" << std::endl;
+   }
+
+/* void MiniTree::InitField */
+   /* unsigned int get_nJet(){ */
+   /*     return *((unsigned int*) fChain->GetBranch("nJet")->GetAddress()); */
+   /* } */
+
 };
 
 
@@ -2227,6 +2242,7 @@ Long64_t MiniTree::LoadTree(Long64_t entry)
    return centry;
 }
 
+
 void MiniTree::Init(TTree *tree)
 {
    // The Init() function is called when the selector needs to initialize

+ 85 - 11
MiniTreeDataSet.hpp

@@ -2,22 +2,19 @@
 #define minitreedataset_h
 
 #include <string>
+#include <tuple>
 
 #include "filval/filval.hpp"
 #include "filval_root/filval_root.hpp"
 #include "MiniTree.hpp"
 
+using namespace std;
 using namespace filval;
 using namespace filval::root;
 
-class MiniTreeDataSet : public filval::DataSet,
+class MiniTreeDataSet : public DataSet,
                         public MiniTree{
     private:
-        template <typename T>
-        void track_branch(const std::string bname, T *bval){
-            values[bname] = new filval::ObservedValue<T>(bval);
-            fChain->SetBranchStatus(bname.c_str(), true);
-        }
         long next_entry;
         long nentries;
         bool load_next(){
@@ -31,26 +28,103 @@ class MiniTreeDataSet : public filval::DataSet,
           :MiniTree(tree){
             fChain->SetBranchStatus("*", false);
 
-            track_branch<int>("nLepGood", &nLepGood);
-            track_branch<int>("nJet", &nJet);
+            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");
+            auto pt_wrapper  = new WrapperVector<float>(&values, "nLepGood", "LepGood_pt");
+            auto eta_wrapper = new WrapperVector<float>(&values, "nLepGood", "LepGood_eta");
+            auto phi_wrapper = new WrapperVector<float>(&values, "nLepGood", "LepGood_phi");
+            auto m_wrapper   = new WrapperVector<float>(&values, "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();
+            };
+            auto lepton_energy = new ZipMapFour<float, float>(get_energy, pt_wrapper, eta_wrapper, phi_wrapper, m_wrapper);
+
+            auto avg_lepton_energy = new Reduce<float>([](vector<float> v){
+                    int n = 0;
+                    float sum = 0;
+                    for (float e : v){
+                        n++;
+                        sum += e;
+                    }
+                    return n>0 ? sum / n : 0;
+                    }, lepton_energy);
+            add_value(avg_lepton_energy, "avg_lepton_energy");
+
+
+
+            Filter* nLepGoodLowFilter = new Filter([nLepGood=values["nLepGood"]](){
+                    return dynamic_cast<Value<int>*>(nLepGood)->get_value() >=3;});
+
+            Filter* nLepGoodHighFilter = new Filter([nLepGood=values["nLepGood"]](){
+                    return dynamic_cast<Value<int>*>(nLepGood)->get_value() <=4;});
+            add_value(nLepGoodLowFilter, "nLepGoodLow");
+            add_value(nLepGoodHighFilter, "nLepGoodHigh");
+            auto nLepGoodRangeFilter = new RangeFilter<int>(dynamic_cast<Value<int>*>(values["nLepGood"]), 3, 5);
+            add_value(nLepGoodRangeFilter, "nLepGoodRange");
+            add_value(!(*nLepGoodRangeFilter), "nLepGoodRangeInv");
 
-            add_value(new FilterGreaterThan<int>(values["nLepGood"], 3), "nLepGoodCut");
 
             add_container(new ContainerTH1I("nLepGood", "Lepton Multiplicity", 10, 0, 10, values["nLepGood"]));
             add_container(new ContainerTH1I("nLepGood2", "Lepton Multiplicity", 10, 0, 10, values["nLepGood"]));
-            containers["nLepGood2"]->add_filter(values["nLepGoodCut"]);
+            containers.at("nLepGood2")->add_filter(values.at("nLepGoodRange"));
+            add_container(new ContainerTH1I("nLepGood3", "Lepton Multiplicity", 10, 0, 10, values["nLepGood"]));
+            containers.at("nLepGood3")->add_filter(values.at("nLepGoodRangeInv"));
 
-            add_value(new DerivedPair<int, int>(&values, "nLepGood", "nJet"), "nLepvsnJet");
+            add_value(new Pair<int, int>(&values, "nLepGood", "nJet"), "nLepvsnJet");
             add_container(new ContainerTGraph("nLepvsnJet", values["nLepvsnJet"]));
 
+            add_container(new ContainerTH1F("avg_lepton_energy", "Average Lepton Energy", 50, 0, 500, values["avg_lepton_energy"]));
 
             next_entry = 0;
             nentries = fChain->GetEntriesFast();
           }
 
+        template <typename T>
+        void track_branch(const std::string bname){
+            T* bref = (T*) fChain->GetBranch(bname.c_str())->GetAddress();
+            values[bname] = new ObservedValue<T>(bref);
+            fChain->SetBranchStatus(bname.c_str(), true);
+            cout << "Registering branch \"" << bname
+                << "\" with address " << bref
+                << " and type " << typeid(bref).name() << endl;
+        }
+
+        template <typename T>
+        void track_branch_ptr(const std::string bname){
+            T* bref = (T*) fChain->GetBranch(bname.c_str())->GetAddress();
+            values[bname] = new ConstantValue<T*>(bref);
+            fChain->SetBranchStatus(bname.c_str(), true);
+            cout << "Registering pointer branch \"" << bname
+                << "\" with address " << bref
+                << " and type " << typeid(bref).name() << endl;
+        }
+
         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

+ 24 - 4
TTTT_Analysis.cpp

@@ -16,7 +16,7 @@ using namespace filval;
 using namespace filval::root;
 
 
-void print_pair(DerivedPair<double, double> dp){
+void print_pair(Pair<double, double> dp){
     pair<double, double> p = dp.get_value();
     cout << "(" << p.first << ", " << p.second << ")\n";
 }
@@ -28,7 +28,7 @@ void test1(){
     ObservedValue<double> x_val(&x);
     ObservedValue<double> y_val(&y);
 
-    DerivedPair<double, double> dp(&x_val, &y_val);
+    Pair<double, double> dp(&x_val, &y_val);
     print_pair(dp);
     x = 2;
     y = 2;
@@ -73,16 +73,36 @@ void test3(){
     TTree *tree = (TTree*) f->Get("tree");
     MiniTreeDataSet mtds(tree);
     mtds.process();
-    TH1* hist = ((ContainerTH1I*)mtds.get_container("nLepGood"))->get_container();
     TCanvas can("c1");
+    can.Clear();
+    TH1* hist = ((ContainerTH1I*)mtds.get_container("nLepGood"))->get_container();
     hist->Draw();
     can.Draw();
     can.SaveAs("outfile.png");
+
+    can.Clear();
+    hist = ((ContainerTH1I*)mtds.get_container("nLepGood2"))->get_container();
+    hist->Draw();
+    can.Draw();
+    can.SaveAs("outfile2.png");
+
+    can.Clear();
+    hist = ((ContainerTH1I*)mtds.get_container("nLepGood3"))->get_container();
+    hist->Draw();
+    can.Draw();
+    can.SaveAs("outfile3.png");
+
+    can.Clear();
+    hist = ((ContainerTH1I*)mtds.get_container("avg_lepton_energy"))->get_container();
+    hist->Draw();
+    can.Draw();
+    can.SaveAs("lepton_energy.png");
+
     can.Clear();
     TGraph* graph= ((ContainerTGraph*)mtds.get_container("nLepvsnJet"))->get_container();
     graph->Draw("A*");
     can.Draw();
-    can.SaveAs("outfile3.png");
+    can.SaveAs("outfileGraph.png");
 
     delete tree;
     f->Close();

+ 2 - 2
filval/container.hpp

@@ -9,14 +9,14 @@ class GenContainer{
     private:
         std::string name;
         std::string desc;
-        std::vector<Filter*> filters;
+        std::vector<GenFilter*> filters;
     protected:
         virtual void _fill() = 0;
     public:
         GenContainer(const std::string name)
           :name(name){ }
         void add_filter(GenValue* filter){
-            filters.push_back(dynamic_cast<Filter*>(filter));
+            filters.push_back(dynamic_cast<GenFilter*>(filter));
         }
         void fill(){
             for (auto filter : filters){

+ 12 - 4
filval/dataset.hpp

@@ -12,24 +12,32 @@ class DataSet{
     public:
         void process(){
             while( load_next() ){
-                for(auto val : values)
-                    val.second->reset();
+                GenValue::reset();
                 for(auto con : containers)
                     con.second->fill();
             }
         }
+
+        /* template <typename T> */
+        /* virtual T* get_field(const std::string& field_name) = 0; */
+
         void add_value(GenValue *value, const std::string& value_name ){
+            /* Adds a value to the dataset's list of known value objects. Note
+             * that all new values are automatically kept track of by
+             * GenValue::values so this is only needed if one wants to recall
+             * the value by name.
+             */
             values[value_name] = value;
         }
         GenValue* get_value(std::string value_name){
-            return values[value_name];
+            return values.at(value_name);
         }
 
         void add_container(GenContainer *container){
             containers[container->get_name()] = container;
         }
         GenContainer* get_container(std::string container_name){
-            return containers[container_name];
+            return containers.at(container_name);
         }
 };
 }

+ 20 - 73
filval/filter.hpp

@@ -1,6 +1,7 @@
 #ifndef filter_h
 #define filter_h
 #include <iostream>
+#include <functional>
 #include "value.hpp"
 /* A Filter is a special type of derived value that can only return a boolean.
  * Container objects have a vector of filters that control if a "fill" call
@@ -8,94 +9,40 @@
  */
 namespace filval {
 
-class Filter : public DerivedValue<bool>{ };
+class GenFilter : public DerivedValue<bool>{};
 
-
-class FilterAnd : public Filter {
-    protected:
-        Filter *filterA;
-        Filter *filterB;
-    void update_value(){
-        value = filterA->get_value() && filterB->get_value();
-    }
-    public:
-        FilterAnd(Filter *filterA, Filter *filterB)
-            :filterA(filterA), filterB(filterB){ }
-};
-
-class FilterOr : public Filter {
+class Filter : public GenFilter{
     private:
-        Filter *filterA;
-        Filter *filterB;
-    void update_value(){
-        value = filterA->get_value() || filterB->get_value();
-    }
-    public:
-        FilterOr(Filter *filterA, Filter *filterB)
-            :filterA(filterA), filterB(filterB){ }
-};
-
-class FilterInv : public Filter {
-    private:
-        Filter *filter;
-    void update_value(){
-        value = !filter->get_value();
-    }
-    public:
-        FilterInv(Filter *filter)
-            :filter(filter){ }
-};
-
-template <typename T>
-class FilterGreaterThan : public Filter {
-    private:
-        Value<T> *filter_value;
-        Value<T> *range_low;
+        std::function<bool()> filter_function;
         void update_value(){
-            value = filter_value->get_value() > range_low->get_value();
+            value = filter_function();
         }
     public:
-        FilterGreaterThan(GenValue* filter_value, GenValue* range_low)
-            :filter_value(dynamic_cast<Value<T>*>(filter_value)),
-             range_low(dynamic_cast<Value<T>*>(range_low)) { }
+        Filter(std::function<bool()> filter_function)
+          :filter_function(filter_function){ }
 
-        FilterGreaterThan(GenValue* filter_value, T range_low)
-            :filter_value(dynamic_cast<Value<T>*>(filter_value)){
-            this->range_low = new ConstantValue<T>(range_low);
+        Filter* operator*(Filter *f){
+            return new Filter([this, f](){return this->get_value() && f->get_value();});
         }
-};
 
-template <typename T>
-class FilterLessThan : public Filter {
-    private:
-        Value<T> *filter_value;
-        Value<T> *range_high;
-        void update_value(){
-            value = filter_value->get_value() < range_high->get_value();
+        Filter* operator+(Filter *f){
+            return new Filter([this, f](){return this->get_value() || f->get_value();});
         }
-    public:
-        FilterLessThan(GenValue* filter_value, GenValue* range_high)
-            :filter_value(dynamic_cast<Value<T>*>(filter_value)),
-             range_high(dynamic_cast<Value<T>*>(range_high)) { }
 
-        FilterLessThan(GenValue* filter_value, T range_high)
-            :filter_value(dynamic_cast<Value<T>*>(filter_value)){
-            this->range_high = new ConstantValue<T>(range_high);
+        Filter* operator!(){
+            return new Filter([this](){return !this->get_value();});
         }
 };
 
-
 template <typename T>
-class RangeFilter : public FilterAnd {
+class RangeFilter : public Filter{
+    private:
     public:
-        RangeFilter(Value<T> *filter_value, Value<T> *range_low, Value<T> *range_high){
-            this->filterA = new FilterLessThan<T>(filter_value, range_high);
-            this->filterB = new FilterGreaterThan<T>(filter_value, range_low);
-         }
-        RangeFilter(Value<T> *filter_value, T range_low, T range_high){
-            this->filterA = new FilterLessThan<T>(filter_value, range_high);
-            this->filterB = new FilterGreaterThan<T>(filter_value, range_low);
-        }
+        RangeFilter(Value<T>* test_value, T range_low, T range_high):
+          Filter([test_value, range_low, range_high]{
+                  T val = test_value->get_value();
+                  return (val >= range_low) && (val < range_high);
+                  }){ }
 };
 }
 #endif // filter_h

+ 154 - 44
filval/value.hpp

@@ -2,85 +2,114 @@
 #define value_hpp
 #include <iostream>
 #include <utility>
+#include <algorithm>
 #include <map>
+#include <vector>
+#include <tuple>
+#include <initializer_list>
+#include <functional>
 
 namespace filval{
 
 class GenValue{
+    private:
+        inline static std::vector<GenValue*> values;
+        virtual void _reset() = 0;
     public:
-        virtual void reset() = 0;
+        GenValue(){
+            values.push_back(this);
+        }
+        static void reset(){
+            for (auto val : values){
+                val->_reset();
+            }
+        }
 };
 typedef std::map<std::string, GenValue*> ValueSet;
 
-/* class ValueSet: public std::map<std::string, GenValue*>{ */
-/*     public: */
-/*         GenValue*& operator[](const std::string& key){ */
-/*             GenValue*& value = (*this)[key]; */
-/*             if (value == NULL){ */
-/*                 std::cerr << "ERROR: key \""<<key */
-/*                     <<"\" not in valueset" << std::endl; */
-/*             } */
-/*             return value; */
-/*         } */
-/* }; */
-
 
-template <typename V>
+template <typename T>
 class Value : public GenValue{
     public:
-        virtual V& get_value() = 0;
+        Value(): GenValue(){}
+        virtual T& get_value() = 0;
 };
 
 
-template <typename V>
-class ObservedValue : public Value<V>{
+template <typename T>
+class ObservedValue : public Value<T>{
     /* For "observed" values, there is nothing to calculate since this is
      * merely a wrapper around a field in the observation. A pointer to the
      * value is kept and it's value is read when requested.
      */
     private:
-        V *val_ref;
+        T *val_ref;
+        void _reset(){ }
     public:
-        ObservedValue(V *val_ref)
-            : val_ref(val_ref){}
-        V& get_value(){
+        ObservedValue(T* val_ref)
+          :Value<T>(),
+           val_ref(val_ref){ }
+        T& get_value(){
             return *val_ref;
         }
-        void reset(){ }
 };
 
 
-template <typename V>
-class DerivedValue : public Value<V>{
+template <typename T>
+class DerivedValue : public Value<T>{
     /* A "derived" value is the result of some sort of calculation. Since it is
      * desireable for the calculation to occur at most a single time for each
      * observation, the result of the calculation is stored in the object. be
      * sure that "reset" is called between processing observations to force a
      * re-calculation.
      */
+    private:
+        void _reset(){
+            value_valid = false;
+        }
     protected:
-        V value; // The value to be calculated
+        T value;
         bool value_valid;
 
         virtual void update_value() = 0;
     public:
-        V& get_value(){
+        DerivedValue() :Value<T>(), value_valid(false) { }
+
+        T& get_value(){
             if (!value_valid){
-                /* std::cout << "updating value!\n"; */
                 update_value();
                 value_valid = true;
             }
             return value;
         }
+};
 
-        void reset(){
-            value_valid = false;
+template <typename T>
+class WrapperVector : public DerivedValue<std::vector<T> >{
+    private:
+        Value<int>* size;
+        Value<T*>* data;
+
+        void update_value(){
+            int n = size->get_value();
+            T* data_ref = data->get_value();
+            this->value.resize(n);
+            for (int i=0; i<n; i++){
+                this->value[i] = *(data_ref+i);
+            }
         }
-};
 
+    public:
+        WrapperVector(Value<int>* _size, Value<T*>* _data)
+          :DerivedValue<std::vector<T> >(),
+           size(_size), data(_data){ }
+        WrapperVector(ValueSet *values, const std::string &label_size, const std::string &label_data)
+          :WrapperVector(dynamic_cast<Value<int>*>(values->at(label_size)),
+                         dynamic_cast<Value<T*>*>(values->at(label_data))) { }
+};
 
 template <typename T1, typename T2>
-class DerivedPair : public DerivedValue<std::pair<T1, T2> >{
+class Pair : public DerivedValue<std::pair<T1, T2> >{
     protected:
         std::pair<Value<T1>*, Value<T2>* > value_pair;
         void update_value(){
@@ -88,27 +117,108 @@ class DerivedPair : public DerivedValue<std::pair<T1, T2> >{
             this->value.second = value_pair.second->get_value();
         }
     public:
-        DerivedPair(ValueSet *values, const std::string &label1, const std::string &label2){
-            ValueSet &valueSet = *values;
-            value_pair.first  = (Value<T1>*) valueSet[label1];
-            value_pair.second = (Value<T2>*) valueSet[label2];
-         }
-        DerivedPair(Value<T1> *value1, Value<T2> *value2){
-            value_pair.first  = value1;
-            value_pair.second = value2;
-         }
+        Pair(Value<T1> *value1, Value<T2> *value2)
+          :DerivedValue<std::pair<T1, T2> >(),
+           value_pair(value1, value2){ }
+        Pair(ValueSet *values, const std::string &label1, const std::string &label2)
+          :Pair((Value<T1>*) values->at(label1),
+                (Value<T1>*) values->at(label2)){ }
+};
+
+template <typename R, typename T>
+class ZipMapFour : public DerivedValue<std::vector<R> >{
+    private:
+        std::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;
 
+        void update_value(){
+            std::vector<T> v1_val = v1->get_value();
+            std::vector<T> v2_val = v2->get_value();
+            std::vector<T> v3_val = v3->get_value();
+            std::vector<T> v4_val = v4->get_value();
+
+            int n;
+            std::tie(n, std::ignore) = std::minmax({v1_val.size(), v2_val.size(), v3_val.size(), v4_val.size()});
+            this->value.resize(n);
+            for (int i=0; i<n; i++){
+                this->value[i] = f(v1_val[i], v2_val[i], v3_val[i], v4_val[i]);
+            }
+        }
+
+    public:
+        ZipMapFour(std::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> >(),
+           f(f), v1(v1), v2(v2), v3(v3), v4(v4) { }
+        ZipMapFour(std::function<R(T, T, T, T)> f,
+                   ValueSet *values,
+                   const std::string &label1,
+                   const std::string &label2,
+                   const std::string &label3,
+                   const std::string &label4)
+          :ZipMapFour(f,
+                      dynamic_cast<Value<std::vector<T> >*>(values->at(label1)),
+                      dynamic_cast<Value<std::vector<T> >*>(values->at(label2)),
+                      dynamic_cast<Value<std::vector<T> >*>(values->at(label3)),
+                      dynamic_cast<Value<std::vector<T> >*>(values->at(label4))){ }
+};
+
+template <typename T>
+class Reduce : public DerivedValue<T>{
+    private:
+        std::function<T(std::vector<T>)> reduce;
+        Value<std::vector<T> >* v;
+        void update_value(){
+            this->value = reduce(v->get_value());
+        }
+    public:
+        Reduce(std::function<T(std::vector<T>)> reduce, Value<std::vector<T> >* v)
+          :DerivedValue<T>(),
+           reduce(reduce), v(v) { }
+};
+
+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(std::function<R(std::tuple<T...>)> f, T... varargs)
+          :f(f),
+           value_tuple(varargs...){ }
+};
+
+template <typename T>
+class BoundValue : public DerivedValue<T>{
+    /* A "bound" value has it's dependencies bound into a function object. */
+    protected:
+        std::function<T()> f;
+        void update_value(){
+            this->value = f();
+        }
+    public:
+        BoundValue(std::function<T()> f)
+          :f(f) { }
 };
 
-template <typename V>
-class ConstantValue : public DerivedValue<V>{
+template <typename T>
+class ConstantValue : public DerivedValue<T>{
     protected:
-        V const_value;
+        T const_value;
         void update_value(){
             this->value = const_value;
         }
     public:
-        ConstantValue(V const_value)
+        ConstantValue(T const_value)
             :const_value(const_value) { }
 };
 }

+ 9 - 0
filval_root/container.hpp

@@ -31,6 +31,15 @@ class ContainerTH1D : public ContainerTH1<double>{
         }
 };
 
+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);
+        }
+};
+
 class ContainerTH1I : public ContainerTH1<int>{
     public:
         ContainerTH1I(const std::string& name, const std::string& title,

+ 27 - 0
filval_root/filter.hpp

@@ -0,0 +1,27 @@
+#ifndef root_filter_hpp
+#define root_filter_hpp
+#include "value.hpp"
+#include "TLorentzVector.h"
+
+namespace filval::root{
+
+class MassFilter : public Filter {
+    private:
+        Value<TLorentzVector> *lorentz_vector;
+        Value<double> *mass_cut_low;
+        Value<double> *mass_cut_high;
+    void update_value(){
+        double m = lorentz_vector->get_value().M();
+        value = (m > mass_cut_low) && (m < mass_cut_high);
+    }
+    public:
+        FilterAnd(Value<TLorentzVector> *lorentz_vector,
+                  Value<double> *mass_cut_low,
+                  Value<double> *mass_cut_high)
+          :lorentz_vector(lorentz_vector),
+           mass_cut_low(mass_cut_low),
+           mass_cut_high(mass_cut_high){ }
+};
+
+}
+#endif // root_filter_hpp

+ 33 - 15
filval_root/value.hpp

@@ -1,11 +1,11 @@
-#ifndef root_values_hpp
-#define root_values_hpp
+#ifndef root_value_hpp
+#define root_value_hpp
 #include "value.hpp"
 #include "TLorentzVector.h"
 
 namespace filval::root{
 
-class DerivedLorentzVector : public DerivedValue<TLorentzVector>{
+class LorentzVector : public DerivedValue<TLorentzVector>{
     protected:
         Value<double> *pt;
         Value<double> *eta;
@@ -15,18 +15,36 @@ class DerivedLorentzVector : public DerivedValue<TLorentzVector>{
             value.SetPtEtaPhiM(pt->get_value(), eta->get_value(), phi->get_value(), m->get_value());
         }
     public:
-        DerivedLorentzVector(ValueSet *values,
-                             const std::string &pt_label,
-                             const std::string &eta_label,
-                             const std::string &phi_label,
-                             const std::string &m_label){
-            ValueSet &valueSet = *values;
-            pt = (Value<double>*) valueSet[pt_label];
-            eta = (Value<double>*) valueSet[eta_label];
-            phi = (Value<double>*) valueSet[phi_label];
-            m = (Value<double>*) valueSet[m_label];
-         }
+        LorentzVector(Value<double>* pt,
+                      Value<double>* eta,
+                      Value<double>* phi,
+                      Value<double>* m)
+          :pt(pt), eta(eta),
+           phi(phi), m(m) { }
 
+        LorentzVector(ValueSet *values,
+                      const std::string &pt_label,
+                      const std::string &eta_label,
+                      const std::string &phi_label,
+                      const std::string &m_label)
+          :LorentzVector(dynamic_cast<Value<double>*>(values->at(pt_label)),
+                         dynamic_cast<Value<double>*>(values->at(eta_label)),
+                         dynamic_cast<Value<double>*>(values->at(phi_label)),
+                         dynamic_cast<Value<double>*>(values->at(m_label))){ }
+};
+
+class LorentzVectorEnergy : public DerivedValue<double>{
+    protected:
+        Value<TLorentzVector>* vector;
+        void update_value(){
+            value = vector->get_value().E();
+        }
+    public:
+        LorentzVectorEnergy(Value<TLorentzVector>* vector)
+          :vector(vector){ }
+
+        LorentzVectorEnergy(ValueSet *values, const std::string& vector_label)
+          :LorentzVectorEnergy(dynamic_cast<Value<TLorentzVector>*>(values->at(vector_label))){ }
 };
 }
-#endif // root_values_hpp
+#endif // root_value_hpp