/*************************************************************************** PRunDataHandler.cpp Author: Andreas Suter e-mail: andreas.suter@psi.ch $Id$ ***************************************************************************/ /*************************************************************************** * Copyright (C) 2007 by Andreas Suter * * andreas.suter@psi.c * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include using namespace std; #include #include #include #include #include #include #include #include #include "TLemRunHeader.h" #include "MuSR_td_PSI_bin.h" #include "PRunDataHandler.h" //-------------------------------------------------------------------------- // Constructor //-------------------------------------------------------------------------- /** *

* */ PRunDataHandler::PRunDataHandler(PMsrHandler *msrInfo) : fMsrInfo(msrInfo) { // cout << endl << "in PRunDataHandler::PRunDataHandler()"; // read files if (!ReadFile()) // couldn't read file fAllDataAvailable = false; else fAllDataAvailable = true; } //-------------------------------------------------------------------------- // Constructor //-------------------------------------------------------------------------- /** *

* */ PRunDataHandler::PRunDataHandler(PMsrHandler *msrInfo, const PStringVector dataPath) : fMsrInfo(msrInfo), fDataPath(dataPath) { // cout << endl << "in PRunDataHandler::PRunDataHandler()"; // read files if (!ReadFile()) // couldn't read file fAllDataAvailable = false; else fAllDataAvailable = true; /*for (unsigned int i=0; i * */ PRunDataHandler::~PRunDataHandler() { for (unsigned int i=0; i * * \param runName */ PRawRunData* PRunDataHandler::GetRunData(TString runName) { unsigned int i; for (i=0; i * */ bool PRunDataHandler::ReadFile() { bool success = true; // loop over the full RUN list to see what needs to be read PMsrRunList *runList = 0; runList = fMsrInfo->GetMsrRunList(); if (runList == 0) { cout << endl << "PRunDataHandler::ReadFile(): Couldn't obtain run list from PMsrHandler: something VERY fishy"; return false; } PMsrRunList::iterator run_it; for (run_it = runList->begin(); run_it != runList->end(); ++run_it) { //cout << endl << "run : " << run_it->fRunName.Data(); fRunName = run_it->fRunName; // check is file is already read if (FileAlreadyRead(*run_it)) continue; // check if file actually exists if (!FileExistsCheck(*run_it)) return false; // everything looks fine, hence try to read the data file if (!run_it->fFileFormat.CompareTo("root-npp")) // not post pile up corrected histos success = ReadRootFile(); else if (!run_it->fFileFormat.CompareTo("root-ppc")) // post pile up corrected histos success = ReadRootFile(); else if (!run_it->fFileFormat.CompareTo("nexus")) success = ReadNexusFile(); else if (!run_it->fFileFormat.CompareTo("psi-bin")) success = ReadPsiBinFile(); else if (!run_it->fFileFormat.CompareTo("mud")) success = ReadMudFile(); else if (!run_it->fFileFormat.CompareTo("nemu")) success = ReadNemuFile(); else if (!run_it->fFileFormat.CompareTo("ascii")) success = ReadAsciiFile(); else success = false; } return success; } //-------------------------------------------------------------------------- // FileAlreadyRead //-------------------------------------------------------------------------- /** *

* */ bool PRunDataHandler::FileAlreadyRead(PMsrRunStructure &runInfo) { for (unsigned int i=0; i * */ bool PRunDataHandler::FileExistsCheck(PMsrRunStructure &runInfo) { bool success = true; // local init TROOT root("PRunBase", "PRunBase", 0); TString pathName = "???"; TString str; TString ext; runInfo.fBeamline.ToLower(); runInfo.fInstitute.ToLower(); runInfo.fFileFormat.ToLower(); // file extensions for the various formats if (!runInfo.fFileFormat.CompareTo("root-npp")) // not post pile up corrected histos ext = TString("root"); else if (!runInfo.fFileFormat.CompareTo("root-ppc")) // post pile up corrected histos ext = TString("root"); else if (!runInfo.fFileFormat.CompareTo("nexus")) ext = TString("nexus"); else if (!runInfo.fFileFormat.CompareTo("psi-bin")) ext = TString("bin"); else if (!runInfo.fFileFormat.CompareTo("mud")) ext = TString("mud"); else if (!runInfo.fFileFormat.CompareTo("nemu")) ext = TString("nemu"); else if (!runInfo.fFileFormat.CompareTo("ascii")) ext = TString("dat"); else success = false; // unkown file format found if (!success) { str = runInfo.fFileFormat; str.ToUpper(); cout << endl << "File Format '" << str.Data() << "' unsupported."; cout << endl << " support file formats are:"; cout << endl << " ROOT-NPP -> root not post pileup corrected for lem"; cout << endl << " ROOT-PPC -> root post pileup corrected for lem"; cout << endl << " NEXUS -> nexus file format"; cout << endl << " PSI-BIN -> psi bin file format"; cout << endl << " MUD -> triumf mud file format"; cout << endl << " NEMU -> lem ascii file format"; cout << endl << " ASCII -> column like file format"; cout << endl; return success; } // check if the file is in the local directory str = runInfo.fRunName + TString(".") + ext; if (gSystem->AccessPathName(str.Data())!=true) { // found in the local dir pathName = str; } // check if the file is found in the directory given in the startup file if (pathName.CompareTo("???") == 0) { // not found in local directory search for (unsigned int i=0; iAccessPathName(str.Data())!=true) { // found pathName = str; break; } } } // check if the file is found in the directories given by WKMFULLDATAPATH const char *wkmpath = gSystem->Getenv("WKMFULLDATAPATH"); if (pathName.CompareTo("???") == 0) { // not found in local directory and xml path str = TString(wkmpath); // WKMFULLDATAPATH has the structure: path_1:path_2:...:path_n TObjArray *tokens = str.Tokenize(":"); TObjString *ostr; for (int i=0; iGetEntries(); i++) { ostr = dynamic_cast(tokens->At(i)); str = ostr->GetString() + TString("/") + runInfo.fRunName + TString(".") + ext; if (gSystem->AccessPathName(str.Data())!=true) { // found pathName = str; break; } } } // check if the file is found in the WKM generated default path if (pathName.CompareTo("???") == 0) { // not found in WKMFULLDATAPATH search str = TString(wkmpath); // WKMFULLDATAPATH has the structure: path_1:path_2:...:path_n TObjArray *tokens = str.Tokenize(":"); TObjString *ostr; for (int i=0; iGetEntries(); i++) { ostr = dynamic_cast(tokens->At(i)); str = ostr->GetString() + TString("/data/") + runInfo.fInstitute + TString("/") + runInfo.fBeamline + TString("/") + runInfo.fRunName + TString(".") + ext; if (gSystem->AccessPathName(str.Data())!=true) { // found pathName = str; break; } } } // no proper path name found if (pathName.CompareTo("???") == 0) { cout << endl << "**ERROR** Couldn't find '" << runInfo.fRunName << "' in any standard path."; cout << endl << " standard search pathes are:"; cout << endl << " 1. the local directory"; cout << endl << " 2. the data directory given in the startup XML file"; cout << endl << " 3. the directories listed in WKMFULLDATAPATH"; cout << endl << " 4. default path construct which is described in the manual"; return false; } fRunPathName = pathName; return true; } //-------------------------------------------------------------------------- // ReadRootFile //-------------------------------------------------------------------------- /** *

* */ bool PRunDataHandler::ReadRootFile() { PDoubleVector histoData; PRawRunData runData; TFile f(fRunPathName.Data()); if (f.IsZombie()) { return false; } TFolder *folder; f.GetObject("RunInfo", folder); if (!folder) { cout << endl << "Couldn't obtain RunInfo from " << fRunPathName.Data() << endl; f.Close(); return false; } // read header and check if some missing run info need to be fed TLemRunHeader *runHeader = dynamic_cast(folder->FindObjectAny("TLemRunHeader")); // check if run header is valid if (!runHeader) { cout << endl << "Couldn't obtain run header info from ROOT file " << fRunPathName.Data() << endl; f.Close(); return false; } // get temperature runData.fTemp = runHeader->GetSampleTemperature(); // get field runData.fField = runHeader->GetSampleBField(); // get implantation energy runData.fEnergy = runHeader->GetImpEnergy(); // get setup runData.fSetup = runHeader->GetLemSetup().GetString(); // get time resolution runData.fTimeResolution = runHeader->GetTimeResolution(); // get number of histogramms int noOfHistos = runHeader->GetNHist(); // get t0's Double_t *t0 = runHeader->GetTimeZero(); // check if t0's are there if (t0[0] != -1) { // ugly, but at the moment there is no other way // copy t0's so they are not lost for (int i=0; i(folder->FindObjectAny(histoName)); if (!histo) { cout << endl << "PRunDataHandler::ReadRootFile: Couldn't get histo " << histoName; return false; } // fill data for (int j=1; jGetNbinsX(); j++) histoData.push_back(histo->GetBinContent(j)); // store them in runData vector runData.fDataBin.push_back(histoData); // clear histoData for the next histo histoData.clear(); } // now read the data which ARE post pileup corrected for (int i=0; i(folder->FindObjectAny(histoName)); if (!histo) { cout << endl << "PRunDataHandler::ReadRootFile: Couldn't get histo " << histoName; return false; } // fill data for (int j=1; jGetNbinsX(); j++) histoData.push_back(histo->GetBinContent(j)); // store them in runData vector runData.fDataBin.push_back(histoData); // clear histoData for the next histo histoData.clear(); } f.Close(); // keep run name runData.fRunName = fRunName; // add run to the run list fData.push_back(runData); // clean up for (unsigned int i=0; i * */ bool PRunDataHandler::ReadNexusFile() { cout << endl << "PRunDataHandler::ReadNexusFile(): Sorry, not yet implemented ..."; return false; } //-------------------------------------------------------------------------- // ReadNemuFile //-------------------------------------------------------------------------- /** *

* */ bool PRunDataHandler::ReadNemuFile() { // cout << endl << "PRunDataHandler::ReadNemuFile(): Sorry, not yet implemented ..."; PDoubleVector histoData; PRawRunData runData; // init runData header info runData.fRunName = TString(""); runData.fRunTitle = TString(""); runData.fSetup = TString(""); runData.fField = nan("NAN"); runData.fTemp = nan("NAN"); runData.fEnergy = nan("NAN"); runData.fTimeResolution = nan("NAN"); // open file ifstream f; // open dump-file f.open(fRunPathName.Data(), ifstream::in); if (!f.is_open()) { cout << endl << "Couldn't open run data (" << fRunPathName.Data() << ") file for reading, sorry ..."; cout << endl; return false; } // read header bool headerInfo = true; char instr[512]; TString line; double dval; int ival; bool ok; int groups = 0, channels = 0; // skip leading empty lines do { f.getline(instr, sizeof(instr)); line = TString(instr); if (!line.IsWhitespace()) break; } while (!f.eof()); // real header data should start here Ssiz_t idx; do { line = TString(instr); if (line.IsWhitespace()) { // end of header reached headerInfo = false; } else { // real stuff, hence filter data if (line.Contains("Title")) { idx = line.Index(":"); line.Replace(0, idx+1, 0, 0); // remove 'Title:' StripWhitespace(line); runData.fRunTitle = line; } else if (line.Contains("Field")) { idx = line.Index(":"); line.Replace(0, idx+1, 0, 0); // remove 'Field:' StripWhitespace(line); dval = ToDouble(line, ok); if (ok) runData.fField = dval; } else if (line.Contains("Setup")) { idx = line.Index(":"); line.Replace(0, idx+1, 0, 0); // remove 'Setup:' StripWhitespace(line); runData.fSetup = line; } else if (line.Contains("Temp")) { idx = line.Index(":"); line.Replace(0, idx+1, 0, 0); // remove 'Temp:' StripWhitespace(line); dval = ToDouble(line, ok); if (ok) runData.fTemp = dval; } else if (line.Contains("Groups")) { idx = line.Index(":"); line.Replace(0, idx+1, 0, 0); // remove 'Groups:' StripWhitespace(line); ival = ToInt(line, ok); if (ok) groups = ival; } else if (line.Contains("Channels")) { idx = line.Index(":"); line.Replace(0, idx+1, 0, 0); // remove 'Channels:' StripWhitespace(line); ival = ToInt(line, ok); if (ok) channels = ival; } else if (line.Contains("Resolution")) { idx = line.Index(":"); line.Replace(0, idx+1, 0, 0); // remove 'Resolution:' StripWhitespace(line); dval = ToDouble(line, ok); if (ok) runData.fTimeResolution = dval * 1000.0; } } f.getline(instr, sizeof(instr)); } while (headerInfo && !f.eof()); if ((groups == 0) || (channels == 0) || isnan(runData.fTimeResolution)) { cout << endl << "PRunDataHandler::ReadNemuFile(): essential header informations are missing!"; f.close(); return false; } /* cout << endl << ">> run title: '" << runData.fRunTitle.Data() << "'"; cout << endl << ">> setup : '" << runData.fSetup.Data() << "'"; cout << endl << ">> field : " << runData.fField; cout << endl << ">> temp : " << runData.fTemp; cout << endl << ">> groups : " << groups; cout << endl << ">> channels : " << channels; cout << endl << ">> time resolution : " << runData.fTimeResolution; */ // read data --------------------------------------------------------- int status; unsigned int group_counter = 0; int val[10]; do { // check if empty line, i.e. new group if (IsWhitespace(instr)) { runData.fDataBin.push_back(histoData); histoData.clear(); group_counter++; } else { // extract values status = sscanf(instr, "%d %d %d %d %d %d %d %d %d %d", &val[0], &val[1], &val[2], &val[3], &val[4], &val[5], &val[6], &val[7], &val[8], &val[9]); // no values found: error if (status == 0) { cout << endl << "PRunDataHandler::ReadNemuFile(): **ERROR** while reading data ..."; // clean up for (unsigned int i=0; i 0) { // feed data for (int i=0; i 0) { runData.fDataBin.push_back(histoData); histoData.clear(); } // close file f.close(); // check if all groups are found if ((int) runData.fDataBin.size() != groups) { cout << endl << "PRunDataHandler::ReadNemuFile(): **ERROR**"; cout << endl << " expected " << groups << " histos, but found " << runData.fDataBin.size(); // clean up for (unsigned int i=0; i * */ bool PRunDataHandler::ReadPsiBinFile() { // cout << endl << "PRunDataHandler::ReadPsiBinFile(): Sorry, not yet implemented ..."; MuSR_td_PSI_bin psiBin; int status; bool success; // read psi bin file status = psiBin.read(fRunPathName.Data()); switch (status) { case 0: // everything perfect success = true; break; case 1: // couldn't open file, or failed while reading the header cout << endl << "**ERROR** couldn't open psibin file, or failed while reading the header"; cout << endl; success = false; break; case 2: // unsupported version of the data cout << endl << "**ERROR** psibin file: unsupported version of the data"; cout << endl; success = false; break; case 3: // error when allocating data buffer cout << endl << "**ERROR** psibin file: error when allocating data buffer"; cout << endl; success = false; break; case 4: // number of histograms/record not equals 1 cout << endl << "**ERROR** psibin file: number of histograms/record not equals 1"; cout << endl; success = false; break; default: // you never should have reached this point success = false; break; } // if any reading error happend, get out of here if (!success) return success; cout << endl << "> " << psiBin.get_numberHisto_int() << ": "; for (int i=0; i " << psiBin.get_nameHisto(i); cout << endl; // fill necessary header informations PIntVector ivec; PRawRunData runData; double dval; // keep run name runData.fRunName = fRunName; // get run title runData.fRunTitle = TString(psiBin.get_comment().c_str()); // run title // get setup runData.fSetup = TString(""); // get field status = sscanf(psiBin.get_field().c_str(), "%lfG", &dval); if (status == 1) runData.fField = dval; // get temperature status = sscanf(psiBin.get_temp().c_str(), "%lfK", &dval); if (status == 1) runData.fTemp = dval; // get time resolution (ns) runData.fTimeResolution = psiBin.get_binWidth_ns(); // get t0's ivec = psiBin.get_t0_vector(); if (ivec.empty()) { cout << endl << "**ERROR** psibin file: couldn't obtain any t0's"; cout << endl; return false; } for (unsigned int i=0; i * */ bool PRunDataHandler::ReadMudFile() { cout << endl << "PRunDataHandler::ReadMudFile(): Sorry, not yet implemented ..."; return false; } //-------------------------------------------------------------------------- // ReadAsciiFile //-------------------------------------------------------------------------- /** *

Reads ascii files. Intended for the No-muSR data. * * The file format definition is: * Comment lines start with a '#' or '%' character. * The file can start with some header info. The header is optional, as all its tags, but * if present it has the following format: * * HEADER * TITLE: title * SETUP: setup * FIELD: field * TEMP: temperature * ENERGY: energy * * field is assumed to be given in (G), the temperature in (K), the energy in (keV) * * The data are read column like and start with the data tag DATA, followed by the * data columns, i.e.: * * DATA * x, y [, error y] * * where spaces, column, are a tab are possible separations. * If no error in y is present, the weighting in the fit will be equal. * */ bool PRunDataHandler::ReadAsciiFile() { bool success = true; cout << endl << "PRunDataHandler::ReadAsciiFile(): Sorry, not yet implemented ..."; // open file ifstream f; // open dump-file f.open(fRunPathName.Data(), ifstream::in); if (!f.is_open()) { cout << endl << "Couldn't open data file (" << fRunPathName.Data() << ") for reading, sorry ..."; cout << endl; return false; } PRawRunData runData; int lineNo = 0; char instr[512]; TString line, workStr; bool headerTag = false; bool dataTag = false; double x, y, ey; while (!f.eof()) { f.getline(instr, sizeof(instr)); line = TString(instr); lineNo++; // check if comment line if (line.BeginsWith("#") || line.BeginsWith("%")) continue; // check if header tag workStr = line; workStr.Remove(TString::kLeading, ' '); // remove spaces from the beining if (workStr.BeginsWith("header", TString::kIgnoreCase)) { headerTag = true; dataTag = false; continue; } // check if data tag workStr = line; workStr.Remove(TString::kLeading, ' '); // remove spaces from the beining if (workStr.BeginsWith("data", TString::kIgnoreCase)) { headerTag = false; dataTag = true; continue; } if (headerTag) { if (line.IsWhitespace()) // ignore empty lines continue; workStr = line; workStr.Remove(TString::kLeading, ' '); // remove spaces from the beining if (workStr.BeginsWith("title:", TString::kIgnoreCase)) { runData.fRunTitle = TString(workStr.Data()+workStr.First(":")+2); } else if (workStr.BeginsWith("setup:", TString::kIgnoreCase)) { runData.fSetup = TString(workStr.Data()+workStr.First(":")+2); } else if (workStr.BeginsWith("field:", TString::kIgnoreCase)) { workStr = TString(workStr.Data()+workStr.First(":")+2); if (!workStr.IsFloat()) { cout << endl << "PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ", field is not a number."; cout << endl; success = false; break; } runData.fField = workStr.Atof(); } else if (workStr.BeginsWith("temp:", TString::kIgnoreCase)) { workStr = TString(workStr.Data()+workStr.First(":")+2); if (!workStr.IsFloat()) { cout << endl << "PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ", temperature is not a number."; cout << endl; success = false; break; } runData.fTemp = workStr.Atof(); } else if (workStr.BeginsWith("energy:", TString::kIgnoreCase)) { workStr = TString(workStr.Data()+workStr.First(":")+2); if (!workStr.IsFloat()) { cout << endl << "PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ", energy is not a number."; cout << endl; success = false; break; } runData.fEnergy = workStr.Atof(); } else { // error cout << endl << "PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ", illegal header line."; cout << endl; success = false; break; } } else if (dataTag) { if (line.IsWhitespace()) // ignore empty lines continue; TObjString *ostr; TObjArray *tokens; // check if data have x, y [, error y] structure, and that x, y, and error y are numbers tokens = line.Tokenize(" ,/t"); // check if the number of data line entries is 2 or 3 if ((tokens->GetEntries() != 2) && (tokens->GetEntries() != 3)) { cout << endl << "PRunDataHandler::ReadAsciiFile **ERROR** found data line with a structure different than \"x, y [, error y]\", cannot be handled (line no " << lineNo << ")"; cout << endl; success = false; break; } // get x ostr = dynamic_cast(tokens->At(0)); if (!ostr->GetString().IsFloat()) { cout << endl << "PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": x = " << ostr->GetString().Data() << " is not a number, sorry."; cout << endl; success = false; break; } x = ostr->GetString().Atof(); // get y ostr = dynamic_cast(tokens->At(1)); if (!ostr->GetString().IsFloat()) { cout << endl << "PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": y = " << ostr->GetString().Data() << " is not a number, sorry."; cout << endl; success = false; break; } y = ostr->GetString().Atof(); // get error y if present if (tokens->GetEntries() == 3) { ostr = dynamic_cast(tokens->At(2)); if (!ostr->GetString().IsFloat()) { cout << endl << "PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": error y = " << ostr->GetString().Data() << " is not a number, sorry."; cout << endl; success = false; break; } ey = ostr->GetString().Atof(); } else { ey = 1.0; } // clean up tokens if (tokens) { delete tokens; tokens = 0; } // keep values runData.fXData.push_back(x); runData.fYData.push_back(y); runData.fErrYData.push_back(ey); } else { cout << endl << "PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << " neither header nor data line. No idea how to handle it!"; cout << endl; success = false; break; } } f.close(); fData.push_back(runData); return success; } //-------------------------------------------------------------------------- // StripWhitespace //-------------------------------------------------------------------------- /** *

* * \param str */ bool PRunDataHandler::StripWhitespace(TString &str) { char *s = 0; char *subs = 0; int i; int start; int end; int size; size = (int)str.Length(); s = new char[size+1]; if (!s) return false; for (int i=0; i * * \param str */ bool PRunDataHandler::IsWhitespace(const char *str) { unsigned int i=0; while (isblank(str[i]) || (iscntrl(str[i])) && str[i] != 0) i++; if (i == strlen(str)) return true; else return false; } //-------------------------------------------------------------------------- // ToDouble //-------------------------------------------------------------------------- /** *

* * \param str * \param ok */ double PRunDataHandler::ToDouble(TString &str, bool &ok) { char *s; double value; int size, status; ok = true; size = (int)str.Length(); s = new char[size+1]; if (!s) { ok = false; return 0.0; } // copy string; stupid way but it works for (int i=0; i * * \param str * \param ok */ int PRunDataHandler::ToInt(TString &str, bool &ok) { char *s; int value; int size, status; ok = true; size = (int)str.Length(); s = new char[size+1]; if (!s) { ok = false; return 0; } // copy string; stupid way but it works for (int i=0; i