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