/*************************************************************************** PStartupHandler.h 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. * ***************************************************************************/ #ifndef _PSTARTUPHANDLER_H_ #define _PSTARTUPHANDLER_H_ #include #include #include #include #include #include "PMusr.h" //-------------------------------------------------------------------------- // This function is a replacement for the ParseFile method of TSAXParser. //-------------------------------------------------------------------------- /** * \brief Replacement function for TSAXParser::ParseFile(). * * This standalone function provides a workaround for environments where * TSAXParser::ParseFile() does not work correctly but ParseBuffer() does. * It reads the entire XML file into memory and then parses it as a buffer. * * \param saxParser Pointer to an initialized TSAXParser object with connected slots * \param startup_path_name Full path to the XML file to be parsed * * \return Parse status: * - 0: Success * - 1: File could not be read * - Other: XML parse error code from TSAXParser::ParseBuffer() * * \see PStartupHandler */ int parseXmlFile(TSAXParser*, const char*); /** * \brief Handles the musrfit XML startup configuration file (musrfit_startup.xml). * * PStartupHandler is responsible for locating, parsing, and providing access to * the musrfit startup configuration file. This XML file contains default settings * that customize musrfit behavior across different installations and user preferences. * * \section startup_contents Configuration File Contents * * The musrfit_startup.xml file stores: * - Data search paths: Directories to search for μSR data files * - Run name templates: Instrument-specific patterns for constructing data file paths * - Fourier transform defaults: Units, apodization, plot type, phase settings * - ROOT marker list: Marker styles for data point display * - ROOT color list: RGB colors for multi-run plotting * * \section startup_search File Search Order * * The startup file is searched in the following locations (first found wins): * -# Current working directory: \c ./musrfit_startup.xml * -# User config directory: \c $HOME/.musrfit/musrfit_startup.xml * -# MUSRFITPATH environment: \c $MUSRFITPATH/musrfit_startup.xml * -# ROOT installation: \c $ROOTSYS/bin/musrfit_startup.xml (with warning) * * If no file is found, a default configuration is automatically created in * \c $HOME/.musrfit/musrfit_startup.xml. * * \section startup_xml XML File Structure * * \code{.xml} * * * Configuration description * /path/to/data/directory * d%yyyy%/tdc/root/deltat_tdc_gps_%yyyy%_%rrrr%.root * * Gauss * 0 * none * real_and_imag * 0.0 * 1.0 * * * * 24 * * * 255,0,0 * * * * \endcode * * \section startup_templates Run Name Templates * * Run name templates use placeholders for automatic file path construction: * - \c %yyyy% : 4-digit year (e.g., 2024) * - \c %yy% : 2-digit year (e.g., 24) * - \c %rrrr% : 4-digit run number with leading zeros * - \c %rrrrr% : 5-digit run number with leading zeros * * Example: \c d%yyyy%/tdc/root/deltat_tdc_gps_%yyyy%_%rrrr%.root * → \c d2024/tdc/root/deltat_tdc_gps_2024_1234.root * * \section startup_sax SAX Parser Implementation * * This class implements the TQObject signal/slot mechanism to handle SAX parser * callbacks. The parser events trigger the following methods: * - OnStartDocument(): Initialize default values * - OnStartElement(): Identify XML element type, set parsing state * - OnCharacters(): Extract element content * - OnEndElement(): Reset parsing state * - OnEndDocument(): Validate and fill missing defaults * - OnWarning/OnError/OnFatalError(): Error handling * * \section startup_usage Usage Example * * \code{.cpp} * // Create handler (searches for and parses startup file) * PStartupHandler startupHandler; * * // Check if configuration was loaded successfully * if (startupHandler.StartupFileFound()) { * // Get data search paths * PStringVector paths = startupHandler.GetDataPathList(); * * // Get Fourier transform defaults * PMsrFourierStructure fourier = startupHandler.GetFourierDefaults(); * * // Get plotting colors and markers * PIntVector colors = startupHandler.GetColorList(); * PIntVector markers = startupHandler.GetMarkerList(); * } * \endcode * * \see PMsrHandler for MSR file parsing * \see PRunDataHandler for data file loading with path resolution */ class PStartupHandler : public TObject, public TQObject { public: /** * \brief Constructor that locates and parses the musrfit startup configuration file. * * Searches for musrfit_startup.xml in standard locations and parses it if found. * If no file is found, creates a default configuration in $HOME/.musrfit/. * * Search order: * -# ./musrfit_startup.xml (current directory) * -# $HOME/.musrfit/musrfit_startup.xml * -# $MUSRFITPATH/musrfit_startup.xml * -# $ROOTSYS/bin/musrfit_startup.xml (with warning) * * \param reset_startup_file If true and file is found, rewrites it with default content. * Useful for restoring corrupted or outdated configurations. * * \note The actual XML parsing is performed by connecting this handler to a TSAXParser * and calling parseXmlFile() externally. * * \see StartupFileFound(), GetStartupFilePath() */ PStartupHandler(bool reset_startup_file=false); /** * \brief Destructor releasing allocated resources. * * Clears all configuration vectors: * - fDataPathList * - fMarkerList * - fColorList * - fRunNameTemplate */ virtual ~PStartupHandler(); /** \brief SAX callback: Called when XML document parsing begins. * Initializes all configuration variables to default values. */ virtual void OnStartDocument(); // SLOT /** \brief SAX callback: Called when XML document parsing ends. * Triggers CheckLists() to ensure all required settings have values. */ virtual void OnEndDocument(); // SLOT /** \brief SAX callback: Called when an XML start element is encountered. * \param str Element name (e.g., "data_path", "marker", "units") * \param attributes XML attributes (used for inst attribute in run_name_template) */ virtual void OnStartElement(const Char_t*, const TList*); // SLOT /** \brief SAX callback: Called when an XML end element is encountered. * \param str Element name (unused, resets parsing state) */ virtual void OnEndElement(const Char_t*); // SLOT /** \brief SAX callback: Called with element text content. * \param str Text content between XML tags (the actual configuration values) */ virtual void OnCharacters(const Char_t*); // SLOT /** \brief SAX callback: Called when XML comment is found (unused). * \param str Comment text */ virtual void OnComment(const Char_t*); // SLOT /** \brief SAX callback: Called when XML parser issues a warning. * \param str Warning message (output to stderr) */ virtual void OnWarning(const Char_t*); // SLOT /** \brief SAX callback: Called when XML parser encounters an error. * \param str Error message (output to stderr) */ virtual void OnError(const Char_t*); // SLOT /** \brief SAX callback: Called when XML parser encounters a fatal error. * \param str Fatal error message (output to stderr) */ virtual void OnFatalError(const Char_t*); // SLOT /** \brief SAX callback: Called for CDATA blocks (unused). * \param str CDATA content * \param len Length of CDATA content */ virtual void OnCdataBlock(const Char_t*, Int_t); // SLOT /** * \brief Checks if the startup configuration file was successfully located. * \return true if musrfit_startup.xml was found (in any search location), false otherwise */ virtual Bool_t StartupFileFound() { return fStartupFileFound; } /** * \brief Returns the full path to the located startup configuration file. * \return Full path including filename (e.g., "/home/user/.musrfit/musrfit_startup.xml"), * or empty string if not found */ virtual TString GetStartupFilePath() { return fStartupFilePath; } /** * \brief Validates configuration lists and fills missing entries with defaults. * * Called at end of XML parsing to ensure all required lists have values. * If a list is empty, populates it with sensible defaults: * - Data paths: PSI facility standard locations * - Markers: ROOT marker codes (circles, squares, triangles, etc.) * - Colors: Standard plotting colors (black, red, green, blue, etc.) */ virtual void CheckLists(); /** * \brief Returns Fourier transform default settings. * \return PMsrFourierStructure containing units, apodization, plot type, phase settings */ virtual PMsrFourierStructure GetFourierDefaults() { return fFourierDefaults; } /** * \brief Returns the list of instrument-specific run name templates. * \return Vector of PRunNameTemplate structures (instrument name + path pattern) */ virtual const PRunNameTemplateList GetRunNameTemplateList() { return fRunNameTemplate; } /** * \brief Returns the list of data file search paths. * \return Vector of directory paths to search for μSR data files */ virtual const PStringVector GetDataPathList() const { return fDataPathList; } /** * \brief Returns the list of ROOT marker codes for plotting. * \return Vector of ROOT TMarker style codes (e.g., 24=open circle, 25=open square) */ virtual const PIntVector GetMarkerList() const { return fMarkerList; } /** * \brief Returns the list of ROOT color codes for plotting. * \return Vector of ROOT TColor codes (generated from RGB values) */ virtual const PIntVector GetColorList() const { return fColorList; } private: /** * \brief Enumeration of XML element types for SAX parser state machine. * * Used by OnStartElement() to set parsing context and by OnCharacters() * to determine how to interpret element content. */ enum EKeyWords { eEmpty, ///< No active element (between elements or unknown) eComment, ///< Inside \ element eDataPath, ///< Inside \ element eRunNameTemplate, ///< Inside \ element eOptions, ///< Inside \ element (reserved) eFourierSettings, ///< Inside \ container eUnits, ///< Inside \ element (Gauss/Tesla/MHz/Mc/s) eFourierPower, ///< Inside \ element (0-20) eApodization, ///< Inside \ element (none/weak/medium/strong) ePlot, ///< Inside \ element (real/imag/real_and_imag/power/phase) ePhase, ///< Inside \ element (degrees) ePhaseIncrement, ///< Inside \ element (degrees per step) eRootSettings, ///< Inside \ container eMarkerList, ///< Inside \ container eMarker, ///< Inside \ element (ROOT marker code) eColorList, ///< Inside \ container eColor ///< Inside \ element (RGB comma-separated) }; EKeyWords fKey; ///< Current XML element type (SAX parser state) Bool_t fStartupFileFound; ///< True if musrfit_startup.xml was located TString fStartupFilePath; ///< Full path to located startup file (empty if not found) TString fCurrentInstrumentName; ///< Instrument name from run_name_template inst attribute PMsrFourierStructure fFourierDefaults; ///< Fourier transform default settings structure PStringVector fDataPathList; ///< List of directories to search for data files PRunNameTemplateList fRunNameTemplate; ///< List of instrument-specific run name patterns PIntVector fMarkerList; ///< List of ROOT TMarker style codes for plotting PIntVector fColorList; ///< List of ROOT TColor codes (from RGB) for plotting /** * \brief Checks if a file exists at the specified path. * \param fln Full path to check * \return true if file exists and is readable, false otherwise */ Bool_t StartupFileExists(Char_t *fln); /** * \brief Creates or overwrites a startup file with default configuration. * * Writes a complete musrfit_startup.xml with: * - Standard PSI data paths * - Run name templates for all PSI instruments * - Default Fourier settings * - Standard marker and color lists * * \param reset_startup_file If true, overwrites existing file at fStartupFilePath. * If false, creates new file at $HOME/.musrfit/musrfit_startup.xml. * \return true on success, false on write failure */ Bool_t WriteDefaultStartupFile(bool reset_startup_file=false); ClassDef(PStartupHandler, 1) }; #endif // _PSTARTUPHANDLER_H_