ColumnDataReader.cpp

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 */
00033 #include <string>
00034 #include <fstream>
00035 #include <iostream>
00036 #include <sstream>
00037 #include <iomanip>
00038 #include <assert.h>
00039 #include <values.h>
00040 #include "ColumnDataReader.hpp"
00041 #include "OutputFileHandler.hpp"
00042 #include "Exception.hpp"
00043 
00048 const int NOT_READ = -999;
00049 
00058 ColumnDataReader::ColumnDataReader(std::string directory, std::string basename,
00059                                    bool make_absolute)
00060 {
00061     // Find out where files are really stored
00062     if (make_absolute)
00063     {
00064         OutputFileHandler output_file_handler(directory, false);
00065         directory = output_file_handler.GetOutputDirectoryFullPath();
00066     }
00067     else
00068     {
00069         // Add a trailing slash if needed
00070         if ( !(*(directory.end()-1) == '/'))
00071         {
00072             directory = directory + "/";
00073         }
00074     }
00075     // Read in info file
00076     mInfoFilename = directory + basename + ".info";
00077     std::ifstream infofile(mInfoFilename.c_str(), std::ios::in);
00078     // If it doesn't exist - throw exception
00079     if (!infofile.is_open())
00080     {
00081         EXCEPTION("Couldn't open info file: " + mInfoFilename);
00082     }
00083     std::string junk;
00084     mNumFixedDimensions = NOT_READ;
00085     mHasUnlimitedDimension = false;
00086     mNumVariables = NOT_READ;
00087 
00088     infofile >> junk;
00089     infofile >> mNumFixedDimensions >> junk;
00090     infofile >> mHasUnlimitedDimension >> junk;
00091     infofile >> mNumVariables;
00092 
00093     if (mNumFixedDimensions == NOT_READ || mNumVariables == NOT_READ)
00094     {
00095         infofile.close();
00096         EXCEPTION("Couldn't read info file correctly");
00097     }
00098     //Read in variables and associated them with a column number
00099     std::string variables;
00100     std::string dataFilename;
00101     if (mHasUnlimitedDimension)
00102     {
00103         if (mNumFixedDimensions < 1)
00104         {
00105             mDataFilename = directory + basename + ".dat";
00106         }
00107         else
00108         {
00109             std::stringstream suffix;
00110             suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << 0;
00111 
00112             mDataFilename = directory + basename + "_" + suffix.str() + ".dat";
00113             //the ancillary path needs to come from a single place that is
00114             //used by both the reader & writer, otherwise all will be bad.
00115             mAncillaryFilename = directory + basename + "_unlimited.dat";
00116             //Extract the units and place into map
00117             std::ifstream ancillaryfile(mAncillaryFilename.c_str(),std::ios::in);
00118             //If it doesn't exist - throw exception
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 dimensionStream(dimension);
00126             std::string dimension_unit, dimension_name, header;
00127             dimensionStream >> header;
00128 
00129             //separate into variable name and units
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 + basename + ".dat";
00142     }
00143 
00144     std::ifstream datafile(mDataFilename.c_str(),std::ios::in);
00145     //If it doesn't exist - throw exception
00146     if (!datafile.is_open())
00147     {
00148         EXCEPTION("Couldn't open data file");
00149     }
00150 
00151     std::getline(datafile, variables);
00152     std::stringstream variableStream(variables);
00153     std::string header, variable, unit;
00154     int column = 0;
00155     //Insert variables into map
00156     while (variableStream >> header)
00157     {
00158         //separate into variable name and units
00159         int unitpos = header.find("(") + 1;
00160 
00161         variable = header.substr(0,unitpos - 1);
00162         unit = header.substr(unitpos,header.length() - unitpos - 1);
00163 
00164         mVariablesToColumns[variable] = column;
00165         mVariablesToUnits[variable] = unit;
00166 
00167         column++;
00168 
00169     }
00170     infofile.close();
00171     datafile.close();
00172 }
00173 
00174 
00175 std::vector<double> ColumnDataReader::GetValues(std::string variableName)
00176 {
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(variableName);
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 
00196 std::vector<double> ColumnDataReader::GetValues(std::string variableName,
00197                                                 int fixedDimension)
00198 {
00199     if (mNumFixedDimensions < 1)
00200     {
00201         EXCEPTION("Data file has no fixed dimension");
00202     }
00203 
00204     mValues.clear();
00205     if (mHasUnlimitedDimension)
00206     {
00207         std::string datafile = mDataFilename;
00208         std::map<std::string, int>::iterator col = mVariablesToColumns.find(variableName);
00209         if (col == mVariablesToColumns.end())
00210         {
00211             EXCEPTION("Unknown variable");
00212         }
00213         int column = (*col).second;
00214 
00215         int counter = 1;
00216         while (true)
00217         {
00218             try
00219             {
00220                 ReadValueFromFile(datafile, column, fixedDimension);
00221             }
00222             catch (Exception)
00223             {
00224                 break;
00225             }
00226 
00227             //advance counter
00228             std::string::size_type underscore_pos = datafile.rfind("_",datafile.length());
00229             std::stringstream suffix;
00230 
00231             suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << counter;
00232 
00233             if (underscore_pos != std::string::npos)
00234             {
00235                 datafile = datafile.substr(0,underscore_pos+1) + suffix.str() + ".dat";
00236             }
00237             counter++;
00238         }
00239     }
00240     else
00241     {
00242         int column = mVariablesToColumns[variableName];
00243         if (0 == column)
00244         {
00245             EXCEPTION("Unknown variable");
00246         }
00247         ReadValueFromFile(mDataFilename,column,fixedDimension);
00248     }
00249 
00250     return mValues;
00251 }
00252 
00253 std::vector<double> ColumnDataReader::GetUnlimitedDimensionValues()
00254 {
00255     mValues.clear();
00256     if (!mHasUnlimitedDimension)
00257     {
00258         EXCEPTION("Data file has no unlimited dimension");
00259     }
00260     if (mNumFixedDimensions > 0)
00261     {
00262         //read in from the ancillary file
00263         ReadColumnFromFile(mAncillaryFilename,0);
00264     }
00265     else
00266     {
00267         //read the first column
00268         ReadColumnFromFile(mDataFilename,0);
00269     }
00270     return mValues;
00271 }
00272 
00273 void ColumnDataReader::ReadValueFromFile(std::string filename, int col, int row)
00274 {
00275     std::ifstream datafile(filename.c_str(),std::ios::in);
00276     //If it doesn't exist - throw exception
00277     if (!datafile.is_open())
00278     {
00279         EXCEPTION("Couldn't open data file");
00280     }
00281     std::string variable_values;
00282     for (int i=0; i < row+1; i++)
00283     {
00284         std::getline(datafile, variable_values);
00285     }
00286 
00287     std::getline(datafile, variable_values);
00288     this->PushColumnEntryFromLine(variable_values, col);
00289 
00290     datafile.close();
00291 }
00292 
00293 void ColumnDataReader::ReadColumnFromFile(std::string filename, int col)
00294 {
00295     //Empty the values vector
00296     mValues.clear();
00297     //read in from the ancillary file
00298     std::ifstream datafile(filename.c_str(),std::ios::in);
00299     std::string value;
00300     //we should have already checked that this file can be opened.
00301     assert(datafile.is_open());
00302     // the current variable becomes true just after reading the last line
00303     bool end_of_file_reached=false;
00304 
00305     //skip header line
00306     end_of_file_reached = std::getline(datafile, value).eof();
00307 
00308     while (!end_of_file_reached)
00309     {
00310         end_of_file_reached = std::getline(datafile, value).eof();
00311         this->PushColumnEntryFromLine(value,col);
00312     }
00313     datafile.close();
00314 }
00315 
00316 void ColumnDataReader::PushColumnEntryFromLine(std::string line, int col)
00317 {
00318     int startpos = col * (FIELD_WIDTH + SPACING) + SPACING - 1;
00319     std::string value = line.substr(startpos,FIELD_WIDTH + 1);
00320     std::stringstream variable_stream(value);
00321     double d_value;
00322     variable_stream >> d_value;
00323     if (variable_stream.fail())
00324     {
00325         d_value=FLT_MAX;
00326     }
00327 
00328 
00329     mValues.push_back(d_value);
00330 }
00331 
00332 bool ColumnDataReader::HasValues(const std::string& variableName)
00333 {
00334     std::map<std::string, int>::iterator col = mVariablesToColumns.find(variableName);
00335     
00336     return !(col == mVariablesToColumns.end());
00337 }

Generated on Wed Mar 18 12:51:52 2009 for Chaste by  doxygen 1.5.5