RootNTuple.cxx
Go to the documentation of this file.
1 
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15 
16 #ifdef _MSC_VER
17 #include "w32pragma.h"
18 #endif
19 
20 #include "RootNTuple.h"
21 
22 #include "RootBranch.h"
23 
24 #include "axes/Range.h"
25 #include "pattern/Observer.h"
26 #include "pattern/string_convert.h"
27 
28 #include "TBranch.h"
29 #include "TTree.h"
30 
31 #ifdef SSTREAM_DEFECT
32 #include <strstream>
33 #else
34 #include <sstream>
35 #endif
36 
37 #ifdef _MSC_VER
38 #define isinf _isinf
39 #endif
40 
41 #include <cmath>
42 #include <cassert>
43 
44 using std::string;
45 using std::vector;
46 using std::runtime_error;
47 
48 using namespace hippodraw;
49 
51 RootNTuple ( TTree * tree )
52  : DataSource ( false ),
53  m_tree ( tree ),
54  m_cur_entry ( UINT_MAX )
55 {
56  initBranches ();
57 }
58 
61  : DataSource ( false ),
62  m_tree ( 0 ),
63  m_cur_entry ( UINT_MAX )
64 {
65 }
66 
68 {
70 
71  BranchList_t::iterator first = m_data.begin();
72  while ( first != m_data.end() ) {
73  delete *first++;
74  }
75 
76  CacheList_t::iterator cache = m_data_cache.begin ();
77  while ( cache != m_data_cache.end() ) {
78  vector< double > * p = *cache++;
79  if ( p != 0 ) {
80  delete p;
81  }
82  }
83 }
84 
88 void
91 {
92  m_dups.clear ();
93 
94  TObjArray * branches = m_tree -> GetListOfBranches ();
95  Int_t number = branches -> GetEntries ();
96 
97  for ( Int_t i = 0; i < number; i++ )
98  {
99  TObject * object = branches -> At ( i );
100  TBranch * branch = dynamic_cast < TBranch * > ( object );
101  if ( branch != 0 )
102  {
103  branch -> SetBasketSize ( 320000 );
104 
105  RootBranch * h_branch = new RootBranch ( branch );
106  const string name = object -> GetName ();
107  int index = indexOf ( name );
108  if ( index < 0 ) {
109  addColumn ( name, h_branch );
110  m_multiDimensional.push_back( h_branch -> isMultiDimensional() );
111  }
112  else {
113  m_dups.push_back ( name );
114  RootBranch * rb = m_data [ index ];
115  m_data [ index ] = h_branch;
116  delete rb;
117  }
118  }
119  }
120 }
121 
122 bool
124 rotateWheels( std::vector < int > & wheels,
125  const std::vector < int > & sz,
126  unsigned int d )
127 {
128  bool full = false;
129 
130  if( d < sz.size() - 1 ) // Still not at the last wheel...
131  {
132  if( rotateWheels( wheels, sz, d + 1 ) == true )
133  {
134  wheels[d]++;
135 
136  full = ( wheels[d] == static_cast< int >( sz[d] ) ) ?
137  true : false;
138 
139  if( full )
140  wheels[d] = 0;
141 
142  return full;
143  }
144  }
145  else // Finally at the last wheel. Phew!
146  {
147  wheels[ d ]++;
148  full = ( wheels[d] == static_cast< int >( sz[d] ) ) ? true : false;
149 
150  if( full )
151  wheels[ d ] = 0;
152  return full;
153  }
154 
155  return full;
156 }
157 
158 void
161 {
163 }
164 
165 unsigned int
167 rows() const
168 {
169  Double_t number = m_tree -> GetEntries ();
170  return static_cast < unsigned int > ( number );
171 }
172 
173 void
175 fillDataCache ( unsigned int column )
176 {
177  unsigned int size = RootNTuple::rows ();
178  vector < double > * cache = new vector < double > ( size );
179  RootBranch * data = m_data [ column ];
180  for ( unsigned int row = 0; row < size; row++ ) {
181  double value = data -> valueAt ( row );
182  cache -> operator [] ( row ) = value;
183  }
184  m_data_cache [ column ] = cache;
185 }
186 
187 bool
189 empty () const
190 {
191  return rows () == 0;
192 }
193 
194 double
196 valueAt ( unsigned int row, unsigned int column ) const
197 {
198  if ( m_data_cache [ column ] == 0 ) {
199  RootNTuple * rtuple = const_cast < RootNTuple * > ( this );
200  rtuple -> fillDataCache ( column );
201  }
202  const vector < double > & cache = *m_data_cache [ column ];
203 
204  return cache[row];
205 }
206 
207 double
209 valueAtNoCache ( unsigned int row, unsigned int column ) const
210 {
211  double value = 0;
212  if ( column < m_data.size () ) { // within original ROOT file
213  RootBranch * data = m_data [ column ];
214  value = data -> valueAt ( row );
215  }
216  else { // added column
217  value = valueAt ( row, column );
218  }
219  return value;
220 }
221 
224 getType ( unsigned int column ) const
225 {
226  RootBranch * data = m_data [ column ];
227 
228  return data -> getType ();
229 }
230 
231 double *
233 doubleArrayAt ( unsigned int row, unsigned int column ) const
234 {
235  RootBranch * data = m_data [ column ];
236 
237  return data -> doubleArrayAt ( row );
238 }
239 
240 float *
242 floatArrayAt ( unsigned int row, unsigned int column ) const
243 {
244  RootBranch * data = m_data [ column ];
245 
246  return data -> floatArrayAt ( row );
247 }
248 
249 int *
251 intArrayAt ( unsigned int row, unsigned int column ) const
252 {
253  RootBranch * data = m_data [ column ];
254 
255  return data -> intArrayAt ( row );
256 }
257 
258 unsigned int *
260 uintArrayAt ( unsigned int row, unsigned int column ) const
261 {
262  RootBranch * data = m_data [ column ];
263 
264  return data -> uintArrayAt ( row );
265 }
266 
267 
268 void
271 {
272  for ( unsigned int i = 0; i < m_data_cache.size (); i++ ) {
273  if ( m_data_cache[i] != 0 ) {
274  delete m_data_cache [i];
275  }
276  m_data_cache[i] = 0;
277  }
278 }
279 
280 void
282 reserve ( unsigned int )
283 {
284  // does nothing.
285 }
286 
287 double
289 operator [] ( std::vector < unsigned int > & ) const // indices ) const
290 {
291  assert ( false );
292  return 0.;
293 }
294 
299 const vector < double > &
301 getRow ( unsigned int row ) const
302 {
303  const vector < string > & labels = getLabels ();
304  unsigned int size = labels.size();
305  for ( unsigned int column = 0; column < size; column++ ) {
306  const string & label = labels [ column ];
307  if ( isUseable ( label ) ) {
308  smartExpandRootNTuple ( label );
309  }
310  else {
311  std::string what ( "RootNTuple: can not export data source\n"
312  "because some column(s) cantain\n"
313  " variable length data" );
314  throw runtime_error ( what );
315  }
316  }
317 
318  size = m_data.size ();
319  m_array.resize ( size );
320  for ( unsigned int column = 0; column < size; column++ ) {
321  // Use this method to avoid reading whole column
322  RootBranch * branch = m_data [ column ];
323  m_array [ column ] = branch -> valueAt ( row );
324  }
325 
326  return m_array;
327 }
328 
329 int
331 addColumn ( const std::string & label,
332  RootBranch * branch )
333 {
334  // Check if label already exists.
335  int index = indexOf ( label );
336  if ( index >= 0 ) {
337  string what ( "RootNTuple Attempt to add a column whose label"
338  " is same as other column." );
339  throw runtime_error ( what );
340  }
341 
342  m_data.push_back ( branch );
343  m_data_cache.push_back ( 0 );
344  addLabel ( label );
345 
346  return m_data.size() - 1;
347 }
348 
349 
350 int
352 addColumn ( const std::string & label,
353  const std::vector < double > & col )
354 {
355  // Check if label already exists.
356  int index = indexOf ( label );
357  if ( index >= 0 ) {
358  string what ( "RootNTuple Attempt to add a column whose label"
359  " is same as other column." );
360  throw runtime_error ( what );
361  }
362 
363  unsigned int new_size = col.size ();
364  // Check if column has right size.
365  if ( m_data.empty () == false ) {
366  unsigned int old_size = rows ();
367 
368  if ( old_size != 0 && old_size != new_size ) {
369  string what ( "RootNTuple Attempt to add a column whose size"
370  " is not equal to other columns." );
371  throw runtime_error ( what );
372  }
373  }
374  vector < double > * vec = new vector < double > ( col );
375  m_data_cache.push_back ( vec );
376  m_multiDimensional.push_back ( false );
377 
378  addLabel ( label );
379 
380  return m_data.size() - 1;
381 }
382 
383 void
385 replaceColumn ( unsigned int col,
386  const std::vector < double > & data )
387 {
388  unsigned int size = columns ();
389  if ( col >= size ) {
390  const string what
391  ( "RootNTuple: Attempt to replace non-existant column." );
392  throw runtime_error ( what );
393  }
394 
395  size = rows ();
396  unsigned int new_size = data.size ();
397  if ( size != 0 && size != new_size ) {
398  const string what
399  ( "RootNTuple: Attempt to replace column with one whose "
400  "size is not equal to other columns." );
401  throw runtime_error ( what );
402  }
403  m_data_cache [ col ] -> resize ( new_size );
404  std::copy ( data.begin(), data.end(), m_data_cache [ col ] -> begin() );
405 
406  notifyObservers ();
407 }
408 
409 void
411 setShape ( std::vector < unsigned int > & shape )
412 {
413  assert ( false ); // not tested
414  m_shape = shape;
415 }
416 
417 const vector < unsigned int > &
419 getShape () const
420 {
421  assert ( false ); // not tested
422  return m_shape;
423 }
424 
425 bool
427 isMultiDimensional ( const std::string & column ) const
428 {
429  unsigned int colIndex = indexOf( column );
430 
431  return m_multiDimensional[ colIndex ];
432 }
433 
434 bool
436 isUseable ( const std::string & column ) const
437 {
438  unsigned int colIndex = indexOf( column );
439  RootBranch * branch = m_data [ colIndex ];
440 
441  return branch -> isUseable ();
442 }
443 
447 void
449 fillShape ( std::vector < int > & shape, unsigned int column ) const
450 {
451  shape.clear ();
452  shape.push_back ( RootNTuple::rows () ); // avoid QtRootNTuple
453  BranchList_t::size_type size = m_data.size ();
454  if ( column < size ) { // do nothing for added columns
455  RootBranch * col = m_data [ column ];
456  const vector < int > & sub_shape = col -> getShape ();
457  unsigned int rank = sub_shape.size ();
458 
459  for ( unsigned int i = 0; i < rank; i++ ) {
460  shape.push_back ( sub_shape [ i ] );
461  }
462  }
463 }
464 
465 bool
467 setReleventIndex( const std::string & column,
468  const std::vector< unsigned int >& index )
469 {
470  // Do not call this function on scalars
471  assert( isMultiDimensional( column ) );
472 
473  unsigned int colIndex = indexOf ( column );
474  RootBranch * col = m_data [ colIndex ];
475 
476  col -> setReleventIndex( index );
477 
478  return true;
479 }
480 
481 
483 TBranch *
485 getTBranch( const std::string & column )
486 {
487  unsigned int colIndex = indexOf ( column );
488  RootBranch * col = m_data [ colIndex ];
489 
490  return col -> getTBranch();
491 }
492 
493 
496 void
498 smartExpandRootNTuple ( const std::string & column ) const
499 {
500  // Expansion is --SURELY NOT-- needed if the data is not multidimensional
501  if ( isMultiDimensional( column ) == true )
502  {
503  // Has the expansion of this column already taken place?
504  bool flag = false;
505  const vector< string > & labels = getLabels();
506 
507  for( unsigned int i = 0; i < labels.size(); i++ ) {
508  const string & label = labels[i];
509  if( label.find( column + "[" ) != string::npos ) {
510  flag = true;
511  break; // No need to check all the labels
512  }
513  }
514 
515  // If no then go ahead and expand
516  if( flag == false )
517  {
518  unsigned int colIndex = indexOf ( column );
519  RootBranch * colRootBranch = m_data [ colIndex ];
520  TBranch * colTBranch = colRootBranch -> getTBranch();
521 
522  unsigned int dims = colRootBranch -> getRank ();
523  const vector < int > & sz =colRootBranch -> getShape ();
524  int nelems = colRootBranch -> numberOfElements();
525 
526  vector< unsigned int > indx( dims, 0);
527 
528  vector< int > wheels( dims, 0);
529  wheels[ dims - 1 ] = -1;
530  RootNTuple * rtuple = const_cast < RootNTuple * > ( this );
531 
532  for( int i = 0; i < nelems; i++ )
533  {
534 #ifdef SSTREAM_DEFECT
535  std::ostrstream namestream;
536 #else
537  std::ostringstream namestream;
538 #endif
539  namestream << column;
540 
541  rtuple -> rotateWheels( wheels, sz, 0 );
542  for ( unsigned int j = 0; j < dims; j++ ) {
543  namestream << "[" << wheels[ j ] << "]";
544  }
545 
546  colTBranch -> SetBasketSize ( 320000 );
547  RootBranch * h_branch = new RootBranch ( colTBranch );
548 
549  for( unsigned int k = 0; k < wheels.size(); k++ )
550  indx[ k ] = static_cast< unsigned int > ( wheels[ k ] );
551  h_branch -> setReleventIndex( indx );
552 
553  rtuple -> addColumn ( namestream.str(), h_branch );
554  rtuple -> m_multiDimensional.push_back( false );
555  }
556  }
557  }
558 }
559 
560 void
562 expandIfNeeded ( const std::string & column ) const
563 {
564  string::size_type pos = column.find_first_of ( '[' );
565 
566  if ( pos != string::npos ) {
567  const string label = column.substr ( 0, pos );
568 
569  if (isMultiDimensional ( label ) ) {
570  smartExpandRootNTuple ( label );
571  }
572  }
573 }
574 
575 void
577 expandIfNeeded ( const std::vector < std::string > & labels ) const
578 {
579  unsigned int size = labels.size ();
580 
581  for ( unsigned int i = 0; i < size; i++ ) {
582  const string & column = labels [ i ];
583  expandIfNeeded ( column );
584  }
585 }
586 
587 const vector < double > &
589 getColumn ( const std::string & name ) const
590 {
591  expandIfNeeded ( name );
592  throwIfInvalidLabel ( name );
593 
594  int index = indexOf ( name );
595 
596  return RootNTuple::getColumn ( index );
597 }
598 
599 const vector < double > &
601 getColumn ( const std::string & name,
602  const std::vector < int > & indices ) const
603 {
604  const string label = createBinding ( name, indices );
605 
606  return RootNTuple::getColumn ( label );
607 }
608 
609 const vector < double > &
611 getColumn ( unsigned int index ) const
612 {
613  isValidColumn ( index );
614 
615  if ( m_data_cache [ index ] == 0 ) {
616  RootNTuple * rtuple = const_cast < RootNTuple * > ( this );
617  rtuple -> fillDataCache ( index );
618  }
619 
620  return *m_data_cache [ index ];
621 }
622 
623 std::string
625 createBinding ( const std::string & label,
626  const std::vector < int > & indices ) const
627 {
628  string text ( label );
629 
630  unsigned int size = indices.size();
631  for ( unsigned int i = 0; i < size; i++ ) {
632  text += "[";
633  text += String::convert ( indices[i] );
634  text += "]";
635  }
636 
637  return text;
638 }
unsigned int i
virtual bool isUseable(const std::string &label) const
Returns true if the column is usable in the context of a DataSource.
Definition: RootNTuple.cxx:436
const std::vector< unsigned int > & getShape() const
Returns the shape of the data elements.
Definition: RootNTuple.cxx:419
Type
The type of data on the branch.
Definition: RootDataType.h:25
The ROOT TTree class.
virtual void notifyObservers() const
Notifies Observer objects of a change.
Definition: Observable.cxx:93
virtual void fillShape(std::vector< int > &v, unsigned int column) const
Fills the vector with the shape of a column.
Definition: RootNTuple.cxx:449
TBranch * getTBranch(const std::string &column)
Get the TBranch associated with this column.
Definition: RootNTuple.cxx:485
virtual void reserve(unsigned int)
Does nothing as the contained ROOT file controls the size.
Definition: RootNTuple.cxx:282
std::vector< std::string > m_dups
A list of labels that duplicated others in a DataSource file.
Definition: DataSource.h:100
hippodraw::RootNTuple class interface.
TTree * m_tree
The ROOT TTree object which is the source of the data.
Definition: RootNTuple.h:64
std::string createBinding(const std::string &name, const std::vector< int > &indices) const
Creates complete binding string from the array variable name and indexes.
Definition: RootNTuple.cxx:625
A DataSource class implemented with a ROOT TBranch objects from a ROOT TTree to store the column data...
Definition: RootNTuple.h:37
virtual float * floatArrayAt(unsigned int row, unsigned int column) const
Returns pointer to a float array type in given row.
Definition: RootNTuple.cxx:242
void * data(numeric::array arr)
Definition: num_util.cpp:389
virtual void setShape(std::vector< unsigned int > &shape)
Sets the shape of the data elements.
Definition: RootNTuple.cxx:411
A class to read data from a ROOT TBranch.
Definition: RootBranch.h:40
virtual void addLabel(const std::string &label)
Adds a new label for a column.
Definition: DataSource.cxx:154
column
The column indices for 2 dimension data point tuple.
virtual ~RootNTuple()
The destructor.
Definition: RootNTuple.cxx:67
void replaceColumn(unsigned int index, const std::vector< double > &data)
Replaces the data in column index.
Definition: RootNTuple.cxx:385
virtual double valueAtNoCache(unsigned int row, unsigned int column) const
Returns the value in the table in position given by the row and column indexes without storing it int...
Definition: RootNTuple.cxx:209
virtual double * doubleArrayAt(unsigned int row, unsigned int column) const
Returns pointer to a double array type in given row.
Definition: RootNTuple.cxx:233
virtual void willDelete(const Observable *)
Notifies this Observer object that one of its Observable objects is about to be deleted.
Definition: Observer.cxx:25
void fillDataCache(unsigned int column)
Fills the data cache for column column.
Definition: RootNTuple.cxx:175
virtual double valueAt(unsigned int row, unsigned int column) const
Returns the value in the table in position given by the row and column indexes.
Definition: RootNTuple.cxx:196
std::vector< intptr_t > shape(numeric::array arr)
Definition: num_util.cpp:317
void smartExpandRootNTuple(const std::string &column) const
Suppose we encounter a RootNTuple which has multi-dimensional data sitting in the rows of the concern...
Definition: RootNTuple.cxx:498
The namespace for conversion to string.
std::vector< unsigned int > m_shape
The shape of the data.
Definition: DataSource.h:96
unsigned int getRank() const
Returns the rank of the data source.
Definition: DataSource.cxx:343
std::vector< bool > m_multiDimensional
Answers if rows of column are composed of the multidimensional data.
Definition: RootNTuple.h:60
virtual const std::vector< std::string > & getLabels() const
Returns the list of available labels.
Definition: DataSource.cxx:172
bool rotateWheels(std::vector< int > &wheels, const std::vector< int > &sz, unsigned int d)
A hack to generate labels.
Definition: RootNTuple.cxx:124
virtual int * intArrayAt(unsigned int row, unsigned int column) const
Returns pointer to a int array type in given row.
Definition: RootNTuple.cxx:251
bool isValidColumn(unsigned int index) const
Returns true if index is valid, otherwise throws a DataSourceException.
Definition: DataSource.cxx:212
int addColumn(const std::string &label, RootBranch *)
Adds a column to the end of the RootNTuple.
Definition: RootNTuple.cxx:331
intp size(numeric::array arr)
Definition: num_util.cpp:296
int rank(numeric::array arr)
Definition: num_util.cpp:271
string convert(int i)
Converts an integer to a string.
CacheList_t m_data_cache
A cache of data already read.
Definition: RootNTuple.h:55
virtual unsigned int rows() const
Returns the size of first dimension, i.e.
Definition: RootNTuple.cxx:167
virtual const std::vector< double > & getRow(unsigned int i) const
Returns a const reference to slice along the axis known as a row.
Definition: RootNTuple.cxx:301
hippodraw::RootBranch class interface.
virtual void throwIfInvalidLabel(const std::string &label) const
Throws a DataSourceException object if label is not a valid label for this DataSource.
Definition: DataSource.cxx:268
hippodraw::RootData::Type getType(unsigned int column) const
Returns the type of data in column.
Definition: RootNTuple.cxx:224
virtual const std::vector< double > & getColumn(const std::string &name) const
Returns the data in the column with label name.
Definition: RootNTuple.cxx:589
hippodraw::Range class interface
virtual int indexOf(const std::string &label) const
Returns true if the specified column labeled label has been filled.
Definition: DataSource.cxx:193
unsigned int columns() const
Returns the number of columns or data arrays available from this DataSource.
Definition: DataSource.h:458
virtual bool empty() const
Returns true, if RootNTuple is empty, i.e.
Definition: RootNTuple.cxx:189
return index
Definition: PickTable.cxx:182
void expandIfNeeded(const std::vector< std::string > &labels) const
Expand the labels if needed.
Definition: RootNTuple.cxx:577
virtual void notifyObservers() const
Notifies observers.
Definition: RootNTuple.cxx:160
virtual void clear()
Removes all the cached data vectors, does not change the contained ROOT file.
Definition: RootNTuple.cxx:270
virtual double operator[](std::vector< unsigned int > &indices) const
Raises an assertion, as a RootNTuple does not really have shape.
Definition: RootNTuple.cxx:289
void initBranches()
Initializes the columns of the NTuple.
Definition: RootNTuple.cxx:90
virtual bool isMultiDimensional(const std::string &column) const
Answers if rows of column are composed of the multidimensional data.
Definition: RootNTuple.cxx:427
virtual unsigned int * uintArrayAt(unsigned int row, unsigned int column) const
Returns pointer to a unsigned int array type in given row and column.
Definition: RootNTuple.cxx:260
BranchList_t m_data
The RootBranch objects that contains the data.
Definition: RootNTuple.h:48
RootNTuple()
The default constructor.
Definition: RootNTuple.cxx:60
Observer class interface.
virtual bool setReleventIndex(const std::string &column, const std::vector< unsigned int > &index)
In case we are dealing with multidimensional data in rows of this column we would like to deal with o...
Definition: RootNTuple.cxx:467
The ROOT TBranch class.
std::vector< double > m_array
A temporary array that can be returned by const reference.
Definition: DataSource.h:88
Base class for DataSource.
Definition: DataSource.h:55

Generated for HippoDraw Class Library by doxygen