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 )
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
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
00232 }
00233
00234 void
00235 RootNTuple::
00236 reserve ( unsigned int )
00237 {
00238
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
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
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
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 );
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 );
00379 return m_shape;
00380 }
00381
00382 unsigned int
00383 RootNTuple::getRank () const
00384 {
00385 assert ( false );
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
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
00454 if ( isMultiDimensional( column ) == true )
00455 {
00456
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
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
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
00590
00591 const string binding = strm_text.str();
00592 return binding;
00593 }