NTuple.cxx
Go to the documentation of this file.
1 
12 #ifdef _MSC_VER
13 #include "msdevstudio/MSconfig.h"
14 #endif
15 
16 #include "NTuple.h"
17 
18 #include "axes/Range.h"
19 #include "pattern/Observer.h"
20 #include "pattern/string_convert.h"
21 
22 #include <algorithm>
23 #include <functional>
24 #include <numeric>
25 #include <stdexcept>
26 
27 #include <cassert>
28 
29 #ifdef ITERATOR_MEMBER_DEFECT
30 using namespace std;
31 #else
32 using std::back_insert_iterator;
33 using std::distance;
34 using std::runtime_error;
35 using std::string;
36 using std::vector;
37 using std::find;
38 using std::min_element;
39 using std::max_element;
40 #endif
41 
42 using namespace hippodraw;
43 
44 NTuple::NTuple ( const std::string & name )
45  : DataSource ( name ),
46  m_i_count ( 1 ),
47  m_i_current ( 0 ),
48  m_i_enabled ( false )
49 {
50 }
51 NTuple::NTuple ( const char * name )
52  : DataSource ( name ),
53  m_i_count ( 1 ),
54  m_i_current ( 0 ),
55  m_i_enabled ( false )
56 {
57 }
58 
59 NTuple::NTuple ( const std::vector< std::string > & labels )
60  : DataSource ( labels ),
61  m_i_count ( 1 ),
62  m_i_current ( 0 ),
63  m_i_enabled ( false )
64 {
65  std::size_t size = labels.size ();
66  for ( std::size_t i = 0; i < size; i++ ) {
67  vector< double > * vp = new vector< double > ();
68  m_data.push_back ( vp );
69  }
70 }
71 
72 NTuple::NTuple ( const NTuple & nt )
73  : DataSource ( nt ),
74  m_i_count ( nt.m_i_count ),
75  m_i_current ( nt.m_i_current ),
76  m_i_enabled ( nt.m_i_enabled )
77 {
78  copy( nt );
79 }
80 
82 NTuple ( const DataSource * ds )
83  : DataSource ( *ds ),
84  m_i_count ( 1 ),
85  m_i_current ( 0 ),
86  m_i_enabled ( false )
87 {
88  copy ( *ds );
89 }
90 
91 NTuple::NTuple ( unsigned int n )
92  : DataSource ( ),
93  m_i_count ( 1 ),
94  m_i_current ( 0 ),
95  m_i_enabled ( false )
96 {
97  vector < string > labels;
98  for ( unsigned int i = 0; i < n; i++ ) {
99  vector<double> * v = new vector<double> ();
100  m_data.push_back( v );
101  labels.push_back ( string ( "nil" ) );
102  }
103 
104  setLabels ( labels );
105 }
106 
108  : DataSource ( ),
109  m_i_count ( 1 ),
110  m_i_current ( 0 ),
111  m_i_enabled ( false ){
112 }
113 
114 NTuple::
115 NTuple ( bool yes )
116  : DataSource ( yes ),
117  m_i_count ( 1 ),
118  m_i_current ( 0 ),
119  m_i_enabled ( false )
120 {
121 }
122 
124 {
126 
127  vector< vector<double> *>::iterator it = m_data.begin();
128  for ( ; it != m_data.end(); ++it ) {
129  delete *it;
130  }
131 }
132 
133 void NTuple::resizeColumns ( size_t new_size )
134 {
135  size_t old_size = m_data.size ();
136 
137  if ( new_size > old_size ) {
138  for ( ; old_size < new_size; old_size++ ) {
139  vector< double > * v = new vector<double> ();
140  m_data.push_back ( v );
141  }
142  }
143  else {
144  m_data.erase ( m_data.begin() + new_size, m_data.end() );
145  }
146 
147 }
148 
149 void
150 NTuple::
151 copy ( const DataSource & rhs )
152 {
153  DataSource::copyPrivate ( rhs );
154  m_data.clear ();
155  try {
156  const NTuple & ntuple = dynamic_cast < const NTuple & > ( rhs );
157 
158  vector< vector<double> *>::const_iterator it = ntuple.m_data.begin();
159  for ( ; it != ntuple.m_data.end(); ++it ) {
160  vector<double> * v = new vector<double> ( **it );
161  m_data.push_back( v );
162  }
163  m_i_count = ntuple.m_i_count;
164  m_i_current = ntuple.m_i_current;
165  m_i_enabled = ntuple.m_i_enabled;
166  }
167  catch ( ... ) {
168  unsigned int columns = rhs.columns ();
169 
170  for ( unsigned int i = 0; i < columns; i++ ) {
171  vector < double > * vec = new vector < double >;
172  m_data.push_back ( vec );
173  }
174 
175  unsigned int size = rhs.rows ();
176  for ( unsigned int i = 0; i < size; i++ ) {
177  const vector < double > & src = rhs.getRow ( i );
178  for ( unsigned int j = 0; j < columns; j++ ) {
179  vector < double > & d = *m_data[j];
180  d.push_back ( src[j] );
181  }
182  }
183  }
184 
185 }
186 
187 void
188 NTuple::
189 append ( const DataSource * source )
190 {
191  checkWidth ( source ); // might throw
192 
193  const NTuple * ntuple = dynamic_cast < const NTuple * > ( source );
194  if ( ntuple != 0 ) {
195  vector < vector < double > * >::const_iterator src
196  = ntuple -> m_data.begin ();
197  vector < vector < double > * >::iterator dst = m_data.begin();
198  while ( dst != m_data.end() ) {
199  vector < double > & dst_vec = *(*dst++);
200  vector < double > & src_vec = *(*src++);
201  std::copy ( src_vec.begin(),
202  src_vec.end(),
203  back_insert_iterator < vector <double > > ( dst_vec) );
204  }
205  }
206  else {
207  DataSource::append ( source );
208  }
209 }
210 
212 {
213  vector< vector<double> *>::iterator it = m_data.begin();
214  for ( ; it < m_data.end(); ++it ) {
215  (*it)->clear();
216  }
217 
218  notifyObservers ();
219 }
220 
221 bool
222 NTuple::
223 empty () const
224 {
225  return m_data.empty () ? true : m_data[0] -> empty ();
226 }
227 
228 unsigned int
229 NTuple::
230 rows () const
231 {
232  unsigned int count = 0;
233 
234  if ( m_data.empty() == false &&
235  m_data[0] -> empty () == false ) {
236  count = m_data[0] -> size ();
237  }
238 
239  return count;
240 }
241 
242 void
243 NTuple::
244 replaceRow ( unsigned int i, const std::vector < double > & v )
245 {
246  if ( ! ( i < rows () ) ) {
247  const string what ( "NTuple::replaceRow: index invalid" );
248  throw runtime_error ( what );
249  }
250 
251  throwIfInvalidRowSize ( v );
252 
253  vector < vector < double > * >:: iterator first = m_data.begin ();
254  vector < double > :: const_iterator d = v.begin();
255  while ( first != m_data.end () ) {
256  vector < double > * column = *first++;
257  column->operator[] ( i ) = *d++;
258  }
259 
260  notifyObservers ();
261 }
262 
263 // note: Using index is twice as fast as using iterators
264 void
265 NTuple::
266 addRow ( const std::vector < double > & v )
267 {
268  throwIfInvalidRowSize ( v );
269 
270  unsigned int size = m_data.size ();
271  for ( unsigned int i = 0; i < size; i++ ) {
272  vector < double > & column = *m_data[i];
273  column.push_back ( v[i] );
274  }
275  notifyObservers ();
276 }
277 
278 void
279 NTuple::
280 insertRow ( unsigned int index, const std::vector < double > & v )
281 {
282  if ( m_data.size() != v.size() ) {
283  const string what ( "NTuple: Attempt to insert a row whose size"
284  " is not equal to other rows." );
285 // throw DataSourceException ( what );
286  throw runtime_error ( what );
287  }
288 
289  if ( index > rows () ) {
290  const string what ( "NTuple::insertRow: index out of range" );
291 // throw DataSourceException ( what );
292  throw runtime_error ( what );
293  }
294 
295  vector<double>::const_iterator vit = v.begin();
296  vector< vector<double> *>::iterator it = m_data.begin();
297  for ( ; it != m_data.end(); ++it ) {
298  vector < double > * p = *it;
299  vector < double > :: iterator where = p->begin() + index;
300  p->insert ( where, *vit++ );
301  }
302 
303  notifyObservers ();
304 }
305 
306 void
307 NTuple::
308 eraseRow ( unsigned int index )
309 {
310  if ( index >= rows () ) {
311  const string what ( "NTuple::insertRow: index out of range" );
312  throw runtime_error ( what );
313  }
314 
315  vector< vector<double> *>::iterator it = m_data.begin();
316  for ( ; it != m_data.end(); ++it ) {
317  vector < double > * p = *it;
318  vector < double > :: iterator where = p->begin() + index;
319  p->erase ( where);
320  }
321 
322  notifyObservers ();
323 }
324 
325 // note: clearing and using push_back was twice as fast as
326 // resizing and using operator[]
327 const std::vector < double > & NTuple::getRow ( unsigned int row ) const
328 {
329  if ( row >= rows () ) {
330  string what ( "NTuple::getRow: argument= ");
331  what += String::convert ( row );
332  what += " out of range";
333  throw runtime_error ( what );
334  }
335  unsigned int cols = columns ();
336  m_row.clear ();
337 
338  for ( unsigned int i = 0; i < cols; i++ ) {
339  const vector < double > & column = *m_data[i];
340  m_row.push_back ( column[row] );
341  }
342 
343  return m_row;
344 }
345 
346 double
347 NTuple::
348 operator [] ( std::vector < unsigned int > & indices ) const
349 {
350  unsigned int rank = getRank ();
351  assert ( indices.size() == rank );
352 
353 
354 if ( rank == 1 ) {
355  unsigned int size = m_data.size();
356  unsigned int row = indices[0] / size;
357  unsigned int col = indices[0] % size;
358  const vector < double > & column = *m_data[col];
359  return column[row];
360  }
361 
362  if ( rank == 2 ) {
363  unsigned int col = indices[1];
364  unsigned int row = indices[0];
365  const vector < double > & column = *m_data[col];
366  return column[row];
367  }
368 
369  if ( rank == 3 ) {
370  unsigned int size = m_data.size();
371  unsigned int col = indices[2];
372  unsigned int j = indices[1];
373  unsigned int i = indices[0];
374 
375  assert ( col < size );
376  assert ( j < m_shape[1] );
377  assert ( i < m_shape[0] );
378 
379  unsigned int row = j + i * m_shape[1];
380  const vector < double > & column = *m_data[col];
381  return column[row];
382  }
383  return 0.0;
384 }
385 
386 double
387 NTuple::
388 valueAt ( unsigned int row, unsigned int column ) const
389 {
390  //return (*m_data[column])[row];
391  vector < double > * v = m_data [ column ];
392  return v -> operator [] ( row );
393 }
394 
395 void NTuple::reserve ( unsigned int count )
396 {
397  vector < vector < double > * >::iterator it = m_data.begin();
398  for ( ; it != m_data.end(); ++it ) {
399  (*it)->reserve ( count );
400  }
401 }
402 
403 int
404 NTuple::
405 addColumn ( const std::string & label,
406  const std::vector< double > & col )
407 {
408  // Check if label already exists.
409  int index = indexOf ( label );
410  if ( index >= 0 ) {
411  string what ( "NTuple: Attempt to add a column with label `");
412  what += label;
413  what += "' which duplicates existing label.";
414  throw runtime_error ( what );
415  }
416 
417  // Check if column has right size.
418  if ( m_data.empty () == false ) {
419  unsigned int size = rows ();
420  unsigned int rows = col.size();
421  if ( size != 0 && size != rows ) {
422  string what ( "NTuple: Attempt to add a column of `" );
423  what += String::convert ( rows );
424  what += "' rows to DataSource with `";
425  what += String ::convert ( size );
426  what += "' rows.";
427  throw runtime_error ( what );
428  }
429  }
430 
431  vector < double > * vec = new vector < double > ( col );
432  m_data.push_back ( vec );
433  addLabel ( label );
434 
435  return m_data.size() - 1;
436 }
437 
438 void
439 NTuple::
440 replaceColumn ( unsigned int col, const std::vector< double > & data )
441 {
442  unsigned int size = columns ();
443  if ( col >= size ) {
444  string what ( "NTuple: Attempt to replace column `");
445  what += String::convert ( col );
446  what += "' of data source with only `";
447  what += String::convert ( size );
448  what += "' columns.";
449  throw runtime_error ( what );
450  }
451 
452  size = rows();
453  unsigned int new_size = data.size ();
454  if ( size != 0 && size != new_size ) {
455  string what ( "NTuple:: Attempt to replace column with size `" );
456  what += String::convert ( size );
457  what += "' with one of size `";
458  what += String::convert ( new_size );
459  what += "'.";
460  throw runtime_error ( what );
461  }
462  m_data[col]->resize ( data.size() );
463  // need std:: below, else conflicts with NTuple::copy()
464  std:: copy ( data.begin (), data.end(), m_data[col]->begin() );
465 
466  notifyObservers ();
467 }
468 
469 void
470 NTuple::
471 setLabels ( const std::vector< std::string > & v )
472 {
473  if ( rows () == 0 ) {
474  resizeColumns ( v.size () );
475  }
476  else {
477  unsigned int vsize = v.size ();
478  if ( vsize != columns () ) {
479  string what ( "NTuple: Attempt to set " );
480  what += String::convert ( vsize );
481  what += " labels with data source of ";
482  what += String::convert ( columns() );
483  what += " columns.";
484  throw runtime_error ( what );
485  }
486  }
487 
488  DataSource::setLabels ( v );
489 }
490 
491 const vector<double> &
492 NTuple::
493 getColumn ( unsigned int i ) const
494 {
495  isValidColumn ( i ); // will throw exception if bad
496 
497  return *m_data[i];
498 }
499 
500 vector<double> & NTuple::getColumn ( unsigned int i )
501 {
502  unsigned int size = columns();
503  if ( i >= size ) {
504  const string what ( "NTuple::getColumn argument out of range" );
505  throw runtime_error ( what );
506  }
507 
508  return *m_data[i];
509 }
510 
511 const vector< double > & NTuple::getColumn ( const std::string & name ) const
512 {
513  throwIfInvalidLabel ( name );
514  int index = indexOf ( name );
515 
516  return *m_data[index];
517 }
518 
519 unsigned int
520 NTuple::
521 indexOfMinElement( unsigned int index ) const
522 {
523  const vector< double > & c = getColumn( index );
524 
525  vector < double > :: const_iterator first
526  = min_element ( c.begin(), c.end() );
527 
528  return distance ( c.begin(), first );
529 }
530 
531 double
532 NTuple::
533 minElement ( unsigned int column ) const
534 {
535  vector < double > & v = *m_data[column];
536 
537  return *min_element ( v.begin(), v.end() );
538 }
539 
540 unsigned int
541 NTuple::
542 indexOfMaxElement ( unsigned int index ) const
543 {
544  const vector< double > & c = getColumn( index );
545 
546  vector < double > :: const_iterator first
547  = max_element ( c.begin(), c.end() );
548 
549  return distance ( c.begin(), first );
550 }
551 
552 double
553 NTuple::
554 maxElement ( unsigned int column ) const
555 {
556  vector < double > & v = *m_data[column];
557 
558  return *max_element ( v.begin(), v.end() );
559 }
560 
561 double NTuple::columnMin( const std::string & name ) const
562 {
563  const vector< double > & c = getColumn( name );
564  return *min_element( c.begin(), c.end() );
565 }
566 
567 double NTuple::columnMax( const std::string & name ) const
568 {
569  const vector< double > & c = getColumn( name );
570  return *max_element( c.begin(), c.end() );
571 }
572 
573 /* virtual */
575 {
576  if ( m_i_enabled == false ) {
578  return;
579  }
580 
581  m_i_current++;
582 
583  if ( m_i_current == m_i_count ) {
585  m_i_current = 0;
586  }
587 }
588 
589 void NTuple::setIntervalEnabled ( bool yes )
590 {
591  m_i_enabled = yes;
592  m_i_current = 0;
593 
594  if ( yes == false ) notifyObservers ();
595 }
596 
598 {
599  return m_i_enabled;
600 }
601 
602 void NTuple::setIntervalCount ( int number )
603 {
604  m_i_count = number;
605  m_i_current = 0;
606 }
607 
608 unsigned int NTuple::getIntervalCount ( ) const
609 {
610  return m_i_count;
611 }
612 
613 bool
614 NTuple::
615 fillRange ( unsigned int column, Range & range ) const
616 {
617  vector < double > & v = *m_data[column];
618 
619  range.setRange ( v.begin(), v.end() );
620 
621  return true;
622 }
623 
624 double
625 NTuple::
626 sum ( unsigned int column ) const
627 {
628  double sum = 0.0;
629  const vector < double > & data = *m_data[ column ];
630 
631  return accumulate ( data.begin(), data.end(), sum );
632 }

Generated for HippoDraw Class Library by doxygen