00001
00012 #ifdef _MSC_VER
00013 #include "msdevstudio/MSconfig.h"
00014 #endif
00015
00016 #include "NTuple.h"
00017
00018 #include "axes/Range.h"
00019 #include "pattern/Observer.h"
00020 #include "pattern/string_convert.h"
00021
00022 #include <algorithm>
00023 #include <functional>
00024 #include <numeric>
00025 #include <stdexcept>
00026
00027 #include <cassert>
00028
00029 #ifdef ITERATOR_MEMBER_DEFECT
00030 using namespace std;
00031 #else
00032 using std::back_insert_iterator;
00033 using std::distance;
00034 using std::runtime_error;
00035 using std::string;
00036 using std::vector;
00037 using std::find;
00038 using std::min_element;
00039 using std::max_element;
00040 #endif
00041
00042 using namespace hippodraw;
00043
00044 NTuple::NTuple ( const std::string & name )
00045 : DataSource ( name ),
00046 m_i_count ( 1 ),
00047 m_i_current ( 0 ),
00048 m_i_enabled ( false )
00049 {
00050 }
00051 NTuple::NTuple ( const char * name )
00052 : DataSource ( name ),
00053 m_i_count ( 1 ),
00054 m_i_current ( 0 ),
00055 m_i_enabled ( false )
00056 {
00057 }
00058
00059 NTuple::NTuple ( const std::vector< std::string > & labels )
00060 : DataSource ( labels ),
00061 m_i_count ( 1 ),
00062 m_i_current ( 0 ),
00063 m_i_enabled ( false )
00064 {
00065 std::size_t size = labels.size ();
00066 for ( std::size_t i = 0; i < size; i++ ) {
00067 vector< double > * vp = new vector< double > ();
00068 m_data.push_back ( vp );
00069 }
00070 }
00071
00072 NTuple::NTuple ( const NTuple & nt )
00073 : DataSource ( nt ),
00074 m_i_count ( nt.m_i_count ),
00075 m_i_current ( nt.m_i_current ),
00076 m_i_enabled ( nt.m_i_enabled )
00077 {
00078 copy( nt );
00079 }
00080
00081 NTuple::
00082 NTuple ( const DataSource * ds )
00083 : DataSource ( *ds ),
00084 m_i_count ( 1 ),
00085 m_i_current ( 0 ),
00086 m_i_enabled ( false )
00087 {
00088 copy ( *ds );
00089 }
00090
00091 NTuple::NTuple ( unsigned int n )
00092 : DataSource ( ),
00093 m_i_count ( 1 ),
00094 m_i_current ( 0 ),
00095 m_i_enabled ( false )
00096 {
00097 vector < string > labels;
00098 for ( unsigned int i = 0; i < n; i++ ) {
00099 vector<double> * v = new vector<double> ();
00100 m_data.push_back( v );
00101 labels.push_back ( string ( "nil" ) );
00102 }
00103
00104 setLabels ( labels );
00105 }
00106
00107 NTuple::NTuple ()
00108 : DataSource ( ),
00109 m_i_count ( 1 ),
00110 m_i_current ( 0 ),
00111 m_i_enabled ( false ){
00112 }
00113
00114 NTuple::
00115 NTuple ( bool yes )
00116 : DataSource ( yes ),
00117 m_i_count ( 1 ),
00118 m_i_current ( 0 ),
00119 m_i_enabled ( false )
00120 {
00121 }
00122
00123 NTuple::~NTuple()
00124 {
00125 Observable::notifyObservers ( &hippodraw::Observer::willDelete );
00126
00127 vector< vector<double> *>::iterator it = m_data.begin();
00128 for ( ; it != m_data.end(); ++it ) {
00129 delete *it;
00130 }
00131 }
00132
00133 void NTuple::resizeColumns ( size_t new_size )
00134 {
00135 size_t old_size = m_data.size ();
00136
00137 if ( new_size > old_size ) {
00138 for ( ; old_size < new_size; old_size++ ) {
00139 vector< double > * v = new vector<double> ();
00140 m_data.push_back ( v );
00141 }
00142 }
00143 else {
00144 m_data.erase ( m_data.begin() + new_size, m_data.end() );
00145 }
00146
00147 }
00148
00149 void
00150 NTuple::
00151 copy ( const DataSource & rhs )
00152 {
00153 DataSource::copyPrivate ( rhs );
00154 m_data.clear ();
00155 try {
00156 const NTuple & ntuple = dynamic_cast < const NTuple & > ( rhs );
00157
00158 vector< vector<double> *>::const_iterator it = ntuple.m_data.begin();
00159 for ( ; it != ntuple.m_data.end(); ++it ) {
00160 vector<double> * v = new vector<double> ( **it );
00161 m_data.push_back( v );
00162 }
00163 m_i_count = ntuple.m_i_count;
00164 m_i_current = ntuple.m_i_current;
00165 m_i_enabled = ntuple.m_i_enabled;
00166 }
00167 catch ( ... ) {
00168 unsigned int columns = rhs.columns ();
00169
00170 for ( unsigned int i = 0; i < columns; i++ ) {
00171 vector < double > * vec = new vector < double >;
00172 m_data.push_back ( vec );
00173 }
00174
00175 unsigned int size = rhs.rows ();
00176 for ( unsigned int i = 0; i < size; i++ ) {
00177 const vector < double > & src = rhs.getRow ( i );
00178 for ( unsigned int j = 0; j < columns; j++ ) {
00179 vector < double > & d = *m_data[j];
00180 d.push_back ( src[j] );
00181 }
00182 }
00183 }
00184
00185 }
00186
00187 void
00188 NTuple::
00189 append ( const DataSource * source )
00190 {
00191 checkWidth ( source );
00192
00193 const NTuple * ntuple = dynamic_cast < const NTuple * > ( source );
00194 if ( ntuple != 0 ) {
00195 vector < vector < double > * >::const_iterator src
00196 = ntuple -> m_data.begin ();
00197 vector < vector < double > * >::iterator dst = m_data.begin();
00198 while ( dst != m_data.end() ) {
00199 vector < double > & dst_vec = *(*dst++);
00200 vector < double > & src_vec = *(*src++);
00201 std::copy ( src_vec.begin(),
00202 src_vec.end(),
00203 back_insert_iterator < vector <double > > ( dst_vec) );
00204 }
00205 }
00206 else {
00207 DataSource::append ( source );
00208 }
00209 }
00210
00211 void NTuple::clear()
00212 {
00213 vector< vector<double> *>::iterator it = m_data.begin();
00214 for ( ; it < m_data.end(); ++it ) {
00215 (*it)->clear();
00216 }
00217
00218 notifyObservers ();
00219 }
00220
00221 bool
00222 NTuple::
00223 empty () const
00224 {
00225 return m_data.empty () ? true : m_data[0] -> empty ();
00226 }
00227
00228 unsigned int
00229 NTuple::
00230 rows () const
00231 {
00232 unsigned int count = 0;
00233
00234 if ( m_data.empty() == false &&
00235 m_data[0] -> empty () == false ) {
00236 count = m_data[0] -> size ();
00237 }
00238
00239 return count;
00240 }
00241
00242 void
00243 NTuple::
00244 replaceRow ( unsigned int i, const std::vector < double > & v )
00245 {
00246 if ( ! ( i < rows () ) ) {
00247 const string what ( "NTuple::replaceRow: index invalid" );
00248 throw runtime_error ( what );
00249 }
00250
00251 throwIfInvalidRowSize ( v );
00252
00253 vector < vector < double > * >:: iterator first = m_data.begin ();
00254 vector < double > :: const_iterator d = v.begin();
00255 while ( first != m_data.end () ) {
00256 vector < double > * column = *first++;
00257 column->operator[] ( i ) = *d++;
00258 }
00259
00260 notifyObservers ();
00261 }
00262
00263
00264 void
00265 NTuple::
00266 addRow ( const std::vector < double > & v )
00267 {
00268 throwIfInvalidRowSize ( v );
00269
00270 unsigned int size = m_data.size ();
00271 for ( unsigned int i = 0; i < size; i++ ) {
00272 vector < double > & column = *m_data[i];
00273 column.push_back ( v[i] );
00274 }
00275 notifyObservers ();
00276 }
00277
00278 void
00279 NTuple::
00280 insertRow ( unsigned int index, const std::vector < double > & v )
00281 {
00282 if ( m_data.size() != v.size() ) {
00283 const string what ( "NTuple: Attempt to insert a row whose size"
00284 " is not equal to other rows." );
00285
00286 throw runtime_error ( what );
00287 }
00288
00289 if ( index > rows () ) {
00290 const string what ( "NTuple::insertRow: index out of range" );
00291
00292 throw runtime_error ( what );
00293 }
00294
00295 vector<double>::const_iterator vit = v.begin();
00296 vector< vector<double> *>::iterator it = m_data.begin();
00297 for ( ; it != m_data.end(); ++it ) {
00298 vector < double > * p = *it;
00299 vector < double > :: iterator where = p->begin() + index;
00300 p->insert ( where, *vit++ );
00301 }
00302
00303 notifyObservers ();
00304 }
00305
00306 void
00307 NTuple::
00308 eraseRow ( unsigned int index )
00309 {
00310 if ( index >= rows () ) {
00311 const string what ( "NTuple::insertRow: index out of range" );
00312 throw runtime_error ( what );
00313 }
00314
00315 vector< vector<double> *>::iterator it = m_data.begin();
00316 for ( ; it != m_data.end(); ++it ) {
00317 vector < double > * p = *it;
00318 vector < double > :: iterator where = p->begin() + index;
00319 p->erase ( where);
00320 }
00321
00322 notifyObservers ();
00323 }
00324
00325
00326
00327 const std::vector < double > & NTuple::getRow ( unsigned int row ) const
00328 {
00329 if ( row >= rows () ) {
00330 string what ( "NTuple::getRow: argument out of range" );
00331
00332 throw runtime_error ( what );
00333 }
00334 unsigned int cols = columns ();
00335 m_row.clear ();
00336
00337 for ( unsigned int i = 0; i < cols; i++ ) {
00338 const vector < double > & column = *m_data[i];
00339 m_row.push_back ( column[row] );
00340 }
00341
00342 return m_row;
00343 }
00344
00345 double
00346 NTuple::
00347 operator [] ( std::vector < unsigned int > & indices ) const
00348 {
00349 unsigned int rank = getRank ();
00350 assert ( indices.size() == rank );
00351
00352
00353 if ( rank == 1 ) {
00354 unsigned int size = m_data.size();
00355 unsigned int row = indices[0] / size;
00356 unsigned int col = indices[0] % size;
00357 const vector < double > & column = *m_data[col];
00358 return column[row];
00359 }
00360
00361 if ( rank == 2 ) {
00362 unsigned int col = indices[1];
00363 unsigned int row = indices[0];
00364 const vector < double > & column = *m_data[col];
00365 return column[row];
00366 }
00367
00368 if ( rank == 3 ) {
00369 unsigned int size = m_data.size();
00370 unsigned int col = indices[2];
00371 unsigned int j = indices[1];
00372 unsigned int i = indices[0];
00373
00374 assert ( col < size );
00375 assert ( j < m_shape[1] );
00376 assert ( i < m_shape[0] );
00377
00378 unsigned int row = j + i * m_shape[1];
00379 const vector < double > & column = *m_data[col];
00380 return column[row];
00381 }
00382 return 0.0;
00383 }
00384
00385 double
00386 NTuple::
00387 valueAt ( unsigned int row, unsigned int column ) const
00388 {
00389
00390 vector < double > * v = m_data [ column ];
00391 return v -> operator [] ( row );
00392 }
00393
00394 void NTuple::reserve ( unsigned int count )
00395 {
00396 vector < vector < double > * >::iterator it = m_data.begin();
00397 for ( ; it != m_data.end(); ++it ) {
00398 (*it)->reserve ( count );
00399 }
00400 }
00401
00402 int
00403 NTuple::
00404 addColumn ( const std::string & label,
00405 const std::vector< double > & col )
00406 {
00407
00408 int index = indexOf ( label );
00409 if ( index >= 0 ) {
00410 string what ( "NTuple: Attempt to add a column with label `");
00411 what += label;
00412 what += "' which duplicates existing label.";
00413 throw runtime_error ( what );
00414 }
00415
00416
00417 if ( m_data.empty () == false ) {
00418 unsigned int size = rows ();
00419 unsigned int rows = col.size();
00420 if ( size != 0 && size != rows ) {
00421 string what ( "NTuple: Attempt to add a column of `" );
00422 what += String::convert ( rows );
00423 what += "' rows to DataSource with `";
00424 what += String ::convert ( size );
00425 what += "' rows.";
00426 throw runtime_error ( what );
00427 }
00428 }
00429
00430 vector < double > * vec = new vector < double > ( col );
00431 m_data.push_back ( vec );
00432 addLabel ( label );
00433
00434 return m_data.size() - 1;
00435 }
00436
00437 void
00438 NTuple::
00439 replaceColumn ( unsigned int col, const std::vector< double > & data )
00440 {
00441 unsigned int size = columns ();
00442 if ( col >= size ) {
00443 string what ( "NTuple: Attempt to replace column `");
00444 what += String::convert ( col );
00445 what += "' of data source with only `";
00446 what += String::convert ( size );
00447 what += "' columns.";
00448 throw runtime_error ( what );
00449 }
00450
00451 size = rows();
00452 unsigned int new_size = data.size ();
00453 if ( size != 0 && size != new_size ) {
00454 string what ( "NTuple:: Attempt to replace column with size `" );
00455 what += String::convert ( size );
00456 what += "' with one of size `";
00457 what += String::convert ( new_size );
00458 what += "'.";
00459 throw runtime_error ( what );
00460 }
00461 m_data[col]->resize ( data.size() );
00462
00463 std:: copy ( data.begin (), data.end(), m_data[col]->begin() );
00464
00465 notifyObservers ();
00466 }
00467
00468 void
00469 NTuple::
00470 setLabels ( const std::vector< std::string > & v )
00471 {
00472 if ( rows () == 0 ) {
00473 resizeColumns ( v.size () );
00474 }
00475 else {
00476 unsigned int vsize = v.size ();
00477 if ( vsize != columns () ) {
00478 string what ( "NTuple: Attempt to set " );
00479 what += String::convert ( vsize );
00480 what += " labels with data source of ";
00481 what += String::convert ( columns() );
00482 what += " columns.";
00483 throw runtime_error ( what );
00484 }
00485 }
00486
00487 DataSource::setLabels ( v );
00488 }
00489
00490 const vector<double> &
00491 NTuple::
00492 getColumn ( unsigned int i ) const
00493 {
00494 isValidColumn ( i );
00495
00496 return *m_data[i];
00497 }
00498
00499 vector<double> & NTuple::getColumn ( unsigned int i )
00500 {
00501 unsigned int size = columns();
00502 if ( i >= size ) {
00503 const string what ( "NTuple::getColumn argument out of range" );
00504 throw runtime_error ( what );
00505 }
00506
00507 return *m_data[i];
00508 }
00509
00510 const vector< double > & NTuple::getColumn ( const std::string & name ) const
00511 {
00512 throwIfInvalidLabel ( name );
00513 int index = indexOf ( name );
00514
00515 return *m_data[index];
00516 }
00517
00518 unsigned int
00519 NTuple::
00520 indexOfMinElement( unsigned int index ) const
00521 {
00522 const vector< double > & c = getColumn( index );
00523
00524 vector < double > :: const_iterator first
00525 = min_element ( c.begin(), c.end() );
00526
00527 return distance ( c.begin(), first );
00528 }
00529
00530 double
00531 NTuple::
00532 minElement ( unsigned int column ) const
00533 {
00534 vector < double > & v = *m_data[column];
00535
00536 return *min_element ( v.begin(), v.end() );
00537 }
00538
00539 unsigned int
00540 NTuple::
00541 indexOfMaxElement ( unsigned int index ) const
00542 {
00543 const vector< double > & c = getColumn( index );
00544
00545 vector < double > :: const_iterator first
00546 = max_element ( c.begin(), c.end() );
00547
00548 return distance ( c.begin(), first );
00549 }
00550
00551 double
00552 NTuple::
00553 maxElement ( unsigned int column ) const
00554 {
00555 vector < double > & v = *m_data[column];
00556
00557 return *max_element ( v.begin(), v.end() );
00558 }
00559
00560 double NTuple::columnMin( const std::string & name ) const
00561 {
00562 const vector< double > & c = getColumn( name );
00563 return *min_element( c.begin(), c.end() );
00564 }
00565
00566 double NTuple::columnMax( const std::string & name ) const
00567 {
00568 const vector< double > & c = getColumn( name );
00569 return *max_element( c.begin(), c.end() );
00570 }
00571
00572
00573 void NTuple::notifyObservers ( ) const
00574 {
00575 if ( m_i_enabled == false ) {
00576 Observable::notifyObservers ( );
00577 return;
00578 }
00579
00580 m_i_current++;
00581
00582 if ( m_i_current == m_i_count ) {
00583 Observable::notifyObservers ( );
00584 m_i_current = 0;
00585 }
00586 }
00587
00588 void NTuple::setIntervalEnabled ( bool yes )
00589 {
00590 m_i_enabled = yes;
00591 m_i_current = 0;
00592
00593 if ( yes == false ) notifyObservers ();
00594 }
00595
00596 bool NTuple::isIntervalEnabled () const
00597 {
00598 return m_i_enabled;
00599 }
00600
00601 void NTuple::setIntervalCount ( int number )
00602 {
00603 m_i_count = number;
00604 m_i_current = 0;
00605 }
00606
00607 unsigned int NTuple::getIntervalCount ( ) const
00608 {
00609 return m_i_count;
00610 }
00611
00612 bool
00613 NTuple::
00614 fillRange ( unsigned int column, Range & range ) const
00615 {
00616 vector < double > & v = *m_data[column];
00617
00618 range.setRange ( v.begin(), v.end() );
00619
00620 return true;
00621 }
00622
00623 double
00624 NTuple::
00625 sum ( unsigned int column ) const
00626 {
00627 double sum = 0.0;
00628 const vector < double > & data = *m_data[ column ];
00629
00630 return accumulate ( data.begin(), data.end(), sum );
00631 }