// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_wroot_ntuple #define tools_wroot_ntuple // An ntuple class to write at the CERN-ROOT format. // It inherits wroot::tree and each column is mapped // on a wroot::branch. Each add_row() does a tree::fill(). #include "tree" #include "../vfind" #include "../vmanip" #include "../ntuple_booking" #include "../sout" #include "../scast" #include "../forit" namespace tools { namespace wroot { class ntuple : public tree { public: class icol { public: virtual ~icol(){} public: virtual void* cast(cid) const = 0; virtual cid id_cls() const = 0; public: virtual void add() = 0; virtual void set_def() = 0; virtual const std::string& name() const = 0; virtual void set_basket_size(uint32) = 0; }; public: template class column : public virtual icol { public: static cid id_class() { static const T s_v = T(); //do that for T = std::string. return _cid(s_v); } virtual void* cast(cid a_class) const { if(void* p = cmp_cast(this,a_class)) {return p;} else return 0; } virtual cid id_cls() const {return id_class();} public: //icol virtual void add() {m_leaf->fill(m_tmp);} virtual void set_def() {m_tmp = m_def;} virtual const std::string& name() const {return m_leaf->name();} virtual void set_basket_size(uint32 a_size) { m_leaf->branch().set_basket_size(a_size); } public: column(tree& a_tree,const std::string& a_name,const T& a_def) :m_tree(a_tree),m_leaf(0) ,m_def(a_def),m_tmp(a_def) { branch* br = m_tree.create_branch(a_name); m_leaf = br->create_leaf(a_name,a_name); } virtual ~column(){} protected: column(const column& a_from) :icol(a_from) ,m_tree(a_from.m_tree) ,m_leaf(0) ,m_def(a_from.m_def) ,m_tmp(a_from.m_tmp) {} column& operator=(const column& a_from){ if(&a_from==this) return *this; m_leaf = 0; m_def = a_from.m_def; m_tmp = a_from.m_tmp; return *this; } public: bool fill(const T& a_value) {m_tmp = a_value;return true;} protected: tree& m_tree; leaf* m_leaf; T m_def; T m_tmp; }; class column_string : public virtual icol { public: static cid id_class() { static const std::string s_v; return _cid(s_v); } virtual void* cast(cid a_class) const { if(void* p = cmp_cast(this,a_class)) {return p;} else return 0; } virtual cid id_cls() const {return id_class();} public: //icol virtual void add() {m_leaf->fill(m_tmp);} virtual void set_def() {m_tmp = m_def;} virtual const std::string& name() const {return m_leaf->name();} virtual void set_basket_size(uint32 a_size) { m_leaf->branch().set_basket_size(a_size); } public: column_string(tree& a_tree,const std::string& a_name,const std::string& a_def) :m_tree(a_tree),m_leaf(0) ,m_def(a_def),m_tmp(a_def) { branch* br = m_tree.create_branch(a_name); m_leaf = br->create_leaf_string(a_name,a_name); } virtual ~column_string(){} protected: column_string(const column_string& a_from) :icol(a_from) ,m_tree(a_from.m_tree) ,m_leaf(0) ,m_def(a_from.m_def) ,m_tmp(a_from.m_tmp) {} column_string& operator=(const column_string& a_from){ if(&a_from==this) return *this; m_leaf = 0; m_def = a_from.m_def; m_tmp = a_from.m_tmp; return *this; } public: bool fill(const std::string& a_value) {m_tmp = a_value;return true;} protected: tree& m_tree; leaf_string* m_leaf; std::string m_def; std::string m_tmp; }; template class std_vector_column : public virtual icol { public: static cid id_class() {return _cid_std_vector();} virtual void* cast(cid a_class) const { if(void* p = cmp_cast(this,a_class)) {return p;} else return 0; } virtual cid id_cls() const {return id_class();} public: //icol virtual void add() {} virtual void set_def() {} virtual const std::string& name() const {return m_leaf->name();} virtual void set_basket_size(uint32 a_size) { m_leaf->branch().set_basket_size(a_size); } public: std_vector_column(tree& a_tree,const std::string& a_name,std::vector& a_user_vec) :m_tree(a_tree) ,m_user_vec(a_user_vec) ,m_leaf(0) { std_vector_be* br = m_tree.create_std_vector_be(a_name,m_user_vec); m_leaf = br->create_leaf_element(a_name,a_name); } virtual ~std_vector_column(){} protected: std_vector_column(const std_vector_column& a_from) :icol(a_from) ,m_tree(a_from.m_tree) ,m_user_vec(a_from.m_user_vec) ,m_leaf(0) {} std_vector_column& operator=(const std_vector_column& a_from){ if(&a_from==this) return *this; m_leaf = 0; return *this; } protected: tree& m_tree; std::vector& m_user_vec; leaf_element* m_leaf; }; public: ntuple(idir& a_dir,const std::string& a_name,const std::string& a_title) :tree(a_dir,a_name,a_title){} ntuple(idir& a_dir,const ntuple_booking& a_bkg) :tree(a_dir,a_bkg.name(),a_bkg.title()){ const std::vector& cols = a_bkg.columns(); tools_vforcit(column_booking,cols,it){ if((*it).cls_id()==_cid(char(0))) { create_column((*it).name()); } else if((*it).cls_id()==_cid(short(0))) { create_column((*it).name()); } else if((*it).cls_id()==_cid(int(0))) { create_column((*it).name()); } else if((*it).cls_id()==_cid(float(0))) { create_column((*it).name()); } else if((*it).cls_id()==_cid(double(0))) { create_column((*it).name()); } else if((*it).cls_id()==_cid(std::string())) { create_column_string((*it).name()); } else if((*it).cls_id()==_cid_std_vector()) { std::vector* vec = (std::vector*)(*it).user_obj(); if(vec) { create_column((*it).name(),*vec); } else { m_out << "tools::wroot::ntuple :" << " for std::vector column " << sout((*it).name()) << ", the user vector pointer is null." << std::endl; tools::clear(m_cols); tools::clear(m_branches); return; } } else if((*it).cls_id()==_cid_std_vector()) { std::vector* vec = (std::vector*)(*it).user_obj(); if(vec) { create_column((*it).name(),*vec); } else { m_out << "tools::wroot::ntuple :" << " for std::vector column " << sout((*it).name()) << ", the user vector pointer is null." << std::endl; tools::clear(m_cols); tools::clear(m_branches); return; } } else if((*it).cls_id()==_cid_std_vector()) { std::vector* vec = (std::vector*)(*it).user_obj(); if(vec) { create_column((*it).name(),*vec); } else { m_out << "tools::wroot::ntuple :" << " for std::vector column " << sout((*it).name()) << ", the user vector pointer is null." << std::endl; tools::clear(m_cols); tools::clear(m_branches); return; } } else if((*it).cls_id()==_cid_std_vector()) { std::vector* vec = (std::vector*)(*it).user_obj(); if(vec) { create_column((*it).name(),*vec); } else { m_out << "tools::wroot::ntuple :" << " for std::vector column " << sout((*it).name()) << ", the user vector pointer is null." << std::endl; tools::clear(m_cols); tools::clear(m_branches); return; } } else if((*it).cls_id()==_cid_std_vector()) { std::vector* vec = (std::vector*)(*it).user_obj(); if(vec) { create_column((*it).name(),*vec); } else { m_out << "tools::wroot::ntuple :" << " for std::vector column " << sout((*it).name()) << ", the user vector pointer is null." << std::endl; tools::clear(m_cols); tools::clear(m_branches); return; } // no leaf_store_class() defined for the other types. } else { m_out << "tools::wroot::ntuple :" << " for column " << sout((*it).name()) << ", type with cid " << (*it).cls_id() << " not yet handled." << std::endl; //throw tools::clear(m_cols); tools::clear(m_branches); return; } } } virtual ~ntuple() {} protected: ntuple(const ntuple& a_from) :iobject(a_from),itree(a_from),tree(a_from) {} ntuple& operator=(const ntuple&){return *this;} public: const std::vector& columns() const {return m_cols;} template column* create_column(const std::string& a_name,const T& a_def = T()) { if(find_named(m_cols,a_name)) return 0; column* col = new column(*this,a_name,a_def); if(!col) return 0; m_cols.push_back(col); return col; } column_string* create_column_string(const std::string& a_name,const std::string& a_def = std::string()) { if(find_named(m_cols,a_name)) return 0; column_string* col = new column_string(*this,a_name,a_def); if(!col) return 0; m_cols.push_back(col); return col; } template std_vector_column* create_column(const std::string& a_name,std::vector& a_user_vec) { //NOTE : to optimize, we do not handle a default std::vector value logic. if(find_named(m_cols,a_name)) return 0; std_vector_column* col = new std_vector_column(*this,a_name,a_user_vec); if(!col) return 0; m_cols.push_back(col); return col; } template column* find_column(const std::string& a_name) { icol* col = find_named(m_cols,a_name); if(!col) return 0; return id_cast >(*col); } column_string* find_column_string(const std::string& a_name) { icol* col = find_named(m_cols,a_name); if(!col) return 0; return id_cast(*col); } bool add_row() { if(m_cols.empty()) return false; tools_vforit(icol*,m_cols,it) (*it)->add(); uint32 n; bool status = tree::fill(n); tools_vforit(icol*,m_cols,it) (*it)->set_def(); return status; } void set_basket_size(uint32 a_size) { tools_vforit(icol*,m_cols,it) (*it)->set_basket_size(a_size); } protected: std::vector m_cols; }; }} #endif