From c8c2df5eb83f2671400f87df6298acd73e2729a0 Mon Sep 17 00:00:00 2001 From: Andreas Suter Date: Tue, 15 Mar 2022 15:47:37 +0100 Subject: [PATCH] add reading routine for the dat-files as generate from msr2data. Use case: special 'non muSR fit' type. --- src/classes/PMusr.cpp | 26 ++++++ src/classes/PRunDataHandler.cpp | 140 +++++++++++++++++++++++++++++++- src/include/PMusr.h | 3 +- 3 files changed, 166 insertions(+), 3 deletions(-) diff --git a/src/classes/PMusr.cpp b/src/classes/PMusr.cpp index 5d5633ea..110d4a3c 100644 --- a/src/classes/PMusr.cpp +++ b/src/classes/PMusr.cpp @@ -150,6 +150,32 @@ PNonMusrRawRunData::~PNonMusrRawRunData() fErrData.clear(); } +//-------------------------------------------------------------------------- +// SetSize (public) +//-------------------------------------------------------------------------- +/** + *

Allows to set the number of data sets before filling it. This is + * needed when reading dat-files generated from msr2data. + * + * @param size number of data sets + */ +void PNonMusrRawRunData::SetSize(const UInt_t size) +{ + // first clean up + for (UInt_t i=0; iReads column like data sets as generated by msr2data with the option + * 'data'. This can be used for the 'non muSR fit' type. + * + * return: + * - true at successful reading, + * - otherwise false. + */ Bool_t PRunDataHandler::ReadDatFile() { Bool_t success = true; - std::cerr << "debug> in PRunDataHandler::ReadDatFile(). Not yet implemented..." << std::endl; + // open file + std::ifstream f; + + // open db-file + f.open(fRunPathName.Data(), std::ifstream::in); + if (!f.is_open()) { + std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** Couldn't open data file (" << fRunPathName.Data() << ") for reading, sorry ..."; + std::cerr << std::endl; + return false; + } + + PRawRunData runData; + runData.fDataNonMusr.SetFromAscii(false); + + Int_t lineNo = 0; + Char_t instr[4096]; + TString line; + Bool_t headerInfo=true; + + // variables needed to tokenize strings + TString tstr; + TObjString *ostr; + TObjArray *tokens = nullptr; + + UInt_t noOfDataSets = 0, noOfEntries = 0; + PBoolVector isData; + Double_t dval; + + while (!f.eof()) { + // get next line from file + f.getline(instr, sizeof(instr)); + line = TString(instr); + lineNo++; + + // check if comment line + if (line.BeginsWith("#") || line.BeginsWith("%")) + continue; + + // ignore empty lines + if (line.IsWhitespace()) + continue; + + tokens = line.Tokenize(" \t"); + if (tokens == nullptr) { // error + std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** couldn't tokenize the line, in lineNo: " << lineNo; + std::cerr << std::endl << ">> line: '" << line << "'."; + std::cerr << std::endl; + return false; + } + + // filter header information + if (headerInfo) { + headerInfo = false; + + // filter out all data tags: this labels are used in the msr-file to select the proper data set + // for the dat-files, label and dataTag are the same + noOfEntries = tokens->GetEntries(); + for (Int_t i=0; i(tokens->At(i)); + tstr = ostr->GetString(); + if (!tstr.EndsWith("Err", TString::kExact)) { + noOfDataSets++; + isData.push_back(true); + runData.fDataNonMusr.AppendDataTag(tstr); + runData.fDataNonMusr.AppendLabel(tstr); + } else { + isData.push_back(false); + } + } + // set the size for the data + runData.fDataNonMusr.SetSize(noOfDataSets); + } else { // deal with data + if (noOfEntries == 0) { + std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** header information is missing."; + std::cerr << std::endl; + return false; + } + if (tokens->GetEntries() != noOfEntries) { // error + std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** data set with wrong number of entries: " << tokens->GetEntries() << ", should be " << noOfEntries << "."; + std::cerr << std::endl << ">> in line: " << lineNo; + std::cerr << std::endl << ">> line: '" << line << "'."; + std::cerr << std::endl; + return false; + } + // fill data and dataErr sets + UInt_t idx = 0; + for (UInt_t i=0; i(tokens->At(i)); + tstr = ostr->GetString(); + if (!tstr.IsFloat()) { // make sure it is a number + std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** data set entry is not a number: " << tstr.Data(); + std::cerr << std::endl << ">> in line: " << lineNo; + std::cerr << std::endl; + return false; + } + dval = tstr.Atof(); + if (isData[i]) { + runData.fDataNonMusr.AppendSubData(idx, dval); + idx++; + } else { // error value + if (isData[i-1] == 1) { // Err or PosErr hence keep it + runData.fDataNonMusr.AppendSubErrData(idx-1, dval); + } + } + } + } + // cleanup + if (tokens) { + delete tokens; + tokens = nullptr; + } + } + + f.close(); + + // got through all the data sets and if there is NO error vector set it to '0.0' + for (UInt_t i=0; iat(i).size() == 0) { + for (UInt_t j=0; jat(i).size(); j++) { + runData.fDataNonMusr.AppendSubErrData(i, 0.0); + } + } + } + + // keep run name + runData.SetRunName(fRunName); + + fData.push_back(runData); return success; } diff --git a/src/include/PMusr.h b/src/include/PMusr.h index e41816c5..01614d30 100644 --- a/src/include/PMusr.h +++ b/src/include/PMusr.h @@ -294,6 +294,7 @@ class PNonMusrRawRunData { virtual const std::vector* GetErrData() { return &fErrData; } virtual void SetFromAscii(const Bool_t bval) { fFromAscii = bval; } + virtual void SetSize(const UInt_t size); virtual void AppendLabel(const TString str) { fLabels.push_back(str); } virtual void SetLabel(const UInt_t idx, const TString str); virtual void AppendDataTag(const TString str) { fDataTags.push_back(str); } @@ -303,7 +304,7 @@ class PNonMusrRawRunData { virtual void AppendSubErrData(const UInt_t idx, const Double_t dval); private: - Bool_t fFromAscii; ///< if true: data file was an ascii input file, otherwise it is a db input file + Bool_t fFromAscii; ///< if true: data file was an ascii input file, otherwise it is a db/dat input file PStringVector fLabels; ///< vector of all labels (used for x-, y-axis title in view) PStringVector fDataTags; ///< vector of all data tags std::vector fData; ///< vector of all data