/*************************************************************************** PmuppScript.cpp Author: Andreas Suter e-mail: andreas.suter@psi.ch ***************************************************************************/ /*************************************************************************** * Copyright (C) 2007-2023 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 // Q_ASSERT #include "PmuppScript.h" //-------------------------------------------------------------------------- /** * @brief PmuppScript::PmuppScript. Ctor * @param script source */ PmuppScript::PmuppScript(QStringList script) : fScript(script) { fLoadPath = QString("./"); fSavePath = QString("./"); fSelected = -2; // nothing selected fNorm = false; fAdmin = std::make_unique(); } //-------------------------------------------------------------------------- /** * @brief PmuppScript::executeScript. Handles the script commands. * @return 0 on success. */ int PmuppScript::executeScript() { fParamDataHandler = std::make_unique(); if (fParamDataHandler == nullptr) { std::cerr << std::endl << "**ERROR** couldn't invoke data handler ..." << std::endl << std::endl; return -1; } QString cmd; int status; for (int i=0; iReadParamFile(flnList, errorMsg); return 0; } //-------------------------------------------------------------------------- /** * @brief PmuppScript::select. Select collection command. * @param str selection command string * @return 0 on success */ int PmuppScript::select(const QString str) { QString cmd = str; QStringList tok = cmd.split(' ', Qt::SkipEmptyParts); if (tok.size() != 2) { std::cerr << std::endl << "**ERROR** wrong 'select' command syntax." << std::endl << std::endl; return -1; } bool ok; int ival = tok[1].toInt(&ok); if (ok) { // collection index given if (ival >= fParamDataHandler->GetNoOfCollections()) { std::cerr << std::endl << "**ERROR** try to select a collection with index " << ival << ", which is >= # collections (" << fParamDataHandler->GetNoOfCollections() << ")." << std::endl << std::endl; return -2; } fSelected = ival; } else { // assume that a collection name is given ival = fParamDataHandler->GetCollectionIndex(tok[1]); if (ival == -1) { std::cerr << std::endl << "**ERROR** couldn't find collection '" << tok[1].toLatin1().constData() << "'." << std::endl << std::endl; return -3; } if (ival >= fParamDataHandler->GetNoOfCollections()) { std::cerr << std::endl << "**ERROR** try to select a collection with index " << ival << ", which is >= # collections (" << fParamDataHandler->GetNoOfCollections() << ")." << std::endl << std::endl; return -2; } fSelected = ival; } return 0; } //-------------------------------------------------------------------------- /** * @brief PmuppScript::selectAll. Select all collections * @return 0 on success */ int PmuppScript::selectAll() { int noColl = fParamDataHandler->GetNoOfCollections(); if ( noColl > 0) { fSelected = -1; // all collections are selected } else { std::cerr << std::endl << "**ERROR** no collections present, hence it is not possible to select them." << std::endl << std::endl; return -1; } return 0; } //-------------------------------------------------------------------------- /** * @brief PmuppScript::addX. Add label to x-axis * @param str label string * @return 0 on success */ int PmuppScript::addX(const QString str) { QString cmd = str, label; QStringList tok = cmd.split(' ', Qt::SkipEmptyParts); if (tok.size() != 2) { std::cerr << std::endl << "**ERROR** in addX: number of tokens missmatch." << std::endl << std::endl; return -1; } label = tok[1].trimmed(); PmuppCollection *coll=0; if (fSelected == -2) { // no selection -> error std::cerr << std::endl << "**ERROR** in addX. addX called without previous 'select' command." << std::endl << std::endl; return -2; } else if (fSelected == -1) { // i.e. select ALL // clean up plot info first fPlotInfo.clear(); // make sure that label is found in ALL collections, or in variables // first check collections bool foundInColl(true), foundInVar(true); QString collName(""); for (int i=0; iGetNoOfCollections(); i++) { coll = fParamDataHandler->GetCollection(i); if (!foundLabel(coll, label)) { // label not found foundInColl = false; collName = coll->GetName(); break; } } // second check variables if (!foundVariable(label)) { // label not found foundInVar = false; } // make sure label(s) have been found if (!foundInColl && !foundInVar) { // not all labels found, neither in collection nor variables. std::cerr << std::endl << "**ERROR** couldn't find '" << label.toLatin1().constData() << "' in collection '" << collName.toLatin1().constData() << "'," << std::endl; std::cerr << " nor is it a defined variable" << std::endl << std::endl; return -4; } // resize fPlotInfo to the number of selections fPlotInfo.resize(fParamDataHandler->GetNoOfCollections()); // feed plot info for (int i=0; iGetCollection(fSelected); if (coll == 0) { std::cerr << std::endl << "**ERROR** in addX: selected collection couldn't be found ..." << std::endl << std::endl; return -3; } // first check collection bool foundInColl(true), foundInVar(true); QString collName(""); if (!foundLabel(coll, label)) { // label not found foundInColl = false; collName = coll->GetName(); } // second check variables if (!foundVariable(label)) { // label not found foundInVar = false; } // make sure label(s) have been found if (!foundInColl && !foundInVar) { // not all labels found, neither in collection nor variables. std::cerr << std::endl << "**ERROR** couldn't find '" << label.toLatin1().constData() << "' in collection '" << collName.toLatin1().constData() << "'," << std::endl; std::cerr << " nor is it a defined variable" << std::endl << std::endl; return -4; } // feed plot entry fPlotEntry.collIdx = fSelected; fPlotEntry.xLabel = label; } return 0; } //-------------------------------------------------------------------------- /** * @brief PmuppScript::addY. Add label to y-axis. * @param str label string * @return 0 on success */ int PmuppScript::addY(const QString str) { QString cmd = str; QVector label; QStringList tok = cmd.split(' ', Qt::SkipEmptyParts); if (tok.size() < 2) { std::cerr << std::endl << "**ERROR** in addY: number of tokens < 2." << std::endl << std::endl; return -1; } // collect all potential labels for (int i=1; i error std::cerr << std::endl << "**ERROR** in addY. addY called without previous 'select' command." << std::endl << std::endl; return -2; } else if (fSelected == -1) { // i.e. select ALL // make sure that label(s) is/are found in ALL collections, or in variables // first check collections bool foundInColl(true), foundInVar(true); int idx = -1; QString collName(""); for (int i=0; iGetNoOfCollections(); i++) { coll = fParamDataHandler->GetCollection(i); for (int j=0; jGetName(); idx = j; break; } } } // second check variables for (int i=0; iGetCollection(fSelected); if (coll == 0) { std::cerr << std::endl << "**ERROR** in addY: selected collection couldn't be found ..." << std::endl << std::endl; return -3; } // first check specific collection bool foundInColl(true), foundInVar(true); int idx = -1; QString collName(""); for (int i=0; iGetName(); idx = i; break; } } // second check variables for (int i=0; isetProcessEnvironment(env); proc->setWorkingDirectory(fSavePath); proc->start(exec_cmd, arg); if (!proc->waitForStarted()) { std::cerr << std::endl << "**ERROR** Could not execute the output command: " << exec_cmd.toLatin1().constData() << std::endl << std::endl; QFile::remove(macroOut); return -3; } proc->waitForFinished(); QFile::remove(macroOut); return 0; } //-------------------------------------------------------------------------- /** * @brief PmuppScript::macro. Create a root macro * @param str macro string command string * @param plotFln plot file name. Depending on the extension (*.png, *.pdf, ...) * the given a file will be created. * @return 0 on success */ int PmuppScript::macro(const QString str, const QString plotFln) { QVector marker = fAdmin->getMarkers(); QVector color = fAdmin->getColors(); QString cmd = str; QStringList tok = cmd.split(' ', Qt::SkipEmptyParts); if (tok.size() != 2) { std::cerr << std::endl << "**ERROR** macro command with wrong number of arguments (" << tok.size() << ")." << std::endl << std::endl; return -1; } QString macroName = tok[1].trimmed(); QString fln = fSavePath + macroName; QFile file(fln); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { std::cerr << std::endl << "**ERROR** Couldn't open macro file for writting." << std::endl << std::endl; return -2; } QTextStream fout(&file); // write header fout << "// --------------------------" << Qt::endl; fout << "// " << fln.toLatin1().constData() << Qt::endl; fout << "// " << QDateTime::currentDateTime().toString("yy/MM/dd - HH:mm:ss") << Qt::endl; fout << "// --------------------------" << Qt::endl; fout << "{" << Qt::endl; fout << " gROOT->Reset();" << Qt::endl; fout << Qt::endl; fout << " gStyle->SetOptTitle(0);" << Qt::endl; fout << " gStyle->SetOptDate(0);" << Qt::endl; fout << " gStyle->SetPadColor(TColor::GetColor(255,255,255)); // pad bkg to white" << Qt::endl; fout << " gStyle->SetCanvasColor(TColor::GetColor(255,255,255)); // canvas bkg to white" << Qt::endl; fout << Qt::endl; fout << " Int_t nn=0, i=0;" << Qt::endl; fout << " Double_t null[512];" << Qt::endl; fout << " Double_t xx[512];" << Qt::endl; fout << " Double_t yy[512];" << Qt::endl; fout << " Double_t yyPosErr[512];" << Qt::endl; fout << " Double_t yyNegErr[512];" << Qt::endl; fout << Qt::endl; // write data QVector xx, yy, yyPosErr, yyNegErr; QString collName; int count=0; double x_min=0.0, x_max=0.0, x_min_new=0.0, x_max_new=0.0, y_min=0.0, y_max=0.0, y_min_new=0.0, y_max_new=0.0; double dval, y_min_norm=1.0e10; for (int i=0; iGetCollectionName(i); xx = fParamDataHandler->GetValues(collName, fPlotInfo[i].xLabel); if (xx.size() == 0) { // it is a variable int idx = getVarIndex(fPlotInfo[i].xLabel); if (idx == -1) { std::cerr << std::endl; std::cerr << "**ERROR** Couldn't get x-label '" << fPlotInfo[i].xLabel.toLatin1().data() << "'." << std::endl; std::cerr << " This should never happens." << std::endl; return -3; } std::vector xVal = fVarHandler[idx].getValues(); QVector qvec(xVal.begin(), xVal.end()); xx = qvec; } // get x-axis min/max minMax(xx, x_min, x_max); if (count==0) { x_min_new = x_min; x_max_new = x_max; } else { if (x_min < x_min_new) x_min_new = x_min; if (y_max > x_max_new) x_max_new = x_max; } for (int j=0; jGetValues(collName, fPlotInfo[i].yLabel[j]); yyPosErr = fParamDataHandler->GetPosErr(collName, fPlotInfo[i].yLabel[j]); yyNegErr = fParamDataHandler->GetNegErr(collName, fPlotInfo[i].yLabel[j]); if (yy.size() == 0) { // it's a variable int idx = getVarIndex(fPlotInfo[i].yLabel[j]); if (idx == -1) { std::cerr << std::endl; std::cerr << "**ERROR** Couldn't get y-label '" << fPlotInfo[i].yLabel[j].toLatin1().data() << "'." << std::endl; std::cerr << " This should never happens." << std::endl; return -3; } std::vector yVal = fVarHandler[idx].getValues(); QVector qvecV(yVal.begin(), yVal.end()); yy = qvecV; std::vector yErr = fVarHandler[idx].getErrors(); QVector qvecE(yErr.begin(), yErr.end()); yyPosErr = qvecE; yyNegErr = qvecE; } // get y-axis min/max minMax(yy, y_min, y_max); if (count==0) { y_min_new = y_min; y_max_new = y_max; } else { if (y_min < y_min_new) y_min_new = y_min; if (y_max > y_max_new) y_max_new = y_max; } fout << " // " << ++count << ". data set" << Qt::endl; fout << " nn = " << xx.size() << ";" << Qt::endl; fout << " // null-values" << Qt::endl; for (int k=0; k 0.0) x_min = 0.0; else x_min = x_min_new; diff = x_max-x_min; x_max = x_max_new + 0.05*diff; diff = y_max_new - y_min_new; y_min = y_min_new - 0.05 * diff; y_max = y_max_new + 0.05 * diff; if (fNorm) { diff = 1.0 - y_min_norm; y_min = y_min_norm - 0.05 * diff; y_max = 1.0 + 0.05 * diff; } // plotting fout << " //**********" << Qt::endl; fout << " // plotting " << Qt::endl; fout << " //**********" << Qt::endl; fout << " TCanvas *c1 = new TCanvas(\"c1\", \"" << macroName.toLatin1().constData() << "\", 10, 10, 600, 700);" << Qt::endl; fout << Qt::endl; count = 0; int rr, gg, bb; for (int i=0; iSetMarkerStyle(" << marker[count].getMarker() << ");" << Qt::endl; fout << " g_" << i << "_" << j << "->SetMarkerSize(" << marker[count].getMarkerSize() << ");" << Qt::endl; color[count].getRGB(rr, gg, bb); fout << " g_" << i << "_" << j << "->SetMarkerColor(TColor::GetColor(" << rr << "," << gg << "," << bb << "));" << Qt::endl; fout << " g_" << i << "_" << j << "->SetLineColor(TColor::GetColor(" << rr << "," << gg << "," << bb << "));" << Qt::endl; } else { fout << " g_" << i << "_" << j << "->SetMarkerStyle(20);" << Qt::endl; fout << " g_" << i << "_" << j << "->SetMarkerSize(1.3);" << Qt::endl; fout << " g_" << i << "_" << j << "->SetMarkerColor(TColor::GetColor(0,0,0));" << Qt::endl; fout << " g_" << i << "_" << j << "->SetLineColor(TColor::GetColor(0,0,0));" << Qt::endl; } fout << " g_" << i << "_" << j << "->SetFillColor(kWhite);" << Qt::endl; fout << " g_" << i << "_" << j << "->GetXaxis()->SetTitle(\"" << getNicerLabel(fPlotInfo[0].xLabel).toLatin1().data() << "\");" << Qt::endl; fout << " g_" << i << "_" << j << "->GetXaxis()->SetTitleSize(0.05);" << Qt::endl; fout << " g_" << i << "_" << j << "->GetXaxis()->SetDecimals(kTRUE);" << Qt::endl; fout << " g_" << i << "_" << j << "->GetXaxis()->SetLimits(" << x_min << "," << x_max << ");" << Qt::endl; fout << " g_" << i << "_" << j << "->GetYaxis()->SetTitle(\"" << getNicerLabel(fPlotInfo[0].yLabel[0]).toLatin1().data() << "\");" << Qt::endl; fout << " g_" << i << "_" << j << "->GetYaxis()->SetTitleSize(0.05);" << Qt::endl; fout << " g_" << i << "_" << j << "->GetYaxis()->SetTitleOffset(1.30);" << Qt::endl; fout << " g_" << i << "_" << j << "->GetYaxis()->SetRangeUser(" << y_min << "," << y_max << ");" << Qt::endl; fout << " g_" << i << "_" << j << "->Draw(\"AP\");" << Qt::endl; } else { if (count < marker.size()) { fout << " g_" << i << "_" << j << "->SetMarkerStyle(" << marker[count].getMarker() << ");" << Qt::endl; fout << " g_" << i << "_" << j << "->SetMarkerSize(" << marker[count].getMarkerSize() << ");" << Qt::endl; color[count].getRGB(rr, gg, bb); fout << " g_" << i << "_" << j << "->SetMarkerColor(TColor::GetColor(" << rr << "," << gg << "," << bb << "));" << Qt::endl; fout << " g_" << i << "_" << j << "->SetLineColor(TColor::GetColor(" << rr << "," << gg << "," << bb << "));" << Qt::endl; } else { fout << " g_" << i << "_" << j << "->SetMarkerStyle(20);" << Qt::endl; fout << " g_" << i << "_" << j << "->SetMarkerSize(1.3);" << Qt::endl; fout << " g_" << i << "_" << j << "->SetMarkerColor(TColor::GetColor(0,0,0));" << Qt::endl; fout << " g_" << i << "_" << j << "->SetLineColor(TColor::GetColor(0,0,0));" << Qt::endl; } fout << " g_" << i << "_" << j << "->SetFillColor(kWhite);" << Qt::endl; fout << " g_" << i << "_" << j << "->Draw(\"Psame\");" << Qt::endl; } count++; } } fout << " c1->SetMargin(0.15, 0.05, 0.12, 0.05);" << Qt::endl; fout << " c1->Update();" << Qt::endl; if (!plotFln.isEmpty()) { fout << Qt::endl; fout << " c1->SaveAs(\"" << plotFln.toLatin1().constData() << "\");" << Qt::endl; } fout << "}" << Qt::endl; return 0; } //-------------------------------------------------------------------------- /** * @brief PmuppScript::var_cmd. Variable definition command * @param str variable definition command string * @return 0 on success */ int PmuppScript::var_cmd(const QString str) { QStringList tok; int idx=0; // get linked collection index for further use tok = str.split(' ', Qt::SkipEmptyParts); if (tok[1].endsWith("Err")) // error variable no need to do something return 0; idx = getCollectionIndex(tok[1]); if (idx == -1) // var not linked to collection, ignore it return 0; // check if the related error variable is present QString varErr = QString("%1%2").arg(tok[1]).arg("Err"); QString varErrCmd(""); for (int i=0; iGetCollection(idx), parse_str, tok[1].toLatin1().data()); if (!varHandler.isValid()) { // deal with errors QString mupp_err = QString("%1/.musrfit/mupp/mupp_err.log").arg(QString(qgetenv("HOME"))); // dump error messages if present QFile fout(mupp_err); if (fout.open(QIODevice::ReadOnly | QIODevice::Text)) { QString msg; while (!fout.atEnd()) { msg = fout.readLine(); std::cerr << msg.toLatin1().data(); } // delete potentially present mupp_err.log file QFile::remove(mupp_err); } return 1; } fVarHandler.push_back(varHandler); return 0; } //-------------------------------------------------------------------------- /** * @brief PmuppScript::foundLabel find label in collection coll. * @param coll collection object * @return true if found */ bool PmuppScript::foundLabel(PmuppCollection *coll, const QString label) { bool result = false; for (int i=0; iGetRun(0).GetNoOfParam(); i++) { if (!coll->GetRun(0).GetParam(i).GetName().compare(label)) { result = true; break; } } return result; } //-------------------------------------------------------------------------- /** * @brief PmuppScript::foundVariable. Check if a variable is found in the * variable handler. * @param var variable name * @return true if found */ bool PmuppScript::foundVariable(const QString var) { bool result = false; for (int i=0; i dvec, double &min, double &max) { min = 99.0e6; max = -99.0e6; for (int i=0; i max) max = dvec[i]; } } //-------------------------------------------------------------------------- /** * @brief PmuppScript::getNicerLabel. Prettify the labels. * @param label to be prettified * @return prettified label */ QString PmuppScript::getNicerLabel(const QString label) { QString nice = label; if (label == "dataE") { nice = "E (keV)"; } else if (label == "dataT") { nice = "T (K)"; } else if (label == "dataB") { nice = "B (G)"; } else if (!label.compare("sigma", Qt::CaseInsensitive)) { if (fNorm) nice = "#sigma/max(#sigma)"; else nice = "#sigma (1/#mus)"; } else if (!label.compare("lambda", Qt::CaseInsensitive)) { if (fNorm) nice = "#lambda/max(#lambda)"; else nice = "#lambda (1/#mus)"; } else if (!label.compare("rate", Qt::CaseInsensitive)) { if (fNorm) nice = "Rate/max(Rate)"; else nice = "Rate (1/#mus)"; } else if (!label.compare("alpha_LR", Qt::CaseInsensitive)) { if (fNorm) nice = "#alpha_{LR}/max(#alpha_{LR})"; else nice = "#alpha_{LR}"; } else if (!label.compare("alpha_TB", Qt::CaseInsensitive)) { if (fNorm) nice = "#alpha_{TB}/max(#alpha_{TB})"; else nice = "#alpha_{TB}"; } else { if (fNorm) { nice = label + "/ max(" + label + ")"; } } return nice; } //-------------------------------------------------------------------------- /** * @brief PmuppScript::getCollectionIndex. Get the index of a collection. * @param var_name name of the collection * @return idx on success, -1 otherwise */ int PmuppScript::getCollectionIndex(const QString var_name) { int idx = -1; QString cmd; QStringList tok; bool ok; for (int i=0; i