/*************************************************************************** PmuppScript.cpp Author: Andreas Suter e-mail: andreas.suter@psi.ch ***************************************************************************/ /*************************************************************************** * Copyright (C) 2007-2025 by Andreas Suter * * andreas.suter@psi.ch * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ /** * @file PmuppScript.cpp * * @brief Implementation of the mupp scripting interface for batch processing. * * This file implements the non-interactive scripting system for mupp, enabling * automated batch processing of parameter data analysis and plotting tasks. * * Key functionality implemented: * - Script command parsing and execution * - Path management with environment variable expansion * - Data collection loading and selection * - X-Y axis parameter configuration * - Variable expression evaluation and storage * - ROOT macro generation with full plot specification * - Batch mode plot creation via ROOT subprocess * - Label formatting for publication-quality plots * * Script command processing: * The executeScript() method processes commands sequentially, maintaining * state throughout execution. Each command type (loadPath, load, select, * x, y, var, norm, plot, macro) has a dedicated handler method. * * ROOT macro generation: * The macro() method creates complete ROOT C++ macros including: * - Data array definitions * - TGraphAsymmErrors objects for error bars * - Canvas and styling setup * - Axis labels and ranges * - Marker and color configuration * - Optional normalization * * Variable system: * Variables are mathematical expressions combining collection parameters. * The var_cmd() method integrates with PVarHandler for expression parsing * and evaluation, enabling derived quantity calculations. */ #include #include #include #include #include #include #include #include #include // Q_ASSERT #include "PmuppScript.h" //-------------------------------------------------------------------------- /** * @brief Constructor for the script interpreter. * * Initializes the script execution environment with default settings: * - Load path: current directory * - Save path: current directory * - Selection state: nothing selected * - Normalization: disabled * - Administration object for configuration access * * @param script list of script commands to be executed */ PmuppScript::PmuppScript(QStringList script) : fScript(script) { fLoadPath = QString("./"); fSavePath = QString("./"); fSelected = -2; // nothing selected fNorm = false; fAdmin = std::make_unique(); } //-------------------------------------------------------------------------- /** * @brief Executes all script commands sequentially. * * Processes each command in the script list, dispatching to appropriate * handler methods based on command type. Maintains state throughout * execution including: * - Loaded data collections * - Current selection * - Plot configurations * - Variable definitions * * Command dispatch table: * - "loadPath" → setLoadPath() * - "savePath" → setSavePath() * - "load " → loadCollection() * - "selectAll" → selectAll() * - "select " → select() * - "x" → addX() * - "y" → addY() * - "norm" → sets fNorm flag * - "plot" → plot() * - "macro" → macro() * - "var" → var_cmd() * - "col" → (handled internally by var) * * Emits finished() signal upon completion or error. * * @return 0 on success, non-zero error code on failure */ int PmuppScript::executeScript() { fParamDataHandler = std::make_unique(); if (fParamDataHandler == nullptr) { std::cerr << std::endl << "**ERROR** couldn't invoke data handler ..." << std::endl << std::endl; return -1; } QString cmd; int status; for (int i=0; iReadParamFile(flnList, errorMsg)) return 1; return 0; } //-------------------------------------------------------------------------- /** * @brief Selects a specific collection for plotting. * * Parses the select command to identify a collection by either: * - Numeric index (0, 1, 2, ...) * - Collection name string * * The selected collection becomes the target for subsequent x and y * commands. Sets fSelected to the collection index. * * @param str select command string (format: "select ") * * @return 0 on success * @return -1 wrong command syntax * @return -2 collection index out of range * @return -3 collection name not found */ int PmuppScript::select(const QString str) { QString cmd = str; QStringList tok = cmd.split(' ', Qt::SkipEmptyParts); if (tok.size() != 2) { std::cerr << std::endl << "**ERROR** wrong 'select' command syntax." << std::endl << std::endl; return -1; } bool ok; int ival = tok[1].toInt(&ok); if (ok) { // collection index given if (ival >= fParamDataHandler->GetNoOfCollections()) { std::cerr << std::endl << "**ERROR** try to select a collection with index " << ival << ", which is >= # collections (" << fParamDataHandler->GetNoOfCollections() << ")." << std::endl << std::endl; return -2; } fSelected = ival; } else { // assume that a collection name is given ival = fParamDataHandler->GetCollectionIndex(tok[1]); if (ival == -1) { std::cerr << std::endl << "**ERROR** couldn't find collection '" << tok[1].toLatin1().constData() << "'." << std::endl << std::endl; return -3; } if (ival >= fParamDataHandler->GetNoOfCollections()) { std::cerr << std::endl << "**ERROR** try to select a collection with index " << ival << ", which is >= # collections (" << fParamDataHandler->GetNoOfCollections() << ")." << std::endl << std::endl; return -2; } fSelected = ival; } return 0; } //-------------------------------------------------------------------------- /** * @brief Selects all loaded collections for plotting. * * Enables batch plotting mode where subsequent x and y commands apply * to all collections. Sets fSelected to -1 (all-selected state). * * This mode is useful for creating overlay plots showing multiple * data sets with the same parameter axes. * * @return 0 on success, -1 if no collections are loaded */ int PmuppScript::selectAll() { int noColl = fParamDataHandler->GetNoOfCollections(); if ( noColl > 0) { fSelected = -1; // all collections are selected } else { std::cerr << std::endl << "**ERROR** no collections present, hence it is not possible to select them." << std::endl << std::endl; return -1; } return 0; } //-------------------------------------------------------------------------- /** * @brief Adds a parameter label to the X-axis. * * Configures the X-axis (independent variable) for the plot. The label * can be either: * - A parameter name from the collection (e.g., "dataT", "dataB") * - A defined variable expression * * Behavior depends on selection state: * - fSelected == -2: Error (no selection made) * - fSelected == -1: Applies to all collections (creates fPlotInfo entries) * - fSelected >= 0: Applies to specific collection (sets fPlotEntry) * * Validation: * - Checks if label exists in collection(s) or as a variable * - Reports error if label not found * * @param str x command string (format: "x