NTupleController.cxx
Go to the documentation of this file.
1 
12 // for truncation warning in debug mode
13 #ifdef _MSC_VER
14 #include "msdevstudio/MSconfig.h"
15 #endif
16 
17 #include "NTupleController.h"
18 
19 #include "CircularBuffer.h"
20 #include "DataSourceController.h"
21 #include "TupleCut.h"
22 
23 #include "pattern/string_convert.h"
24 
25 
26 
27 #include <algorithm>
28 #include <stdexcept>
29 #include <fstream>
30 #include <utility>
31 
32 #include <cassert>
33 
34 using std::endl;
35 using std::ofstream;
36 using std::runtime_error;
37 using std::string;
38 using std::vector;
39 
40 using namespace hippodraw;
41 
43 
45 {
46 }
47 
51 {
52  assert ( false );
53 }
54 
56 {
57  if ( s_instance == 0 ) {
58  s_instance = new NTupleController ( );
59  }
60  return s_instance;
61 }
62 
63 string::size_type
65 findWhite ( const std::string & line, unsigned int left, bool tabs_only )
66 {
67  string::size_type right = line.find( '\t', left );
68 
69  if( line.find( '\n', left ) < right ) right = line.find( '\n', left );
70 
71  if ( tabs_only == false ) {
72  if( line.find( ' ', left ) < right ) right = line.find( ' ', left );
73  }
74 
75  return right;
76 }
77 
78 void
80 splitAndFill ( const std::string & line,
81  std::vector < std::string > & values )
82 {
83  static string white ( " \n\r\t" );
84  values.clear ();
85 
86  string::size_type start = line.find_first_not_of ( white, 0 );
87  while ( start != string::npos ) {
88  string::size_type end = line.find_first_of ( white, start );
89  if ( end != string::npos ) {
90  values.push_back ( string ( line, start, end - start ) );
91  start = line.find_first_not_of ( white, end );
92  }
93  else {
94  values.push_back ( string ( line, start ) ); // to end
95  break;
96  }
97  }
98 }
99 
112 int
114 readAsciiNTuple ( NTuple * ntuple, const std::string & filename )
115 {
116  // Two local flags to define if name or labels are missing
117  bool hasTitle = true;
118  bool hasLabel = true;
119 
120  string dir_name = filename;
121 
122  string::size_type pos = dir_name.find_last_of( '/' );
123  if ( pos == string::npos ) {
124  dir_name = ".";
125  } else {
126  dir_name.erase( pos );
127  }
128  dir_name += "/";
129 
130  std::ifstream infile( filename.c_str() );
131  if( !infile.is_open() ) {
132  string what ( "NTupleController: Could not open file\n`" );
133  what += filename.c_str();
134  what += "'\n";
135  what += "Files doesn't exist or is not readable.";
136  throw runtime_error ( what );
137  }
138  string line;
139  if( !std::getline( infile, line ) ) {
140  return -2;
141  }
142 
143  // ignore spaces at the beginning of the line
144  while( findWhite( line, 0, false ) == 0 ) line = line.substr( 1 );
145  string::size_type firstTab = line.find( '\t', 0 );
146 
147  // fist line with tab, no name
148  if ( firstTab != line.npos ) {
149  hasTitle = false;
150  ntuple->setTitle ("<none>");
151  string firstword = line.substr ( 0, firstTab );
152 
153  // first line are numbers, no labels
154  if ( std::atof ( firstword.c_str() ) != 0.0 ) {
155  hasLabel = false;
156  }
157  }
158  else {
159  // first line is a single number, no name, no labels
160  if ( std::atof ( line.c_str() ) != 0.0 ) {
161  hasTitle = false;
162  ntuple->setTitle("<none>");
163  hasLabel = false;
164  }
165  // name exist
166  else ntuple->setTitle ( line );
167  }
168 
169  // second line missing
170  if ( hasTitle ){
171  if ( !std::getline( infile, line ) )
172  return -2;
173  }
174 
175  string::size_type size = line.size ();
176  if ( line[size-1] == '\r' ) { // CR on Windows written file
177  line.erase ( size-1 );
178  }
179  line += "\n";
180  string::size_type right = findWhite( line, 0, true );
181  string firstlabel = line.substr( 0, right );
182  // current line start with number, no labels
183  if ( std::atof ( firstlabel.c_str() ) != 0.0 ) hasLabel=false;
184 
185  vector< string > labels;
186  string::size_type left = 0;
187  // label index, used when labels in the file are missing
188  int i=0;
189 
190  while( right != line.npos ){
191  if( right == left ){
192  left++;
193  right = findWhite( line, left, true );
194  continue;
195  }
196 
197  string label;
198  if (!hasLabel) {
199  // make a label name when label name is missing
200  label="Column"+String::convert(i);
201  i++;
202  }
203  // read label name from the file
204  else label = line.substr( left, right - left );
205  labels.push_back ( label );
206  left = right + 1;
207  right = findWhite( line, left, true );
208  }
209  if ( labels.size () == 0 ) {
210  return -2;
211  }
212 
213  ntuple->setLabels ( labels );
214 
215  unsigned int columns = labels.size ();
216  vector < double > vals ( columns );
217 
218  if ( hasLabel ) {
219  std::getline ( infile, line );
220  }
221 
222  do {
223  // else use current line
224  vector < string > values;
225  splitAndFill ( line, values );
226 
227  if ( values.size() != columns ) {
228  return -2;
229  }
230  for ( unsigned int i = 0; i < columns; i++ ) {
231  vals[i] = atof ( values[i].c_str() );
232  }
233  ntuple -> addRow ( vals );
234 
235  } while ( std::getline ( infile, line ) );
236 
237  vector < unsigned int > shape ( 2 );
238  shape[0] = ntuple -> rows();
239  shape[1] = ntuple -> columns ();
240  ntuple -> setShape ( shape );
241 
242  return 0;
243 }
244 
245 DataSource *
247 createNTuple ( const std::string & filename )
248 {
249  unsigned int columns = 0;
250  NTuple * nt = new NTuple ( columns );
251  try {
252  fillFromFile ( filename, nt );
253  }
254  catch ( const runtime_error & e ) {
255  delete nt;
256  throw e;
257  }
258 
259  return nt;
260 }
261 
262 void
264 fillFromFile ( const std::string & filename, NTuple * nt )
265 {
266  int retval = readAsciiNTuple ( nt, filename );
267 
268  if ( retval < 0 ) {
269  std::string what ( "NTupleController: File:\n `" );
270  what += filename;
271  what += "'\n ";
272  if ( retval == -1 ) {
273  what += "could not be found.";
274  }
275  else {
276  what += "had bad format.";
277  }
278  throw std::runtime_error ( what );
279  }
280 
282  DataSource * ds = controller -> getDataSource ( filename );
283 
284  // Register the NTuple name if it's not in memory.
285  // Alway register that it came from a file.
286  nt -> setName ( filename ); // before registering.
287  if ( ds == 0 ) controller -> registerNTuple ( filename, nt );
288  controller -> registerDataSourceFile ( nt );
289 }
290 
291 NTuple *
293 createNTuple ( const std::vector < std::string > & labels )
294 {
295  NTuple * nt = new NTuple ( labels );
297  controller -> registerNTuple ( nt );
298 
299  return nt;
300 }
301 
304 createCircularBuffer ( const std::vector < std::string > & labels )
305 {
306  CircularBuffer * nt = new CircularBuffer ( labels );
308  controller -> registerNTuple ( nt );
309 
310  return nt;
311 }
312 
313 NTuple *
315 createNTuple ( unsigned int columns )
316 {
317  NTuple * nt = new NTuple ( columns );
319  controller -> registerNTuple ( nt );
320 
321  return nt;
322 }
323 
326 createCircularBuffer ( unsigned int columns )
327 {
328  CircularBuffer * nt = new CircularBuffer ( columns );
330  controller -> registerNTuple ( nt );
331 
332  return nt;
333 }
334 
335 NTuple *
338 {
339  NTuple * nt = new NTuple ();
341  controller -> registerNTuple ( nt );
342 
343  return nt;
344 }
345 
349 {
350  CircularBuffer * nt = new CircularBuffer ();
352  controller -> registerNTuple ( nt );
353 
354  return nt;
355 }
356 
357 DataSource *
359 findDataSource ( const std::string & name ) const
360 {
362 
363  return controller -> findDataSource ( name );
364 }
365 
366 void
368 changeName ( DataSource * ntuple, const std::string & new_name )
369 {
370  ntuple -> setName ( new_name );
371 }
372 
373 int
375 writeNTupleToFile ( const std::string & name,
376  const std::string & filename )
377 {
379  DataSource * ntuple
380  = controller -> findDataSource ( name );
381  // throws exception if not found
382  if ( ntuple == 0 ) return -1;
383 
384  return writeNTupleToFile ( ntuple, filename );
385 }
386 
388 int
391  const std::string & filename )
392 {
393  ofstream file ( filename.c_str() );
394  if ( file.is_open () == false ) {
395  return 1;
396  }
397  file << ntuple->title() << endl;
398 
399  const vector < string > & labels = ntuple->getLabels ();
400 #ifdef ITERATOR_MEMBER_DEFECT
401  std::
402 #endif
403  vector < string > ::const_iterator first = labels.begin ();
404  string label = *first++;
405  file << label;
406  while ( first != labels.end() ) {
407  label = *first++;
408  file << "\t" << label;
409  }
410  file << endl;
411 
412  unsigned int rows = ntuple->rows ();
413  for ( unsigned int i = 0; i < rows; i++ ) {
414  const vector < double > & row = ntuple->getRow ( i );
415 
416 #ifdef ITERATOR_MEMBER_DEFECT
417  std::
418 #endif
419  vector < double > ::const_iterator first = row.begin();
420  while ( first != row.end() ) {
421  file << "\t" << *first++;
422  }
423  file << endl;
424  }
425 
427  controller -> registerDataSourceFile ( ntuple );
428 
429  return 0;
430 }
431 
435 void
437 saveNTuples ( const std::string & fileprefix, const std::string & filesuffix )
438 {
439  string::size_type pos = fileprefix.find_last_of ( '/' );
440  const string path = fileprefix.substr ( 0, pos + 1 );
441  const string basename = fileprefix.substr ( pos + 1 );
442 
444  vector < DataSource * > tuples;
445  controller->getDataSources ( tuples, false ); // only non files
446  unsigned int size = tuples.size();
447 
448  for ( unsigned int i = 0; i < size; i++ ) {
449  DataSource * ntuple = tuples[i];
450  const string & tuple_name = ntuple->getName ();
451 
452  string filename ( basename );
453  filename += String::convert ( i );
454  filename += filesuffix;
455 
456  string tuple_file ( path );
457  tuple_file += filename;
458 
459  writeNTupleToFile ( tuple_name, tuple_file );
460  controller -> changeName ( tuple_name, filename );
461  }
462 }
463 
464 string
467 {
469  controller -> registerNTuple ( ds );
470 
471  return ds -> getName ();
472 }
473 
474 void
476 registerNTuple ( const std::string & key, DataSource * ntuple )
477 {
479  controller -> registerNTuple ( key, ntuple );
480 }
481 
482 
483 NTuple *
485 createNTuple( const std::vector < std::string > & column_list,
486  const std::vector < const TupleCut * > & cut_list,
487  DataSource * ds )
488 {
489  if ( column_list.empty() ) return NULL;
490 
491  unsigned int columnNumber = column_list.size();
492  unsigned int cutNumber = cut_list.size();
493  unsigned int size = ds->rows();
494 
495  NTuple * nt = new NTuple( column_list );
496 
497  // Check all the rows.
498  for ( unsigned int i = 0; i < size; i++ )
499  {
500  // If cut is not selected, default is accept.
501  bool accept = true;
502 
503  // Check all the cuts.
504  for ( unsigned int j = 0; j < cutNumber; j++ )
505  {
506  const TupleCut * tc = cut_list[j];
507  accept = tc -> acceptRow ( ds, i );
508  if (!accept) break;
509  }
510 
511  // Add the row when all cuts accept the row.
512  if (accept) {
513  vector <double> row;
514  for ( unsigned int k = 0; k < columnNumber; k++ )
515  {
516  row.push_back(ds->valueAtNoCache(i,ds->indexOf(column_list[k])));
517  }
518  nt->addRow(row);
519  }
520  }
521 
522  return nt;
523 
524 }
525 
526 int
528 createNTupleToFile( const std::vector < std::string > & column_list,
529  const std::vector < const TupleCut * > & cut_list,
530  DataSource * ds,
531  const std::string & filename,
532  const std::string & dsname)
533 {
534  if ( column_list.empty() ) return 1;
535 
536  ofstream file ( filename.c_str() );
537  if ( file.is_open () == false ) {
538  return 1;
539  }
540  // Check the column list and create indices for inner loop
541  unsigned int columnNumber = column_list.size();
542  vector < int > col_indices ( columnNumber );
543 
544  for ( unsigned int i = 0; i < columnNumber; i++ ) {
545  const string & label = column_list [ i ];
546  int index = ds -> indexOf ( label );
547  if ( index < 0 ) {
548  ds -> throwIfInvalidLabel ( label );
549  }
550  col_indices [i] = index;
551  }
552 
553  file << dsname << endl;
554 
555 #ifdef ITERATOR_MEMBER_DEFECT
556  std::
557 #endif
558  vector < string > ::const_iterator first = column_list.begin ();
559  string label = *first++;
560  file << label;
561  while ( first != column_list.end() ) {
562  label = *first++;
563  file << "\t" << label;
564  }
565  file << endl;
566 
567  unsigned int cutNumber = cut_list.size();
568  unsigned int size = ds->rows();
569 
570  // Check all the rows.
571  for ( unsigned int i = 0; i < size; i++ )
572  {
573  // If cut is not selected, default is accept.
574  bool accept = true;
575 
576  // Check all the cuts.
577  for ( unsigned int j = 0; j < cutNumber; j++ )
578  {
579  const TupleCut * tc = cut_list[j];
580  accept = tc -> acceptRow ( ds, i );
581  if (!accept) break;
582  }
583 
584  // Add the row to the file when all cuts accept the row.
585  if (accept) {
586 
587  for ( unsigned int k = 0; k < columnNumber; k++ )
588  {
589  int index = col_indices [ k ];
590  file << "\t" << ds -> valueAtNoCache (i, index );
591  }
592  file << endl;
593  }
594  }
595  return 0;
596 }
virtual void setTitle(const std::string &title)
Sets the title of the data source to title.
Definition: DataSource.cxx:146
void splitAndFill(const std::string &line, std::vector< std::string > &values)
Splits the line at white space and fills values with strings found.
unsigned int i
std::string::size_type findWhite(const std::string &line, unsigned int left=0, bool tabs_only=false)
Find and return position of white space.
NTupleController()
A default constructor for avoiding creation except by itself.
std::string registerNTuple(DataSource *nt)
Register a NTuple.
int writeNTupleToFile(DataSource *source, const std::string &filename)
Writes the DataSource source to a file given by filename.
void changeName(DataSource *source, const std::string &newname)
Changes the name of the DataSource object.
int createNTupleToFile(const std::vector< std::string > &column_list, const std::vector< const TupleCut * > &cut_list, DataSource *ds, const std::string &filename, const std::string &dsname)
Create NTuple with column list and cut list and save to a file.
int readAsciiNTuple(NTuple *ntuple, const std::string &filename)
Reads ASCII formatted file and fills the NTuple.
void setLabels(const std::vector< std::string > &v)
Assigns the label to each column from the vector of strings.
Definition: NTuple.cxx:471
const std::string & title() const
Returns a const reference to the title of the data source.
Definition: DataSource.cxx:141
std::vector< intptr_t > shape(numeric::array arr)
Definition: num_util.cpp:317
The class expresses a cut on a DataSource, i.e.
Definition: TupleCut.h:43
virtual void addRow(const std::vector< double > &v)
Adds a row to the end of the ntuple.
Definition: NTuple.cxx:266
The namespace for conversion to string.
CircularBuffer * createCircularBuffer()
Creates and registers an empty CircularBuffer.
void fillFromFile(const std::string &file, NTuple *source)
Fills the empty NTuple source from reading data from the file.
void saveNTuples(const std::string &prefix, const std::string &suffix)
Saves all the NTuple.
virtual const std::vector< std::string > & getLabels() const
Returns the list of available labels.
Definition: DataSource.cxx:172
A singleton class that is the interface between GUI and the NTuple objects.
intp size(numeric::array arr)
Definition: num_util.cpp:296
string convert(int i)
Converts an integer to a string.
CircularBuffer class interface.
A singleton class that is the interface between GUI and the DataSource objects.
virtual double valueAtNoCache(unsigned int row, unsigned int column) const
Returns the value in the table in position given by the row and column indexes without storing it int...
Definition: DataSource.cxx:541
static NTupleController * instance()
Returns the pointer to the singleton instance.
NTuple * createNTuple()
Creates and registers an empty NTuple.
void getDataSources(std::vector< DataSource * > &, bool all=true) const
Clears and fills the vector with the registered DataSource objects.
A DataSource class implemented with std::vector&lt;double&gt; to store the column data. ...
Definition: NTuple.h:33
hippodraw::TupleCut class interface
virtual unsigned int rows() const =0
Returns the number of rows.
virtual int indexOf(const std::string &label) const
Returns true if the specified column labeled label has been filled.
Definition: DataSource.cxx:193
CircularBuffer manager.
return index
Definition: PickTable.cxx:182
hippodraw::NTupleController class interface
DataSourceController class interface.
virtual const std::vector< double > & getRow(unsigned int) const =0
Returns a const reference to slice along the axis known as a row.
DataSource * findDataSource(const std::string &name) const
Returns the DataSource object with name name.
const std::string & getName() const
Returns the name of the data source.
Definition: DataSource.cxx:136
static NTupleController * s_instance
The pointer to the singleton object.
static DataSourceController * instance()
Returns the pointer to the singleton instance.
Base class for DataSource.
Definition: DataSource.h:55

Generated for HippoDraw Class Library by doxygen