ソースを参照

Adds ability to save fv::root containers to root files.

Caleb Fangmeier 7 年 前
コミット
4d26f66e94
共有9 個のファイルを変更した141 個の追加74 個の削除を含む
  1. 0 4
      CMakeLists.txt
  2. 4 3
      analysis/MiniTreeDataSet.hpp
  3. 10 17
      analysis/TTTT_Analysis.cpp
  4. 1 1
      filval/argparse.hpp
  5. 9 2
      filval/container.hpp
  6. 10 3
      filval/dataset.hpp
  7. 20 10
      filval/log.hpp
  8. 31 14
      filval/value.hpp
  9. 56 20
      filval_root/container.hpp

+ 0 - 4
CMakeLists.txt

@@ -49,13 +49,9 @@ IF(DOXYGEN_FOUND)
     )
 ENDIF(DOXYGEN_FOUND)
 
-
-
-
 FIND_PACKAGE(ROOT REQUIRED)
 INCLUDE_DIRECTORIES(SYSTEM ${ROOT_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
 LINK_LIBRARIES(${ROOT_LIBRARIES})
 
 
-
 ADD_EXECUTABLE(main ${CMAKE_CURRENT_SOURCE_DIR}/analysis/TTTT_Analysis.cpp)

+ 4 - 3
analysis/MiniTreeDataSet.hpp

@@ -56,9 +56,10 @@ class MiniTreeDataSet : public DataSet,
                  << " and type " << typeid(bref).name());
             return new PointerValue<T>(bname, bref);
         }
-
-        void register_container(GenContainer* container){
-            containers[container->get_name()] = container;
+        void save_all(){
+            for(auto container : containers){
+                container.second->save_as("outfile", SaveOption::ROOT);
+            }
         }
 };
 #endif // minitreedataset_h

+ 10 - 17
analysis/TTTT_Analysis.cpp

@@ -49,6 +49,7 @@ void declare_values(MiniTreeDataSet& mt){
     auto eta_wrapper = new WrapperVector<float>("nLepGood", "LepGood_eta");
     auto phi_wrapper = new WrapperVector<float>("nLepGood", "LepGood_phi");
     auto m_wrapper   = new WrapperVector<float>("nLepGood", "LepGood_mass");
+    /* auto dxy_wrapper   = new WrapperVector<float>("nLepGood", "LepGood_dxy"); */
 
     auto& get_energy = GenFunction::register_function<float(float,float,float,float)>("get_energy", FUNC(([](float pt, float eta, float phi, float m){
         TLorentzVector t;
@@ -72,29 +73,21 @@ void declare_values(MiniTreeDataSet& mt){
 }
 
 void declare_containers(MiniTreeDataSet& mt){
-    mt.add_container(new ContainerTH1I("nLepGood", "Lepton Multiplicity", lookup("nLepGood"), 10, 0, 10));
+    mt.register_container(new ContainerTH1I("nLepGood", "Lepton Multiplicity", lookup("nLepGood"), 10, 0, 10));
 
-    mt.add_container(new ContainerTH1I("nLepGood2", "Lepton Multiplicity", lookup("nLepGood"), 10, 0, 10));
+    mt.register_container(new ContainerTH1I("nLepGood2", "Lepton Multiplicity", lookup("nLepGood"), 10, 0, 10));
     mt.get_container("nLepGood2")->add_filter(lookup_filter("3<=nLepGood<5"));
 
-    mt.add_container(new ContainerTH1I("nLepGood3", "Lepton Multiplicity", lookup("nLepGood"), 10, 0, 10));
+    mt.register_container(new ContainerTH1I("nLepGood3", "Lepton Multiplicity", lookup("nLepGood"), 10, 0, 10));
     mt.get_container("nLepGood3")->add_filter(!(*lookup_filter("3<=nLepGood<5")));
 
-    mt.add_container(new ContainerTGraph("nLepvsnJet", new Pair<int, int>("nLepGood", "nJet") ));
+    /* mt.register_container(new ContainerTGraph("nLepvsnJet", new Pair<int, int>("nLepGood", "nJet") )); */
 
-    mt.add_container(new ContainerTH1F("avg_lepton_energy", "Average Lepton Energy", lookup("avg_lepton_energy"), 50, 0, 500));
-    mt.add_container(new ContainerTH1F("max_lepton_energy", "Maximum Lepton Energy", lookup("max_lepton_energy"), 50, 0, 500));
+    mt.register_container(new ContainerTH1F("avg_lepton_energy", "Average Lepton Energy", lookup("avg_lepton_energy"), 50, 0, 500));
+    mt.register_container(new ContainerTH1F("max_lepton_energy", "Maximum Lepton Energy", lookup("max_lepton_energy"), 50, 0, 500));
 
 }
 
-void save_containers(MiniTreeDataSet& mt){
-    mt.get_container("nLepGood")->save();
-    mt.get_container("nLepGood2")->save();
-    mt.get_container("nLepGood3")->save();
-    mt.get_container("avg_lepton_energy")->save();
-    mt.get_container("max_lepton_energy")->save();
-}
-
 void run_analysis(const std::string& filename){
     TFile *f = TFile::Open(filename.c_str());
     TTree *tree = (TTree*) f->Get("tree");
@@ -102,14 +95,14 @@ void run_analysis(const std::string& filename){
     enable_branches(mt);
     declare_values(mt);
     declare_containers(mt);
-    /* DEBUG(GenValue::summary()); */
     mt.process();
-    save_containers(mt);
+    mt.save_all();
+    /* save_containers(mt); */
 }
 
 int main(int argc, char * argv[])
 {
-    clog.rdbuf(new Log("mylog.txt", LogPriority::kLogDebug));
+    Log::init_logger("log.txt", LogPriority::kLogDebug);
     ArgParser args(argc, argv);
     if(args.cmdOptionExists("-f")) {
         run_analysis(args.getCmdOption("-f"));

+ 1 - 1
filval/argparse.hpp

@@ -29,6 +29,7 @@
  * SOFTWARE.
  *
  * @section DESCRIPTION
+ * \see http://stackoverflow.com/questions/865668/how-to-parse-command-line-arguments-in-c#868894
  */
 #ifndef argparse_hpp
 #define argparse_hpp
@@ -36,7 +37,6 @@
 #include <string>
 #include <vector>
 namespace fv::util{
-/// \see http://stackoverflow.com/questions/865668/how-to-parse-command-line-arguments-in-c#868894
 class ArgParser{
     private:
         std::vector <std::string> tokens;

+ 9 - 2
filval/container.hpp

@@ -5,6 +5,13 @@
 #include <vector>
 
 namespace fv{
+
+enum SaveOption{
+    PNG = 0,
+    PDF = 1,
+    ROOT = 2
+};
+
 class GenContainer{
     private:
         std::string name;
@@ -36,8 +43,8 @@ class GenContainer{
         const std::string& get_name(){
             return name;
         }
-        virtual void save_as(const std::string& fname) = 0;
-        virtual void save() = 0;
+        virtual void save_as(const std::string& fname, const SaveOption& option) = 0;
+        virtual void save(const SaveOption& option=SaveOption::PNG) = 0;
 };
 typedef std::map<std::string, GenContainer*> ContainerSet;
 

+ 10 - 3
filval/dataset.hpp

@@ -36,15 +36,22 @@ class DataSet{
             std::cout << " Finished!" << std::endl;
         }
 
-        void add_container(GenContainer *container){
+        virtual void save_all(){
+            for(auto container : containers)
+                container.second->save();
+        }
+
+        void register_container(GenContainer *container){
+            if (containers[container->get_name()] != nullptr){
+                CRITICAL("Container with name \""+container->get_name()+"\" already exists.", -1);
+            }
             containers[container->get_name()] = container;
         }
 
         GenContainer* get_container(std::string container_name){
             GenContainer* c = containers[container_name];
             if (c == nullptr){
-                std::cout << "Request for container \"" << container_name << "\" failed. Doesn't exist." << std::endl;
-                exit(-1);
+                CRITICAL("Request for container \"" << container_name << "\" failed. Doesn't exist.", -1);
             }
             return c;
         }

+ 20 - 10
filval/log.hpp

@@ -50,7 +50,7 @@ enum LogPriority {
     kLogDebug     = 0   // debug-level message
 };
 
-#define CRITICAL(x,y) std::clog << fv::util::LogPriority::kLogCritical << __FILE__ << "@L" << __LINE__ << " :: " << x << std::flush; exit(y)
+#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
@@ -67,14 +67,15 @@ private:
     std::ofstream logfile;
     LogPriority priority_curr;
     LogPriority priority_set;
-    std::map<LogPriority,std::string> name_map = {{kLogEmergency, "EMERGENCY"},
-                                                  {kLogAlert,     "ALERT"},
-                                                  {kLogCritical,  "CRITICAL"},
-                                                  {kLogError,     "ERROR"},
-                                                  {kLogWarning,   "WARNING"},
-                                                  {kLogNotice,    "NOTICE"},
-                                                  {kLogInfo,      "INFO"},
-                                                  {kLogDebug,     "DEBUG"}};
+    inline static Log* singleton = nullptr;
+    const std::map<LogPriority,std::string> name_map = {{kLogEmergency, "EMERGENCY"},
+                                                        {kLogAlert,     "ALERT"},
+                                                        {kLogCritical,  "CRITICAL"},
+                                                        {kLogError,     "ERROR"},
+                                                        {kLogWarning,   "WARNING"},
+                                                        {kLogNotice,    "NOTICE"},
+                                                        {kLogInfo,      "INFO"},
+                                                        {kLogDebug,     "DEBUG"}};
 
     friend std::ostream& operator<< (std::ostream& os, const LogPriority& log_priority){
         static_cast<Log *>(os.rdbuf())->priority_curr = log_priority;
@@ -84,7 +85,7 @@ protected:
     int sync(){
         if (buffer_.length()) {
             if (priority_curr >= priority_set){
-                logfile << name_map[priority_curr] << ": " <<  buffer_ << std::endl << std::flush;
+                logfile << name_map.at(priority_curr) << ": " <<  buffer_ << std::endl << std::flush;
             }
             buffer_.erase();
             /* priority_curr = kLogDebug; // default to debug for each message */
@@ -105,6 +106,15 @@ public:
         priority_set = priority;
         priority_curr = kLogDebug;
     }
+
+    static Log& init_logger(std::string filename, LogPriority priority){
+        if (singleton == nullptr){
+            singleton = new Log(filename, priority);
+            std::cout << "Writing log data to " << filename << std::endl;
+            std::clog.rdbuf(singleton);
+        }
+        return *singleton;
+    }
 };
 }
 #endif // log_hpp

+ 31 - 14
filval/value.hpp

@@ -41,6 +41,7 @@
  */
 #ifndef value_hpp
 #define value_hpp
+#include <iomanip>
 #include <iostream>
 #include <sstream>
 #include <utility>
@@ -68,9 +69,6 @@ class GenFunction {
     private:
         std::string name;
         std::string impl;
-    protected:
-        /* virtual void _() = 0; */
-
 
     public:
         /**
@@ -89,18 +87,35 @@ class GenFunction {
             return name;
         }
 
+        /**
+         * Attempt to invoke clang-format for the purpose of printing out
+         * nicely formatted functions to the log file. If clang-format is not
+         * present, this function just passes through the code unmodified.
+         */
+        static std::string format_code(const std::string& code){
+            std::stringstream code_out("");
+            std::string command("echo \""+code+"\" | clang-format");
+            char buffer[255];
+            FILE *stream = popen(command.c_str(), "r");
+            while (fgets(buffer, 255, stream) != NULL)
+                code_out << buffer;
+            if (pclose(stream) == 0)
+                return code_out.str();
+            else
+                return code;
+        }
+
         static std::string summary(){
             std::stringstream ss;
+            ss << "The following functions have been registered" << std::endl;
             for(auto p : function_registry){
                 if (p.second == nullptr) continue;
-                ss << p.second->name << std::endl;
-                ss << "\t" << p.second->impl << std::endl;
-                ss << "##############################" << std::endl;
+                ss << "-->" << p.second->name << std::endl;
+                ss << format_code(p.second->impl);
             }
             return ss.str();
         }
 
-        /* template <typename R, typename... ArgTypes> */
         template <typename T>
         static Function<T>& register_function(const std::string& name, std::function<T> f, const std::string& impl){
             in_register_function = true;
@@ -117,10 +132,6 @@ class GenFunction {
             in_register_function = false;
             return *func;
         }
-
-        /* static Function<R(ArgTypes...)>& register_function(const std::string& name, std::function<R(ArgTypes...)> f){ */
-        /*     return Function<R(ArgTypes...)>::register_function(name, f, "N/A"); */
-        /* } */
 };
 
 
@@ -215,7 +226,7 @@ class GenValue{
             else if (values[name] != nullptr)
                 return values[name];
             else{
-                ERROR("Could not find alias or value \"" << name << "\". I'll tell you the ones I know about."
+                ERROR("Could not find alias or value \"" << name << "\". I'll tell you the ones I know about." << std::endl
                         << summary());
                 CRITICAL("Aborting... :(", -1);
             }
@@ -256,7 +267,12 @@ class GenValue{
             }
             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;
+}
 
 
 /**
@@ -383,8 +399,8 @@ class WrapperVector : public DerivedValue<std::vector<T> >{
            size(size), data(data){ }
 
         WrapperVector(const std::string &label_size, const std::string &label_data)
-          :WrapperVector(dynamic_cast<Value<int>*>(GenValue::values.at(label_size)),
-                         dynamic_cast<Value<T*>*>(GenValue::values.at(label_data))) { }
+          :WrapperVector(dynamic_cast<Value<int>*>(GenValue::get_value(label_size)),
+                         dynamic_cast<Value<T*>*>(GenValue::get_value(label_data))) { }
 };
 
 /**
@@ -460,6 +476,7 @@ class ZipMapFour : public DerivedValue<std::vector<R> >{
                       dynamic_cast<Value<std::vector<T> >*>(GenValue::values.at(label4))){ }
 };
 
+
 /**
  * Reduce a Value of type vector<T> to just a T.
  * This is useful functionality to model, for instance, calculating the maximum

+ 56 - 20
filval_root/container.hpp

@@ -1,11 +1,44 @@
 #ifndef root_container_hpp
 #define root_container_hpp
 #include <utility>
-#include "../filval/filval.hpp"
+#include <iostream>
+#include "TFile.h"
 #include "TH1.h"
 #include "TH2.h"
 #include "TGraph.h"
-#include <iostream>
+#include "TROOT.h"
+
+#include "../filval/filval.hpp"
+
+namespace fv::root::util{
+void _save_img(TObject* container, const std::string& fname){
+    TCanvas* c1 = new TCanvas("c1");
+    container->Draw();
+    c1->Draw();
+    c1->SaveAs(fname.c_str());
+    delete c1;
+}
+
+void _save_bin(TObject* container, const std::string& fname){
+    INFO("Saving object: " << container->GetName() << " into file " << fname);
+    TFile* f = TFile::Open(fname.c_str(), "UPDATE");
+    container->Write(container->GetName());
+    f->Close();
+}
+
+void _save_as(TObject* container, const std::string& fname, const SaveOption& option = SaveOption::PNG) {
+    switch(option){
+        case PNG:
+            _save_img(container, fname+".png"); break;
+        case PDF:
+            _save_img(container, fname+".pdf"); break;
+        case ROOT:
+            _save_bin(container, fname+".root"); break;
+        default:
+            break;
+    }
+}
+}
 
 namespace fv::root {
 
@@ -18,6 +51,7 @@ class ContainerTH1 : public Container<TH1>{
             }
             container->Fill(value->get_value());
         }
+
     protected:
         std::string title;
         int nbins;
@@ -32,15 +66,12 @@ class ContainerTH1 : public Container<TH1>{
            title(title), nbins(nbins), low(low), high(high),
            value(dynamic_cast<Value<T>*>(value)) { }
 
-        void save_as(const std::string& fname) {
-            TCanvas* c1 = new TCanvas("c1");
-            container->Draw();
-            c1->Draw();
-            c1->SaveAs(fname.c_str());
-            delete c1;
+        void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
+            util::_save_as(container, fname, option);
         }
-        virtual void save() {
-            save_as(this->get_name() + ".png");
+
+        void save(const SaveOption& option = SaveOption::PNG) {
+            save_as(this->get_name(), option);
         }
 };
 
@@ -76,6 +107,7 @@ class ContainerTH2 : public Container<TH2>{
             std::pair<T, T> val = value->get_value();
             container->Fill(val.first, val.second);
         }
+
     protected:
         std::string title;
         int nbins_x;
@@ -86,6 +118,7 @@ class ContainerTH2 : public Container<TH2>{
         T high_y;
         Value<std::pair<T, T> > *value;
         virtual void init_TH2() = 0;
+
     public:
         explicit ContainerTH2(const std::string& name, const std::string& title,
                       int nbins_x, double low_x, double high_x,
@@ -95,15 +128,13 @@ class ContainerTH2 : public Container<TH2>{
            nbins_x(nbins_x), low_x(low_x), high_x(high_x),
            nbins_y(nbins_y), low_y(low_y), high_y(high_y),
            value(dynamic_cast<Value<T>*>(value)) { }
-        void save_as(const std::string& fname) {
-            TCanvas* c1 = new TCanvas("c1");
-            container->Draw();
-            c1->Draw();
-            c1->SaveAs(fname.c_str());
-            delete c1;
+
+        void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
+            util::_save_as(container, fname, option);
         }
-        virtual void save() {
-            save_as(this->get_name() + ".png");
+
+        void save(const SaveOption& option = SaveOption::PNG) {
+            save_as(this->get_name(), option);
         }
 };
 
@@ -155,8 +186,13 @@ class ContainerTGraph : public Container<TGraph>{
             }
             return container;
         }
-        void save_as(const std::string& fname) { }
-        virtual void save() { }
+        void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
+            util::_save_as(container, fname, option);
+        }
+
+        void save(const SaveOption& option = SaveOption::PNG) {
+            save_as(this->get_name(), option);
+        }
 };
 
 }