Browse Source

Major rewrite to V2.0.0. Highlights include:

  - Significantly reduces the role of the Value class by re-introducing
  the looper in the analysis routine.
  - No longer are containers hooked up with values. They are registered
  first, and then filled in the looper.
Caleb Fangmeier 6 years ago
parent
commit
625f835f8d

+ 4 - 0
.gitignore

@@ -28,3 +28,7 @@
 *.out
 *.app
 
+
+.idea/
+
+cmake-build-*/

+ 38 - 0
CMakeLists.txt

@@ -0,0 +1,38 @@
+CMAKE_MINIMUM_REQUIRED (VERSION 2.8)
+
+PROJECT (FILVAL CXX)
+
+OPTION(BUILD_EXAMPLES "Build the demonstration programs" ON)
+
+SET(BUILD_SHARED_LIBS ON)
+ADD_SUBDIRECTORY(yaml-cpp)
+
+# Declare semantic versioning for FILVAL
+SET(FILVAL_VERSION_MAJOR 2)
+SET(FILVAL_VERSION_MINOR 0)
+SET(FILVAL_VERSION_PATCH 0)
+CONFIGURE_FILE (
+        "${PROJECT_SOURCE_DIR}/include/filval.hpp"
+        "${PROJECT_BINARY_DIR}/include/filval.hpp"
+)
+
+
+LIST( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake )
+
+FIND_PACKAGE(ROOT REQUIRED)
+INCLUDE_DIRECTORIES( SYSTEM ${ROOT_INCLUDE_DIR} include/ root/include/ yaml-cpp/include/ )
+
+# Adds the dictionary library for additonal type serialization
+
+
+SET( CLINGDICTFILE ${CMAKE_CURRENT_BINARY_DIR}/clingdict.cpp )
+ROOT_GENERATE_DICTIONARY( "" ${CMAKE_CURRENT_SOURCE_DIR}/root/include/LinkDef.hpp ${CLINGDICTFILE} "" )
+
+ADD_LIBRARY( filval SHARED ${CLINGDICTFILE} )
+
+#SET(EXE_LIBS filval ${ROOT_LIBRARIES} ${PROJECT_BINARY_DIR}/libyaml-cpp.so)
+
+IF (BUILD_EXAMPLES)
+    ADD_EXECUTABLE(example1 examples/example1.cpp)
+    TARGET_LINK_LIBRARIES(example1 ${ROOT_LIBRARIES} yaml-cpp)
+ENDIF()

+ 0 - 404
api.hpp

@@ -1,404 +0,0 @@
-/**
- * @file
- * @author  Caleb Fangmeier <caleb@fangmeier.tech>
- * @version 0.1
- *
- * @section LICENSE
- *
- *
- * MIT License
- *
- * Copyright (c) 2017 Caleb Fangmeier
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * @section DESCRIPTION
- * This is the main api for FilVal. Users should try to avoid instantiating
- * Value objects directly, but rather use these functions. There are multiple
- * reasons for this. First of all, these functions do the extra work of making
- * sure that an identical Value doesn't already exist. If one does, it returns
- * the old Value object rather than creating a new one. The second reason is
- * that C++ allows type deduction for functions so one can often leave out the
- * type definitions to produce shorter, more readable, code. This cannot be
- * done when creating templated objects directly.
- */
-#ifndef API_HPP
-#define API_HPP
-#include <string>
-#include <vector>
-#include "filval/value.hpp"
-namespace fv{
-
-
-    template<typename T>
-    Value<T>* lookup(const std::string& name){
-        Value<T>* tv = GenValue::get_value<T>(name);
-        if (tv == nullptr){
-            CRITICAL("Could not find alias or value \"" << name << "\"."
-                     <<" I'll tell you the ones I know about." << std::endl
-                     << GenValue::summary(), -1);
-        }
-        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);
-        return tv != nullptr;
-    }
-
-    ObsFilter* lookup_obs_filter(const std::string& name){
-        ObsFilter* f =  dynamic_cast<ObsFilter*>(GenValue::get_value<bool>(name));
-        if(f == nullptr){
-            CRITICAL("ObsFilter: "+f->get_name() + "has improper type.",-1);
-        }
-        return f;
-    }
-
-    template <typename T>
-    decltype(auto)
-    wrapper_vector(Value<int>* size, Value<T*>* data, const std::string& alias=""){
-        typedef std::vector<T> type;
-        const std::string& name = WrapperVector<T>::fmt_name(size, data);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new WrapperVector<T>(size, data, alias);
-    }
-
-    template <typename... ArgTypes>
-    decltype(auto)
-    zip(Value<std::vector<ArgTypes>>*... args, const std::string& alias=""){
-        typedef std::vector<std::tuple<ArgTypes...>> type;
-        std::string& name = Zip<ArgTypes...>::fmt_name(args...);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new Zip<ArgTypes...>(args..., alias);
-    }
-
-    template <typename Ret, typename ArgType>
-    decltype(auto)
-    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))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new Map<Ret(ArgType)>(fn, arg, alias);
-    }
-
-    template <typename Ret, typename... ArgTypes>
-    decltype(auto)
-    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))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new TupMap<Ret(ArgTypes...)>(fn, arg, alias);
-    }
-
-    template <typename... ArgTypes>
-    decltype(auto)
-    tuple(Value<ArgTypes>*... args){
-        typedef std::tuple<ArgTypes...> type;
-        const std::string& name = Tuple<ArgTypes...>::fmt_name(args...);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new Tuple<ArgTypes...>(args..., "");
-    }
-
-    template <size_t N, typename... ArgTypes>
-    decltype(auto)
-    detup(Value<std::tuple<ArgTypes...>>* tup, const std::string& alias=""){
-        typedef typename std::tuple_element<N, std::tuple<ArgTypes...>>::type type;
-        const std::string& name = DeTup<N, ArgTypes...>::fmt_name(tup);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new DeTup<N, ArgTypes...>(tup, alias);
-    }
-
-    template <size_t N, typename... ArgTypes>
-    decltype(auto)
-    detup_vec(Value<std::vector<std::tuple<ArgTypes...>>>* tup, const std::string& alias=""){
-        typedef std::vector<typename std::tuple_element<N, std::tuple<ArgTypes...>>::type> type;
-        const std::string& name = DeTupVector<N, ArgTypes...>::fmt_name(tup);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            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)
-    tup_apply(Function<Ret(ArgTypes...)>* fn, Value<std::tuple<ArgTypes...>>* arg, const std::string& alias=""){
-        typedef Ret type;
-        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 TupApply<Ret(ArgTypes...)>(fn, arg, alias);
-    }
-
-    template <typename T1, typename T2>
-    decltype(auto)
-    pair(Value<T1>* val1, Value<T2>* val2, const std::string& alias=""){
-        typedef std::pair<T1,T2> type;
-        const std::string& name = Pair<T1,T2>::fmt_name(val1, val2);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new Pair<T1,T2>(val1, val2, alias);
-    }
-
-    template <typename T1, typename T2>
-    decltype(auto)
-    pair(const std::string& name1, const std::string& name2, const std::string& alias=""){
-        return pair<T1,T2>(lookup<T1>(name1), lookup<T2>(name2), alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    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))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new Reduce<T>(fn, v, alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    max(Value<std::vector<T>>* v, const std::string& alias=""){
-        typedef T type;
-        const std::string& name = Max<T>::fmt_name(v);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new Max<T>(v, alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    max(const std::string& v_name, const std::string& alias=""){
-        return max(lookup<std::vector<T>>(v_name), alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    min(Value<std::vector<T>>* v, const std::string& alias=""){
-        typedef T type;
-        const std::string& name = Min<T>::fmt_name(v);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new Min<T>(v, alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    min(const std::string& v_name, const std::string& alias=""){
-        return min(lookup<std::vector<T>>(v_name), alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    range(Value<std::vector<T>>* v, const std::string& alias=""){
-        typedef T type;
-        const std::string& name = Range<T>::fmt_name(v);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new Range<T>(v, alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    range(const std::string& v_name, const std::string& alias=""){
-        return range(lookup<std::vector<T>>(v_name), alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    mean(Value<std::vector<T>>* v, const std::string& alias=""){
-        typedef T type;
-        const std::string& name = Mean<T>::fmt_name(v);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new Mean<T>(v, alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    mean(const std::string& v_name, const std::string& alias=""){
-        return mean(lookup<std::vector<T>>(v_name), alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    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))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new Count<T>(selector, v, alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    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);
-    }
-
-    template <typename FST, typename SND>
-    decltype(auto)
-    cart_product(Value<std::vector<FST>>* val1, Value<std::vector<SND>>* val2, const std::string& alias=""){
-        typedef std::vector<std::tuple<FST,SND>> type;
-        const std::string& name = CartProduct<FST, SND>::fmt_name(val1, val2);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new CartProduct<FST, SND>(val1, val2, alias);
-    }
-
-    template <typename FST, typename SND>
-    decltype(auto)
-    cart_product(const std::string& val1_name, const std::string& val2_name, const std::string& alias=""){
-        return cart_product<FST,SND>(lookup<std::vector<FST>>(val1_name), lookup<std::vector<SND>>(val2_name), alias);
-    }
-
-    template <typename T, int Size>
-    decltype(auto)
-    combinations(Value<std::vector<T>>* val, const std::string& alias=""){
-        typedef std::vector<typename HomoTuple<T,Size>::type> type;
-        const std::string& name = Combinations<T, Size>::fmt_name(val);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new Combinations<T, Size>(val, alias);
-    }
-
-    template <typename T, int Size>
-    decltype(auto)
-    combinations(const std::string& val_name, const std::string alias = ""){
-        return combinations<T, Size>(lookup<std::vector<T>>(val_name), alias);
-    }
-
-    template < typename T>
-    decltype(auto)
-    constant(const std::string name, T const_value, const std::string alias=""){
-        typedef T type;
-        const std::string& val_name = ConstantValue<T>::fmt_name(name);
-        if (check_exists<type>(val_name))
-            return lookup<type>(val_name);
-        else
-            return (Value<type>*)new ConstantValue<T>(val_name, const_value, alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    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))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new BoundValue<T>(f, alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    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))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new Filter<T>(filter, val, alias);
-    }
-
-    template <typename T>
-    decltype(auto)
-    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=""){
-        typedef std::vector<std::tuple<ArgTypes...>> type;
-        const std::string& name = TupFilter<ArgTypes...>::fmt_name(filter, val);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new TupFilter<ArgTypes...>(filter, val, alias);
-    }
-
-    template <typename... ArgTypes>
-    decltype(auto)
-    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);
-    }
-
-    ObsFilter* obs_filter(const std::string& name, std::function<bool()> filter_function, const std::string& impl=""){
-        return new ObsFilter(name, filter_function, impl);
-    }
-
-    template <typename T>
-    static Function<T>* func(const std::string& name, std::function<T> f, const std::string& impl){
-        return GenFunction::reg_func(name, f, impl);
-    }
-
-    template <typename Ret>
-    decltype(auto)
-    func_value(const std::string& name, std::function<Ret()> f, const std::string&& impl, const std::string& alias=""){
-        typedef Ret type;
-        const std::string& val_name = FunctionValue<Ret>::fmt_name(name);
-        if (check_exists<type>(val_name))
-            return lookup<type>(val_name);
-        else {
-            Function<Ret()>* fn = func(name, f, impl);
-            return (Value<type>*)new FunctionValue<Ret>(name, fn, alias);
-        }
-    }
-}
-#endif // API_HPP

+ 16 - 0
cmake/FindJupyter.cmake

@@ -0,0 +1,16 @@
+# - Find Jupyter instalation
+# This module tries to find the Jupyter installation on your system.
+
+FIND_PROGRAM(JUPYTER_EXECUTABLE NAMES jupyter)
+SET(JUPYTER_FOUND False)
+IF(NOT ${JUPYTER_EXECUTABLE} MATCHES "JUPYTER_EXECUTABLE-NOTFOUND")
+    SET(JUPYTER_FOUND True)
+    MESSAGE("-- Found Jupyter: " ${JUPYTER_EXECUTABLE})
+ENDIF()
+
+FIND_PROGRAM(NBCONVERT_EXECUTABLE NAMES jupyter-nbconvert)
+SET(NBCONVERT_FOUND False)
+IF(NOT ${NBCONVERT_EXECUTABLE} MATCHES "NBCONVERT_EXECUTABLE-NOTFOUND")
+    SET(NBCONVERT_FOUND True)
+    MESSAGE("-- Found nbconvert: " ${NBCONVERT_EXECUTABLE})
+ENDIF()

+ 237 - 0
cmake/FindROOT.cmake

@@ -0,0 +1,237 @@
+# - Find ROOT instalation
+# This module tries to find the ROOT installation on your system.
+# It tries to find the root-config script which gives you all the needed information.
+# If the system variable ROOTSYS is set this is straight forward.
+# If not the module uses the pathes given in ROOT_CONFIG_SEARCHPATH.
+# If you need an other path you should add this path to this varaible.
+# The root-config script is then used to detect basically everything else.
+# This module defines a number of key variables and macros.
+
+# F.Uhlig@gsi.de (fairroot.gsi.de)
+
+
+SET(ROOT_CONFIG_SEARCHPATH
+  ${SIMPATH}/tools/root/bin
+  $ENV{ROOTSYS}/bin
+  /usr/local/bin
+  /opt/local/bin
+  /root/bin
+)
+
+SET(ROOT_DEFINITIONS "")
+
+SET(ROOT_INSTALLED_VERSION_TOO_OLD FALSE)
+
+SET(ROOT_CONFIG_EXECUTABLE ROOT_CONFIG_EXECUTABLE-NOTFOUND)
+
+FIND_PROGRAM(ROOT_CONFIG_EXECUTABLE NAMES root-config PATHS
+   ${ROOT_CONFIG_SEARCHPATH}
+   NO_DEFAULT_PATH)
+
+IF (${ROOT_CONFIG_EXECUTABLE} MATCHES "ROOT_CONFIG_EXECUTABLE-NOTFOUND")
+  MESSAGE( FATAL_ERROR "ROOT not installed in the searchpath and ROOTSYS is not set. Please
+ set ROOTSYS or add the path to your ROOT installation in the Macro FindROOT.cmake in the
+ subdirectory cmake/modules.")
+ELSE (${ROOT_CONFIG_EXECUTABLE} MATCHES "ROOT_CONFIG_EXECUTABLE-NOTFOUND")
+  STRING(REGEX REPLACE "(^.*)/bin/root-config" "\\1" test ${ROOT_CONFIG_EXECUTABLE})
+  SET( ENV{ROOTSYS} ${test})
+  set( ROOTSYS ${test})
+ENDIF (${ROOT_CONFIG_EXECUTABLE} MATCHES "ROOT_CONFIG_EXECUTABLE-NOTFOUND")
+
+# root config is a bash script and not commonly executable under Windows
+# make some static assumptions instead
+IF (WIN32)
+  SET(ROOT_FOUND FALSE)
+  IF (ROOT_CONFIG_EXECUTABLE)
+    SET(ROOT_FOUND TRUE)
+    set(ROOT_INCLUDE_DIR ${ROOTSYS}/include)
+    set(ROOT_LIBRARY_DIR ${ROOTSYS}/lib)
+    SET(ROOT_BINARY_DIR ${ROOTSYS}/bin)
+    set(ROOT_LIBRARIES -LIBPATH:${ROOT_LIBRARY_DIR} libGpad.lib libHist.lib libGraf.lib libGraf3d.lib libTree.lib libRint.lib libPostscript.lib libMatrix.lib libPhysics.lib libMathCore.lib libRIO.lib libNet.lib libThread.lib libCore.lib libCint.lib libMinuit.lib libGui.lib libSpectrum.lib)
+    FIND_PROGRAM(ROOT_CINT_EXECUTABLE
+      NAMES rootcint
+      PATHS ${ROOT_BINARY_DIR}
+      NO_DEFAULT_PATH
+      )
+    MESSAGE(STATUS "Found ROOT: $ENV{ROOTSYS}/bin/root (WIN32/version not identified)")
+  ENDIF (ROOT_CONFIG_EXECUTABLE)
+
+ELSE(WIN32)
+
+  IF (ROOT_CONFIG_EXECUTABLE)
+
+    SET(ROOT_FOUND FALSE)
+
+    EXEC_PROGRAM(${ROOT_CONFIG_EXECUTABLE} ARGS "--version" OUTPUT_VARIABLE ROOTVERSION)
+
+    MESSAGE(STATUS "Found ROOT: $ENV{ROOTSYS}/bin/root (found version ${ROOTVERSION})")
+
+    # we need at least version 5.00/00
+    IF (NOT ROOT_MIN_VERSION)
+      SET(ROOT_MIN_VERSION "5.00/00")
+    ENDIF (NOT ROOT_MIN_VERSION)
+
+    # now parse the parts of the user given version string into variables
+    STRING(REGEX REPLACE "^([0-9]+)\\.[0-9][0-9]+\\/[0-9][0-9]+" "\\1" req_root_major_vers "${ROOT_MIN_VERSION}")
+    STRING(REGEX REPLACE "^[0-9]+\\.([0-9][0-9])+\\/[0-9][0-9]+.*" "\\1" req_root_minor_vers "${ROOT_MIN_VERSION}")
+    STRING(REGEX REPLACE "^[0-9]+\\.[0-9][0-9]+\\/([0-9][0-9]+)" "\\1" req_root_patch_vers "${ROOT_MIN_VERSION}")
+
+    # and now the version string given by qmake
+    STRING(REGEX REPLACE "^([0-9]+)\\.[0-9][0-9]+\\/[0-9][0-9]+.*" "\\1" found_root_major_vers "${ROOTVERSION}")
+    STRING(REGEX REPLACE "^[0-9]+\\.([0-9][0-9])+\\/[0-9][0-9]+.*" "\\1" found_root_minor_vers "${ROOTVERSION}")
+    STRING(REGEX REPLACE "^[0-9]+\\.[0-9][0-9]+\\/([0-9][0-9]+).*" "\\1" found_root_patch_vers "${ROOTVERSION}")
+
+    IF (found_root_major_vers LESS 5)
+      MESSAGE( FATAL_ERROR "Invalid ROOT version \"${ROOTERSION}\", at least major version 4 is required, e.g. \"5.00/00\"")
+    ENDIF (found_root_major_vers LESS 5)
+
+    # compute an overall version number which can be compared at once
+    MATH(EXPR req_vers "${req_root_major_vers}*10000 + ${req_root_minor_vers}*100 + ${req_root_patch_vers}")
+    MATH(EXPR found_vers "${found_root_major_vers}*10000 + ${found_root_minor_vers}*100 + ${found_root_patch_vers}")
+
+    IF (found_vers LESS req_vers)
+      SET(ROOT_FOUND FALSE)
+      SET(ROOT_INSTALLED_VERSION_TOO_OLD TRUE)
+    ELSE (found_vers LESS req_vers)
+      SET(ROOT_FOUND TRUE)
+    ENDIF (found_vers LESS req_vers)
+
+  ENDIF (ROOT_CONFIG_EXECUTABLE)
+
+
+  IF (ROOT_FOUND)
+
+    STRING(REGEX REPLACE "^([0-9]+)\\.[0-9][0-9]+\\/[0-9][0-9]+" "\\1" ROOT_MAJOR_VER "${ROOTVERSION}")
+    IF(ROOT_MAJOR_VER EQUAL 6)
+      MESSAGE("-- ROOT 6 detected - requiring C++11")
+      ADD_DEFINITIONS("-std=c++1y -DROOT_MAJOR_VER=6")
+    ENDIF(ROOT_MAJOR_VER EQUAL 6)
+
+    # ask root-config for the library dir
+    # Set ROOT_LIBRARY_DIR
+
+    EXEC_PROGRAM( ${ROOT_CONFIG_EXECUTABLE}
+      ARGS "--libdir"
+      OUTPUT_VARIABLE ROOT_LIBRARY_DIR_TMP )
+
+    IF(EXISTS "${ROOT_LIBRARY_DIR_TMP}")
+      SET(ROOT_LIBRARY_DIR ${ROOT_LIBRARY_DIR_TMP} )
+    ELSE(EXISTS "${ROOT_LIBRARY_DIR_TMP}")
+      MESSAGE("Warning: ROOT_CONFIG_EXECUTABLE reported ${ROOT_LIBRARY_DIR_TMP} as library path,")
+      MESSAGE("Warning: but ${ROOT_LIBRARY_DIR_TMP} does NOT exist, ROOT must NOT be installed correctly.")
+    ENDIF(EXISTS "${ROOT_LIBRARY_DIR_TMP}")
+
+    # ask root-config for the binary dir
+    EXEC_PROGRAM(${ROOT_CONFIG_EXECUTABLE}
+      ARGS "--bindir"
+      OUTPUT_VARIABLE root_bins )
+    SET(ROOT_BINARY_DIR ${root_bins})
+
+    # ask root-config for the include dir
+    EXEC_PROGRAM( ${ROOT_CONFIG_EXECUTABLE}
+      ARGS "--incdir"
+      OUTPUT_VARIABLE root_headers )
+    SET(ROOT_INCLUDE_DIR ${root_headers})
+    # CACHE INTERNAL "")
+
+    # ask root-config for the library varaibles
+    EXEC_PROGRAM( ${ROOT_CONFIG_EXECUTABLE}
+      #    ARGS "--noldflags --noauxlibs --libs"
+      ARGS "--glibs"
+      OUTPUT_VARIABLE root_flags )
+
+    #  STRING(REGEX MATCHALL "([^ ])+"  root_libs_all ${root_flags})
+    #  STRING(REGEX MATCHALL "-L([^ ])+"  root_library ${root_flags})
+    #  REMOVE_FROM_LIST(root_flags "${root_libs_all}" "${root_library}")
+
+    SET(ROOT_LIBRARIES "${root_flags} -lMinuit -lSpectrum -lTMVA")
+
+    # Make variables changeble to the advanced user
+    MARK_AS_ADVANCED( ROOT_LIBRARY_DIR ROOT_INCLUDE_DIR ROOT_DEFINITIONS)
+
+    # Set ROOT_INCLUDES
+    SET( ROOT_INCLUDES ${ROOT_INCLUDE_DIR})
+
+    SET(LD_LIBRARY_PATH ${LD_LIBRARY_PATH} ${ROOT_LIBRARY_DIR})
+
+    #######################################
+    #
+    #       Check the executables of ROOT
+    #          ( rootcint )
+    #
+    #######################################
+
+    FIND_PROGRAM(ROOT_CINT_EXECUTABLE
+      NAMES rootcint
+      PATHS ${ROOT_BINARY_DIR}
+      NO_DEFAULT_PATH
+      )
+
+  ENDIF (ROOT_FOUND)
+ENDIF(WIN32)
+
+  ###########################################
+  #
+  #       Macros for building ROOT dictionary
+  #
+  ###########################################
+
+MACRO (ROOT_GENERATE_DICTIONARY INFILES LINKDEF_FILE OUTFILE INCLUDE_DIRS_IN)
+
+  set(INCLUDE_DIRS)
+
+  foreach (_current_FILE ${INCLUDE_DIRS_IN})
+    set(INCLUDE_DIRS ${INCLUDE_DIRS} -I${_current_FILE})
+  endforeach (_current_FILE ${INCLUDE_DIRS_IN})
+
+  if (CMAKE_SYSTEM_NAME MATCHES Linux)
+    ADD_CUSTOM_COMMAND(OUTPUT ${OUTFILE}
+       COMMAND LD_LIBRARY_PATH=${ROOT_LIBRARY_DIR} ROOTSYS=${ROOTSYS} ${ROOT_CINT_EXECUTABLE}
+       ARGS -f ${OUTFILE} -c -DHAVE_CONFIG_H ${INCLUDE_DIRS} ${INFILES} ${LINKDEF_FILE} DEPENDS ${INFILES} ${LINKDEF_FILE})
+  else (CMAKE_SYSTEM_NAME MATCHES Linux)
+    if (CMAKE_SYSTEM_NAME MATCHES Darwin)
+      ADD_CUSTOM_COMMAND(OUTPUT ${OUTFILE}
+       COMMAND DYLD_LIBRARY_PATH=${ROOT_LIBRARY_DIR} ROOTSYS=${ROOTSYS} ${ROOT_CINT_EXECUTABLE}
+       ARGS -f ${OUTFILE} -c -DHAVE_CONFIG_H ${INCLUDE_DIRS} ${INFILES} ${LINKDEF_FILE} DEPENDS ${INFILES} ${LINKDEF_FILE})
+    endif (CMAKE_SYSTEM_NAME MATCHES Darwin)
+  endif (CMAKE_SYSTEM_NAME MATCHES Linux)
+
+ENDMACRO (ROOT_GENERATE_DICTIONARY)
+
+MACRO (GENERATE_ROOT_TEST_SCRIPT SCRIPT_FULL_NAME)
+
+  get_filename_component(path_name ${SCRIPT_FULL_NAME} PATH)
+  get_filename_component(file_extension ${SCRIPT_FULL_NAME} EXT)
+  get_filename_component(file_name ${SCRIPT_FULL_NAME} NAME_WE)
+  set(shell_script_name "${file_name}.sh")
+
+  #MESSAGE("PATH: ${path_name}")
+  #MESSAGE("Ext: ${file_extension}")
+  #MESSAGE("Name: ${file_name}")
+  #MESSAGE("Shell Name: ${shell_script_name}")
+
+  string(REPLACE ${PROJECT_SOURCE_DIR}
+         ${PROJECT_BINARY_DIR} new_path ${path_name}
+        )
+
+  #MESSAGE("New PATH: ${new_path}")
+
+  file(MAKE_DIRECTORY ${new_path}/data)
+
+  CONVERT_LIST_TO_STRING(${LD_LIBRARY_PATH})
+  set(MY_LD_LIBRARY_PATH ${output})
+  set(my_script_name ${SCRIPT_FULL_NAME})
+
+  if(CMAKE_SYSTEM MATCHES Darwin)
+    configure_file(${PROJECT_SOURCE_DIR}/cmake/scripts/root_macro_macos.sh.in
+                   ${new_path}/${shell_script_name}
+                  )
+  else(CMAKE_SYSTEM MATCHES Darwin)
+    configure_file(${PROJECT_SOURCE_DIR}/cmake/scripts/root_macro.sh.in
+                   ${new_path}/${shell_script_name}
+                  )
+  endif(CMAKE_SYSTEM MATCHES Darwin)
+
+  EXEC_PROGRAM(/bin/chmod ARGS "u+x  ${new_path}/${shell_script_name}")
+
+ENDMACRO (GENERATE_ROOT_TEST_SCRIPT)

+ 0 - 292
container.hpp

@@ -1,292 +0,0 @@
-/**
- * @file
- * @author  Caleb Fangmeier <caleb@fangmeier.tech>
- * @version 0.1
- *
- * @section LICENSE
- *
- *
- * MIT License
- *
- * Copyright (c) 2017 Caleb Fangmeier
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef container_hpp
-#define container_hpp
-#include <typeindex>
-#include <vector>
-#include <map>
-
-#include "value.hpp"
-#include "filter.hpp"
-
-template class std::vector<std::vector<float> >;
-template class std::vector<std::vector<int> >;
-
-
-namespace fv::util{
-std::string get_type_name(const std::type_index& index){
-    std::map<std::type_index, std::string> _map;
-    // Add to this list as needed :)
-    _map[typeid(int)]="int";
-    _map[typeid(unsigned int)]="unsigned int";
-    _map[typeid(float)]="float";
-    _map[typeid(double)]="double";
-    _map[typeid(std::vector<int>)]="std::vector<int>";
-    _map[typeid(std::vector<float>)]="std::vector<float>";
-    _map[typeid(std::pair<std::vector<float>,std::vector<float>>)]="std::pair<std::vector<float>,std::vector<float>>";
-    _map[typeid(std::vector<std::pair<float,int>>)]="std::vector<std::pair<float,int>>";
-    _map[typeid(std::map<std::string,std::string>)] = "std::map<std::string,std::string>";
-
-    if (_map[index] == ""){
-        CRITICAL("Cannot lookup type name of \"" << index.name() << "\"",-1);
-    }
-    return _map[index];
-}
-}
-
-namespace fv{
-
-/**
- * Enumeration of different options that can be used to save Containers. Not
- * all options are allowed for all Containers.
- */
-enum SaveOption{
-    PNG = 0,
-    PDF = 1,
-    ROOT = 2
-};
-
-/**
- * Generic, untyped parent class of Container. Used to allow for placing
- * Containers of disparate types in common data structures.
- */
-class GenContainer{
-    private:
-        std::string name;
-        std::string desc;
-        std::vector<ObsFilter*> filters;
-    protected:
-        virtual void _fill() = 0;
-    public:
-        GenContainer(const std::string name, const std::string& desc)
-          :name(name),desc(desc) { }
-
-        GenContainer(const std::string name)
-          :GenContainer(name,"N/A"){ }
-
-        GenContainer* add_filter(GenValue* filter){
-            filters.push_back(static_cast<ObsFilter*>(filter));
-            return this;
-        }
-
-        void fill(){
-            for (auto filter : filters){
-                if (!filter->get_value()) return;
-            }
-            _fill();
-        }
-
-        void set_description(const std::string& description){
-            desc = description;
-        }
-
-        const std::string& get_name(){
-            return name;
-        }
-
-        virtual const std::string get_value_name(){
-            return "N/A";
-        }
-
-        virtual GenContainer* clone_as(const std::string& new_name) = 0;
-
-        virtual void save_as(const std::string& fname, const SaveOption& option) = 0;
-
-        virtual void save(const SaveOption& option=SaveOption::PNG) {
-            save_as(get_name(), option);
-        }
-};
-
-/**
- * A class that is used to "hold" values. When an event is loaded, the
- * associated filters on this container are checked. If they all pass, the
- * \c _fill() method is called and the Container can access the stored Value
- * object to process it. For example, if the Container is a ROOT Histogram
- * object, it may call <tt>container->Fill(value->get_value())</tt>.
- */
-template <typename H, typename V>
-class Container : public GenContainer{
-    protected:
-        H* container;
-        Value<V> *value;
-    public:
-        Container(const std::string& name, Value<V>* value)
-          :GenContainer(name),
-           container(nullptr),
-           value(value){ }
-
-        virtual ~Container(){
-            if (container != nullptr) delete container;
-        }
-
-        virtual H* get_container(){
-            return container;
-        }
-
-        virtual const std::string get_value_name(){
-            return value->get_name();
-        }
-};
-
-/**
- * Calculate the Mean of a Value over a series of observations. This class is
- * given a value of some type that supports addition and division(eg. a \c
- * float) and yields the mean value. Note that this implementation does \i not
- * support serialization so it is not incredibly useful. See the ROOT
- * Containers for Containers that support serialization using ROOT's
- * facilities.
- */
-template <typename T>
-class ContainerMean : public Container<T,T>{
-    private:
-        int count;
-        T sum;
-
-        void _fill(){
-            count++;
-            sum += this->value->get_value();
-        }
-    public:
-        ContainerMean(const std::string& name, Value<T>* value)
-          :Container<std::vector<T>,T>(name, value){
-            this->container = new T();
-        }
-
-        T* get_container(){
-            *(this->container) = sum/count;
-            return (this->container);
-        }
-
-        GenContainer* clone_as(const std::string& new_name){
-            return new ContainerMean(new_name, this->value);
-        }
-
-        void save_as(const std::string&) {
-            WARNING("Saving of ContainerMean objects not supported");
-        }
-};
-
-template<typename T>
-std::ostream& operator<< (std::ostream & out, const std::vector<T>& data) {
-    size_t len = data.size();
-    if (len == 0) out << "[]";
-    else {
-        out << "[" << data[0];
-        for (size_t i=1; i<len; i++) out << ", " << data[i];
-        out << "]";
-    }
-    return out ;
-}
-
-/**
- * Prints out the value registered to it
- */
-template <typename T>
-class Logger : public Container<std::ostream, T>{
-    private:
-    using to_str_t = std::function<void(T, std::ostream&)>;
-    to_str_t value_to_string;
-
-        static void default_to_string(T& t, std::ostream& os) {
-            os << t;
-        }
-
-        void _fill(){
-            auto& os = (*this->container);
-            std::stringstream vs;
-            os << this->get_name() << std::endl;
-            if (value_to_string != nullptr) value_to_string(this->value->get_value(), vs);
-            else                            default_to_string(this->value->get_value(), vs);
-            for (const char& c : vs.str()) {
-                if (c == '\n') os << std::endl << "  ";
-                else           os << c;
-            }
-            os << std::endl;
-        }
-
-    public:
-        Logger(Value<T>* value, std::ostream* out, to_str_t value_to_string = nullptr)
-          :Container<std::ostream,T>("Logger:" + value->get_name(), value),
-           value_to_string(value_to_string) {
-            this->container = out;
-        }
-
-        std::ostream* get_container(){
-            return this->container;
-        }
-
-        GenContainer* clone_as(const std::string& new_name){
-            return new Logger(this->value, this->container, value_to_string);
-        }
-
-        void save_as(const std::string&, const SaveOption&) { }
-};
-
-/**
- * Prints out the value registered to it
- */
-class FuncLogger : public GenContainer {
-    private:
-    std::ostream* os;
-    using to_str_t = std::function<void(std::ostream&)>;
-    to_str_t value_to_string;
-
-        void _fill(){
-            auto& os_ref = (*this->os);
-            std::stringstream vs;
-            os_ref << this->get_name() << std::endl << "  ";
-            value_to_string(vs);
-            for (const char& c : vs.str()) {
-                if (c == '\n') os_ref << std::endl << "  ";
-                else           os_ref << c;
-            }
-            os_ref << std::endl;
-        }
-
-    public:
-        FuncLogger(const std::string& name, std::ostream* os, to_str_t value_to_string)
-          :GenContainer("Logger:" + name),
-           value_to_string(value_to_string),
-           os(os) { }
-
-        std::ostream* get_container(){
-            return os;
-        }
-
-        GenContainer* clone_as(const std::string& new_name){
-            return new FuncLogger(new_name, this->os, value_to_string);
-        }
-
-        void save_as(const std::string&, const SaveOption&) { }
-};
-
-}
-#endif // container_hpp

+ 0 - 167
dataset.hpp

@@ -1,167 +0,0 @@
-/**
- * @file
- * @author  Caleb Fangmeier <caleb@fangmeier.tech>
- * @version 0.1
- *
- * @section LICENSE
- *
- *
- * MIT License
- *
- * Copyright (c) 2017 Caleb Fangmeier
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef dataset_hpp
-#define dataset_hpp
-#include <iostream>
-#include "value.hpp"
-#include "container.hpp"
-#include "memtrack.hpp"
-#include "config.hpp"
-#include "log.hpp"
-
-namespace fv{
-
-/*
- * A DataSet is a generic source of data that is used to populate
- * ObservedValues. For each ObservedValue, it is recommened that the DataSet
- * have a field whose value is updated when the load_next() method is called. A
- * pointer to this value is then passed during the creation of the
- * ObservedValue. It is important, therefore, that the location in memory of
- * the data not change from event to event.
- */
-class DataSet{
-    private:
-        void summary(){
-            INFO(GenValue::summary());
-            INFO(GenFunction::summary());
-        }
-
-        Value<int>* current_event_number;
-        int max_events;
-
-    protected:
-        std::map<std::string, GenContainer*> containers;
-        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;
-            for(auto container : containers)
-                value_map[container.first] = container.second->get_value_name();
-            return value_map;
-        }
-
-        std::map<std::string,std::string> get_function_name_impl_map(){
-            std::map<std::string, std::string> impl_map;
-            for(auto fn : GenFunction::function_registry)
-                if (fn.second != nullptr){
-                    impl_map[fn.first] = GenFunction::format_code(fn.second->get_impl());
-                }
-            return impl_map;
-        }
-    public:
-        DataSet() {
-            auto event_check = GenFunction::reg_func<int()>("event_number",
-                FUNC(([ds=this](){
-                    return ds->get_current_event();
-                })));
-            current_event_number = new BoundValue<int>(event_check);
-            set_max_events(fv::util::the_config->get_max_events());
-        }
-
-        void process(bool silent=false){
-            int events, current_event;
-            summary();
-            events = get_events();
-            if (max_events > 0) events = max_events;
-            if (!silent) std::cout << std::endl;
-            while( load_next() ){
-                current_event = get_current_event();
-                if (!silent){
-                    size_t m_used = getCurrentRSS() / 1024 / 1024;
-                    size_t m_peak = getPeakRSS() / 1024 / 1024;
-                    std::cout << "\rprocessing event: " << current_event+1 << "/" << events
-                    << ", " << m_used << "/" << m_peak << "MB used/peak"
-                    << " of file: " << get_current_file().filename << std::flush;
-                }
-                GenValue::reset();
-                for(auto con : containers){
-                    DEBUG("Filling container " << con.first << ".");
-                    con.second->fill();
-                }
-                if(max_events && current_event+1 >= max_events) break;
-            }
-            if (!silent) std::cout << " Finished!" << std::endl;
-        }
-
-        void set_max_events(const int& max_events){
-            this->max_events = max_events;
-        }
-
-        int get_max_events(){
-            return this->max_events;
-        }
-
-        virtual void save_all(){
-            for(auto container : containers)
-                container.second->save();
-        }
-
-        template<typename C, typename... ArgTypes>
-        C* register_container(ArgTypes... args){
-            C* container = new C(args...);
-            if (containers[container->get_name()] != nullptr){
-                CRITICAL("Container with name \""+container->get_name()+"\" already exists.", -1);
-            }
-            containers[container->get_name()] = container;
-            return container;
-        }
-
-        void cut_set(GenContainer* base_container, std::vector<std::pair<Value<bool>*, std::string>> filters){
-            for(auto p : filters){
-                Value<bool>* filter;
-                std::string new_name;
-                std::tie(filter, new_name) = p;
-                if (containers[new_name] != nullptr){
-                    CRITICAL("Container with name \""<<new_name<<"\" already exists.", -1);
-                }
-                auto new_container = base_container->clone_as(new_name);
-                new_container->add_filter(filter);
-                containers[new_container->get_name()] = new_container;
-            }
-        }
-
-        GenContainer* get_container(std::string container_name){
-            GenContainer* c = containers[container_name];
-            if (c == nullptr){
-                CRITICAL("Request for container \"" << container_name << "\" failed. Doesn't exist.", -1);
-            }
-            return c;
-        }
-
-        Value<int>* get_current_event_number(){
-            return current_event_number;
-        }
-};
-}
-#endif // dataset_hpp

+ 61 - 0
examples/config.yaml

@@ -0,0 +1,61 @@
+#max-events: 3000
+debug: false
+
+output-file: example.root
+source-files:
+    - filename: /home/caleb/Sources/PycharmProjects/EGamma/data/new_trees/trackingNtuple_1.root
+
+hist-params:
+    track_px:
+        label_x: "track_px"
+        nbins: 30
+        low: -300
+        high: 300
+        label_y: ""
+    eff_v_pt:
+        label_x: "eff_v_pt"
+        nbins: 30
+        low: 0
+        high: 300
+        label_y: ""
+    eff_v_eta:
+        label_x: "eff_v_eta"
+        nbins: 30
+        low: -3.0
+        high: 3.0
+        label_y: ""
+    eff_v_phi:
+        label_x: "eff_v_phi"
+        nbins: 30
+        low: -3.2
+        high: 3.2
+        label_y: ""
+
+    pur_v_pt:
+        label_x: "pur_v_pt"
+        nbins: 30
+        low: 0
+        high: 300
+        label_y: ""
+    pur_v_eta:
+        label_x: "pur_v_eta"
+        nbins: 30
+        low: -3.0
+        high: 3.0
+        label_y: ""
+    pur_v_phi:
+        label_x: "pur_v_phi"
+        nbins: 30
+        low: -3.2
+        high: 3.2
+        label_y: ""
+
+    n_hit_v_eta:
+        label_x: "eta"
+        nbins_x: 60
+        low_x: -3
+        high_x: 3
+        label_y: "Number of Pixel Hits"
+        nbins_y: 7
+        low_y: -0.5
+        high_y: 6.5

+ 117 - 58
examples/example1.cpp

@@ -34,64 +34,123 @@
  */
 
 #include <iostream>
-#include <utility>
-
-#include "filval/filval.hpp"
-
-int main(int argc, const char* argv[]){
-    // Initialize logging. Let's not worry about what is being logged right now
-    // and just redirect it to /dev/null so it doesn't appear on the screen.
-    fv::util::Log::init_logger("/dev/null", fv::util::LogPriority::kLogDebug);
-
-    // declare a helper function to print out a std::pair object
-    auto print_pair = [](fv::Value<std::pair<double, double>>* dp){
-        std::pair<double, double> p = dp->get_value();
-        std::cout << "(" << p.first << ", " << p.second << ")\n";
-    };
-
-    // These variables are the "Values" that will be observed. Think of these
-    // as sources of data that will be updated as new observations are loaded.
-    double x = 12;
-    double y = 13;
-
-    // This is where the fun begins. Here we declare a couple ObservedValue
-    // objects. these are basically just fancy wrappers around the x, and y
-    // variables declared above. They have the job of supplying the value
-    // stored by x and y when requested.
-    fv::ObservedValue<double> x_val("x", &x);
-    fv::ObservedValue<double> y_val("y", &y);
-
-    // Now that we have a few source values, let's compose them together into a
-    // pair. The fv api defines a function to do this: fv::pair. This function
-    // takes pointers to two Value objects and creates a new value that is a
-    // std::pair of these objects.
-    fv::Value<std::pair<double, double>>* dp = fv::pair(&x_val, &y_val);
-
-    // If we call the print_pair function that we declared earlier with the new
-    // value object, we can see that, indeed, we see the correct output
-    // (12, 13)
-    print_pair(dp);
-
-    // Now let's update the values of x and y to both be 2. Normally this job
-    // will be handled by a DataSet object which manages these variables, but
-    // we can do it here for now.
-    x = 2;
-    y = 2;
-
-    // Before we can access these new values through our value chain, we need
-    // to tell the values to "reset". One of the main features of FV is that
-    // each value is only calculated at most once per observation, regardless
-    // of how many times it is accessed. However, this means that we have to
-    // tell the objects when a new object has been loaded so it will actually
-    // do a re-calculation. In the case of dp, this means that it will
-    // re-access the values of x and y and create a new pair with the updated
-    // values.
-    fv::GenValue::reset();
-
-    // Call print_pair again just to verify that it gives the updated values,
-    // and indeed it does.
-    // (2, 2)
-    print_pair(dp);
+#include <vector>
+#include <TSystem.h>
+#include <dataset.hpp>
 
+#include <TROOT.h>
+#include <TChain.h>
+
+#include <filval.hpp>
+#include <root_filval.hpp>
+
+using namespace std;
+
+class TrackingNtuple {
+public :
+    TTree          *fChain;   //!pointer to the analyzed TTree or TChain
+    Int_t           fCurrent; //!current Tree number in a TChain
+
+    vector<float>   *trk_px;
+    vector<float>   *trk_py;
+    vector<float>   *trk_pz;
+
+    // List of branches
+    TBranch        *b_trk_px;   //!
+    TBranch        *b_trk_py;   //!
+    TBranch        *b_trk_pz;   //!
+
+    TrackingNtuple(TTree *tree=0);
+    virtual ~TrackingNtuple();
+    virtual Int_t    GetEntry(Long64_t entry);
+    virtual Long64_t LoadTree(Long64_t entry);
+    virtual void     Init(TTree *tree);
+};
+
+TrackingNtuple::TrackingNtuple(TTree *tree) : fChain(0) {
+// if parameter tree is not specified (or zero), connect the file
+// used to generate this class and read the Tree.
+    if (tree == 0) {
+        TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject("trackingNtuple_1.root");
+        if (!f || !f->IsOpen()) {
+            f = new TFile("trackingNtuple_1.root");
+        }
+        TDirectory * dir = (TDirectory*)f->Get("trackingNtuple_1.root:/trackingNtuple");
+        dir->GetObject("tree",tree);
+
+    }
+    Init(tree);
+}
+
+TrackingNtuple::~TrackingNtuple() {
+    if (!fChain) return;
+    delete fChain->GetCurrentFile();
+}
+
+Int_t TrackingNtuple::GetEntry(Long64_t entry) {
+    // Read contents of entry.
+    if (!fChain) return 0;
+    return fChain->GetEntry(entry);
+}
+
+Long64_t TrackingNtuple::LoadTree(Long64_t entry) {
+    // Set the environment to read one entry
+    if (!fChain) return -5;
+    Long64_t centry = fChain->LoadTree(entry);
+    if (centry < 0) return centry;
+    if (fChain->GetTreeNumber() != fCurrent) {
+        fCurrent = fChain->GetTreeNumber();
+    }
+    return centry;
+}
+
+void TrackingNtuple::Init(TTree *tree) {
+    // Set object pointer
+    trk_px = 0;
+    trk_py = 0;
+    trk_pz = 0;
+    // Set branch addresses and branch pointers
+    if (!tree) return;
+    fChain = tree;
+    fCurrent = -1;
+    fChain->SetMakeClass(1);
+
+    fChain->SetBranchAddress("trk_px", &trk_px, &b_trk_px);
+    fChain->SetBranchAddress("trk_py", &trk_py, &b_trk_py);
+    fChain->SetBranchAddress("trk_pz", &trk_pz, &b_trk_pz);
+}
+
+void run(bool silent) {
+    using namespace fv;
+    using namespace fv_root;
+    auto file_list = the_config->get_source_files();
+    string output_filename = the_config->get_output_filename();
+    TreeDataSet<TrackingNtuple> tds(output_filename, file_list, "trackingNtuple/tree");
+
+    auto& px = *tds.track_branch_obj<vector<float>>("trk_py");
+
+    auto& cont = *tds.register_container<ContainerTH1<int>>("trk_py", "Track Px", TH1Params::lookup("track_px"));
+
+    while(tds.next(silent)) {
+        for (const float& p : px()) {
+            cont.fill(p);
+        }
+    }
+
+    tds.save_all();
+}
+
+int main(int argc, char* argv[]){
+    using namespace fv_util;
+    ArgParser args(argc, argv);
+    bool silent = args.cmdOptionExists("-s");
+    if(args.cmdOptionExists("-c")) {
+        init_config(args.getCmdOption("-c"));
+        init_log(fv_util::LogPriority::kLogInfo);
+//        gSystem->Load("libfilval.so");
+        run(silent);
+    } else {
+        cout << "Usage: ./" << argv[0] << " (-s) -c config_file.yaml" << endl;
+    }
     return 0;
 }

+ 0 - 89
filter.hpp

@@ -1,89 +0,0 @@
-/**
- * @file
- * @author  Caleb Fangmeier <caleb@fangmeier.tech>
- * @version 0.1
- *
- * @section LICENSE
- *
- *
- * MIT License
- *
- * Copyright (c) 2017 Caleb Fangmeier
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * @section DESCRIPTION
- * 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
- * actually places data into the container or not. This file contains a variety
- * of generic filters to aide in analysis.
- */
-#ifndef filter_h
-#define filter_h
-#include <iostream>
-#include <functional>
-#include "value.hpp"
-namespace fv {
-
-class ObsFilter : public DerivedValue<bool>{
-    private:
-        Function<bool()>* filter_function;
-
-        void update_value(){
-            value = (*filter_function)();
-        }
-
-    public:
-        ObsFilter(const std::string& name, std::function<bool()> filter_function, const std::string& impl="")
-          :DerivedValue<bool>(name),
-           filter_function(GenFunction::reg_func<bool()>("filter::"+name, filter_function, impl)){ }
-};
-
-/** Return a new filter that is the conjuction of a vector of source filters
- */
-ObsFilter* all(const std::vector<ObsFilter*>&& fs){
-    if(fs.size() == 0){
-        return nullptr;
-    } else{
-        std::stringstream ss;
-        ss << fs[0]->get_name();
-        for(size_t i=1; i<fs.size(); i++) ss << "AND" << fs[i]->get_name();
-        return new ObsFilter(ss.str(), [fs](){
-                return std::all_of(std::begin(fs), std::end(fs), [](ObsFilter* f){return f->get_value();});
-        });
-    }
-}
-
-/** Return a new filter that is the disjunction of a vector of source filters
- */
-ObsFilter* any(const std::vector<ObsFilter*>&& fs){
-    if(fs.size() == 0){
-        return nullptr;
-    } else{
-        std::stringstream ss;
-        ss << fs[0]->get_name();
-        for(size_t i=1; i<fs.size(); i++) ss << "OR" << fs[i]->get_name();
-        return new ObsFilter(ss.str(), [fs](){
-                return std::any_of(std::begin(fs), std::end(fs), [](ObsFilter* f){return f->get_value();});
-        });
-    }
-}
-
-}
-#endif // filter_h

+ 0 - 14
filval.hpp

@@ -1,14 +0,0 @@
-#ifndef filval_hpp
-#define filval_hpp
-#define FILVAL_VERSION_MAJOR @FILVAL_VERSION_MAJOR@
-#define FILVAL_VERSION_MINOR @FILVAL_VERSION_MINOR@
-#include "value.hpp"
-#include "filter.hpp"
-#include "container.hpp"
-#include "dataset.hpp"
-#include "log.hpp"
-#include "argparse.hpp"
-#include "config.hpp"
-#include "memtrack.hpp"
-#include "api.hpp"
-#endif // filval_hpp

+ 1 - 1
argparse.hpp

@@ -36,7 +36,7 @@
 #include <algorithm>
 #include <string>
 #include <vector>
-namespace fv::util{
+namespace fv_util{
 class ArgParser{
     private:
         std::vector <std::string> tokens;

+ 32 - 29
config.hpp

@@ -35,49 +35,52 @@
 
 #include "yaml-cpp/yaml.h"
 
-namespace fv::util {
+namespace fv_util {
 struct DataFileDescriptor{
     std::string filename;
     std::string label;
     std::string category;
     int file_number;
+    int n_events;
 
-    DataFileDescriptor():filename(""), label(""),category(""),file_number(-1) { }
+    DataFileDescriptor():filename(""), label(""),category(""),file_number(-1), n_events(-1){ }
 
-    DataFileDescriptor(const std::string filename, const std::string label, const std::string category)
-      :filename(filename), label(label),category(category),file_number(-1) { }
+    DataFileDescriptor(const std::string filename, const std::string label, const std::string category, const int n_events)
+      :filename(filename), label(label),category(category),file_number(-1), n_events(n_events) { }
 
-    DataFileDescriptor(const std::string filename, const std::string label, const std::string category, const int file_number)
-      :filename(filename), label(label),category(category),file_number(file_number) { }
+    DataFileDescriptor(const std::string filename, const std::string label, const std::string category, const int file_number, const int n_events)
+      :filename(filename), label(label),category(category),file_number(file_number), n_events(n_events) { }
 };
 }
 
 namespace YAML {
-template<>
-struct convert<fv::util::DataFileDescriptor> {
-  static Node encode(const fv::util::DataFileDescriptor& rhs) {
-    Node node;
-    node["filename"] = rhs.filename;
-    node["label"] = rhs.label;
-    node["category"] = rhs.category;
-    return node;
-  }
-
-  static bool decode(const Node& node, fv::util::DataFileDescriptor& rhs) {
-    if(!node.IsMap()) {
-      return false;
-    }
-
-    if(!node["filename"]) return false;
-    rhs.filename = node["filename"].as<std::string>();
-    if(node["label"]) rhs.label = node["label"].as<std::string>();
-    if(node["category"]) rhs.category = node["category"].as<std::string>();
-    return true;
-  }
-};
+    template<>
+    struct convert<fv_util::DataFileDescriptor> {
+        static Node encode(const fv_util::DataFileDescriptor &rhs) {
+            Node node;
+            node["filename"] = rhs.filename;
+            node["label"] = rhs.label;
+            node["category"] = rhs.category;
+            node["n_events"] = rhs.n_events;
+            return node;
+        }
+
+        static bool decode(const Node &node, fv_util::DataFileDescriptor &rhs) {
+            if (!node.IsMap()) {
+                return false;
+            }
+
+            if (!node["filename"]) return false;
+            rhs.filename = node["filename"].as<std::string>();
+            if (node["label"]) rhs.label = node["label"].as<std::string>();
+            if (node["category"]) rhs.category = node["category"].as<std::string>();
+            if (node["n_events"]) rhs.n_events = node["n_events"].as<int>();
+            return true;
+        }
+    };
 }
 
-namespace fv::util {
+namespace fv_util {
 class Config{
     private:
         std::string input_filename;

+ 188 - 0
include/container.hpp

@@ -0,0 +1,188 @@
+/**
+ * @file
+ * @author  Caleb Fangmeier <caleb@fangmeier.tech>
+ * @version 0.1
+ *
+ * @section LICENSE
+ *
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Caleb Fangmeier
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef container_hpp
+#define container_hpp
+
+#include <typeindex>
+#include <vector>
+#include <map>
+
+#include "value.hpp"
+
+template
+class std::vector<std::vector<float> >;
+
+template
+class std::vector<std::vector<int> >;
+
+
+namespace fv::util {
+    std::string get_type_name(const std::type_index &index) {
+        std::map<std::type_index, std::string> _map;
+        // Add to this list as needed :)
+        _map[typeid(int)] = "int";
+        _map[typeid(unsigned int)] = "unsigned int";
+        _map[typeid(float)] = "float";
+        _map[typeid(double)] = "double";
+        _map[typeid(std::vector<int>)] = "std::vector<int>";
+        _map[typeid(std::vector<float>)] = "std::vector<float>";
+        _map[typeid(std::pair<std::vector<float>, std::vector<float>>)] = "std::pair<std::vector<float>,std::vector<float>>";
+        _map[typeid(std::vector<std::pair<float, int>>)] = "std::vector<std::pair<float,int>>";
+        _map[typeid(std::map<std::string, std::string>)] = "std::map<std::string,std::string>";
+
+        if (_map[index] == "") {
+            CRITICAL("Cannot lookup type name of \"" << index.name() << "\"", -1);
+        }
+        return _map[index];
+    }
+}
+
+namespace fv {
+
+/**
+ * Enumeration of different options that can be used to save Containers. Not
+ * all options are allowed for all Containers.
+ */
+    enum SaveOption {
+        PNG = 0,
+        PDF = 1,
+        ROOT = 2
+    };
+
+/**
+ * Generic, untyped parent class of Container. Used to allow for placing
+ * Containers of disparate types in common data structures.
+ */
+    class GenContainer {
+    private:
+        std::string name;
+        std::string desc;
+    public:
+        GenContainer(const std::string name, const std::string &desc)
+                : name(name), desc(desc) {}
+
+        GenContainer(const std::string name)
+                : GenContainer(name, "N/A") {}
+
+        void set_description(const std::string &description) {
+            desc = description;
+        }
+
+        const std::string &get_name() {
+            return name;
+        }
+
+        virtual const std::string get_value_name() {
+            return "N/A";
+        }
+
+        virtual GenContainer *clone_as(const std::string &new_name) = 0;
+
+        virtual void save_as(const std::string &fname, const SaveOption &option) = 0;
+
+        virtual void save(const SaveOption &option = SaveOption::PNG) {
+            save_as(get_name(), option);
+        }
+    };
+
+/**
+ * A class that is used to "hold" values. When an event is loaded the
+ * \c fill() method is called and the Container can access the stored Value
+ * object to process it. For example, if the Container is a ROOT Histogram
+ * object, it may call <tt>container->Fill(value->get_value())</tt>.
+ */
+    template<typename H, typename V>
+    class Container : public GenContainer {
+    protected:
+        H *container;
+    public:
+        Container(const std::string &name)
+                : GenContainer(name),
+                  container(nullptr) {}
+
+        virtual ~Container() {
+            if (container != nullptr) delete container;
+        }
+
+        virtual H *get_container() {
+            return container;
+        }
+
+        virtual void fill(const V&) = 0;
+    };
+
+/**
+ * Prints out the value registered to it
+ */
+    template<typename T>
+    class Logger : public Container<std::ostream, T> {
+    private:
+        using to_str_t = std::function<void(T, std::ostream &)>;
+        to_str_t value_to_string;
+        std::string logger_name;
+
+        static void default_to_string(T &t, std::ostream &os) {
+            os << t;
+        }
+
+    public:
+        void fill(const T& the_value) {
+            auto &os = (*this->container);
+            std::stringstream vs;
+            os << this->get_name() << std::endl;
+            if (value_to_string != nullptr) value_to_string(the_value, vs);
+            else default_to_string(the_value, vs);
+            for (const char &c : vs.str()) {
+                if (c == '\n') os << std::endl << "  ";
+                else os << c;
+            }
+            os << std::endl;
+        }
+
+        Logger(std::ostream *out, const std::string& logger_name, to_str_t value_to_string = nullptr)
+                : Container<std::ostream, T>("Logger:" + logger_name),
+                  value_to_string(value_to_string), logger_name(logger_name) {
+            this->container = out;
+        }
+
+        std::ostream *get_container() {
+            return this->container;
+        }
+
+        GenContainer *clone_as(const std::string &new_name) {
+            return new Logger(this->container, logger_name, value_to_string);
+        }
+
+        void save_as(const std::string &, const SaveOption &) {}
+    };
+
+}
+#endif // container_hpp

+ 125 - 0
include/dataset.hpp

@@ -0,0 +1,125 @@
+/**
+ * @file
+ * @author  Caleb Fangmeier <caleb@fangmeier.tech>
+ * @version 0.1
+ *
+ * @section LICENSE
+ *
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Caleb Fangmeier
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef dataset_hpp
+#define dataset_hpp
+#include <iostream>
+#include "value.hpp"
+#include "container.hpp"
+#include "memtrack.hpp"
+#include "config.hpp"
+#include "log.hpp"
+
+#include "TFile.h"
+
+namespace fv {
+
+/*
+ * A DataSet is a generic source of data that is used to populate
+ * ObservedValues. For each ObservedValue, it is recommened that the DataSet
+ * have a field whose value is updated when the load_next() method is called. A
+ * pointer to this value is then passed during the creation of the
+ * ObservedValue. It is important, therefore, that the location in memory of
+ * the data not change from event to event.
+ */
+    class DataSet {
+    private:
+        void summary() {
+            INFO(GenValue::summary());
+        }
+
+        int max_events;
+
+    protected:
+        std::map<std::string, GenContainer *> containers;
+
+        virtual int get_events() = 0;
+
+        virtual int get_current_event() = 0;
+
+        virtual fv_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;
+            for (auto container : containers)
+                value_map[container.first] = container.second->get_value_name();
+            return value_map;
+        }
+
+        virtual bool load_next() = 0;
+
+    public:
+        bool next(bool print_status=true) {
+            if(print_status) {
+                size_t m_used = fv_util::getCurrentRSS() / 1024 / 1024;
+                size_t m_peak = fv_util::getPeakRSS() / 1024 / 1024;
+                std::cout << "\rprocessing event: " << get_current_event() + 1 << "/" << get_events()
+                          << ", " << m_used << "/" << m_peak << "MB used/peak"
+                          << " of file: " << get_current_file().filename << std::flush;
+            }
+            if (max_events && get_current_event() + 1 >= max_events) return false;
+            GenValue::reset();
+            return load_next();
+        }
+
+        void set_max_events(const int &max_events) {
+            this->max_events = max_events;
+        }
+
+        int get_max_events() {
+            return this->max_events;
+        }
+
+        virtual void save_all() {
+            for (auto container : containers)
+                container.second->save();
+        }
+
+        template<typename C, typename... ArgTypes>
+        C *register_container(ArgTypes... args) {
+            C *container = new C(args...);
+            if (containers[container->get_name()] != nullptr) {
+                CRITICAL("Container with name \"" + container->get_name() + "\" already exists.", -1);
+            }
+            containers[container->get_name()] = container;
+            return container;
+        }
+
+        GenContainer *get_container(std::string container_name) {
+            GenContainer *c = containers[container_name];
+            if (c == nullptr) {
+                CRITICAL("Request for container \"" << container_name << "\" failed. Doesn't exist.", -1);
+            }
+            return c;
+        }
+    };
+
+}
+#endif // dataset_hpp

+ 32 - 0
include/filval.hpp

@@ -0,0 +1,32 @@
+#ifndef filval_hpp
+#define filval_hpp
+#define FILVAL_VERSION_MAJOR @FILVAL_VERSION_MAJOR@
+#define FILVAL_VERSION_MINOR @FILVAL_VERSION_MINOR@
+#include "value.hpp"
+#include "container.hpp"
+#include "dataset.hpp"
+#include "log.hpp"
+#include "argparse.hpp"
+#include "config.hpp"
+#include "memtrack.hpp"
+
+namespace fv {
+    template<typename T>
+    Value<T> *lookup(const std::string &name) {
+        Value<T> *tv = GenValue::get_value<T>(name);
+        if (tv == nullptr) {
+            CRITICAL("Could not find alias or value \"" << name << "\"."
+                                                        << " I'll tell you the ones I know about." << std::endl
+                                                        << GenValue::summary(), -1);
+        }
+        return tv;
+    }
+
+    template<typename T>
+    bool check_exists(const std::string name) {
+        Value<T> *tv = GenValue::get_value<T>(name);
+        return tv != nullptr;
+    }
+}
+
+#endif // filval_hpp

+ 7 - 7
log.hpp

@@ -40,7 +40,7 @@
 
 #include "config.hpp"
 
-namespace fv::util{
+namespace fv_util {
 enum LogPriority {
     kLogEmergency = 7,  // system is unusable
     kLogAlert     = 6,  // action must be taken immediately
@@ -52,12 +52,12 @@ enum LogPriority {
     kLogDebug     = 0   // debug-level message
 };
 
-#define CRITICAL(x,y) std::clog << fv::util::LogPriority::kLogCritical << __FILE__ << "@L" << __LINE__ << " :: " << x << std::flush; std::cout << "Errors encountered! See log file for details."<<std::endl;exit(y)
-#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 << x << std::flush
-#define DEBUGL(x) std::clog << fv::util::LogPriority::kLogDebug << __FILE__ << "@L" << __LINE__ << " :: " << x << std::flush
+#define CRITICAL(x,y) std::clog << fv_util::LogPriority::kLogCritical << __FILE__ << "@L" << __LINE__ << " :: " << x << std::flush; std::cout << "Errors encountered! See log file for details."<<std::endl;exit(y)
+#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 << 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

+ 43 - 0
include/memtrack.hpp

@@ -0,0 +1,43 @@
+#ifndef memtrack_hpp
+#define memtrack_hpp
+/*
+ * Author:  David Robert Nadeau
+ * Site:    http://NadeauSoftware.com/
+ * License: Creative Commons Attribution 3.0 Unported License
+ *          http://creativecommons.org/licenses/by/3.0/deed.en_US
+ */
+
+#include <unistd.h>
+#include <sys/resource.h>
+#include <stdio.h>
+
+namespace fv_util {
+
+/**
+ * Returns the peak (maximum so far) resident set size (physical
+ * memory use) measured in bytes.
+ */
+    size_t getPeakRSS() {
+        struct rusage rusage;
+        getrusage(RUSAGE_SELF, &rusage);
+        return (size_t) (rusage.ru_maxrss * 1024L);
+    }
+
+/**
+ * Returns the current resident set size (physical memory use) measured
+ * in bytes.
+ */
+    size_t getCurrentRSS() {
+        long rss = 0L;
+        FILE *fp = NULL;
+        if ((fp = fopen("/proc/self/statm", "r")) == NULL)
+            return (size_t) 0L;      /* Can't open? */
+        if (fscanf(fp, "%*s%ld", &rss) != 1) {
+            fclose(fp);
+            return (size_t) 0L;      /* Can't read? */
+        }
+        fclose(fp);
+        return (size_t) rss * (size_t) sysconf(_SC_PAGESIZE);
+    }
+} // fv
+#endif //  memtrack_hpp

+ 365 - 0
include/value.hpp

@@ -0,0 +1,365 @@
+/**
+ * @file
+ * @author  Caleb Fangmeier <caleb@fangmeier.tech>
+ * @version 0.1
+ *
+ * @section LICENSE
+ *
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Caleb Fangmeier
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * @section DESCRIPTION
+ * This header defines a set of generic classes that wrap up "values". In
+ * essence, a Value<T> object is just something that contains a value of type T
+ * and can provide it when requested. The usefulness stems from composing
+ * values together with calculations. This enables very clear dependency
+ * mapping and a way to know clearly how every value was arrived at. This could
+ * be used to, for example, automatically generate commentary for plots that
+ * explain the exect calculation used to create it. Or easily making a series
+ * of plots contrasting different values that have been composed slightly
+ * differently.
+ */
+#ifndef value_hpp
+#define value_hpp
+
+#include <algorithm>
+#include <functional>
+#include <initializer_list>
+#include <iomanip>
+#include <iostream>
+#include <limits>
+#include <map>
+#include <sstream>
+#include <tuple>
+#include <typeindex>
+#include <utility>
+#include <vector>
+
+#include "log.hpp"
+#include "config.hpp"
+
+/**
+ * The namespace containing all filval classes and functions.
+ */
+namespace fv {
+
+    template<typename T>
+    class Value;
+
+/**
+ * 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:
+        /**
+         * The name of the value.
+         * This is used to allow for dynamic lookup of
+         * values based on their name via GenValue::get_value.
+         */
+        std::string name;
+
+    protected:
+        /**
+         * Mark the internal value as invalid. This is needed for DerivedValue
+         * to force a recalculation of the internal value when a new
+         * observation is loaded into memory. It is called automatically for
+         * all GenValue objects when reset is called.
+         */
+        bool value_valid;
+
+        void _reset() {
+            this->value_valid = false;
+        }
+
+        /**
+         * A static mapping containing all created Value objects.
+         * Every value object must have a unique name, and this name is used as
+         * a key in values to that object. This is used to enable more dynamic
+         * creation of objects as well as avoiding the uneccesary passing of
+         * pointers.
+         */
+        inline static std::map<std::pair<const std::type_index, const std::string>, GenValue *> values;
+
+        /**
+         * Composite value names are typically nested. This makes complex
+         * values have rather unwieldy names. Therefore, one can declare
+         * aliases which allow for more human-usable names to be used. When a
+         * value is requested by name, an alias with that value takes precidence
+         * over a name with that value.
+         */
+        inline static std::map<std::pair<const std::type_index, const std::string>, GenValue *> aliases;
+
+    public:
+        GenValue(const std::type_index &&ti, const std::string &name, const std::string &alias)
+                : name(name), value_valid(false) {
+            if (alias != "")
+                INFO("Registered value: \"" << name << "\" with alias: \"" << alias << "\"");
+            else
+                INFO("Registered value: \"" << name);
+            values[std::make_pair(ti, name)] = this;
+            if (alias != "")
+                GenValue::alias(ti, alias, this);
+        }
+
+        const std::string &get_name() {
+            return name;
+        }
+
+        static void reset() {
+            for (auto val : values) {
+                if (val.second != nullptr) {
+                    val.second->_reset();
+                }
+            }
+        }
+
+        template<typename T>
+        static Value<T> *get_value(const std::string &name) {
+            const std::type_index &ti = typeid(T);
+            auto lookup_id = std::make_pair(ti, name);
+            if (aliases[lookup_id] != nullptr)
+                return (Value<T> *) aliases[lookup_id];
+            else
+                return (Value<T> *) values[lookup_id];
+        }
+
+
+        static void alias(const std::type_index &ti, const std::string &name, GenValue *value) {
+            auto lookup_id = std::make_pair(ti, name);
+            if (aliases[lookup_id] != nullptr) {
+                WARNING("WARNING: alias \"" << name << "\" overrides previous entry.");
+            }
+            aliases[lookup_id] = value;
+        }
+
+        template<typename T>
+        static void alias(const std::string &name, Value<T> *value) {
+            alias(typeid(T), name, value);
+        }
+
+        static std::string summary() {
+            std::stringstream ss;
+            ss << "The following values have been created:" << std::endl;
+            for (auto item : values) {
+                auto &key = item.first;
+                auto &value = item.second;
+                if (value == nullptr) continue;
+                ss << "\tVALUE::\"" << key.second << "\" at address " << value << std::endl;
+            }
+            ss << "And these aliases:" << std::endl;
+            for (auto item : aliases) {
+                auto &key = item.first;
+                auto &value = item.second;
+                std::string orig("VOID");
+                if (value == nullptr) continue;
+                for (auto v_item : values) {
+                    auto &v_value = v_item.second;
+                    if (v_value == value) {
+                        orig = v_value->get_name();
+                        break;
+                    }
+                }
+                ss << "\tALIAS::\"" << key.second << "\" referring to \"" << orig << "\"" << std::endl;
+            }
+            return ss.str();
+        }
+
+        friend std::ostream &operator<<(std::ostream &os, const GenValue &gv);
+    };
+
+    std::ostream &operator<<(std::ostream &os, GenValue &gv) {
+        os << gv.get_name();
+        return os;
+    }
+
+
+/**
+ * A templated value.
+ * In order to facilitate run-time creation of analysis routines, it is
+ * necessary to have some ability to get and store *values*. Values can either
+ * be directly taken from some original data source (i.e. ObservedValue), or
+ * they can be a function of some other set of values (i.e. DerivedValue). They
+ * template class T of Value<T> is the type of thing that is returned upon
+ * calling get_value().
+ */
+    template<typename T>
+    class Value : public GenValue {
+    public:
+        Value(const std::string &name, const std::string &alias = "")
+                : GenValue(typeid(T), name, alias) {}
+
+        /** Calculate, if necessary, and return the value held by this object.
+         */
+        virtual T &operator() () = 0;
+    };
+
+
+/**
+ * A value supplied by the dataset, not derived.
+ * An ObservedValue is the interface to your dataset. Upon creation, an
+ * ObservedValue is given a pointer to an object of type T. When an observation
+ * is loaded into memory, the value at the location referenced by that pointer
+ * must be updated with the associated data from that observation. This is the
+ * responsibility of whatever DataSet implementation is being used. This object
+ * then will read that data and return it when requested.
+ */
+    template<typename T>
+    class ObservedValue : public Value<T> {
+    private:
+        T *val_ref;
+
+    public:
+        ObservedValue(const std::string &name, T *val_ref, const std::string &alias = "")
+                : Value<T>(name, alias),
+                  val_ref(val_ref) {}
+
+        static std::string fmt_name(const std::string &name) {
+            return name;
+        }
+
+        T &operator() (){
+            if (!this->value_valid) {
+                if (fv_util::debug_on) {
+                    std::cout << "Calculating Value: " << this->get_name() << std::endl;
+                }
+                this->value_valid = true;
+            }
+            return *val_ref;
+        }
+    };
+
+
+/**
+ * A Value derived from some other Values, not directly from the dataset.
+ * A DerivedValue is generally defined as some function of other Value objects.
+ * For example, a Pair is a function of two other Value objects that makes a
+ * pair of them. Note that these other Value objects are free to be either
+ * ObservedValues or other DerivedValues.
+ *
+ * It is desireable from a performance standpoint that each DerivedValue be
+ * calculated no more than once per observation. Therefore, when a get_value is
+ * called on a DerivedValue, it first checks whether the value that it holds is
+ * **valid**, meaning it has already been calculated for this observation. If
+ * so, it simply returns the value. If not, the update_value function is called
+ * to calculate the value. and then the newly calculated value is marked as
+ * valid and returned.
+ */
+    template<typename T>
+    class DerivedValue : public Value<T> {
+    protected:
+        T value;
+
+        /**
+         * Updates the internal value.
+         * This function should be overridden by any child class to do the
+         * actual work of updating value based on whatever rules the class
+         * chooses. Normally, this consists of geting the values from some
+         * associated Value objects, doing some calculation on them, and
+         * storing the result in value.
+         */
+        virtual void update_value() = 0;
+
+    public:
+        DerivedValue(const std::string &name, const std::string &alias = "")
+                : Value<T>(name, alias) {}
+
+        T &operator() () {
+            if (!this->value_valid) {
+                if (fv_util::debug_on) {
+                    std::cout << "Calculating Value: " << this->get_name() << std::endl;
+                }
+                update_value();
+                this->value_valid = true;
+            }
+            return value;
+        }
+    };
+
+
+/**
+ * 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, const std::string alias = "")
+                : DerivedValue<T *>(name, alias) {
+            this->value = ptr;
+        }
+    };
+
+
+/**
+ * Used for when the value is an object whose location in memory is changing,
+ * but one has a pointer to a pointer that points to the always updated
+ * location. (Mainly when reading objects such as stl containers from a root
+ * TTree)
+ */
+    template<typename T>
+    class ObjectValue : public DerivedValue<T> {
+    protected:
+        T **obj_pointer;
+
+        void update_value() {
+            this->value = **obj_pointer;
+        }
+
+    public:
+        ObjectValue(const std::string &name, T **ptr, const std::string alias = "")
+                : DerivedValue<T>(name, alias),
+                  obj_pointer(ptr) {}
+    };
+
+
+/**
+ * A Value which always returns the same value, supplied in the constructor.
+ */
+    template<typename T>
+    class ConstantValue : public DerivedValue<T> {
+    protected:
+        void update_value() {}
+
+    public:
+        static std::string fmt_name(const std::string &name) {
+            return "const::" + name;
+        }
+
+        ConstantValue(const std::string &name, T const_value, const std::string alias = "")
+                : DerivedValue<T>(fmt_name(name), alias) {
+            this->value = const_value;
+        }
+    };
+
+}
+#endif // value_hpp

+ 0 - 118
memtrack.hpp

@@ -1,118 +0,0 @@
-#ifndef memtrack_hpp
-#define memtrack_hpp
-/*
- * Author:  David Robert Nadeau
- * Site:    http://NadeauSoftware.com/
- * License: Creative Commons Attribution 3.0 Unported License
- *          http://creativecommons.org/licenses/by/3.0/deed.en_US
- */
-
-#if defined(_WIN32)
-#include <windows.h>
-#include <psapi.h>
-#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
-#include <unistd.h>
-#include <sys/resource.h>
-
-#if defined(__APPLE__) && defined(__MACH__)
-#include <mach/mach.h>
-#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
-#include <fcntl.h>
-#include <procfs.h>
-#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
-#include <stdio.h>
-#endif
-
-#else
-#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
-#endif
-
-
-
-namespace fv{
-
-/**
- * Returns the peak (maximum so far) resident set size (physical
- * memory use) measured in bytes, or zero if the value cannot be
- * determined on this OS.
- */
-size_t getPeakRSS( )
-{
-#if defined(_WIN32)
-    /* Windows -------------------------------------------------- */
-    PROCESS_MEMORY_COUNTERS info;
-    GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
-    return (size_t)info.PeakWorkingSetSize;
-
-#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
-    /* AIX and Solaris ------------------------------------------ */
-    struct psinfo psinfo;
-    int fd = -1;
-    if ( (fd = open( "/proc/self/psinfo", O_RDONLY )) == -1 )
-        return (size_t)0L;      /* Can't open? */
-    if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) )
-    {
-        close( fd );
-        return (size_t)0L;      /* Can't read? */
-    }
-    close( fd );
-    return (size_t)(psinfo.pr_rssize * 1024L);
-
-#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
-    /* BSD, Linux, and OSX -------------------------------------- */
-    struct rusage rusage;
-    getrusage( RUSAGE_SELF, &rusage );
-#if defined(__APPLE__) && defined(__MACH__)
-    return (size_t)rusage.ru_maxrss;
-#else
-    return (size_t)(rusage.ru_maxrss * 1024L);
-#endif
-
-#else
-    /* Unknown OS ----------------------------------------------- */
-    return (size_t)0L;          /* Unsupported. */
-#endif
-}
-
-/**
- * Returns the current resident set size (physical memory use) measured
- * in bytes, or zero if the value cannot be determined on this OS.
- */
-size_t getCurrentRSS( )
-{
-#if defined(_WIN32)
-    /* Windows -------------------------------------------------- */
-    PROCESS_MEMORY_COUNTERS info;
-    GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
-    return (size_t)info.WorkingSetSize;
-
-#elif defined(__APPLE__) && defined(__MACH__)
-    /* OSX ------------------------------------------------------ */
-    struct mach_task_basic_info info;
-    mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
-    if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO,
-        (task_info_t)&info, &infoCount ) != KERN_SUCCESS )
-        return (size_t)0L;      /* Can't access? */
-    return (size_t)info.resident_size;
-
-#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
-    /* Linux ---------------------------------------------------- */
-    long rss = 0L;
-    FILE* fp = NULL;
-    if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL )
-        return (size_t)0L;      /* Can't open? */
-    if ( fscanf( fp, "%*s%ld", &rss ) != 1 )
-    {
-        fclose( fp );
-        return (size_t)0L;      /* Can't read? */
-    }
-    fclose( fp );
-    return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE);
-
-#else
-    /* AIX, BSD, Solaris, and Unknown OS ------------------------ */
-    return (size_t)0L;          /* Unsupported. */
-#endif
-}
-} // fv
-#endif //  memtrack_hpp

+ 0 - 63
root/api.hpp

@@ -1,63 +0,0 @@
-#ifndef ROOT_API_HPP
-#define ROOT_API_HPP
-#include <string>
-#include <vector>
-#include <tuple>
-#include "filval/api.hpp"
-#include "filval/root/value.hpp"
-namespace fv::root{
-
-    decltype(auto)
-    lorentz_vectors(Value<std::vector<float>>* pt, Value<std::vector<float>>* eta,
-                    Value<std::vector<float>>* phi, Value<std::vector<float>>* mass,
-                    const std::string& alias=""){
-        typedef std::vector<TLorentzVector> type;
-        const std::string& name = root::LorentzVectors::fmt_name(pt, eta, phi, mass);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new root::LorentzVectors(pt, eta, phi, mass, alias);
-    }
-
-    decltype(auto)
-    lorentz_vectors(const std::string& pt_name, const std::string& eta_name,
-                    const std::string& phi_name, const std::string& mass_name,
-                    const std::string& alias=""){
-        return lorentz_vectors(lookup<std::vector<float>>(pt_name), lookup<std::vector<float>>(eta_name),
-                               lookup<std::vector<float>>(phi_name), lookup<std::vector<float>>(mass_name),
-                               alias);
-    }
-
-    decltype(auto)
-    energies(Value<std::vector<TLorentzVector>>* vectors, const std::string& alias="") {
-        typedef std::vector<float> type;
-        const std::string& name = root::Energies::fmt_name(vectors);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new root::Energies(vectors, alias);
-    }
-
-    decltype(auto)
-    energies(const std::string& vectors_name, const std::string& alias="") {
-        return energies(lookup<std::vector<TLorentzVector>>(vectors_name), alias);
-    }
-
-    template<typename... DataTypes>
-    decltype(auto)
-    mva_data(Value<bool>* is_training, Value<bool>* is_signal, Value<double>* weight,
-             const std::pair<std::string, Value<DataTypes>*>&&... data_vals) {
-        typedef typename root::MVAData<DataTypes...> mva_type;
-        typedef typename mva_type::type type;
-        std::string alias="";
-        const std::string& name = mva_type::fmt_name(is_training, is_signal, weight,
-                                                     std::forward<const std::pair<std::string,Value<DataTypes>*>>(data_vals)...);
-        if (check_exists<type>(name))
-            return lookup<type>(name);
-        else
-            return (Value<type>*)new mva_type(is_training, is_signal, weight,
-                                                     std::forward<const std::pair<std::string,Value<DataTypes>*>>(data_vals)...);
-    }
-
-}
-#endif // ROOT_API_HPP

+ 0 - 561
root/container.hpp

@@ -1,561 +0,0 @@
-#ifndef root_container_hpp
-#define root_container_hpp
-#include <iostream>
-#include <utility>
-#include <map>
-
-#include "TROOT.h"
-#include "TFile.h"
-#include "TCanvas.h"
-#include "TGraph.h"
-#include "TH1.h"
-#include "TH2.h"
-
-#include "TMVA/Factory.h"
-#include "TMVA/DataLoader.h"
-#include "TMVA/DataSetInfo.h"
-
-#include "filval/container.hpp"
-
-namespace fv::root::util{
-    /**
-     * Save a TObject. The TObject will typically be a Histogram or Graph object,
-     * but can really be any TObject. The SaveOption can be used to specify how to
-     * save the file.
-     */
-    void save_as(TObject* container, const std::string& fname, const SaveOption& option = SaveOption::PNG) {
-
-        auto save_img = [](TObject* container, const std::string& fname){
-            TCanvas* c1 = new TCanvas("c1");
-            container->Draw();
-            c1->Draw();
-            c1->SaveAs(fname.c_str());
-            delete c1;
-        };
-
-        auto save_bin = [](TObject* container){
-            INFO("Saving object: " << container->GetName() << " into file " << gDirectory->GetName());
-            container->Write(container->GetName(), TObject::kOverwrite);
-        };
-
-        switch(option){
-            case PNG:
-                save_img(container, fname+".png"); break;
-            case PDF:
-                save_img(container, fname+".pdf"); break;
-            case ROOT:
-                save_bin(container); break;
-            default:
-                break;
-        }
-    }
-
-
-    /**
-     * Saves an STL container into a ROOT file. ROOT knows how to serialize STL
-     * containers, but it needs the *name* of the type of the container, eg.
-     * std::map<int,int> to be able to do this. In order to generate this name at
-     * run-time, the fv::util::get_type_name function uses RTTI to get type info
-     * and use it to look up the proper name.
-     *
-     * For nexted containers, it is necessary to generate the CLING dictionaries
-     * for each type at compile time to enable serialization. To do this, add the
-     * type definition into the LinkDef.hpp header file.
-     */
-    void save_as_stl(void* container, const std::string& type_name,
-                      const std::string& obj_name,
-                      const SaveOption& option = SaveOption::PNG) {
-        switch(option){
-            case PNG:
-                INFO("Cannot save STL container " << type_name <<" as png");
-                break;
-            case PDF:
-                INFO("Cannot save STL container " << type_name <<" as pdf");
-                break;
-            case ROOT:
-                /* DEBUG("Writing object \"" << obj_name << "\" of type \"" << type_name << "\"\n"); */
-                gDirectory->WriteObjectAny(container, type_name.c_str(), obj_name.c_str());
-                break;
-            default:
-                break;
-        }
-    }
-}
-
-namespace fv::root {
-
-struct TH1Params{
-    std::string label_x;
-    int nbins;
-    double low;
-    double high;
-    std::string label_y;
-
-    static TH1Params lookup(const std::string&& param_key){
-        auto hist_params = fv::util::the_config->get("hist-params");
-        if(!hist_params[param_key]){
-            CRITICAL("Key \"" << param_key << "\" does not exist under hist-params in supplied config file. Add it!", true);
-        }
-        else{
-            auto params = hist_params[param_key];
-            return TH1Params({params["label_x"].as<std::string>(),
-                              params["nbins"].as<int>(),
-                              params["low"].as<double>(),
-                              params["high"].as<double>(),
-                              params["label_y"].as<std::string>()
-                              });
-
-        }
-    }
-};
-
-template <typename V>
-class _ContainerTH1 : public Container<TH1,V>{
-    private:
-        void _fill(){
-            if (this->container == nullptr){
-                if (this->value == nullptr){
-                    CRITICAL("Container: \"" << this->get_name() << "\" has a null Value object. "
-                             << "Probably built with imcompatible type",-1);
-                }
-                this->container = new TH1D(this->get_name().c_str(), this->title.c_str(),
-                                           params.nbins, params.low, params.high);
-                this->container->SetXTitle(params.label_x.c_str());
-                this->container->SetYTitle(params.label_y.c_str());
-            }
-            _do_fill();
-        }
-
-    protected:
-        std::string title;
-        TH1Params params;
-
-        virtual void _do_fill() = 0;
-
-    public:
-        explicit _ContainerTH1(const std::string& name, Value<V>* value,
-                               const std::string& title,
-                               const TH1Params& params)
-          :Container<TH1,V>(name, value),
-           title(title),
-           params(params) { }
-
-        void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
-            util::save_as(this->get_container(), fname, option);
-        }
-};
-
-template <typename V>
-class ContainerTH1 : public _ContainerTH1<V>{
-    using _ContainerTH1<V>::_ContainerTH1;
-    void _do_fill(){
-        this->container->Fill(this->value->get_value());
-    }
-    public:
-        GenContainer* clone_as(const std::string& new_name){
-            return new ContainerTH1<V>(new_name, this->value, this->title, this->params);
-        }
-};
-
-template <typename V>
-class ContainerTH1Many : public _ContainerTH1<std::vector<V>>{
-    using _ContainerTH1<std::vector<V>>::_ContainerTH1;
-    void _do_fill(){
-        for(const V &x : this->value->get_value())
-            this->container->Fill(x);
-    }
-    public:
-        GenContainer* clone_as(const std::string& new_name){
-            return new ContainerTH1Many<V>(new_name, this->value, this->title, this->params);
-        }
-};
-
-struct TH2Params{
-    std::string label_x;
-    int nbins_x;
-    double low_x;
-    double high_x;
-    std::string label_y;
-    int nbins_y;
-    double low_y;
-    double high_y;
-
-    static TH2Params lookup(const std::string&& param_key){
-        auto hist_params = fv::util::the_config->get("hist-params");
-        if(!hist_params[param_key]){
-            CRITICAL("Key \"" << param_key << "\" does not exist under hist-params in supplied config file. Add it!", true);
-        }
-        else{
-            auto params = hist_params[param_key];
-            return TH2Params({params["label_x"].as<std::string>(),
-                              params["nbins_x"].as<int>(),
-                              params["low_x"].as<double>(),
-                              params["high_x"].as<double>(),
-                              params["label_y"].as<std::string>(),
-                              params["nbins_y"].as<int>(),
-                              params["low_y"].as<double>(),
-                              params["high_y"].as<double>()
-                              });
-
-        }
-    }
-};
-
-template <typename V>
-class _ContainerTH2 : public Container<TH2,std::pair<V,V>>{
-    private:
-        void _fill(){
-            if (this->container == nullptr){
-                if (this->value == nullptr){
-                    CRITICAL("Container: \"" << this->get_name() << "\" has a null Value object. "
-                             << "Probably built with imcompatible type",-1);
-                }
-                this->container = new TH2D(this->get_name().c_str(), this->title.c_str(),
-                                           params.nbins_x, params.low_x, params.high_x,
-                                           params.nbins_y, params.low_y, params.high_y);
-                this->container->SetXTitle(params.label_x.c_str());
-                this->container->SetYTitle(params.label_y.c_str());
-            }
-            _do_fill(this->value->get_value());
-        }
-
-    protected:
-        std::string title;
-        TH2Params params;
-
-        virtual void _do_fill(const std::pair<V,V>& val) = 0;
-
-    public:
-        explicit _ContainerTH2(const std::string& name, Value<std::pair<V, V>>* value,
-                               const std::string& title,
-                               TH2Params params)
-          :Container<TH2,std::pair<V,V>>(name, value),
-           title(title),
-           params(params) { }
-
-        void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
-            util::save_as(this->get_container(), fname, option);
-        }
-
-};
-
-template <typename V>
-class ContainerTH2 : public _ContainerTH2<V>{
-    using _ContainerTH2<V>::_ContainerTH2;
-    void _do_fill(const std::pair<V,V>& val){
-        this->container->Fill(val.first,val.second);
-    }
-    public:
-        GenContainer* clone_as(const std::string& new_name){
-            return new ContainerTH2<V>(new_name, this->value, this->title, this->params);
-        }
-};
-
-template <typename V>
-class ContainerTH2Many : public _ContainerTH2<std::vector<V>>{
-    using _ContainerTH2<std::vector<V>>::_ContainerTH2;
-    void _do_fill(const std::pair<std::vector<V>,std::vector<V>>& val){
-        int min_size = std::min(val.first.size(), val.second.size());
-        for(int i=0; i<min_size; i++)
-            this->container->Fill(val.first[i],val.second[i]);
-    }
-    public:
-        GenContainer* clone_as(const std::string& new_name){
-            return new ContainerTH2Many<V>(new_name, this->value, this->title, this->params);
-        }
-};
-
-template <typename V>
-class ContainerTGraph : public Container<TGraph,std::pair<V,V>>{
-    private:
-        std::vector<V> x_data;
-        std::vector<V> y_data;
-        std::string title;
-        bool data_modified;
-        void _fill(){
-            auto val = this->value->get_value();
-            x_data.push_back(val.first);
-            y_data.push_back(val.second);
-            data_modified = true;
-        }
-    public:
-        ContainerTGraph(const std::string& name, const std::string& title, Value<std::pair<V, V>>* value)
-          :Container<TGraph,std::pair<V,V>>(name, value),
-           data_modified(false){
-            this->container = new TGraph();
-           }
-
-        TGraph* get_container(){
-            if (data_modified){
-                delete this->container;
-                this->container = new TGraph(x_data.size(), x_data.data(), y_data.data());
-                this->container->SetName(this->get_name().c_str());
-                this->container->SetTitle(title.c_str());
-                data_modified = false;
-            }
-            return this->container;
-        }
-
-        GenContainer* clone_as(const std::string& new_name){
-            return new ContainerTGraph<V>(new_name, this->title, this->value);
-        }
-
-        void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
-            util::save_as(get_container(), fname, option);
-        }
-};
-
-template <typename V>
-class Vector : public Container<std::vector<V>,V>{
-    private:
-
-        void _fill(){
-            this->container->push_back(this->value->get_value());
-        }
-    public:
-        Vector(const std::string& name, Value<V>* value)
-          :Container<std::vector<V>,V>(name, value){
-            this->container = new std::vector<V>;
-        }
-
-        GenContainer* clone_as(const std::string& new_name){
-            return new Vector<V>(new_name, this->value);
-        }
-
-        void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
-            std::string type_name = "std::vector<"+fv::util::get_type_name(typeid(V))+">";
-            util::save_as_stl(this->get_container(), type_name, this->get_name(), option);
-        }
-};
-
-template <typename V>
-class VectorMany : public Container<std::vector<V>,std::vector<V>>{
-    private:
-
-        void _fill(){
-            for(const V& val: this->value->get_value())
-                this->container->push_back(val);
-        }
-    public:
-        VectorMany(const std::string& name, Value<std::vector<V>>* value)
-          :Container<std::vector<V>,std::vector<V>>(name, value){
-            this->container = new std::vector<V>;
-        }
-
-        GenContainer* clone_as(const std::string& new_name){
-            return new VectorMany<V>(new_name, this->value);
-        }
-
-        void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
-            std::string type_name = "std::vector<"+fv::util::get_type_name(typeid(V))+">";
-            util::save_as_stl(this->get_container(), type_name, this->get_name(), option);
-        }
-};
-
-template <typename V, typename D>
-class _Counter : public Container<std::map<D,int>,V>{
-    public:
-        explicit _Counter(const std::string& name, Value<V>* value)
-          :Container<std::map<D,int>,V>(name, value) {
-            this->container = new std::map<D,int>;
-        }
-
-        void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
-            std::string type_name = "std::map<"+fv::util::get_type_name(typeid(D))+",int>";
-            util::save_as_stl(this->get_container(), type_name, this->get_name(), option);
-        }
-};
-
-
-/**
- * A Counter that keeps a mapping of the number of occurances of each input
- * value.
- */
-template <typename V>
-class Counter : public _Counter<V,V>{
-    using _Counter<V,V>::_Counter;
-        void _fill(){
-            (*this->container)[this->value->get_value()]++;
-        }
-    public:
-        GenContainer* clone_as(const std::string& new_name){
-            return new Counter<V>(new_name, this->value);
-        }
-};
-
-/**
- * Same as Counter but accepts multiple values per fill.
- */
-template <typename V>
-class CounterMany : public _Counter<std::vector<V>,V>{
-    using _Counter<std::vector<V>,V>::_Counter;
-        void _fill(){
-            for(V& val : this->value->get_value())
-                (*this->container)[val]++;
-        }
-    public:
-        GenContainer* clone_as(const std::string& new_name){
-            return new CounterMany<V>(new_name, this->value);
-        }
-};
-
-class PassCount : public Container<int,bool>{
-    private:
-        void _fill() {
-            if(this->value->get_value()) (*this->container)++;
-        }
-    public:
-        PassCount(const std::string& name, Value<bool>* value)
-          :Container<int,bool>(name, value){
-            this->container = new int(0);
-        }
-
-        GenContainer* clone_as(const std::string& new_name){
-            return new PassCount(new_name, this->value);
-        }
-
-        void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
-            //ROOT(hilariously) cannot serialize basic data types, we wrap this
-            //in a vector.
-            std::vector<int> v({*this->get_container()});
-            util::save_as_stl(&v, "std::vector<int>", this->get_name(), option);
-        }
-};
-
-
-template <typename T>
-class EfficiencyContainer : public Container<TH1F, std::vector<T>>{
-    private:
-        std::function<bool(T)>* selector;  // Selects whether object is up for consideration
-        std::function<bool(T)>* predicate; // Says whether the object passes the efficiency criteria
-        std::function<float(T)>* get_val;  // Returns a floating point value from the object that is actually
-                                           // used in the histogram
-        bool write_num_den;
-        TH1F num;
-        TH1F den;
-        TH1F eff;
-
-        TH1Params params;
-
-        void _fill(){
-            for (auto& obj : this->value->get_value()) {
-                if (selector == nullptr or (*selector)(obj)) {
-                    float val = (*get_val)(obj);
-                    den.Fill(val);
-                    if ((*predicate)(obj)) {
-                        num.Fill(val);
-                    }
-                }
-            }
-        }
-
-    public:
-        EfficiencyContainer(const std::string& name, Value<std::vector<T>>* value, TH1Params params,
-                            std::function<bool(T)>* selector, std::function<bool(T)>* predicate,
-                            std::function<float(T)>* get_val, bool write_num_den=false)
-          :Container<TH1F, std::vector<T>>(name, value),
-           num{(name+"_num").c_str(), (name+"_num").c_str(), params.nbins, params.low, params.high},
-           den{(name+"_den").c_str(), (name+"_den").c_str(), params.nbins, params.low, params.high},
-           eff{name.c_str(), name.c_str(), params.nbins, params.low, params.high},
-           selector(selector), predicate(predicate), get_val(get_val), params(params), write_num_den(write_num_den) {
-            num.SetXTitle(params.label_x.c_str()); num.SetYTitle(params.label_y.c_str());
-            den.SetXTitle(params.label_x.c_str()); den.SetYTitle(params.label_y.c_str());
-            eff.SetXTitle(params.label_x.c_str()); eff.SetYTitle(params.label_y.c_str());
-            this->container = &eff;
-           }
-
-        TH1F* get_container() {
-            eff.Sumw2();
-            eff.Divide(&num, &den, 1, 1, "B");
-            return this->container;
-        }
-
-        GenContainer* clone_as(const std::string& new_name){
-            return new EfficiencyContainer<T>(new_name, this->value, this->params, selector, predicate, get_val);
-        }
-
-        void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
-            util::save_as(this->get_container(), fname, option);
-            if (write_num_den) {
-                util::save_as(&num, fname, option);
-                util::save_as(&den, fname, option);
-            }
-        }
-};
-
-template <typename... ArgTypes>
-class MVA : public Container<TMVA::DataLoader,typename MVAData<ArgTypes...>::type>{
-    private:
-        std::vector<std::pair<std::string,std::string>> methods;
-
-        std::string cut;
-        std::string opt;
-
-        void _fill(){
-            std::tuple<ArgTypes...> t;
-            typename MVAData<ArgTypes...>::type& event = this->value->get_value();
-            bool is_training, is_signal;
-            double weight;
-            std::tie(is_training, is_signal, weight, t) = event;
-            std::vector<double> v = t2v<double>(t);
-            if (is_signal){
-                if (is_training){
-                    this->container->AddSignalTrainingEvent(v, weight);
-                } else {
-                    this->container->AddSignalTestEvent(v, weight);
-                }
-            } else {
-                if (is_training){
-                    this->container->AddBackgroundTrainingEvent(v, weight);
-                } else {
-                    this->container->AddBackgroundTestEvent(v, weight);
-                }
-            }
-        }
-    public:
-        MVA(const std::string& name, MVAData<ArgTypes...>* value, const std::string& cut = "", const std::string& opt = "")
-          :Container<TMVA::DataLoader,typename MVAData<ArgTypes...>::type>(name, value),
-           cut(cut), opt(opt) {
-            this->container = new TMVA::DataLoader(name);
-            for (std::pair<std::string,char>& p : value->get_label_types()){
-                this->container->AddVariable(p.first, p.second);
-            }
-        }
-
-        void add_method(const std::string& method_name, const std::string& method_params) {
-            methods.push_back(std::make_pair(method_name, method_params));
-        }
-
-        GenContainer* clone_as(const std::string& new_name){
-            auto mva = new MVA<ArgTypes...>(new_name, (MVAData<ArgTypes...>*)this->value, this->cut, this->opt);
-            mva->methods = methods;
-            return mva;
-        }
-
-        void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
-            TFile* outputFile = gDirectory->GetFile();
-
-            this->container->PrepareTrainingAndTestTree(cut.c_str(), opt.c_str());
-            TMVA::Factory *factory = new TMVA::Factory("TMVAClassification", outputFile,
-                                                       "!V:!Silent:Color:DrawProgressBar:Transformations=I;D;P;G,D:AnalysisType=Classification");
-
-            TMVA::Types& types = TMVA::Types::Instance();
-            for(auto& p : methods){
-                std::string method_name, method_params;
-                std::tie(method_name, method_params)  = p;
-                TMVA::Types::EMVA method_type = types.GetMethodType(method_name);
-                factory->BookMethod(this->container, method_type, method_name, method_params);
-            }
-
-            // Train MVAs using the set of training events
-            factory->TrainAllMethods();
-            // Evaluate all MVAs using the set of test events
-            factory->TestAllMethods();
-            // Evaluate and compare performance of all configured MVAs
-            factory->EvaluateAllMethods();
-
-            delete factory;
-        }
-};
-}
-#endif // root_container_hpp

+ 0 - 27
root/filter.hpp

@@ -1,27 +0,0 @@
-#ifndef root_filter_hpp
-#define root_filter_hpp
-#include "value.hpp"
-#include "TLorentzVector.h"
-
-namespace fv::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

+ 0 - 7
root/filval.hpp

@@ -1,7 +0,0 @@
-#ifndef root_filval_hpp
-#define root_filval_hpp
-#include "filval/root/value.hpp"
-#include "filval/root/container.hpp"
-#include "filval/root/api.hpp"
-#include "filval/root/dataset.hpp"
-#endif // root_filval_hpp

root/LinkDef.hpp → root/include/LinkDef.hpp


root/README.md → root/include/README.md


+ 377 - 0
root/include/root_container.hpp

@@ -0,0 +1,377 @@
+#ifndef root_container_hpp
+#define root_container_hpp
+
+#include <iostream>
+#include <utility>
+#include <map>
+
+#include "TROOT.h"
+#include "TFile.h"
+#include "TCanvas.h"
+#include "TGraph.h"
+#include "TH1.h"
+#include "TH2.h"
+
+#include "TMVA/Factory.h"
+#include "TMVA/DataLoader.h"
+#include "TMVA/DataSetInfo.h"
+
+#include "container.hpp"
+
+namespace fv_root_util {
+    using namespace fv;
+    /**
+     * Save a TObject. The TObject will typically be a Histogram or Graph object,
+     * but can really be any TObject. The SaveOption can be used to specify how to
+     * save the file.
+     */
+    void save_as(TObject *container, const std::string &fname, const SaveOption &option = SaveOption::PNG) {
+
+        auto save_img = [](TObject *container, const std::string &fname) {
+            TCanvas *c1 = new TCanvas("c1");
+            container->Draw();
+            c1->Draw();
+            c1->SaveAs(fname.c_str());
+            delete c1;
+        };
+
+        auto save_bin = [](TObject *container) {
+            INFO("Saving object: " << container->GetName() << " into file " << gDirectory->GetName());
+            container->Write(container->GetName(), TObject::kOverwrite);
+        };
+
+        switch (option) {
+            case SaveOption::PNG:
+                save_img(container, fname + ".png");
+                break;
+            case SaveOption::PDF:
+                save_img(container, fname + ".pdf");
+                break;
+            case SaveOption::ROOT:
+                save_bin(container);
+                break;
+            default:
+                break;
+        }
+    }
+
+
+    /**
+     * Saves an STL container into a ROOT file. ROOT knows how to serialize STL
+     * containers, but it needs the *name* of the type of the container, eg.
+     * std::map<int,int> to be able to do this. In order to generate this name at
+     * run-time, the fv::util::get_type_name function uses RTTI to get type info
+     * and use it to look up the proper name.
+     *
+     * For nexted containers, it is necessary to generate the CLING dictionaries
+     * for each type at compile time to enable serialization. To do this, add the
+     * type definition into the LinkDef.hpp header file.
+     */
+    void save_as_stl(void *container, const std::string &type_name,
+                     const std::string &obj_name,
+                     const SaveOption &option = SaveOption::PNG) {
+        switch (option) {
+            case SaveOption::PNG:
+                INFO("Cannot save STL container " << type_name << " as png");
+                break;
+            case SaveOption::PDF:
+                INFO("Cannot save STL container " << type_name << " as pdf");
+                break;
+            case SaveOption::ROOT:
+                /* DEBUG("Writing object \"" << obj_name << "\" of type \"" << type_name << "\"\n"); */
+                gDirectory->WriteObjectAny(container, type_name.c_str(), obj_name.c_str());
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+namespace fv_root {
+    using namespace fv;
+
+    struct TH1Params {
+        std::string label_x;
+        int nbins;
+        double low;
+        double high;
+        std::string label_y;
+
+        static TH1Params lookup(const std::string &&param_key) {
+            auto hist_params = fv_util::the_config->get("hist-params");
+            if (!hist_params[param_key]) {
+                CRITICAL(
+                        "Key \"" << param_key << "\" does not exist under hist-params in supplied config file. Add it!",
+                        true);
+            } else {
+                auto params = hist_params[param_key];
+                return TH1Params({params["label_x"].as<std::string>(),
+                                  params["nbins"].as<int>(),
+                                  params["low"].as<double>(),
+                                  params["high"].as<double>(),
+                                  params["label_y"].as<std::string>()
+                                 });
+
+            }
+        }
+    };
+
+    template<typename V>
+    class ContainerTH1 : public Container<TH1, V> {
+    protected:
+        std::string title;
+        TH1Params params;
+
+    public:
+        ContainerTH1(const std::string &name, const std::string &title, const TH1Params &params)
+                : Container<TH1, V>(name), title(title), params(params) {
+            this->container = new TH1D(this->get_name().c_str(), this->title.c_str(),
+                                       params.nbins, params.low, params.high);
+            this->container->SetXTitle(params.label_x.c_str());
+            this->container->SetYTitle(params.label_y.c_str());
+        }
+
+        void fill(const V &v) {
+            this->container->Fill(v);
+        }
+
+        void fill_weight(const V &v, const float &weight) {
+            this->container->Fill(v, weight);
+        }
+
+        void fill_many(const std::vector<V> &vs) {
+            for (const V &v : vs) {
+                this->container->Fill(v);
+            }
+        }
+
+        void save_as(const std::string &fname, const SaveOption &option = SaveOption::PNG) {
+            if (this->get_container() == nullptr) {
+                WARNING("Container " << this->get_name() << " never filled, cowardly refusing to save");
+            } else {
+                fv_root_util::save_as(this->get_container(), fname, option);
+            }
+        }
+
+        GenContainer *clone_as(const std::string &new_name) {
+            return new ContainerTH1<V>(new_name, this->title, this->params);
+        }
+    };
+
+    struct TH2Params {
+        std::string label_x;
+        int nbins_x;
+        double low_x;
+        double high_x;
+        std::string label_y;
+        int nbins_y;
+        double low_y;
+        double high_y;
+
+        static TH2Params lookup(const std::string &&param_key) {
+            auto hist_params = fv_util::the_config->get("hist-params");
+            if (!hist_params[param_key]) {
+                CRITICAL(
+                        "Key \"" << param_key << "\" does not exist under hist-params in supplied config file. Add it!",
+                        true);
+            } else {
+                auto params = hist_params[param_key];
+                return TH2Params({params["label_x"].as<std::string>(),
+                                  params["nbins_x"].as<int>(),
+                                  params["low_x"].as<double>(),
+                                  params["high_x"].as<double>(),
+                                  params["label_y"].as<std::string>(),
+                                  params["nbins_y"].as<int>(),
+                                  params["low_y"].as<double>(),
+                                  params["high_y"].as<double>()
+                                 });
+
+            }
+        }
+    };
+
+    template<typename V>
+    class ContainerTH2 : public Container<TH2, V> {
+    private:
+        std::string title;
+        TH2Params params;
+    public:
+        ContainerTH2(const std::string &name, const std::string &title, TH2Params params)
+                : Container<TH2, V>(name), title(title), params(params) {
+            this->container = new TH2D(this->get_name().c_str(), this->title.c_str(),
+                                       params.nbins_x, params.low_x, params.high_x,
+                                       params.nbins_y, params.low_y, params.high_y);
+            this->container->SetXTitle(params.label_x.c_str());
+            this->container->SetYTitle(params.label_y.c_str());
+        }
+
+        void fill(const V& x, const V& y) {
+            this->container->Fill(x, y);
+        }
+
+        void fill_weight(const V& x, const V& y, const V& weight) {
+            this->container->Fill(x, y, weight);
+        }
+
+        void save_as(const std::string &fname, const SaveOption &option = SaveOption::PNG) {
+            fv_root_util::save_as(this->get_container(), fname, option);
+        }
+
+    };
+
+    template<typename V>
+    class ContainerTGraph : public Container<TGraph, V> {
+    private:
+        std::vector<V> x_data;
+        std::vector<V> y_data;
+        std::string title;
+        bool data_modified;
+
+
+    public:
+        ContainerTGraph(const std::string &name, const std::string &title)
+                : Container<TGraph, V>(name), data_modified(false) {
+            this->container = new TGraph();
+        }
+
+        TGraph *get_container() {
+            if (data_modified) {
+                delete this->container;
+                this->container = new TGraph(x_data.size(), x_data.data(), y_data.data());
+                this->container->SetName(this->get_name().c_str());
+                this->container->SetTitle(title.c_str());
+                data_modified = false;
+            }
+            return this->container;
+        }
+
+        GenContainer *clone_as(const std::string &new_name) {
+            return new ContainerTGraph<V>(new_name, this->title);
+        }
+
+        void save_as(const std::string &fname, const SaveOption &option = SaveOption::PNG) {
+            fv_root_util::save_as(get_container(), fname, option);
+        }
+
+        void fill(const V& x, const V& y) {
+            x_data.push_back(x);
+            y_data.push_back(y);
+            data_modified = true;
+        }
+    };
+
+    template<typename V>
+    class Vector : public Container<std::vector<V>, V> {
+    public:
+        Vector(const std::string &name)
+                : Container<std::vector<V>, V>(name) {
+            this->container = new std::vector<V>;
+        }
+
+        void fill(const V& v) {
+            this->container->push_back(v);
+        }
+
+        GenContainer *clone_as(const std::string &new_name) {
+            return new Vector<V>(new_name);
+        }
+
+        void save_as(const std::string &fname, const SaveOption &option = SaveOption::PNG) {
+            std::string type_name = "std::vector<" + fv::util::get_type_name(typeid(V)) + ">";
+            fv_root_util::save_as_stl(this->get_container(), type_name, this->get_name(), option);
+        }
+    };
+
+/**
+ * A Counter that keeps a mapping of the number of occurances of each input
+ * value.
+ */
+    template<typename V>
+    class Counter : public Container<std::map<V, size_t>, V> {
+    public:
+        Counter(const std::string &name)
+                : Container<std::map<V, size_t>, V>(name) {
+            this->container = new std::map<V, size_t>;
+        }
+
+        void save_as(const std::string &fname, const SaveOption &option = SaveOption::PNG) {
+            std::string type_name = "std::map<" + fv::util::get_type_name(typeid(V)) + ",int>";
+            fv_root_util::save_as_stl(this->get_container(), type_name, this->get_name(), option);
+        }
+
+        void fill(const V& v) {
+            (*this->container)[v]++;
+        }
+
+        GenContainer *clone_as(const std::string &new_name) {
+            return new Counter<V>(new_name);
+        }
+    };
+
+
+    template<typename T>
+    class EfficiencyContainer : public Container<TH1F, std::vector<T>> {
+    private:
+        std::function<bool(T)> *selector;  // Selects whether object is up for consideration
+        std::function<bool(T)> *predicate; // Says whether the object passes the efficiency criteria
+        std::function<float(T)> *get_val;  // Returns a floating point value from the object that is actually
+        // used in the histogram
+        bool write_num_den;
+        TH1F num;
+        TH1F den;
+        TH1F eff;
+
+        TH1Params params;
+
+        void _fill() {
+            for (auto &obj : this->value->get_value()) {
+                if (selector == nullptr or (*selector)(obj)) {
+                    float val = (*get_val)(obj);
+                    den.Fill(val);
+                    if ((*predicate)(obj)) {
+                        num.Fill(val);
+                    }
+                }
+            }
+        }
+
+    public:
+        EfficiencyContainer(const std::string &name, Value<std::vector<T>> *value, TH1Params params,
+                            std::function<bool(T)> *selector, std::function<bool(T)> *predicate,
+                            std::function<float(T)> *get_val, bool write_num_den = false)
+                : Container<TH1F, std::vector<T>>(name, value),
+                  num{(name + "_num").c_str(), (name + "_num").c_str(), params.nbins, params.low, params.high},
+                  den{(name + "_den").c_str(), (name + "_den").c_str(), params.nbins, params.low, params.high},
+                  eff{name.c_str(), name.c_str(), params.nbins, params.low, params.high},
+                  selector(selector), predicate(predicate), get_val(get_val), params(params),
+                  write_num_den(write_num_den) {
+            num.SetXTitle(params.label_x.c_str());
+            num.SetYTitle(params.label_y.c_str());
+            den.SetXTitle(params.label_x.c_str());
+            den.SetYTitle(params.label_y.c_str());
+            eff.SetXTitle(params.label_x.c_str());
+            eff.SetYTitle(params.label_y.c_str());
+            this->container = &eff;
+        }
+
+        TH1F *get_container() {
+            eff.Sumw2();
+            eff.Divide(&num, &den, 1, 1, "B");
+            return this->container;
+        }
+
+        GenContainer *clone_as(const std::string &new_name) {
+            return new EfficiencyContainer<T>(new_name, this->value, this->params, selector, predicate, get_val);
+        }
+
+        void save_as(const std::string &fname, const SaveOption &option = SaveOption::PNG) {
+            fv_root_util::save_as(this->get_container(), fname, option);
+            if (write_num_den) {
+                fv_root_util::save_as(&num, fname, option);
+                fv_root_util::save_as(&den, fname, option);
+            }
+        }
+    };
+
+}
+#endif // root_container_hpp

+ 72 - 78
root/dataset.hpp

@@ -36,50 +36,52 @@
 
 #include "TChain.h"
 
-#include "filval/filval.hpp"
-#include "filval/root/filval.hpp"
+#include "filval.hpp"
+#include "root_filval.hpp"
 
-using namespace std;
-using namespace fv;
-using namespace fv::util;
-using namespace fv::root;
 
-template<typename TREE_CLASS>
-class TreeDataSet : public DataSet{
+namespace fv_root {
+    using namespace std;
+    using namespace fv;
+    using namespace fv_util;
+
+    template<typename TREE_CLASS>
+    class TreeDataSet : public DataSet {
     private:
         // Maps filenames to data label, eg. "TTTT", or "TTZ"
-        std::map<std::string,std::string> input_labels;
+        std::map<std::string, std::string> input_labels;
         // Maps filenames to data category. Either "signal" or "background"
-        std::map<std::string,std::string> input_categories;
+        std::map<std::string, std::string> input_categories;
         std::string output_filename;
-        std::map<std::string,DataFileDescriptor> file_descriptors;
-        TFile* output_file;
-        TREE_CLASS* tree_obj;
+        std::map<std::string, DataFileDescriptor> file_descriptors;
+        TFile *output_file;
+        TREE_CLASS *tree_obj;
         long next_entry;
         long nentries;
 
-        bool load_next(){
-            if (next_entry >= nentries) return false;
-            tree_obj->LoadTree(next_entry);
-            tree_obj->GetEntry(next_entry);
-            ++next_entry;
-            return true;
-        }
-
-        int get_events(){
+        int get_events() {
             return nentries;
         }
 
-        int get_current_event(){
-            return next_entry-1;
+        int get_current_event() {
+            return next_entry - 1;
         }
 
-        fv::util::DataFileDescriptor& get_current_file(){
-            TFile* file = tree_obj->fChain->GetCurrentFile();
+        fv_util::DataFileDescriptor &get_current_file() {
+            TFile *file = tree_obj->fChain->GetCurrentFile();
             std::string filename = file->GetName();
             return file_descriptors.at(filename);
         }
 
+        bool load_next() {
+            if (next_entry >= nentries) return false;
+            tree_obj->LoadTree(next_entry);
+            tree_obj->GetEntry(next_entry);
+            ++next_entry;
+            return true;
+        }
+
+
         /* void save_event_count(){ */
         /*     std::map<std::string,int> event_counts; */
         /*     std::map<std::string,float> xsecs; */
@@ -104,14 +106,14 @@ class TreeDataSet : public DataSet{
 
     public:
 
-        TreeDataSet(const std::string& output_filename, const std::vector<DataFileDescriptor>& dfds,
-                    const std::string& tree_name)
-          :DataSet(),
-           output_filename(output_filename),
-           next_entry(0) {
-            TChain* chain = new TChain(tree_name.c_str());
+        TreeDataSet(const std::string &output_filename, const std::vector<DataFileDescriptor> &dfds,
+                    const std::string &tree_name)
+                : DataSet(),
+                  output_filename(output_filename),
+                  next_entry(0) {
+            TChain *chain = new TChain(tree_name.c_str());
             int cnt = 0;
-            for(const DataFileDescriptor& dfd : dfds){
+            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)); */
@@ -124,98 +126,90 @@ class TreeDataSet : public DataSet{
             nentries = tree_obj->fChain->GetEntries();
             output_file = TFile::Open(output_filename.c_str(), "RECREATE");
             set_branch_status("*", false);
-          }
+        }
 
-        ~TreeDataSet(){
+        ~TreeDataSet() {
             /* save_event_count_and_xsection(); */
             output_file->Close();
         }
 
-        const std::string& get_current_event_category() const{
-            TFile* file = tree_obj->fChain->GetCurrentFile();
+        const std::string &get_current_event_category() const {
+            TFile *file = tree_obj->fChain->GetCurrentFile();
             std::string filename = file->GetName();
             return input_categories.at(filename);
         }
 
-        const std::string& get_current_event_label() const{
-            TFile* file = tree_obj->fChain->GetCurrentFile();
+        const std::string &get_current_event_label() const {
+            TFile *file = tree_obj->fChain->GetCurrentFile();
             std::string filename = file->GetName();
             return input_labels.at(filename);
         }
 
-        template <typename T>
-        Value<T>* track_branch(const std::string& bname){
-            TBranch* branch = tree_obj->fChain->GetBranch(bname.c_str());
-            if (branch == nullptr){
+        template<typename T>
+        Value<T> *track_branch(const std::string &bname) {
+            TBranch *branch = tree_obj->fChain->GetBranch(bname.c_str());
+            if (branch == nullptr) {
                 CRITICAL("Branch: " << bname << " does not exist in input tree.", -1);
             }
-            T* bref = (T*) branch->GetAddress();
+            T *bref = (T *) branch->GetAddress();
             set_branch_status(bname, true);
             INFO("Registering branch \"" << bname
-                 << "\" with address " << bref
-                 << " and type " << typeid(bref).name());
+                                         << "\" with address " << bref
+                                         << " and type " << typeid(bref).name());
             return new ObservedValue<T>(bname, bref);
         }
 
-        template <typename T>
-        Value<T*>* track_branch_ptr(const std::string& bname){
-            TBranch* branch = tree_obj->fChain->GetBranch(bname.c_str());
-            if (branch == nullptr){
+        template<typename T>
+        Value<T *> *track_branch_ptr(const std::string &bname) {
+            TBranch *branch = tree_obj->fChain->GetBranch(bname.c_str());
+            if (branch == nullptr) {
                 CRITICAL("Branch: " << bname << " does not exist in input tree.", -1);
             }
-            T* bref = (T*) branch->GetAddress();
+            T *bref = (T *) branch->GetAddress();
             set_branch_status(bname, true);
             INFO("Registering pointer branch \"" << bname
-                 << "\" with address " << bref
-                 << " and type " << typeid(bref).name());
+                                                 << "\" 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;
+        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();
+            if (!found) {
+                DataFileDescriptor &dfd = get_current_file();
                 CRITICAL("Branch: " << bname << " does not exist in input tree of file "
-                         << dfd.filename, -1);
+                                    << dfd.filename, -1);
             }
 
         }
 
-        template <typename T>
-        Value<T>* track_branch_obj(const std::string& bname){
-            TBranch* branch = tree_obj->fChain->GetBranch(bname.c_str());
-            if (branch == nullptr){
+        template<typename T>
+        Value<T> *track_branch_obj(const std::string &bname) {
+            TBranch *branch = tree_obj->fChain->GetBranch(bname.c_str());
+            if (branch == nullptr) {
                 CRITICAL("Branch: " << bname << " does not exist in input tree.", -1);
             }
-            T** bref = (T**) branch->GetAddress();
+            T **bref = (T **) branch->GetAddress();
             set_branch_status(bname, true);
             INFO("Registering object branch \"" << bname
-                 << "\" with address " << bref
-                 << " and type " << typeid(bref).name());
+                                                << "\" with address " << bref
+                                                << " and type " << typeid(bref).name());
             return new ObjectValue<T>(bname, bref);
         }
 
-        template <typename T>
-        decltype(auto) track_branch_vec(const std::string& size_bname, const std::string& value_bname){
-            track_branch_ptr<T>(value_bname);
-            return wrapper_vector<T>(lookup<int>(size_bname), lookup<T*>(value_bname), value_bname);
-        }
-
-        void save_all(){
+        void save_all() {
             output_file->cd();
 
             // Save the value names for each container to enable looking up
             // what values are plotted
-            std::map<string,string> value_lookup = this->get_container_name_value_map();
+            std::map<string, string> value_lookup = this->get_container_name_value_map();
             gDirectory->WriteObjectAny(&value_lookup, "std::map<std::string,std::string>", "_value_lookup");
 
-            std::map<string,string> fn_impl_lookup = this->get_function_name_impl_map();
-            gDirectory->WriteObjectAny(&fn_impl_lookup, "std::map<std::string,std::string>", "_function_impl_lookup");
-
-            for(auto container : containers){
+            for (auto container : containers) {
                 container.second->save_as("outfile", SaveOption::ROOT);
             }
         }
-};
+    };
+}
 #endif // root_dataset_h

+ 5 - 0
root/include/root_filval.hpp

@@ -0,0 +1,5 @@
+#ifndef root_filval_hpp
+#define root_filval_hpp
+#include "root_container.hpp"
+#include "root_dataset.hpp"
+#endif // root_filval_hpp

+ 0 - 163
root/value.hpp

@@ -1,163 +0,0 @@
-#ifndef root_value_hpp
-#define root_value_hpp
-#include "filval/value.hpp"
-#include "TLorentzVector.h"
-
-namespace fv::root{
-
-class LorentzVectors : public DerivedValue<std::vector<TLorentzVector>>{
-    protected:
-        Value<std::vector<float>> *pt_val;
-        Value<std::vector<float>> *eta_val;
-        Value<std::vector<float>> *phi_val;
-        Value<std::vector<float>> *mass_val;
-
-        void update_value(){
-            auto pt = pt_val->get_value();
-            auto eta = eta_val->get_value();
-            auto phi = phi_val->get_value();
-            auto mass = mass_val->get_value();
-            std::vector<int> sizes = {pt.size(), eta.size(), phi.size(), mass.size()};
-            int size = *std::min_element(sizes.begin(), sizes.end());
-            this->value.clear();
-            TLorentzVector lv;
-            for (int i =0; i<size; i++){
-                lv.SetPtEtaPhiM(pt[i], eta[i], phi[i], mass[i]);
-                this->value.push_back(lv);
-            }
-        }
-
-    public:
-        static std::string fmt_name(Value<std::vector<float>>* pt, Value<std::vector<float>>* eta,
-                                    Value<std::vector<float>>* phi, Value<std::vector<float>>* mass){
-            return "lorentz_vectors("+pt->get_name()+"," +eta->get_name()+","+
-                                      phi->get_name()+"," +mass->get_name()+")";
-        }
-
-        LorentzVectors(Value<std::vector<float>>* pt,
-                      Value<std::vector<float>>* eta,
-                      Value<std::vector<float>>* phi,
-                      Value<std::vector<float>>* mass,
-                      const std::string& alias)
-          :DerivedValue<std::vector<TLorentzVector>>(fmt_name(pt,eta,phi,mass), alias),
-           pt_val(pt), eta_val(eta), phi_val(phi), mass_val(mass) { }
-};
-
-class Energies : public DerivedValue<std::vector<float>>{
-    private:
-        Value<std::vector<TLorentzVector>> *vectors;
-        void update_value(){
-            std::vector<TLorentzVector>& vecs = vectors->get_value();
-            this->value.clear();
-            for (auto v : vecs){
-                this->value.push_back(v.Energy());
-            }
-        }
-
-    public:
-        static std::string fmt_name(Value<std::vector<TLorentzVector>> *vectors){
-            return "energies("+vectors->get_name()+")";
-        }
-
-        Energies(Value<std::vector<TLorentzVector>> *vectors,
-                 const std::string& alias)
-          :DerivedValue<std::vector<float>>(fmt_name(vectors), alias),
-           vectors(vectors) { }
-};
-
-
-namespace detail {
-    template<typename Tuple, std::size_t... Is>
-    decltype(auto) tuple_get_values_impl(const Tuple& t, std::index_sequence<Is...>){
-        return std::make_tuple(std::get<1>(std::get<Is>(t))->get_value()...);
-    }
-
-    template<typename Tuple, std::size_t... Is>
-    decltype(auto) tuple_get_labels_impl(const Tuple& t, std::index_sequence<Is...>){
-        return std::make_tuple(std::get<0>(std::get<Is>(t))...);
-    }
-}
-/**
- * Converts a tuple of pairs of label/Value objects to a tuple of the contained values
- */
-template<typename... ArgTypes>
-std::tuple<ArgTypes...> tuple_get_values(const std::tuple<std::pair<std::string,Value<ArgTypes>*>...>& t){
-    return detail::tuple_get_values_impl<std::tuple<std::pair<std::string,Value<ArgTypes>*>...>>(t, std::index_sequence_for<ArgTypes...>{});
-}
-
-/**
- * Converts a tuple of pairs of label/Value objects to a tuple of just the
- * labels
- */
-template<typename... ArgTypes>
-decltype(auto) tuple_get_labels(const std::tuple<std::pair<std::string,Value<ArgTypes>*>...>& t){
-    return detail::tuple_get_labels_impl<std::tuple<std::pair<std::string,Value<ArgTypes>*>...>>(t, std::index_sequence_for<ArgTypes...>{});
-}
-
-
-//-----------------------
-
-template <typename T>
-char type_lookup(){
-    return 0;
-}
-template <>
-char type_lookup<int>(){
-    return 'I';
-}
-template <>
-char type_lookup<float>(){
-    return 'F';
-}
-template <>
-char type_lookup<double>(){
-    return 'F';
-}
-
-
-template<typename... DataTypes>
-class MVAData : public DerivedValue<std::tuple<bool,bool,double,std::tuple<DataTypes...>>>{
-    private:
-        std::tuple<std::pair<std::string,Value<DataTypes>*>...> data;
-        Value<bool>* is_training;
-        Value<bool>* is_signal;
-        Value<double>* weight;
-
-        void update_value(){
-            this->value = std::make_tuple(is_training->get_value(), is_signal->get_value(), weight->get_value(),
-                                          tuple_get_values(data));
-        }
-
-        template <typename... Types>
-        static std::vector<std::pair<std::string, char>> get_label_types_impl(std::pair<std::string,Value<Types>*>... pairs){
-            return std::vector<std::pair<std::string, char>>({ std::make_pair(pairs.first,type_lookup<Types>())...});
-        }
-
-
-    public:
-        typedef std::tuple<bool, bool, double, std::tuple<DataTypes...>> type;
-
-
-        std::vector<std::pair<std::string, char>> get_label_types(){
-            return call(get_label_types_impl<DataTypes...>, data);
-        }
-
-        static std::string fmt_name(Value<bool>* is_training, Value<bool>* is_signal, Value<double>* weight,
-                                    const std::pair<std::string, Value<DataTypes>*>&&... data_vals){
-            //TODO: add data names
-            return "mva_data("+is_training->get_name()+","
-                              +is_signal->get_name()+","
-                              +weight->get_name()+")";
-        }
-
-        MVAData(Value<bool>* is_training, Value<bool>* is_signal,
-                Value<double>* weight, const std::pair<std::string, Value<DataTypes>*>&&... data_vals)
-          :DerivedValue<type>(fmt_name(is_training, is_signal, weight,
-                                       std::forward<const std::pair<std::string,Value<DataTypes>*>>(data_vals)...),""),
-           data(std::make_tuple(data_vals...)),
-           is_training(is_training),
-           is_signal(is_signal),
-           weight(weight) { }
-};
-}
-#endif // root_value_hpp

File diff suppressed because it is too large
+ 0 - 1319
value.hpp