ColumnDataReader.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include "ColumnDataReader.hpp"
00036 #include "ColumnDataConstants.hpp"
00037
00038 #include <fstream>
00039 #include <sstream>
00040 #include <iomanip>
00041 #include <cassert>
00042 #include <climits>
00043 #include "OutputFileHandler.hpp"
00044 #include "Exception.hpp"
00045
00050 const int NOT_READ = -999;
00051
00052 ColumnDataReader::ColumnDataReader(const std::string& rDirectory,
00053 const std::string& rBaseName,
00054 bool makeAbsolute)
00055 {
00056
00057 std::string directory;
00058 if (makeAbsolute)
00059 {
00060 OutputFileHandler output_file_handler(rDirectory, false);
00061 directory = output_file_handler.GetOutputDirectoryFullPath();
00062 }
00063 else
00064 {
00065
00066 if ( !(*(rDirectory.end()-1) == '/'))
00067 {
00068 directory = rDirectory + "/";
00069 }
00070 }
00071
00072
00073 mInfoFilename = directory + rBaseName + ".info";
00074 std::ifstream infofile(mInfoFilename.c_str(), std::ios::in);
00075
00076
00077 if (!infofile.is_open())
00078 {
00079 EXCEPTION("Couldn't open info file: " + mInfoFilename);
00080 }
00081 std::string junk;
00082 mNumFixedDimensions = NOT_READ;
00083 mHasUnlimitedDimension = false;
00084 mNumVariables = NOT_READ;
00085
00086 infofile >> junk;
00087 infofile >> mNumFixedDimensions >> junk;
00088 infofile >> mHasUnlimitedDimension >> junk;
00089 infofile >> mNumVariables;
00090
00091 if (mNumFixedDimensions == NOT_READ || mNumVariables == NOT_READ)
00092 {
00093 infofile.close();
00094 EXCEPTION("Couldn't read info file correctly");
00095 }
00096
00097
00098 if (mHasUnlimitedDimension)
00099 {
00100 if (mNumFixedDimensions < 1)
00101 {
00102 mDataFilename = directory + rBaseName + ".dat";
00103 }
00104 else
00105 {
00106 std::stringstream suffix;
00107 suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << 0;
00108
00109 mDataFilename = directory + rBaseName + "_" + suffix.str() + ".dat";
00110
00111
00112
00113 mAncillaryFilename = directory + rBaseName + "_unlimited.dat";
00114
00115
00116 std::ifstream ancillaryfile(mAncillaryFilename.c_str(), std::ios::in);
00117
00118
00119 if (!ancillaryfile.is_open())
00120 {
00121 EXCEPTION("Couldn't open ancillary data file");
00122 }
00123 std::string dimension;
00124 std::getline(ancillaryfile, dimension);
00125 std::stringstream dimension_stream(dimension);
00126 std::string dimension_unit, dimension_name, header;
00127 dimension_stream >> header;
00128
00129
00130 int unitpos = header.find("(") + 1;
00131
00132 dimension_name = header.substr(0, unitpos - 1);
00133 dimension_unit = header.substr(unitpos, header.length() - unitpos - 1);
00134
00135 mVariablesToUnits[dimension_name] = dimension_unit;
00136 ancillaryfile.close();
00137 }
00138 }
00139 else
00140 {
00141 mDataFilename = directory + rBaseName + ".dat";
00142 }
00143
00144 std::ifstream datafile(mDataFilename.c_str(), std::ios::in);
00145
00146 if (!datafile.is_open())
00147 {
00148 EXCEPTION("Couldn't open data file");
00149 }
00150
00151 std::string variables;
00152 std::getline(datafile, variables);
00153 std::stringstream variable_stream(variables);
00154 std::string header, variable, unit;
00155 int column = 0;
00156
00157
00158 while (variable_stream >> header)
00159 {
00160
00161 int unitpos = header.find("(") + 1;
00162
00163 variable = header.substr(0, unitpos - 1);
00164 unit = header.substr(unitpos, header.length() - unitpos - 1);
00165
00166 mVariablesToColumns[variable] = column;
00167 mVariablesToUnits[variable] = unit;
00168
00169 column++;
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 std::string first_line;
00184 std::string first_entry;
00185
00186
00187 while (first_entry.length()==0 && !datafile.eof())
00188 {
00189 std::getline(datafile, first_line);
00190 std::stringstream stream(first_line);
00191 stream >> first_entry;
00192 }
00193
00194 if (datafile.eof() && first_entry.length()==0)
00195 {
00196 EXCEPTION("Unable to determine field width from file as cannot find any data entries");
00197 }
00198
00199 size_t dot_pos = first_entry.find(".");
00200 size_t e_pos = first_entry.find("e");
00201 if (dot_pos == std::string::npos || e_pos == std::string::npos)
00202 {
00203 EXCEPTION("Badly formatted scientific data field");
00204 }
00205 mFieldWidth = e_pos - dot_pos - 1 + 7;
00206
00207 dot_pos = first_line.find(".");
00208 size_t second_dot_pos = first_line.find(".", dot_pos+1);
00209 if ((second_dot_pos != std::string::npos) &&
00210 (second_dot_pos - dot_pos == mFieldWidth + SPACING - 1))
00211 {
00212 mFieldWidth--;
00213 }
00214
00215 infofile.close();
00216 datafile.close();
00217 }
00218
00219 std::vector<double> ColumnDataReader::GetValues(const std::string& rVariableName)
00220 {
00221 if (mNumFixedDimensions > 0)
00222 {
00223 EXCEPTION("Data file has fixed dimension which must be specified");
00224 }
00225
00226 std::map<std::string, int>::iterator col = mVariablesToColumns.find(rVariableName);
00227 if (col == mVariablesToColumns.end())
00228 {
00229 std::stringstream variable_name;
00230 variable_name << rVariableName;
00231 EXCEPTION("'" + variable_name.str() + "' is an unknown variable.");
00232 }
00233
00234 int column = (*col).second;
00235 ReadColumnFromFile(mDataFilename, column);
00236
00237 return mValues;
00238 }
00239
00240 std::vector<double> ColumnDataReader::GetValues(const std::string& rVariableName,
00241 int fixedDimension)
00242 {
00243 if (mNumFixedDimensions < 1)
00244 {
00245 EXCEPTION("Data file has no fixed dimension");
00246 }
00247
00248 mValues.clear();
00249 if (mHasUnlimitedDimension)
00250 {
00251 std::string datafile = mDataFilename;
00252 std::map<std::string, int>::iterator col = mVariablesToColumns.find(rVariableName);
00253 if (col == mVariablesToColumns.end())
00254 {
00255 EXCEPTION("Unknown variable");
00256 }
00257 int column = (*col).second;
00258
00259 int counter = 1;
00260 while (true)
00261 {
00262 try
00263 {
00264 ReadValueFromFile(datafile, column, fixedDimension);
00265 }
00266 catch (Exception)
00267 {
00268 break;
00269 }
00270
00271
00272 std::string::size_type underscore_pos = datafile.rfind("_", datafile.length());
00273 std::stringstream suffix;
00274
00275 suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << counter;
00276
00277 if (underscore_pos != std::string::npos)
00278 {
00279 datafile = datafile.substr(0, underscore_pos+1) + suffix.str() + ".dat";
00280 }
00281 counter++;
00282 }
00283 }
00284 else
00285 {
00286 int column = mVariablesToColumns[rVariableName];
00287 if (0 == column)
00288 {
00289 EXCEPTION("Unknown variable");
00290 }
00291 ReadValueFromFile(mDataFilename, column, fixedDimension);
00292 }
00293
00294 return mValues;
00295 }
00296
00297 std::vector<double> ColumnDataReader::GetUnlimitedDimensionValues()
00298 {
00299 mValues.clear();
00300 if (!mHasUnlimitedDimension)
00301 {
00302 EXCEPTION("Data file has no unlimited dimension");
00303 }
00304 if (mNumFixedDimensions > 0)
00305 {
00306
00307 ReadColumnFromFile(mAncillaryFilename, 0);
00308 }
00309 else
00310 {
00311
00312 ReadColumnFromFile(mDataFilename, 0);
00313 }
00314 return mValues;
00315 }
00316
00317 void ColumnDataReader::ReadValueFromFile(const std::string& rFilename, int col, int row)
00318 {
00319 std::ifstream datafile(rFilename.c_str(), std::ios::in);
00320
00321 if (!datafile.is_open())
00322 {
00323 EXCEPTION("Couldn't open data file");
00324 }
00325 std::string variable_values;
00326 for (int i=0; i<row+1; i++)
00327 {
00328 std::getline(datafile, variable_values);
00329 }
00330
00331 std::getline(datafile, variable_values);
00332 this->PushColumnEntryFromLine(variable_values, col);
00333
00334 datafile.close();
00335 }
00336
00337 void ColumnDataReader::ReadColumnFromFile(const std::string& rFilename, int col)
00338 {
00339
00340 mValues.clear();
00341
00342
00343 std::ifstream datafile(rFilename.c_str(), std::ios::in);
00344 std::string value;
00345
00346
00347 assert(datafile.is_open());
00348
00349
00350 bool end_of_file_reached = false;
00351
00352
00353 end_of_file_reached = std::getline(datafile, value).eof();
00354
00355 while (!end_of_file_reached)
00356 {
00357 end_of_file_reached = std::getline(datafile, value).eof();
00358 this->PushColumnEntryFromLine(value, col);
00359 }
00360 datafile.close();
00361 }
00362
00363 void ColumnDataReader::PushColumnEntryFromLine(const std::string& rLine, int col)
00364 {
00365 int startpos = col * (mFieldWidth + SPACING) + SPACING - 1;
00366 std::string value = rLine.substr(startpos, mFieldWidth + 1);
00367 std::stringstream variable_stream(value);
00368 double d_value;
00369 variable_stream >> d_value;
00370 if (variable_stream.fail())
00371 {
00372 d_value = DBL_MAX;
00373 }
00374
00375 mValues.push_back(d_value);
00376 }
00377
00378 bool ColumnDataReader::HasValues(const std::string& rVariableName)
00379 {
00380 std::map<std::string, int>::iterator col = mVariablesToColumns.find(rVariableName);
00381 return !(col == mVariablesToColumns.end());
00382 }
00383
00384 unsigned ColumnDataReader::GetFieldWidth()
00385 {
00386 return mFieldWidth;
00387 }
00388