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