RootNTuple.cxx
Go to the documentation of this file.
1 
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15 
16 #include "RootNTuple.h"
17 
18 #include "RootBranch.h"
19 
20 #include "axes/Range.h"
21 #include "pattern/Observer.h"
22 #include "pattern/string_convert.h"
23 
24 #include "TBranch.h"
25 #include "TTree.h"
26 
27 #ifdef SSTREAM_DEFECT
28 #include <strstream>
29 #else
30 #include <sstream>
31 #endif
32 
33 #ifdef _MSC_VER
34 #define isinf _isinf
35 #endif
36 
37 #include <cmath>
38 #include <cassert>
39 
40 using std::string;
41 using std::vector;
42 using std::runtime_error;
43 
44 using namespace hippodraw;
45 
47 RootNTuple ( TTree * tree )
48  : DataSource ( false ),
49  m_tree ( tree ),
50  m_cur_entry ( UINT_MAX )
51 {
52  initBranches ();
53 }
54 
57  : DataSource ( false ),
58  m_tree ( 0 ),
59  m_cur_entry ( UINT_MAX )
60 {
61 }
62 
64 {
66 
67  BranchList_t::iterator first = m_data.begin();
68  while ( first != m_data.end() ) {
69  delete *first++;
70  }
71 
72  CacheList_t::iterator cache = m_data_cache.begin ();
73  while ( cache != m_data_cache.end() ) {
74  vector< double > * p = *cache++;
75  if ( p != 0 ) {
76  delete p;
77  }
78  }
79 }
80 
84 void
87 {
88  m_dups.clear ();
89 
90  TObjArray * branches = m_tree -> GetListOfBranches ();
91  Int_t number = branches -> GetEntries ();
92 
93  for ( Int_t i = 0; i < number; i++ )
94  {
95  TObject * object = branches -> At ( i );
96  TBranch * branch = dynamic_cast < TBranch * > ( object );
97  if ( branch != 0 )
98  {
99  branch -> SetBasketSize ( 320000 );
100 
101  RootBranch * h_branch = new RootBranch ( branch );
102  const string name = object -> GetName ();
103  int index = indexOf ( name );
104  if ( index < 0 ) {
105  addColumn ( name, h_branch );
106  m_multiDimensional.push_back( h_branch -> isMultiDimensional() );
107  }
108  else {
109  m_dups.push_back ( name );
110  RootBranch * rb = m_data [ index ];
111  m_data [ index ] = h_branch;
112  delete rb;
113  }
114  }
115  }
116 }
117 
118 bool
120 rotateWheels( std::vector < int > & wheels,
121  const std::vector < int > & sz,
122  unsigned int d )
123 {
124  bool full = false;
125 
126  if( d < sz.size() - 1 ) // Still not at the last wheel...
127  {
128  if( rotateWheels( wheels, sz, d + 1 ) == true )
129  {
130  wheels[d]++;
131 
132  full = ( wheels[d] == static_cast< int >( sz[d] ) ) ?
133  true : false;
134 
135  if( full )
136  wheels[d] = 0;
137 
138  return full;
139  }
140  }
141  else // Finally at the last wheel. Phew!
142  {
143  wheels[ d ]++;
144  full = ( wheels[d] == static_cast< int >( sz[d] ) ) ? true : false;
145 
146  if( full )
147  wheels[ d ] = 0;
148  return full;
149  }
150 
151  return full;
152 }
153 
154 void
157 {
159 }
160 
161 unsigned int
163 rows() const
164 {
165  Double_t number = m_tree -> GetEntries ();
166  return static_cast < unsigned int > ( number );
167 }
168 
169 void
171 fillDataCache ( unsigned int column )
172 {
173  unsigned int size = RootNTuple::rows ();
174  vector < double > * cache = new vector < double > ( size );
175  RootBranch * data = m_data [ column ];
176  for ( unsigned int row = 0; row < size; row++ ) {
177  double value = data -> valueAt ( row );
178  cache -> operator [] ( row ) = value;
179  }
180  m_data_cache [ column ] = cache;
181 }
182 
183 bool
185 empty () const
186 {
187  return rows () == 0;
188 }
189 
190 double
192 valueAt ( unsigned int row, unsigned int column ) const
193 {
194  if ( m_data_cache [ column ] == 0 ) {
195  RootNTuple * rtuple = const_cast < RootNTuple * > ( this );
196  rtuple -> fillDataCache ( column );
197  }
198  const vector < double > & cache = *m_data_cache [ column ];
199 
200  return cache[row];
201 }
202 
203 double
205 valueAtNoCache ( unsigned int row, unsigned int column ) const
206 {
207  double value = 0;
208  if ( column < m_data.size () ) { // within original ROOT file
209  RootBranch * data = m_data [ column ];
210  value = data -> valueAt ( row );
211  }
212  else { // added column
213  value = valueAt ( row, column );
214  }
215  return value;
216 }
217 
220 getType ( unsigned int column ) const
221 {
222  RootBranch * data = m_data [ column ];
223 
224  return data -> getType ();
225 }
226 
227 double *
229 doubleArrayAt ( unsigned int row, unsigned int column ) const
230 {
231  RootBranch * data = m_data [ column ];
232 
233  return data -> doubleArrayAt ( row );
234 }
235 
236 float *
238 floatArrayAt ( unsigned int row, unsigned int column ) const
239 {
240  RootBranch * data = m_data [ column ];
241 
242  return data -> floatArrayAt ( row );
243 }
244 
245 int *
247 intArrayAt ( unsigned int row, unsigned int column ) const
248 {
249  RootBranch * data = m_data [ column ];
250 
251  return data -> intArrayAt ( row );
252 }
253 
254 unsigned int *
256 uintArrayAt ( unsigned int row, unsigned int column ) const
257 {
258  RootBranch * data = m_data [ column ];
259 
260  return data -> uintArrayAt ( row );
261 }
262 
263 
264 void
267 {
268  for ( unsigned int i = 0; i < m_data_cache.size (); i++ ) {
269  if ( m_data_cache[i] != 0 ) {
270  delete m_data_cache [i];
271  }
272  m_data_cache[i] = 0;
273  }
274 }
275 
276 void
278 reserve ( unsigned int )
279 {
280  // does nothing.
281 }
282 
283 double
285 operator [] ( std::vector < unsigned int > & ) const // indices ) const
286 {
287  assert ( false );
288  return 0.;
289 }
290 
295 const vector < double > &
297 getRow ( unsigned int row ) const
298 {
299  const vector < string > & labels = getLabels ();
300  unsigned int size = labels.size();
301  for ( unsigned int column = 0; column < size; column++ ) {
302  const string & label = labels [ column ];
303  if ( isUseable ( label ) ) {
304  smartExpandRootNTuple ( label );
305  }
306  else {
307  std::string what ( "RootNTuple: can not export data source\n"
308  "because some column(s) cantain\n"
309  " variable length data" );
310  throw runtime_error ( what );
311  }
312  }
313 
314  size = m_data.size ();
315  m_array.resize ( size );
316  for ( unsigned int column = 0; column < size; column++ ) {
317  // Use this method to avoid reading whole column
318  RootBranch * branch = m_data [ column ];
319  m_array [ column ] = branch -> valueAt ( row );
320  }
321 
322  return m_array;
323 }
324 
325 int
327 addColumn ( const std::string & label,
328  RootBranch * branch )
329 {
330  // Check if label already exists.
331  int index = indexOf ( label );
332  if ( index >= 0 ) {
333  string what ( "RootNTuple Attempt to add a column whose label"
334  " is same as other column." );
335  throw runtime_error ( what );
336  }
337 
338  m_data.push_back ( branch );
339  m_data_cache.push_back ( 0 );
340  addLabel ( label );
341 
342  return m_data.size() - 1;
343 }
344 
345 
346 int
348 addColumn ( const std::string & label,
349  const std::vector < double > & col )
350 {
351  // Check if label already exists.
352  int index = indexOf ( label );
353  if ( index >= 0 ) {
354  string what ( "RootNTuple Attempt to add a column whose label"
355  " is same as other column." );
356  throw runtime_error ( what );
357  }
358 
359  unsigned int new_size = col.size ();
360  // Check if column has right size.
361  if ( m_data.empty () == false ) {
362  unsigned int old_size = rows ();
363 
364  if ( old_size != 0 && old_size != new_size ) {
365  string what ( "RootNTuple Attempt to add a column whose size"
366  " is not equal to other columns." );
367  throw runtime_error ( what );
368  }
369  }
370  vector < double > * vec = new vector < double > ( col );
371  m_data_cache.push_back ( vec );
372  m_multiDimensional.push_back ( false );
373 
374  addLabel ( label );
375 
376  return m_data.size() - 1;
377 }
378 
379 void
381 replaceColumn ( unsigned int col,
382  const std::vector < double > & data )
383 {
384  unsigned int size = columns ();
385  if ( col >= size ) {
386  const string what
387  ( "RootNTuple: Attempt to replace non-existant column." );
388  throw runtime_error ( what );
389  }
390 
391  size = rows ();
392  unsigned int new_size = data.size ();
393  if ( size != 0 && size != new_size ) {
394  const string what
395  ( "RootNTuple: Attempt to replace column with one whose "
396  "size is not equal to other columns." );
397  throw runtime_error ( what );
398  }
399  m_data_cache [ col ] -> resize ( new_size );
400  std::copy ( data.begin(), data.end(), m_data_cache [ col ] -> begin() );
401 
402  notifyObservers ();
403 }
404 
405 void
407 setShape ( std::vector < unsigned int > & shape )
408 {
409  assert ( false ); // not tested
410  m_shape = shape;
411 }
412 
413 const vector < unsigned int > &
415 getShape () const
416 {
417  assert ( false ); // not tested
418  return m_shape;
419 }
420 
421 bool
423 isMultiDimensional ( const std::string & column ) const
424 {
425  unsigned int colIndex = indexOf( column );
426 
427  return m_multiDimensional[ colIndex ];
428 }
429 
430 bool
432 isUseable ( const std::string & column ) const
433 {
434  unsigned int colIndex = indexOf( column );
435  RootBranch * branch = m_data [ colIndex ];
436 
437  return branch -> isUseable ();
438 }
439 
443 void
445 fillShape ( std::vector < int > & shape, unsigned int column ) const
446 {
447  shape.clear ();
448  shape.push_back ( RootNTuple::rows () ); // avoid QtRootNTuple
449  BranchList_t::size_type size = m_data.size ();
450  if ( column < size ) { // do nothing for added columns
451  RootBranch * col = m_data [ column ];
452  const vector < int > & sub_shape = col -> getShape ();
453  unsigned int rank = sub_shape.size ();
454 
455  for ( unsigned int i = 0; i < rank; i++ ) {
456  shape.push_back ( sub_shape [ i ] );
457  }
458  }
459 }
460 
461 bool
463 setReleventIndex( const std::string & column,
464  const std::vector< unsigned int >& index )
465 {
466  // Do not call this function on scalars
467  assert( isMultiDimensional( column ) );
468 
469  unsigned int colIndex = indexOf ( column );
470  RootBranch * col = m_data [ colIndex ];
471 
472  col -> setReleventIndex( index );
473 
474  return true;
475 }
476 
477 
479 TBranch *
481 getTBranch( const std::string & column )
482 {
483  unsigned int colIndex = indexOf ( column );
484  RootBranch * col = m_data [ colIndex ];
485 
486  return col -> getTBranch();
487 }
488 
489 
492 void
494 smartExpandRootNTuple ( const std::string & column ) const
495 {
496  // Expansion is --SURELY NOT-- needed if the data is not multidimensional
497  if ( isMultiDimensional( column ) == true )
498  {
499  // Has the expansion of this column already taken place?
500  bool flag = false;
501  const vector< string > & labels = getLabels();
502 
503  for( unsigned int i = 0; i < labels.size(); i++ ) {
504  const string & label = labels[i];
505  if( label.find( column + "[" ) != string::npos ) {
506  flag = true;
507  break; // No need to check all the labels
508  }
509  }
510 
511  // If no then go ahead and expand
512  if( flag == false )
513  {
514  unsigned int colIndex = indexOf ( column );
515  RootBranch * colRootBranch = m_data [ colIndex ];
516  TBranch * colTBranch = colRootBranch -> getTBranch();
517 
518  unsigned int dims = colRootBranch -> getRank ();
519  const vector < int > & sz =colRootBranch -> getShape ();
520  int nelems = colRootBranch -> numberOfElements();
521 
522  vector< unsigned int > indx( dims, 0);
523 
524  vector< int > wheels( dims, 0);
525  wheels[ dims - 1 ] = -1;
526  RootNTuple * rtuple = const_cast < RootNTuple * > ( this );
527 
528  for( int i = 0; i < nelems; i++ )
529  {
530 #ifdef SSTREAM_DEFECT
531  std::ostrstream namestream;
532 #else
533  std::ostringstream namestream;
534 #endif
535  namestream << column;
536 
537  rtuple -> rotateWheels( wheels, sz, 0 );
538  for ( unsigned int j = 0; j < dims; j++ ) {
539  namestream << "[" << wheels[ j ] << "]";
540  }
541 
542  colTBranch -> SetBasketSize ( 320000 );
543  RootBranch * h_branch = new RootBranch ( colTBranch );
544 
545  for( unsigned int k = 0; k < wheels.size(); k++ )
546  indx[ k ] = static_cast< unsigned int > ( wheels[ k ] );
547  h_branch -> setReleventIndex( indx );
548 
549  rtuple -> addColumn ( namestream.str(), h_branch );
550  rtuple -> m_multiDimensional.push_back( false );
551  }
552  }
553  }
554 }
555 
556 void
558 expandIfNeeded ( const std::string & column ) const
559 {
560  string::size_type pos = column.find_first_of ( '[' );
561 
562  if ( pos != string::npos ) {
563  const string label = column.substr ( 0, pos );
564 
565  if (isMultiDimensional ( label ) ) {
566  smartExpandRootNTuple ( label );
567  }
568  }
569 }
570 
571 void
573 expandIfNeeded ( const std::vector < std::string > & labels ) const
574 {
575  unsigned int size = labels.size ();
576 
577  for ( unsigned int i = 0; i < size; i++ ) {
578  const string & column = labels [ i ];
579  expandIfNeeded ( column );
580  }
581 }
582 
583 const vector < double > &
585 getColumn ( const std::string & name ) const
586 {
587  expandIfNeeded ( name );
588  throwIfInvalidLabel ( name );
589 
590  int index = indexOf ( name );
591 
592  return RootNTuple::getColumn ( index );
593 }
594 
595 const vector < double > &
597 getColumn ( const std::string & name,
598  const std::vector < int > & indices ) const
599 {
600  const string label = createBinding ( name, indices );
601 
602  return RootNTuple::getColumn ( label );
603 }
604 
605 const vector < double > &
607 getColumn ( unsigned int index ) const
608 {
609  isValidColumn ( index );
610 
611  if ( m_data_cache [ index ] == 0 ) {
612  RootNTuple * rtuple = const_cast < RootNTuple * > ( this );
613  rtuple -> fillDataCache ( index );
614  }
615 
616  return *m_data_cache [ index ];
617 }
618 
619 std::string
621 createBinding ( const std::string & label,
622  const std::vector < int > & indices ) const
623 {
624  string text ( label );
625 
626  unsigned int size = indices.size();
627  for ( unsigned int i = 0; i < size; i++ ) {
628  text += "[";
629  text += String::convert ( indices[i] );
630  text += "]";
631  }
632 
633  return text;
634 }

Generated for HippoDraw Class Library by doxygen