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