Преглед на файлове

Adjusts usage of Function object to work with pointers rather than
references

Caleb Fangmeier преди 7 години
родител
ревизия
1a85d61848
променени са 9 файла, в които са добавени 193 реда и са изтрити 90 реда
  1. 30 14
      api.hpp
  2. 8 2
      datafile.hpp
  3. 5 2
      dataset.hpp
  4. 2 2
      filter.hpp
  5. 2 1
      log.hpp
  6. 44 15
      python/plotter.py
  7. 1 1
      python/process_parallel.py
  8. 30 8
      root/dataset.hpp
  9. 71 45
      value.hpp

+ 30 - 14
api.hpp

@@ -57,6 +57,11 @@ namespace fv{
         return tv;
     }
 
+    template<typename T>
+    Function<T>* lookup_function(const std::string& name){
+        return GenFunction::lookup_function<T>(name);
+    }
+
     template<typename T>
     bool check_exists(const std::string name){
         Value<T>* tv = GenValue::get_value<T>(name);
@@ -95,7 +100,7 @@ namespace fv{
 
     template <typename Ret, typename ArgType>
     decltype(auto)
-    map(Function<Ret(ArgType)>& fn, Value<std::vector<ArgType>>* arg, const std::string& alias=""){
+    map(Function<Ret(ArgType)>* fn, Value<std::vector<ArgType>>* arg, const std::string& alias=""){
         typedef std::vector<Ret> type;
         const std::string& name = Map<Ret(ArgType)>::fmt_name(fn, arg);
         if (check_exists<type>(name))
@@ -106,7 +111,7 @@ namespace fv{
 
     template <typename Ret, typename... ArgTypes>
     decltype(auto)
-    tup_map(Function<Ret(ArgTypes...)>& fn, Value<std::vector<std::tuple<ArgTypes...>>>* arg, const std::string& alias=""){
+    tup_map(Function<Ret(ArgTypes...)>* fn, Value<std::vector<std::tuple<ArgTypes...>>>* arg, const std::string& alias=""){
         typedef std::vector<Ret> type;
         const std::string& name = TupMap<Ret(ArgTypes...)>::fmt_name(fn, arg);
         if (check_exists<type>(name))
@@ -148,15 +153,26 @@ namespace fv{
             return (Value<type>*)new DeTupVector<N, ArgTypes...>(tup, alias);
     }
 
+    template <typename Ret, typename ArgType>
+    decltype(auto)
+    apply(Function<Ret(ArgType)>* fn, Value<ArgType>* arg, const std::string& alias=""){
+        typedef Ret type;
+        const std::string& name = Apply<Ret(ArgType)>::fmt_name(fn, arg);
+        if (check_exists<type>(name))
+            return lookup<type>(name);
+        else
+            return (Value<type>*)new Apply<Ret(ArgType)>(fn, arg, alias);
+    }
+
     template <typename Ret, typename... ArgTypes>
     decltype(auto)
-    apply(Function<Ret(ArgTypes...)>& fn, Value<std::tuple<ArgTypes...>>* arg, const std::string& alias=""){
+    tup_apply(Function<Ret(ArgTypes...)>* fn, Value<std::tuple<ArgTypes...>>* arg, const std::string& alias=""){
         typedef Ret type;
-        const std::string& name = Apply<Ret(ArgTypes...)>::fmt_name(fn, arg);
+        const std::string& name = TupApply<Ret(ArgTypes...)>::fmt_name(fn, arg);
         if (check_exists<type>(name))
             return lookup<type>(name);
         else
-            return (Value<type>*)new Apply<Ret(ArgTypes...)>(fn, arg, alias);
+            return (Value<type>*)new TupApply<Ret(ArgTypes...)>(fn, arg, alias);
     }
 
     template <typename T1, typename T2>
@@ -178,7 +194,7 @@ namespace fv{
 
     template <typename T>
     decltype(auto)
-    reduce(Function<T(std::vector<T>)>& fn, Value<std::vector<T>>* v, const std::string& alias=""){
+    reduce(Function<T(std::vector<T>)>* fn, Value<std::vector<T>>* v, const std::string& alias=""){
         typedef T type;
         const std::string& name = Reduce<T>::fmt_name(fn, v);
         if (check_exists<type>(name))
@@ -257,7 +273,7 @@ namespace fv{
 
     template <typename T>
     decltype(auto)
-    count(Function<bool(T)>& selector, Value<std::vector<T>>* v, const std::string& alias=""){
+    count(Function<bool(T)>* selector, Value<std::vector<T>>* v, const std::string& alias=""){
         typedef int type;
         const std::string& name = Count<T>::fmt_name(selector, v);
         if (check_exists<type>(name))
@@ -268,7 +284,7 @@ namespace fv{
 
     template <typename T>
     decltype(auto)
-    count(Function<bool(T)>& selector, const std::string& v_name, const std::string& alias=""){
+    count(Function<bool(T)>* selector, const std::string& v_name, const std::string& alias=""){
         return count<T>(selector, lookup<std::vector<T>>(v_name), alias);
     }
 
@@ -319,7 +335,7 @@ namespace fv{
 
     template <typename T>
     decltype(auto)
-    bound(Function<T()>& f, const std::string alias=""){
+    bound(Function<T()>* f, const std::string alias=""){
         typedef T type;
         const std::string& name = BoundValue<T>::fmt_name(f);
         if (check_exists<type>(name))
@@ -330,7 +346,7 @@ namespace fv{
 
     template <typename T>
     decltype(auto)
-    filter(Function<bool(T)>& filter, Value<std::vector<T>>* val, const std::string alias=""){
+    filter(Function<bool(T)>* filter, Value<std::vector<T>>* val, const std::string alias=""){
         typedef std::vector<T> type;
         const std::string& name = Filter<T>::fmt_name(filter, val);
         if (check_exists<type>(name))
@@ -341,13 +357,13 @@ namespace fv{
 
     template <typename T>
     decltype(auto)
-    filter(Function<bool(T)>& filter_func, const std::string& val_name, const std::string alias=""){
+    filter(Function<bool(T)>* filter_func, const std::string& val_name, const std::string alias=""){
         return filter<T>(filter_func, lookup<std::vector<T>>(val_name), alias);
     }
 
     template <typename... ArgTypes>
     decltype(auto)
-    tup_filter(Function<bool(ArgTypes...)>& filter, Value<std::vector<std::tuple<ArgTypes...>>>* val, const std::string alias=""){
+    tup_filter(Function<bool(ArgTypes...)>* filter, Value<std::vector<std::tuple<ArgTypes...>>>* val, const std::string alias=""){
         typedef std::vector<std::tuple<ArgTypes...>> type;
         const std::string& name = TupFilter<ArgTypes...>::fmt_name(filter, val);
         if (check_exists<type>(name))
@@ -358,7 +374,7 @@ namespace fv{
 
     template <typename... ArgTypes>
     decltype(auto)
-    tup_filter(Function<bool(ArgTypes...)>& filter, const std::string& val_name, const std::string alias=""){
+    tup_filter(Function<bool(ArgTypes...)>* filter, const std::string& val_name, const std::string alias=""){
         return tup_filter<ArgTypes...>(filter, lookup<std::vector<std::tuple<ArgTypes...>>>(val_name), alias);
     }
 
@@ -367,7 +383,7 @@ namespace fv{
     }
 
     template <typename T>
-    static Function<T>& func(const std::string& name, std::function<T> f, const std::string& impl){
+    static Function<T>* func(const std::string& name, std::function<T> f, const std::string& impl){
         return GenFunction::reg_func(name, f, impl);
     }
 

+ 8 - 2
datafile.hpp

@@ -88,12 +88,18 @@ struct DataFileDescriptor{
     std::string filename;
     std::string label;
     std::string category;
+    int file_number;
+
+    DataFileDescriptor():filename(""), label(""),category(""),file_number(-1) { }
+
+    DataFileDescriptor(const std::string filename, const std::string label, const std::string category, const int file_number)
+      :filename(filename), label(label),category(category),file_number(file_number) { }
 
     DataFileDescriptor(const std::string filename, const std::string label, const std::string category)
-      :filename(filename), label(label),category(category) { }
+      :filename(filename), label(label),category(category),file_number(-1) { }
 
     DataFileDescriptor(const std::string line)
-      :filename(""),label(""),category(""){
+      :filename(""),label(""),category(""),file_number(-1){
         auto fields = split(line, ':');
         filename = strip(fields[0]);
         if(fields.size()>1) label=strip(fields[1]);

+ 5 - 2
dataset.hpp

@@ -33,6 +33,7 @@
 #include <iostream>
 #include "value.hpp"
 #include "container.hpp"
+#include "datafile.hpp"
 #include "log.hpp"
 
 namespace fv{
@@ -62,6 +63,7 @@ class DataSet{
         virtual bool load_next() = 0;
         virtual int get_events() = 0;
         virtual int get_current_event() = 0;
+        virtual util::DataFileDescriptor& get_current_file() = 0;
 
         std::map<std::string,std::string> get_container_name_value_map(){
             std::map<std::string, std::string> value_map;
@@ -80,7 +82,7 @@ class DataSet{
         }
     public:
         DataSet():max_events(0){
-            auto& event_check = GenFunction::reg_func<int()>("event_number",
+            auto event_check = GenFunction::reg_func<int()>("event_number",
                 FUNC(([ds=this](){
                     return ds->get_current_event();
                 })));
@@ -95,7 +97,8 @@ class DataSet{
             if (!silent) std::cout << std::endl;
             while( load_next() ){
                 current_event = get_current_event();
-                if (!silent) std::cout << "\rprocessing event: " << current_event+1 << "/" << events << std::flush;
+                if (!silent) std::cout << "\rprocessing event: " << current_event+1 << "/" << events
+                    << " of file: " << get_current_file().filename << std::flush;
                 GenValue::reset();
                 for(auto con : containers){
                     con.second->fill();

+ 2 - 2
filter.hpp

@@ -43,10 +43,10 @@ namespace fv {
 
 class ObsFilter : public DerivedValue<bool>{
     private:
-        Function<bool()>& filter_function;
+        Function<bool()>* filter_function;
 
         void update_value(){
-            value = filter_function();
+            value = (*filter_function)();
         }
 
     public:

+ 2 - 1
log.hpp

@@ -54,7 +54,8 @@ enum LogPriority {
 #define ERROR(x) std::clog << fv::util::LogPriority::kLogError << __FILE__ << "@L" << __LINE__ << " :: " << x << std::flush
 #define WARNING(x) std::clog << fv::util::LogPriority::kLogWarning << x << std::flush
 #define INFO(x) std::clog << fv::util::LogPriority::kLogInfo << x << std::flush
-#define DEBUG(x) std::clog << fv::util::LogPriority::kLogDebug << __FILE__ << "@L" << __LINE__ << " :: " << x << std::flush
+#define DEBUG(x) std::clog << fv::util::LogPriority::kLogDebug << x << std::flush
+#define DEBUGL(x) std::clog << fv::util::LogPriority::kLogDebug << __FILE__ << "@L" << __LINE__ << " :: " << x << std::flush
 
 /**
  * /see http://stackoverflow.com/questions/2638654/redirect-c-stdclog-to-syslog-on-unix

+ 44 - 15
python/plotter.py

@@ -28,24 +28,24 @@ def add_decorations(axes, luminosity, energy):
               transform=axes.transAxes)
 
 
-def to_bin_list(th1, include_errors=False):
+def to_bin_list(th1):
     bins = []
     for i in range(th1.GetNbinsX()):
-        center = th1.GetBinCenter(i + 1)
-        width = th1.GetBinWidth(i + 1)
-        content = th1.GetBinContent(i + 1)
-        if include_errors:
-            error = th1.GetBinError(i + 1)
-            bins.append((center-width/2, center+width/2, (content, error)))
-        else:
-            bins.append((center-width/2, center+width/2, content))
+        bin_ = i+1
+
+        center = th1.GetBinCenter(bin_)
+        width = th1.GetBinWidth(bin_)
+        content = th1.GetBinContent(bin_)
+        error = th1.GetBinError(bin_)
+
+        bins.append((center-width/2, center+width/2, (content, error)))
     return bins
 
 
 def histogram(th1, include_errors=False):
     edges = []
     values = []
-    bin_list = to_bin_list(th1, include_errors)
+    bin_list = to_bin_list(th1)
     for (l_edge, _, val) in bin_list:
         edges.append(l_edge)
         values.append(val)
@@ -53,30 +53,59 @@ def histogram(th1, include_errors=False):
     return values, edges
 
 
-def plot_histogram(h1, *args, axes=None, norm=None, include_errors=False, **kwargs):
+def histogram_slice(hist, range_):
+    bins, edges = hist
+    lim_low, lim_high = range_
+    bins_new = []
+    edges_new = []
+    for i, (bin_, low, high) in enumerate(zip(bins, edges, edges[1:])):
+        if low >= lim_low and high <= lim_high:
+            bins_new.append(bin_)
+            if edges_new:
+                edges_new.pop()  # pop off last high edge
+            edges_new.append(low)
+            edges_new.append(high)
+    return bins_new, edges_new
+
+
+def plot_histogram(h1, *args, axes=None, norm=None, include_errors=False,
+                   log=False, xlim=None, ylim=None, **kwargs):
     """ Plots a 1D ROOT histogram object using matplotlib """
     import numpy as np
-    bins, edges = histogram(h1, include_errors=include_errors)
+    if isinstance(h1, tuple):
+        bins, edges = h1
+    else:
+        bins, edges = histogram(h1, include_errors=True)
 
-    if norm is not None:
-        scale = norm/np.sum(bins)
-        bins = [(bin*scale, err*scale) for (bin, err) in bins]
+    scale = 1. if norm is None else norm/np.sum(bins)
+    bins = [(bin_*scale, err*scale) for (bin_, err) in bins]
     bins, errs = list(zip(*bins))
 
     left, right = np.array(edges[:-1]), np.array(edges[1:])
     X = np.array([left, right]).T.flatten()
     Y = np.array([bins, bins]).T.flatten()
+
     if axes is None:
         import matplotlib.pyplot as plt
         axes = plt.gca()
+
     axes.set_xlabel(kwargs.pop('xlabel', ''))
     axes.set_ylabel(kwargs.pop('ylabel', ''))
     axes.set_title(kwargs.pop('title', ''))
+    if xlim is not None:
+        axes.set_xlim(xlim)
+    if ylim is not None:
+        axes.set_ylim(ylim)
+    # elif not log:
+    #     axes.set_ylim((0, None))
+
     axes.plot(X, Y, *args, linewidth=1, **kwargs)
     if include_errors:
         axes.errorbar(0.5*(left+right), bins, yerr=errs,
                       color='k', marker=None, linestyle='None',
                       barsabove=True, elinewidth=.7, capsize=1)
+    if log:
+        axes.set_yscale('log')
 
 
 def histogram2d(th2, include_errors=False):

+ 1 - 1
python/process_parallel.py

@@ -1,4 +1,4 @@
-#!env/bin/python
+#! /usr/bin/env python3
 from os import listdir
 from os.path import join, isdir
 import argparse

+ 30 - 8
root/dataset.hpp

@@ -41,6 +41,7 @@
 
 using namespace std;
 using namespace fv;
+using namespace fv::util;
 using namespace fv::root;
 
 template<typename TREE_CLASS>
@@ -51,7 +52,7 @@ class TreeDataSet : public DataSet{
         // Maps filenames to data category. Either "signal" or "background"
         std::map<std::string,std::string> input_categories;
         std::string output_filename;
-        std::vector<fv::util::DataFileDescriptor> dfds;
+        std::map<std::string,DataFileDescriptor> file_descriptors;
         TFile* output_file;
         TREE_CLASS* tree_obj;
         long next_entry;
@@ -73,6 +74,12 @@ class TreeDataSet : public DataSet{
             return next_entry-1;
         }
 
+        fv::util::DataFileDescriptor& get_current_file(){
+            TFile* file = tree_obj->fChain->GetCurrentFile();
+            std::string filename = file->GetName();
+            return file_descriptors.at(filename);
+        }
+
         /* void save_event_count(){ */
         /*     std::map<std::string,int> event_counts; */
         /*     std::map<std::string,float> xsecs; */
@@ -97,14 +104,18 @@ class TreeDataSet : public DataSet{
 
     public:
 
-        TreeDataSet(const std::string& output_filename, const std::vector<fv::util::DataFileDescriptor>& dfds,
+        TreeDataSet(const std::string& output_filename, const std::vector<DataFileDescriptor>& dfds,
                     const std::string& tree_name)
           :DataSet(),
-           dfds(dfds),
            output_filename(output_filename),
            next_entry(0) {
             TChain* chain = new TChain(tree_name.c_str());
-            for(auto& dfd : dfds){
+            int cnt = 0;
+            for(const DataFileDescriptor& dfd : dfds){
+                file_descriptors[dfd.filename] = dfd;
+                /* file_descriptors.insert(std::make_pair(dfd.filename, dfd)); */
+                /* file_descriptors.emplace(std::make_pair(dfd.filename, dfd)); */
+                file_descriptors[dfd.filename].file_number = cnt++;
                 chain->Add(dfd.filename.c_str());
                 input_labels[dfd.filename] = dfd.label;
                 input_categories[dfd.filename] = dfd.category;
@@ -112,7 +123,7 @@ class TreeDataSet : public DataSet{
             tree_obj = new TREE_CLASS(chain);
             nentries = tree_obj->fChain->GetEntries();
             output_file = TFile::Open(output_filename.c_str(), "RECREATE");
-            tree_obj->fChain->SetBranchStatus("*", false);
+            set_branch_status("*", false);
           }
 
         ~TreeDataSet(){
@@ -139,7 +150,7 @@ class TreeDataSet : public DataSet{
                 CRITICAL("Branch: " << bname << " does not exist in input tree.", -1);
             }
             T* bref = (T*) branch->GetAddress();
-            tree_obj->fChain->SetBranchStatus(bname.c_str(), true);
+            set_branch_status(bname, true);
             INFO("Registering branch \"" << bname
                  << "\" with address " << bref
                  << " and type " << typeid(bref).name());
@@ -153,13 +164,24 @@ class TreeDataSet : public DataSet{
                 CRITICAL("Branch: " << bname << " does not exist in input tree.", -1);
             }
             T* bref = (T*) branch->GetAddress();
-            tree_obj->fChain->SetBranchStatus(bname.c_str(), true);
+            set_branch_status(bname, true);
             INFO("Registering pointer branch \"" << bname
                  << "\" with address " << bref
                  << " and type " << typeid(bref).name());
             return new PointerValue<T>(bname, bref);
         }
 
+        void set_branch_status(const std::string& bname, bool status){
+            unsigned int found=0;
+            tree_obj->fChain->SetBranchStatus(bname.c_str(), true, &found);
+            if (!found){
+                DataFileDescriptor& dfd = get_current_file();
+                CRITICAL("Branch: " << bname << " does not exist in input tree of file "
+                         << dfd.filename, -1);
+            }
+
+        }
+
         template <typename T>
         Value<T>* track_branch_obj(const std::string& bname){
             TBranch* branch = tree_obj->fChain->GetBranch(bname.c_str());
@@ -167,7 +189,7 @@ class TreeDataSet : public DataSet{
                 CRITICAL("Branch: " << bname << " does not exist in input tree.", -1);
             }
             T** bref = (T**) branch->GetAddress();
-            tree_obj->fChain->SetBranchStatus(bname.c_str(), true);
+            set_branch_status(bname, true);
             INFO("Registering object branch \"" << bname
                  << "\" with address " << bref
                  << " and type " << typeid(bref).name());

+ 71 - 45
value.hpp

@@ -115,8 +115,8 @@ std::vector<R> t2v(const std::tuple<ArgTypes...>& t){
 
 namespace detail {
     template <class F, class Tuple, std::size_t... I>
-    constexpr decltype(auto) call_impl(F &&f, Tuple &&t, std::index_sequence<I...>){
-        return f(std::get<I>(std::forward<Tuple>(t))...);
+    constexpr decltype(auto) call_impl(F *f, Tuple &&t, std::index_sequence<I...>){
+        return (*f)(std::get<I>(std::forward<Tuple>(t))...);
     }
 }
 
@@ -124,9 +124,9 @@ namespace detail {
  * Call a function f with the elements of the tuple t as arguments
  */
 template <class F, class Tuple>
-constexpr decltype(auto) call(F &&f, Tuple &&t){
+constexpr decltype(auto) call(F *f, Tuple &&t){
     return detail::call_impl(
-        std::forward<F>(f), std::forward<Tuple>(t),
+        f, std::forward<Tuple>(t),
         std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{});
 }
 
@@ -194,7 +194,7 @@ class GenFunction {
         }
 
         template <typename T>
-        static Function<T>& reg_func(const std::string& name, std::function<T> f, const std::string& impl){
+        static Function<T>* reg_func(const std::string& name, std::function<T> f, const std::string& impl){
             in_reg_func = true;
             Function<T>* func;
             if (GenFunction::function_registry[name] != nullptr){
@@ -207,11 +207,11 @@ class GenFunction {
                 GenFunction::function_registry[name] = func;
             }
             in_reg_func = false;
-            return *func;
+            return func;
         }
 
         template <typename T>
-        static Function<T>& lookup_function(const std::string& name){
+        static Function<T>* lookup_function(const std::string& name){
             if (GenFunction::function_registry[name] == nullptr){
                 CRITICAL("Function \"" << name << "\" not previously registered", -1);
             } else {
@@ -219,7 +219,7 @@ class GenFunction {
                 if (func == nullptr){
                     CRITICAL("Function \"" << name << "\" request and register have mismatched types", -1);
                 }
-                return *GenFunction::function_registry[name];
+                return func;
             }
         }
 };
@@ -692,7 +692,7 @@ template <typename Ret, typename ArgType>
 class Map<Ret(ArgType)> : public DerivedValue<std::vector<Ret>>{
     private:
         typedef Value<std::vector<ArgType>> arg_type;
-        Function<Ret(ArgType)>& fn;
+        Function<Ret(ArgType)>* fn;
         arg_type* arg;
 
         void update_value(){
@@ -703,11 +703,11 @@ class Map<Ret(ArgType)> : public DerivedValue<std::vector<Ret>>{
         }
 
     public:
-        static std::string fmt_name(Function<Ret(ArgType)>& fn, arg_type* arg){
-            return "map("+fn.get_name()+":"+arg->get_name()+")";
+        static std::string fmt_name(Function<Ret(ArgType)>* fn, arg_type* arg){
+            return "map("+fn->get_name()+":"+arg->get_name()+")";
         }
 
-        Map(Function<Ret(ArgType)>& fn, arg_type* arg, const std::string& alias)
+        Map(Function<Ret(ArgType)>* fn, arg_type* arg, const std::string& alias)
           :DerivedValue<std::vector<Ret>>(fmt_name(fn, arg), alias),
            fn(fn), arg(arg){ }
 
@@ -728,7 +728,7 @@ template <typename Ret, typename... ArgTypes>
 class TupMap<Ret(ArgTypes...)> : public DerivedValue<std::vector<Ret>>{
     private:
         typedef Value<std::vector<std::tuple<ArgTypes...>>> arg_type;
-        Function<Ret(ArgTypes...)>& fn;
+        Function<Ret(ArgTypes...)>* fn;
         arg_type* arg;
 
         void update_value(){
@@ -739,11 +739,11 @@ class TupMap<Ret(ArgTypes...)> : public DerivedValue<std::vector<Ret>>{
         }
 
     public:
-        static std::string fmt_name(Function<Ret(ArgTypes...)>& fn, arg_type* arg){
-            return "tup_map("+fn.get_name()+":"+arg->get_name()+")";
+        static std::string fmt_name(Function<Ret(ArgTypes...)>* fn, arg_type* arg){
+            return "tup_map("+fn->get_name()+":"+arg->get_name()+")";
         }
 
-        TupMap(Function<Ret(ArgTypes...)>& fn, arg_type* arg, const std::string& alias)
+        TupMap(Function<Ret(ArgTypes...)>* fn, arg_type* arg, const std::string& alias)
           :DerivedValue<std::vector<Ret>>(fmt_name(fn, arg), alias),
            fn(fn), arg(arg){ }
 
@@ -883,14 +883,40 @@ class DeTupVector : public DerivedValue<std::vector<typename std::tuple_element<
 };
 
 template<typename> class Apply; // undefined
+/**
+ * Applies a function to a tuple of values and returns a value. This will
+ * typically be called with a Tuple object as an argument.
+ */
+template <typename Ret, typename ArgType>
+class Apply<Ret(ArgType)> : public DerivedValue<Ret>{
+    private:
+        Function<Ret(ArgType)>* fn;
+        Value<ArgType>* arg;
+
+        void update_value(){
+            this->value = (*fn)(arg->get_value());
+        }
+
+    public:
+        static std::string fmt_name(Function<Ret(ArgType)>* fn, Value<ArgType>* arg){
+            return "apply("+fn->get_name()+":"+arg->get_name()+")";
+        }
+
+        Apply(Function<Ret(ArgType)>* fn, Value<ArgType>* arg, const std::string& alias)
+          :DerivedValue<Ret>(fmt_name(fn,arg), alias),
+           fn(fn), arg(arg){ }
+
+};
+
+template<typename> class TupApply; // undefined
 /**
  * Applies a function to a tuple of values and returns a value. This will
  * typically be called with a Tuple object as an argument.
  */
 template <typename Ret, typename... ArgTypes>
-class Apply<Ret(ArgTypes...)> : public DerivedValue<Ret>{
+class TupApply<Ret(ArgTypes...)> : public DerivedValue<Ret>{
     private:
-        Function<Ret(ArgTypes...)>& fn;
+        Function<Ret(ArgTypes...)>* fn;
         Value<std::tuple<ArgTypes...>>* arg;
 
         void update_value(){
@@ -899,11 +925,11 @@ class Apply<Ret(ArgTypes...)> : public DerivedValue<Ret>{
         }
 
     public:
-        static std::string fmt_name(Function<Ret(ArgTypes...)>& fn, Value<std::tuple<ArgTypes...>>* arg){
-            return "apply("+fn.get_name()+":"+arg->get_name()+")";
+        static std::string fmt_name(Function<Ret(ArgTypes...)>* fn, Value<std::tuple<ArgTypes...>>* arg){
+            return "tup_apply("+fn->get_name()+":"+arg->get_name()+")";
         }
 
-        Apply(Function<Ret(ArgTypes...)>& fn, Value<std::tuple<ArgTypes...>>* arg, const std::string& alias)
+        TupApply(Function<Ret(ArgTypes...)>* fn, Value<std::tuple<ArgTypes...>>* arg, const std::string& alias)
           :DerivedValue<Ret>(fmt_name(fn,arg), alias),
            fn(fn), arg(arg){ }
 
@@ -915,7 +941,7 @@ class Apply<Ret(ArgTypes...)> : public DerivedValue<Ret>{
 template<typename T>
 class Count : public DerivedValue<int>{
     private:
-        Function<bool(T)>& selector;
+        Function<bool(T)>* selector;
         Value<std::vector<T> >* v;
 
         void update_value(){
@@ -927,11 +953,11 @@ class Count : public DerivedValue<int>{
         }
 
     public:
-        static std::string fmt_name(Function<bool(T)>& selector, Value<std::vector<T>>* v){
-            return "count("+selector.get_name()+":"+v->get_name()+")";
+        static std::string fmt_name(Function<bool(T)>* selector, Value<std::vector<T>>* v){
+            return "count("+selector->get_name()+":"+v->get_name()+")";
         }
 
-        Count(Function<bool(T)>& selector, Value<std::vector<T>>* v, const std::string alias)
+        Count(Function<bool(T)>* selector, Value<std::vector<T>>* v, const std::string alias)
           :DerivedValue<int>(fmt_name(selector,v), alias),
            selector(selector), v(v) { }
 };
@@ -942,7 +968,7 @@ class Count : public DerivedValue<int>{
 template<typename T>
 class Filter : public DerivedValue<std::vector<T>>{
     private:
-        Function<bool(T)>& filter;
+        Function<bool(T)>* filter;
         Value<std::vector<T> >* v;
 
         void update_value(){
@@ -954,11 +980,11 @@ class Filter : public DerivedValue<std::vector<T>>{
         }
 
     public:
-        static std::string fmt_name(Function<bool(T)>& filter, Value<std::vector<T>>* v){
-            return "filter("+filter.get_name()+":"+v->get_name()+")";
+        static std::string fmt_name(Function<bool(T)>* filter, Value<std::vector<T>>* v){
+            return "filter("+filter->get_name()+":"+v->get_name()+")";
         }
 
-        Filter(Function<bool(T)>& filter, Value<std::vector<T>>* v, const std::string alias)
+        Filter(Function<bool(T)>* filter, Value<std::vector<T>>* v, const std::string alias)
           :DerivedValue<std::vector<T>>(fmt_name(filter,v), alias),
            filter(filter), v(v) { }
 };
@@ -972,7 +998,7 @@ template<typename... ArgTypes>
 class TupFilter : public DerivedValue<std::vector<std::tuple<ArgTypes...>>>{
     private:
         typedef std::vector<std::tuple<ArgTypes...>> value_type;
-        Function<bool(ArgTypes...)>& filter;
+        Function<bool(ArgTypes...)>* filter;
         Value<value_type>* arg;
 
         void update_value(){
@@ -984,11 +1010,11 @@ class TupFilter : public DerivedValue<std::vector<std::tuple<ArgTypes...>>>{
         }
 
     public:
-        static std::string fmt_name(Function<bool(ArgTypes...)>& filter, Value<value_type>* arg){
-            return "tup_filter("+filter.get_name()+":"+arg->get_name()+")";
+        static std::string fmt_name(Function<bool(ArgTypes...)>* filter, Value<value_type>* arg){
+            return "tup_filter("+filter->get_name()+":"+arg->get_name()+")";
         }
 
-        TupFilter(Function<bool(ArgTypes...)>& filter, Value<value_type>* arg, const std::string alias)
+        TupFilter(Function<bool(ArgTypes...)>* filter, Value<value_type>* arg, const std::string alias)
           :DerivedValue<value_type>(fmt_name(filter, arg), alias),
            filter(filter), arg(arg) { }
 };
@@ -1002,7 +1028,7 @@ class TupFilter : public DerivedValue<std::vector<std::tuple<ArgTypes...>>>{
 template <typename T>
 class Reduce : public DerivedValue<T>{
     private:
-        Function<T(std::vector<T>)>& reduce_fn;
+        Function<T(std::vector<T>)>* reduce_fn;
 
         void update_value(){
             this->value = reduce_fn(v->get_value());
@@ -1012,11 +1038,11 @@ class Reduce : public DerivedValue<T>{
         Value<std::vector<T> >* v;
 
     public:
-        static std::string fmt_name(Function<T(std::vector<T>)>& reduce_fn, Value<std::vector<T>>* v){
-            return "reduce("+reduce_fn.get_name()+":"+v->get_name()+")";
+        static std::string fmt_name(Function<T(std::vector<T>)>* reduce_fn, Value<std::vector<T>>* v){
+            return "reduce("+reduce_fn->get_name()+":"+v->get_name()+")";
         }
 
-        Reduce(Function<T(std::vector<T>)>& reduce_fn, Value<std::vector<T> >* v, const std::string alias)
+        Reduce(Function<T(std::vector<T>)>* reduce_fn, Value<std::vector<T> >* v, const std::string alias)
           :DerivedValue<T>(fmt_name(reduce_fn, v), alias),
            reduce_fn(reduce_fn), v(v) { }
 };
@@ -1112,7 +1138,7 @@ class ElementOf : public Reduce<T>{
 template <typename T>
 class ReduceIndex : public DerivedValue<std::pair<T, int> >{
     private:
-        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(){
@@ -1120,8 +1146,8 @@ class ReduceIndex : public DerivedValue<std::pair<T, int> >{
         }
 
     public:
-        ReduceIndex(Function<std::pair<T,int>(std::vector<T>)>& reduce, Value<std::vector<T> >* v, const std::string alias="")
-          :DerivedValue<T>("reduceIndexWith("+reduce.get_name()+":"+v->get_name()+")", alias),
+        ReduceIndex(Function<std::pair<T,int>(std::vector<T>)>* reduce, Value<std::vector<T> >* v, const std::string alias="")
+          :DerivedValue<T>("reduceIndexWith("+reduce->get_name()+":"+v->get_name()+")", alias),
            reduce(reduce), v(v) { }
 };
 
@@ -1242,17 +1268,17 @@ class CartProduct : public DerivedValue<std::vector<std::tuple<FST,SND>>>{
 template <typename T>
 class BoundValue : public DerivedValue<T>{
     protected:
-        Function<T()>& f;
+        Function<T()>* f;
         void update_value(){
-            this->value = f();
+            this->value = (*f)();
         }
 
     public:
-        static std::string fmt_name(Function<T()> f){
-            return f.get_name()+"(<bound>)";
+        static std::string fmt_name(Function<T()>* f){
+            return f->get_name()+"(<bound>)";
         }
 
-        BoundValue(Function<T()>& f, const std::string alias="")
+        BoundValue(Function<T()>* f, const std::string alias="")
           :DerivedValue<T>(fmt_name(f), alias),
            f(f) { }
 };