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 )
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
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 () ) {
00209 RootBranch * data = m_data [ column ];
00210 value = data -> valueAt ( row );
00211 }
00212 else {
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
00281 }
00282
00283 double
00284 RootNTuple::
00285 operator [] ( std::vector < unsigned int > & ) 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
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
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
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
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 );
00410 m_shape = shape;
00411 }
00412
00413 const vector < unsigned int > &
00414 RootNTuple::
00415 getShape () const
00416 {
00417 assert ( false );
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 () );
00449 BranchList_t::size_type size = m_data.size ();
00450 if ( column < size ) {
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
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
00497 if ( isMultiDimensional( column ) == true )
00498 {
00499
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;
00508 }
00509 }
00510
00511
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 }