CEDRIC  Revision_backup-2009-02
DataReader.h
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * Copyright (C) 2008 Max Hermann
4  *
5  * This file is part of the "CEDRIC Event Display" application.
6  *
7  *****************************************************************************/
8 
9 #ifndef REDUKT_DATAREADER_H
10 #define REDUKT_DATAREADER_H
11 
12 #include <boost/numeric/ublas/matrix.hpp>
13 
14 #include <sstream>
15 #include <fstream>
16 #include <iostream>
17 #include <vector>
18 
30 template<class C>
32 {
33 public:
34  DataReader( C& data ): m_data(data), m_rows(-1),m_columns(-1) {}
35 
36  bool loadCSV( const char* filename );
37 
38  int numRows() const { return m_rows; }
39  int numColumns() const { return m_columns; }
40 
41 protected:
42  inline bool insertValue( int row, int column, double value );
43 
44  void inline remove_commas ( std::string& s )
45  {
46  size_t pos = s.find(',');
47  while( pos != std::string::npos )
48  {
49  // replace found comma with space character
50  s[pos] = ' ';
51 
52  // go and find next comma
53  pos = s.find( ',', pos );
54  }
55  }
56 
57  void inline remove_comments( std::string& s )
58  {
59  size_t pos = s.find('#');
60  if( pos != std::string::npos )
61  {
62  // remove rest of line beginning with '#'
63  s.erase( pos );
64  }
65  }
66 
67  bool inline is_comment_or_empty( const std::string& s )
68  {
69  // find first non empty character
70  size_t pos = s.find_first_not_of(' ');
71 
72  // line empty?
73  if( pos == std::string::npos ) return true;
74 
75  // line begins with caret '#'?
76  if( s[pos] == '#' ) return true;
77 
78  return false;
79  }
80 
81 private:
82  C& m_data;
83  int m_rows, m_columns;
84 };
85 
86 
87 //=====================================================================================================================
88 
89 // TEMPLATE IMPLEMENTATION
90 
91 //=====================================================================================================================
92 
93 template<class C>
94 bool DataReader<C>::loadCSV( const char* filename )
95 {
96  using namespace std;
97 
98  // open file
99  ifstream f;
100  f.open( filename, ifstream::in );
101  if( !f.good() )
102  {
103  f.close();
104  cout << "ERROR opening file " << filename << endl;
105  return false;
106  }
107 
108  int rows=0, columns=-1;
109 
110  // read line by line
111  string line;
112  int cur_line=0; // number of read lines (also counts empty and ignored lines)
113  while( !f.eof() )
114  {
115  cout << "Read " << cur_line << " lines\r" << std::flush;
116 
117  getline( f, line ); cur_line++;
118  if( line.empty() ) continue;
119 
120  // ignore comment lines
121  if( is_comment_or_empty( line ) ) continue;
122 
123  // we want space-separated data, so we remove any commas
124  remove_commas( line );
125 
126  // remove any trailing comments
127  remove_comments( line );
128 
129  stringstream ss( line );
130 
131  int cur_col = 0;
132 
133  double value;
134  bool first_value_in_row=true;
135  while( (ss >> value) && !ss.fail() )
136  {
137  if( columns != -1 )
138  if( cur_col >= columns )
139  {
140  cout << endl << "WARNING skipped additional column in line " << cur_line << endl;
141  continue;
142  }
143 
144  insertValue( rows, cur_col, value );
145  cur_col++;
146 
147  first_value_in_row = false;
148  }
149 
150  // fail bit indicates that input could not be interpreted as double
151  //if( ss.fail() ) // also true when bad bit set
152  if( ss.rdstate() & ifstream::failbit )
153  {
154  if( first_value_in_row )
155  {
156  cout << endl << "WARNING skipped line " << cur_line << " assuming it contains some kind of comment" << endl;
157  // skip whole line (assuming row contains a comment or headers)
158  continue;
159  }
160 
161  //~ // exit with an error
162  //~ f.close();
163  //~ cout << "ERROR parsing error at line " << cur_line << endl;
164  //~ return false;
165  }
166 
167  // just read the first data column?
168  if( columns == -1 )
169  {
170  // yes, then store number of columns which all following rows must match
171  columns = cur_col;
172  }
173  else
174  {
175  // cur_col must match columns
176  if( cur_col =! columns )
177  {
178  cout << endl << "ERROR in line " << cur_line << ", too few columns!" << endl;
179  f.close();
180  return false;
181  }
182  }
183 
184  rows++;
185  }
186 
187  f.close();
188 
189  // set members
190  m_rows = rows;
191  m_columns = columns;
192 
193  return true;
194 };
195 
196 
197 //=====================================================================================================================
198 
199 // TEMPLATE SPECIALIZATION
200 
201 //=====================================================================================================================
202 
203 template<>
204 bool DataReader<boost::numeric::ublas::matrix<float> >::insertValue( int row, int column, double value )
205 {
206  //m_data.insert_element( row, col, (float)value );
207  //~ unsigned int nrows = (row >= (int)m_data.size1()) ? row+1 : m_data.size1();
208  //~ unsigned int ncols = (column >= (int)m_data.size2()) ? column+1 : m_data.size2();
209  //~ m_data.resize( nrows, ncols );
210  m_data( row, column ) = (float)value;
211  return true;
212 }
213 
214 template<>
215 bool DataReader<boost::numeric::ublas::matrix<double> >::insertValue( int row, int column, double value )
216 {
217  //~ unsigned int nrows = (row >= (int)m_data.size1()) ? row+1 : m_data.size1();
218  //~ unsigned int ncols = (column >= (int)m_data.size2()) ? column+1 : m_data.size2();
219  //~ m_data.resize( nrows, ncols );
220  m_data( row, column ) = value;
221  return true;
222 }
223 
224 template<>
225 bool DataReader<std::vector<float> >::insertValue( int /*row*/, int /*column*/, double value )
226 {
227  // we ignore row and column and assume row wise input
228  m_data.push_back( (float)value );
229  return true;
230 }
231 
232 template<>
233 bool DataReader<std::vector<double> >::insertValue( int /*row*/, int /*column*/, double value )
234 {
235  // we ignore row and column and assume row wise input
236  m_data.push_back( (double)value );
237  return true;
238 }
239 
240 
241 #endif // REDUKT_DATAREADER_H
Load real valued matrix type data from disk (currently only CSV is supported).
Definition: DataReader.h:31
int numRows() const
Definition: DataReader.h:38
int numColumns() const
Definition: DataReader.h:39
DataReader(C &data)
Definition: DataReader.h:34
void remove_comments(std::string &s)
Definition: DataReader.h:57
bool insertValue(int row, int column, double value)
bool is_comment_or_empty(const std::string &s)
Definition: DataReader.h:67
bool loadCSV(const char *filename)
Definition: DataReader.h:94
void remove_commas(std::string &s)
Definition: DataReader.h:44