improve doxygen documentation of PMsr2Data.*

This commit is contained in:
2025-11-14 09:11:28 +01:00
parent 91e76d56df
commit 41b39ab2ab
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
{