NTuple.cxx

Go to the documentation of this file.
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 ); // might throw 
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 // note: Using index is twice as fast as using iterators
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 //     throw DataSourceException ( what );
00286     throw runtime_error ( what );
00287   }
00288 
00289   if ( index > rows () ) {
00290     const string what ( "NTuple::insertRow: index out of range" );
00291 //     throw DataSourceException ( what );
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 // note: clearing and using push_back was twice as fast as
00326 // resizing and using operator[]
00327 const std::vector < double > & NTuple::getRow ( unsigned int row ) const
00328 {
00329   if ( row >= rows () ) {
00330     string what ( "NTuple::getRow: argument= ");
00331     what += String::convert ( row );
00332     what += " out of range";
00333     throw runtime_error ( what );
00334   }
00335   unsigned int cols = columns ();
00336   m_row.clear ();
00337 
00338   for ( unsigned int i = 0; i < cols; i++ ) {
00339     const vector < double > & column = *m_data[i];
00340     m_row.push_back ( column[row] );
00341   }
00342 
00343   return m_row;
00344 }
00345 
00346 double
00347 NTuple::
00348 operator [] ( std::vector < unsigned int > & indices ) const
00349 {
00350   unsigned int rank = getRank ();
00351   assert ( indices.size() == rank );
00352 
00353 
00354 if ( rank == 1 ) {
00355     unsigned int size = m_data.size();
00356     unsigned int row = indices[0] / size;
00357     unsigned int col = indices[0] % size;
00358     const vector < double > & column = *m_data[col];
00359     return column[row];
00360   }
00361 
00362   if ( rank == 2 ) {
00363     unsigned int col = indices[1];
00364     unsigned int row = indices[0];
00365     const vector < double > & column = *m_data[col];
00366     return column[row];
00367   }
00368 
00369   if ( rank == 3 ) {
00370     unsigned int size = m_data.size();
00371     unsigned int col = indices[2];
00372     unsigned int j = indices[1];
00373     unsigned int i = indices[0];
00374 
00375     assert ( col < size );
00376     assert ( j < m_shape[1] );
00377     assert ( i < m_shape[0] );
00378 
00379     unsigned int row = j + i * m_shape[1];
00380     const vector < double > & column = *m_data[col];
00381     return column[row];
00382   }
00383   return 0.0;
00384 }
00385 
00386 double
00387 NTuple::
00388 valueAt ( unsigned int row, unsigned int column ) const
00389 {
00390   //return (*m_data[column])[row];
00391   vector < double > * v = m_data [ column ];
00392   return v -> operator [] ( row );
00393 }
00394 
00395 void NTuple::reserve ( unsigned int count )
00396 {
00397   vector < vector < double > * >::iterator it = m_data.begin();
00398   for ( ; it != m_data.end(); ++it ) {
00399     (*it)->reserve ( count );
00400   }
00401 }
00402 
00403 int
00404 NTuple::
00405 addColumn ( const std::string & label,
00406             const std::vector< double > & col )
00407 {
00408   // Check if label already exists.
00409   int index = indexOf ( label );
00410   if ( index >= 0 ) {
00411     string what ( "NTuple: Attempt to add a column with label `");
00412     what += label;
00413     what += "' which duplicates existing label.";
00414     throw runtime_error ( what );
00415   }
00416 
00417   // Check if column has right size.
00418   if ( m_data.empty () == false ) {
00419     unsigned int size = rows ();
00420     unsigned int rows = col.size();
00421     if ( size != 0 && size != rows ) {
00422       string what ( "NTuple: Attempt to add a column of `" );
00423       what += String::convert ( rows );
00424       what += "' rows to DataSource with `";
00425       what += String ::convert ( size );
00426       what += "' rows.";
00427       throw runtime_error ( what );
00428     }
00429   }
00430 
00431   vector < double > * vec = new vector < double > ( col );
00432   m_data.push_back ( vec );
00433   addLabel ( label );
00434 
00435   return m_data.size() - 1;
00436 }
00437 
00438 void
00439 NTuple::
00440 replaceColumn ( unsigned int col, const std::vector< double > & data )
00441 {
00442   unsigned int size = columns ();
00443   if ( col >= size ) {
00444     string what ( "NTuple: Attempt to replace column `");
00445     what += String::convert ( col );
00446     what += "' of data source with only `";
00447     what += String::convert ( size );
00448     what += "' columns.";
00449     throw runtime_error ( what );
00450   }
00451 
00452   size = rows();
00453   unsigned int new_size = data.size ();
00454   if ( size != 0 && size != new_size ) {
00455     string what ( "NTuple:: Attempt to replace column with size `" );
00456     what += String::convert ( size );
00457     what += "' with one of size `";
00458     what += String::convert ( new_size );
00459     what += "'.";
00460     throw runtime_error ( what );
00461   }
00462   m_data[col]->resize ( data.size() );
00463   // need std:: below, else conflicts with NTuple::copy()
00464   std:: copy ( data.begin (), data.end(), m_data[col]->begin() );
00465 
00466   notifyObservers ();
00467 }
00468 
00469 void
00470 NTuple::
00471 setLabels ( const std::vector< std::string > & v )
00472 {
00473   if ( rows () == 0 ) {
00474     resizeColumns ( v.size () );
00475   }
00476   else {
00477     unsigned int vsize = v.size ();
00478     if ( vsize  != columns () ) {
00479       string what ( "NTuple: Attempt to set " );
00480       what += String::convert ( vsize );
00481       what += " labels with data source of ";
00482       what += String::convert ( columns() );
00483       what += " columns.";
00484       throw runtime_error ( what );
00485     }
00486   }
00487 
00488   DataSource::setLabels ( v );
00489 }
00490 
00491 const vector<double> &
00492 NTuple::
00493 getColumn ( unsigned int i ) const
00494 {
00495   isValidColumn ( i ); // will throw exception if bad
00496 
00497   return *m_data[i];
00498 }
00499 
00500 vector<double> & NTuple::getColumn ( unsigned int i )
00501 {
00502   unsigned int size = columns();
00503   if ( i >= size ) {
00504     const string what ( "NTuple::getColumn argument out of range" );
00505     throw runtime_error ( what );
00506   }
00507 
00508   return *m_data[i];
00509 }
00510 
00511 const vector< double > & NTuple::getColumn ( const std::string & name ) const
00512 {
00513   throwIfInvalidLabel ( name );
00514   int index = indexOf ( name );
00515 
00516   return *m_data[index];
00517 }
00518 
00519 unsigned int
00520 NTuple::
00521 indexOfMinElement( unsigned int index ) const
00522 {
00523   const vector< double > & c = getColumn( index );
00524 
00525   vector < double > :: const_iterator first
00526     = min_element ( c.begin(), c.end() );
00527 
00528   return distance ( c.begin(), first );
00529 }
00530 
00531 double
00532 NTuple::
00533 minElement ( unsigned int column ) const
00534 {
00535   vector < double > & v = *m_data[column];
00536 
00537   return *min_element ( v.begin(), v.end() );
00538 }
00539 
00540 unsigned int
00541 NTuple::
00542 indexOfMaxElement ( unsigned int index ) const
00543 {
00544   const vector< double > & c = getColumn( index );
00545 
00546   vector < double > :: const_iterator first
00547     = max_element ( c.begin(), c.end() );
00548 
00549   return distance ( c.begin(), first );
00550 }
00551 
00552 double
00553 NTuple::
00554 maxElement ( unsigned int column ) const
00555 {
00556   vector < double > & v = *m_data[column];
00557 
00558   return *max_element ( v.begin(), v.end() );
00559 }
00560 
00561 double NTuple::columnMin( const std::string & name ) const
00562 {
00563   const vector< double > & c = getColumn( name );
00564   return *min_element( c.begin(), c.end() );
00565 }
00566 
00567 double NTuple::columnMax( const std::string & name ) const
00568 {
00569   const vector< double > & c = getColumn( name );
00570   return *max_element( c.begin(), c.end() );
00571 }
00572 
00573 /* virtual */
00574 void NTuple::notifyObservers ( ) const
00575 {
00576   if ( m_i_enabled == false ) {
00577     Observable::notifyObservers ( );
00578     return;
00579   }
00580 
00581   m_i_current++;
00582 
00583   if ( m_i_current == m_i_count ) {
00584     Observable::notifyObservers ( );
00585     m_i_current = 0;
00586   }
00587 }
00588 
00589 void NTuple::setIntervalEnabled ( bool yes )
00590 {
00591   m_i_enabled = yes;
00592   m_i_current = 0;
00593 
00594   if ( yes == false ) notifyObservers ();
00595 }
00596 
00597 bool NTuple::isIntervalEnabled () const
00598 {
00599   return m_i_enabled;
00600 }
00601 
00602 void NTuple::setIntervalCount ( int number )
00603 {
00604   m_i_count = number;
00605   m_i_current = 0;
00606 }
00607 
00608 unsigned int NTuple::getIntervalCount ( ) const
00609 {
00610   return m_i_count;
00611 }
00612 
00613 bool
00614 NTuple::
00615 fillRange ( unsigned int column, Range & range ) const
00616 {
00617   vector < double > & v = *m_data[column];
00618 
00619   range.setRange ( v.begin(), v.end() );
00620 
00621   return true;
00622 }
00623 
00624 double
00625 NTuple::
00626 sum ( unsigned int column ) const
00627 {
00628   double sum = 0.0;
00629   const vector < double > & data = *m_data[ column ];
00630 
00631   return accumulate ( data.begin(), data.end(), sum );
00632 }

Generated for HippoDraw Class Library by doxygen