mupp 1.1.0
Loading...
Searching...
No Matches
PmuppGui.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 PmuppGui.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
61
62#include <sys/types.h>
63#include <sys/ipc.h>
64#include <sys/msg.h>
65#include <sys/stat.h>
66#include <errno.h>
67
68#include <cmath>
69#include <iostream>
70
71#include <QApplication>
72#include <QToolBar>
73#include <QMenuBar>
74#include <QMessageBox>
75#include <QRect>
76#include <QSpacerItem>
77#include <QFrame>
78#include <QStringList>
79#include <QFileDialog>
80#include <QListWidgetItem>
81#include <QInputDialog>
82#include <QFile>
83#include <QTextStream>
84#include <QDateTime>
85#include <QKeyEvent>
86#include <QProcessEnvironment>
87#include <QDir>
88#include <QTextStream>
89#include <QDateTime>
90
91#include <QtDebug>
92
93#include "mupp_version.h"
94#ifdef HAVE_GIT_REV_H
95#include "git-revision.h"
96#endif
97#include "PmuppGui.h"
98
99//----------------------------------------------------------------------------------------------------
108{
109 fCollectionTag = -1;
110 fXlabel = "";
111 fYlabel.clear();
112}
113
114//-----------------------------------------------------------------------------
124void PmuppXY::setYlabel(int idx, QString str)
125{
126 if (idx >= fYlabel.size())
127 return;
128
129 fYlabel[idx] = str;
130}
131
132//-----------------------------------------------------------------------------
142{
143 if (idx >= fYlabel.size())
144 return;
145
146 fYlabel.remove(idx);
147}
148
149//-----------------------------------------------------------------------------
159void PmuppXY::removeYlabel(QString str)
160{
161 for (int i=0; i<fYlabel.size(); i++) {
162 if (fYlabel[i] == str) {
163 fYlabel.remove(i);
164 return;
165 }
166 }
167}
168
169//-----------------------------------------------------------------------------
181QString PmuppXY::getYlabel(int idx)
182{
183 if (idx >= fYlabel.size())
184 return QString("");
185
186 return fYlabel[idx];
187}
188
189//-----------------------------------------------------------------------------
206{
207 QString str = fXlabel;
208
209 // remove trailing '-)'
210 int idx = fXlabel.lastIndexOf("-)");
211 if (idx == -1)
212 return -1;
213 str.remove(idx, str.length()-idx);
214
215 // remove everything up to '(-'
216 idx = fXlabel.indexOf("(-");
217 if (idx == -1)
218 return -1;
219 idx += 2;
220 str.remove(0, idx);
221
222 bool ok;
223 idx = str.toInt(&ok);
224 if (!ok)
225 return -1;
226
227 return idx;
228}
229
230//-----------------------------------------------------------------------------
250{
251 if (idx >= fYlabel.size())
252 return -1;
253
254 QString str = fYlabel[idx];
255
256 // remove trailing '-)'
257 int iidx = fXlabel.lastIndexOf("-)");
258 if (iidx == -1)
259 return -1;
260 str.remove(iidx, str.length()-iidx);
261
262 // remove everything up to '(-'
263 iidx = fXlabel.indexOf("(-");
264 if (iidx == -1)
265 return -1;
266 iidx += 2;
267 str.remove(0, iidx);
268
269 bool ok;
270 iidx = str.toInt(&ok);
271 if (!ok)
272 return -1;
273
274 return iidx;
275}
276
277//-----------------------------------------------------------------------------
295{
296 int length = errMsg.length();
297
298 fErrMsg = new QPlainTextEdit(errMsg);
299 fOK = new QPushButton("Done", this);
300
301 fErrMsg->setReadOnly(true);
302
303 QVBoxLayout *layout = new QVBoxLayout;
304 layout->addWidget(fErrMsg);
305 layout->addWidget(fOK);
306
307 connect( fOK, SIGNAL( clicked() ), this, SLOT( accept() ));
308
309 if (length > 0) {
310 int noBreaks = errMsg.count('\n');
311 int width = 20*length / noBreaks;
312 if (width < 300)
313 width = 300;
314 if (width > 900)
315 width = 900;
316 setMinimumWidth(width);
317 }
318 setLayout(layout);
319 show();
320}
321
322//-----------------------------------------------------------------------------
343PmuppGui::PmuppGui(QStringList fln)
344{
345 QDateTime dt = QDateTime::currentDateTime();
346 fDatime = dt.toSecsSinceEpoch();
347 fMuppInstance = -1;
348
349 fNormalizeAction = nullptr;
350
351 fMacroPath = QString("./");
352 fMacroName = QString("");
353
355
356 fAdmin = new PmuppAdmin();
357 fIgnoreThemeAutoDetection = fAdmin->getIgnoreThemeAutoDetection();
358 fDarkThemeIconsMenu = fAdmin->getDarkThemeIconsMenuFlag();
359 fDarkThemeIconsToolbar = fAdmin->getDarkThemeIconsToolbarFlag();
360
362 bool dataAtStartup = false;
363 if (fln.size() > 0) {
364 if (fln[0].contains(".msr")) {
365 // get collection Name
366 QString collName = QString("collName0");
367 fParamDataHandler->NewCollection(collName);
368 }
369 QString errorMsg("");
370 if (!fParamDataHandler->ReadParamFile(fln, errorMsg)) {
371 QMessageBox::critical(this, "ERROR", errorMsg);
372 } else {
373 dataAtStartup = true; // delay to deal with the data sets until the GUI is ready to do so
374 }
375 }
376
377 getTheme();
378
379 QString iconName("");
381 iconName = QString(":/icons/mupp-dark.svg");
382 else
383 iconName = QString(":/icons/mupp-plain.svg");
384 setWindowIcon( QIcon( QPixmap(iconName) ) );
385
386 // setup menus
390
391 // create central widget
392 fCentralWidget = std::make_unique<QWidget>(this);
393
394 // setup widgets
395 fBoxLayout_Main = std::make_unique<QBoxLayout>(QBoxLayout::TopToBottom);
396 fBoxLayout_Main->setGeometry(QRect(10, 40, 600, 500));
397
398 fBoxLayout_Top = std::make_unique<QBoxLayout>(QBoxLayout::LeftToRight);
399 fGridLayout_Left = std::make_unique<QGridLayout>();
400 fGridLayout_Right = std::make_unique<QGridLayout>();
401
402 // label for the collection/parameter list widgets
403 fColLabel = std::make_unique<QLabel>(this);
404 fColLabel->setText("Collection -> Parameter");
405 fColLabel->setMaximumHeight(15);
406
407 // central widget for the collection/parameter list widgets
408 fColParamSplitter = std::make_unique<QSplitter>(Qt::Horizontal, this);
409 fColParamSplitter->setMinimumSize(550,330);
410
411 fColList = std::make_unique<QListWidget>(this);
412 fColList->setSelectionMode(QAbstractItemView::ExtendedSelection);
413
414 fParamList = std::make_unique<QListWidget>(this);
415 // the next two lines enable drag and drop facility (drag)
416 fParamList->setSelectionMode(QAbstractItemView::SingleSelection);
417 fParamList->setDragEnabled(true);
418
419 fColParamSplitter->addWidget(fColList.get());
420 fColParamSplitter->addWidget(fParamList.get());
421
422 fRemoveCollection = std::make_unique<QPushButton>("Remove Collection", this);
423 fRefreshCollection = std::make_unique<QPushButton>("Refresh Collection", this);
424
425 fGridLayout_Left->addWidget(fColLabel.get(), 1, 1, 1, 2);
426 fGridLayout_Left->addWidget(fColParamSplitter.get(), 2, 1, 1, 2);
427 fGridLayout_Left->addWidget(fRemoveCollection.get(), 3, 1);
428 fGridLayout_Left->addWidget(fRefreshCollection.get(), 3, 2);
429
430 // X-axis
431 fXaxisLabel = std::make_unique<QLabel>("x-axis");
432 fViewX = std::make_unique<QListWidget>(this);
433 // the next two lines enable drag and drop facility (copy drop)
434 fViewX->viewport()->setAcceptDrops(true);
435 fViewX->setDropIndicatorShown(true);
436
437 fAddX = std::make_unique<QPushButton>("add X", this);
438 fRemoveX = std::make_unique<QPushButton>("remove X", this);
439
440 // Y-axis
441 fYaxisLabel = std::make_unique<QLabel>("y-axis");
442 fViewY = std::make_unique<QListWidget>(this);
443 // the next two lines enable drag and drop facility (copy drop)
444 fViewY->viewport()->setAcceptDrops(true);
445 fViewY->setDropIndicatorShown(true);
446
447 fAddY = std::make_unique<QPushButton>("add Y", this);
448 fRemoveY = std::make_unique<QPushButton>("remove Y", this);
449
450 // 2 column button's for the right grid
451 fAddDitto = std::make_unique<QPushButton>("Add Ditto", this);
452 fPlot = std::make_unique<QPushButton>("Plot", this);
453
454 fGridLayout_Right->addWidget(fXaxisLabel.get(), 1, 1);
455 fGridLayout_Right->addWidget(fYaxisLabel.get(), 1, 2);
456 fGridLayout_Right->addWidget(fViewX.get(), 2, 1);
457 fGridLayout_Right->addWidget(fViewY.get(), 2, 2);
458 fGridLayout_Right->addWidget(fAddX.get(), 3, 1);
459 fGridLayout_Right->addWidget(fAddY.get(), 3, 2);
460 fGridLayout_Right->addWidget(fRemoveX.get(), 4, 1);
461 fGridLayout_Right->addWidget(fRemoveY.get(), 4, 2);
462 fGridLayout_Right->addWidget(fAddDitto.get(), 5, 1, 1, 2);
463 fGridLayout_Right->addWidget(fPlot.get(), 6, 1, 1, 2);
464
465 fBoxLayout_Top->addLayout(fGridLayout_Left.get());
466 fBoxLayout_Top->addLayout(fGridLayout_Right.get());
467
468 fCmdLineHistory = std::make_unique<QPlainTextEdit>(this);
469 fCmdLineHistory->setReadOnly(true);
470 fCmdLineHistory->setMaximumBlockCount(50);
471 // fill cmd history
472 for (int i=0; i<fCmdHistory.size(); i++)
473 fCmdLineHistory->insertPlainText(QString("%1\n").arg(fCmdHistory[i]));
474 fCmdLine = std::make_unique<QLineEdit>(this);
475 fCmdLine->installEventFilter(this);
476 fCmdLine->setText("$ ");
477 fCmdLine->setFocus(); // sets the keyboard focus
478 fExitButton = std::make_unique<QPushButton>("E&xit", this);
479
480 QVBoxLayout *cmdLayout = new QVBoxLayout;
481 QLabel *cmdLabel = new QLabel("History:");
482 cmdLayout->addWidget(cmdLabel);
483 cmdLayout->addWidget(fCmdLineHistory.get());
484 cmdLayout->addWidget(fCmdLine.get());
485
486 fBoxLayout_Cmd = std::make_unique<QBoxLayout>(QBoxLayout::LeftToRight);
487 fBoxLayout_Cmd->addLayout(cmdLayout);
488 fBoxLayout_Cmd->addWidget(fExitButton.get());
489 fBoxLayout_Cmd->setAlignment(fCmdLine.get(), Qt::AlignBottom);
490 fBoxLayout_Cmd->setAlignment(fExitButton.get(), Qt::AlignBottom);
491
492 fCmdSplitter = std::make_unique<QSplitter>(Qt::Vertical, this);
493 QWidget *topWidget = new QWidget(this); // only needed since splitter needs a QWidget
494 topWidget->setLayout(fBoxLayout_Top.get());
495 QWidget *cmdWidget = new QWidget(this); // only needed since splitter needs a QWidget
496 cmdWidget->setLayout(fBoxLayout_Cmd.get());
497 fCmdSplitter->addWidget(topWidget);
498 fCmdSplitter->addWidget(cmdWidget);
499
500 fBoxLayout_Main->addWidget(fCmdSplitter.get());
501
502 // establish all the necessary signal/slots
503 connect(fRefreshCollection.get(), SIGNAL( pressed() ), this, SLOT( refresh() ));
504 connect(fRemoveCollection.get(), SIGNAL( pressed() ), this, SLOT( remove() ));
505 connect(fAddX.get(), SIGNAL( pressed() ), this, SLOT( addX() ));
506 connect(fAddY.get(), SIGNAL( pressed() ), this, SLOT( addY() ));
507 connect(fRemoveX.get(), SIGNAL( pressed() ), this, SLOT( removeX() ));
508 connect(fRemoveY.get(), SIGNAL( pressed() ), this, SLOT( removeY() ));
509 connect(fAddDitto.get(), SIGNAL( pressed() ), this, SLOT( addDitto() ));
510 connect(fPlot.get(), SIGNAL( pressed()), this, SLOT( plot()) );
511 connect(fCmdLine.get(), SIGNAL ( returnPressed() ), this, SLOT( handleCmds() ));
512 connect(fExitButton.get(), SIGNAL( pressed() ), this, SLOT( aboutToQuit() ));
513
514 connect(fColList.get(), SIGNAL( currentRowChanged(int) ), this, SLOT( updateParamList(int) ));
515 connect(fColList.get(), SIGNAL( itemDoubleClicked(QListWidgetItem*) ), this, SLOT( editCollName(QListWidgetItem*) ));
516
517 connect(fViewX.get(), SIGNAL( currentRowChanged(int) ), this, SLOT( refreshY() ));
518 connect(fViewX.get(), SIGNAL( itemChanged(QListWidgetItem*) ), this, SLOT( dropOnViewX(QListWidgetItem*) ));
519 connect(fViewY.get(), SIGNAL( itemChanged(QListWidgetItem*) ), this, SLOT( dropOnViewY(QListWidgetItem*) ));
520
521 // deal with parameter data specifics
522 if (dataAtStartup)
524
525 connect(fParamDataHandler, SIGNAL( newData() ), this, SLOT( handleNewData() ));
526
527 fCentralWidget->setLayout(fBoxLayout_Main.get());
528 setCentralWidget(fCentralWidget.get());
529
530 // in case there is no db/dat file list given open the db/dat file open menu automatically.
531 if (fln.size() == 0) {
532 fileOpen();
533 if (fParamDataHandler->GetNoOfCollections() == 0) { // file open dialog has been cancelled
534 exit(0);
535 }
536 }
537}
538
539//-----------------------------------------------------------------------------
544{
545 // all relevant clean up job are done in ::aboutToQuit()
546}
547
548//-----------------------------------------------------------------------------
554{
555 // kill mupp_plot if active
556 if (fMuppPlot) {
557 if (fMuppPlot->state() != QProcess::NotRunning) {
558 fMuppPlot->terminate();
559 }
560 }
561
562 // remove message queue
563 key_t key;
564 int flags, msqid;
565
566 // generate the ICP message queue key
567 key = ftok(QCoreApplication::applicationFilePath().toLatin1().data(), 1);
568
569 if (key != -1) {
570 // set the necessary IPC message queue flags
571 flags = IPC_CREAT;
572
573 // open the message queue
574 msqid = msgget(key, flags | S_IRUSR | S_IWUSR);
575 if (msqid != -1) {
576 if (msgctl(msqid, IPC_RMID, NULL) == -1) {
577 std::cerr << "**ERROR** couldn't removed the message queue (msqid=" << msqid << ", " << std::strerror(errno) << ")." << std::endl << std::endl;
578 }
579 }
580 }
581
582 // clean up temporary plot files
583 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
584 if (fMuppInstance != -1) {
585 QString pathName = QString("%1/.musrfit/mupp/_mupp_%2.dat").arg(env.value("HOME")).arg(fDatime);
586 QFile::remove(pathName);
587 pathName = QString("%1/.musrfit/mupp/_mupp_ftok_%2.dat").arg(env.value("HOME")).arg(fMuppInstance);
588 QFile::remove(pathName);
589 }
590
591 // needed for clean up and to save the cmd history
593
594 if (fParamDataHandler) {
595 delete fParamDataHandler;
597 }
598
599 if (fAdmin) {
600 delete fAdmin;
601 fAdmin = 0;
602 }
603
604 exit(0);
605}
606
607//-----------------------------------------------------------------------------
612{
613 QToolBar *tb = new QToolBar( this );
614 tb->setWindowTitle( "File Actions" );
615 addToolBar( tb );
616
617 QMenu *menu = new QMenu( tr( "F&ile" ), this );
618 menuBar()->addMenu( menu );
619
620 QAction *a;
621
622 QString iconName("");
624 iconName = QString(":/icons/document-open-dark.svg");
625 else
626 iconName = QString(":/icons/document-open-plain.svg");
627 a = new QAction( QIcon( QPixmap(iconName) ), tr( "&Open..." ), this );
628 a->setShortcut( tr("Ctrl+O") );
629 a->setStatusTip( tr("Open a musrfit parameter file.") );
630 connect( a, SIGNAL( triggered() ), this, SLOT( fileOpen() ) );
631 menu->addAction(a);
632 if (!fDarkThemeIconsToolbar) { // tool bar icon is not dark, even though the theme is (ubuntu, mx, xfce)
633 iconName = QString(":/icons/document-open-plain.svg");
634 a = new QAction( QIcon( QPixmap(iconName) ), tr( "&New..." ), this );
635 connect( a, SIGNAL( triggered() ), this, SLOT( fileOpen() ) );
636 }
637 tb->addAction(a);
638
639 fRecentFilesMenu = menu->addMenu( tr("Recent Files") );
640 for (int i=0; i<MAX_RECENT_FILES; i++) {
641 fRecentFilesAction[i] = new QAction(fRecentFilesMenu);
642 fRecentFilesAction[i]->setVisible(false);
643 connect( fRecentFilesAction[i], SIGNAL(triggered()), this, SLOT(fileOpenRecent()));
645 }
647
648 a = new QAction( tr( "E&xit" ), this );
649 a->setShortcut( tr("Ctrl+Q") );
650 a->setStatusTip( tr("Exit Program") );
651 connect( a, SIGNAL( triggered() ), this, SLOT( fileExit() ) );
652 menu->addAction(a);
653}
654
655//-----------------------------------------------------------------------------
660{
661 QMenu *menu = new QMenu( tr( "&Tools" ), this );
662 menuBar()->addMenu( menu );
663
664 QAction *a;
665
666 a = new QAction(tr( "Plot ..." ), this );
667 a->setStatusTip( tr("Plot x/y parameters") );
668 connect( a, SIGNAL( triggered() ), this, SLOT( plot() ) );
669 menu->addAction(a);
670
671 a = new QAction(tr( "Create ROOT Macro ..." ), this );
672 a->setStatusTip( tr("Creates a ROOT Macro with the given x/y parameters") );
673 connect( a, SIGNAL( triggered() ), this, SLOT( createMacro() ) );
674 menu->addAction(a);
675
676 menu->addSeparator();
677
678 a = new QAction(tr( "Dump Collections ..." ), this );
679 a->setStatusTip( tr("Dump all collections") );
680 connect( a, SIGNAL( triggered() ), this, SLOT( toolDumpCollections() ) );
681 menu->addAction(a);
682
683 a = new QAction(tr( "Dump XY ..." ), this );
684 a->setStatusTip( tr("Dump XY parameter list") );
685 connect( a, SIGNAL( triggered() ), this, SLOT( toolDumpXY() ) );
686 menu->addAction(a);
687
688 menu->addSeparator();
689
690 a = new QAction(tr( "Add Variable" ), this );
691 a->setStatusTip( tr("Calls a dialog which allows to add variables which are expressions of db/dat vars.") );
692 connect( a, SIGNAL( triggered() ), this, SLOT( addVar() ));
693 menu->addAction(a);
694
695 menu->addSeparator();
696
697 fNormalizeAction = std::make_unique<QAction>(tr( "Normalize" ), this);
698 fNormalizeAction->setStatusTip( tr("Plot Data Normalized (y-axis)") );
699 fNormalizeAction->setCheckable(true);
700 connect( fNormalizeAction.get(), SIGNAL( changed() ), this, SLOT( normalize() ) );
701 menu->addAction(fNormalizeAction.get());
702}
703
704//-----------------------------------------------------------------------------
709{
710 QMenu *menu = new QMenu( tr( "&Help" ), this );
711 menuBar()->addMenu( menu );
712
713 QAction *a;
714/*
715 a = new QAction(tr( "Contents ..." ), this );
716 a->setStatusTip( tr("Help Contents") );
717 connect( a, SIGNAL( triggered() ), this, SLOT( helpContents() ));
718 menu->addAction(a);
719*/
720
721 a = new QAction( tr( "Cmd's" ), this );
722 a->setStatusTip( tr( "Lists the command line commands" ) );
723 connect( a, SIGNAL( triggered() ), this, SLOT( helpCmds() ));
724 menu->addAction(a);
725
726 a = new QAction( tr( "Author(s) ..." ), this );
727 a->setStatusTip( tr( "About the Author(s)") );
728 connect( a, SIGNAL( triggered() ), this, SLOT( helpAbout() ));
729 menu->addAction(a);
730
731 a = new QAction( tr( "About Qt..." ), this );
732 a->setStatusTip( tr( "Help About Qt") );
733 connect( a, SIGNAL( triggered() ), this, SLOT( helpAboutQt() ));
734 menu->addAction(a);
735}
736
737//-----------------------------------------------------------------------------
742{
743 QStringList list = QFileDialog::getOpenFileNames(
744 this,
745 "muSR Parameter Files",
746 "./",
747 "dat-files (*.dat);; db-Files (*.db);; All Params (*.msr *.db *.dat);; Msr-Files (*.msr);; All (*)");
748
749 if (list.count() == 0)
750 return;
751
752 bool msrPresent = false;
753 bool dbPresent = false;
754 for (int i=0; i<list.count(); i++) {
755 if (list[i].endsWith(".msr"))
756 msrPresent = true;
757 else if (list[i].endsWith(".db") || list[i].endsWith(".dat"))
758 dbPresent = true;
759 else {
760 QMessageBox::critical(this, "ERROR", QString("Found file with unkown extension:\n%1\nWill not do anything here.").arg(list[i]));
761 return;
762 }
763 }
764
765 if (msrPresent && dbPresent) {
766 QMessageBox::critical(this, "ERROR", "Currently mixed reading of msr and db/dat is not supported.");
767 return;
768 }
769
770 QString errorMsg("");
771 if (!fParamDataHandler->ReadParamFile(list, errorMsg)) {
772 QMessageBox::critical(this, "ERROR", errorMsg);
773 return;
774 }
775
776 // populate the recent files
777 if (msrPresent || dbPresent) {
778 for (int i=0; i<list.size(); i++) {
779 fAdmin->addRecentFile(list[i]); // keep it in admin
780 fillRecentFiles(); // update menu
781 }
782 }
783}
784
785//-----------------------------------------------------------------------------
790{
791 QAction *action = qobject_cast<QAction *>(sender());
792
793 if (action) {
794 QStringList fln;
795 fln << action->text();
796 QString errorMsg("");
797 if (!fParamDataHandler->ReadParamFile(fln, errorMsg)) {
798 QMessageBox::critical(this, "ERROR", errorMsg);
799 return;
800 }
801 }
802}
803
804//-----------------------------------------------------------------------------
809{
810 aboutToQuit();
811}
812
813//-----------------------------------------------------------------------------
818{
819 if (fParamDataHandler->GetNoOfCollections()) {
820 fParamDataHandler->Dump();
821 } else {
822 QMessageBox::warning(this, "dump collections", "no collections present");
823 }
824}
825
826//-----------------------------------------------------------------------------
831{
832 if (fXY.size() > 0) {
833 for (int i=0; i<fXY.size(); i++) {
834 qInfo() << "<-><-><-><-><-><-><-><-><-><->";
835 qInfo() << i << ": collection tag: " << fXY[i].getCollectionTag();
836 qInfo() << " x-param: " << fXY[i].getXlabel();
837 for (int j=0; j<fXY[i].getYlabelSize(); j++)
838 qInfo() << " y-param: " << fXY[i].getYlabel(j);
839 }
840 } else {
841 QMessageBox::warning(this, "dump XY", "no XY list present yet");
842 }
843}
844
845//-----------------------------------------------------------------------------
851{
852 fNormalize = fNormalizeAction->isChecked();
853}
854
855//-----------------------------------------------------------------------------
860{
861 QMessageBox::information(this, "cmd help", "<b>help:</b> this help.<br>"\
862 "<b>add var</b>: allows to add a variable which is formula of collection vars.<br>"\
863 "<b>ditto</b>: addX/Y for the new selection as for the previous ones.<br>"\
864 "<b>dump collections:</b> dumps all currently loaded collections.<br>"\
865 "<b>dump XY:</b> dumps X/Y tree.<br>"\
866 "<b>exit/quit:</b> close mupp.<br>"\
867 "<b>load:</b> calls the open file dialog.<br>"\
868 "<b>norm &lt;flag&gt;:</b> normalize plots to maximum if &lt;flag&gt; is true<br>"\
869 "<b>macro &lt;fln&gt;:</b> saves the X/Y data as a ROOT macro (*.C).<br>"\
870 "<b>path &lt;macroPath&gt;:</b> sets the path to the place where the macros will be saved.<br>"\
871 "<b>plot:</b> plot the X/Y data.<br>"\
872 "<b>refresh:</b> refresh the currently selected collection.<br>"\
873 "<b>select &lt;nn&gt;:</b> select collection in GUI.<br>"\
874 "&nbsp;&nbsp;&nbsp;&nbsp;&lt;nn&gt; is either the collection name or the row number.<br>"\
875 "<b>x &lt;param_name&gt; / y &lt;param_name&gt;:</b> add the parameter to the select axis.<br>"\
876 "<b>rmx &lt;param_name&gt; / rmy &lt;param_name&gt;:</b> remove the parameter of the select axis.<br>"\
877 "<b>flush:</b> flush the history buffer.");
878}
879
880//-----------------------------------------------------------------------------
885{
886#ifdef HAVE_GIT_REV_H
887 QMessageBox::information(this, "about", QString("mupp: created by Andreas Suter.\nVersion: %1\nBranch: %2\nHash: %3").arg(MUPP_VERSION).arg(GIT_BRANCH).arg(GIT_CURRENT_SHA1));
888#else
889 QMessageBox::information(this, "about", QString("mupp: created by Andreas Suter.\nVersion: %1").arg(MUPP_VERSION));
890#endif
891}
892
893//-----------------------------------------------------------------------------
898{
899 QMessageBox::aboutQt(this);
900}
901
902//-----------------------------------------------------------------------------
910bool PmuppGui::eventFilter(QObject *o, QEvent *e)
911{
912 static int idx = fCmdHistory.size();
913
914 if (e->type() == QEvent::KeyPress) {
915 QKeyEvent *k = static_cast<QKeyEvent*>(e);
916 int key = k->key();
917 if (key == Qt::Key_Up) {
918 if (idx > 0)
919 idx--;
920 if (idx < fCmdHistory.size())
921 fCmdLine->setText(fCmdHistory[idx]);
922 } else if (key == Qt::Key_Down) {
923 if (idx < fCmdHistory.size())
924 idx++;
925 if (idx < fCmdHistory.size())
926 fCmdLine->setText(fCmdHistory[idx]);
927 else
928 fCmdLine->setText("$ ");
929 } else if (key == Qt::Key_Return) {
930 QString cmd = fCmdLine->text();
931 bool found = false;
932 for (int i=0; i<fCmdHistory.size(); i++) {
933 if (cmd == fCmdHistory[i]) {
934 found = true;
935 }
936 }
937 if (!found) {
938 if (fCmdHistory.size() >= 50)
939 fCmdHistory.removeFirst();
940 fCmdHistory.push_back(cmd);
941 fCmdLineHistory->insertPlainText(QString("%1\n").arg(cmd));
942 }
943 }
944 return false;
945 }
946
947 // make sure the base class can handle all the events not handled here
948 return QMainWindow::eventFilter(o, e);
949}
950
951//-----------------------------------------------------------------------------
956{
958 return;
959
960 fDarkThemeIconsMenu = false; // true if theme is dark
961 fDarkThemeIconsToolbar = false; // needed for ubuntu dark since there the menu icons
962 // are dark, however the toolbar icons are plain!
963
964 QString str = QIcon::themeName();
965
966 if (str.isEmpty()) {
967 if (fAdmin->getDarkThemeIconsMenuFlag()) {
968 fDarkThemeIconsMenu = true;
969 }
970 if (fAdmin->getDarkThemeIconsToolbarFlag()) {
972 }
973 return;
974 }
975
976 if (str.contains("dark", Qt::CaseInsensitive)) {
977 fDarkThemeIconsMenu = true;
978 if (str.contains("ubuntu", Qt::CaseInsensitive) ||
979 str.contains("xfce", Qt::CaseInsensitive)) {
981 } else {
983 }
984 }
985}
986
987//-----------------------------------------------------------------------------
992{
993 for (int i=0; i<fAdmin->getNumRecentFiles(); i++) {
994 fRecentFilesAction[i]->setText(fAdmin->getRecentFile(i));
995 fRecentFilesAction[i]->setVisible(true);
996 }
997}
998
999//-----------------------------------------------------------------------------
1005{
1006 QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment();
1007 QString home = procEnv.value("HOME", "");
1008 if (home.isEmpty())
1009 return;
1010
1011 QString pathName = home + "/.musrfit/mupp/mupp_history.txt";
1012
1013 QFile file(pathName);
1014 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
1015 std::cerr << std::endl;
1016 std::cerr << "***********" << std::endl;
1017 std::cerr << "**WARNING** readCmdHistory(): couldn't open mupp_history.txt for reading ..." << std::endl;;
1018 std::cerr << "***********" << std::endl;
1019 return;
1020 }
1021
1022 QTextStream fin(&file);
1023
1024 fCmdHistory.clear();
1025 QString line;
1026 while (!fin.atEnd()) {
1027 line = fin.readLine();
1028 if (line.startsWith("%") || line.isEmpty())
1029 continue;
1030 fCmdHistory.push_back(line);
1031 }
1032}
1033
1034//-----------------------------------------------------------------------------
1039{
1040 QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment();
1041 QString home = procEnv.value("HOME", "");
1042 if (home.isEmpty())
1043 return;
1044
1045 QString pathName = home + "/.musrfit/mupp/";
1046 QDir dir(pathName);
1047 if (!dir.exists()) {
1048 // directory $HOME/.musrfit/mupp does not exist hence create it
1049 dir.mkpath(pathName);
1050 }
1051 pathName += "mupp_history.txt";
1052
1053 QFile file(pathName);
1054 if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
1055 return;
1056
1057 QTextStream fout(&file);
1058
1059 // write header
1060 QDateTime dt = QDateTime::currentDateTime();
1061 fout << "% mupp history file" << Qt::endl;
1062 fout << "% " << dt.toString("HH:mm:ss - yy/MM/dd") << Qt::endl;
1063
1064 // write history
1065 for (int i=0; i<fCmdHistory.size(); i++)
1066 fout << fCmdHistory[i] << Qt::endl;
1067
1068 fout << "% end mupp history file" << Qt::endl;
1069
1070 file.close();
1071}
1072
1073//-----------------------------------------------------------------------------
1078{
1079 QListWidgetItem *item = fColList->currentItem();
1080 if (item == 0)
1081 return;
1082 QString label = item->text();
1083
1084 QString pathName("");
1085 int collIdx=-1;
1086
1087 for (int i=0; i<fParamDataHandler->GetNoOfCollections(); i++) {
1088 if (fParamDataHandler->GetCollection(i)->GetName() == label) { // found collection
1089 QDir dir(QDir::currentPath());
1090 pathName = dir.path() + "/" + fParamDataHandler->GetCollection(i)->GetName();
1091 collIdx = i;
1092 break;
1093 }
1094 }
1095
1096 // re-load collection
1097 PmuppCollection coll;
1098 bool ok=false;
1099 if (pathName.endsWith(".db")) {
1100 QString errorMsg("");
1101 coll = fParamDataHandler->ReadDbFile(pathName, ok, errorMsg);
1102 if (!ok) {
1103 QMessageBox::critical(this, "ERROR - REFRESH",
1104 QString("Couldn't refresh %1\nFile corrupted?!\n").arg(fParamDataHandler->GetCollection(collIdx)->GetName())+
1105 errorMsg);
1106 return;
1107 }
1108 } else if (pathName.endsWith(".dat")) {
1109 QString errorMsg("");
1110 coll = fParamDataHandler->ReadColumnParamFile(pathName, ok, errorMsg);
1111 if (!ok) {
1112 QMessageBox::critical(this, "ERROR - REFRESH",
1113 QString("Couldn't refresh %1\nFile corrupted?!\n").arg(fParamDataHandler->GetCollection(collIdx)->GetName())+
1114 errorMsg);
1115 return;
1116 }
1117 } else {
1118 QMessageBox::critical(this, "ERROR - REFRESH",
1119 QString("Couldn't refresh %1").arg(fParamDataHandler->GetCollection(collIdx)->GetName()));
1120 return;
1121 }
1122
1123 QString collName = pathName;
1124 int pos = collName.lastIndexOf("/");
1125 collName.remove(0, pos+1);
1126 coll.SetName(collName);
1127 coll.SetPathName(pathName);
1128 fParamDataHandler->ReplaceCollection(coll, collIdx);
1129
1130 // update the parameter list (GUI)
1131 updateParamList(collIdx);
1132
1133 // update XY list (GUI)
1135}
1136
1137//-----------------------------------------------------------------------------
1142{
1143 // get current collection
1144 QListWidgetItem *item = fColList->currentItem();
1145 if (item == 0)
1146 return;
1147
1148 QString collName = item->text();
1149
1150 // remove it from the list widget but keep the index for further use
1151 int idx = fColList->row(item);
1152 fColList->removeItemWidget(item);
1153 delete item;
1154
1155 // remove it from the collection handler
1156 fParamDataHandler->RemoveCollection(collName);
1157
1158 // next it is necessary to update the XY-parameter list
1159 updateXYList(fColList->currentRow());
1160
1161 // if there no collections left remove all the parameters from the X/Y list
1162 // remove all fXY as well
1163 if (fColList->count() == 0) {
1164 fViewX->clear();
1165 fViewY->clear();
1166 fXY.clear();
1167 return;
1168 }
1169
1170 // select the row before the delete one if possible
1171 if (idx > 0)
1172 idx -= 1;
1173 fColList->setCurrentRow(idx, QItemSelectionModel::Select);
1174
1175 // update the parameter list (GUI)
1176 updateParamList(idx);
1177
1178 // update XY list (GUI)
1180}
1181
1182//-----------------------------------------------------------------------------
1187void PmuppGui::addX(QString param)
1188{
1189 QString paramName("");
1190 if (!param.isEmpty()) {
1191 // check that param exists
1192 if (fParamList->findItems(param, Qt::MatchCaseSensitive).empty()) {
1193 QMessageBox::critical(this, "ERROR", QString("Parameter X '%1' not found").arg(param));
1194 return;
1195 }
1196 paramName = param;
1197 } else {
1198 // get the parameter name from the parameter list widget
1199 QListWidgetItem *item = fParamList->currentItem();
1200 if (item == 0)
1201 return;
1202 paramName = item->text();
1203 }
1204 int idx = fColList->currentRow();
1205 QString xLabel = QString("%1 (-%2-)").arg(paramName).arg(idx);
1206
1207 // check if it is not already present
1208 for (int i=0; i<fViewX->count(); i++) {
1209 if (fViewX->item(i)->text() == xLabel)
1210 return;
1211 }
1212
1213 // set the parameter name on the view X list widget
1214 fViewX->addItem(xLabel);
1215 fViewX->setCurrentRow(fViewX->count()-1);
1216
1217 // add the item to the XY list
1218 PmuppXY xyItem;
1219 xyItem.setCollectionTag(idx);
1220 xyItem.setXlabel(xLabel);
1221
1222 fXY.push_back(xyItem);
1223}
1224
1225//-----------------------------------------------------------------------------
1230void PmuppGui::addY(QString param)
1231{
1232 QString paramName("");
1233 if (!param.isEmpty()) {
1234 // check that param exists
1235 if (fParamList->findItems(param, Qt::MatchCaseSensitive).empty()) {
1236 QMessageBox::critical(this, "ERROR", QString("Parameter Y '%1' not found").arg(param));
1237 return;
1238 }
1239 paramName = param;
1240 } else {
1241 // get the parameter name from the parameter list widget
1242 QListWidgetItem *item = fParamList->currentItem();
1243 if (item == 0)
1244 return;
1245 paramName = item->text();
1246 }
1247 int idx = fColList->currentRow();
1248 QString yLabel = QString("%1 (-%2-)").arg(paramName).arg(idx);
1249
1250 // make sure that any x-parameter selection is already present
1251 if (fViewX->count() == 0) {
1252 QMessageBox::warning(this, "WARNING", "It is compulsory to have at least one x-parameter set\nbefore trying to add a y-parameter.");
1253 return;
1254 }
1255
1256 // check if collection of x- and y-parameter selection correspond
1257 idx=getXlabelIndex(fViewX->currentItem()->text());
1258 if (idx == -1)
1259 return;
1260 if (fXY[idx].getCollectionTag() != fColList->currentRow()) {
1261 QMessageBox::warning(this, "WARNING", "x/y parameters need to originate from the same collection.");
1262 return;
1263 }
1264
1265 // check if it is not already present
1266 for (int i=0; i<fViewY->count(); i++) {
1267 if (fViewY->item(i)->text() == yLabel)
1268 return;
1269 }
1270
1271 // set the parameter name on the view Y list widget
1272 fViewY->addItem(yLabel);
1273
1274 // add the item to the XY list
1275 idx=getXlabelIndex(fViewX->currentItem()->text());
1276 if (idx == -1)
1277 return;
1278
1279 fXY[idx].addYlabel(yLabel);
1280}
1281
1282//-----------------------------------------------------------------------------
1287void PmuppGui::removeX(QString param)
1288{
1289 QListWidgetItem *item = fViewX->currentItem();
1290 if (item == 0)
1291 return;
1292
1293 int idx;
1294 if (!param.isEmpty()) {
1295 idx=fColList->currentRow();
1296 param = QString("%1 (-%2-)").arg(param).arg(idx);
1297 idx=getXlabelIndex(param);
1298 } else {
1299 idx=getXlabelIndex(item->text());
1300 }
1301
1302 if (idx == -1)
1303 return;
1304 fXY.remove(idx);
1305
1306 fViewX->removeItemWidget(item);
1307 delete item;
1308}
1309
1310//-----------------------------------------------------------------------------
1315void PmuppGui::removeY(QString param)
1316{
1317 QListWidgetItem *item = fViewY->currentItem();
1318 if (item == 0)
1319 return;
1320
1321 // find y in XY and remove it
1322 QString xLabel = fViewX->currentItem()->text();
1323 QString yLabel = item->text();
1324 if (!param.isEmpty()) {
1325 yLabel = param;
1326 }
1327 int idx = getXlabelIndex(xLabel);
1328 if (idx == -1)
1329 return;
1330 fXY[idx].removeYlabel(yLabel);
1331
1332 fViewY->removeItemWidget(item);
1333 delete item;
1334}
1335
1336
1337//-----------------------------------------------------------------------------
1343{
1344 if (fXY.size() == 0) {
1345 QMessageBox::critical(this, "ERROR", "No x/y items present.\nTherefore nothing to be done.");
1346 return;
1347 }
1348
1349 if (!allXYEqual()) {
1350 QMessageBox::critical(this, "ERROR", "Multiple unequal sets of x/y items present.\nDo not know how to handle.");
1351 return;
1352 }
1353
1354 // get the selected items from the collection
1355 QList<QListWidgetItem*> items = fColList->selectedItems();
1356 if (items.count() == 0) { // no selections present hence drop out
1357 return;
1358 }
1359
1360 // verify that all selected items have corresponding x/y values
1361 bool ok=false;
1362 PmuppCollection muCol;
1363 PmuppRun muRun;
1364 for (int i=0; i<items.count(); i++) {
1365 ok = false;
1366 muCol = fParamDataHandler->GetCollection(items[i]->text(), ok);
1367 if (!ok)
1368 return;
1369 muRun = muCol.GetRun(0);
1370 // check x-values
1371 if (!findValue(muRun, kXaxis))
1372 return;
1373 // check y-values
1374 if (!findValue(muRun, kYaxis))
1375 return;
1376 }
1377
1378 // populate all necessary x- and y-values for all selected collections
1379 PmuppXY muXY = fXY[0];
1380 int idx;
1381 for (int i=0; i<items.count(); i++) {
1382 idx = fColList->row(items[i]);
1383 if (indexAlreadyPresent(idx))
1384 continue;
1385 replaceIndex(muXY, idx);
1386 fXY.push_back(muXY);
1387 // add x-axis view
1388 fViewX->addItem(muXY.getXlabel());
1389 fViewX->setCurrentRow(fViewX->count()-1);
1390 }
1391
1392 // un-select the collecion list
1393 fColList->clearSelection();
1394}
1395
1396//-----------------------------------------------------------------------------
1402{
1403 // create collection list
1404 QVector<PCollInfo> collection_list;
1405
1406 // go through all available collections and obtain the needed information
1407 PCollInfo collInfo;
1408 for (int i=0; i<fParamDataHandler->GetNoOfCollections(); i++) {
1409 // get collection name
1410 collInfo.fCollName = fParamDataHandler->GetCollectionName(i);
1411 // get variable names
1412 for (int j=0; j<fParamDataHandler->GetCollection(i)->GetRun(0).GetNoOfParam(); j++) {
1413 collInfo.fVarName << fParamDataHandler->GetCollection(i)->GetRun(0).GetParam(j).GetName();
1414 }
1415 collection_list.push_back(collInfo);
1416 }
1417
1418 // call variable dialog
1419 fVarDlg.reset();
1420 fVarDlg = std::make_unique<PVarDialog>(collection_list, fDarkThemeIconsMenu);
1421 connect(fVarDlg.get(), SIGNAL(check_request(QString,QVector<int>)), this, SLOT(check(QString,QVector<int>)));
1422 connect(fVarDlg.get(), SIGNAL(add_request(QString,QVector<int>)), this, SLOT(add(QString,QVector<int>)));
1423 fVarDlg->show();
1424}
1425
1426//-----------------------------------------------------------------------------
1433void PmuppGui::check(QString varStr, QVector<int> idx)
1434{
1435 // expose every loaded collection inside a <python> block (coll[]/collErr[]),
1436 // addressable by index and by name, so a check exercises the same namespace
1437 // the actual evaluation will see.
1438 std::vector<PmuppCollection*> allColl;
1439 for (int i=0; i<fParamDataHandler->GetNoOfCollections(); i++)
1440 allColl.push_back(fParamDataHandler->GetCollection(i));
1441
1442 int count = 0;
1443 for (int i=0; i<idx.size(); i++) {
1444 PVarHandler var_check(fParamDataHandler->GetCollection(idx[i]), varStr.toLatin1().data(),
1445 std::string(), allColl);
1446 if (var_check.isValid()) {
1447 count++;
1448 } else {
1450 return;
1451 }
1452 }
1453 if (count == idx.size()) {
1454 QMessageBox::information(this, "INFO", "Parsing successful.");
1455 }
1456 fVarDlg->raise();
1457 fVarDlg->setFocus();
1458}
1459
1460//-----------------------------------------------------------------------------
1466void PmuppGui::add(QString varStr, QVector<int> idx)
1467{
1468 // analyze varStr to see how many variables are present
1469 // the PVarHandler class handles only ONE variable of ONE collection.
1470 QStringList varNames = getVarNames(varStr);
1471
1472 // expose every loaded collection inside a <python> block (coll[]/collErr[]),
1473 // addressable by index and by name.
1474 std::vector<PmuppCollection*> allColl;
1475 for (int i=0; i<fParamDataHandler->GetNoOfCollections(); i++)
1476 allColl.push_back(fParamDataHandler->GetCollection(i));
1477
1478 // go through all collections
1479 for (int i=0; i<idx.size(); i++) {
1480 // go through all the defined variables
1481 for (int j=0; j<varNames.count(); j++) {
1482 PVarHandler var(fParamDataHandler->GetCollection(idx[i]),
1483 varStr.toLatin1().data(),
1484 varNames[j].toLatin1().data(),
1485 allColl);
1486 if (!var.isValid()) {
1488 return;
1489 }
1490 // check if variable name for the given collection already exists
1491 int var_idx=-1;
1492 for (int k=0; k<fVarHandler.size(); k++) {
1493 if ((fVarHandler[k].getVarName() == var.getVarName()) &&
1494 (fVarHandler[k].getCollName()) == var.getCollName()) {
1495 var_idx = k;
1496 }
1497 }
1498 if (var_idx == -1) // a new variable
1499 fVarHandler.push_back(var); // collect all valid variables
1500 else // replace an already existing variable
1501 fVarHandler[var_idx] = var;
1502 }
1503 }
1504
1505 // add the new variable to the paramter list (fParamList)
1506 // update the parameter list (GUI)
1507 updateParamList(fColList->currentRow());
1508 // update XY list (GUI)
1510
1511}
1512
1513//-----------------------------------------------------------------------------
1519{
1520 // get error messages
1521 QString mupp_err = QString("%1/.musrfit/mupp/mupp_err.log").arg(QString(qgetenv("HOME")));
1522 QFile fin(mupp_err);
1523 QString errStr("");
1524 if (fin.open(QIODevice::ReadOnly | QIODevice::Text)) {
1525 QTextStream in(&fin);
1526 while (!in.atEnd()) {
1527 errStr += in.readLine();
1528 errStr += "\n";
1529 }
1530 }
1531 fin.close();
1532 QFile::remove(mupp_err);
1533
1534 if (errStr.isEmpty())
1535 errStr = "unknown error - should never happen.";
1536 QString msg = QString("Parse error(s):\n");
1537 msg += errStr;
1538 PVarErrorDialog *errDlg = new PVarErrorDialog(msg);
1539}
1540
1541//-----------------------------------------------------------------------------
1548QStringList PmuppGui::getVarNames(QString parseStr)
1549{
1550 QStringList varNames;
1551 QString str;
1552 int idxS=0, idxE=0;
1553
1554 // a <python> block carries the mupp 'var' declarations only in the part
1555 // before the block; the python code must not be scanned for 'var'.
1556 int pyIdx = parseStr.indexOf("<python>");
1557 if (pyIdx != -1)
1558 parseStr = parseStr.left(pyIdx);
1559
1560 while (idxS != -1) {
1561 idxS = parseStr.indexOf("var", idxS);
1562 if (idxS != -1) {
1563 idxE = parseStr.indexOf("=", idxS);
1564 str = parseStr.mid(idxS+4, idxE-idxS-4).trimmed();
1565 if (!str.endsWith("Err"))
1566 varNames << str;
1567 idxS = idxE;
1568 }
1569 }
1570
1571 return varNames;
1572}
1573
1574//-----------------------------------------------------------------------------
1583QVector<double> PmuppGui::getValues(QString collName, QString paramName, bool &ok)
1584{
1585 ok = false;
1586 QVector<double> values;
1587
1588 // 1st check if paramName is found in collection
1589 values = fParamDataHandler->GetValues(collName, paramName);
1590
1591 // 2nd check if paramName is found in variable handler
1592 if (values.size() == 0) {
1593 for (int i=0; i<fVarHandler.size(); i++) {
1594 if ((fVarHandler[i].getCollName() == collName) &&
1595 (fVarHandler[i].getVarName() == paramName)) {
1596 // getValues() returns by value: bind it to a single object so begin()
1597 // and end() refer to the same vector (calling it twice yields iterators
1598 // into two distinct temporaries -> UB / crash).
1599 std::vector<double> vec = fVarHandler[i].getValues();
1600 values = QVector<double>(vec.begin(), vec.end());
1601 }
1602 }
1603 }
1604
1605 if (values.size() > 0)
1606 ok = true;
1607
1608 return values;
1609}
1610
1611//-----------------------------------------------------------------------------
1621QVector<double> PmuppGui::getPosErr(QString collName, QString paramName, bool &ok)
1622{
1623 ok = false;
1624 QVector<double> values;
1625
1626 // 1st check if paramName is found in collection
1627 values = fParamDataHandler->GetPosErr(collName, paramName);
1628
1629 // 2nd check if paramName is found in variable handler
1630 if (values.size() == 0) {
1631 for (int i=0; i<fVarHandler.size(); i++) {
1632 if ((fVarHandler[i].getCollName() == collName) &&
1633 (fVarHandler[i].getVarName() == paramName)) {
1634 // see getValues(): bind the by-value result to one object before
1635 // taking begin()/end().
1636 std::vector<double> vec = fVarHandler[i].getErrors();
1637 values = QVector<double>(vec.begin(), vec.end());
1638 }
1639 }
1640 }
1641
1642 if (values.size() > 0)
1643 ok = true;
1644
1645 return values;
1646}
1647
1648//-----------------------------------------------------------------------------
1658QVector<double> PmuppGui::getNegErr(QString collName, QString paramName, bool &ok)
1659{
1660 ok = false;
1661 QVector<double> values;
1662
1663 // 1st check if paramName is found in collection
1664 values = fParamDataHandler->GetNegErr(collName, paramName);
1665
1666 // 2nd check if paramName is found in variable handler
1667 if (values.size() == 0) {
1668 for (int i=0; i<fVarHandler.size(); i++) {
1669 if ((fVarHandler[i].getCollName() == collName) &&
1670 (fVarHandler[i].getVarName() == paramName)) {
1671 // see getValues(): bind the by-value result to one object before
1672 // taking begin()/end().
1673 std::vector<double> vec = fVarHandler[i].getErrors();
1674 values = QVector<double>(vec.begin(), vec.end());
1675 }
1676 }
1677 }
1678
1679 if (values.size() > 0)
1680 ok = true;
1681
1682 return values;
1683}
1684
1685//-----------------------------------------------------------------------------
1693{
1694 bool result = false;
1695
1696 if (tag == kXaxis) {
1697 for (int i=0; i<fXY.size(); i++) {
1698 for (int j=0; j<run.GetNoOfParam(); j++) {
1699 if (fXY[i].getXlabel().startsWith(run.GetParam(j).GetName())) {
1700 result = true;
1701 break;
1702 }
1703 }
1704 }
1705 } else if (tag == kYaxis) {
1706 for (int i=0; i<fXY.size(); i++) {
1707 for (int j=0; j<fXY[i].getYlabelSize(); j++) {
1708 for (int k=0; k<run.GetNoOfParam(); k++) {
1709 if (fXY[i].getYlabel(j).startsWith(run.GetParam(k).GetName())) {
1710 result = true;
1711 break;
1712 }
1713 }
1714 }
1715 }
1716 }
1717
1718 return result;
1719}
1720
1721//-----------------------------------------------------------------------------
1727{
1728 // first make sure that all x-labels are equivalent. They have the form '<label> (-#-)' and
1729 // all <label> must be equal
1730 QString str1, str2;
1731 int idx;
1732 str1 = fXY[0].getXlabel();
1733 idx = str1.lastIndexOf(" (-");
1734 str1.remove(idx, str1.length()-idx);
1735 for (int i=1; i<fXY.size(); i++) {
1736 str2 = fXY[i].getXlabel();
1737 idx = str2.lastIndexOf(" (-");
1738 str2.remove(idx, str2.length()-idx);
1739 if (str1 != str2)
1740 return false;
1741 }
1742
1743 // make sure that the number of all y-label items is equal
1744 for (int i=1; i<fXY.size(); i++) {
1745 if (fXY[0].getYlabelSize() != fXY[i].getYlabelSize())
1746 return false;
1747 }
1748
1749 // make sure that the y-labels are equivalent.
1750 for (int j=0; j<fXY[0].getYlabelSize(); j++) {
1751 str1 = fXY[0].getYlabel(j);
1752 idx = str1.lastIndexOf(" (-");
1753 str1.remove(idx, str1.length()-idx);
1754 for (int i=1; i<fXY.size(); i++) {
1755 str2 = fXY[i].getYlabel(j);
1756 idx = str2.lastIndexOf(" (-");
1757 str2.remove(idx, str2.length()-idx);
1758 if (str1 != str2)
1759 return false;
1760 }
1761 }
1762
1763 return true;
1764}
1765
1766//-----------------------------------------------------------------------------
1774{
1775 QString str = QString("(-%1-)").arg(idx);
1776
1777 for (int i=0; i<fXY.size(); i++) {
1778 if (fXY[i].getXlabel().contains(str))
1779 return true;
1780 }
1781
1782 return false;
1783}
1784
1785//-----------------------------------------------------------------------------
1791void PmuppGui::replaceIndex(PmuppXY &data, const int idx)
1792{
1793 // handle x-label
1794 QString label = data.getXlabel();
1795 int pos = label.lastIndexOf(" (-");
1796 label.truncate(pos);
1797 QString str = QString(" (-%1-)").arg(idx);
1798 label += str;
1799 data.setXlabel(label);
1800
1801 // handle y-label(s)
1802 for (int i=0; i<data.getYlabelSize(); i++) {
1803 label = data.getYlabel(i);
1804 int pos = label.lastIndexOf(" (-");
1805 label.truncate(pos);
1806 label += str;
1807 data.setYlabel(i, label);
1808 }
1809
1810 data.setCollectionTag(idx);
1811}
1812
1813//-----------------------------------------------------------------------------
1820{
1821 int idx=-1;
1822
1823 for (int i=0; i<fXY.size(); i++) {
1824 if (fXY[i].getXlabel() == label) {
1825 idx = i;
1826 break;
1827 }
1828 }
1829
1830 return idx;
1831}
1832
1833//-----------------------------------------------------------------------------
1838void PmuppGui::dropOnViewX(QListWidgetItem *item)
1839{
1840 if (item == 0)
1841 return;
1842
1843 if (item->text().contains("(-"))
1844 return;
1845
1846 int idx = fColList->currentRow();
1847 QString xLabel = QString("%1 (-%2-)").arg(item->text()).arg(idx);
1848
1849 // check if it is not already present
1850 for (int i=0; i<fViewX->count(); i++) {
1851 if (fViewX->item(i)->text() == xLabel) {
1852 fViewX->removeItemWidget(item);
1853 delete item;
1854 return;
1855 }
1856 }
1857
1858 fViewX->setCurrentItem(item);
1859 fViewX->currentItem()->setText(xLabel);
1860
1861 // add the item to the XY list
1862 PmuppXY xyItem;
1863 xyItem.setCollectionTag(idx);
1864 xyItem.setXlabel(xLabel);
1865
1866 fXY.push_back(xyItem);
1867}
1868
1869//-----------------------------------------------------------------------------
1874void PmuppGui::dropOnViewY(QListWidgetItem *item)
1875{
1876 if (item == 0)
1877 return;
1878
1879 if (item->text().contains("(-"))
1880 return;
1881
1882 // make sure that any x-parameter selection is already present
1883 if (fViewX->count() == 0) {
1884 fViewY->removeItemWidget(item);
1885 delete item;
1886 QMessageBox::warning(this, "WARNING", "It is compulsory to have at least one x-parameter set\nbefore trying to add a y-parameter.");
1887 return;
1888 }
1889
1890 int idx = fColList->currentRow();
1891 QString yLabel = QString("%1 (-%2-)").arg(item->text()).arg(idx);
1892
1893 // check if it is not already present
1894 for (int i=0; i<fViewY->count(); i++) {
1895 if (fViewY->item(i)->text() == yLabel) {
1896 fViewY->removeItemWidget(item);
1897 delete item;
1898 return;
1899 }
1900 }
1901
1902 fViewY->setCurrentItem(item);
1903 fViewY->currentItem()->setText(yLabel);
1904
1905 // add the item to the XY list
1906 idx=getXlabelIndex(fViewX->currentItem()->text());
1907 if (idx == -1)
1908 return;
1909
1910 fXY[idx].addYlabel(yLabel);
1911}
1912
1913//-----------------------------------------------------------------------------
1918{
1919 // clear Y view
1920 fViewY->clear();
1921
1922 // get proper X view item
1923 QListWidgetItem *item = fViewX->currentItem();
1924 if (item == 0)
1925 return;
1926
1927 QString xLabel = item->text();
1928 int idx = getXlabelIndex(xLabel);
1929 if (idx == -1)
1930 return;
1931
1932 for (int i=0; i<fXY[idx].getYlabelSize(); i++)
1933 fViewY->addItem(fXY[idx].getYlabel(i));
1934}
1935
1936//-----------------------------------------------------------------------------
1941{
1942 QVector<PmuppMarker> marker = fAdmin->getMarkers();
1943 QVector<PmuppColor> color = fAdmin->getColors();
1944
1945 if (fXY.size() == 0) {
1946 QMessageBox::information(this, "createMacro", "No parameter list present.");
1947 return;
1948 }
1949
1950 if (fMacroName.isEmpty()) {
1951 fMacroName = "__mupp.C";
1952 }
1953 if (!fMacroPath.isEmpty()) {
1954 if (fMacroPath.endsWith("/"))
1955 fMacroName.prepend(fMacroPath);
1956 else
1957 fMacroName.prepend(fMacroPath + "/");
1958 }
1959
1960 QFile file(fMacroName);
1961 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
1962 QMessageBox::critical(this, "ERROR", "Couldn't open macro file for writting.");
1963 return;
1964 }
1965
1966 QTextStream fout(&file);
1967
1968 fout << "// " << fMacroName.toLatin1().data() << Qt::endl;
1969 fout << "// " << QDateTime::currentDateTime().toString("yy/MM/dd - HH:mm:ss") << Qt::endl;
1970 fout << "// " << Qt::endl;
1971 fout << "{" << Qt::endl;
1972 fout << " gROOT->Reset();" << Qt::endl;
1973 fout << Qt::endl;
1974 fout << " gStyle->SetOptTitle(0);" << Qt::endl;
1975 fout << " gStyle->SetOptDate(0);" << Qt::endl;
1976 fout << " gStyle->SetPadColor(TColor::GetColor(255,255,255)); // pad bkg to white" << Qt::endl;
1977 fout << " gStyle->SetCanvasColor(TColor::GetColor(255,255,255)); // canvas bkg to white" << Qt::endl;
1978 fout << Qt::endl;
1979 fout << " Int_t nn=0, i=0;" << Qt::endl;
1980 fout << " Double_t xx[512];" << Qt::endl;
1981 fout << " Double_t xxPosErr[512];" << Qt::endl;
1982 fout << " Double_t xxNegErr[512];" << Qt::endl;
1983 fout << " Double_t yy[512];" << Qt::endl;
1984 fout << " Double_t yyPosErr[512];" << Qt::endl;
1985 fout << " Double_t yyNegErr[512];" << Qt::endl;
1986
1987 // create all the necessary TGraph's
1988 int collTag = -1, pos;
1989 QString collName("");
1990 QString xLabel(""), yLabel("");
1991 char gLabel[128];
1992 QVector<double> xx, xxPosErr, xxNegErr, yy, yyPosErr, yyNegErr;
1993 double xMin=1.0e10, xMax=-1.0e10, yMin=1.0e10, yMax=-1.0e10;
1994 bool ok;
1995 for (int i=0; i<fXY.size(); i++) {
1996 collTag = fXY[i].getCollectionTag();
1997 collName = fColList->item(collTag)->text();
1998 // x-label
1999 xLabel = fXY[i].getXlabel();
2000 pos = xLabel.indexOf(" (-");
2001 xLabel.remove(pos, xLabel.length()-pos);
2002 // get x-vector and x-errors (x-errors are optional; use 0.0 if not available)
2003 xx = getValues(collName, xLabel, ok);
2004 if (!ok) {
2005 QString msg = QString("Couldn't get x-axis data from '%1', coll: '%2'").arg(xLabel).arg(collName);
2006 QMessageBox::critical(this, "ERROR", msg);
2007 return;
2008 }
2009 xxPosErr = getPosErr(collName, xLabel, ok);
2010 if (!ok)
2011 xxPosErr = QVector<double>(xx.size(), 0.0);
2012 xxNegErr = getNegErr(collName, xLabel, ok);
2013 if (!ok)
2014 xxNegErr = QVector<double>(xx.size(), 0.0);
2015 getMinMax(xx, xMin, xMax);
2016 // a couple of x-vector specifics
2017 if ((xLabel == "dataT") || (xLabel == "dataE"))
2018 xMin = 0.0;
2019 // get y-, yPosErr-, and yNegErr-vector
2020 for (int j=0; j<fXY[i].getYlabelSize(); j++) {
2021 // y-label
2022 yLabel = fXY[i].getYlabel(j);
2023 pos = yLabel.indexOf(" (-");
2024 yLabel.remove(pos, yLabel.length()-pos);
2025 // get y-vector
2026 yy = getValues(collName, yLabel, ok);
2027 if (!ok) {
2028 QString msg = QString("Couldn't get y-axis data from '%1', coll: '%2'").arg(yLabel).arg(collName);
2029 QMessageBox::critical(this, "ERROR", msg);
2030 return;
2031 }
2032 yyPosErr = getPosErr(collName, yLabel, ok);
2033 if (!ok) {
2034 QString msg = QString("Couldn't get y-axis pos. error data from '%1', coll: '%2'").arg(yLabel).arg(collName);
2035 QMessageBox::critical(this, "ERROR", msg);
2036 return;
2037 }
2038 yyNegErr = getNegErr(collName, yLabel, ok);
2039 if (!ok) {
2040 QString msg = QString("Couldn't get y-axis neg. error data from '%1', coll: '%2'").arg(yLabel).arg(collName);
2041 QMessageBox::critical(this, "ERROR", msg);
2042 return;
2043 }
2044 yLabel = substituteDefaultLabels(yLabel);
2045 getMinMax(yy, yMin, yMax);
2046 // create TGraph objects
2047 fout << Qt::endl;
2048 snprintf(gLabel, sizeof(gLabel), "g_%d_%d", i, j);
2049 fout << " nn = " << xx.size() << ";" << Qt::endl;
2050 fout << Qt::endl;
2051 fout << " // xx" << Qt::endl;
2052 for (int k=0; k<xx.size(); k++) {
2053 fout << " xx[" << k << "]=" << xx[k] << ";" << Qt::endl;
2054 }
2055 fout << " // xxPosErr" << Qt::endl;
2056 for (int k=0; k<xx.size(); k++) {
2057 fout << " xxPosErr[" << k << "]=" << xxPosErr[k] << ";" << Qt::endl;
2058 }
2059 fout << " // xxNegErr" << Qt::endl;
2060 for (int k=0; k<xx.size(); k++) {
2061 fout << " xxNegErr[" << k << "]=" << fabs(xxNegErr[k]) << ";" << Qt::endl;
2062 }
2063 fout << " // yy" << Qt::endl;
2064 for (int k=0; k<xx.size(); k++) {
2065 fout << " yy[" << k << "]=" << yy[k] << ";" << Qt::endl;
2066 }
2067 fout << " // yyPosErr" << Qt::endl;
2068 for (int k=0; k<xx.size(); k++) {
2069 fout << " yyPosErr[" << k << "]=" << yyPosErr[k] << ";" << Qt::endl;
2070 }
2071 fout << " // yyNegErr" << Qt::endl;
2072 for (int k=0; k<xx.size(); k++) {
2073 fout << " yyNegErr[" << k << "]=" << fabs(yyNegErr[k]) << ";" << Qt::endl;
2074 }
2075 fout << Qt::endl;
2076 fout << " TGraphAsymmErrors *" << gLabel << " = new TGraphAsymmErrors(nn, xx, yy, xxNegErr, xxPosErr, yyNegErr, yyPosErr);" << Qt::endl;
2077 }
2078 }
2079 fout << Qt::endl;
2080 fout << " //***************" << Qt::endl;
2081 fout << " // plotting " << Qt::endl;
2082 fout << " //***************" << Qt::endl;
2083 fout << " TCanvas *c1 = new TCanvas(\"c1\", \"" << fMacroName.toLatin1().data() << "\", 10, 10, 600, 700);" << Qt::endl;
2084 fout << Qt::endl;
2085 int idx, r, g, b;
2086 PmuppMarker markerObj;
2087 for (int i=0; i<fXY.size(); i++) {
2088 xLabel = fXY[i].getXlabel();
2089 pos = xLabel.indexOf(" (-");
2090 xLabel.remove(pos, xLabel.length()-pos);
2091 xLabel = substituteDefaultLabels(xLabel);
2092 for (int j=0; j<fXY[i].getYlabelSize(); j++) {
2093 idx = i*fXY[i].getYlabelSize()+j; // graph number idx
2094 markerObj = marker[idx];
2095 yLabel = fXY[i].getYlabel(j);
2096 pos = yLabel.indexOf(" (-");
2097 yLabel.remove(pos, yLabel.length()-pos);
2098 yLabel = substituteDefaultLabels(yLabel);
2099 snprintf(gLabel, sizeof(gLabel), "g_%d_%d", i, j);
2100 if ((i==0) && (j==0)) { // first graph
2101 if (idx < marker.size()) {
2102 fout << " " << gLabel << "->SetMarkerStyle(" << markerObj.getMarker() << ");" << Qt::endl;
2103 fout << " " << gLabel << "->SetMarkerSize(" << markerObj.getMarkerSize() << ");" << Qt::endl;
2104 } else {
2105 fout << " " << gLabel << "->SetMarkerStyle(20); // bullet" << Qt::endl;
2106 fout << " " << gLabel << "->SetMarkerSize(1.5);" << Qt::endl;
2107 }
2108 if (idx < color.size()) {
2109 color[idx].getRGB(r, g, b);
2110 fout << " " << gLabel << "->SetMarkerColor(TColor::GetColor(" << r << "," << g << "," << b << "));" << Qt::endl;
2111 fout << " " << gLabel << "->SetLineColor(TColor::GetColor(" << r << "," << g << "," << b << "));" << Qt::endl;
2112 } else {
2113 fout << " " << gLabel << "->SetMarkerColor(kBlue);" << Qt::endl;
2114 fout << " " << gLabel << "->SetLineColor(kBlue);" << Qt::endl;
2115 }
2116 fout << " " << gLabel << "->SetFillColor(kWhite);" << Qt::endl;
2117 fout << " " << gLabel << "->GetXaxis()->SetTitle(\"" << xLabel.toLatin1().data() << "\");" << Qt::endl;
2118 fout << " " << gLabel << "->GetXaxis()->SetTitleSize(0.05);" << Qt::endl;
2119 fout << " " << gLabel << "->GetXaxis()->SetRangeUser(" << 0.95*xMin << ", " << 1.05*xMax << ");" << Qt::endl;
2120 fout << " " << gLabel << "->GetYaxis()->SetTitle(\"" << yLabel.toLatin1().data() << "\");" << Qt::endl;
2121 fout << " " << gLabel << "->GetYaxis()->SetTitleSize(0.05);" << Qt::endl;
2122 fout << " " << gLabel << "->GetYaxis()->SetTitleOffset(1.30);" << Qt::endl;
2123 fout << " " << gLabel << "->GetYaxis()->SetRangeUser(" << 0.95*yMin << ", " << 1.05*yMax << ");" << Qt::endl;
2124 fout << " " << gLabel << "->GetXaxis()->SetDecimals(kTRUE);" << Qt::endl;
2125 fout << " " << gLabel << "->Draw(\"AP\");" << Qt::endl;
2126 } else { // consecutive graphs
2127 if (idx < marker.size()) {
2128 fout << " " << gLabel << "->SetMarkerStyle(" << markerObj.getMarker() << ");" << Qt::endl;
2129 fout << " " << gLabel << "->SetMarkerSize(" << markerObj.getMarkerSize() << ");" << Qt::endl;
2130 } else {
2131 fout << " " << gLabel << "->SetMarkerStyle(" << 21+j << ");" << Qt::endl;
2132 fout << " " << gLabel << "->SetMarkerSize(1.5);" << Qt::endl;
2133 }
2134 if (idx < color.size()) {
2135 color[idx].getRGB(r, g, b);
2136 fout << " " << gLabel << "->SetMarkerColor(TColor::GetColor(" << r << "," << g << "," << b << "));" << Qt::endl;
2137 fout << " " << gLabel << "->SetLineColor(TColor::GetColor(" << r << "," << g << "," << b << "));" << Qt::endl;
2138 } else {
2139 fout << " " << gLabel << "->SetMarkerColor(kBlue);" << Qt::endl;
2140 fout << " " << gLabel << "->SetLineColor(kBlue);" << Qt::endl;
2141 }
2142 fout << " " << gLabel << "->SetFillColor(kWhite);" << Qt::endl;
2143 fout << " " << gLabel << "->Draw(\"Psame\");" << Qt::endl;
2144 }
2145 }
2146 }
2147 fout << "}" << Qt::endl;
2148
2149 // clear macro name
2150 fMacroName = QString("");
2151}
2152
2153//-----------------------------------------------------------------------------
2159{
2160 // check if there is something to be plotted
2161 if (fXY.size() == 0) {
2162 QMessageBox::information(this, "PLOT", "No parameter list present.");
2163 return;
2164 }
2165
2166 // write data file with path name: $HOME/.musrfit/mupp/_mupp_<startUpTime>.dat
2167 // where <startUpTime> is the time when mupp has been started.
2168 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2169 QString pathName = QString("%1/.musrfit/mupp/_mupp_%2.dat").arg(env.value("HOME")).arg(fDatime);
2170
2171 int collTag = -1, pos;
2172 QString collName("");
2173 QString xLabel(""), yLabel("");
2174 QVector<double> xx, xxPosErr, xxNegErr, yy, yyPosErr, yyNegErr;
2175 QVector< QVector<double> > yyy, yyyPosErr, yyyNegErr;
2176 bool ok;
2177
2178 QFile file(pathName);
2179 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
2180 QMessageBox::critical(this, "ERROR", "Couldn't write necessary temporary file!");
2181 return;
2182 }
2183 QTextStream fout(&file);
2184
2185 fout << "% path file name: " << pathName << Qt::endl;
2186 fout << "% creation time : " << QDateTime::currentDateTime().toString("yyyy.MM.dd - hh:mm:ss") << Qt::endl;
2187 fout << "%" << Qt::endl;
2188 for (int i=0; i<fXY.size(); i++) {
2189 // header info
2190 collTag = fXY[i].getCollectionTag();
2191 collName = fColList->item(collTag)->text();
2192
2193 fout << "% ---------" << Qt::endl;
2194 fout << "% collName = " << collName << Qt::endl;
2195 fout << "% start ---" << Qt::endl;
2196
2197 // x-label
2198 xLabel = fXY[i].getXlabel();
2199 pos = xLabel.indexOf(" (-");
2200 xLabel.remove(pos, xLabel.length()-pos);
2201 // get x-vector and x-errors (x-errors are optional; use 0.0 if not available)
2202 xx = getValues(collName, xLabel, ok);
2203 if (!ok) {
2204 QString msg = QString("Couldn't get x-axis data from '%1', coll: '%2'").arg(xLabel).arg(collName);
2205 QMessageBox::critical(this, "ERROR", msg);
2206 return;
2207 }
2208 xxPosErr = getPosErr(collName, xLabel, ok);
2209 if (!ok)
2210 xxPosErr = QVector<double>(xx.size(), 0.0);
2211 xxNegErr = getNegErr(collName, xLabel, ok);
2212 if (!ok)
2213 xxNegErr = QVector<double>(xx.size(), 0.0);
2214
2215 xLabel = substituteDefaultLabels(xLabel);
2216 fout << "xLabel: " << xLabel << ", ";
2217 for (int j=0; j<fXY[i].getYlabelSize()-1; j++) {
2218 // get y-label
2219 yLabel = fXY[i].getYlabel(j);
2220 pos = yLabel.indexOf(" (-");
2221 yLabel.remove(pos, yLabel.length()-pos);
2222 // get y-vector and errors
2223 yy = getValues(collName, yLabel, ok);
2224 if (!ok) {
2225 QString msg = QString("Couldn't get y-axis data from '%1', coll: '%2'").arg(yLabel).arg(collName);
2226 QMessageBox::critical(this, "ERROR", msg);
2227 return;
2228 }
2229 yyy.push_back(yy);
2230 yyPosErr = getPosErr(collName, yLabel, ok);
2231 if (!ok) {
2232 QString msg = QString("Couldn't get y-axis pos. error data from '%1', coll: '%2'").arg(yLabel).arg(collName);
2233 QMessageBox::critical(this, "ERROR", msg);
2234 return;
2235 }
2236 yyyPosErr.push_back(yyPosErr);
2237 yyNegErr = getNegErr(collName, yLabel, ok);
2238 if (!ok) {
2239 QString msg = QString("Couldn't get y-axis neg. error data from '%1', coll: '%2'").arg(yLabel).arg(collName);
2240 QMessageBox::critical(this, "ERROR", msg);
2241 return;
2242 }
2243 yyyNegErr.push_back(yyNegErr);
2244 yLabel = substituteDefaultLabels(yLabel);
2245 fout << "yLabel: " << yLabel << ", ";
2246 }
2247 // get last y-label
2248 int idx=fXY[i].getYlabelSize()-1;
2249 yLabel = fXY[i].getYlabel(idx);
2250 pos = yLabel.indexOf(" (-");
2251 yLabel.remove(pos, yLabel.length()-pos);
2252 // get y-vector and errors
2253 yy = getValues(collName, yLabel, ok);
2254 if (!ok) {
2255 QString msg = QString("Couldn't get y-axis data from '%1', coll: '%2'").arg(yLabel).arg(collName);
2256 QMessageBox::critical(this, "ERROR", msg);
2257 return;
2258 }
2259 yyy.push_back(yy);
2260 yyPosErr = getPosErr(collName, yLabel, ok);
2261 if (!ok) {
2262 QString msg = QString("Couldn't get y-axis pos. error data from '%1', coll: '%2'").arg(yLabel).arg(collName);
2263 QMessageBox::critical(this, "ERROR", msg);
2264 return;
2265 }
2266 yyyPosErr.push_back(yyPosErr);
2267 yyNegErr = getNegErr(collName, yLabel, ok);
2268 if (!ok) {
2269 QString msg = QString("Couldn't get y-axis neg. error data from '%1', coll: '%2'").arg(yLabel).arg(collName);
2270 QMessageBox::critical(this, "ERROR", msg);
2271 return;
2272 }
2273 yyyNegErr.push_back(yyNegErr);
2274
2275 yLabel = substituteDefaultLabels(yLabel);
2276 fout << "yLabel: " << yLabel << Qt::endl;
2277
2278 // normalize if wished
2279 if (fNormalize) {
2280 double max=0.0;
2281 for (int k=0; k<yyy.size(); k++) {
2282 max=0.0;
2283 for (int j=0; j<xx.size(); j++) {
2284 if (yyy[k][j] > max)
2285 max = yyy[k][j];
2286 }
2287 for (int j=0; j<xx.size(); j++) {
2288 yyy[k][j] /= max;
2289 yyyPosErr[k][j] /= max;
2290 yyyNegErr[k][j] /= max;
2291 }
2292 }
2293 }
2294
2295 // data: x, xPosErr, xNegErr, y1, y1PosErr, y1NegErr, ...
2296 for (int j=0; j<xx.size(); j++) {
2297 fout << xx[j] << ", " << xxPosErr[j] << ", " << xxNegErr[j] << ", ";
2298 for (int k=0; k<yyy.size()-1; k++) {
2299 fout << yyy[k][j] << ", " << yyyPosErr[k][j] << ", " << yyyNegErr[k][j] << ", ";
2300 }
2301 idx = yyy.size()-1;
2302 fout << yyy[idx][j] << ", " << yyyPosErr[idx][j] << ", " << yyyNegErr[idx][j];
2303 fout << Qt::endl;
2304 }
2305
2306 fout << "% end -----" << Qt::endl;
2307
2308 // clear collection related vectors
2309 yyy.clear();
2310 yyyPosErr.clear();
2311 yyyNegErr.clear();
2312 }
2313
2314 file.close();
2315
2316 // get first free mupp instance
2318
2319 // issue a system message to inform to ROOT parameter plotter (rpp) that new data are available
2320 key_t key;
2321 struct mbuf msg;
2322 int flags, msqid;
2323
2324 // generate the ICP message queue key
2325 QString tmpPathName = QString("%1/.musrfit/mupp/_mupp_ftok_%2.dat").arg(env.value("HOME")).arg(fMuppInstance);
2326 file.setFileName(tmpPathName);
2327 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
2328 QMessageBox::critical(this, "ERROR", "Couldn't write necessary temporary file!");
2329 return;
2330 }
2331 fout.setDevice(&file);
2332 fout << QCoreApplication::applicationFilePath().toLatin1().data() << Qt::endl;
2333 file.close();
2334
2335 key = ftok(QCoreApplication::applicationFilePath().toLatin1().data(), fMuppInstance);
2336 if (key == -1) {
2337 QMessageBox::critical(this, "ERROR", QString("Couldn't obtain necessary key to install the IPC message queue (%1).").arg(std::strerror(errno)));
2338 return;
2339 }
2340
2341 // set the necessary IPC message queue flags
2342 flags = IPC_CREAT;
2343
2344 // open the message queue
2345 msqid = msgget(key, flags | S_IRUSR | S_IWUSR);
2346 if (msqid == -1) {
2347 QMessageBox::critical(this, "ERROR", QString("Couldn't open the IPC message queue (%1).").arg(std::strerror(errno)));
2348 return;
2349 }
2350
2351 // send message
2352 flags = IPC_NOWAIT;
2353 msg.mtype = 1;
2354 strncpy(msg.mtext, pathName.toLatin1().data(), PMUPP_MAX_MTEXT);
2355 if (msgsnd(msqid, &msg, strlen(msg.mtext)+1, flags) == -1) {
2356 QMessageBox::critical(this, "ERROR", QString("Couldn't send the IPC message (%1).").arg(std::strerror(errno)));
2357 return;
2358 }
2359
2360 // start native ROOT parameter plot application if not already running
2361 if (fMuppPlot == nullptr) { // not running yet
2362 startMuppPlot();
2363 } else {
2364 // check if mupp_plot is still running
2365 if (fMuppPlot->state() == QProcess::NotRunning) { // not running hence start it
2366 startMuppPlot();
2367 }
2368 }
2369}
2370
2371//-----------------------------------------------------------------------------
2376{
2377 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2378 QString cmd = QString("%1/bin/mupp_plot").arg(MUPP_PREFIX);
2379#if defined(Q_OS_DARWIN)
2380 cmd = QString("/Applications/mupp.app/Contents/MacOS/mupp_plot");
2381#endif
2382 QString workDir = QString("./");
2383 QStringList arg;
2384
2385 // feed the mupp instance
2386 arg << QString("%1").arg(fMuppInstance);
2387
2388 fMuppPlot = std::make_unique<QProcess>(this);
2389 if (fMuppPlot == nullptr) {
2390 QMessageBox::critical(this, "ERROR", "Couldn't invoke QProcess for mupp_plot!");
2391 return;
2392 }
2393
2394 // make sure that the system environment variables are properly set
2395#if defined(Q_OS_DARWIN)
2396 env.insert("DYLD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:/usr/local/lib:" + env.value("DYLD_LIBRARY_PATH"));
2397#else
2398 env.insert("LD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:" + env.value("LD_LIBRARY_PATH"));
2399#endif
2400 fMuppPlot->setProcessEnvironment(env);
2401 fMuppPlot->setWorkingDirectory(workDir);
2402 fMuppPlot->start(cmd, arg);
2403 if (!fMuppPlot->waitForStarted()) {
2404 // error handling
2405 QString msg(tr("Could not execute the output command: ")+cmd);
2406 QMessageBox::critical(this, tr("FATAL ERROR"), msg, QMessageBox::Close );
2407 return;
2408 }
2409}
2410
2411//-----------------------------------------------------------------------------
2416{
2417 QString cmd = fCmdLine->text();
2418
2419 fCmdLine->setText("$ ");
2420
2421 cmd = cmd.trimmed();
2422 cmd = cmd.remove("$ ");
2423 cmd = cmd.trimmed();
2424
2425 if (!cmd.compare("exit", Qt::CaseInsensitive) || !cmd.compare("quit", Qt::CaseInsensitive)) {
2426 aboutToQuit();
2427 } else if (!cmd.compare("load", Qt::CaseInsensitive) || !cmd.compare("open", Qt::CaseInsensitive)) {
2428 fileOpen();
2429 } else if (!cmd.compare("dump collections", Qt::CaseInsensitive)) {
2431 } else if (!cmd.compare("dump XY", Qt::CaseInsensitive)) {
2432 toolDumpXY();
2433 } else if (!cmd.compare("refresh", Qt::CaseInsensitive)) {
2434 refresh();
2435 } else if (!cmd.compare("plot", Qt::CaseInsensitive)) {
2436 plot();
2437 } else if (cmd.startsWith("macro")) { // cmd: macro <fln>
2438 QStringList tok = cmd.split(" ", Qt::SkipEmptyParts);
2439 if (tok.size() != 2) {
2440 QMessageBox::critical(this, "ERROR", QString("wrong macro cmd: %1.\nPlease check the help.").arg(cmd));
2441 return;
2442 }
2443 fMacroName = tok[1];
2444 createMacro();
2445 } else if (cmd.startsWith("path")) { // cmd: path <macro_path>
2446 QMessageBox::information(this , "INFO", "set's eventually the path for the macros to be saved.");
2447 // will set the path to where to save the macro
2448 QStringList tok = cmd.split(" ", Qt::SkipEmptyParts);
2449 if (tok.size() != 2) {
2450 QMessageBox::critical(this, "ERROR", QString("wrong path cmd: %1.\nPlease check the help.").arg(cmd));
2451 return;
2452 }
2453 // replace "~" -> "$HOME"
2454 fMacroPath = tok[1].replace("~", "$HOME");
2455 // if environment variable is found -> expand it
2456 QString envVar=fMacroPath;
2457 if (envVar.startsWith("$")) {
2458 envVar.remove("$");
2459 int pos = envVar.indexOf("/");
2460 if (pos > 0)
2461 envVar.remove(pos, fMacroPath.length()-pos);
2462 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2463 QString fullPath = env.value(envVar); // get environment variable value if present, otherwise "" is returned
2464 if (fullPath.isEmpty()) {
2465 fMacroPath = "";
2466 QMessageBox::critical(this, "ERROR", QString("Environment variable '%1' not present. Typo?!").arg(envVar.prepend("$")));
2467 return;
2468 }
2469 fMacroPath.replace(envVar.prepend("$"), fullPath);
2470 }
2471 } else if (cmd.startsWith("select") || cmd.startsWith("sc")) {
2472 selectCollection(cmd);
2473 } else if (cmd.startsWith("x")) {
2474 QStringList tok = cmd.split(" ", Qt::SkipEmptyParts);
2475 if (tok.size() > 1)
2476 addX(tok[1]);
2477 else
2478 QMessageBox::critical(this, "ERROR", QString("Found command 'x' without variable."));
2479 } else if (cmd.startsWith("y")) {
2480 QStringList tok = cmd.split(" ", Qt::SkipEmptyParts);
2481 if (tok.size() > 1)
2482 addY(tok[1]);
2483 else
2484 QMessageBox::critical(this, "ERROR", QString("Found command 'y' without variable."));
2485 } else if (cmd.startsWith("ditto")) {
2486 addDitto();
2487 } else if (cmd.startsWith("rmx")) {
2488 QStringList tok = cmd.split(" ", Qt::SkipEmptyParts);
2489 if (tok.size() > 1)
2490 removeX(tok[1]);
2491 else
2492 QMessageBox::critical(this, "ERROR", QString("Found command 'rmx' without variable."));
2493 } else if (cmd.startsWith("rmy")) {
2494 QStringList tok = cmd.split(" ", Qt::SkipEmptyParts);
2495 if (tok.size() > 1)
2496 removeY(tok[1]);
2497 else
2498 QMessageBox::critical(this, "ERROR", QString("Found command 'rmy' without variable."));
2499 } else if (cmd.startsWith("norm")) {
2500 QStringList tok = cmd.split(" ", Qt::SkipEmptyParts);
2501 if (tok.size() != 2) {
2502 QMessageBox::critical(this, "ERROR", "found wrong norm cmd, will ignore it.");
2503 return;
2504 }
2505 if (!tok[1].trimmed().compare("true", Qt::CaseInsensitive)) {
2506 fNormalizeAction->setChecked(true);
2507 } else if (!tok[1].trimmed().compare("false", Qt::CaseInsensitive)) {
2508 fNormalizeAction->setChecked(false);
2509 } else {
2510 QMessageBox::critical(this, "ERROR", "found wrong norm cmd, will ignore it.");
2511 return;
2512 }
2513 } else if (cmd.startsWith("add var")) {
2514 addVar();
2515 } else if (cmd.startsWith("flush")) {
2516 fCmdHistory.clear();
2517 fCmdLine->setText("$ ");
2518 fCmdLineHistory->clear();
2519 fCmdLineHistory->insertPlainText("$");
2520 } else if (cmd.startsWith("help")) {
2521 helpCmds();
2522 } else {
2523 helpCmds();
2524 }
2525}
2526
2527//-----------------------------------------------------------------------------
2532{
2533 // update collection list view
2535}
2536
2537//-----------------------------------------------------------------------------
2542{
2543 // check if collection is already present
2544 bool valid=false;
2545 PmuppCollection coll;
2546 for (int i=0; i<fParamDataHandler->GetNoOfCollections(); i++) {
2547 coll = fParamDataHandler->GetCollection(i, valid);
2548 if (isNewCollection(coll)) {
2549 fColList->addItem(coll.GetName());
2550 }
2551 }
2552}
2553
2554//-----------------------------------------------------------------------------
2560void PmuppGui::updateParamList(int currentRow)
2561{
2562 QListWidgetItem *item = fColList->item(currentRow);
2563 if (item == 0) {
2564 fParamList->clear();
2565 return;
2566 }
2567
2568 // update parameter list widget
2569 bool valid = false;
2570 PmuppCollection coll = fParamDataHandler->GetCollection(item->text(), valid);
2571 if (!valid) {
2572 return;
2573 }
2574
2575 PmuppRun run = coll.GetRun(0);
2576
2577 fParamList->clear();
2578 for (int i=0; i<run.GetNoOfParam(); i++) {
2579 fParamList->insertItem(i, run.GetParam(i).GetName());
2580 }
2581
2582 // check if this collection has defined variables, and if yes add them as well
2583 for (int i=0; i<fVarHandler.size(); i++) {
2584 if (fVarHandler[i].getCollName() == item->text()) {
2585 fParamList->addItem(fVarHandler[i].getVarName());
2586 }
2587 }
2588}
2589
2590//-----------------------------------------------------------------------------
2596{
2597 // 1st: remove XY with collection index idx from the list
2598 for (int i=0; i<fXY.size(); i++) {
2599 // since each collection is only once present, the following is good enough
2600 if (fXY[i].getCollectionTag() == idx) {
2601 fXY.remove(i);
2602 break;
2603 }
2604 }
2605
2606 // 2nd: re-number the XY list according to the new collections
2607 QString str("");
2608 int pos=-1;
2609 int oldIdx=-1;
2610 for (int i=0; i<fXY.size(); i++) {
2611 oldIdx = fXY[i].getCollectionTag();
2612 if (oldIdx > idx) {
2613 // correct collection tag
2614 fXY[i].setCollectionTag(oldIdx-1);
2615 // correct X label
2616 str = fXY[i].getXlabel();
2617 pos = str.indexOf("(");
2618 str.remove(pos, str.length()-pos);
2619 str += QString("(-%1-)").arg(oldIdx-1);
2620 fXY[i].setXlabel(str);
2621 // correct Y label
2622 for (int j=0; j<fXY[i].getYlabelSize(); j++) {
2623 str = fXY[i].getYlabel(j);
2624 pos = str.indexOf("(");
2625 str.remove(pos, str.length()-pos);
2626 str += QString("(-%1-)").arg(oldIdx-1);
2627 fXY[i].setYlabel(j, str);
2628 }
2629 }
2630 }
2631}
2632
2633//-----------------------------------------------------------------------------
2639{
2640 fViewX->clear();
2641
2642 for (int i=0; i<fXY.size(); i++) {
2643 fViewX->addItem(fXY[i].getXlabel());
2644 }
2645
2646 fViewX->setCurrentRow(0);
2647}
2648
2649//-----------------------------------------------------------------------------
2656{
2657 for (int i=0; i<fColList->count(); i++)
2658 if (fColList->item(i)->text() == coll.GetName())
2659 return false;
2660 return true;
2661}
2662
2663//-----------------------------------------------------------------------------
2668void PmuppGui::editCollName(QListWidgetItem *item)
2669{
2670 bool ok;
2671 QString oldName = item->text();
2672 QString newName = QInputDialog::getText(this, "Change Collection Name", "Collection Name",
2673 QLineEdit::Normal, oldName, &ok);
2674 if (ok && !newName.isEmpty()) {
2675 item->setText(newName);
2676 fParamDataHandler->GetCollection(oldName)->SetName(newName);
2677 fParamDataHandler->Dump();
2678 }
2679}
2680
2681//-----------------------------------------------------------------------------
2688void PmuppGui::getMinMax(QVector<double> &data, double &min, double &max)
2689{
2690 for (int i=0; i<data.size(); i++) {
2691 if (data[i] < min)
2692 min = data[i];
2693 if (data[i] > max)
2694 max = data[i];
2695 }
2696}
2697
2698//-----------------------------------------------------------------------------
2706{
2707 QString result(label);
2708
2709 if (label == "dataT") {
2710 result = QString("T (K)");
2711 } else if (label == "dataB") {
2712 result = QString("B (G)");
2713 } else if (label == "dataE") {
2714 result =QString("E (keV)");
2715 } else if (!label.compare("sigma", Qt::CaseInsensitive)) {
2716 if (fNormalize) {
2717 result = QString("#sigma/max(#sigma)");
2718 } else {
2719 result = QString("#sigma (1/#mus)");
2720 }
2721 } else if (!label.compare("lambda", Qt::CaseInsensitive)) {
2722 if (fNormalize) {
2723 result = QString("#lambda/max(#lambda)");
2724 } else {
2725 result = QString("#lambda (1/#mus)");
2726 }
2727 } else if (!label.compare("alpha_LR", Qt::CaseInsensitive)) {
2728 if (fNormalize) {
2729 result = QString("#alpha_{LR}/max(#alpha_{LR})");
2730 } else {
2731 result = QString("#alpha_{LR}");
2732 }
2733 } else if (!label.compare("alpha_TB", Qt::CaseInsensitive)) {
2734 if (fNormalize) {
2735 result = QString("#alpha_{TB}/max(#alpha_{TB})");
2736 } else {
2737 result = QString("#alpha_{TB}");
2738 }
2739 } else {
2740 if (fNormalize) {
2741 result = QString("Normalized ");
2742 result += label;
2743 }
2744 }
2745
2746 return result;
2747}
2748
2749//-----------------------------------------------------------------------------
2756{
2757 bool ok;
2758 int ival, pos=-1;
2759 QString str = cmd;
2760 if (cmd.contains("select")) {
2761 str.remove("select");
2762 str = str.trimmed();
2763 } else if (cmd.contains("sc")) {
2764 pos = cmd.indexOf("sc");
2765 str.remove(0, pos+2);
2766 str = str.trimmed();
2767 } else {
2768 return;
2769 }
2770
2771 ival = str.toInt(&ok);
2772 if (ok) { // it is a number
2773 if (ival < fColList->count())
2774 fColList->setCurrentRow(ival);
2775 else
2776 QMessageBox::critical(this, "ERROR",
2777 QString("Found Row Selection %1 which is > #Selections=%2").arg(ival).arg(fColList->count()));
2778 } else { // assume it is a collection name
2779 for (int i=0; i<fColList->count(); i++) {
2780 if (fColList->item(i)->text() == str) {
2781 fColList->setCurrentRow(i);
2782 break;
2783 }
2784 }
2785 }
2786}
2787
2788//-----------------------------------------------------------------------------
2795{
2796 // if fMuppInstance already set, i.e. != -1, do nothing
2797 if (fMuppInstance != -1)
2798 return fMuppInstance;
2799
2800 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2801 QString fln("");
2802 uint i=0;
2803 for (i=0; i<256; i++) {
2804 fln = QString("%1/.musrfit/mupp/_mupp_ftok_%2.dat").arg(env.value("HOME")).arg(i);
2805 if (!QFile::exists(fln))
2806 break;
2807 }
2808
2809 return i;
2810}
2811
Main GUI interface for the mupp (MusrFit Parameter Plotter) application.
Central manager class for loading and accessing parameter collections.
Definition Pmupp.h:306
Dialog for displaying variable parsing error messages.
Definition PmuppGui.h:214
PVarErrorDialog(QString errMsg)
Constructor that creates and displays the error dialog.
Definition PmuppGui.cpp:294
QPushButton * fOK
button to close the dialog
Definition PmuppGui.h:226
QPlainTextEdit * fErrMsg
text widget displaying the error message
Definition PmuppGui.h:225
The PVarHandler class handles variable parsing, evaluation, and data management.
Definition PVarHandler.h:69
QString getVarName()
Gets the variable name.
bool isValid()
Checks if the parsing and evaluation were successful.
QString getCollName()
Gets the collection name.
Main administration class for mupp configuration management.
Definition PmuppAdmin.h:325
Represents a collection of related experimental runs.
Definition Pmupp.h:234
void SetPathName(QString pathName)
Sets the full path name of the collection file.
Definition Pmupp.h:245
void SetName(QString name)
Sets the collection name.
Definition Pmupp.h:251
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
bool fDarkThemeIconsMenu
flag for dark theme menu icons
Definition PmuppGui.h:364
void getTheme()
Detects system theme (light/dark) and configures icons accordingly.
Definition PmuppGui.cpp:955
void addVar()
Opens dialog to add/manage variable definitions.
void remove()
Removes the selected collection from the list.
std::unique_ptr< QBoxLayout > fBoxLayout_Top
top horizontal layout (left->right)
Definition PmuppGui.h:385
std::unique_ptr< QListWidget > fColList
list widget displaying data collections
Definition PmuppGui.h:392
uint fMuppInstance
unique instance identifier for this mupp session
Definition PmuppGui.h:369
std::unique_ptr< QProcess > fMuppPlot
external process for ROOT-based plotting
Definition PmuppGui.h:415
void plot()
Generates and displays the plot using current configuration.
uint getFirstAvailableMuppInstance()
Finds the first available mupp instance number for IPC.
void writeCmdHistory()
Writes command history to disk before exit.
void check(QString varStr, QVector< int > idx)
Checks variable expressions for validity.
std::unique_ptr< QAction > fNormalizeAction
action for normalize toggle
Definition PmuppGui.h:382
virtual ~PmuppGui()
Destructor. Cleans up resources and saves command history.
Definition PmuppGui.cpp:543
std::unique_ptr< QBoxLayout > fBoxLayout_Main
main vertical layout (top->bottom)
Definition PmuppGui.h:384
int getXlabelIndex(QString label)
Gets the index of an X-axis label in the XY list.
std::unique_ptr< PVarDialog > fVarDlg
variable definition dialog
Definition PmuppGui.h:413
void addX(QString param="")
Adds a parameter to the X-axis.
bool allXYEqual()
Checks if all X-Y configurations are identical.
void add(QString varStr, QVector< int > idx)
Adds a validated variable expression.
std::unique_ptr< QPlainTextEdit > fCmdLineHistory
text area displaying command history
Definition PmuppGui.h:407
std::unique_ptr< QLabel > fXaxisLabel
label for X-axis selection area
Definition PmuppGui.h:396
std::unique_ptr< QPushButton > fAddX
button to add parameter to X-axis
Definition PmuppGui.h:400
void helpCmds()
Shows help dialog with available commands.
Definition PmuppGui.cpp:859
std::unique_ptr< QListWidget > fViewY
list widget showing current Y-axis parameters
Definition PmuppGui.h:399
void selectCollection(QString cmd)
Selects a collection based on command string.
void helpAboutQt()
Shows Qt framework information dialog.
Definition PmuppGui.cpp:897
void toolDumpCollections()
Dumps collection information for debugging purposes.
Definition PmuppGui.cpp:817
void refresh()
Refreshes the collection list from data handler.
void getMinMax(QVector< double > &data, double &min, double &max)
Finds minimum and maximum values in a data vector.
std::unique_ptr< QPushButton > fRemoveY
button to remove Y-axis parameter
Definition PmuppGui.h:404
void removeY(QString param="")
Removes a parameter from the Y-axis.
void createMacro()
Creates a ROOT macro file from current plot configuration.
void updateXYListGui()
Updates the X-Y axis list widgets in the GUI.
void editCollName(QListWidgetItem *item)
Handles editing of collection name via double-click.
bool fDarkThemeIconsToolbar
flag for dark theme toolbar icons
Definition PmuppGui.h:365
void setupToolActions()
Sets up Tools menu actions (Dump, Variables, Normalize).
Definition PmuppGui.cpp:659
std::unique_ptr< QWidget > fCentralWidget
central widget containing all GUI elements
Definition PmuppGui.h:378
PParamDataHandler * fParamDataHandler
handler for parameter data collections
Definition PmuppGui.h:371
void handleCmds()
Processes commands entered in the command line.
std::unique_ptr< QLineEdit > fCmdLine
line edit for command input
Definition PmuppGui.h:408
std::unique_ptr< QPushButton > fPlot
button to generate and display plot
Definition PmuppGui.h:405
QVector< double > getPosErr(QString collName, QString paramName, bool &ok)
Gets positive error values for a parameter.
std::unique_ptr< QSplitter > fColParamSplitter
splitter between collection and parameter lists
Definition PmuppGui.h:391
void fileExit()
Exits the application after cleanup.
Definition PmuppGui.cpp:808
EAxis
Enumeration for axis type identification.
Definition PmuppGui.h:359
@ kXaxis
X-axis (independent variable)
Definition PmuppGui.h:359
bool fNormalize
flag indicating normalization mode
Definition PmuppGui.h:366
QStringList getVarNames(QString parseStr)
Extracts variable names from a parse string.
void refreshY()
Refreshes the Y-axis list after variable changes.
QVector< double > getNegErr(QString collName, QString paramName, bool &ok)
Gets negative error values for a parameter.
void startMuppPlot()
Starts the external ROOT plotting process.
std::unique_ptr< QPushButton > fRemoveX
button to remove X-axis parameter
Definition PmuppGui.h:403
bool indexAlreadyPresent(int idx)
Checks if an index is already present in XY list.
void removeX(QString param="")
Removes a parameter from the X-axis.
void dropOnViewY(QListWidgetItem *item)
Handles drag-and-drop onto Y-axis view.
std::unique_ptr< QListWidget > fParamList
list widget displaying parameters in selected collection
Definition PmuppGui.h:393
void fileOpen()
Opens a file dialog to select parameter data files to load.
Definition PmuppGui.cpp:741
void setupHelpActions()
Sets up Help menu actions (Commands, About).
Definition PmuppGui.cpp:708
std::unique_ptr< QLabel > fYaxisLabel
label for Y-axis selection area
Definition PmuppGui.h:397
QString substituteDefaultLabels(QString label)
Substitutes default parameter labels with descriptive names.
QAction * fRecentFilesAction[MAX_RECENT_FILES]
array of the recent file actions
Definition PmuppGui.h:381
bool isNewCollection(PmuppCollection &coll)
Checks if a collection is new (not already in the list).
void fillRecentFiles()
Populates the recent files menu from configuration.
Definition PmuppGui.cpp:991
void fileOpenRecent()
Opens a recently used parameter file.
Definition PmuppGui.cpp:789
std::unique_ptr< QListWidget > fViewX
list widget showing current X-axis parameter
Definition PmuppGui.h:398
void addDitto()
Copies X-axis parameter to Y-axis (ditto function).
void dropOnViewX(QListWidgetItem *item)
Handles drag-and-drop onto X-axis view.
void replaceIndex(PmuppXY &data, const int idx)
Replaces an index in the XY data structure.
PmuppGui(QStringList fln)
Constructor. Creates the main GUI window.
Definition PmuppGui.cpp:343
std::unique_ptr< QPushButton > fAddDitto
button to copy X-axis parameter to Y-axis
Definition PmuppGui.h:402
bool fIgnoreThemeAutoDetection
flag to override automatic theme detection
Definition PmuppGui.h:363
QMenu * fRecentFilesMenu
recent file menu
Definition PmuppGui.h:380
void updateParamList(int currentRow)
Updates the parameter list based on selected collection.
void handleNewData()
Handles newly loaded data by updating GUI components.
QVector< QString > fCmdHistory
command history buffer for navigation
Definition PmuppGui.h:411
QString fMacroPath
directory path for ROOT macro generation
Definition PmuppGui.h:375
void aboutToQuit()
Slot called when application is about to quit. Saves state.
Definition PmuppGui.cpp:553
std::unique_ptr< QGridLayout > fGridLayout_Right
right grid layout (2 columns, 6 rows)
Definition PmuppGui.h:387
QString fMacroName
name of the generated ROOT macro file
Definition PmuppGui.h:376
void updateXYList(int idx)
Updates the X-Y axis configuration for a specific index.
void updateCollectionList()
Updates the collection list widget from data handler.
QVector< PmuppXY > fXY
vector of X-Y axis configurations
Definition PmuppGui.h:372
void setupFileActions()
Sets up File menu actions (Open, Recent Files, Exit).
Definition PmuppGui.cpp:611
void readCmdHistory()
Reads command history from disk at startup.
std::unique_ptr< QPushButton > fRefreshCollection
button to refresh collection list
Definition PmuppGui.h:395
std::unique_ptr< QLabel > fColLabel
label for collection/parameter section
Definition PmuppGui.h:390
std::unique_ptr< QPushButton > fAddY
button to add parameter to Y-axis
Definition PmuppGui.h:401
std::unique_ptr< QSplitter > fCmdSplitter
splitter between history and command input
Definition PmuppGui.h:406
PmuppAdmin * fAdmin
administration object managing configuration
Definition PmuppGui.h:362
std::unique_ptr< QBoxLayout > fBoxLayout_Cmd
command area horizontal layout (left->right)
Definition PmuppGui.h:388
void helpAbout()
Shows about dialog with application information.
Definition PmuppGui.cpp:884
QVector< double > getValues(QString collName, QString paramName, bool &ok)
Gets parameter values from a collection.
void parseErrMsgDlg()
Displays a dialog with variable parsing error messages.
QVector< PVarHandler > fVarHandler
vector of variable handlers
Definition PmuppGui.h:373
std::unique_ptr< QPushButton > fExitButton
button to exit application
Definition PmuppGui.h:409
bool findValue(PmuppRun &run, EAxis tag)
Finds parameter value in a run structure.
std::unique_ptr< QGridLayout > fGridLayout_Left
left grid layout (2 columns, 3 rows)
Definition PmuppGui.h:386
qint64 fDatime
timestamp for IPC message queue identification
Definition PmuppGui.h:368
void toolDumpXY()
Dumps X-Y axis information for debugging purposes.
Definition PmuppGui.cpp:830
void normalize()
Toggles normalization mode for plot data.
Definition PmuppGui.cpp:850
bool eventFilter(QObject *o, QEvent *e)
Event filter for handling keyboard and mouse events.
Definition PmuppGui.cpp:910
void addY(QString param="")
Adds a parameter to the Y-axis.
std::unique_ptr< QPushButton > fRemoveCollection
button to remove selected collection
Definition PmuppGui.h:394
Represents a plot marker style and size.
Definition PmuppAdmin.h:146
void getMarker(int &marker, double &size)
Gets both marker code and size.
Definition PmuppAdmin.h:170
double getMarkerSize()
Gets the marker size multiplier.
Definition PmuppAdmin.h:182
QString GetName()
Gets the parameter name.
Definition Pmupp.h:118
Represents all fit parameters from a single experimental run.
Definition Pmupp.h:156
PmuppParam GetParam(unsigned int idx)
Retrieves a parameter from a run by index.
Definition Pmupp.cpp:184
int GetNoOfParam()
Gets the number of parameters in this run.
Definition Pmupp.h:207
Data structure for X-Y axis label associations.
Definition PmuppGui.h:101
void setCollectionTag(int tag)
Sets the collection tag (identifier).
Definition PmuppGui.h:112
int getXlabelIdx()
Extracts the parameter index from the X-axis label.
Definition PmuppGui.cpp:205
QString fXlabel
X-axis parameter label.
Definition PmuppGui.h:191
void setYlabel(int idx, QString str)
Sets the Y-axis label at a specific index.
Definition PmuppGui.cpp:124
int getYlabelIdx(int idx)
Extracts the parameter index from a Y-axis label.
Definition PmuppGui.cpp:249
void removeYlabel(int idx)
Removes a Y-axis label by index.
Definition PmuppGui.cpp:141
void init()
Initializes the object to default state.
Definition PmuppGui.cpp:107
QString getYlabel(int idx)
Gets a Y-axis label by index.
Definition PmuppGui.cpp:181
QString getXlabel()
Gets the X-axis label.
Definition PmuppGui.h:155
void setXlabel(QString str)
Sets the X-axis label.
Definition PmuppGui.h:118
int fCollectionTag
identifier for the associated data collection
Definition PmuppGui.h:190
int getYlabelSize()
Gets the number of Y-axis labels.
Definition PmuppGui.h:167
QVector< QString > fYlabel
vector of Y-axis parameter labels
Definition PmuppGui.h:192
#define PMUPP_MAX_MTEXT
Maximum size of the message text buffer.
Definition mupp.h:61
#define MAX_RECENT_FILES
Maximum number of recent files to be tracked.
Definition mupp.h:53
The PCollInfo struct holds collection information.
Definition PVarDialog.h:50
QStringList fVarName
variable names of the given collection
Definition PVarDialog.h:52
QString fCollName
collection name (may include path)
Definition PVarDialog.h:51
Message buffer structure for inter-process communication.
Definition mupp.h:70
char mtext[PMUPP_MAX_MTEXT]
message body containing the actual message data
Definition mupp.h:72
long mtype
message type identifier for message routing
Definition mupp.h:71