From 65d40cfe978deb3a3ebd9dbe183b7d928b5ded21 Mon Sep 17 00:00:00 2001 From: Andreas Suter Date: Sun, 18 Dec 2016 10:31:16 +0100 Subject: [PATCH] improved user interface. (i) it is searching now not only in the current directory or file-path-name, but also in the default search paths for data files as defined in the musrfit_startup.xml. (ii) it is now also possible to use run numbers rather than full file names. --- src/dump_header.cpp | 417 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 392 insertions(+), 25 deletions(-) diff --git a/src/dump_header.cpp b/src/dump_header.cpp index 20f816ea..f6affbac 100644 --- a/src/dump_header.cpp +++ b/src/dump_header.cpp @@ -31,12 +31,16 @@ #include "config.h" #endif +#include +#include +#include #include #include #include #include #include +#include #include #include @@ -46,6 +50,7 @@ using namespace std; #include #include "git-revision.h" +#include "PStartupHandler.h" #include "TMusrRunHeader.h" #include "TLemRunHeader.h" #include "MuSR_td_PSI_bin.h" @@ -64,16 +69,29 @@ using namespace std; */ void dump_header_syntax() { - cout << endl << "usage: dump_header [--file_format ] | --help | --version"; - cout << endl << " Dumps the header information of a given muSR data file onto the standard output."; - cout << endl << " If no is given, it will try to fiddle out what it might be."; + cout << endl << "usage: dump_header [-rn | -fn ] [-ff, --fileFormat ]"; + cout << endl << " [-y, --year ] [-s, --summary] [--psi-bulk ] |"; + cout << endl << " --help | --version"; cout << endl; - cout << endl << " : muSR data file name."; - cout << endl << " --file_format : where can be:"; + cout << endl << " Dumps the header information of a given muSR data file onto the standard output."; + cout << endl << " If no info is povided, it will try to guess what it might be."; + cout << endl << " For guessing of the file format is not possible. The default assumption here is 'MusrRoot'."; + cout << endl; + cout << endl << " -rn, --runNo : run number of the header to be dumped."; + cout << endl << " -fn, --fileName : muSR data file name."; + cout << endl << " -ff, --fileFormat : where can be:"; cout << endl << " MusrRoot, NeXus, ROOT (old LEM), PSI-BIN, PSI-MDU, MUD, WKM"; cout << endl << " NeXus is only supported if enabled."; - cout << endl << " --help, -h : will show this help"; - cout << endl << " --version, -v : will show the current version."; + cout << endl << " -y, --year : has to be 4 digit, e.g. 2005, if provided it is used to"; + cout << endl << " generate the file name for the given , otherwise the current"; + cout << endl << " year is used. If a file name is given, this option has no effect."; + cout << endl << " -s, --summary : this option is used for LE-uSR data sets only. It will, additionally"; + cout << endl << " to the header information, print the summary file content."; + cout << endl << " --psi-bulk : where consists of two items: (i) pta or tdc, "; + cout << endl << " (ii) gps | ltf | dolly | gpd | hifi. This is needed in combination with"; + cout << endl << " the file formats PSI-BIN and PSI-MDU."; + cout << endl << " -h, --help : will show this help"; + cout << endl << " -v, --version : will show the current version."; cout << endl << endl; } @@ -81,7 +99,7 @@ void dump_header_syntax() /** * */ -int dump_header_root(const string fileName, const string fileFormat) +int dump_header_root(const string fileName, const string fileFormat, const bool summary) { TFile f(fileName.c_str()); if (f.IsZombie()) { @@ -178,6 +196,27 @@ int dump_header_root(const string fileName, const string fileFormat) delete header; } + // summary as well? + if (summary && (fileType == DH_MUSR_ROOT)) { + TObjArray *runSum=0; + runSum = (TObjArray*)folder->FindObject("RunSummary"); + if (!runSum) { // something is wrong!! + cerr << endl << "**ERROR** Couldn't obtain RunSummary " << fileName << endl; + f.Close(); + return 1; + } + cout << "++++++++++++++++++++" << endl; + cout << " Run Summary" << endl; + cout << "++++++++++++++++++++" << endl; + TObjString *tstr; + TString str; + for (Int_t i=0; iGetEntries(); i++) { + tstr = (TObjString*)runSum->At(i); + str = tstr->String(); + cout << str; + } + } + f.Close(); return 0; @@ -562,7 +601,145 @@ int dump_header_wkm(const string fileName, const string fileFormat) //------------------------------------------------------------------------ /** - * + * @brief is_number + * @param s + * @return + */ +bool dump_is_number(const char *s) +{ + int i=0; + + if (s == 0) // make sure it is not a null pointer + return false; + + while (isdigit(s[i])) + i++; + + if (s[i] == '\0') + return true; + else + return false; +} + +//------------------------------------------------------------------------ +/** + * @brief dump_current_year + * @return + */ +int dump_current_year() +{ + time_t rawtime; + struct tm * timeinfo; + char buffer[32]; + + time (&rawtime); + timeinfo = localtime(&rawtime); + strftime(buffer, 32, "%Y", timeinfo); + + return atoi(buffer); +} + +//------------------------------------------------------------------------ +/** + * @brief dump_create_fln + * @param runNo + * @param year + * @param fileFormat + * @return + */ +string dump_create_fln(string runNo, string year, string fileFormat, bool pta, string instrument) +{ + string result = "??"; + int yearShort=0; + int iRunNo=0; + + if (fileFormat.empty()) + fileFormat = "MusrRoot"; + + // make sure that a 'legal' file format has been found + if (!boost::iequals(fileFormat, "MusrRoot") && + !boost::iequals(fileFormat, "NeXus") && + !boost::iequals(fileFormat, "ROOT") && + !boost::iequals(fileFormat, "PSI-BIN") && + !boost::iequals(fileFormat, "PSI-MDU") && + !boost::iequals(fileFormat, "MDU") && + !boost::iequals(fileFormat, "WKM")) { + return result; + } + + // if year is an empty string get the current year + int yy=-1; + stringstream ss; + if (year.empty()) { + yy = dump_current_year(); + ss << yy; + year = ss.str(); + } + yy = atoi(year.c_str()); + if (yy > 2000) + yearShort = yy - 2000; + else + yearShort = yy - 1900; + + iRunNo = atoi(runNo.c_str()); + + char fln[64]; + char ptatdc[8]; + if (pta) + strcpy(ptatdc, "pta"); + else + strcpy(ptatdc, "tdc"); + if (boost::iequals(fileFormat, "MusrRoot") || boost::iequals(fileFormat, "ROOT")) { + snprintf(fln, sizeof(fln), "lem%02d_his_%04d.root", yearShort, iRunNo); + } else if (boost::iequals(fileFormat, "NeXus")) { + snprintf(fln, sizeof(fln), "%s.nxs", runNo.c_str()); + } else if (boost::iequals(fileFormat, "PSI-BIN")) { + snprintf(fln, sizeof(fln), "deltat_%s_%s_%04d.bin", ptatdc, instrument.c_str(), iRunNo); + } else if (boost::iequals(fileFormat, "PSI-MDU")) { + snprintf(fln, sizeof(fln), "%s_%s_%s_%05d.mdu", ptatdc, instrument.c_str(), year.c_str(), iRunNo); + } else if (boost::iequals(fileFormat, "MUD")) { + snprintf(fln, sizeof(fln), "%06d.msr", iRunNo); + } else if (boost::iequals(fileFormat, "WKM")) { + + } + result = fln; + + return result; +} + +//------------------------------------------------------------------------ +/** + * @brief dump_file_exists + * @param pathName + * @return + */ +bool dump_file_exists(const string pathName) +{ + bool exists = true; + + int res = access(pathName.c_str(), R_OK); + if (res < 0) { + if (errno == ENOENT) { + // file does not exist + exists = false; + } else if (errno == EACCES) { + // file exists but is not readable + exists = false; + } else { + // FAIL + exists = false; + } + } + + return exists; +} + +//------------------------------------------------------------------------ +/** + * @brief main + * @param argc + * @param argv + * @return */ int main(int argc, char *argv[]) { @@ -571,9 +748,14 @@ int main(int argc, char *argv[]) return 0; } + string runNo(""); string fileName(""); string fileFormat(""); - int count=0; + string year(""); + bool pta(false); + string instrument(""); + bool summary(false); + for (int i=1; i= argc) { - cout << endl << "**ERROR** found '--file_format' without !" << endl; + cerr << endl << "**ERROR** found -rn, --runNo without !" << endl; + dump_header_syntax(); + return 1; + } + // make sure there is only one 'legal' run number + int count = 1; + while (dump_is_number(argv[i+count]) && (i+count < argc)) + count++; + // make sure there is one and only one run number given + if (count == 1) { + cerr << endl << "**ERROR** found -rn, --runNo without , or the provided ('" << argv[i+1] << "') is not a number!" << endl; + dump_header_syntax(); + return 1; + } + if (count > 2) { + cerr << endl << "**ERROR** found -rn, --runNo with more than one ! This is not yet supported." << endl; + dump_header_syntax(); + return 1; + } + runNo = argv[i+1]; + i++; + } else if (!strcmp(argv[i], "-fn") || !strcmp(argv[i], "--fileName")) { + if (i+1 >= argc) { + cerr << endl << "**ERROR** found -fn, --fileName without !" << endl; + dump_header_syntax(); + return 1; + } + fileName = argv[i+1]; + i++; + } else if (!strcmp(argv[i], "--fileFormat") || !strcmp(argv[i], "-ff")) { + if (i+1 >= argc) { + cerr << endl << "**ERROR** found -ff, --fileFormat without !" << endl; dump_header_syntax(); return 1; } @@ -595,27 +808,169 @@ int main(int argc, char *argv[]) if (!boost::iequals(ff, "MusrRoot") && !boost::iequals(ff, "NeXus") && !boost::iequals(ff, "ROOT") && !boost::iequals(ff, "PSI-BIN") && !boost::iequals(ff, "PSI-MDU") && !boost::iequals(ff, "MUD") && !boost::iequals(ff, "WKM")) { // none of the listed found - cout << endl << "**ERROR** found unsupported muSR file data format: " << argv[i+1] << endl; + cerr << endl << "**ERROR** found unsupported muSR file data format: " << argv[i+1] << endl; dump_header_syntax(); return 1; } fileFormat = argv[i+1]; i++; + } else if (!strcmp(argv[i], "-y") || !strcmp(argv[i], "--year")) { + if (i+1 >= argc) { + cerr << endl << "**ERROR** found -y, --year without !" << endl; + dump_header_syntax(); + return 1; + } + if (!dump_is_number(argv[i+1])) { + cerr << endl << "**ERROR** found -y, --year with sensless '" << argv[i+1] << "'!" << endl; + dump_header_syntax(); + return 1; + } + int yy = strtod(argv[i+1], (char**)0); + if ((yy < 1950) || (yy > dump_current_year())) { + cerr << endl << "**ERROR** found -y, --year with '" << yy << "'!"; + cerr << endl << " Well, cannot handle files in the pre-muSR time nor in the future." << endl; + dump_header_syntax(); + return 1; + } + year = argv[i+1]; + i++; + } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--summary")) { + summary = true; + } else if (!strcmp(argv[i], "--psi-bulk")) { + if (i+2 >= argc) { + cerr << endl << "**ERROR** found --psi-bulk with insufficient input!" << endl; + dump_header_syntax(); + return 1; + } + if (!strcmp(argv[i+1], "pta")) + pta = true; + else if (!strcmp(argv[i+1], "tdc")) + pta = false; + else { + cerr << endl << "**ERROR** found --psi-bulk with 1st argument '" << argv[i+1] << "'! Allowed is 'pta' or 'tdc'." << endl; + dump_header_syntax(); + return 1; + } + if (strcmp(argv[i+2], "gps") && strcmp(argv[i+2], "ltf") && strcmp(argv[i+2], "dolly") && + strcmp(argv[i+2], "gpd") && strcmp(argv[i+2], "hifi")) { + cerr << endl << "**ERROR** found --psi-bulk with 2nd argument '" << argv[i+1] << "'! This is an unkown instrument." << endl; + dump_header_syntax(); + return 1; + } + instrument = argv[i+2]; + i += 2; } else { - count++; - fileName = argv[i]; + cerr << endl << "**ERROR** found unkown option '" << argv[i] << "'." << endl; + dump_header_syntax(); + return 1; } } - // check if more then one file name was given - if (count != 1) { - cout << endl << "**ERROR** (only) a single file name is needed!" << endl; - dump_header_syntax(); + // if year is not provided, take the current one + if (year.empty()) { + stringstream ss; + ss << dump_current_year(); + year = ss.str(); + } + + if ((runNo.length() != 0) && (fileName.length() != 0)) { + cerr << endl << "**ERROR** currently only either runNo or fileName can be handled, not both simultanously." << endl; + return 1; + } + + // invoke the startup handler in order to get the default search paths to the data files + // read startup file + char startup_path_name[128]; + TSAXParser *saxParser = new TSAXParser(); + PStartupHandler *startupHandler = new PStartupHandler(); + if (!startupHandler->StartupFileFound()) { + cerr << endl << ">> musrfit **WARNING** couldn't find " << startupHandler->GetStartupFilePath().Data(); + cerr << endl; + // clean up + if (saxParser) { + delete saxParser; + saxParser = 0; + } + if (startupHandler) { + delete startupHandler; + startupHandler = 0; + } + } else { + strcpy(startup_path_name, startupHandler->GetStartupFilePath().Data()); + saxParser->ConnectToHandler("PStartupHandler", startupHandler); + //status = saxParser->ParseFile(startup_path_name); + // parsing the file as above seems to lead to problems in certain environments; + // use the parseXmlFile function instead (see PStartupHandler.cpp for the definition) + int status = parseXmlFile(saxParser, startup_path_name); + // check for parse errors + if (status) { // error + cerr << endl << ">> musrfit **WARNING** Reading/parsing musrfit_startup.xml failed."; + cerr << endl; + // clean up + if (saxParser) { + delete saxParser; + saxParser = 0; + } + if (startupHandler) { + delete startupHandler; + startupHandler = 0; + } + } + } + + // runNo given, hence try to create the necessary file name based on the provided information + if (runNo != "") { + string str = dump_create_fln(runNo, year, fileFormat, pta, instrument); + if (str == "??") { + cerr << endl << "**ERROR** couldn't get a proper file name." << endl; + return 1; + } + fileName = str; + } + + bool found_fln = false; + // 1st check if the file name is found in the current directory + string pathFln(""); + pathFln = "./" + fileName; + if (dump_file_exists(pathFln)) + found_fln = true; + + // 2nd check if file name is found in any default search paths if not already found in the current directory + if (!found_fln) { + PStringVector pathList = startupHandler->GetDataPathList(); + for (unsigned int i=0; i