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 }

Generated for HippoDraw Class Library by doxygen