improve doxygen documentation of PMsr2Data.*

This commit is contained in:
2025-11-14 09:11:28 +01:00
parent a40c431396
commit 5f1b4fa5f5
2 changed files with 507 additions and 109 deletions

View File

@@ -49,11 +49,26 @@ using namespace boost::algorithm;
#include "PMsr2Data.h"
//-------------------------------------------------------------
// Constructor
//-------------------------------------------------------------
/**
* <p> Constructor
* \brief Constructor that initializes the msr2data handler.
*
* \param ext extension/suffix of the msr-files to be processed
* Initializes all member variables and prepares the object for processing.
* Sets default values:
* - Run number digits: 4 (typical for standard run numbering)
* - Global/specific parameter counts: 0
* - Header written flag: false
* - Run list file flag: false
*
* All handler pointers (SAX parser, startup handler, data handler, msr handler)
* are initialized to nullptr and will be created as needed during processing.
*
* \param ext File extension for data files (e.g., ".bin", ".root", ".mdu")
* This extension is used to locate corresponding data files for each run
*
* \note The extension should include the leading dot if required
*/
PMsr2Data::PMsr2Data(const std::string &ext) : fFileExtension(ext), fRunListFile(false), fNumGlobalParam(0), fNumSpecParam(0), fNumTempRunBlocks(0), fRunNumberDigits(4), fHeaderWritten(false)
{
@@ -65,9 +80,15 @@ PMsr2Data::PMsr2Data(const std::string &ext) : fFileExtension(ext), fRunListFile
fMsrHandler = nullptr;
}
//-------------------------------------------------------------
// Destructor
//-------------------------------------------------------------
/**
* <p> Destructor
* \brief Destructor that cleans up resources.
*
* Clears all vectors and resets iterators. The unique_ptr members
* (fRunListFileStream, fSaxParser, fStartupHandler, fDataHandler, fMsrHandler)
* are automatically cleaned up through their destructors.
*/
PMsr2Data::~PMsr2Data()
{
@@ -76,21 +97,36 @@ PMsr2Data::~PMsr2Data()
fIndVar.clear();
}
//-------------------------------------------------------------
// DetermineRunNumberDigits
//-------------------------------------------------------------
/**
* <p> Determines the number of digits used for the run number in the data file name from the first msr-file that is processed
* If the specified run number is the first one of the list of runs and it cannot be opened, then the rest of the given runs is checked
* until an existing msr-file is found
* \brief Determines the number of digits used for run number formatting.
*
* <p><b>return:</b>
* - 0 if the number has been determined and set successfully
* - -1 in case the msr-file cannot be read
* - -2 if the msr-file-number does not match the data-file-number
* - -3 if the msr-file does not contain a RUN block
* Analyzes the first processable msr-file to determine how many digits are
* used for run number formatting in data file names. This ensures consistent
* zero-padding when generating new msr-files from templates.
*
* \param runNo run number of an msr-file
* \param normalMode false for global mode
* The algorithm:
* 1. Attempts to open the msr-file for the specified run number
* 2. If in global mode and file not found, tries the "+global" variant
* 3. If first run fails, iterates through the run list to find an existing file
* 4. Searches the RUN block for the run number in the data file path
* 5. Counts leading zeros to determine the digit width
*
* Example: If the data file is "run_0042.bin", this determines 4 digits.
*
* \param runNo Run number to analyze
* \param normalMode true for normal mode, false for global fitting mode
*
* \return
* - 0 if the number of digits was successfully determined
* - -1 if no msr-file could be opened
* - -2 if msr-file run number doesn't match data file run number
* - -3 if the msr-file contains no RUN block
*
* \note The determined digit count is stored in fRunNumberDigits
* \note In global mode, also checks for files with "+global" suffix
*/
int PMsr2Data::DetermineRunNumberDigits(unsigned int runNo, bool normalMode) const
{
@@ -177,13 +213,27 @@ int PMsr2Data::DetermineRunNumberDigits(unsigned int runNo, bool normalMode) con
return -3;
}
//-------------------------------------------------------------
// CheckRunNumbersInRange
//-------------------------------------------------------------
/**
* <p> Checks if all given run numbers are in the range covered by the number of digits used in the data file name
* \brief Validates that all run numbers fit within the determined digit width.
*
* <p><b>return:</b>
* - 0 if everything is fine
* - -1 if a given run number is too big
* Checks if all run numbers in the run vector can be represented with the
* number of digits determined from the data file naming convention. This
* prevents formatting errors when generating file names.
*
* The check has been loosened since 2023 to accommodate LEM run numbers
* exceeding 9999 by allowing one extra digit beyond the determined width.
*
* Maximum allowed run number = 10^(fRunNumberDigits+1) - 1
*
* \return
* - 0 if all run numbers are within the acceptable range
* - -1 if any run number exceeds the maximum
*
* \note Since 2023, uses fRunNumberDigits+1 instead of fRunNumberDigits
* to handle larger run numbers at facilities like LEM
*/
int PMsr2Data::CheckRunNumbersInRange() const
{
@@ -201,13 +251,18 @@ int PMsr2Data::CheckRunNumbersInRange() const
return 0;
}
//-------------------------------------------------------------
// GetPresentRun
//-------------------------------------------------------------
/**
* <p> Determines the current run number
* \brief Returns the current run number being processed.
*
* <p><b>return:</b>
* - current run number
* - 0 if all runs have been processed already
* Retrieves the run number pointed to by the internal iterator.
* Used to track progress through the run list during processing.
*
* \return
* - Current run number if processing is ongoing
* - 0 if all runs have been processed (iterator at end)
*/
unsigned int PMsr2Data::GetPresentRun() const
{
@@ -217,15 +272,20 @@ unsigned int PMsr2Data::GetPresentRun() const
return 0;
}
//-------------------------------------------------------------
// SetRunNumbers (single run)
//-------------------------------------------------------------
/**
* <p> Initialization of the internal list of runs using a single run number
* \brief Sets a single run number for processing.
*
* <p><b>return:</b>
* Clears any existing run list and initializes with a single run number.
* The internal iterator is reset to point to the beginning.
*
* \param runNo Run number to process (must be >= 1)
*
* \return
* - 0 if the run number is valid
* - 1 otherwise
*
* \param runNo run number
* - 1 if the run number is invalid (< 1)
*/
int PMsr2Data::SetRunNumbers(unsigned int runNo)
{
@@ -239,16 +299,24 @@ int PMsr2Data::SetRunNumbers(unsigned int runNo)
return 0;
}
//-------------------------------------------------------------
// SetRunNumbers (range)
//-------------------------------------------------------------
/**
* <p> Initialization of the internal list of runs using first and last run numbers
* \brief Sets a range of run numbers for processing.
*
* <p><b>return:</b>
* - 0 if the run numbers are valid
* - 1 otherwise
* Clears any existing run list and populates it with all run numbers
* from runNoStart to runNoEnd (inclusive). Handles both ascending
* and descending ranges automatically.
*
* \param runNoStart first run number
* \param runNoEnd last run number
* \param runNoStart First run number in the range (must be >= 1)
* \param runNoEnd Last run number in the range (must be >= 1)
*
* \return
* - 0 if both run numbers are valid
* - 1 if either run number is invalid (< 1)
*
* \note If runNoStart > runNoEnd, the range is generated in descending order
*/
int PMsr2Data::SetRunNumbers(unsigned int runNoStart, unsigned int runNoEnd)
{
@@ -268,16 +336,21 @@ int PMsr2Data::SetRunNumbers(unsigned int runNoStart, unsigned int runNoEnd)
return 0;
}
//-------------------------------------------------------------
// SetRunNumbers (explicit vector)
//-------------------------------------------------------------
/**
* <p> Initialization of the internal list of runs using explicitly specified run numbers
* \brief Sets run numbers from an explicit vector.
*
* <p><b>return:</b>
* Clears any existing run list and copies the provided vector of run numbers.
* All run numbers in the vector must be valid (>= 1).
*
* \param runListVector Vector containing run numbers to process
*
* \return
* - -1 if the vector is empty
* - 0 if all run numbers are valid
* - 1 otherwise
*
* \param runListVector vector containing the run numbers to be processed
* - 1 if any run number is invalid (< 1)
*/
int PMsr2Data::SetRunNumbers(const std::vector<unsigned int> &runListVector)
{
@@ -295,16 +368,34 @@ int PMsr2Data::SetRunNumbers(const std::vector<unsigned int> &runListVector)
return 0;
}
//-------------------------------------------------------------
// SetRunNumbers (from file)
//-------------------------------------------------------------
/**
* <p> Initialization of the internal list of runs using a run list file
* \brief Sets run numbers from a run list file.
*
* <p><b>return:</b>
* Reads run numbers from a text file with the following format:
* - First line: "RUN" followed by optional independent variable names
* - Subsequent lines: run number followed by corresponding variable values
* - Comments start with '#' and are ignored
* - Empty lines are skipped
*
* Example run list file:
* \verbatim
* RUN FIELD TEMP
* 1234 0.5 295.0
* 1235 1.0 295.0 # This is a comment
* 1236 1.5 295.0
* \endverbatim
*
* \param runListFile Path to run list file
*
* \return
* - -1 if the run list file cannot be opened
* - 0 if all run numbers are valid
* - 1 otherwise
* - 1 if any run number is invalid (< 1) or file format is incorrect
*
* \param runListFile name of run list file
* \note Sets fRunListFile flag to true and opens stream for reading variables
*/
int PMsr2Data::SetRunNumbers(const std::string &runListFile)
{
@@ -366,13 +457,27 @@ int PMsr2Data::SetRunNumbers(const std::string &runListFile)
return 0;
}
//-------------------------------------------------------------
// ParseXmlStartupFile
//-------------------------------------------------------------
/**
* <p> Parse the musrfit startup xml file
* \brief Parses the musrfit XML startup file for configuration.
*
* <p><b>return:</b>
* - 0 if everything went fine
* - return value of the parseXmlFile function otherwise
* Creates a SAX parser and startup handler to read the musrfit_startup.xml
* configuration file. This file contains paths, templates, and other settings
* needed for msr2data operation.
*
* The parseXmlFile function is used instead of ParseFile to avoid
* environment-specific issues encountered with direct parsing.
*
* \return
* - 0 if parsing succeeded
* - Non-zero error code from parseXmlFile if parsing failed
*
* \note Outputs a warning to stderr if parsing fails
*
* \see PStartupHandler for XML configuration details
* \see parseXmlFile for the parsing implementation
*/
int PMsr2Data::ParseXmlStartupFile()
{
@@ -392,15 +497,22 @@ int PMsr2Data::ParseXmlStartupFile()
return status;
}
//-------------------------------------------------------------
// ReadMsrFile
//-------------------------------------------------------------
/**
* <p> Read in a msr-file into the default structure
* \brief Reads and parses an msr-file.
*
* <p><b>return:</b>
* - PMUSR_SUCCESS if everything is OK
* - return value of the ReadMsrFile-method otherwise
* Creates a new PMsrHandler and uses it to read and parse the specified
* msr-file into the internal data structure.
*
* \param infile name of the msr-file to be read
* \param infile Path to the msr-file to read
*
* \return
* - PMUSR_SUCCESS if reading and parsing succeeded
* - Error code from PMsrHandler::ReadMsrFile otherwise
*
* \see PMsrHandler::ReadMsrFile for parsing details
*/
int PMsr2Data::ReadMsrFile(const std::string &infile) const
{
@@ -423,14 +535,23 @@ int PMsr2Data::ReadMsrFile(const std::string &infile) const
return status;
}
//-------------------------------------------------------------
// GetSingleRunMsrFile
//-------------------------------------------------------------
/**
* <p> Read in the single run msr-file corresponding to the position in the run-vector
* into a secondary msr-handler different from the class member
* \brief Retrieves msr-file handler for a single-run fit file.
*
* <p><b>return:</b>
* - pointer to the secondary msr-handler or 0 in case of an error
* Reads the "-OneRunFit" variant of the msr-file for the current run.
* This is used when extracting individual run results from global fits.
*
* The file name format: "<runNumber>-OneRunFit<extension>.msr"
*
* \return
* - Pointer to newly created PMsrHandler on success
* - nullptr if file cannot be read or parsed
*
* \note Caller is responsible for deleting the returned handler
* \note Different from the class member fMsrHandler
*/
PMsrHandler* PMsr2Data::GetSingleRunMsrFile() const
{
@@ -457,13 +578,23 @@ PMsrHandler* PMsr2Data::GetSingleRunMsrFile() const
return singleRunMsrFile;
}
//-------------------------------------------------------------
// ReadRunDataFile
//-------------------------------------------------------------
/**
* <p> Read in a run data-file
* \brief Reads the run data file for the current run.
*
* <p><b>return:</b>
* - 0 if everything is OK
* - 1 otherwise
* Creates a PRunDataHandler and reads the experimental data file
* associated with the current msr-file. Uses data paths from the
* startup handler if available, otherwise uses defaults.
*
* \return
* - 0 if all data was successfully read
* - 1 if some data files could not be read (with warning)
*
* \note Outputs a warning to stderr if data is unavailable but continues processing
*
* \see PRunDataHandler for data file reading details
*/
int PMsr2Data::ReadRunDataFile()
{
@@ -2457,13 +2588,23 @@ int PMsr2Data::WriteOutput(const std::string &outfile, const std::vector<unsigne
}
//-------------------------------------------------------------
// WriteValue (single value)
//-------------------------------------------------------------
/**
* <p>Write formatted output to column-formatted ASCII output file
* \brief Writes a formatted numeric value to output stream.
*
* \param outFile output file stream to the ASCII file
* \param value number to be written to the ASCII file
* \param width column width of the ASCII file
* Formats the value for column-aligned ASCII output with automatic
* selection of scientific notation for very large or very small numbers.
*
* Formatting rules:
* - Scientific notation if |value| >= 1e6 or (|value| < 1e-4 and value != 0)
* - Fixed-point notation otherwise
* - Left-aligned in field of specified width
*
* \param outFile Output file stream
* \param value Numeric value to write
* \param width Column width for formatting
*/
void PMsr2Data::WriteValue(std::fstream &outFile, const double &value, const unsigned int &width) const
{
@@ -2474,16 +2615,32 @@ void PMsr2Data::WriteValue(std::fstream &outFile, const double &value, const uns
outFile << std::setw(width) << std::left << value;
}
//-------------------------------------------------------------
// WriteValue (value with error)
//-------------------------------------------------------------
/**
* <p>Write a value to the outFile stream. The string length is determined on its error.
* E.g. 17.0023 +- 0.0018, or 73212.081 +- 0.033, etc.
* \brief Writes a value with error-based precision formatting.
*
* \param outFile output stream object
* \param value to be written to stream outFile
* \param errValue error of the value. needed to determine the needed accuracy
* \param width field width for outFile for formatted output
* \param db true for db-file output, false for dat-file output. Needed to have at least on space between numbers for dat-file output
* Formats output with precision determined by the error value, ensuring
* significant digits are preserved appropriately. The precision is calculated
* based on the first significant digit of the error.
*
* Examples:
* - value=17.0023 ± errValue=0.0018 → formatted with 4 decimal places
* - value=73212.081 ± errValue=0.033 → formatted with 2 decimal places
*
* Formatting rules:
* - Precision based on error's first significant digit
* - Scientific notation if |value| >= 1e6 or (|value| < 1e-4 and value != 0)
* - Extra space added after value in ASCII mode for readability
*
* \param outFile Output file stream
* \param value Numeric value to write
* \param errValue Error/uncertainty value (determines precision)
* \param width Field width for formatted output
* \param db true for DB format, false for ASCII format (adds extra space)
*
* \see GetFirstSignificantDigit for precision calculation
*/
void PMsr2Data::WriteValue(std::fstream &outFile, const double &value, const double &errValue, const unsigned int &width, const bool &db) const
{
@@ -2509,14 +2666,28 @@ void PMsr2Data::WriteValue(std::fstream &outFile, const double &value, const dou
}
}
//-------------------------------------------------------------
// GetFirstSignificantDigit
//-------------------------------------------------------------
/**
* <p>Determines the first significant digit of the provided number value.
* E.g. for value=2.03 it will return 1, for value=0.00023 it will return 4, etc.
* \brief Determines the position of the first significant digit.
*
* \param value for which the first significant digit needs to be determined.
* Calculates how many decimal places are needed to reach the first
* significant digit by repeatedly multiplying by 10 until the value
* is >= 1.0. This is used for precision control in output formatting.
*
* \return first significant digit of the provided number value
* Examples:
* - value = 2.03 → returns 1 (first significant digit in tenths place)
* - value = 0.00023 → returns 4 (first significant digit in ten-thousandths)
* - value = 0.5 → returns 1
*
* \param value Value to analyze (typically an error/uncertainty)
*
* \return
* - Position of first significant digit (1-19)
* - 6 if no significant digit found after 20 iterations (default precision)
*
* \note Maximum 20 iterations to prevent infinite loops
*/
int PMsr2Data::GetFirstSignificantDigit(const double &value) const
{
@@ -2538,15 +2709,26 @@ int PMsr2Data::GetFirstSignificantDigit(const double &value) const
return prec+1;
}
//-------------------------------------------------------------
// InParameterList
//-------------------------------------------------------------
/**
* <p>Checks paramValue is found in the paramList. If paramList
* is empty, ALL paramValues will be accepted, i.e. return true.
* \brief Checks if a parameter index should be included in output.
*
* \param paramValue paramValue to be checked
* \param paramList parameter list
* Determines whether a given parameter should be written to the output
* file based on the user-specified parameter list. If the parameter list
* is empty, all parameters are included by default.
*
* \return true if the paramValue if found in paramList, or true if paramList is empty.
* \param paramValue Zero-based parameter index to check
* \param paramList Vector of one-based parameter numbers to output
* (empty vector means output all parameters)
*
* \return
* - true if paramValue should be included in output
* - true if paramList is empty (output all parameters)
* - false if paramValue is not in the list
*
* \note paramValue is zero-based while paramList contains one-based indices
*/
bool PMsr2Data::InParameterList(const unsigned int &paramValue, const std::vector<unsigned int> &paramList) const
{

View File

@@ -45,57 +45,273 @@
//-------------------------------------------------------------
/**
* <p> Class providing the necessary utilities for msr2data:
* generate new msr-files from a template, collect fit parameters from msr-files and write them to DB or plain ASCII files
* \brief Utility class for msr2data: template-based msr-file generation and parameter extraction.
*
* PMsr2Data provides comprehensive functionality for the msr2data tool, which is used to:
* - Generate new msr-files from templates by substituting run numbers
* - Extract fit parameters from analyzed msr-files
* - Write collected parameters to database (DB) or plain ASCII files
* - Support both single-run and global (multi-run) fitting workflows
*
* Key Features:
* - Template-based msr-file generation with automatic run number substitution
* - Flexible run number specification (single, range, list file, explicit list)
* - Parameter extraction from fitted msr-files
* - Multiple output formats (DB format, ASCII tables)
* - Global fitting support for combined multi-run analysis
* - XML-based configuration via startup files
*
* Implementation Note:
* This class uses std::string and standard C++ string handling exclusively
* (rather than ROOT's TString) to demonstrate modern C++ practices, though
* this occasionally requires conversions when interfacing with PMusr classes.
*
* Typical Workflow:
* 1. Create PMsr2Data object with file extension
* 2. Parse XML startup file for configuration
* 3. Set run numbers (single, range, or list)
* 4. Generate msr-files from template or extract parameters from fitted files
* 5. Write output to DB or ASCII format
*
* \see PStartupHandler for XML configuration parsing
* \see PRunDataHandler for run data management
* \see PMsrHandler for msr-file parsing and manipulation
*/
class PMsr2Data
{
public:
PMsr2Data(const std::string&); // File extension
//-----------------------------------------------------------------------
/**
* \brief Constructor that initializes the msr2data handler.
*
* \param fileExtension File extension for data files (e.g., "bin", "root", "mdu")
*/
PMsr2Data(const std::string& fileExtension);
//-----------------------------------------------------------------------
/**
* \brief Destructor that cleans up resources.
*/
~PMsr2Data();
int SetRunNumbers(unsigned int); // single run given
int SetRunNumbers(unsigned int, unsigned int); // run list specified through first and last run number
int SetRunNumbers(const std::string&); // run list file given
int SetRunNumbers(const std::vector<unsigned int>&); // explicit run list specified using [ ]
//-----------------------------------------------------------------------
/**
* \brief Sets a single run number for processing.
*
* \param runNumber Single run number to process
* \return 0 on success, non-zero on error
*/
int SetRunNumbers(unsigned int runNumber);
//-----------------------------------------------------------------------
/**
* \brief Sets a range of run numbers (from first to last, inclusive).
*
* \param firstRun First run number in the range
* \param lastRun Last run number in the range
* \return 0 on success, non-zero on error
*/
int SetRunNumbers(unsigned int firstRun, unsigned int lastRun);
//-----------------------------------------------------------------------
/**
* \brief Sets run numbers from a run list file.
*
* Reads run numbers from a text file, one run number per line.
*
* \param runListFileName Path to file containing run numbers
* \return 0 on success, non-zero on error
*/
int SetRunNumbers(const std::string& runListFileName);
//-----------------------------------------------------------------------
/**
* \brief Sets run numbers from an explicit vector.
*
* \param runVector Vector of run numbers to process
* \return 0 on success, non-zero on error
*/
int SetRunNumbers(const std::vector<unsigned int>& runVector);
//-----------------------------------------------------------------------
/**
* \brief Gets the current run number being processed.
*
* \return Current run number from the internal iterator
*/
unsigned int GetPresentRun() const;
int DetermineRunNumberDigits(unsigned int, bool) const;
//-----------------------------------------------------------------------
/**
* \brief Determines the number of digits needed for run number formatting.
*
* Analyzes run numbers to determine zero-padding requirements for
* consistent file naming.
*
* \param maxRunNumber Maximum run number to consider
* \param templateFile Whether processing a template file
* \return Number of digits needed for run number formatting
*/
int DetermineRunNumberDigits(unsigned int maxRunNumber, bool templateFile) const;
//-----------------------------------------------------------------------
/**
* \brief Validates that all run numbers are within acceptable ranges.
*
* \return 0 if all run numbers are valid, non-zero otherwise
*/
int CheckRunNumbersInRange() const;
//-----------------------------------------------------------------------
/**
* \brief Parses the XML startup file for configuration.
*
* Reads and processes the msr2data XML startup file containing
* paths, templates, and other configuration settings.
*
* \return 0 on success, non-zero on parsing errors
*/
int ParseXmlStartupFile();
int ReadMsrFile(const std::string&) const;
//-----------------------------------------------------------------------
/**
* \brief Reads and parses an msr-file.
*
* \param msrFileName Path to the msr-file to read
* \return 0 on success, non-zero on read/parse errors
*/
int ReadMsrFile(const std::string& msrFileName) const;
//-----------------------------------------------------------------------
/**
* \brief Reads the run data file for the current run.
*
* \return 0 on success, non-zero on read errors
*/
int ReadRunDataFile();
bool PrepareNewInputFile(unsigned int, bool) const; // template
bool PrepareGlobalInputFile(unsigned int, const std::string&, unsigned int) const; // generate msr-input file for a global fit
//-----------------------------------------------------------------------
/**
* \brief Generates a new msr-file from a template.
*
* Creates an msr-file by substituting run number placeholders in the
* template with actual run numbers.
*
* \param templateNumber Template identifier number
* \param sorted Whether to generate sorted output
* \return true on success, false on failure
*/
bool PrepareNewInputFile(unsigned int templateNumber, bool sorted) const;
int WriteOutput(const std::string&, const std::vector<unsigned int>&, bool, unsigned int, bool global = false, unsigned int counter = 0) const;
//-----------------------------------------------------------------------
/**
* \brief Generates an msr-file for global (multi-run) fitting.
*
* Creates a combined msr-file for global fits across multiple runs.
*
* \param templateNumber Template identifier number
* \param globalOutputFile Path to output global msr-file
* \param runListSize Number of runs in the global fit
* \return true on success, false on failure
*/
bool PrepareGlobalInputFile(unsigned int templateNumber, const std::string& globalOutputFile, unsigned int runListSize) const;
//-----------------------------------------------------------------------
/**
* \brief Writes extracted parameters to output file.
*
* Outputs fit parameters in either DB format or ASCII table format.
*
* \param outputFileName Output file path
* \param parameters Vector of parameter indices to output
* \param dbFormat Whether to use DB format (true) or ASCII (false)
* \param precision Number of significant digits for output
* \param global Whether this is global fit output
* \param counter Counter for global fit indexing
* \return 0 on success, non-zero on write errors
*/
int WriteOutput(const std::string& outputFileName, const std::vector<unsigned int>& parameters, bool dbFormat, unsigned int precision, bool global = false, unsigned int counter = 0) const;
private:
bool PrepareNewSortedInputFile(unsigned int) const; // template
//-----------------------------------------------------------------------
/**
* \brief Generates a sorted msr-file from a template.
*
* Internal helper for creating sorted msr-files with proper histogram ordering.
*
* \param templateNumber Template identifier number
* \return true on success, false on failure
*/
bool PrepareNewSortedInputFile(unsigned int templateNumber) const;
//-----------------------------------------------------------------------
/**
* \brief Retrieves msr-file handler for a single run.
*
* \return Pointer to PMsrHandler for the current run
*/
PMsrHandler* GetSingleRunMsrFile() const;
//-----------------------------------------------------------------------
/**
* \brief Writes a single numeric value to output stream.
*
* \param outFile Output file stream
* \param value Value to write
* \param width Field width for formatting
*/
void WriteValue(std::fstream &outFile, const double &value, const unsigned int &width) const;
void WriteValue(std::fstream &outFile, const double &value, const double &errValue, const unsigned int &width, const bool &db) const;
int GetFirstSignificantDigit(const double &value) const;
bool InParameterList(const unsigned int &paramValue, const std::vector<unsigned int>&) const;
std::string fFileExtension;
std::vector<unsigned int> fRunVector;
mutable std::vector<unsigned int>::const_iterator fRunVectorIter;
bool fRunListFile;
std::vector<std::string> fIndVar;
std::unique_ptr<std::ifstream> fRunListFileStream;
std::unique_ptr<TSAXParser> fSaxParser;
std::unique_ptr<PStartupHandler> fStartupHandler;
mutable std::unique_ptr<PRunDataHandler> fDataHandler;
mutable std::unique_ptr<PMsrHandler> fMsrHandler;
mutable unsigned int fNumGlobalParam;
mutable unsigned int fNumSpecParam;
mutable unsigned int fNumTempRunBlocks;
mutable unsigned int fRunNumberDigits;
mutable bool fHeaderWritten;
//-----------------------------------------------------------------------
/**
* \brief Writes a value with its error to output stream.
*
* Formats output based on DB or ASCII mode.
*
* \param outFile Output file stream
* \param value Value to write
* \param errValue Error/uncertainty value
* \param width Field width for formatting
* \param db Whether to use DB format (true) or ASCII (false)
*/
void WriteValue(std::fstream &outFile, const double &value, const double &errValue, const unsigned int &width, const bool &db) const;
//-----------------------------------------------------------------------
/**
* \brief Determines the first significant digit position of a value.
*
* Used for intelligent formatting and precision control.
*
* \param value Value to analyze
* \return Position of first significant digit
*/
int GetFirstSignificantDigit(const double &value) const;
//-----------------------------------------------------------------------
/**
* \brief Checks if a parameter is in the output parameter list.
*
* \param paramValue Parameter index to check
* \param paramList List of parameters to output
* \return true if parameter should be output, false otherwise
*/
bool InParameterList(const unsigned int &paramValue, const std::vector<unsigned int>& paramList) const;
std::string fFileExtension; ///< File extension for data files (e.g., "bin", "root")
std::vector<unsigned int> fRunVector; ///< Vector of run numbers to process
mutable std::vector<unsigned int>::const_iterator fRunVectorIter; ///< Iterator for current position in run vector
bool fRunListFile; ///< Flag indicating if run list is from a file
std::vector<std::string> fIndVar; ///< Independent variables for output
std::unique_ptr<std::ifstream> fRunListFileStream; ///< Stream for reading run list file
std::unique_ptr<TSAXParser> fSaxParser; ///< XML SAX parser for startup file
std::unique_ptr<PStartupHandler> fStartupHandler; ///< Handler for XML startup file configuration
mutable std::unique_ptr<PRunDataHandler> fDataHandler; ///< Handler for run data files
mutable std::unique_ptr<PMsrHandler> fMsrHandler; ///< Handler for msr-file parsing and generation
mutable unsigned int fNumGlobalParam; ///< Number of global parameters in fit
mutable unsigned int fNumSpecParam; ///< Number of spectrum-specific parameters
mutable unsigned int fNumTempRunBlocks; ///< Number of temporary run blocks
mutable unsigned int fRunNumberDigits; ///< Number of digits for run number formatting
mutable bool fHeaderWritten; ///< Flag tracking if output header has been written
};