mupp 1.1.0
Loading...
Searching...
No Matches
PmuppScript.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 PmuppScript.cpp
4
5 Author: Andreas Suter
6 e-mail: andreas.suter@psi.ch
7
8***************************************************************************/
9
10/***************************************************************************
11 * Copyright (C) 2007-2026 by Andreas Suter *
12 * andreas.suter@psi.ch *
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program; if not, write to the *
26 * Free Software Foundation, Inc., *
27 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
28 ***************************************************************************/
29
67
68#include <cmath>
69#include <iostream>
70
71#include <QProcessEnvironment>
72#include <QString>
73#include <QFile>
74#include <QTextStream>
75#include <QDateTime>
76#include <QProcess>
77
78#include <QtGlobal> // Q_ASSERT
79
80#include "PmuppScript.h"
81
82//--------------------------------------------------------------------------
95PmuppScript::PmuppScript(QStringList script) :
96 fScript(script)
97{
98 fLoadPath = QString("./");
99 fSavePath = QString("./");
100 fSelected = -2; // nothing selected
101 fNorm = false;
102
103 fAdmin = std::make_unique<PmuppAdmin>();
104}
105
106//--------------------------------------------------------------------------
137{
138 fParamDataHandler = std::make_unique<PParamDataHandler>();
139 if (fParamDataHandler == nullptr) {
140 std::cerr << std::endl << "**ERROR** couldn't invoke data handler ..." << std::endl << std::endl;
141 return -1;
142 }
143
144 QString cmd;
145 int status;
146 for (int i=0; i<fScript.size(); i++) {
147 status = 0;
148 cmd = fScript.at(i);
149 if (cmd.startsWith("loadPath")) {
150 setLoadPath(cmd);
151 } else if (cmd.startsWith("savePath")) {
152 setSavePath(cmd);
153 } else if (cmd.startsWith("load ")) {
154 status = loadCollection(cmd);
155 } else if (cmd.startsWith("selectAll")) {
156 status = selectAll();
157 } else if (cmd.startsWith("select ")) {
158 status = select(cmd);
159 } else if (cmd.startsWith("x")) {
160 status = addX(cmd);
161 } else if (cmd.startsWith("y")) {
162 status = addY(cmd);
163 } else if (cmd.startsWith("norm")) {
164 fNorm = true;
165 } else if (cmd.startsWith("plot")) {
166 status = plot(cmd);
167 } else if (cmd.startsWith("macro")) {
168 status = macro(cmd);
169 } else if (cmd.startsWith("var")) {
170 status = var_cmd(cmd, i);
171 } else if (cmd.startsWith("col")) {
172 // nothing to be done here, since var handles it internally
173 } else if (cmd.startsWith("<python>")) {
174 // the python block is consumed by var_cmd of the linked variable
175 } else {
176 std::cerr << "**ERROR** found unkown script command '" << cmd.toLatin1().constData() << "'." << std::endl << std::endl;
177 status = -2;
178 }
179 // check for errors
180 if (status != 0) {
181 emit finished();
182 return status;
183 }
184 }
185
186 emit finished();
187
188 return 0;
189}
190
191//--------------------------------------------------------------------------
210void PmuppScript::setLoadPath(const QString cmd)
211{
212 QString str = cmd;
213 QStringList tok;
214
215 // remove command from string
216 str = str.remove("loadPath ");
217
218 // tokenize path string
219 tok = str.split("/", Qt::SkipEmptyParts);
220
221 // check if there is a bash variable which needs to be resolved
222 QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment();
223 QString path = QString("");
224 for (int i=0; i<tok.size(); i++) {
225 str = tok.at(i);
226 if (str.startsWith("$")) {
227 str = str.remove("$");
228 QString var = procEnv.value(str, "");
229 path += var + "/";
230 } else {
231 path += str + "/";
232 }
233 }
234
235 fLoadPath = path;
236}
237
238//--------------------------------------------------------------------------
256void PmuppScript::setSavePath(const QString cmd)
257{
258 QString str = cmd;
259 QStringList tok;
260
261 // remove command from string
262 str = str.remove("savePath ");
263
264 // tokenize path string
265 tok = str.split("/", Qt::SkipEmptyParts);
266
267 // check if there is a bash variable which needs to be resolved
268 QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment();
269 QString path = QString("");
270 for (int i=0; i<tok.size(); i++) {
271 str = tok.at(i);
272 if (str.startsWith("$")) {
273 str = str.remove("$");
274 QString var = procEnv.value(str, "");
275 path += var + "/";
276 } else {
277 path += str + "/";
278 }
279 }
280
281 fSavePath = path;
282}
283
284//--------------------------------------------------------------------------
301int PmuppScript::loadCollection(const QString str)
302{
303 QString fln = str;
304 fln = fln.remove("load ");
305 fln = fln.trimmed();
306 fln = fln.prepend(fLoadPath);
307
308 QStringList flnList;
309 flnList << fln;
310
311 QString errorMsg("");
312 if (!fParamDataHandler->ReadParamFile(flnList, errorMsg))
313 return 1;
314
315 return 0;
316}
317
318//--------------------------------------------------------------------------
336int PmuppScript::select(const QString str)
337{
338 QString cmd = str;
339 QStringList tok = cmd.split(' ', Qt::SkipEmptyParts);
340 if (tok.size() != 2) {
341 std::cerr << std::endl << "**ERROR** wrong 'select' command syntax." << std::endl << std::endl;
342 return -1;
343 }
344
345 bool ok;
346 int ival = tok[1].toInt(&ok);
347 if (ok) { // collection index given
348 if (ival >= fParamDataHandler->GetNoOfCollections()) {
349 std::cerr << std::endl << "**ERROR** try to select a collection with index " << ival << ", which is >= # collections (" << fParamDataHandler->GetNoOfCollections() << ")." << std::endl << std::endl;
350 return -2;
351 }
352 fSelected = ival;
353 } else { // assume that a collection name is given
354 ival = fParamDataHandler->GetCollectionIndex(tok[1]);
355 if (ival == -1) {
356 std::cerr << std::endl << "**ERROR** couldn't find collection '" << tok[1].toLatin1().constData() << "'." << std::endl << std::endl;
357 return -3;
358 }
359 if (ival >= fParamDataHandler->GetNoOfCollections()) {
360 std::cerr << std::endl << "**ERROR** try to select a collection with index " << ival << ", which is >= # collections (" << fParamDataHandler->GetNoOfCollections() << ")." << std::endl << std::endl;
361 return -2;
362 }
363 fSelected = ival;
364 }
365
366 return 0;
367}
368
369//--------------------------------------------------------------------------
382{
383 int noColl = fParamDataHandler->GetNoOfCollections();
384 if ( noColl > 0) {
385 fSelected = -1; // all collections are selected
386 } else {
387 std::cerr << std::endl << "**ERROR** no collections present, hence it is not possible to select them." << std::endl << std::endl;
388 return -1;
389 }
390
391 return 0;
392}
393
394//--------------------------------------------------------------------------
420int PmuppScript::addX(const QString str)
421{
422 QString cmd = str, label;
423 QStringList tok = cmd.split(' ', Qt::SkipEmptyParts);
424
425 if (tok.size() != 2) {
426 std::cerr << std::endl << "**ERROR** in addX: number of tokens missmatch." << std::endl << std::endl;
427 return -1;
428 }
429 label = tok[1].trimmed();
430
431 PmuppCollection *coll=0;
432 if (fSelected == -2) { // no selection -> error
433 std::cerr << std::endl << "**ERROR** in addX. addX called without previous 'select' command." << std::endl << std::endl;
434 return -2;
435 } else if (fSelected == -1) { // i.e. select ALL
436 // clean up plot info first
437 fPlotInfo.clear();
438
439 // make sure that label is found in ALL collections, or in variables
440 // first check collections
441 bool foundInColl(true), foundInVar(true);
442 QString collName("");
443 for (int i=0; i<fParamDataHandler->GetNoOfCollections(); i++) {
444 coll = fParamDataHandler->GetCollection(i);
445 if (!foundLabel(coll, label)) { // label not found
446 foundInColl = false;
447 collName = coll->GetName();
448 break;
449 }
450 }
451 // second check variables
452 if (!foundVariable(label)) { // label not found
453 foundInVar = false;
454 }
455 // make sure label(s) have been found
456 if (!foundInColl && !foundInVar) { // not all labels found, neither in collection nor variables.
457 std::cerr << std::endl << "**ERROR** couldn't find '" << label.toLatin1().constData() << "' in collection '" << collName.toLatin1().constData() << "'," << std::endl;
458 std::cerr << " nor is it a defined variable" << std::endl << std::endl;
459 return -4;
460 }
461
462 // resize fPlotInfo to the number of selections
463 fPlotInfo.resize(fParamDataHandler->GetNoOfCollections());
464
465 // feed plot info
466 for (int i=0; i<fPlotInfo.size(); i++) {
467 fPlotInfo[i].collIdx = i;
468 fPlotInfo[i].xLabel = label;
469 }
470 } else { // a specific selection
471 // check that label is found in the selected collection, or in variables
472 coll = fParamDataHandler->GetCollection(fSelected);
473 if (coll == 0) {
474 std::cerr << std::endl << "**ERROR** in addX: selected collection couldn't be found ..." << std::endl << std::endl;
475 return -3;
476 }
477 // first check collection
478 bool foundInColl(true), foundInVar(true);
479 QString collName("");
480 if (!foundLabel(coll, label)) { // label not found
481 foundInColl = false;
482 collName = coll->GetName();
483 }
484 // second check variables
485 if (!foundVariable(label)) { // label not found
486 foundInVar = false;
487 }
488 // make sure label(s) have been found
489 if (!foundInColl && !foundInVar) { // not all labels found, neither in collection nor variables.
490 std::cerr << std::endl << "**ERROR** couldn't find '" << label.toLatin1().constData() << "' in collection '" << collName.toLatin1().constData() << "'," << std::endl;
491 std::cerr << " nor is it a defined variable" << std::endl << std::endl;
492 return -4;
493 }
494
495 // feed plot entry
496 fPlotEntry.collIdx = fSelected;
497 fPlotEntry.xLabel = label;
498 }
499
500 return 0;
501}
502
503//--------------------------------------------------------------------------
533int PmuppScript::addY(const QString str)
534{
535 QString cmd = str;
536 QVector<QString> label;
537 QStringList tok = cmd.split(' ', Qt::SkipEmptyParts);
538
539 if (tok.size() < 2) {
540 std::cerr << std::endl << "**ERROR** in addY: number of tokens < 2." << std::endl << std::endl;
541 return -1;
542 }
543 // collect all potential labels
544 for (int i=1; i<tok.size(); i++)
545 label.push_back(tok[i].trimmed());
546
547 PmuppCollection *coll=0;
548 if (fSelected == -2) { // no selection -> error
549 std::cerr << std::endl << "**ERROR** in addY. addY called without previous 'select' command." << std::endl << std::endl;
550 return -2;
551 } else if (fSelected == -1) { // i.e. select ALL
552 // make sure that label(s) is/are found in ALL collections, or in variables
553 // first check collections
554 bool foundInColl(true), foundInVar(true);
555 int idx = -1;
556 QString collName("");
557 for (int i=0; i<fParamDataHandler->GetNoOfCollections(); i++) {
558 coll = fParamDataHandler->GetCollection(i);
559 for (int j=0; j<label.size(); j++) {
560 if (!foundLabel(coll, label[j])) { // label not found
561 foundInColl = false;
562 collName = coll->GetName();
563 idx = j;
564 break;
565 }
566 }
567 }
568 // second check variables
569 for (int i=0; i<label.size(); i++) {
570 if (!foundVariable(label[i])) { // label not found
571 foundInVar = false;
572 idx = i;
573 break;
574 }
575 }
576 // make sure label(s) have been found
577 if (!foundInColl && !foundInVar) { // not all labels found, neither in collection nor variables.
578 std::cerr << std::endl << "**ERROR** couldn't find '" << label[idx].toLatin1().constData() << "' in collection '" << collName.toLatin1().constData() << "'," << std::endl;
579 std::cerr << " nor is it a defined variable" << std::endl << std::endl;
580 return -4;
581 }
582
583 // feed plot info with y-label(s)
584 for (int i=0; i<fPlotInfo.size(); i++) {
585 fPlotInfo[i].yLabel = label;
586 }
587 } else { // a specific selection
588 // clear yLabel
589 fPlotEntry.yLabel.clear();
590
591 // check that label is found in the selected collection, or in the variables
592 coll = fParamDataHandler->GetCollection(fSelected);
593 if (coll == 0) {
594 std::cerr << std::endl << "**ERROR** in addY: selected collection couldn't be found ..." << std::endl << std::endl;
595 return -3;
596 }
597
598 // first check specific collection
599 bool foundInColl(true), foundInVar(true);
600 int idx = -1;
601 QString collName("");
602 for (int i=0; i<label.size(); i++) {
603 if (!foundLabel(coll, label[i])) { // label not found
604 foundInColl = false;
605 collName = coll->GetName();
606 idx = i;
607 break;
608 }
609 }
610 // second check variables
611 for (int i=0; i<label.size(); i++) {
612 if (!foundVariable(label[i])) { // label not found
613 foundInVar = false;
614 idx = i;
615 break;
616 }
617 }
618 // make sure label(s) have been found
619 if (!foundInColl && !foundInVar) { // not all labels found, neither in collection nor variables.
620 std::cerr << std::endl << "**ERROR** couldn't find '" << label[idx].toLatin1().constData() << "' in collection '" << collName.toLatin1().constData() << "'," << std::endl;
621 std::cerr << " nor is it a defined variable" << std::endl << std::endl;
622 return -4;
623 }
624
625 fPlotEntry.yLabel = label;
626
627 // add plot entry
628 fPlotInfo.push_back(fPlotEntry);
629 }
630
631
632 return 0;
633}
634
635//--------------------------------------------------------------------------
662int PmuppScript::plot(const QString str)
663{
664 QString cmd = str;
665 QStringList tok = cmd.split(' ', Qt::SkipEmptyParts);
666 if (tok.size() != 2) {
667 std::cerr << std::endl << "**ERROR** in plot: number of tokens != 2." << std::endl << std::endl;
668 return -1;
669 }
670 QString flnOut = fSavePath + tok[1];
671 QString macroOut = fSavePath + "__out.C";
672
673 if (macro(QString("macro " + macroOut), flnOut) != 0) {
674 std::cerr << std::endl << "**ERROR** temporary macro generation failed." << std::endl << std::endl;
675 return -1;
676 }
677
678 // call root via batch
679 QProcess *proc = new QProcess(this);
680 if (proc == nullptr) {
681 std::cerr << std::endl << "**ERROR** couldn't invoke root.exe in batch mode." << std::endl << std::endl;
682 return -2;
683 }
684
685 // make sure that the system environment variables are properly set
686 QString exec_cmd = "root.exe";
687 QStringList arg;
688 arg << "-b";
689 arg << macroOut;
690 arg << "-q";
691
692 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
693#if defined(Q_OS_DARWIN)
694 env.insert("DYLD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:/usr/local/lib:" + env.value("DYLD_LIBRARY_PATH"));
695#else
696 env.insert("LD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:" + env.value("LD_LIBRARY_PATH"));
697#endif
698 proc->setProcessEnvironment(env);
699 proc->setWorkingDirectory(fSavePath);
700 proc->start(exec_cmd, arg);
701 if (!proc->waitForStarted()) {
702 std::cerr << std::endl << "**ERROR** Could not execute the output command: " << exec_cmd.toLatin1().constData() << std::endl << std::endl;
703 QFile::remove(macroOut);
704 return -3;
705 }
706 proc->waitForFinished();
707
708 QFile::remove(macroOut);
709
710 return 0;
711}
712
713//--------------------------------------------------------------------------
751int PmuppScript::macro(const QString str, const QString plotFln)
752{
753 QVector<PmuppMarker> marker = fAdmin->getMarkers();
754 QVector<PmuppColor> color = fAdmin->getColors();
755
756 QString cmd = str;
757 QStringList tok = cmd.split(' ', Qt::SkipEmptyParts);
758 if (tok.size() != 2) {
759 std::cerr << std::endl << "**ERROR** macro command with wrong number of arguments (" << tok.size() << ")." << std::endl << std::endl;
760 return -1;
761 }
762 QString macroName = tok[1].trimmed();
763
764 QString fln = fSavePath + macroName;
765 QFile file(fln);
766 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
767 std::cerr << std::endl << "**ERROR** Couldn't open macro file for writting." << std::endl << std::endl;
768 return -2;
769 }
770
771 QTextStream fout(&file);
772
773 // write header
774 fout << "// --------------------------" << Qt::endl;
775 fout << "// " << fln.toLatin1().constData() << Qt::endl;
776 fout << "// " << QDateTime::currentDateTime().toString("yy/MM/dd - HH:mm:ss") << Qt::endl;
777 fout << "// --------------------------" << Qt::endl;
778 fout << "{" << Qt::endl;
779 fout << " gROOT->Reset();" << Qt::endl;
780 fout << Qt::endl;
781 fout << " gStyle->SetOptTitle(0);" << Qt::endl;
782 fout << " gStyle->SetOptDate(0);" << Qt::endl;
783 fout << " gStyle->SetPadColor(TColor::GetColor(255,255,255)); // pad bkg to white" << Qt::endl;
784 fout << " gStyle->SetCanvasColor(TColor::GetColor(255,255,255)); // canvas bkg to white" << Qt::endl;
785 fout << Qt::endl;
786 fout << " Int_t nn=0, i=0;" << Qt::endl;
787 fout << " Double_t xx[512];" << Qt::endl;
788 fout << " Double_t xxPosErr[512];" << Qt::endl;
789 fout << " Double_t xxNegErr[512];" << Qt::endl;
790 fout << " Double_t yy[512];" << Qt::endl;
791 fout << " Double_t yyPosErr[512];" << Qt::endl;
792 fout << " Double_t yyNegErr[512];" << Qt::endl;
793 fout << Qt::endl;
794
795 // write data
796 QVector<double> xx, xxPosErr, xxNegErr, yy, yyPosErr, yyNegErr;
797 QString collName;
798 int count=0;
799 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;
800 double dval, y_min_norm=1.0e10;
801 for (int i=0; i<fPlotInfo.size(); i++) {
802 // get collection name
803 collName = fParamDataHandler->GetCollectionName(i);
804 xx = fParamDataHandler->GetValues(collName, fPlotInfo[i].xLabel);
805 if (xx.size() == 0) { // it is a variable
806 int idx = getVarIndex(fPlotInfo[i].xLabel);
807 if (idx == -1) {
808 std::cerr << std::endl;
809 std::cerr << "**ERROR** Couldn't get x-label '" << fPlotInfo[i].xLabel.toLatin1().data() << "'." << std::endl;
810 std::cerr << " This should never happens." << std::endl;
811 return -3;
812 }
813 std::vector<double> xVal = fVarHandler[idx].getValues();
814 QVector<double> qvec(xVal.begin(), xVal.end());
815 xx = qvec;
816 // use variable errors for x
817 std::vector<double> xErr = fVarHandler[idx].getErrors();
818 QVector<double> qvecE(xErr.begin(), xErr.end());
819 xxPosErr = qvecE;
820 xxNegErr = qvecE;
821 } else {
822 // x-errors from parameter data handler (0.0 if not available)
823 xxPosErr = fParamDataHandler->GetPosErr(collName, fPlotInfo[i].xLabel);
824 if (xxPosErr.size() == 0)
825 xxPosErr = QVector<double>(xx.size(), 0.0);
826 xxNegErr = fParamDataHandler->GetNegErr(collName, fPlotInfo[i].xLabel);
827 if (xxNegErr.size() == 0)
828 xxNegErr = QVector<double>(xx.size(), 0.0);
829 }
830 // get x-axis min/max
831 minMax(xx, x_min, x_max);
832 if (count==0) {
833 x_min_new = x_min;
834 x_max_new = x_max;
835 } else {
836 if (x_min < x_min_new)
837 x_min_new = x_min;
838 if (y_max > x_max_new)
839 x_max_new = x_max;
840 }
841
842 for (int j=0; j<fPlotInfo[i].yLabel.size(); j++) {
843 yy = fParamDataHandler->GetValues(collName, fPlotInfo[i].yLabel[j]);
844 yyPosErr = fParamDataHandler->GetPosErr(collName, fPlotInfo[i].yLabel[j]);
845 yyNegErr = fParamDataHandler->GetNegErr(collName, fPlotInfo[i].yLabel[j]);
846 if (yy.size() == 0) { // it's a variable
847 int idx = getVarIndex(fPlotInfo[i].yLabel[j]);
848 if (idx == -1) {
849 std::cerr << std::endl;
850 std::cerr << "**ERROR** Couldn't get y-label '" << fPlotInfo[i].yLabel[j].toLatin1().data() << "'." << std::endl;
851 std::cerr << " This should never happens." << std::endl;
852 return -3;
853 }
854 std::vector<double> yVal = fVarHandler[idx].getValues();
855 QVector<double> qvecV(yVal.begin(), yVal.end());
856 yy = qvecV;
857 std::vector<double> yErr = fVarHandler[idx].getErrors();
858 QVector<double> qvecE(yErr.begin(), yErr.end());
859 yyPosErr = qvecE;
860 yyNegErr = qvecE;
861 }
862 // get y-axis min/max
863 minMax(yy, y_min, y_max);
864 if (count==0) {
865 y_min_new = y_min;
866 y_max_new = y_max;
867 } else {
868 if (y_min < y_min_new)
869 y_min_new = y_min;
870 if (y_max > y_max_new)
871 y_max_new = y_max;
872 }
873 fout << " // " << ++count << ". data set" << Qt::endl;
874 fout << " nn = " << xx.size() << ";" << Qt::endl;
875 fout << " // x-values" << Qt::endl;
876 for (int k=0; k<xx.size(); k++) {
877 fout << " xx[" << k << "]=" << xx[k] << ";" << Qt::endl;
878 }
879 fout << " // xxPosErr-values" << Qt::endl;
880 for (int k=0; k<xxPosErr.size(); k++) {
881 fout << " xxPosErr[" << k << "]=" << fabs(xxPosErr[k]) << ";" << Qt::endl;
882 }
883 fout << " // xxNegErr-values" << Qt::endl;
884 for (int k=0; k<xxNegErr.size(); k++) {
885 fout << " xxNegErr[" << k << "]=" << fabs(xxNegErr[k]) << ";" << Qt::endl;
886 }
887 fout << " // y-values" << Qt::endl;
888 for (int k=0; k<yy.size(); k++) {
889 dval = yy[k];
890 if (fNorm) {
891 dval /= y_max;
892 if (dval < y_min_norm)
893 y_min_norm = dval;
894 }
895 fout << " yy[" << k << "]=" << dval << ";" << Qt::endl;
896 }
897 fout << " // yyNegErr-values" << Qt::endl;
898 for (int k=0; k<yyNegErr.size(); k++) {
899 dval = fabs(yyNegErr[k]);
900 if (fNorm)
901 dval /= fabs(y_max);
902 fout << " yyNegErr[" << k << "]=" << dval << ";" << Qt::endl;
903 }
904 fout << " // yyPosErr-values" << Qt::endl;
905 for (int k=0; k<yyPosErr.size(); k++) {
906 dval = fabs(yyPosErr[k]);
907 if (fNorm)
908 dval /= fabs(y_max);
909 fout << " yyPosErr[" << k << "]=" << dval << ";" << Qt::endl;
910 }
911 fout << Qt::endl;
912 fout << " TGraphAsymmErrors *g_" << i << "_" << j << " = new TGraphAsymmErrors(nn, xx, yy, xxNegErr, xxPosErr, yyNegErr, yyPosErr);" << Qt::endl;
913 fout << Qt::endl;
914 }
915 }
916
917 // x,y-min/max range
918 double diff;
919 if (x_min_new > 0.0)
920 x_min = 0.0;
921 else
922 x_min = x_min_new;
923 diff = x_max-x_min;
924 x_max = x_max_new + 0.05*diff;
925 diff = y_max_new - y_min_new;
926 y_min = y_min_new - 0.05 * diff;
927 y_max = y_max_new + 0.05 * diff;
928 if (fNorm) {
929 diff = 1.0 - y_min_norm;
930 y_min = y_min_norm - 0.05 * diff;
931 y_max = 1.0 + 0.05 * diff;
932 }
933
934 // plotting
935 fout << " //**********" << Qt::endl;
936 fout << " // plotting " << Qt::endl;
937 fout << " //**********" << Qt::endl;
938 fout << " TCanvas *c1 = new TCanvas(\"c1\", \"" << macroName.toLatin1().constData() << "\", 10, 10, 600, 700);" << Qt::endl;
939 fout << Qt::endl;
940
941 count = 0;
942 int rr, gg, bb;
943 for (int i=0; i<fPlotInfo.size(); i++) {
944 for (int j=0; j<fPlotInfo[i].yLabel.size(); j++) {
945 if (count == 0) {
946 if (count < marker.size()) {
947 fout << " g_" << i << "_" << j << "->SetMarkerStyle(" << marker[count].getMarker() << ");" << Qt::endl;
948 fout << " g_" << i << "_" << j << "->SetMarkerSize(" << marker[count].getMarkerSize() << ");" << Qt::endl;
949 color[count].getRGB(rr, gg, bb);
950 fout << " g_" << i << "_" << j << "->SetMarkerColor(TColor::GetColor(" << rr << "," << gg << "," << bb << "));" << Qt::endl;
951 fout << " g_" << i << "_" << j << "->SetLineColor(TColor::GetColor(" << rr << "," << gg << "," << bb << "));" << Qt::endl;
952 } else {
953 fout << " g_" << i << "_" << j << "->SetMarkerStyle(20);" << Qt::endl;
954 fout << " g_" << i << "_" << j << "->SetMarkerSize(1.3);" << Qt::endl;
955 fout << " g_" << i << "_" << j << "->SetMarkerColor(TColor::GetColor(0,0,0));" << Qt::endl;
956 fout << " g_" << i << "_" << j << "->SetLineColor(TColor::GetColor(0,0,0));" << Qt::endl;
957 }
958 fout << " g_" << i << "_" << j << "->SetFillColor(kWhite);" << Qt::endl;
959 fout << " g_" << i << "_" << j << "->GetXaxis()->SetTitle(\"" << getNicerLabel(fPlotInfo[0].xLabel).toLatin1().data() << "\");" << Qt::endl;
960 fout << " g_" << i << "_" << j << "->GetXaxis()->SetTitleSize(0.05);" << Qt::endl;
961 fout << " g_" << i << "_" << j << "->GetXaxis()->SetDecimals(kTRUE);" << Qt::endl;
962 fout << " g_" << i << "_" << j << "->GetXaxis()->SetLimits(" << x_min << "," << x_max << ");" << Qt::endl;
963 fout << " g_" << i << "_" << j << "->GetYaxis()->SetTitle(\"" << getNicerLabel(fPlotInfo[0].yLabel[0]).toLatin1().data() << "\");" << Qt::endl;
964 fout << " g_" << i << "_" << j << "->GetYaxis()->SetTitleSize(0.05);" << Qt::endl;
965 fout << " g_" << i << "_" << j << "->GetYaxis()->SetTitleOffset(1.30);" << Qt::endl;
966 fout << " g_" << i << "_" << j << "->GetYaxis()->SetRangeUser(" << y_min << "," << y_max << ");" << Qt::endl;
967 fout << " g_" << i << "_" << j << "->Draw(\"AP\");" << Qt::endl;
968 } else {
969 if (count < marker.size()) {
970 fout << " g_" << i << "_" << j << "->SetMarkerStyle(" << marker[count].getMarker() << ");" << Qt::endl;
971 fout << " g_" << i << "_" << j << "->SetMarkerSize(" << marker[count].getMarkerSize() << ");" << Qt::endl;
972 color[count].getRGB(rr, gg, bb);
973 fout << " g_" << i << "_" << j << "->SetMarkerColor(TColor::GetColor(" << rr << "," << gg << "," << bb << "));" << Qt::endl;
974 fout << " g_" << i << "_" << j << "->SetLineColor(TColor::GetColor(" << rr << "," << gg << "," << bb << "));" << Qt::endl;
975 } else {
976 fout << " g_" << i << "_" << j << "->SetMarkerStyle(20);" << Qt::endl;
977 fout << " g_" << i << "_" << j << "->SetMarkerSize(1.3);" << Qt::endl;
978 fout << " g_" << i << "_" << j << "->SetMarkerColor(TColor::GetColor(0,0,0));" << Qt::endl;
979 fout << " g_" << i << "_" << j << "->SetLineColor(TColor::GetColor(0,0,0));" << Qt::endl;
980 }
981 fout << " g_" << i << "_" << j << "->SetFillColor(kWhite);" << Qt::endl;
982 fout << " g_" << i << "_" << j << "->Draw(\"Psame\");" << Qt::endl;
983 }
984 count++;
985 }
986 }
987 fout << " c1->SetMargin(0.15, 0.05, 0.12, 0.05);" << Qt::endl;
988 fout << " c1->Update();" << Qt::endl;
989 if (!plotFln.isEmpty()) {
990 fout << Qt::endl;
991 fout << " c1->SaveAs(\"" << plotFln.toLatin1().constData() << "\");" << Qt::endl;
992 }
993 fout << "}" << Qt::endl;
994
995 return 0;
996}
997
998//--------------------------------------------------------------------------
1030int PmuppScript::var_cmd(const QString str, int script_idx)
1031{
1032 QStringList tok;
1033 int idx=0;
1034
1035 // get linked collection index for further use
1036 tok = str.split(' ', Qt::SkipEmptyParts);
1037 if (tok[1].endsWith("Err")) // error variable no need to do something
1038 return 0;
1039 idx = getCollectionIndex(tok[1]);
1040 if (idx == -1) // var not linked to collection, ignore it
1041 return 0;
1042
1043 // python-mode variable: 'var <name> = python' means the value/error are
1044 // computed in a <python> ... </python> block elsewhere in the script.
1045 if (tok.last() == "python") {
1046 // pair this declaration with the next <python> block in the script, so
1047 // multiple python-defined variables can coexist.
1048 QString pyBlock = getPythonBlock(script_idx);
1049 if (pyBlock.isEmpty()) {
1050 std::cerr << "**ERROR** variable '" << tok[1].toLatin1().data()
1051 << "' declared as python, but no <python> ... </python> block was found." << std::endl;
1052 return 1;
1053 }
1054 // expose every loaded collection inside the <python> block (coll[]/collErr[]),
1055 // addressable by index and by name, so one block can serve several collections.
1056 std::vector<PmuppCollection*> allColl;
1057 for (int i=0; i<fParamDataHandler->GetNoOfCollections(); i++)
1058 allColl.push_back(fParamDataHandler->GetCollection(i));
1059 PVarHandler varHandler(fParamDataHandler->GetCollection(idx),
1060 pyBlock.toLatin1().data(), tok[1].toLatin1().data(), allColl);
1061 if (!varHandler.isValid()) {
1062 // dump error messages if present
1063 QString mupp_err = QString("%1/.musrfit/mupp/mupp_err.log").arg(QString(qgetenv("HOME")));
1064 QFile fout(mupp_err);
1065 if (fout.open(QIODevice::ReadOnly | QIODevice::Text)) {
1066 QString msg;
1067 while (!fout.atEnd()) {
1068 msg = fout.readLine();
1069 std::cerr << msg.toLatin1().data();
1070 }
1071 QFile::remove(mupp_err);
1072 }
1073 return 1;
1074 }
1075 fVarHandler.push_back(varHandler);
1076 return 0;
1077 }
1078
1079 // check if the related error variable is present
1080 QString varErr = QString("%1%2").arg(tok[1]).arg("Err");
1081 QString varErrCmd("");
1082 for (int i=0; i<fScript.size(); i++) {
1083 if (fScript.at(i).contains(varErr, Qt::CaseSensitive)) {
1084 varErrCmd = fScript.at(i);
1085 break;
1086 }
1087 }
1088
1089 std::string parse_str = str.toLatin1().data();
1090 if (!varErrCmd.isEmpty()) {
1091 parse_str += "\n";
1092 parse_str += varErrCmd.toLatin1().data();
1093 }
1094
1095 PVarHandler varHandler(fParamDataHandler->GetCollection(idx), parse_str, tok[1].toLatin1().data());
1096 if (!varHandler.isValid()) {
1097 // deal with errors
1098 QString mupp_err = QString("%1/.musrfit/mupp/mupp_err.log").arg(QString(qgetenv("HOME")));
1099
1100 // dump error messages if present
1101 QFile fout(mupp_err);
1102 if (fout.open(QIODevice::ReadOnly | QIODevice::Text)) {
1103 QString msg;
1104 while (!fout.atEnd()) {
1105 msg = fout.readLine();
1106 std::cerr << msg.toLatin1().data();
1107 }
1108 // delete potentially present mupp_err.log file
1109 QFile::remove(mupp_err);
1110 }
1111 return 1;
1112 }
1113 fVarHandler.push_back(varHandler);
1114
1115 return 0;
1116}
1117
1118//--------------------------------------------------------------------------
1131bool PmuppScript::foundLabel(PmuppCollection *coll, const QString label)
1132{
1133 bool result = false;
1134 for (int i=0; i<coll->GetRun(0).GetNoOfParam(); i++) {
1135 if (!coll->GetRun(0).GetParam(i).GetName().compare(label)) {
1136 result = true;
1137 break;
1138 }
1139 }
1140
1141 return result;
1142}
1143
1144//--------------------------------------------------------------------------
1156bool PmuppScript::foundVariable(const QString var)
1157{
1158 bool result = false;
1159 for (int i=0; i<fVarHandler.size(); i++) {
1160 if (!fVarHandler[i].getVarName().compare(var)) {
1161 result = true;
1162 break;
1163 }
1164 }
1165
1166 return result;
1167}
1168
1169//--------------------------------------------------------------------------
1181int PmuppScript::getVarIndex(const QString var)
1182{
1183 int idx = -1;
1184 for (int i=0; i<fVarHandler.size(); i++) {
1185 if (!fVarHandler[i].getVarName().compare(var)) {
1186 idx = i;
1187 break;
1188 }
1189 }
1190
1191 return idx;
1192}
1193
1194//--------------------------------------------------------------------------
1205void PmuppScript::minMax(QVector<double> dvec, double &min, double &max)
1206{
1207 min = 99.0e6;
1208 max = -99.0e6;
1209 for (int i=0; i<dvec.size(); i++) {
1210 if (dvec[i] < min)
1211 min = dvec[i];
1212 if (dvec[i] > max)
1213 max = dvec[i];
1214 }
1215}
1216
1217//--------------------------------------------------------------------------
1243QString PmuppScript::getNicerLabel(const QString label)
1244{
1245 QString nice = label;
1246
1247 if (label == "dataE") {
1248 nice = "E (keV)";
1249 } else if (label == "dataT") {
1250 nice = "T (K)";
1251 } else if (label == "dataB") {
1252 nice = "B (G)";
1253 } else if (!label.compare("sigma", Qt::CaseInsensitive)) {
1254 if (fNorm)
1255 nice = "#sigma/max(#sigma)";
1256 else
1257 nice = "#sigma (1/#mus)";
1258 } else if (!label.compare("lambda", Qt::CaseInsensitive)) {
1259 if (fNorm)
1260 nice = "#lambda/max(#lambda)";
1261 else
1262 nice = "#lambda (1/#mus)";
1263 } else if (!label.compare("rate", Qt::CaseInsensitive)) {
1264 if (fNorm)
1265 nice = "Rate/max(Rate)";
1266 else
1267 nice = "Rate (1/#mus)";
1268 } else if (!label.compare("alpha_LR", Qt::CaseInsensitive)) {
1269 if (fNorm)
1270 nice = "#alpha_{LR}/max(#alpha_{LR})";
1271 else
1272 nice = "#alpha_{LR}";
1273 } else if (!label.compare("alpha_TB", Qt::CaseInsensitive)) {
1274 if (fNorm)
1275 nice = "#alpha_{TB}/max(#alpha_{TB})";
1276 else
1277 nice = "#alpha_{TB}";
1278 } else {
1279 if (fNorm) {
1280 nice = label + "/ max(" + label + ")";
1281 }
1282 }
1283
1284 return nice;
1285}
1286
1287//--------------------------------------------------------------------------
1302QString PmuppScript::getPythonBlock(int start_idx)
1303{
1304 for (int i=start_idx+1; i<fScript.size(); i++) {
1305 if (fScript.at(i).startsWith("<python>"))
1306 return fScript.at(i);
1307 }
1308 return QString();
1309}
1310
1311//--------------------------------------------------------------------------
1322int PmuppScript::getCollectionIndex(const QString var_name)
1323{
1324 int idx = -1;
1325 QString cmd;
1326 QStringList tok;
1327 bool ok;
1328
1329 for (int i=0; i<fScript.size(); i++) {
1330 cmd = fScript.at(i);
1331 if (cmd.startsWith("col")) {
1332 tok.clear();
1333 tok = cmd.split(' ', Qt::SkipEmptyParts);
1334 if (tok[3] == var_name) {
1335 idx = tok[1].toInt(&ok);
1336 if (!ok) {
1337 Q_ASSERT(0);
1338 }
1339 break;
1340 }
1341 }
1342 }
1343
1344 return idx;
1345}
Scripting interface for mupp batch processing.
The PVarHandler class handles variable parsing, evaluation, and data management.
Definition PVarHandler.h:69
bool isValid()
Checks if the parsing and evaluation were successful.
Represents a collection of related experimental runs.
Definition Pmupp.h:234
PmuppRun GetRun(unsigned int idx)
Retrieves a run from a collection by index.
Definition Pmupp.cpp:204
QString GetName()
Gets the collection name.
Definition Pmupp.h:269
QString GetName()
Gets the parameter name.
Definition Pmupp.h:118
PmuppParam GetParam(unsigned int idx)
Retrieves a parameter from a run by index.
Definition Pmupp.cpp:184
PmuppPlotEntry fPlotEntry
single plot configuration (for specific selection)
QString fSavePath
directory path for saving output files
void setSavePath(const QString cmd)
Sets the save path for output files.
int getCollectionIndex(const QString var_name)
Gets the collection index associated with a variable.
QVector< PmuppPlotEntry > fPlotInfo
vector of all plot configurations (for all selections)
int select(const QString str)
Selects a specific collection for plotting.
int fSelected
selection state: -2=none, -1=all, >=0=specific index
QString getPythonBlock(int start_idx=-1)
Returns the verbatim <python> ... </python> block of the script.
int addX(const QString str)
Adds a parameter to the X-axis.
std::unique_ptr< PmuppAdmin > fAdmin
administration object for configuration
QString fLoadPath
directory path for loading input data files
PmuppScript(QStringList script)
Constructor. Initializes the script interpreter.
QString getNicerLabel(const QString label)
Converts parameter labels to prettier ROOT format.
int addY(const QString str)
Adds one or more parameters to the Y-axis.
void minMax(QVector< double > dvec, double &min, double &max)
Finds minimum and maximum values in a data vector.
void setLoadPath(const QString cmd)
Sets the load path for input data files.
int macro(const QString str, const QString plotFln="")
Generates a ROOT macro for plotting.
int executeScript()
Executes all script commands sequentially.
int plot(const QString str)
Creates a plot file by generating and executing a ROOT macro.
QVector< PVarHandler > fVarHandler
vector of variable expression handlers
int selectAll()
Selects all loaded collections for plotting.
int var_cmd(const QString str, int script_idx=-1)
Processes a variable definition command.
QStringList fScript
list of script commands to execute
bool foundLabel(PmuppCollection *coll, const QString label)
Checks if a parameter label exists in a collection.
int loadCollection(const QString str)
Loads a data collection from file.
void finished()
Signal emitted when script execution completes.
int getVarIndex(const QString var)
Gets the index of a variable in the handler vector.
std::unique_ptr< PParamDataHandler > fParamDataHandler
handler for parameter data collections
bool foundVariable(const QString var)
Checks if a variable is defined in the variable handler.
bool fNorm
normalization flag (true = normalize Y-data to max value)