ColumnDataReader.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
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 
00044 #include "OutputFileHandler.hpp"
00045 #include "Exception.hpp"
00046 
00051 const int NOT_READ = -999;
00052 
00053 ColumnDataReader::ColumnDataReader(const std::string& rDirectory,
00054                                    const std::string& rBaseName,
00055                                    bool makeAbsolute)
00056 {
00057     // Find out where files are really stored
00058     std::string directory;
00059     if (makeAbsolute)
00060     {
00061         OutputFileHandler output_file_handler(rDirectory, false);
00062         directory = output_file_handler.GetOutputDirectoryFullPath();
00063     }
00064     else
00065     {
00066         // Add a trailing slash if needed
00067         if ( !(*(rDirectory.end()-1) == '/'))
00068         {
00069             directory = rDirectory + "/";
00070         }
00071     }
00072 
00073     // Read in info file
00074     mInfoFilename = directory + rBaseName + ".info";
00075     std::ifstream infofile(mInfoFilename.c_str(), std::ios::in);
00076 
00077     // If it doesn't exist - throw exception
00078     if (!infofile.is_open())
00079     {
00080         EXCEPTION("Couldn't open info file: " + mInfoFilename);
00081     }
00082     std::string junk;
00083     mNumFixedDimensions = NOT_READ;
00084     mHasUnlimitedDimension = false;
00085     mNumVariables = NOT_READ;
00086 
00087     infofile >> junk;
00088     infofile >> mNumFixedDimensions >> junk;
00089     infofile >> mHasUnlimitedDimension >> junk;
00090     infofile >> mNumVariables;
00091 
00092     if (mNumFixedDimensions == NOT_READ || mNumVariables == NOT_READ)
00093     {
00094         infofile.close();
00095         EXCEPTION("Couldn't read info file correctly");
00096     }
00097 
00098     // Read in variables and associated them with a column number
00099     if (mHasUnlimitedDimension)
00100     {
00101         if (mNumFixedDimensions < 1)
00102         {
00103             mDataFilename = directory + rBaseName + ".dat";
00104         }
00105         else
00106         {
00107             std::stringstream suffix;
00108             suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << 0;
00109 
00110             mDataFilename = directory + rBaseName + "_" + suffix.str() + ".dat";
00111 
00112             // The ancillary path needs to come from a single place that is
00113             // used by both the reader & writer, otherwise all will be bad.
00114             mAncillaryFilename = directory + rBaseName + "_unlimited.dat";
00115 
00116             // Extract the units and place into map
00117             std::ifstream ancillaryfile(mAncillaryFilename.c_str(), std::ios::in);
00118 
00119             // If it doesn't exist - throw exception
00120             if (!ancillaryfile.is_open())
00121             {
00122                 EXCEPTION("Couldn't open ancillary data file");
00123             }
00124             std::string dimension;
00125             std::getline(ancillaryfile, dimension);
00126             std::stringstream dimension_stream(dimension);
00127             std::string dimension_unit, dimension_name, header;
00128             dimension_stream >> header;
00129 
00130             // Separate into variable name and units
00131             int unitpos = header.find("(") + 1;
00132 
00133             dimension_name = header.substr(0, unitpos - 1);
00134             dimension_unit = header.substr(unitpos, header.length() - unitpos - 1);
00135 
00136             mVariablesToUnits[dimension_name] = dimension_unit;
00137             ancillaryfile.close();
00138         }
00139     }
00140     else
00141     {
00142         mDataFilename = directory + rBaseName + ".dat";
00143     }
00144 
00145     std::ifstream datafile(mDataFilename.c_str(), std::ios::in);
00146     // If it doesn't exist - throw exception
00147     if (!datafile.is_open())
00148     {
00149         EXCEPTION("Couldn't open data file");
00150     }
00151 
00152     std::string variables;
00153     std::getline(datafile, variables);
00154     std::stringstream variable_stream(variables);
00155     std::string header, variable, unit;
00156     int column = 0;
00157 
00158     // Insert variables into map
00159     while (variable_stream >> header)
00160     {
00161         // Separate into variable name and units
00162         int unitpos = header.find("(") + 1;
00163 
00164         variable = header.substr(0, unitpos - 1);
00165         unit = header.substr(unitpos, header.length() - unitpos - 1);
00166 
00167         mVariablesToColumns[variable] = column;
00168         mVariablesToUnits[variable] = unit;
00169 
00170         column++;
00171     }
00172     infofile.close();
00173     datafile.close();
00174 }
00175 
00176 std::vector<double> ColumnDataReader::GetValues(const std::string& rVariableName)
00177 {
00178     if (mNumFixedDimensions > 0)
00179     {
00180         EXCEPTION("Data file has fixed dimension which must be specified");
00181     }
00182 
00183     std::map<std::string, int>::iterator col = mVariablesToColumns.find(rVariableName);
00184     if (col == mVariablesToColumns.end())
00185     {
00186         EXCEPTION("Unknown variable");
00187     }
00188 
00189     int column = (*col).second;
00190     ReadColumnFromFile(mDataFilename, column);
00191 
00192     return mValues;
00193 }
00194 
00195 std::vector<double> ColumnDataReader::GetValues(const std::string& rVariableName,
00196                                                 int fixedDimension)
00197 {
00198     if (mNumFixedDimensions < 1)
00199     {
00200         EXCEPTION("Data file has no fixed dimension");
00201     }
00202 
00203     mValues.clear();
00204     if (mHasUnlimitedDimension)
00205     {
00206         std::string datafile = mDataFilename;
00207         std::map<std::string, int>::iterator col = mVariablesToColumns.find(rVariableName);
00208         if (col == mVariablesToColumns.end())
00209         {
00210             EXCEPTION("Unknown variable");
00211         }
00212         int column = (*col).second;
00213 
00214         int counter = 1;
00215         while (true)
00216         {
00217             try
00218             {
00219                 ReadValueFromFile(datafile, column, fixedDimension);
00220             }
00221             catch (Exception)
00222             {
00223                 break;
00224             }
00225 
00226             // Advance counter
00227             std::string::size_type underscore_pos = datafile.rfind("_", datafile.length());
00228             std::stringstream suffix;
00229 
00230             suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << counter;
00231 
00232             if (underscore_pos != std::string::npos)
00233             {
00234                 datafile = datafile.substr(0, underscore_pos+1) + suffix.str() + ".dat";
00235             }
00236             counter++;
00237         }
00238     }
00239     else
00240     {
00241         int column = mVariablesToColumns[rVariableName];
00242         if (0 == column)
00243         {
00244             EXCEPTION("Unknown variable");
00245         }
00246         ReadValueFromFile(mDataFilename, column, fixedDimension);
00247     }
00248 
00249     return mValues;
00250 }
00251 
00252 std::vector<double> ColumnDataReader::GetUnlimitedDimensionValues()
00253 {
00254     mValues.clear();
00255     if (!mHasUnlimitedDimension)
00256     {
00257         EXCEPTION("Data file has no unlimited dimension");
00258     }
00259     if (mNumFixedDimensions > 0)
00260     {
00261         // Read in from the ancillary file
00262         ReadColumnFromFile(mAncillaryFilename, 0);
00263     }
00264     else
00265     {
00266         // Read the first column
00267         ReadColumnFromFile(mDataFilename, 0);
00268     }
00269     return mValues;
00270 }
00271 
00272 void ColumnDataReader::ReadValueFromFile(const std::string& rFilename, int col, int row)
00273 {
00274     std::ifstream datafile(rFilename.c_str(), std::ios::in);
00275     // If it doesn't exist - throw exception
00276     if (!datafile.is_open())
00277     {
00278         EXCEPTION("Couldn't open data file");
00279     }
00280     std::string variable_values;
00281     for (int i=0; i<row+1; i++)
00282     {
00283         std::getline(datafile, variable_values);
00284     }
00285 
00286     std::getline(datafile, variable_values);
00287     this->PushColumnEntryFromLine(variable_values, col);
00288 
00289     datafile.close();
00290 }
00291 
00292 void ColumnDataReader::ReadColumnFromFile(const std::string& rFilename, int col)
00293 {
00294     // Empty the values vector
00295     mValues.clear();
00296 
00297     // Read in from the ancillary file
00298     std::ifstream datafile(rFilename.c_str(), std::ios::in);
00299     std::string value;
00300 
00301     // We should have already checked that this file can be opened.
00302     assert(datafile.is_open());
00303 
00304     // The current variable becomes true just after reading the last line
00305     bool end_of_file_reached = false;
00306 
00307     // Skip header line
00308     end_of_file_reached = std::getline(datafile, value).eof();
00309 
00310     while (!end_of_file_reached)
00311     {
00312         end_of_file_reached = std::getline(datafile, value).eof();
00313         this->PushColumnEntryFromLine(value, col);
00314     }
00315     datafile.close();
00316 }
00317 
00318 void ColumnDataReader::PushColumnEntryFromLine(const std::string& rLine, int col)
00319 {
00320     int startpos = col * (FIELD_WIDTH + SPACING) + SPACING - 1;
00321     std::string value = rLine.substr(startpos, FIELD_WIDTH + 1);
00322     std::stringstream variable_stream(value);
00323     double d_value;
00324     variable_stream >> d_value;
00325     if (variable_stream.fail())
00326     {
00327         d_value = DBL_MAX;
00328     }
00329 
00330     mValues.push_back(d_value);
00331 }
00332 
00333 bool ColumnDataReader::HasValues(const std::string& rVariableName)
00334 {
00335     std::map<std::string, int>::iterator col = mVariablesToColumns.find(rVariableName);
00336     return !(col == mVariablesToColumns.end());
00337 }

Generated on Tue Aug 4 16:10:22 2009 for Chaste by  doxygen 1.5.5