mupp 1.1.0
Loading...
Searching...
No Matches
mupp.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 mupp.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
48
49#include <iostream>
50
51#include <QObject>
52#include <QScopedPointer>
53#include <QApplication>
54#include <QCoreApplication>
55#include <QFile>
56#include <QString>
57#include <QStringList>
58#include <QVector>
59#include <QTextStream>
60#include <QTimer>
61
62#include "mupp_version.h"
63#ifdef HAVE_GIT_REV_H
64#include "git-revision.h"
65#endif
66#include "PmuppScript.h"
67#include "PmuppGui.h"
68
69//------------------------------------------------------------------------
81{
82 std::cout << std::endl;
83 std::cout << "SCRIPT COMMANDS:" << std::endl;
84 std::cout << " Lines starting with '#', '%', or '//' are comments and will be ignored." << std::endl;
85 std::cout << " The same is true for empty lines. Comments are also allowed at the end" << std::endl;
86 std::cout << " for a command, i.e. loadPath ./ # the best place ever." << std::endl;
87 std::cout << std::endl;
88 std::cout << " load <coll> : load a collection. <coll> is the filename of the" << std::endl;
89 std::cout << " collection (*.db, *.dat)" << std::endl;
90 std::cout << " loadPath <path> : set the load path to <path>; accepting bash variables" << std::endl;
91 std::cout << " like $HOME, etc." << std::endl;
92 std::cout << " x <var-name> : set a x-axis variable. <var-name> is a data tag of" << std::endl;
93 std::cout << " the db/dat-file." << std::endl;
94 std::cout << " y <var-name> : set a y-axis variable. <var-name> is a data tag of" << std::endl;
95 std::cout << " the db/dat-file." << std::endl;
96 std::cout << " select <nn> : select collection <nn>, where <nn> is the row-number" << std::endl;
97 std::cout << " or the name of the collection to be selected." << std::endl;
98 std::cout << " selectAll : i.e. already set addX, addY will apply to ALL collections" << std::endl;
99 std::cout << " present." << std::endl;
100 std::cout << " savePath <path> : sets the save path to <path>; accepting bash variables" << std::endl;
101 std::cout << " like $HOME, etc." << std::endl;
102 std::cout << " plot <fln> : where <fln> is the file name with extension under which" << std::endl;
103 std::cout << " the plot should be saved." << std::endl;
104 std::cout << " macro <fln> : where <fln> is the file name under which the root macro" << std::endl;
105 std::cout << " should be saved." << std::endl;
106 std::cout << " var <var_name> = <expr> : defines a variable." << std::endl;
107 std::cout << " <expr> is a mathematical expression where" << std::endl;
108 std::cout << " collection variables are addressed via the '$'," << std::endl;
109 std::cout << " e.g. dataT is addressed by $dataT, etc." << std::endl;
110 std::cout << " var <var_name> = python : the variable is computed in a python block" << std::endl;
111 std::cout << " <python> ... </python> given later in the script." << std::endl;
112 std::cout << " Inside the block, collection parameters are bare" << std::endl;
113 std::cout << " names (e.g. Sigma, SigmaErr); the block must assign" << std::endl;
114 std::cout << " <var_name> and <var_name>Err. Requires ROOT built" << std::endl;
115 std::cout << " with -Dtpython=ON." << std::endl;
116 std::cout << " col <nn> : <var_name> : links <var_name> to the collection <nn>, where" << std::endl;
117 std::cout << " <nn> is the number of the collection as defined" << std::endl;
118 std::cout << " by the order of load, starting with 0." << std::endl;
119 std::cout << std::endl;
120}
121
122//------------------------------------------------------------------------
138{
139 std::cout << std::endl;
140 std::cout << "usage: mupp [OPTIONS] [[--path <fit-param-path>] <fit-param-file-names>]" << std::endl;
141 std::cout << std::endl;
142 std::cout << "OPTIONS:" << std::endl;
143 std::cout << " -h, --help: this help" << std::endl;
144 std::cout << " -v, --version: current mupp version" << std::endl;
145 std::cout << " -s <fln>, --script <fln>: <fln> being a mupp script." << std::endl;
146 std::cout << " --path <fit-param-path>: path where to look for the <fit-param-file-names>" << std::endl;
147 std::cout << " <fit-param-file-names>: list of file name(s) to be loaded." << std::endl;
148 std::cout << " allowed formats are: db, dat, msr" << std::endl << std::endl;
150}
151
152//------------------------------------------------------------------------
170int mupp_script_read(const char *fln, QStringList &list)
171{
172 QFile file(fln);
173 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
174 std::cerr << std::endl;
175 std::cerr << "*********" << std::endl;
176 std::cerr << "**ERROR** couldn't open '" << fln << "'." << std::endl;
177 std::cerr << "*********" << std::endl;
178 return -1;
179 }
180
181 QTextStream fin(&file);
182 QString line;
183 int pos;
184 bool inPython = false; // true while reading a <python> ... </python> block
185 QString pyBlock;
186 while (!fin.atEnd()) {
187 line = fin.readLine();
188
189 // a <python> ... </python> block is read verbatim (indentation and the
190 // characters #, %, // are significant in python) and stored as a single
191 // list entry, so that the normal command processing below is bypassed.
192 if (!inPython && line.trimmed().startsWith("<python>")) {
193 inPython = true;
194 pyBlock = line + "\n";
195 continue;
196 }
197 if (inPython) {
198 pyBlock += line + "\n";
199 if (line.trimmed() == "</python>") {
200 list << pyBlock;
201 pyBlock.clear();
202 inPython = false;
203 }
204 continue;
205 }
206
207 line = line.simplified();
208 if (line.isEmpty())
209 continue;
210 if (line.startsWith("#") || line.startsWith("%") || line.startsWith("//"))
211 continue;
212 // remove all potentially present trailing comments
213 pos = line.indexOf("#");
214 if (pos != -1)
215 line.remove(pos, line.length()-pos);
216 pos = line.indexOf("%");
217 if (pos != -1)
218 line.remove(pos, line.length()-pos);
219 pos = line.indexOf("//");
220 if (pos != -1)
221 line.remove(pos, line.length()-pos);
222 line = line.simplified();
223 // feed script list
224 list << line;
225 }
226 if (inPython) {
227 std::cerr << std::endl;
228 std::cerr << "*********" << std::endl;
229 std::cerr << "**ERROR** <python> block not terminated with </python> in '" << fln << "'." << std::endl;
230 std::cerr << "*********" << std::endl;
231 return -1;
232 }
233
234 return 0;
235}
236
237//------------------------------------------------------------------------
251bool mupp_bash_variable_exists(const QString str)
252{
253 QString var = str;
254 var.remove("$");
255
256 QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment();
257 QString varExpanded = procEnv.value(var, "");
258 if (!varExpanded.isEmpty())
259 return true;
260
261 return false;
262}
263
264//------------------------------------------------------------------------
291int mupp_script_syntax_check(QStringList &list)
292{
293 QString str;
294 QStringList tok;
295 QVector<QString> var_names;
296 QVector<bool> var_linked;
297 int noOfCollections = 0;
298 for (int i=0; i<list.size(); i++) {
299 tok.clear();
300 str = list.at(i);
301 if (str.startsWith("loadPath")) {
302 tok = str.split(' ', Qt::SkipEmptyParts);
303 if (tok.size() < 2) {
304 std::cerr << std::endl;
305 std::cerr << "****************" << std::endl;
306 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'. <path> is missing." << std::endl;
307 std::cerr << "****************" << std::endl;
308 return -1;
309 }
310 tok.clear();
311
312 // check if bash variables are present, and if yes try to resolve them making sure they or NOT empty.
313 str = str.remove("loadPath ");
314 tok = str.split('/');
315 for (int i=0; i<tok.size(); i++) {
316 if (tok.at(i).startsWith("$")) {
317 if (!mupp_bash_variable_exists(tok.at(i))) {
318 std::cerr << std::endl;
319 std::cerr << "****************" << std::endl;
320 std::cerr << "**SYNTAX ERROR** found in command '" << list.at(i).toLatin1().constData() << "' an empty bash variable '" << tok.at(i).toLatin1().constData() << "'." << std::endl;
321 std::cerr << "****************" << std::endl;
322 return -2;
323 }
324 }
325 }
326 } else if (str.startsWith("load")) {
327 tok = str.split(' ', Qt::SkipEmptyParts);
328 if (tok.size() < 2) {
329 std::cerr << std::endl;
330 std::cerr << "****************" << std::endl;
331 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'. At least one collection file name is expected." << std::endl;
332 std::cerr << "****************" << std::endl;
333 return -1;
334 }
335 noOfCollections++;
336 } else if (str.startsWith("x")) {
337 tok = str.split(' ', Qt::SkipEmptyParts);
338 if (tok.size() != 2) {
339 std::cerr << std::endl;
340 std::cerr << "****************" << std::endl;
341 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'. Only one variable name is accepted." << std::endl;
342 std::cerr << "****************" << std::endl;
343 return -1;
344 }
345 } else if (str.startsWith("y")) {
346 tok = str.split(' ', Qt::SkipEmptyParts);
347 if (tok.size() < 2) {
348 std::cerr << std::endl;
349 std::cerr << "****************" << std::endl;
350 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'. At least one variable name is needed." << std::endl;
351 std::cerr << "****************" << std::endl;
352 return -1;
353 }
354 } else if (str.startsWith("select ")) {
355 tok = str.split(' ', Qt::SkipEmptyParts);
356 if (tok.size() != 2) {
357 std::cerr << std::endl;
358 std::cerr << "****************" << std::endl;
359 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'. Only one row-number of collection name is accepted." << std::endl;
360 std::cerr << "****************" << std::endl;
361 return -1;
362 }
363 } else if (str.startsWith("selectAll")) {
364 if (str.compare("selectAll")) {
365 std::cerr << std::endl;
366 std::cerr << "****************" << std::endl;
367 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'. selectAll doesn't accept any options." << std::endl;
368 std::cerr << "****************" << std::endl;
369 return -1;
370 }
371 } else if (str.startsWith("savePath")) {
372 tok = str.split(' ', Qt::SkipEmptyParts);
373 if (tok.size() != 2) {
374 std::cerr << std::endl;
375 std::cerr << "****************" << std::endl;
376 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'. Only one save path is accepted." << std::endl;
377 std::cerr << "****************" << std::endl;
378 return -1;
379 }
380 } else if (str.startsWith("plot")) {
381 tok = str.split(' ', Qt::SkipEmptyParts);
382 if (tok.size() != 2) {
383 std::cerr << std::endl;
384 std::cerr << "****************" << std::endl;
385 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'. Only one file name is accepted." << std::endl;
386 std::cerr << "****************" << std::endl;
387 return -1;
388 }
389 // check extension
390 tok.clear();
391 tok = str.split('.', Qt::SkipEmptyParts);
392 QString ext = tok.at(tok.size()-1);
393 ext = ext.toLower();
394 if ((ext != "pdf") && (ext != "jpg") && (ext != "png") && (ext != "svg") && (ext != "gif")) {
395 std::cerr << std::endl;
396 std::cerr << "****************" << std::endl;
397 std::cerr << "**SYNTAX ERROR** found extension " << ext.toLatin1().constData() << " in '" << str.toLatin1().constData() << "' which is not supported." << std::endl;
398 std::cerr << " Currently only: pdf, jpg, png, svg, and gif are supported." << std::endl;
399 std::cerr << "****************" << std::endl;
400 return -2;
401 }
402 } else if (str.startsWith("macro")) {
403 tok = str.split(' ', Qt::SkipEmptyParts);
404 if (tok.size() != 2) {
405 std::cerr << std::endl;
406 std::cerr << "****************" << std::endl;
407 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'. Only one file name is accepted." << std::endl;
408 std::cerr << "****************" << std::endl;
409 return -1;
410 }
411 // check extension
412 tok.clear();
413 tok = str.split('.', Qt::SkipEmptyParts);
414 QString ext = tok.at(tok.size()-1);
415 ext = ext.toLower();
416 if (ext != "c") {
417 std::cerr << std::endl;
418 std::cerr << "****************" << std::endl;
419 std::cerr << "**SYNTAX ERROR** found extension " << ext.toLatin1().constData() << " in '" << str.toLatin1().constData() << "' which is not supported." << std::endl;
420 std::cerr << " Currently only: C are supported." << std::endl;
421 std::cerr << "****************" << std::endl;
422 return -2;
423 }
424 } else if (str.startsWith("norm")) {
425 // nothing-to-be-done
426 } else if (str.startsWith("var")) {
427 tok.clear();
428 tok = str.split(' ', Qt::SkipEmptyParts);
429 if (tok.size() < 2) {
430 std::cerr << std::endl;
431 std::cerr << "****************" << std::endl;
432 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'." << std::endl;
433 std::cerr << " Illegal variable definition." << std::endl;
434 std::cerr << "****************" << std::endl;
435 return -1;
436 }
437 // keep var name for later use
438 var_names.push_back(tok[1]);
439 var_linked.push_back(false);
440 // the parsing etc is dealt within the scripting class
441 } else if (str.startsWith("col")) {
442 tok.clear();
443 tok = str.split(' ', Qt::SkipEmptyParts);
444 if (tok.size() != 4) {
445 std::cerr << std::endl;
446 std::cerr << "****************" << std::endl;
447 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'. Syntax for variable collection linking is:" << std::endl;
448 std::cerr << " col <nn> : <var_name>. Where <nn> is the collection index, and <var_name> the variable name to be linked." << std::endl;
449 std::cerr << "****************" << std::endl;
450 return -1;
451 }
452 if (tok[2] != ":") {
453 std::cerr << std::endl;
454 std::cerr << "****************" << std::endl;
455 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'. Syntax for variable collection linking is:" << std::endl;
456 std::cerr << " col <nn> : <var_name>. Where <nn> is the collection index, and <var_name> the variable name to be linked." << std::endl;
457 std::cerr << "****************" << std::endl;
458 return -2;
459 }
460 // will check that the to be linked variable and the target collection exists
461 // first check that the collection exists
462 bool ok;
463 int idx = tok[1].toInt(&ok);
464 if (!ok) {
465 std::cerr << std::endl;
466 std::cerr << "****************" << std::endl;
467 std::cerr << "**SYNTAX ERROR** found '" << str.toLatin1().constData() << "'. Syntax for variable collection linking is:" << std::endl;
468 std::cerr << " col <nn> : <var_name>. Where <nn> is the collection index, and <var_name> the variable name to be linked." << std::endl;
469 std::cerr << " collection index is not a number here!" << std::endl;
470 std::cerr << "****************" << std::endl;
471 return -2;
472 }
473 if (idx >= noOfCollections) {
474 std::cerr << std::endl;
475 std::cerr << "****************" << std::endl;
476 std::cerr << "**SYNTAX ERROR** in '" << str.toLatin1().constData() << "'." << std::endl;
477 std::cerr << " Requested collection '" << idx << "' is out-of-range." << std::endl;
478 std::cerr << " Only " << noOfCollections << " or present." << std::endl;
479 std::cerr << " Collection indexing starts at 0, not 1." << std::endl;
480 std::cerr << "****************" << std::endl;
481 return -3;
482 }
483 // make sure that the variable to be linked has been defined and is NOT an error variable.
484 if (tok[3].endsWith("Err")) {
485 std::cerr << std::endl;
486 std::cerr << "****************" << std::endl;
487 std::cerr << "**SYNTAX ERROR** in '" << str.toLatin1().constData() << "'." << std::endl;
488 std::cerr << " Only variables can be linked, NOT error variables." << std::endl;
489 std::cerr << " Error variables are linked implicitly." << std::endl;
490 std::cerr << "****************" << std::endl;
491 return -4;
492 }
493 idx = -1;
494 for (unsigned int i=0; i<var_names.size(); i++) {
495 if (tok[3] == var_names[i]) {
496 idx = i;
497 break;
498 }
499 }
500 if (idx == -1) {
501 std::cerr << std::endl;
502 std::cerr << "****************" << std::endl;
503 std::cerr << "**SYNTAX ERROR** in '" << str.toLatin1().constData() << "'." << std::endl;
504 std::cerr << " Variable to be linked not defined yet." << std::endl;
505 std::cerr << "****************" << std::endl;
506 return -5;
507 }
508 var_linked[idx] = true;
509 } else if (str.startsWith("<python>")) {
510 // a python block is evaluated through the linked 'var ... = python'
511 // declarations; nothing to validate here.
512 } else {
513 std::cerr << "*********" << std::endl;
514 std::cerr << "**ERROR** found unrecognized script command: '" << str.toLatin1().constData() << "'." << std::endl;
515 std::cerr << "*********" << std::endl;
517 return -3;
518 }
519 }
520 if (noOfCollections == -1) {
521 std::cerr << "****************" << std::endl;
522 std::cerr << "**SYNTAX ERROR** no data loaded." << std::endl;
523 std::cerr << "****************" << std::endl;
525 return -4;
526 }
527 if (var_names.size() != var_linked.size()) {
528 std::cerr << "****************" << std::endl;
529 std::cerr << "**SYNTAX ERROR**" << std::endl;
530 std::cerr << "****************" << std::endl;
531 std::cerr << "** Your never should have reached this point **" << std::endl;
532 std::cerr << "****************" << std::endl;
533 return -4;
534 }
535 for (int i=0; i<var_names.size(); i++) {
536 if (!var_names[i].endsWith("Err") && !var_linked[i]) {
537 std::cerr << "****************" << std::endl;
538 std::cerr << "** WARNING **" << std::endl;
539 std::cerr << "****************" << std::endl;
540 std::cerr << " Found unlinked variable : " << var_names[i].toLatin1().constData() << std::endl;
541 std::cerr << "****************" << std::endl;
542 }
543 }
544
545 return 0;
546}
547
548//------------------------------------------------------------------------
567QCoreApplication* createApplication(int &argc, char *argv[], bool gui)
568{
569 if (gui)
570 return new QApplication(argc, argv);
571 else
572 return new QCoreApplication(argc, argv);
573}
574
575//------------------------------------------------------------------------
611int main(int argc, char *argv[])
612{
613 Q_INIT_RESOURCE(mupp);
614
615 QStringList fln;
616 QStringList script;
617
618 if (argc > 1) {
619 if (!qstrcmp(argv[1], "-h") || !qstrcmp(argv[1], "--help")) {
620 mupp_syntax();
621 return 0;
622 } else if (!qstrcmp(argv[1], "-v") || !qstrcmp(argv[1], "--version")) {
623#ifdef HAVE_GIT_REV_H
624 std::cout << std::endl << "mupp version: " << MUPP_VERSION << ", git-branch: " << GIT_BRANCH << ", git-rev: " << GIT_CURRENT_SHA1 << std::endl << std::endl;
625#else
626 std::cout << std::endl << "mupp version: " << MUPP_VERSION << std::endl << std::endl;
627#endif
628 return 0;
629 } else if (!qstrcmp(argv[1], "-s") || !qstrcmp(argv[1], "--script")) {
630 if (argc != 3) {
631 std::cerr << std::endl;
632 std::cerr << "*********" << std::endl;
633 std::cerr << "**ERROR** the script option cannot be combined with something else." << std::endl;
634 std::cerr << "*********" << std::endl;
635 mupp_syntax();
636 return -1;
637 }
638 // make sure that the script file exists
639 if (!QFile::exists(argv[2])) {
640 std::cerr << std::endl;
641 std::cerr << "*********" << std::endl;
642 std::cerr << "**ERROR** the script file '" << argv[2] << "' doesn't exist." << std::endl;
643 std::cerr << "*********" << std::endl << std::endl;
644 return -1;
645 }
646
647 // read script file
648 if (mupp_script_read(argv[2], script) != 0) {
649 std::cerr << std::endl;
650 std::cerr << "*********" << std::endl;
651 std::cerr << "**ERROR** couldn't read script '" << argv[2] << "'" << std::endl;
652 std::cerr << "*********" << std::endl;
653 return -1;
654 }
655
656 // check syntax of the script
657 if (mupp_script_syntax_check(script) != 0) {
658 return -1;
659 }
660 } else if (argc >= 2) { // assume it should be a fit-param-file-name list
661 // check if a path is given
662 int start=1;
663 QString path="";
664 if (!qstrcmp(argv[1], "--path")) {
665 if (argc < 4) {
666 std::cerr << std::endl;
667 std::cerr << "*********" << std::endl;
668 std::cerr << "**ERROR** tag '--path' needs to be followed by a <fit-param-path> and at least one <fit-param-file-name>" << std::endl;
669 std::cerr << "*********" << std::endl;
670 mupp_syntax();
671 return -1;
672 }
673 path = argv[2];
674 start = 3;
675 }
676 for (int i=start; i<argc; i++) {
677 fln.push_back(argv[i]);
678 }
679 if (!path.isEmpty()) {
680 for (int i=0; i<fln.size(); i++) {
681 fln[i].prepend(path+"/");
682 }
683 }
684 }
685 }
686
687 bool guiFlag=true;
688 if (script.size() > 0) { // script
689 guiFlag = false;
690 }
691 QScopedPointer<QCoreApplication> app(createApplication(argc, argv, guiFlag));
692
693 std::unique_ptr<PmuppGui> gui;
694 std::unique_ptr<PmuppScript> mupp_script;
695 if (qobject_cast<QApplication *>(app.get())) { // GUI
696 gui = std::make_unique<PmuppGui>(fln);
697 if (gui == nullptr) {
698 std::cerr << std::endl;
699 std::cerr << "*********" << std::endl;
700 std::cerr << "**ERROR** couldn't invoke mupp gui..." << std::endl;
701 std::cerr << "*********" << std::endl;
702 return -1;
703 }
704 gui->setWindowTitle( "muSR Parameter Plotter" );
705 gui->resize( 800, 500 );
706 gui->show();
707
708 app.get()->connect( app.get(), SIGNAL( lastWindowClosed() ), app.get(), SLOT( quit() ) );
709 app.get()->connect( app.get(), SIGNAL( aboutToQuit() ), gui.get(), SLOT( aboutToQuit() ) );
710 } else { // scripting
711 mupp_script = std::make_unique<PmuppScript>(script);
712 if (mupp_script == nullptr) {
713 std::cerr << std::endl;
714 std::cerr << "*********" << std::endl;
715 std::cerr << "**ERROR** couldn't invoke script class..." << std::endl;
716 std::cerr << "*********" << std::endl;
717 return -1;
718 }
719
720 // This will cause the application to exit when the task signals finished.
721 QObject::connect( mupp_script.get(), SIGNAL( finished() ), app.get(), SLOT( quit() ) );
722
723 // This will run the task from the application event loop.
724 QTimer::singleShot(0, mupp_script.get(), SLOT( executeScript() ) );
725 }
726
727 return app->exec();
728}
Main GUI interface for the mupp (MusrFit Parameter Plotter) application.
Scripting interface for mupp batch processing.
int main(int argc, char *argv[])
Main entry point of the mupp application.
Definition mupp.cpp:611
int mupp_script_syntax_check(QStringList &list)
Validates the syntax of mupp script commands.
Definition mupp.cpp:291
QCoreApplication * createApplication(int &argc, char *argv[], bool gui)
Factory function to create the appropriate Qt application object.
Definition mupp.cpp:567
bool mupp_bash_variable_exists(const QString str)
Checks if a bash environment variable exists and is non-empty.
Definition mupp.cpp:251
void mupp_script_syntax()
Displays the mupp script syntax help to stdout.
Definition mupp.cpp:80
int mupp_script_read(const char *fln, QStringList &list)
Reads a mupp script file and parses its content into a string list.
Definition mupp.cpp:170
void mupp_syntax()
Displays the mupp application syntax and usage help to stdout.
Definition mupp.cpp:137