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 for (unsigned i=0; i<mVariables.size(); i++)
00284 {
00285 (*mpCurrentOutputFile) << mVariables[i].mVariableName << "(" << mVariables[i].mVariableUnits << ")";
00286 if (i < mVariables.size()-1)
00287 {
00288 (*mpCurrentOutputFile) << " ";
00289 }
00290 }
00291 (*mpCurrentOutputFile) << std::endl;
00292 mRowStartPosition = mpCurrentOutputFile->tellp();
00293
00294
00295 std::string blank_line(mRowWidth, ' ');
00296 (*mpCurrentOutputFile) << blank_line;
00297 }
00298 }
00299 else
00300 {
00301
00302 mRowWidth = (mVariables.size() + fixed_dimension_variable) * (mFieldWidth + SPACING);
00303 std::string filename = mBaseName + ".dat";
00304 this->CreateFixedDimensionFile(filename);
00305 }
00306
00307
00308 std::string infoname = mBaseName + ".info";
00309 this->CreateInfoFile(infoname);
00310
00311 mIsInDefineMode = false;
00312 }
00313
00314 void ColumnDataWriter::CreateFixedDimensionFile(const std::string& rFileName)
00315 {
00316
00317 mpCurrentOutputFile = mOutputFileHandler.OpenOutputFile(rFileName, std::ios::out);
00318 (*mpCurrentOutputFile) << std::setiosflags(std::ios::scientific);
00319 (*mpCurrentOutputFile) << std::setprecision(mPrecision);
00320 if (mpFixedDimensionVariable != NULL)
00321 {
00322 (*mpCurrentOutputFile) << mpFixedDimensionVariable->mVariableName
00323 << "(" << mpFixedDimensionVariable->mVariableUnits << ") ";
00324 }
00325
00326 for (unsigned i = 0; i < mVariables.size(); i++)
00327 {
00328 (*mpCurrentOutputFile) << mVariables[i].mVariableName << "(" << mVariables[i].mVariableUnits << ")";
00329 if (i < mVariables.size()-1)
00330 {
00331 (*mpCurrentOutputFile) << " ";
00332 }
00333 }
00334 (*mpCurrentOutputFile) << std::endl;
00335 mRowStartPosition = mpCurrentOutputFile->tellp();
00336 std::string blank_line(mRowWidth, ' ');
00337 for (int i = 0; i < mFixedDimensionSize; i++)
00338 {
00339 (*mpCurrentOutputFile) << blank_line << std::endl;
00340 }
00341 }
00342
00343 void ColumnDataWriter::CreateInfoFile(const std::string& rFileName)
00344 {
00345
00346 out_stream p_info_file = mOutputFileHandler.OpenOutputFile(rFileName, std::ios::out);
00347 (*p_info_file) << "FIXED " << mFixedDimensionSize << std::endl;
00348 (*p_info_file) << "UNLIMITED " << mIsUnlimitedDimensionSet << std::endl;
00349 (*p_info_file) << "VARIABLES " << mVariables.size() << std::endl;
00350 if(mCommentForInfoFile!="")
00351 {
00352 *p_info_file << mCommentForInfoFile << std::endl;
00353 }
00354 *p_info_file << ChasteBuildInfo::GetProvenanceString();
00355 p_info_file->close();
00356 }
00357
00358 void ColumnDataWriter::DoAdvanceAlongUnlimitedDimension()
00359 {
00360 mHasPutVariable = false;
00361 mNeedAdvanceAlongUnlimitedDimension = false;
00362
00363 if (mIsUnlimitedDimensionSet)
00364 {
00365 if (mIsFixedDimensionSet)
00366 {
00367
00368 mpCurrentOutputFile->close();
00369 std::stringstream suffix;
00370 suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << mUnlimitedDimensionPosition + 1;
00371
00372 std::string filename = mBaseName + "_" + suffix.str() + ".dat";
00373 this->CreateFixedDimensionFile(filename);
00374 }
00375 else
00376 {
00377
00378 mpCurrentOutputFile->seekp(mRowStartPosition+mRowWidth);
00379 (*mpCurrentOutputFile) << std::endl;
00380 mRowStartPosition = mpCurrentOutputFile->tellp();
00381 std::string blank_line(mRowWidth,' ');
00382 (*mpCurrentOutputFile) << blank_line;
00383 }
00384 }
00385 else
00386 {
00387 EXCEPTION("Cannot advance along unlimited dimension if it is not defined");
00388 }
00389 mUnlimitedDimensionPosition++;
00390 }
00391
00392 void ColumnDataWriter::AdvanceAlongUnlimitedDimension()
00393 {
00394 if (mHasPutVariable)
00395 {
00396 mNeedAdvanceAlongUnlimitedDimension = true;
00397 }
00398 }
00399
00400 void ColumnDataWriter::PutVariable(int variableID, double variableValue, long dimensionPosition)
00401 {
00402 if (mNeedAdvanceAlongUnlimitedDimension)
00403 {
00404 DoAdvanceAlongUnlimitedDimension();
00405 }
00406
00407
00408 if (mIsInDefineMode)
00409 {
00410 EXCEPTION("Cannot put variables when in Define mode");
00411 }
00412
00413 if (variableID > (int)mVariables.size() ||
00414 (variableID != UNLIMITED_DIMENSION_VAR_ID &&
00415 variableID != FIXED_DIMENSION_VAR_ID &&
00416 variableID < 0))
00417 {
00418 EXCEPTION("variableID unknown");
00419 }
00420
00421 if (mIsFixedDimensionSet)
00422 {
00423 if (dimensionPosition == -1 && variableID != UNLIMITED_DIMENSION_VAR_ID)
00424 {
00425 EXCEPTION("Dimension position not supplied");
00426 }
00427 if (dimensionPosition < -1 || dimensionPosition >= mFixedDimensionSize)
00428 {
00429 EXCEPTION("Dimension position out of range");
00430 }
00431 if (dimensionPosition != -1 && variableID == UNLIMITED_DIMENSION_VAR_ID)
00432 {
00433 EXCEPTION("Dimension position supplied, but not required");
00434 }
00435 }
00436
00437 if (mIsUnlimitedDimensionSet)
00438 {
00439 if (mIsFixedDimensionSet)
00440 {
00441
00442 if (variableID == UNLIMITED_DIMENSION_VAR_ID)
00443 {
00444 (*mpCurrentAncillaryFile) << std::endl << " ";
00445 mpCurrentAncillaryFile->width(mFieldWidth);
00446 (*mpCurrentAncillaryFile) << variableValue;
00447 }
00448 else
00449 {
00450 int position;
00451 if (variableID == FIXED_DIMENSION_VAR_ID)
00452 {
00453 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition + SPACING - 1;
00454 }
00455 else
00456 {
00457
00458 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition +
00459 ((variableID + (mpFixedDimensionVariable != NULL)) * (mFieldWidth + SPACING)) + SPACING - 1;
00460 }
00461
00462 mpCurrentOutputFile->seekp(position);
00463 mpCurrentOutputFile->width(mFieldWidth);
00464 (*mpCurrentOutputFile) << variableValue;
00465 }
00466 }
00467 else
00468 {
00469
00470 int position;
00471 if (variableID == UNLIMITED_DIMENSION_VAR_ID)
00472 {
00473 position = mRowStartPosition + SPACING - 1;
00474 }
00475 else
00476 {
00477 position = (variableID + (mpUnlimitedDimensionVariable != NULL)) * (mFieldWidth + SPACING) +
00478 mRowStartPosition + SPACING - 1;
00479 }
00480
00481 mpCurrentOutputFile->seekp(position);
00482 mpCurrentOutputFile->width(mFieldWidth);
00483 (*mpCurrentOutputFile) << variableValue;
00484 }
00485 }
00486 else
00487 {
00488
00489 int position;
00490 if (variableID == FIXED_DIMENSION_VAR_ID)
00491 {
00492 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition + SPACING - 1;
00493 }
00494 else
00495 {
00496 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition +
00497 ((variableID + (mpFixedDimensionVariable != NULL)) * (mFieldWidth + SPACING)) + SPACING - 1;
00498 }
00499 mpCurrentOutputFile->seekp(position);
00500 mpCurrentOutputFile->width(mFieldWidth);
00501 (*mpCurrentOutputFile) << variableValue;
00502 }
00503
00504 mHasPutVariable = true;
00505 }