Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

RootNTuple.cxx

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

Generated for HippoDraw-1.14.8.5 by doxygen 1.4.3