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
00034 #include "ColumnDataWriter.hpp"
00035 #include "ColumnDataConstants.hpp"
00036 #include "Exception.hpp"
00037 #include "Version.hpp"
00038
00039 #include <ctype.h>
00040 #include <sstream>
00041 #include <iomanip>
00042 #include <fstream>
00043
00044
00045
00046 ColumnDataWriter::ColumnDataWriter(const std::string& rDirectory,
00047 const std::string& rBaseName,
00048 bool cleanDirectory,
00049 unsigned precision)
00050 : mOutputFileHandler(rDirectory, cleanDirectory),
00051 mDirectory(rDirectory),
00052 mBaseName(rBaseName),
00053 mIsInDefineMode(true),
00054 mIsFixedDimensionSet(false),
00055 mIsUnlimitedDimensionSet(false),
00056 mUnlimitedDimensionPosition(0),
00057 mFixedDimensionSize(-1),
00058 mpCurrentOutputFile(NULL),
00059 mpCurrentAncillaryFile(NULL),
00060 mpUnlimitedDimensionVariable(NULL),
00061 mpFixedDimensionVariable(NULL),
00062 mFieldWidth(precision+7),
00063 mPrecision(precision),
00064 mHasPutVariable(false),
00065 mNeedAdvanceAlongUnlimitedDimension(false)
00066 {
00067 if (mPrecision<2 || mPrecision>20)
00068 {
00069 EXCEPTION("Precision must be between 2 and 20 (inclusive)");
00070 }
00071 }
00072
00073 ColumnDataWriter::~ColumnDataWriter()
00074 {
00075
00076 Close();
00077
00078
00079 if (mpUnlimitedDimensionVariable != NULL)
00080 {
00081 delete mpUnlimitedDimensionVariable;
00082 }
00083 if (mpFixedDimensionVariable != NULL)
00084 {
00085 delete mpFixedDimensionVariable;
00086 }
00087 }
00088
00089 std::string ColumnDataWriter::GetOutputDirectory()
00090 {
00091 return mOutputFileHandler.GetOutputDirectoryFullPath();
00092 }
00093
00094 void ColumnDataWriter::Close()
00095 {
00096 if (mpCurrentOutputFile.get() != NULL)
00097 {
00098 mpCurrentOutputFile->close();
00099 mpCurrentOutputFile = out_stream(NULL);
00100 }
00101
00102 if (mpCurrentAncillaryFile.get() != NULL)
00103 {
00104 mpCurrentAncillaryFile->close();
00105 mpCurrentAncillaryFile = out_stream(NULL);
00106 }
00107 }
00108
00109 void ColumnDataWriter::CheckVariableName(const std::string& rName)
00110 {
00111 if (rName.length() == 0)
00112 {
00113 EXCEPTION("Variable name not allowed: may not be blank.");
00114 }
00115 CheckUnitsName(rName);
00116 }
00117
00118 void ColumnDataWriter::CheckUnitsName(const std::string& rName)
00119 {
00120 for (unsigned i=0; i<rName.length(); i++)
00121 {
00122 if (!isalnum(rName[i]) && !(rName[i]=='_'))
00123 {
00124 std::string error = "Variable name/units '" + rName + "' not allowed: may only contain alphanumeric characters or '_'.";
00125 EXCEPTION(error);
00126 }
00127 }
00128 }
00129
00130 int ColumnDataWriter::DefineUnlimitedDimension(const std::string& rDimensionName,
00131 const std::string& rDimensionUnits)
00132 {
00133 if (mIsUnlimitedDimensionSet)
00134 {
00135 EXCEPTION("Unlimited dimension already set. Cannot be defined twice");
00136 }
00137
00138 if (!mIsInDefineMode)
00139 {
00140 EXCEPTION("Cannot define variables when not in Define mode");
00141 }
00142
00143 CheckVariableName(rDimensionName);
00144 CheckUnitsName(rDimensionUnits);
00145
00146 mUnlimitedDimensionName = rDimensionName;
00147 mUnlimitedDimensionUnits = rDimensionUnits;
00148
00149 mpUnlimitedDimensionVariable = new DataWriterVariable;
00150 mpUnlimitedDimensionVariable->mVariableName = rDimensionName;
00151 mpUnlimitedDimensionVariable->mVariableUnits = rDimensionUnits;
00152
00153 mIsUnlimitedDimensionSet = true;
00154
00155 return UNLIMITED_DIMENSION_VAR_ID;
00156 }
00157
00158 int ColumnDataWriter::DefineFixedDimension(const std::string& rDimensionName,
00159 const std::string& rDimensionUnits,
00160 long dimensionSize)
00161 {
00162 if (!mIsInDefineMode)
00163 {
00164 EXCEPTION("Cannot define variables when not in Define mode");
00165 }
00166 if (dimensionSize < 1)
00167 {
00168 EXCEPTION("Fixed dimension must be at least 1 long");
00169 }
00170
00171 CheckVariableName(rDimensionName);
00172 CheckUnitsName(rDimensionUnits);
00173
00174 mFixedDimensionName = rDimensionName;
00175 mFixedDimensionUnits = rDimensionUnits;
00176 mFixedDimensionSize = dimensionSize;
00177
00178 mIsFixedDimensionSet = true;
00179
00180 mpFixedDimensionVariable = new DataWriterVariable;
00181 mpFixedDimensionVariable->mVariableName = rDimensionName;
00182 mpFixedDimensionVariable->mVariableUnits = rDimensionUnits;
00183 return FIXED_DIMENSION_VAR_ID;
00184 }
00185
00186 int ColumnDataWriter::DefineVariable(const std::string& rVariableName,
00187 const std::string& rVariableUnits)
00188 {
00189 if (!mIsInDefineMode)
00190 {
00191 EXCEPTION("Cannot define variables when not in Define mode");
00192 }
00193
00194 CheckVariableName(rVariableName);
00195 CheckUnitsName(rVariableUnits);
00196
00197 int variable_id;
00198
00199 if (rVariableName == mUnlimitedDimensionName)
00200 {
00201 EXCEPTION("Variable name: " + rVariableName + " already in use as unlimited dimension");
00202 }
00203 else if (rVariableName == mFixedDimensionName)
00204 {
00205 EXCEPTION("Variable name: " + rVariableName + " already in use as fixed dimension");
00206 }
00207 else
00208 {
00209
00210 DataWriterVariable new_variable;
00211 new_variable.mVariableName = rVariableName;
00212 new_variable.mVariableUnits = rVariableUnits;
00213 mVariables.push_back(new_variable);
00214
00215
00216
00217 variable_id = mVariables.size()-1;
00218 }
00219
00220 return variable_id;
00221 }
00222
00223 void ColumnDataWriter::EndDefineMode()
00224 {
00225
00226 if (mIsFixedDimensionSet == false && mIsUnlimitedDimensionSet == false)
00227 {
00228 EXCEPTION("Cannot end define mode. No dimensions have been defined.");
00229 }
00230
00231 if (mVariables.size() < 1)
00232 {
00233 EXCEPTION("Cannot end define mode. No variables have been defined.");
00234 }
00235
00236 int unlimited_dimension_variable = (mpUnlimitedDimensionVariable != NULL);
00237 int fixed_dimension_variable = (mpFixedDimensionVariable != NULL);
00238 if (mIsUnlimitedDimensionSet)
00239 {
00240 if (mIsFixedDimensionSet)
00241 {
00242 mRowWidth = (mVariables.size() + fixed_dimension_variable) * (mFieldWidth + SPACING);
00243 mAncillaryRowWidth = mFieldWidth + SPACING;
00244
00245
00246 std::stringstream suffix;
00247 suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << mUnlimitedDimensionPosition;
00248
00249 if (mpUnlimitedDimensionVariable != NULL)
00250 {
00251 std::string ancillary_filename = mBaseName + "_unlimited.dat";
00252 mpCurrentAncillaryFile = mOutputFileHandler.OpenOutputFile(ancillary_filename, std::ios::out);
00253 (*mpCurrentAncillaryFile) << std::setiosflags(std::ios::scientific);
00254 (*mpCurrentAncillaryFile) << std::setprecision(mPrecision);
00255 if (mpUnlimitedDimensionVariable != NULL)
00256 {
00257 (*mpCurrentAncillaryFile) << mpUnlimitedDimensionVariable->mVariableName
00258 << "(" << mpUnlimitedDimensionVariable->mVariableUnits << ") ";
00259 }
00260 }
00261 mAncillaryRowStartPosition = mpCurrentAncillaryFile->tellp();
00262 std::string filename = mBaseName + "_" + suffix.str() + ".dat";
00263 this->CreateFixedDimensionFile(filename);
00264 }
00265 else
00266 {
00267 mRowWidth = (mVariables.size() + unlimited_dimension_variable) * (mFieldWidth + SPACING);
00268
00269
00270 std::string filename = mBaseName + ".dat";
00271 mpCurrentOutputFile = mOutputFileHandler.OpenOutputFile(filename, std::ios::out);
00272 (*mpCurrentOutputFile) << std::setiosflags(std::ios::scientific);
00273 (*mpCurrentOutputFile) << std::setprecision(mPrecision);
00274 if (mpUnlimitedDimensionVariable != NULL)
00275 {
00276 (*mpCurrentOutputFile) << mpUnlimitedDimensionVariable->mVariableName
00277 << "(" << mpUnlimitedDimensionVariable->mVariableUnits << ") ";
00278 }
00279
00280
00281
00282 for (unsigned i=0; i<mVariables.size(); i++)
00283 {
00284 (*mpCurrentOutputFile) << mVariables[i].mVariableName << "(" << mVariables[i].mVariableUnits << ")";
00285 if (i < mVariables.size()-1)
00286 {
00287 (*mpCurrentOutputFile) << " ";
00288 }
00289 }
00290 (*mpCurrentOutputFile) << std::endl;
00291 mRowStartPosition = mpCurrentOutputFile->tellp();
00292
00293
00294 std::string blank_line(mRowWidth, ' ');
00295 (*mpCurrentOutputFile) << blank_line;
00296 }
00297 }
00298 else
00299 {
00300
00301 mRowWidth = (mVariables.size() + fixed_dimension_variable) * (mFieldWidth + SPACING);
00302 std::string filename = mBaseName + ".dat";
00303 this->CreateFixedDimensionFile(filename);
00304 }
00305
00306
00307 std::string infoname = mBaseName + ".info";
00308 this->CreateInfoFile(infoname);
00309
00310 mIsInDefineMode = false;
00311 }
00312
00313 void ColumnDataWriter::CreateFixedDimensionFile(const std::string& rFileName)
00314 {
00315
00316 mpCurrentOutputFile = mOutputFileHandler.OpenOutputFile(rFileName, std::ios::out);
00317 (*mpCurrentOutputFile) << std::setiosflags(std::ios::scientific);
00318 (*mpCurrentOutputFile) << std::setprecision(mPrecision);
00319 if (mpFixedDimensionVariable != NULL)
00320 {
00321 (*mpCurrentOutputFile) << mpFixedDimensionVariable->mVariableName
00322 << "(" << mpFixedDimensionVariable->mVariableUnits << ") ";
00323 }
00324
00325 for (unsigned i = 0; i < mVariables.size(); i++)
00326 {
00327 (*mpCurrentOutputFile) << mVariables[i].mVariableName << "(" << mVariables[i].mVariableUnits << ")";
00328 if (i < mVariables.size()-1)
00329 {
00330 (*mpCurrentOutputFile) << " ";
00331 }
00332 }
00333 (*mpCurrentOutputFile) << std::endl;
00334 mRowStartPosition = mpCurrentOutputFile->tellp();
00335 std::string blank_line(mRowWidth, ' ');
00336 for (int i = 0; i < mFixedDimensionSize; i++)
00337 {
00338 (*mpCurrentOutputFile) << blank_line << std::endl;
00339 }
00340 }
00341
00342 void ColumnDataWriter::CreateInfoFile(const std::string& rFileName)
00343 {
00344
00345 out_stream p_info_file = mOutputFileHandler.OpenOutputFile(rFileName, std::ios::out);
00346 (*p_info_file) << "FIXED " << mFixedDimensionSize << std::endl;
00347 (*p_info_file) << "UNLIMITED " << mIsUnlimitedDimensionSet << std::endl;
00348 (*p_info_file) << "VARIABLES " << mVariables.size() << std::endl;
00349 *p_info_file << ChasteBuildInfo::GetProvenanceString();
00350 p_info_file->close();
00351 }
00352
00353 void ColumnDataWriter::DoAdvanceAlongUnlimitedDimension()
00354 {
00355 mHasPutVariable = false;
00356 mNeedAdvanceAlongUnlimitedDimension = false;
00357
00358 if (mIsUnlimitedDimensionSet)
00359 {
00360 if (mIsFixedDimensionSet)
00361 {
00362
00363 mpCurrentOutputFile->close();
00364 std::stringstream suffix;
00365 suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << mUnlimitedDimensionPosition + 1;
00366
00367 std::string filename = mBaseName + "_" + suffix.str() + ".dat";
00368 this->CreateFixedDimensionFile(filename);
00369 }
00370 else
00371 {
00372
00373 mpCurrentOutputFile->seekp(mRowStartPosition+mRowWidth);
00374 (*mpCurrentOutputFile) << std::endl;
00375 mRowStartPosition = mpCurrentOutputFile->tellp();
00376 std::string blank_line(mRowWidth,' ');
00377 (*mpCurrentOutputFile) << blank_line;
00378 }
00379 }
00380 else
00381 {
00382 EXCEPTION("Cannot advance along unlimited dimension if it is not defined");
00383 }
00384 mUnlimitedDimensionPosition++;
00385 }
00386
00387 void ColumnDataWriter::AdvanceAlongUnlimitedDimension()
00388 {
00389 if (mHasPutVariable)
00390 {
00391 mNeedAdvanceAlongUnlimitedDimension = true;
00392 }
00393 }
00394
00395 void ColumnDataWriter::PutVariable(int variableID, double variableValue, long dimensionPosition)
00396 {
00397 if (mNeedAdvanceAlongUnlimitedDimension)
00398 {
00399 DoAdvanceAlongUnlimitedDimension();
00400 }
00401
00402
00403 if (mIsInDefineMode)
00404 {
00405 EXCEPTION("Cannot put variables when in Define mode");
00406 }
00407
00408 if (variableID > (int)mVariables.size() ||
00409 (variableID != UNLIMITED_DIMENSION_VAR_ID &&
00410 variableID != FIXED_DIMENSION_VAR_ID &&
00411 variableID < 0))
00412 {
00413 EXCEPTION("variableID unknown");
00414 }
00415
00416 if (mIsFixedDimensionSet)
00417 {
00418 if (dimensionPosition == -1 && variableID != UNLIMITED_DIMENSION_VAR_ID)
00419 {
00420 EXCEPTION("Dimension position not supplied");
00421 }
00422 if (dimensionPosition < -1 || dimensionPosition >= mFixedDimensionSize)
00423 {
00424 EXCEPTION("Dimension position out of range");
00425 }
00426 if (dimensionPosition != -1 && variableID == UNLIMITED_DIMENSION_VAR_ID)
00427 {
00428 EXCEPTION("Dimension position supplied, but not required");
00429 }
00430 }
00431
00432 if (mIsUnlimitedDimensionSet)
00433 {
00434 if (mIsFixedDimensionSet)
00435 {
00436
00437 if (variableID == UNLIMITED_DIMENSION_VAR_ID)
00438 {
00439 (*mpCurrentAncillaryFile) << std::endl << " ";
00440 mpCurrentAncillaryFile->width(mFieldWidth);
00441 (*mpCurrentAncillaryFile) << variableValue;
00442 }
00443 else
00444 {
00445 int position;
00446 if (variableID == FIXED_DIMENSION_VAR_ID)
00447 {
00448 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition + SPACING - 1;
00449 }
00450 else
00451 {
00452
00453 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition +
00454 ((variableID + (mpFixedDimensionVariable != NULL)) * (mFieldWidth + SPACING)) + SPACING - 1;
00455 }
00456
00457 mpCurrentOutputFile->seekp(position);
00458 mpCurrentOutputFile->width(mFieldWidth);
00459 (*mpCurrentOutputFile) << variableValue;
00460 }
00461 }
00462 else
00463 {
00464
00465 int position;
00466 if (variableID == UNLIMITED_DIMENSION_VAR_ID)
00467 {
00468 position = mRowStartPosition + SPACING - 1;
00469 }
00470 else
00471 {
00472 position = (variableID + (mpUnlimitedDimensionVariable != NULL)) * (mFieldWidth + SPACING) +
00473 mRowStartPosition + SPACING - 1;
00474 }
00475
00476 mpCurrentOutputFile->seekp(position);
00477 mpCurrentOutputFile->width(mFieldWidth);
00478 (*mpCurrentOutputFile) << variableValue;
00479 }
00480 }
00481 else
00482 {
00483
00484 int position;
00485 if (variableID == FIXED_DIMENSION_VAR_ID)
00486 {
00487 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition + SPACING - 1;
00488 }
00489 else
00490 {
00491 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition +
00492 ((variableID + (mpFixedDimensionVariable != NULL)) * (mFieldWidth + SPACING)) + SPACING - 1;
00493 }
00494 mpCurrentOutputFile->seekp(position);
00495 mpCurrentOutputFile->width(mFieldWidth);
00496 (*mpCurrentOutputFile) << variableValue;
00497 }
00498
00499 mHasPutVariable = true;
00500 }