Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/tools/rroot/ntuple

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
  2 // See the file tools.license for terms.
  3 
  4 #ifndef tools_rroot_ntuple
  5 #define tools_rroot_ntuple
  6 
  7 // to have same API than rcsv::ntuple.
  8 
  9 #include "../rntuple"
 10 
 11 #include "tree"
 12 #include "leaf"
 13 #include "stl_vector"
 14 
 15 #include "../cids"
 16 #include "../vfind"
 17 #include "../vmanip"
 18 #include "../ntuple_binding"
 19 #include "../get_lines"
 20 
 21 #ifdef TOOLS_MEM
 22 #include "../mem"
 23 #endif
 24 
 25 namespace tools {
 26 namespace rroot {
 27 
 28 class ntuple : public virtual read::intuple {
 29   typedef read::intuple parent;
 30 public:
 31   static const std::string& s_class() {
 32     static const std::string s_v("tools::rroot::ntuple");
 33     return s_v;
 34   }
 35   virtual const std::string& s_cls() const {return s_class();}
 36 public: //intuple
 37   virtual void start() {m_index = -1;}
 38   virtual bool next() {
 39     m_index++;
 40     if((uint64)m_index>=m_tree.entries()) return false;
 41     return true;
 42   }
 43   virtual read::icol* find_icol(const std::string& a_name){
 44     return find_named<read::icol>(m_cols,a_name);
 45   }
 46   virtual const std::vector<read::icol*>& columns() const {return m_cols;}
 47   virtual const std::string& title() const {return m_tree.title();}
 48   virtual bool number_of_entries(uint64 & a_value) const {a_value = m_tree.entries();return true;}
 49 public:
 50 
 51   template <class T,class LEAF>
 52   class column_ref : public virtual read::icolumn<T> {
 53     typedef read::icolumn<T> parent;
 54   public:
 55     static cid id_class() {return 200+_cid(T())+10000;}
 56   public: //icol
 57     virtual void* cast(cid a_class) const {
 58       if(void* p = cmp_cast<column_ref>(this,a_class)) return p;
 59       return parent::cast(a_class);
 60     }
 61     virtual cid id_cls() const {return id_class();}
 62   public: //icol
 63     virtual const std::string& name() const {return m_leaf.name();}
 64   public: //icolumn<T>
 65     virtual bool fetch_entry() const {return _fetch_entry();}
 66     virtual bool get_entry(T& a_v) const {
 67       if(!_fetch_entry()) {a_v = T();return false;}
 68       a_v = m_ref;
 69       return true;
 70     }
 71   public:
 72     column_ref(ifile& a_file,branch& a_branch,LEAF& a_leaf,int64& a_index,T& a_ref)
 73     :m_file(a_file)
 74     ,m_branch(a_branch)
 75     ,m_leaf(a_leaf)
 76     ,m_index(a_index) //WARNING : we keep the ref !
 77     ,m_ref(a_ref)
 78     {}
 79     virtual ~column_ref(){}
 80   protected:
 81     column_ref(const column_ref& a_from)
 82     :read::icol(a_from)
 83     ,parent(a_from)
 84     ,m_file(a_from.m_file)
 85     ,m_branch(a_from.m_branch)
 86     ,m_leaf(a_from.m_leaf)
 87     ,m_index(a_from.m_index)
 88     ,m_ref(a_from.m_ref)
 89     {}
 90     column_ref& operator=(const column_ref& a_from){
 91       if(&a_from==this) return *this;
 92       return *this;
 93     }
 94   protected:
 95     //typedef typename LEAF::value_t value_t;
 96     bool _fetch_entry() const {
 97       unsigned int n;
 98       if(!m_branch.find_entry(m_file,uint32(m_index),n)) {m_ref = T();return false;}
 99       if(!m_leaf.num_elem()) {m_ref = T();return true;} //it is ok. It may be a vector from a row_wise ntuple column.
100       typename LEAF::value_t _tmp;
101       if(!m_leaf.value(0,_tmp)) return false;
102       m_ref = T(_tmp);
103       return true;
104     }
105   protected:
106     ifile& m_file;
107     branch& m_branch;
108     LEAF& m_leaf;
109     int64& m_index; //WARNING : a ref.
110     T& m_ref;
111     //value_t m_tmp;
112   };
113 
114   template <class T,class LEAF>
115   class column : public column_ref<T,LEAF> {
116     typedef column_ref<T,LEAF> parent;
117   public:
118     static cid id_class() {return 200+_cid(T());}
119   public: //icol
120     virtual void* cast(cid a_class) const {
121       if(void* p = cmp_cast<column>(this,a_class)) return p;
122       return parent::cast(a_class);
123     }
124     virtual cid id_cls() const {return id_class();}
125   public:
126     column(ifile& a_file,branch& a_branch,LEAF& a_leaf,int64& a_index)
127     :parent(a_file,a_branch,a_leaf,a_index,m_value)
128     ,m_value(T())
129     {}
130     virtual ~column(){}
131   protected:
132     column(const column& a_from)
133     :read::icol(a_from)
134     ,read::icolumn<T>(a_from)
135     ,parent(a_from)
136     ,m_value(a_from.m_value)
137     {}
138     column& operator=(const column& a_from){
139       if(&a_from==this) return *this;
140       m_value = a_from.m_value;
141       return *this;
142     }
143   public:
144     const T& get_value() const {return m_value;}
145   protected:
146     T m_value;
147   };
148 
149   class column_string_ref : public virtual read::icol {
150     typedef read::icol parent;
151   public:
152     static cid id_class() {
153       static const std::string s_v;
154       return _cid(s_v)+10000;
155     }
156   public: //icol
157     virtual void* cast(cid a_class) const {
158       if(void* p = cmp_cast<column_string_ref>(this,a_class)) return p;
159       return 0;
160     }
161     virtual cid id_cls() const {return id_class();}
162     virtual const std::string& name() const {return m_leaf.name();}
163   public:
164     virtual bool fetch_entry() const {return _fetch_entry();}
165   public:
166     column_string_ref(ifile& a_file,branch& a_branch,leaf_string& a_leaf,int64& a_index,std::string& a_ref)
167     :m_file(a_file)
168     ,m_branch(a_branch)
169     ,m_leaf(a_leaf)
170     ,m_index(a_index) //WARNING : we keep the ref !
171     ,m_ref(a_ref)
172     {}
173     virtual ~column_string_ref(){}
174   protected:
175     column_string_ref(const column_string_ref& a_from)
176     :parent(a_from)
177     ,m_file(a_from.m_file)
178     ,m_branch(a_from.m_branch)
179     ,m_leaf(a_from.m_leaf)
180     ,m_index(a_from.m_index)
181     ,m_ref(a_from.m_ref)
182     {}
183     column_string_ref& operator=(const column_string_ref& a_from){
184       if(&a_from==this) return *this;
185       return *this;
186     }
187   public:
188     bool get_entry(std::string& a_v) const {
189       if(!_fetch_entry()) {a_v.clear();return false;}
190       a_v = m_ref;
191       return true;
192     }
193   protected:
194     bool _fetch_entry() const {
195       unsigned int n;
196       if(!m_branch.find_entry(m_file,uint32(m_index),n)) {m_ref.clear();return false;}
197       const char* _cs = m_leaf.value();
198       if(!_cs) {m_ref.clear();return false;}
199       m_ref = _cs;
200       return true;
201     }
202   protected:
203     ifile& m_file;
204     branch& m_branch;
205     leaf_string& m_leaf;
206     int64& m_index; //WARNING : a ref.
207     std::string& m_ref;
208   };
209 
210   class column_string : public column_string_ref {
211     typedef column_string_ref parent;
212   public:
213     static cid id_class() {
214       static const std::string s_v;
215       return _cid(s_v);
216     }
217   public: //icol
218     virtual void* cast(cid a_class) const {
219       if(void* p = cmp_cast<column_string>(this,a_class)) return p;
220       return parent::cast(a_class);
221     }
222     virtual cid id_cls() const {return id_class();}
223     virtual const std::string& name() const {return m_leaf.name();}
224   public:
225     column_string(ifile& a_file,branch& a_branch,leaf_string& a_leaf,int64& a_index)
226     :parent(a_file,a_branch,a_leaf,a_index,m_value)
227     {}
228     virtual ~column_string(){}
229   protected:
230     column_string(const column_string& a_from)
231     :read::icol(a_from)
232     ,parent(a_from)
233     ,m_value(a_from.m_value)
234     {}
235     column_string& operator=(const column_string& a_from){
236       if(&a_from==this) return *this;
237       m_value = a_from.m_value;
238       return *this;
239     }
240   public:
241     const std::string& get_value() const {return m_value;}
242   protected:
243     std::string m_value;
244   };
245 
246   class column_vector_string_ref : public column_string_ref {
247     typedef column_string_ref parent;
248   public:
249     static cid id_class() {return _cid_std_vector<std::string>()+10000;}
250   public: //icol
251     virtual void* cast(cid a_class) const {
252       if(void* p = cmp_cast<column_vector_string_ref>(this,a_class)) return p;
253       return parent::cast(a_class);
254     }
255     virtual cid id_cls() const {return id_class();}
256     virtual const std::string& name() const {return m_leaf.name();}
257   public:
258     virtual bool fetch_entry() const {return _fetch_entry();}
259   public:
260     column_vector_string_ref(ifile& a_file,branch& a_branch,leaf_string& a_leaf,int64& a_index,
261                              std::vector<std::string>& a_ref,char a_sep)
262     :parent(a_file,a_branch,a_leaf,a_index,m_value)
263     ,m_ref(a_ref)
264     ,m_sep(a_sep)
265     {}
266     virtual ~column_vector_string_ref(){}
267   protected:
268     column_vector_string_ref(const column_vector_string_ref& a_from)
269     :read::icol(a_from)
270     ,parent(a_from)
271     ,m_ref(a_from.m_ref)
272     ,m_sep(a_from.m_sep)
273     {}
274     column_vector_string_ref& operator=(const column_vector_string_ref& a_from){
275       if(&a_from==this) return *this;
276       m_sep = a_from.m_sep;
277       return *this;
278     }
279   public:
280     bool get_entry(std::vector<std::string>& a_v) const {
281       if(!_fetch_entry()) {a_v.clear();return false;}
282       a_v = m_ref;
283       return true;
284     }
285   protected:
286     bool _fetch_entry() const {
287       if(!parent::_fetch_entry()) return false;
288       get_lines(m_value,m_ref);
289       return true;
290     }
291   protected:
292     std::vector<std::string>& m_ref;
293     char m_sep;
294     std::string m_value;
295   };
296 
297   class column_vector_string : public column_vector_string_ref {
298     typedef column_vector_string_ref parent;
299   public:
300     static cid id_class() {return _cid_std_vector<std::string>();}
301   public: //icol
302     virtual void* cast(cid a_class) const {
303       if(void* p = cmp_cast<column_vector_string>(this,a_class)) return p;
304       return parent::cast(a_class);
305     }
306     virtual cid id_cls() const {return id_class();}
307     virtual const std::string& name() const {return m_leaf.name();}
308   public:
309     column_vector_string(ifile& a_file,branch& a_branch,leaf_string& a_leaf,int64& a_index,char a_sep)
310     :parent(a_file,a_branch,a_leaf,a_index,m_value,a_sep)
311     {}
312     virtual ~column_vector_string(){}
313   protected:
314     column_vector_string(const column_vector_string& a_from)
315     :read::icol(a_from)
316     ,parent(a_from)
317     ,m_value(a_from.m_value)
318     {}
319     column_vector_string& operator=(const column_vector_string& a_from){
320       if(&a_from==this) return *this;
321       m_value = a_from.m_value;
322       return *this;
323     }
324   public:
325     const std::vector<std::string>& get_value() const {return m_value;}
326   protected:
327     std::vector<std::string> m_value;
328   };
329 
330   // to read row_wise columns with vector of basic types :
331   template <class T>
332   class std_vector_column_ref : public virtual read::icolumn<T> {
333     typedef read::icolumn<T> parent;
334   public:
335     static cid id_class() {return 200+_cid(T())+10000;}
336   public: //icol
337     virtual void* cast(cid a_class) const {
338       if(void* p = cmp_cast<std_vector_column_ref>(this,a_class)) return p;
339       return parent::cast(a_class);
340     }
341     virtual cid id_cls() const {return id_class();}
342   public: //icol
343     virtual const std::string& name() const {return m_leaf.name();}
344   public: //icolumn<T>
345     virtual bool fetch_entry() const {return _fetch_entry();}
346     virtual bool get_entry(T& a_v) const {
347       if(!_fetch_entry()) {a_v = T();return false;}
348       if(m_ref.empty()) {a_v = T();return false;}
349       a_v = m_ref[0];
350       return true;
351     }
352   public:
353     std_vector_column_ref(ifile& a_file,branch& a_branch,leaf<T>& a_leaf,int64& a_index,std::vector<T>& a_ref)
354     :m_file(a_file)
355     ,m_branch(a_branch)
356     ,m_leaf(a_leaf)
357     ,m_index(a_index) //WARNING : we keep the ref !
358     ,m_ref(a_ref)
359     {}
360     virtual ~std_vector_column_ref(){}
361   protected:
362     std_vector_column_ref(const std_vector_column_ref& a_from)
363     :read::icol(a_from)
364     ,parent(a_from)
365     ,m_file(a_from.m_file)
366     ,m_branch(a_from.m_branch)
367     ,m_leaf(a_from.m_leaf)
368     ,m_index(a_from.m_index)
369     ,m_ref(a_from.m_ref)
370     {}
371     std_vector_column_ref& operator=(const std_vector_column_ref& a_from){
372       if(&a_from==this) return *this;
373       return *this;
374     }
375   protected:
376     bool _fetch_entry() const {
377       unsigned int n;
378       if(!m_branch.find_entry(m_file,uint32(m_index),n)) {m_ref.clear();return false;}
379       m_leaf.value(m_ref);
380       return true;
381     }
382   protected:
383     ifile& m_file;
384     branch& m_branch;
385     leaf<T>& m_leaf;
386     int64& m_index; //WARNING : a ref.
387     std::vector<T>& m_ref;
388   };
389 
390   // to read column_wise columns with vector of basic types :
391   template <class RT,class T>
392   class column_element_ref : public virtual read::icolumn<T> {
393     typedef read::icolumn<T> parent;
394   public:
395     static cid id_class() {return 300+_cid(T())+10000;}
396   public: //icol
397     virtual void* cast(cid a_class) const {
398       if(void* p = cmp_cast<column_element_ref>(this,a_class)) return p;
399       return parent::cast(a_class);
400     }
401     virtual cid id_cls() const {return id_class();}
402   public: //icol
403     virtual const std::string& name() const {return m_leaf.name();}
404   public: //icolumn<T>
405     virtual bool fetch_entry() const {return _fetch_entry();}
406     virtual bool get_entry(T& a_v) const {
407       if(!_fetch_entry()) {a_v = T();return false;}
408       a_v = m_ref;
409       return true;
410     }
411   public:
412     column_element_ref(ifile& a_file,branch_element& a_branch,leaf_element& a_leaf,int64& a_index,T& a_ref)
413     :m_file(a_file)
414     ,m_be(a_branch)
415     ,m_leaf(a_leaf)
416     ,m_index(a_index) //WARNING : we keep the ref !
417     ,m_ref(a_ref)
418     {}
419     virtual ~column_element_ref(){}
420   protected:
421     column_element_ref(const column_element_ref& a_from)
422     :read::icol(a_from),parent(a_from)
423     ,m_file(a_from.m_file)
424     ,m_be(a_from.m_be)
425     ,m_leaf(a_from.m_leaf)
426     ,m_index(a_from.m_index)
427     ,m_ref(a_from.m_ref)
428     {}
429     column_element_ref& operator=(const column_element_ref& a_from){
430       if(&a_from==this) return *this;
431       return *this;
432     }
433   protected:
434     bool _fetch_entry() const {
435       unsigned int n;
436       if(!m_be.find_entry(m_file,uint32(m_index),n)) {m_ref = T();return false;}
437       iro* obj = m_be.object(); //Not owner.
438       if(!obj)  {m_ref = T();return false;}
439       RT* v = id_cast<iro,RT>(*obj);
440       if(!v)  {m_ref = T();return false;}
441       m_ref = *v; //it assumes a T::operator=(RT)
442       return true;
443     }
444   protected:
445     ifile& m_file;
446     branch_element& m_be;
447     leaf_element& m_leaf;
448     int64& m_index; //WARNING : a ref.
449     T& m_ref;
450   };
451 
452   template <class RT,class T>
453   class column_element : public column_element_ref<RT,T> {
454     typedef column_element_ref<RT,T> parent;
455   public:
456     static cid id_class() {return 300+_cid(T());}
457   public: //icol
458     virtual void* cast(cid a_class) const {
459       if(void* p = cmp_cast<column_element>(this,a_class)) return p;
460       return parent::cast(a_class);
461     }
462     virtual cid id_cls() const {return id_class();}
463   public:
464     column_element(ifile& a_file,branch_element& a_branch,leaf_element& a_leaf,int64& a_index)
465     :parent(a_file,a_branch,a_leaf,a_index,m_value)
466     ,m_value(T())
467     {}
468     virtual ~column_element(){}
469   protected:
470     column_element(const column_element& a_from)
471     :read::icol(a_from)
472     ,read::icolumn<T>(a_from)
473     ,parent(a_from)
474     ,m_value(a_from.m_value)
475     {}
476     column_element& operator=(const column_element& a_from){
477       if(&a_from==this) return *this;
478       m_value = a_from.m_value;
479       return *this;
480     }
481   public:
482     const T& get_value() const {return m_value;}
483   protected:
484     T m_value;
485   };
486 
487 public:
488   ntuple(tree& a_tree):m_tree(a_tree),m_index(-1){
489 #ifdef TOOLS_MEM
490     mem::increment(s_class().c_str());
491 #endif
492   }
493   virtual ~ntuple() {
494     safe_clear<read::icol>(m_cols);
495 #ifdef TOOLS_MEM
496     mem::decrement(s_class().c_str());
497 #endif
498   }
499 protected:
500   ntuple(const ntuple& a_from)
501   :parent(a_from),m_tree(a_from.m_tree){
502 #ifdef TOOLS_MEM
503     mem::increment(s_class().c_str());
504 #endif
505   }
506   ntuple& operator=(const ntuple&){return *this;}
507 public:
508   bool initialize(std::ostream& a_out,const ntuple_binding& a_bd = ntuple_binding(),bool a_enforce_double = false) {
509     safe_clear<read::icol>(m_cols);
510 
511     std::vector<base_leaf*> leaves;
512     m_tree.find_leaves(leaves);
513     tools_vforcit(base_leaf*,leaves,it) {
514       base_leaf* bl = (*it);
515       if(find_named<read::icol>(m_cols,bl->name())) {
516         a_out << "tools::rroot::ntuple::initialize :"
517               << " column with name " << sout(bl->name())
518               << " already exists."
519               << std::endl;
520         safe_clear<read::icol>(m_cols);
521         return false;
522       }
523       branch* _branch = m_tree.find_leaf_branch(*bl);
524       if(!_branch) {
525         a_out << "tools::rroot::ntuple::initialize :"
526               << " can't find branch of leaf " << sout(bl->name()) << "."
527               << std::endl;
528         safe_clear<read::icol>(m_cols);
529         return false;
530       }
531 
532       //a_out << "tools::rroot::ntuple::initialize :"
533       //      << " branch " << _branch->name()
534       //      << ", entries " << _branch->entry_number() << "."
535       //      << std::endl;
536 
537 #define TOOLS_RROOT_NTUPLE_CREATE_COL(a__type) \
538       if(leaf<a__type>* lf_##a__type = safe_cast<base_leaf, leaf<a__type> >(*bl) ){\
539         cid user_cid;void* user_obj;\
540         a_bd.find_user_obj(bl->name(),user_cid,user_obj);\
541         typedef leaf<a__type> leaf_t;\
542         if(!user_obj) {\
543           if(a_enforce_double) {\
544             column<double,leaf_t>* col = new column<double,leaf_t>(m_tree.file(),*_branch,*lf_##a__type,m_index);\
545             m_cols.push_back(col);\
546           } else {\
547             column<a__type,leaf_t>* col = new column<a__type,leaf_t>(m_tree.file(),*_branch,*lf_##a__type,m_index);\
548             m_cols.push_back(col);\
549           }\
550         } else {\
551           const base_leaf* lfc = bl->leaf_count();\
552           if(lfc) {\
553             /*::printf("debug : ntuple : create col leaf count : %s\n",bl->name().c_str());*/\
554             if(user_cid!=_cid_std_vector<a__type>()) {\
555               a_out << "tools::rroot::ntuple::initialize :"\
556                     << " for leaf with name " << sout(bl->name())\
557                     << ", user variable type is not a std::vector of " << #a__type << "."\
558                     << std::endl;\
559               safe_clear<read::icol>(m_cols);\
560               return false;\
561             }\
562             std::vector<a__type>* user_var = (std::vector<a__type>*)user_obj;\
563             std_vector_column_ref<a__type>* col = new std_vector_column_ref<a__type>\
564         (m_tree.file(),*_branch,*lf_##a__type,m_index,*user_var);\
565             m_cols.push_back(col);\
566           } else {\
567             /*::printf("debug : ntuple : create col : %s\n",bl->name().c_str());*/\
568             if(user_cid!=_cid(a__type())) {\
569               a_out << "tools::rroot::ntuple::initialize :"\
570                     << " for leaf with name " << sout(bl->name())\
571                     << ", user variable type is not a " << #a__type << "."\
572                     << std::endl;\
573               safe_clear<read::icol>(m_cols);\
574               return false;\
575             }\
576             a__type* user_var = (a__type*)user_obj;\
577             column_ref<a__type,leaf_t>* col =\
578               new column_ref<a__type,leaf_t>(m_tree.file(),*_branch,*lf_##a__type,m_index,*user_var);\
579             m_cols.push_back(col);\
580           }\
581   }\
582       }
583 
584       //below types are in sync with wroot/ntuple.
585 
586            TOOLS_RROOT_NTUPLE_CREATE_COL(char)
587       else TOOLS_RROOT_NTUPLE_CREATE_COL(short)
588       else TOOLS_RROOT_NTUPLE_CREATE_COL(int)
589       else TOOLS_RROOT_NTUPLE_CREATE_COL(float)
590       else TOOLS_RROOT_NTUPLE_CREATE_COL(double)
591 
592       else if(leaf_string* ls = safe_cast<base_leaf, leaf_string >(*bl) ){
593         char sep = '\n';
594         cid user_cid;void* user_obj;
595         if(!a_bd.find_user_obj(bl->name(),user_cid,user_obj)) {
596           column_vector_string* col = new column_vector_string(m_tree.file(),*_branch,*ls,m_index,sep);
597           m_cols.push_back(col);
598   } else if(user_cid==_cid_std_vector<std::string>()) {
599           std::vector<std::string>* user_var = (std::vector<std::string>*)user_obj;
600           if(user_var) {
601             column_vector_string_ref* col = new column_vector_string_ref(m_tree.file(),*_branch,*ls,m_index,*user_var,sep);
602             m_cols.push_back(col);
603     } else {
604       column_vector_string* col = new column_vector_string(m_tree.file(),*_branch,*ls,m_index,sep);
605             m_cols.push_back(col);
606           }
607         } else if(user_cid==_cid(std::string())) {
608           std::string* user_var = (std::string*)user_obj;
609           if(user_var) {
610             column_string_ref* col = new column_string_ref(m_tree.file(),*_branch,*ls,m_index,*user_var);
611             m_cols.push_back(col);
612     } else {
613       column_string* col = new column_string(m_tree.file(),*_branch,*ls,m_index);
614             m_cols.push_back(col);
615           }
616   } else {
617           a_out << "tools::rroot::ntuple::initialize :"
618                 << " for leaf with name " << sout(ls->name())
619                 << ", user variable type is not a std::string or a std::vector<std::string>."
620                 << ". It's class id is " << user_cid << "."
621                 << std::endl;
622           safe_clear<read::icol>(m_cols);
623           return false;
624   }
625 
626       } else if(leaf_element* le = safe_cast<base_leaf,leaf_element>(*bl) ){
627 
628         branch_element* be = safe_cast<branch,branch_element>(*_branch);
629         if(!be) {
630           a_out << "tools::rroot::ntuple::initialize : branch is not a branch_element." << std::endl;
631           safe_clear<read::icol>(m_cols);
632           return false;
633         }
634 
635 #define TOOLS_RROOT_NTUPLE_CREATE_VEC_COL(a__name,a__type) \
636         if(be->class_name()==a__name) {\
637           /*::printf("debug : ntuple : create vec col : %s\n",bl->name().c_str());*/\
638           typedef a__type el_t;\
639           std::vector<el_t>* user_var = a_bd.find_vector_variable<el_t>(bl->name());\
640           if(user_var) {\
641             typedef column_element_ref< stl_vector<el_t> , std::vector<el_t> > ce_t;\
642             ce_t* col = new ce_t(m_tree.file(),*be,*le,m_index,*user_var);\
643             m_cols.push_back(col);\
644     } else {\
645             typedef column_element< stl_vector<el_t> , std::vector<el_t> > ce_t;\
646             ce_t* col = new ce_t(m_tree.file(),*be,*le,m_index);\
647             m_cols.push_back(col);\
648     }\
649   }
650 
651              TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<char>",char)
652         else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<short>",short)
653       //else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<unsigned short>",unsigned short)
654       //else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<unsigned int>",unsigned int)
655         else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<int>",int)
656         else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<float>",float)
657         else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<double>",double)
658 
659       //else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<string>",std::string)
660       //else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<unsigned long>",uint64) //beurk
661 
662         // WARNING : take care of the space in "> >".
663   /* VisualC++ : the below does not compile.
664         else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<vector<unsigned short> >",std::vector<unsigned short>)
665         else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<vector<short> >",std::vector<short>)
666         else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<vector<unsigned int> >",std::vector<unsigned int>)
667         else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<vector<int> >",std::vector<short>)
668         else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<vector<float> >",std::vector<float>)
669         else TOOLS_RROOT_NTUPLE_CREATE_VEC_COL("vector<vector<double> >",std::vector<double>)
670         */
671 
672         else {
673           a_out << "tools::rroot::ntuple::initialize :"
674                 << " WARNING : leaf element"
675                 << " with name " << sout(bl->name())
676                 << ",title " << sout(bl->title())
677                 << " br_elem class name " << be->class_name() << "."
678                 << " entries " << be->entry_number() << "."
679                 << std::endl;
680         }
681 
682       } else {
683         a_out << "tools::rroot::ntuple::initialize :"
684               << " WARNING : column type not yet handled for leaf"
685               << " with name " << sout(bl->name())
686               << " and title " << sout(bl->title()) << "."
687               << " s_cls() is " << sout(bl->s_cls()) << "."
688               << " Not fatal."
689               << std::endl;
690       }
691 
692     }
693 
694 #undef TOOLS_RROOT_NTUPLE_CREATE_VEC_COL
695 #undef TOOLS_RROOT_NTUPLE_CREATE_COL
696 
697     size_t num = m_cols.size();
698     if(!num) {
699       a_out << "tools::rroot::ntuple::initialize :"
700             << " zero columns."
701             << std::endl;
702       return false;
703     }
704 
705    {tools_vforcit(column_binding,a_bd.columns(),it) {
706       if(!find_named<read::icol>(m_cols,(*it).name())) {
707         a_out << "tools::rroot::ntuple::initialize :"
708               << " warning : for column binding with name " << sout((*it).name()) << ", no ntuple column found."
709               << std::endl;
710       }
711     }}
712 
713     //a_out << "tools::rroot::ntuple::initialize :"
714     //      << " number of columns " << num << "."
715     //      << std::endl;
716 
717     return true;
718   }
719 
720   bool get_row() const {
721     bool status = true;
722     tools_vforcit(read::icol*,m_cols,it) {
723       if(!(*it)->fetch_entry()) {
724         m_tree.out() << "tools::rroot::ntuple::get_row : fetch_entry() failed for leaf " << (*it)->name() << std::endl;
725         status = false;
726       }
727     }
728     return status;
729   }
730 protected:
731   tree& m_tree;
732   std::vector<read::icol*> m_cols;
733   int64 m_index;
734 };
735 
736 // for gopaw :
737 
738 class fac_tree_holder {
739 public:
740   fac_tree_holder(ifac* a_fac,tree* a_tree):m_fac(a_fac),m_tree(a_tree){}  //own a_fac,a_tree.
741   virtual ~fac_tree_holder() {delete m_tree;delete m_fac;}
742 protected:
743   fac_tree_holder(const fac_tree_holder&){}
744   fac_tree_holder& operator=(const fac_tree_holder&){return *this;}
745 protected:
746   ifac* m_fac;
747   tree* m_tree;
748 };
749 
750 class fac_tree_ntuple : public fac_tree_holder, public ntuple { //fac_tree_holder must be first.
751   typedef ntuple parent;
752 public:
753   static const std::string& s_class() {
754     static const std::string s_v("tools::rroot::fac_tree_ntuple");
755     return s_v;
756   }
757   virtual const std::string& s_cls() const {return s_class();}
758 public:
759   fac_tree_ntuple(ifac* a_fac,tree* a_tree) //own these.
760   :fac_tree_holder(a_fac,a_tree)
761   ,parent(*a_tree)  //deleted first.
762   {}
763   virtual ~fac_tree_ntuple() {}
764 protected:
765   fac_tree_ntuple(const fac_tree_ntuple& a_from):read::intuple(a_from),fac_tree_holder(a_from),parent(a_from){}
766   fac_tree_ntuple& operator=(const fac_tree_ntuple&){return *this;}
767 };
768 
769 }}
770 
771 #endif