/*************************************************************************** PStartupHandler.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. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "PStartupHandler.h" ClassImpQ(PStartupHandler) //-------------------------------------------------------------------------- // This function is a replacement for the ParseFile method of TSAXParser. // It is needed because in certain environments ParseFile does not work but ParseBuffer does. //-------------------------------------------------------------------------- /** * \brief Replacement for TSAXParser::ParseFile() that uses buffer-based parsing. * * This function provides a workaround for environments where the standard * TSAXParser::ParseFile() method fails but ParseBuffer() works correctly. * It reads the entire XML file into memory and then parses it as a buffer. * * Algorithm: * -# Open XML file in binary mode, positioned at end to determine size * -# Allocate buffer for entire file content * -# Read file into buffer * -# Close file * -# Call saxParser->ParseBuffer() with buffer contents * -# Free buffer memory * * Memory Management: * The function allocates a buffer equal to the file size, which is freed * after parsing completes. For very large XML files, this may consume * significant memory temporarily. * * \param saxParser Pointer to an initialized TSAXParser object. The parser * should have its signal slots connected to a handler object * (e.g., PStartupHandler) before calling this function. * \param startup_path_name Full filesystem path to the XML file to be parsed. * * \return Parse status code: * - 0: Success (file parsed without errors) * - 1: File could not be opened or read * - Other: XML parse error code from TSAXParser::ParseBuffer() * * \see PStartupHandler for the XML content handler implementation */ int parseXmlFile(TSAXParser *saxParser, const char *startup_path_name) { int status; std::fstream xmlFile; unsigned int xmlSize = 0; char *xmlBuffer = nullptr; xmlFile.open(startup_path_name, std::ios::in | std::ios::ate); // open file for reading and go to the end of the file if (xmlFile.is_open()) { // check if file has been opened successfully xmlSize = xmlFile.tellg(); // get the position within the stream == size of the file (since we are at the end) xmlFile.seekg(0, std::ios::beg); // go back to the beginning of the stream xmlBuffer = new char[xmlSize]; // allocate buffer memory for the whole XML file xmlFile.read(xmlBuffer, xmlSize); // read in the whole XML file into the buffer xmlFile.close(); // close the XML file } if (!xmlBuffer) { // file has not been read into the buffer status = 1; } else { status = saxParser->ParseBuffer(xmlBuffer, xmlSize); // parse buffer delete[] xmlBuffer; // free the buffer memory xmlBuffer = nullptr; } return status; } //-------------------------------------------------------------------------- // Constructor //-------------------------------------------------------------------------- /** * \brief Constructor that locates and optionally resets the musrfit startup configuration. * * Searches for the musrfit_startup.xml configuration file in standard locations * and initializes the handler. If no file is found, creates a default configuration. * * Search Order: * -# Current working directory: \c ./musrfit_startup.xml * -# User config directory: \c $HOME/.musrfit/musrfit_startup.xml * -# MUSRFITPATH environment variable: \c $MUSRFITPATH/musrfit_startup.xml * -# ROOT installation: \c $ROOTSYS/bin/musrfit_startup.xml (with warning) * * File Creation: * If no startup file is found in any location, a default configuration is * automatically created at \c $HOME/.musrfit/musrfit_startup.xml. This includes: * - Standard PSI facility data paths * - Run name templates for all PSI instruments * - Default Fourier transform settings * - Standard marker and color lists * * Reset Mode: * When reset_startup_file=true and a file is found, the existing file is * overwritten with default content. This is useful for: * - Restoring corrupted configurations * - Updating to new default settings after software updates * - Resetting user customizations to defaults * * \param reset_startup_file If true, overwrites existing startup file with defaults. * If false (default), uses existing file or creates new one. * * \note This constructor only locates the file. Actual XML parsing must be * performed separately by connecting this handler to a TSAXParser and * calling parseXmlFile(). * * \see StartupFileFound(), GetStartupFilePath(), WriteDefaultStartupFile() */ PStartupHandler::PStartupHandler(bool reset_startup_file) { fStartupFileFound = false; fStartupFilePath = ""; // get default path (for the moment only linux like) Char_t *pmusrpath=nullptr; Char_t *home=nullptr; Char_t musrpath[128]; Char_t startup_path_name[128]; strncpy(musrpath, "", sizeof(musrpath)); // check if the startup file is found in the current directory strcpy(startup_path_name, "./musrfit_startup.xml"); if (StartupFileExists(startup_path_name)) { fStartupFileFound = true; fStartupFilePath = TString(startup_path_name); } if (!fStartupFileFound) { // startup file not found in the current directory // check if the startup file is found under $HOME/.musrfit home = getenv("HOME"); if (home != nullptr) { snprintf(startup_path_name, sizeof(startup_path_name), "%s/.musrfit/musrfit_startup.xml", home); if (StartupFileExists(startup_path_name)) { fStartupFilePath = TString(startup_path_name); fStartupFileFound = true; } } } if (!fStartupFileFound) { // startup file not found in $HOME/.musrfit // check if the MUSRFITPATH system variable is set pmusrpath = getenv("MUSRFITPATH"); if (pmusrpath != nullptr) { snprintf(startup_path_name, sizeof(startup_path_name), "%s/musrfit_startup.xml", pmusrpath); if (StartupFileExists(startup_path_name)) { fStartupFilePath = TString(startup_path_name); fStartupFileFound = true; } } } if (!fStartupFileFound) { // MUSRFITPATH not set or empty, will try $ROOTSYS/bin home = getenv("ROOTSYS"); if (home != nullptr) { snprintf(musrpath, sizeof(musrpath), "%s/bin", home); std::cerr << std::endl << "**WARNING** MUSRFITPATH environment variable not set will try " << musrpath << std::endl; snprintf(startup_path_name, sizeof(startup_path_name), "%s/musrfit_startup.xml", musrpath); if (StartupFileExists(startup_path_name)) { fStartupFilePath = TString(startup_path_name); fStartupFileFound = true; } } } // musrfit_startup.xml found. Check if it should be rewritten if (fStartupFileFound && reset_startup_file) { std::cout << std::endl; std::cout << ">> Will only reset the file: '" << fStartupFilePath.Data() << "'."<< std::endl; std::cout << std::endl; if (!WriteDefaultStartupFile(reset_startup_file)) { std::cerr << std::endl << "**ERROR** couldn't re-write " << fStartupFilePath.Data() << "." << std::endl; return; } } // if musrfit_startup.xml is still not found, will create a default one if (!fStartupFileFound) { std::cout << std::endl << "**INFO** no musrfit_startup.xml file found, will write a default one." << std::endl; if (!WriteDefaultStartupFile()) { std::cerr << std::endl << "**ERROR** couldn't write default musrfit_startup.xml." << std::endl; } else { home = getenv("HOME"); if (home != nullptr) { snprintf(startup_path_name, sizeof(startup_path_name), "%s/.musrfit/musrfit_startup.xml", home); if (StartupFileExists(startup_path_name)) { fStartupFilePath = TString(startup_path_name); fStartupFileFound = true; } } } } } //-------------------------------------------------------------------------- // Destructor //-------------------------------------------------------------------------- /** * \brief Destructor that releases all allocated configuration data. * * Clears all configuration vectors to free memory: * - fDataPathList: Data file search paths * - fMarkerList: ROOT marker style codes * - fColorList: ROOT color codes * - fRunNameTemplate: Instrument run name patterns * * \note The Fourier defaults structure is a value type and is automatically * cleaned up when the object is destroyed. */ PStartupHandler::~PStartupHandler() { // clean up fDataPathList.clear(); fMarkerList.clear(); fColorList.clear(); fRunNameTemplate.clear(); } //-------------------------------------------------------------------------- // OnStartDocument //-------------------------------------------------------------------------- /** * \brief SAX callback invoked at the start of XML document parsing. * * Initializes all configuration variables to default values before parsing * begins. This ensures a clean state even if the same handler is reused. * * Initialization: * - fKey = eEmpty (no active element) * - Fourier defaults: * - fFourierBlockPresent = false * - fUnits = FOURIER_UNIT_GAUSS * - fFourierPower = 0 (no zero-padding) * - fApodization = FOURIER_APOD_NONE * - fPlotTag = FOURIER_PLOT_REAL_AND_IMAG * - fRangeForPhaseCorrection = [-1.0, -1.0] (auto) * - fPlotRange = [-1.0, -1.0] (auto) * - fPhaseIncrement = 1.0 degree * * \note This is a SAX parser callback connected via TQObject signals. * It is automatically called by TSAXParser at document start. */ void PStartupHandler::OnStartDocument() { fKey = eEmpty; // init fourier default variables fFourierDefaults.fFourierBlockPresent = false; fFourierDefaults.fUnits = FOURIER_UNIT_GAUSS; fFourierDefaults.fFourierPower = 0; fFourierDefaults.fApodization = FOURIER_APOD_NONE; fFourierDefaults.fPlotTag = FOURIER_PLOT_REAL_AND_IMAG; fFourierDefaults.fRangeForPhaseCorrection[0] = -1.0; fFourierDefaults.fRangeForPhaseCorrection[1] = -1.0; fFourierDefaults.fPlotRange[0] = -1.0; fFourierDefaults.fPlotRange[1] = -1.0; fFourierDefaults.fPhaseIncrement = 1.0; fStartupOptions.writeExpectedChisq = false; // NOT defined in the XML, but initialized for later use!! fStartupOptions.estimateN0 = false; // NOT defined in the XML, but initialized for later use!! fStartupOptions.useDKS = false; } //-------------------------------------------------------------------------- // OnEndDocument //-------------------------------------------------------------------------- /** * \brief SAX callback invoked at the end of XML document parsing. * * Finalizes configuration by calling CheckLists() to ensure all required * settings have values. If any list is empty after parsing, it will be * populated with default values. * * \note This is a SAX parser callback connected via TQObject signals. * It is automatically called by TSAXParser when parsing completes. * * \see CheckLists() */ void PStartupHandler::OnEndDocument() { // check if anything was set, and if not set some default stuff CheckLists(); } //-------------------------------------------------------------------------- // OnStartElement //-------------------------------------------------------------------------- /** * \brief SAX callback invoked when an XML start element tag is encountered. * * Identifies the element type and sets the parsing state (fKey) accordingly. * This state is used by OnCharacters() to determine how to process element content. * * Recognized Elements: * - \c data_path → eDataPath (data file search directory) * - \c run_name_template → eRunNameTemplate (with inst attribute extraction) * - \c marker → eMarker (ROOT marker style code) * - \c color → eColor (RGB color specification) * - \c units → eUnits (Fourier frequency units) * - \c fourier_power → eFourierPower (zero-padding power) * - \c apodization → eApodization (windowing function) * - \c plot → ePlot (Fourier plot type) * - \c phase → ePhase (Fourier phase value) * - \c phase_increment → ePhaseIncrement (phase adjustment step) * * Attribute Handling: * For \c run_name_template elements, extracts the \c inst attribute value * and stores it in fCurrentInstrumentName for use when processing the * element content. * * \param str XML element name (tag name without angle brackets) * \param attributes TList of TXMLAttr objects containing element attributes * * \note Unrecognized elements leave fKey unchanged (typically eEmpty), * causing their content to be ignored. */ void PStartupHandler::OnStartElement(const Char_t *str, const TList *attributes) { if (!strcmp(str, "data_path")) { fKey = eDataPath; } else if (!strcmp(str, "use_dks")) { fKey = eUseDKS; } else if (!strcmp(str, "run_name_template")) { fKey = eRunNameTemplate; TXMLAttr *attr; TIter next(attributes); while ((attr = (TXMLAttr*) next())) { if (!strcmp(attr->GetName(), "inst")) { fCurrentInstrumentName = attr->GetValue(); } } } else if (!strcmp(str, "marker")) { fKey = eMarker; } else if (!strcmp(str, "color")) { fKey = eColor; } else if (!strcmp(str, "units")) { fKey = eUnits; } else if (!strcmp(str, "fourier_power")) { fKey = eFourierPower; } else if (!strcmp(str, "apodization")) { fKey = eApodization; } else if (!strcmp(str, "plot")) { fKey = ePlot; } else if (!strcmp(str, "phase")) { fKey = ePhase; } else if (!strcmp(str, "phase_increment")) { fKey = ePhaseIncrement; } } //-------------------------------------------------------------------------- // OnEndElement //-------------------------------------------------------------------------- /** * \brief SAX callback invoked when an XML end element tag is encountered. * * Resets the parsing state (fKey) to eEmpty, indicating that any subsequent * character data should be ignored until the next start element is found. * * \param str XML element name (unused, state is always reset to eEmpty) * * \note The element name parameter is not used because all elements reset * to the same state. This simplifies handling of nested elements. */ void PStartupHandler::OnEndElement(const Char_t *str) { fKey = eEmpty; } //-------------------------------------------------------------------------- // OnCharacters //-------------------------------------------------------------------------- /** * \brief SAX callback invoked with text content between XML element tags. * * Processes element content based on the current parsing state (fKey) set * by OnStartElement(). Each element type has specific parsing logic and * validation. * * Element Processing: * * - eDataPath: Adds path string directly to fDataPathList * * - eRunNameTemplate: Creates PRunNameTemplate with current instrument * name and template string, adds to fRunNameTemplate * * - eMarker: Validates numeric string, converts to int, adds to fMarkerList * * - eColor: Parses "R,G,B" format (comma-separated integers 0-255), * converts to ROOT color code via TColor::GetColor(), adds to fColorList * * - eUnits: Maps string to FOURIER_UNIT_* constant: * - "gauss" → FOURIER_UNIT_GAUSS * - "tesla" → FOURIER_UNIT_TESLA * - "mhz" → FOURIER_UNIT_FREQ * - "mc/s" → FOURIER_UNIT_CYCLES * * - eFourierPower: Validates integer 0-20, sets fFourierDefaults.fFourierPower * * - eApodization: Maps string to FOURIER_APOD_* constant: * - "none" → FOURIER_APOD_NONE * - "weak" → FOURIER_APOD_WEAK * - "medium" → FOURIER_APOD_MEDIUM * - "strong" → FOURIER_APOD_STRONG * * - ePlot: Maps string to FOURIER_PLOT_* constant: * - "real" → FOURIER_PLOT_REAL * - "imag" → FOURIER_PLOT_IMAG * - "real_and_imag" → FOURIER_PLOT_REAL_AND_IMAG * - "power" → FOURIER_PLOT_POWER * - "phase" → FOURIER_PLOT_PHASE * * - ePhase: Validates float, adds to fFourierDefaults.fPhase vector * * - ePhaseIncrement: Validates float, sets fFourierDefaults.fPhaseIncrement * * \param str Text content between XML tags * * \note Invalid values generate warning messages to stderr but do not cause * parsing to fail. The invalid value is simply ignored. */ void PStartupHandler::OnCharacters(const Char_t *str) { TObjArray *tokens; TObjString *ostr; TString tstr; Int_t color, r, g, b, ival; PRunNameTemplate tmpl; switch (fKey) { case eDataPath: // check that str is a valid path // add str to the path list fDataPathList.push_back(str); break; case eUseDKS: tstr = TString(str); if (tstr.BeginsWith("y") || tstr.BeginsWith("Y")) fStartupOptions.useDKS = true; break; case eRunNameTemplate: tmpl.instrument = fCurrentInstrumentName; tmpl.runNameTemplate = str; fRunNameTemplate.push_back(tmpl); fCurrentInstrumentName="???"; break; case eMarker: // check that str is a number tstr = TString(str); if (tstr.IsDigit()) { // add converted str to the marker list fMarkerList.push_back(tstr.Atoi()); } else { std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a number, will ignore it"; std::cerr << std::endl; } break; case eColor: // check that str is a rbg code tstr = TString(str); tokens = tstr.Tokenize(","); // check that there any tokens if (!tokens) { std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a rbg code, will ignore it"; std::cerr << std::endl; return; } // check there is the right number of tokens if (tokens->GetEntries() != 3) { std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a rbg code, will ignore it"; std::cerr << std::endl; return; } // get r ostr = dynamic_cast(tokens->At(0)); tstr = ostr->GetString(); if (tstr.IsDigit()) { r = tstr.Atoi(); } else { std::cerr << std::endl << "PStartupHandler **WARNING** r within the rgb code is not a number, will ignore it"; std::cerr << std::endl; return; } // get g ostr = dynamic_cast(tokens->At(1)); tstr = ostr->GetString(); if (tstr.IsDigit()) { g = tstr.Atoi(); } else { std::cerr << std::endl << "PStartupHandler **WARNING** g within the rgb code is not a number, will ignore it"; std::cerr << std::endl; return; } // get b ostr = dynamic_cast(tokens->At(2)); tstr = ostr->GetString(); if (tstr.IsDigit()) { b = tstr.Atoi(); } else { std::cerr << std::endl << "PStartupHandler **WARNING** b within the rgb code is not a number, will ignore it"; std::cerr << std::endl; return; } // clean up tokens if (tokens) { delete tokens; tokens = nullptr; } // generate the ROOT color code based on str color = TColor::GetColor(r,g,b); // add the color code to the color list fColorList.push_back(color); break; case eUnits: tstr = TString(str); if (!tstr.CompareTo("gauss", TString::kIgnoreCase)) { fFourierDefaults.fUnits = FOURIER_UNIT_GAUSS; } else if (!tstr.CompareTo("tesla", TString::kIgnoreCase)) { fFourierDefaults.fUnits = FOURIER_UNIT_TESLA; } else if (!tstr.CompareTo("mhz", TString::kIgnoreCase)) { fFourierDefaults.fUnits = FOURIER_UNIT_FREQ; } else if (!tstr.CompareTo("mc/s", TString::kIgnoreCase)) { fFourierDefaults.fUnits = FOURIER_UNIT_CYCLES; } else { std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a valid unit, will ignore it."; std::cerr << std::endl; } break; case eFourierPower: tstr = TString(str); if (tstr.IsDigit()) { ival = tstr.Atoi(); if ((ival >= 0) && (ival <= 20)) { fFourierDefaults.fFourierPower = ival; } else { std::cerr << std::endl << "PStartupHandler **WARNING** fourier power '" << str << "' is not a valid number (0..20), will ignore it."; std::cerr << std::endl; } } else { std::cerr << std::endl << "PStartupHandler **WARNING** fourier power '" << str << "' is not a valid number (0..20), will ignore it."; std::cerr << std::endl; } break; case eApodization: tstr = TString(str); if (!tstr.CompareTo("none", TString::kIgnoreCase)) { fFourierDefaults.fApodization = FOURIER_APOD_NONE; } else if (!tstr.CompareTo("weak", TString::kIgnoreCase)) { fFourierDefaults.fApodization = FOURIER_APOD_WEAK; } else if (!tstr.CompareTo("medium", TString::kIgnoreCase)) { fFourierDefaults.fApodization = FOURIER_APOD_MEDIUM; } else if (!tstr.CompareTo("strong", TString::kIgnoreCase)) { fFourierDefaults.fApodization = FOURIER_APOD_STRONG; } else { std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a valid apodization, will ignore it."; std::cerr << std::endl; } break; case ePlot: tstr = TString(str); if (!tstr.CompareTo("real", TString::kIgnoreCase)) { fFourierDefaults.fPlotTag = FOURIER_PLOT_REAL; } else if (!tstr.CompareTo("imag", TString::kIgnoreCase)) { fFourierDefaults.fPlotTag = FOURIER_PLOT_IMAG; } else if (!tstr.CompareTo("real_and_imag", TString::kIgnoreCase)) { fFourierDefaults.fPlotTag = FOURIER_PLOT_REAL_AND_IMAG; } else if (!tstr.CompareTo("power", TString::kIgnoreCase)) { fFourierDefaults.fPlotTag = FOURIER_PLOT_POWER; } else if (!tstr.CompareTo("phase", TString::kIgnoreCase)) { fFourierDefaults.fPlotTag = FOURIER_PLOT_PHASE; } else { std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a valid plot option, will ignore it."; std::cerr << std::endl; } break; case ePhase: tstr = TString(str); if (tstr.IsFloat()) { fFourierDefaults.fPhase.push_back(tstr.Atof()); } else { std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a valid phase, will ignore it."; std::cerr << std::endl; } break; case ePhaseIncrement: tstr = TString(str); if (tstr.IsFloat()) { fFourierDefaults.fPhaseIncrement = tstr.Atof(); } else { std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a valid phase increment, will ignore it."; std::cerr << std::endl; } break; default: break; } } //-------------------------------------------------------------------------- // OnComment //-------------------------------------------------------------------------- /** * \brief SAX callback invoked when an XML comment is encountered. * * Currently does nothing. XML comments in the startup file are ignored. * * \param str Comment text content (without \" << std::endl; fout << " no" << std::endl; fout << " /psi.ch/group/lmu/public/data/lem/his" << std::endl; fout << " /psi.ch/group/lmu/public/data/alc/his" << std::endl; fout << " /psi.ch/group/lmu/public/data/dolly/his" << std::endl; fout << " /psi.ch/group/lmu/public/data/flame/his" << std::endl; fout << " /psi.ch/group/lmu/public/data/gpd/his" << std::endl; fout << " /psi.ch/group/lmu/public/data/gps/his" << std::endl; fout << " /psi.ch/group/lmu/public/data/hal/his" << std::endl; fout << " /psi.ch/group/lmu/public/data/ltf/his" << std::endl; fout << " /psi.ch/group/lmu/public/data/misc/his" << std::endl; fout << " /psi.ch/group/lmu/public/data/vms/his" << std::endl; fout << " " << std::endl; fout << " d%yyyy%/deltat_misc_%rrrr%.bin" << std::endl; fout << " " << std::endl; fout << " d%yyyy%/deltat_zh_chem_%rrrr%.bin" << std:: endl; fout << " d%yyyy%/deltat_tdc_alc_%rrrr%.bin" << std::endl; fout << " d%yyyy%/tdc/deltat_tdc_alc_%rrrr%.bin" << std::endl; fout << " " << std::endl; fout << " d%yyyy%/tdc/root/deltat_tdc_vms_%yyyy%_%rrrr%.root" << std::endl; fout << " " << std::endl; fout << " d%yyyy%/tdc/root/deltat_tdc_dolly_%yyyy%_%rrrr%.root" << std::endl; fout << " d%yyyy%/pie1/deltat_flc_%rrrr%.bin" << std::endl; fout << " d%yyyy%/pie3/deltat_flc_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_flc_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_pta_dolly_%rrrr%.bin" << std::endl; fout << " d%yyyy%/pta/deltat_pta_dolly_%rrrr%.bin" << std::endl; fout << " d%yyyy%/tdc/deltat_tdc_dolly_%rrrr%.bin" << std::endl; fout << " d%yyyy%/tdc/mdu/deltat_tdc_dolly_%rrrr%.mdu" << std::endl; fout << " " << std::endl; fout << " d%yyyy%/tdc/root/deltat_tdc_flame_%yyyy%_%rrrr%.root" << std::endl; fout << " d%yyyy%/tdc/deltat_tdc_flame_%rrrr%.bin" << std::endl; fout << " d%yyyy%/tdc/mdu/deltat_tdc_flame_%yyyy%_%rrrr%.mdu" << std::endl; fout << " " << std::endl; fout << " d%yyyy%/tdc/root/deltat_tdc_gpd_%yyyy%_%rrrr%.root" << std::endl; fout << " d%yyyy%/deltat_mue1_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_fq_si_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_strobo_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_hp_ni_ht_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_hp_ni_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_ccr2_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_gpd_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_janis_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_janis_gpd_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_pta_gpd_%rrrr%.bin" << std::endl; fout << " d%yyyy%/pta/deltat_pta_gpd_%rrrr%.bin" << std::endl; fout << " d%yyyy%/tdc/deltat_tdc_gpd_%rrrr%.bin" << std::endl; fout << " d%yyyy%/tdc/mdu/deltat_tdc_gpd_%rrrr%.mdu" << std::endl; fout << " " << std::endl; fout << " d%yyyy%/tdc/root/deltat_tdc_gps_%yyyy%_%rrrr%.root" << std::endl; fout << " d%yyyy%/deltat_ccr_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_he3_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_stutt_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_ltf_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_flc_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_flc2_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_oven_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_oven2_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_pta_gps_%rrrr%.bin" << std::endl; fout << " d%yyyy%/tdc/deltat_tdc_gps_%rrrr%.bin" << std::endl; fout << " d%yyyy%/tdc/mdu/deltat_tdc_gps_%yyyy%_%rrrr%.mdu" << std::endl; fout << " " << std::endl; fout << " d%yyyy%/tdc/root/deltat_tdc_hifi_%yyyy%_%rrrr%.root" << std::endl; fout << " d%yyyy%/tdc/deltat_hifi_%rrrr%.bin" << std::endl; fout << " d%yyyy%/tdc/tdc_hifi_%yyyy%_%rrrrr%.mdu" << std::endl; fout << " d%yyyy%/tdc/root/deltat_tdc_hifi_%yyyy%_%rrrr%.mdu" << std::endl; fout << " " << std::endl; fout << " d%yyyy%/deltat_ltf_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_ltf2_%rrrr%.bin" << std::endl; fout << " d%yyyy%/deltat_pta_ltf_%rrrr%.bin" << std::endl; fout << " d%yyyy%/pta/deltat_pta_ltf_%rrrr%.bin" << std::endl; fout << " d%yyyy%/tdc/deltat_tdc_ltf_%rrrr%.bin" << std::endl; fout << " " << std::endl; fout << " %yyyy%/lem%yy%_his_%rrrr%.root" << std::endl; fout << " d%yyyy%/tdc/lem%yy%_his_%rrrr%.root" << std::endl; fout << " %yyyy%/lem%yy%_his_%rrrrr%.root" << std::endl; fout << " d%yyyy%/tdc/lem%yy%_his_%rrrrr%.root" << std::endl; fout << " " << std::endl; fout << " Gauss" << std::endl; fout << " 0" << std::endl; fout << " none" << std::endl; fout << " real_and_imag" << std::endl; fout << " 0.0" << std::endl; fout << " 1.0" << std::endl; fout << " " << std::endl; fout << " " << std::endl; fout << " " << std::endl; fout << " " << std::endl; fout << " 24 " << std::endl; fout << " 25 " << std::endl; fout << " 26 " << std::endl; fout << " 27 " << std::endl; fout << " 28 " << std::endl; fout << " 29 " << std::endl; fout << " 30 " << std::endl; fout << " 20 " << std::endl; fout << " 21 " << std::endl; fout << " 22 " << std::endl; fout << " 23 " << std::endl; fout << " 2 " << std::endl; fout << " 3 " << std::endl; fout << " 5 " << std::endl; fout << " " << std::endl; fout << " " << std::endl; fout << " " << std::endl; fout << " 0,0,0 " << std::endl; fout << " 255,0,0 " << std::endl; fout << " 0,153,0 " << std::endl; fout << " 0,0,255 " << std::endl; fout << " 255,0,255 " << std::endl; fout << " 0,255,255 " << std::endl; fout << " 153,0,255 " << std::endl; fout << " 102,102,51 " << std::endl; fout << " 51,102,51 " << std::endl; fout << " 153,0,0 " << std::endl; fout << " " << std::endl; fout << " " << std::endl; fout << "" << std::endl; fout.close(); return true; } // ------------------------------------------------------------------------- // end // -------------------------------------------------------------------------