RootNTuple.cxx

Go to the documentation of this file.
00001 
00012 #ifdef HAVE_CONFIG_H
00013 #include "config.h"
00014 #endif
00015 
00016 #include "RootNTuple.h"
00017 
00018 #include "RootBranch.h"
00019 
00020 #include "axes/Range.h"
00021 #include "pattern/Observer.h"
00022 #include "pattern/string_convert.h"
00023 
00024 #include "TBranch.h"
00025 #include "TTree.h"
00026 
00027 #ifdef SSTREAM_DEFECT
00028 #include <strstream>
00029 #else
00030 #include <sstream>
00031 #endif
00032 
00033 #ifdef _MSC_VER
00034 #define isinf _isinf
00035 #endif
00036 
00037 #include <cmath>
00038 #include <cassert>
00039 
00040 using std::string;
00041 using std::vector;
00042 using std::runtime_error;
00043 
00044 using namespace hippodraw;
00045 
00046 RootNTuple::
00047 RootNTuple ( TTree * tree )
00048   : DataSource ( false ),
00049     m_tree ( tree ),
00050     m_cur_entry ( UINT_MAX )
00051 {
00052   initBranches ();
00053 }
00054 
00055 RootNTuple::
00056 RootNTuple ( )
00057   : DataSource ( false ),
00058     m_tree ( 0 ),
00059     m_cur_entry ( UINT_MAX )
00060 {
00061 }
00062 
00063 RootNTuple::~RootNTuple()
00064 {
00065   Observable::notifyObservers ( &hippodraw::Observer::willDelete );
00066 
00067   BranchList_t::iterator first = m_data.begin();
00068   while ( first != m_data.end() ) {
00069     delete *first++;
00070   }
00071 
00072   CacheList_t::iterator cache = m_data_cache.begin ();
00073   while ( cache != m_data_cache.end() ) {
00074     vector< double > * p = *cache++;
00075     if ( p != 0 ) {
00076       delete p;
00077     }
00078   }
00079 }
00080 
00084 void 
00085 RootNTuple::
00086 initBranches( )
00087 {
00088   m_dups.clear ();
00089 
00090   TObjArray * branches = m_tree -> GetListOfBranches ();
00091   Int_t number = branches -> GetEntries ();
00092   
00093   for ( Int_t i = 0; i < number; i++ )
00094     {
00095       TObject * object = branches -> At ( i );
00096       TBranch * branch = dynamic_cast < TBranch * > ( object );
00097       if ( branch != 0 )
00098         {
00099           branch -> SetBasketSize ( 320000 );
00100           
00101           RootBranch * h_branch = new RootBranch ( branch );
00102           const string name = object -> GetName ();
00103           int index = indexOf ( name );
00104           if ( index < 0 ) {
00105             addColumn ( name, h_branch );
00106             m_multiDimensional.push_back( h_branch -> isMultiDimensional() );
00107           }
00108           else {
00109             m_dups.push_back ( name );
00110             RootBranch * rb = m_data [ index ];
00111             m_data [ index ] = h_branch;
00112             delete rb;
00113           }
00114         }
00115     }
00116 }
00117 
00118 bool
00119 RootNTuple::
00120 rotateWheels( std::vector < int > & wheels,
00121               const std::vector < int > & sz,
00122               unsigned int d )
00123 {
00124   bool full = false;
00125   
00126   if( d < sz.size() - 1 ) // Still not at the last wheel...
00127     {
00128       if( rotateWheels( wheels, sz, d + 1 ) == true )
00129         {
00130           wheels[d]++;
00131 
00132           full = ( wheels[d] == static_cast< int >( sz[d] )  ) ? 
00133             true : false;
00134 
00135           if( full )
00136             wheels[d] = 0;
00137           
00138           return full;
00139         }
00140     }
00141   else // Finally at the last wheel. Phew!
00142     {
00143       wheels[ d ]++;
00144       full = ( wheels[d] == static_cast< int >( sz[d] )  ) ? true : false;
00145 
00146       if( full )
00147         wheels[ d ] = 0;
00148       return full;
00149     }
00150   
00151   return full;
00152 }
00153 
00154 void
00155 RootNTuple::
00156 notifyObservers ( ) const
00157 {
00158   Observable::notifyObservers ();
00159 }
00160 
00161 unsigned int
00162 RootNTuple::
00163 rows() const
00164 {
00165   Double_t number =  m_tree -> GetEntries ();
00166   return static_cast < unsigned int > ( number );
00167 }
00168 
00169 void
00170 RootNTuple::
00171 fillDataCache ( unsigned int column )
00172 {
00173   unsigned int size = RootNTuple::rows ();
00174   vector < double > * cache = new vector < double > ( size );
00175   RootBranch * data = m_data [ column ];
00176   for ( unsigned int row = 0; row < size; row++ ) {
00177     double value = data -> valueAt ( row );
00178     cache -> operator [] ( row ) = value;
00179   }
00180   m_data_cache [ column ] = cache;
00181 }
00182 
00183 bool
00184 RootNTuple::
00185 empty () const
00186 {
00187   return rows () == 0;
00188 }
00189 
00190 double
00191 RootNTuple::
00192 valueAt ( unsigned int row, unsigned int column ) const
00193 {
00194   if ( m_data_cache [ column ] == 0 ) {
00195     RootNTuple * rtuple = const_cast < RootNTuple * > ( this );
00196     rtuple -> fillDataCache ( column );
00197   }
00198   const vector < double > & cache = *m_data_cache [ column ];
00199 
00200   return cache[row];
00201 }
00202 
00203 double
00204 RootNTuple::
00205 valueAtNoCache ( unsigned int row, unsigned int column ) const
00206 {
00207   double value = 0;
00208   if ( column < m_data.size () ) { // within original ROOT file
00209     RootBranch * data = m_data [ column ];
00210     value = data -> valueAt ( row );
00211   }
00212   else { // added column
00213     value = valueAt ( row, column );
00214   }
00215   return value;
00216 }
00217 
00218 RootData::Type
00219 RootNTuple::
00220 getType ( unsigned int column ) const
00221 {
00222   RootBranch * data = m_data [ column ];
00223 
00224   return data -> getType ();
00225 }
00226 
00227 double *
00228 RootNTuple::
00229 doubleArrayAt ( unsigned int row, unsigned int column ) const
00230 {
00231   RootBranch * data = m_data [ column ];
00232 
00233   return data -> doubleArrayAt ( row );
00234 }
00235 
00236 float *
00237 RootNTuple::
00238 floatArrayAt ( unsigned int row, unsigned int column ) const
00239 {
00240   RootBranch * data = m_data [ column ];
00241 
00242   return data -> floatArrayAt ( row );
00243 }
00244 
00245 int *
00246 RootNTuple::
00247 intArrayAt ( unsigned int row, unsigned int column ) const
00248 {
00249   RootBranch * data = m_data [ column ];
00250 
00251   return data -> intArrayAt ( row );
00252 }
00253 
00254 unsigned int *
00255 RootNTuple::
00256 uintArrayAt ( unsigned int row, unsigned int column ) const
00257 {
00258   RootBranch * data = m_data [ column ];
00259 
00260   return data -> uintArrayAt ( row );
00261 }
00262 
00263 
00264 void
00265 RootNTuple::
00266 clear ()
00267 {
00268   for ( unsigned int i = 0; i < m_data_cache.size (); i++ ) {
00269     if ( m_data_cache[i] != 0 ) {
00270       delete m_data_cache [i];
00271     }
00272     m_data_cache[i] = 0;
00273   }
00274 }
00275 
00276 void
00277 RootNTuple::
00278 reserve ( unsigned int )
00279 {
00280   // does nothing.
00281 }
00282 
00283 double
00284 RootNTuple::
00285 operator [] ( std::vector < unsigned int > & ) const // indices ) const
00286 {
00287   assert ( false );
00288   return 0.;
00289 }
00290 
00295 const vector < double > &
00296 RootNTuple::
00297 getRow ( unsigned int row ) const
00298 {
00299   const vector < string > & labels = getLabels ();
00300   unsigned int size = labels.size();
00301   for ( unsigned int column = 0; column < size; column++ ) {
00302     const string & label = labels [ column ];
00303     if ( isUseable ( label ) ) {
00304       smartExpandRootNTuple ( label );
00305     }
00306     else {
00307       std::string what ( "RootNTuple: can not export data source\n"
00308                          "because some column(s) cantain\n"
00309                          " variable length data" );
00310       throw runtime_error ( what );
00311     }
00312   }
00313 
00314   size = m_data.size ();
00315   m_array.resize ( size );
00316   for ( unsigned int column = 0; column < size; column++ ) {
00317     // Use this method to avoid reading whole column
00318     RootBranch * branch = m_data [ column ];
00319     m_array [ column ] = branch -> valueAt ( row );
00320   }
00321 
00322   return m_array;
00323 }
00324 
00325 int
00326 RootNTuple::
00327 addColumn ( const std::string & label,
00328             RootBranch * branch )
00329 {
00330   // Check if label already exists.
00331   int index = indexOf ( label );
00332   if ( index >= 0 ) {
00333     string what ( "RootNTuple Attempt to add a column whose label"
00334                   " is same as other column." );
00335     throw runtime_error ( what );
00336   }
00337 
00338   m_data.push_back ( branch );
00339   m_data_cache.push_back ( 0 );
00340   addLabel ( label );
00341   
00342   return m_data.size() - 1;
00343 }
00344 
00345 
00346 int
00347 RootNTuple::
00348 addColumn ( const std::string & label,
00349             const std::vector < double > & col )
00350 {
00351   // Check if label already exists.
00352   int index = indexOf ( label );
00353   if ( index >= 0 ) {
00354     string what ( "RootNTuple Attempt to add a column whose label"
00355                   " is same as other column." );
00356     throw runtime_error ( what );
00357   }
00358 
00359   unsigned int new_size = col.size ();
00360   //  Check if column has right size.
00361     if ( m_data.empty () == false ) {
00362       unsigned int old_size = rows ();
00363   
00364       if ( old_size != 0 && old_size != new_size ) {
00365         string what ( "RootNTuple Attempt to add a column whose size"
00366                     " is not equal to other columns." );
00367         throw runtime_error ( what );
00368       }
00369     }
00370   vector < double > * vec = new vector < double > ( col );
00371   m_data_cache.push_back ( vec );
00372   m_multiDimensional.push_back ( false );
00373     
00374   addLabel ( label );
00375 
00376   return m_data.size() - 1;
00377 }
00378 
00379 void
00380 RootNTuple::
00381 replaceColumn ( unsigned int col,
00382                 const std::vector < double > & data )
00383 {
00384   unsigned int size = columns ();
00385   if ( col >= size ) {
00386     const string what
00387       ( "RootNTuple: Attempt to replace non-existant column." );
00388     throw runtime_error ( what );
00389   }
00390 
00391   size = rows ();
00392   unsigned int new_size = data.size ();
00393   if ( size != 0 && size != new_size ) {
00394     const string what
00395       ( "RootNTuple: Attempt to replace column with one whose "
00396         "size is not equal to other columns." );
00397       throw runtime_error ( what );
00398   }
00399   m_data_cache [ col ] -> resize ( new_size );
00400   std::copy ( data.begin(), data.end(), m_data_cache [ col ] -> begin() );
00401 
00402   notifyObservers ();
00403 }
00404 
00405 void
00406 RootNTuple::
00407 setShape ( std::vector < unsigned int > & shape )
00408 {
00409   assert ( false ); // not tested
00410   m_shape = shape;
00411 }
00412 
00413 const vector < unsigned int > &
00414 RootNTuple::
00415 getShape () const
00416 {
00417   assert ( false ); // not tested
00418   return m_shape;
00419 }
00420 
00421 bool
00422 RootNTuple::
00423 isMultiDimensional ( const std::string & column ) const
00424 {
00425   unsigned int colIndex = indexOf( column );
00426 
00427   return m_multiDimensional[ colIndex ];
00428 }
00429 
00430 bool
00431 RootNTuple::
00432 isUseable ( const std::string & column ) const
00433 {
00434   unsigned int colIndex = indexOf( column );
00435   RootBranch * branch = m_data [ colIndex ];
00436 
00437   return branch -> isUseable ();
00438 }
00439 
00443 void
00444 RootNTuple::
00445 fillShape ( std::vector < int > & shape, unsigned int column ) const
00446 {
00447   shape.clear ();
00448   shape.push_back ( RootNTuple::rows () ); // avoid QtRootNTuple
00449   BranchList_t::size_type size = m_data.size ();
00450   if ( column < size ) { // do nothing for added columns
00451     RootBranch * col = m_data [ column ];
00452     const vector < int > & sub_shape = col -> getShape ();
00453     unsigned int rank = sub_shape.size ();
00454 
00455     for ( unsigned int i = 0; i < rank; i++ ) {
00456       shape.push_back ( sub_shape [ i ] );
00457     }
00458   }
00459 }
00460 
00461 bool
00462 RootNTuple::
00463 setReleventIndex( const std::string & column,
00464                   const std::vector< unsigned int >& index )
00465 {
00466   // Do not call this function on scalars
00467   assert( isMultiDimensional( column ) );
00468   
00469   unsigned int colIndex = indexOf ( column );
00470   RootBranch * col = m_data [ colIndex ];
00471 
00472   col -> setReleventIndex( index );
00473 
00474   return true;
00475 }
00476 
00477 
00479 TBranch *
00480 RootNTuple::
00481 getTBranch( const std::string & column )
00482 {
00483   unsigned int colIndex = indexOf ( column );
00484   RootBranch * col = m_data [ colIndex ];
00485   
00486   return col -> getTBranch();
00487 }
00488 
00489 
00492 void
00493 RootNTuple::
00494 smartExpandRootNTuple ( const std::string & column ) const
00495 {
00496   // Expansion is --SURELY NOT-- needed if the data is not multidimensional
00497   if ( isMultiDimensional( column ) == true )
00498     {
00499       // Has the expansion of this column already taken place?
00500       bool flag = false;
00501       const vector< string > & labels = getLabels();
00502       
00503       for( unsigned int i = 0; i < labels.size(); i++ ) {
00504         const string & label = labels[i];
00505         if( label.find( column + "[" ) != string::npos ) {
00506           flag = true;
00507           break;  // No need to check all the labels
00508         }
00509       }
00510       
00511       // If no then go ahead and expand
00512       if( flag == false )
00513         {
00514           unsigned int colIndex = indexOf ( column );
00515           RootBranch * colRootBranch = m_data [ colIndex ];
00516           TBranch * colTBranch = colRootBranch -> getTBranch();
00517           
00518           unsigned int dims = colRootBranch -> getRank ();
00519           const vector < int > & sz =colRootBranch -> getShape ();
00520           int nelems = colRootBranch -> numberOfElements();
00521 
00522           vector< unsigned int > indx( dims, 0);
00523           
00524           vector< int > wheels( dims, 0);
00525           wheels[ dims - 1 ] = -1;
00526           RootNTuple * rtuple = const_cast < RootNTuple * > ( this );
00527           
00528           for( int i = 0; i < nelems; i++ )
00529             {
00530 #ifdef SSTREAM_DEFECT
00531               std::ostrstream namestream;
00532 #else
00533               std::ostringstream namestream;
00534 #endif
00535               namestream << column;
00536               
00537               rtuple ->  rotateWheels( wheels, sz, 0 );
00538               for ( unsigned int j = 0; j < dims; j++ ) {
00539                 namestream << "[" << wheels[ j ] << "]";
00540               }
00541               
00542               colTBranch -> SetBasketSize ( 320000 );
00543               RootBranch * h_branch = new RootBranch ( colTBranch );
00544               
00545               for( unsigned int k = 0; k < wheels.size(); k++ )
00546                 indx[ k ] = static_cast< unsigned int > ( wheels[ k ] );
00547               h_branch -> setReleventIndex( indx );
00548               
00549               rtuple -> addColumn ( namestream.str(), h_branch );
00550               rtuple -> m_multiDimensional.push_back( false );
00551             }
00552         }
00553     }
00554 }
00555 
00556 void
00557 RootNTuple::
00558 expandIfNeeded ( const std::string & column ) const
00559 {
00560   string::size_type pos = column.find_first_of ( '[' );
00561 
00562   if ( pos != string::npos ) {
00563     const string label = column.substr ( 0, pos );
00564 
00565     if (isMultiDimensional ( label ) ) {
00566       smartExpandRootNTuple ( label );
00567     }
00568   }
00569 }
00570 
00571 void
00572 RootNTuple::
00573 expandIfNeeded ( const std::vector < std::string > & labels ) const
00574 {
00575   unsigned int size = labels.size ();
00576 
00577   for ( unsigned int i = 0; i < size; i++ ) {
00578     const string & column = labels [ i ];
00579     expandIfNeeded ( column );
00580   }
00581 }
00582 
00583 const vector < double > &
00584 RootNTuple::
00585 getColumn ( const std::string & name ) const
00586 {
00587   expandIfNeeded ( name );
00588   throwIfInvalidLabel ( name );
00589 
00590   int index = indexOf ( name );
00591 
00592   return RootNTuple::getColumn ( index );
00593 }
00594 
00595 const vector < double > &
00596 RootNTuple::
00597 getColumn ( const std::string & name,
00598             const std::vector < int > & indices ) const
00599 {
00600   const string label = createBinding ( name, indices );
00601 
00602   return RootNTuple::getColumn ( label );
00603 }
00604 
00605 const vector < double > &
00606 RootNTuple::
00607 getColumn ( unsigned int index ) const
00608 {
00609   isValidColumn ( index );
00610 
00611   if ( m_data_cache [ index ] == 0 ) {
00612     RootNTuple * rtuple = const_cast < RootNTuple * > ( this );
00613     rtuple -> fillDataCache ( index );
00614   }
00615 
00616   return *m_data_cache [ index ];
00617 }
00618 
00619 std::string
00620 RootNTuple::
00621 createBinding ( const std::string & label, 
00622                 const std::vector < int > & indices ) const
00623 {
00624   string text ( label );
00625 
00626   unsigned int size = indices.size();
00627   for ( unsigned int i = 0; i < size; i++ ) {
00628     text += "[";
00629     text += String::convert ( indices[i] );
00630     text += "]";
00631   }
00632 
00633   return text;
00634 }

Generated for HippoDraw Class Library by doxygen