/*************************************************************************** Pmupp.cpp Author: Andreas Suter e-mail: andreas.suter@psi.ch ***************************************************************************/ /*************************************************************************** * Copyright (C) 2007-2020 by Andreas Suter * * andreas.suter@psi.ch * * * * 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 #include #include #include #include #include #include #include #include #include #include #include #include "Pmupp.h" #define PMUPP_UNDEF -1 #define PMUPP_VALUE 0 #define PMUPP_POSNEGERR 1 #define PMUPP_POSERR 2 #define PMUPP_NEGERR 3 #define PMUPP_RUN 4 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ /** * @brief PmuppParam::PmuppParam. Ctor */ PmuppParam::PmuppParam() { ResetParam(); } //-------------------------------------------------------------------------- /** * @brief PmuppParam::PmuppParam. Ctor * @param name parameter name * @param param parameter value * @param posErr parameter error */ PmuppParam::PmuppParam(QString name, double param, double posErr) { SetParam(name, param, posErr); } //-------------------------------------------------------------------------- /** * @brief PmuppParam::PmuppParam. Ctor * @param name parameter name * @param param parameter value * @param posErr positive parameter error * @param negErr negative parameter error */ PmuppParam::PmuppParam(QString name, double param, double posErr, double negErr) { SetParam(name, param, posErr, negErr); } //-------------------------------------------------------------------------- /** * @brief PmuppParam::ResetParam. Reset the parameter values */ void PmuppParam::ResetParam() { fName = ""; fValue = MUPP_UNDEF; fPosErr = MUPP_UNDEF; fNegErr = MUPP_UNDEF; } //-------------------------------------------------------------------------- /** * @brief PmuppParam::SetParam. Set a parameter * @param name parameter name * @param param parameter value * @param posErr parameter error */ void PmuppParam::SetParam(QString name, double param, double posErr) { fName = name; fValue = param; fPosErr = posErr; } //-------------------------------------------------------------------------- /** * @brief PmuppParam::SetParam. Set a parameter * @param name parameter name * @param param parameter value * @param posErr positive parameter value * @param negErr negative parameter value */ void PmuppParam::SetParam(QString name, double param, double posErr, double negErr) { fName = name; fValue = param; fPosErr = posErr; fNegErr = negErr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ /** * @brief PmuppRun::GetParam. Get a parameter from a run * @param idx index of the parameter * @return the parameter value */ PmuppParam PmuppRun::GetParam(unsigned int idx) { PmuppParam param; if (idx < (unsigned int)fParam.size()) param = fParam[idx]; return param; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ /** * @brief PmuppCollection::GetRun. Returns a run from a collection. * @param idx of the run in a collection * @return a run from a collection */ PmuppRun PmuppCollection::GetRun(unsigned int idx) { PmuppRun run; if (idx < (unsigned int)fRun.size()) run = fRun[idx]; return run; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ /** * @brief PParamDataHandler::NewCollection. Adds an empty new collection with * name 'name'. * @param name of the new collection */ void PParamDataHandler::NewCollection(const QString name) { PmuppCollection collection; collection.SetName(name); fCollection.push_back(collection); } //-------------------------------------------------------------------------- /** * @brief PParamDataHandler::analyzeFileList. In case the input is given by * msr-files, the structure of the file names needs to be analyzed that * msr2data can be called. * * @param fln list of msr-files to be analyzed. * @param collectionName output collection name (db-/dat-file). * @param arg argument list which is needed to feed msr2data * @param workDir working directory * @param errorMsg error message in case something went wrong. * * @return true if successful, false otherwise */ bool PParamDataHandler::analyzeFileList(const QStringList &fln, QString &collectionName, QStringList &arg, QString &workDir, QString &errorMsg) { // 1) check all the msr-files have the same structure: .msr with the same // for all msr-files present. QString ext(""); QStringList run; QStringList tok; int pos0=-1, pos1=-1; QString flnCurrent(""), extCurrent(""), runStr(""); bool ok; pos0 = fln[0].lastIndexOf("/"); workDir = fln[0].left(pos0); for (int i=0; i and pos0 = flnCurrent.indexOf("_"); if (pos0 == -1) { errorMsg = "msr-file name has a structure which cannot be handled.\n\ It should be , where is the run number\n\ and needs to start with a '_'."; return false; } pos1 = flnCurrent.lastIndexOf("."); if ((pos1 == -1) || (pos1 < pos0)) { errorMsg = "msr-file name has a structure which cannot be handled.\n\ It should be .msr, where is the run number\n\ and needs to start with a '_'."; return false; } // get run number runStr = flnCurrent.left(pos0); runStr.toInt(&ok); // output not needed, only check that it is a number if (!ok) { errorMsg = QString("Found run number string '%1' which is not a number.").arg(runStr); return false; } run << runStr; // keep extension if (i == 0) ext = flnCurrent.mid(pos0, pos1-pos0); else extCurrent = flnCurrent.mid(pos0, pos1-pos0); // make sure all extensions are identical if ((i>0) && (ext != extCurrent)) { errorMsg = "Currently mixed msr-file extensions cannot be handled."; return false; } } arg << "["; for (int i=0; isetProcessEnvironment(env); fProc->setWorkingDirectory(workDir); fProc->start(cmd, arg); if (!fProc->waitForFinished()) { errorMsg = QString(tr("Could not execute the output command: ")+cmd[0]); return false; } // since the db-file should now be present, just load it collection = ReadDbFile(pathName, valid, errorMsg); if (!valid) { std::cerr << std::endl; std::cerr << "----" << std::endl; std::cerr << "**ERROR** read db-file failure (" << pathName.toLatin1().data() << "." << std::endl; std::cerr << "----" << std::endl; return false; } collName.remove(".db"); collection.SetPathName(pathName); collection.SetName(collName); fCollection.push_back(collection); } else { // db-, dat-file list for (int i=0; i 0) { if (collection.GetRun(0).GetNoOfParam() != run.GetNoOfParam()) { errorMsg = fln + QString(".\n"); errorMsg += QString(" first run (#%1) has %2 params.\n").arg(collection.GetRun(0).GetNumber()).arg(collection.GetRun(0).GetNoOfParam()); errorMsg += QString(" current run (#%1) has %2 params.\n").arg(run.GetNumber()).arg(run.GetNoOfParam()); errorMsg += QString(" Inspect your db-file!"); std::cerr << std::endl; std::cerr << "----" << std::endl; std::cerr << "**ERROR** in " << errorMsg.toLatin1().data() << std::endl; std::cerr << "----" << std::endl; file.close(); valid = false; return collection; } } collection.AddRun(run); run.Clear(); } else { // parameter if (token.size() != 4) { // wrong number of parameter tokens std::cerr << std::endl; std::cerr << "----" << std::endl; std::cerr << "**ERROR** in" << fln.toLatin1().data() <<". # parameter tokens != 4." << std::endl; std::cerr << "----" << std::endl; file.close(); valid = false; return collection; } subTok = token[0].split("="); if (subTok.size() != 2) { std::cerr << std::endl; std::cerr << "----" << std::endl; std::cerr << "**ERROR** in" << fln.toLatin1().data() <<". parameter name=value token missing." << std::endl; std::cerr << "----" << std::endl; file.close(); valid = false; return collection; } QString paramName = subTok[0].trimmed(); param.ResetParam(); param.SetName(paramName); dval = subTok[1].toDouble(&ok); if (ok) { param.SetValue(dval); } else { std::cerr << std::endl; std::cerr << "----" << std::endl; std::cerr << "**ERROR** in" << fln.toLatin1().data() <<". parameter name=value token missing or wrong?!" << std::endl; std::cerr << "----" << std::endl; file.close(); valid = false; return collection; } // pos. err dval = token[1].toDouble(&ok); if (ok) { param.SetPosErr(dval); } else { std::cerr << std::endl; std::cerr << "----" << std::endl; std::cerr << "**ERROR** in" << fln.toLatin1().data() <<". parameter pos. error not a number?!" << std::endl; std::cerr << "----" << std::endl; file.close(); valid = false; return collection; } // neg. err dval = token[2].toDouble(&ok); if (ok) { param.SetNegErr(dval); } else { std::cerr << std::endl; std::cerr << "----" << std::endl; std::cerr << "**ERROR** in" << fln.toLatin1().data() <<". parameter neg. error not a number?!" << std::endl; std::cerr << "----" << std::endl; file.close(); valid = false; return collection; } run.AddParam(param); } } } if (!param_found) { std::cerr << std::endl; std::cerr << "----" << std::endl; std::cerr << "**ERROR** in" << fln.toLatin1().data() <<". No parameter found." << std::endl; std::cerr << "----" << std::endl; } file.close(); valid = true; return collection; } //-------------------------------------------------------------------------- /** * @brief PParamDataHandler::ReadColumnParamFile. Reads a dat-file * @param fln file name of the dat-file to be read * @param valid true on success, false otherwise. * @param errorMsg error message in case read fails. * * @return the collection object containing the dat-file on success. */ PmuppCollection PParamDataHandler::ReadColumnParamFile(const QString fln, bool &valid, QString &errorMsg) { PmuppCollection collection; PmuppRun run; valid = true; QFile file(fln); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { errorMsg = QString("couldn't open ")+fln; std::cerr << std::endl; std::cerr << "----" << std::endl; std::cerr << "**ERROR** " << errorMsg.toLatin1().data() << std::endl; std::cerr << "----" << std::endl; valid = false; return collection; } QTextStream in(&file); QString line; QStringList token; bool done = false, ok; double dval = 0; int ival; PmuppParam param; run.SetName(fln); // read header information line = in.readLine(); token = line.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts); QVector headerInfo; QVector headerCode; // 0=value, 1=pos/neg err, 2=pos err, 3=neg err, 4=run number int code=PMUPP_UNDEF; for (int i=0; i=fCollection.size())) { valid = false; return collection; } return fCollection[idx]; } //-------------------------------------------------------------------------- /** * @brief PParamDataHandler::GetCollection. Get a pointer of the requested * collection. * @param idx of the collection * * @return requested pointer to the collection on success. */ PmuppCollection *PParamDataHandler::GetCollection(const int idx) { if ((idx<0) || (idx>=fCollection.size())) { return nullptr; } return &fCollection[idx]; } //-------------------------------------------------------------------------- /** * @brief PParamDataHandler::GetCollection. Get collection by name. * @param name of the requested collection * @param valid true if found * * @return requested collection on success. */ PmuppCollection PParamDataHandler::GetCollection(const QString name, bool &valid) { valid = true; PmuppCollection collection; int idx=-1; for (int i=0; i= 0) && (idx < fCollection.size())) name = fCollection[idx].GetName(); return name; } //-------------------------------------------------------------------------- /** * @brief PParamDataHandler::GetValues. Get the data values of a parameter of * a requested collection. * @param collName name of the collection * @param paramName parameter name * * @return data values of the requested parameter name of the collection collName. * Empty data vector otherwise. */ QVector PParamDataHandler::GetValues(QString collName, QString paramName) { QVector data; // find collection with correct name int idx=-1; for (int i=0; i PParamDataHandler::GetPosErr(QString collName, QString paramName) { QVector data; // find collection with correct name int idx=-1; for (int i=0; i PParamDataHandler::GetNegErr(QString collName, QString paramName) { QVector data; // find collection with correct name int idx=-1; for (int i=0; i= fCollection.size()) return; fCollection.replace(idx, coll); } //-------------------------------------------------------------------------- /** * @brief PParamDataHandler::Dump. Dumps the collection onto stdout */ void PParamDataHandler::Dump() { PmuppRun run; PmuppParam param; for (int i=0; i +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-" << std::endl; std::cout << "debug> collection name: " << fCollection[i].GetName().toLatin1().data() << std::endl; std::cout << "debug> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-" << std::endl; for (int j=0; j ----------------------------------" << std::endl; run = fCollection[i].GetRun(j); std::cout << "debug>> run number: " << run.GetNumber() << std::endl; std::cout << "debug>> run name : " << run.GetName().toLatin1().data() << std::endl; std::cout << "debug>> ---------------------------------" << std::endl; for (int k=0; k>> " << param.GetName().toLatin1().data() << ": " << param.GetValue() << " -+ " << param.GetNegErr() << " / " << param.GetPosErr() << std::endl; } } } } //-------------------------------------------------------------------------- /** * @brief PParamDataHandler::readFromStdOut */ void PParamDataHandler::readFromStdOut() { qInfo() << fProc->readAllStandardOutput(); } //-------------------------------------------------------------------------- /** * @brief PParamDataHandler::readFromStdErr */ void PParamDataHandler::readFromStdErr() { qInfo() << fProc->readAllStandardError(); } //-------------------------------------------------------------------------- /** * @brief PParamDataHandler::processDone * @param exitCode * @param exitStatus */ void PParamDataHandler::processDone(int exitCode, QProcess::ExitStatus exitStatus) { qInfo() << "in processDone()"; if ((exitStatus == QProcess::CrashExit) && (exitCode != 0)) { qInfo() << "**ERROR** processDone: exitCode = " << exitCode << Qt::endl; } }