improve the doxygen docu of PRunNonMusr.*

This commit is contained in:
2025-11-15 08:42:21 +01:00
parent 707736b8d4
commit 27b3b317ba
2 changed files with 589 additions and 29 deletions

View File

@@ -35,7 +35,21 @@
// Constructor
//--------------------------------------------------------------------------
/**
* <p>Constructor.
* \brief Default constructor creating an empty, invalid non-μSR run object.
*
* Initializes all member variables to default/safe values:
* - fNoOfFitBins = 0 (no bins to fit)
* - fPacking = 1 (no data averaging)
* - fStartTimeBin = 0 (first data point)
* - fEndTimeBin = 0 (no range)
* - fHandleTag = kEmpty (uninitialized)
* - fRawRunData = nullptr (no data loaded)
*
* This constructor is needed for creating vectors of PRunNonMusr objects.
* The resulting object cannot be used until properly initialized via the
* main constructor.
*
* \see PRunNonMusr(PMsrHandler*, PRunDataHandler*, UInt_t, EPMusrHandleTag, Bool_t)
*/
PRunNonMusr::PRunNonMusr() : PRunBase()
{
@@ -53,12 +67,48 @@ PRunNonMusr::PRunNonMusr() : PRunBase()
// Constructor
//--------------------------------------------------------------------------
/**
* <p>Constructor
* \brief Main constructor initializing a non-μSR run from MSR file and x-y data.
*
* \param msrInfo pointer to the msr-file handler
* \param rawData raw run data
* \param runNo number of the run within the msr-file
* \param tag tag showing what shall be done: kFit == fitting, kView == viewing
* Performs comprehensive initialization for general curve fitting:
*
* 1. <b>Base Class Initialization:</b>
* - Calls PRunBase constructor with MSR/data handlers
* - Initializes theory engine and parameter mappings
* - Sets up FUNCTIONS block evaluation
*
* 2. <b>Raw Data Loading:</b>
* - Retrieves raw x-y data using run name from MSR file
* - Calls fRawData->GetRunData(*runName)
* - Validates data was successfully loaded
* - If loading fails → marks run invalid, prints error
*
* 3. <b>Data Preparation:</b>
* - Calls PrepareData() to process x-y data
* - Extracts x-y columns based on MSR file specification
* - Applies packing to average data points
* - Sets up fit range boundaries
* - If preparation fails → marks run invalid
*
* The object is marked as invalid (fValid=false) if:
* - Raw data file cannot be loaded (file not found, wrong format, etc.)
* - PrepareData() fails (invalid column indices, missing packing, etc.)
*
* Key features for non-μSR:
* - No histogram processing (data is already x-y pairs)
* - No time-zero determination (not time-differential)
* - No background subtraction (included in y-data)
* - No asymmetry calculation (direct y vs. x fitting)
*
* \param msrInfo Pointer to MSR file handler (must remain valid for object lifetime)
* \param rawData Pointer to raw data handler for loading data files
* \param runNo Run number (0-based index in MSR file RUN blocks)
* \param tag Operation mode: kFit (fitting), kView (display/plotting)
* \param theoAsData Theory mode: true = at data x-values, false = high-resolution (minimal effect for non-μSR)
*
* \warning Always check IsValid() after construction before using for fitting
*
* \see PrepareData() for data processing details
* \see PRunBase constructor for base class initialization
*/
PRunNonMusr::PRunNonMusr(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t runNo, EPMusrHandleTag tag, Bool_t theoAsData) :
PRunBase(msrInfo, rawData, runNo, tag), fTheoAsData(theoAsData)
@@ -80,7 +130,15 @@ PRunNonMusr::PRunNonMusr(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t
// Destructor
//--------------------------------------------------------------------------
/**
* <p>Destructor
* \brief Destructor (no cleanup needed for non-μSR).
*
* The fRawRunData pointer is not owned by this class and is not deleted here.
* It is managed by the PRunDataHandler and will be cleaned up externally.
*
* Base class destructor (PRunBase) handles cleanup of:
* - Theory engine objects
* - Parameter mapping structures
* - Function value caches
*/
PRunNonMusr::~PRunNonMusr()
{
@@ -90,12 +148,43 @@ PRunNonMusr::~PRunNonMusr()
// CalcChiSquare
//--------------------------------------------------------------------------
/**
* <p>Calculate chi-square.
* \brief Calculates χ² between non-μSR x-y data and theory.
*
* <b>return:</b>
* - chisq value
* Computes the chi-squared statistic for general x-y data:
* \f[ \chi^2 = \sum_{i={\rm start}}^{\rm end} \frac{(y_i - f(x_i))^2}{\sigma_i^2} \f]
*
* \param par parameter vector iterated by minuit2
* where:
* - x_i is the independent variable (arbitrary units)
* - y_i is the measured dependent variable
* - f(x_i) is the theory function evaluated at x_i
* - σ_i is the error on y_i (from data file)
*
* Algorithm:
* 1. <b>Evaluate FUNCTIONS block:</b>
* - Loop over user-defined functions
* - Compute function values using current parameters
* - Store in fFuncValues for use by theory
*
* 2. <b>Calculate χ² sum:</b>
* - Loop from fStartTimeBin to fEndTimeBin (inclusive)
* - For each data point i:
* a. Get x-value: x = fData.GetX()->at(i)
* b. Evaluate theory at x: theo = fTheory->Func(x, par, fFuncValues)
* c. Get data and error: y = fData.GetValue()->at(i), σ = fData.GetError()->at(i)
* d. Compute contribution: Δχ² = (y - theo)² / σ²
* - Sum all contributions
*
* Key differences from μSR fits:
* - x-axis is arbitrary (not necessarily time in μs)
* - Theory evaluated on-demand (not pre-calculated on grid)
* - Loop end is INCLUSIVE (i <= fEndTimeBin)
* - No OpenMP parallelization (simpler, smaller data sets)
*
* \param par Parameter vector from MINUIT with current parameter values
* \return Chi-squared value (minimize during fitting)
*
* \see CalcMaxLikelihood() - NOT IMPLEMENTED for non-μSR
* \see PrepareData() for x-y data loading and fit range setup
*/
Double_t PRunNonMusr::CalcChiSquare(const std::vector<Double_t>& par)
{
@@ -122,12 +211,26 @@ Double_t PRunNonMusr::CalcChiSquare(const std::vector<Double_t>& par)
// CalcChiSquareExpected (public)
//--------------------------------------------------------------------------
/**
* <p>Calculate expected chi-square. Currently not implemented since not clear what to be done.
* \brief Calculates expected χ² (NOT IMPLEMENTED for non-μSR).
*
* <b>return:</b>
* - chisq value == 0.0
* This method is not implemented because the concept of "expected χ²" requires
* knowledge of the underlying statistical distribution of the data, which is
* not well-defined for general x-y data.
*
* \param par parameter vector iterated by minuit2
* For μSR histogram data, the expected χ² can be calculated based on Poisson
* statistics. For arbitrary non-μSR data, the appropriate statistical model
* depends on the data source:
* - Counting experiments → Poisson
* - Averaged measurements → Gaussian
* - Other experiments → problem-specific distributions
*
* Without knowing the data's statistical nature, a meaningful implementation
* cannot be provided.
*
* \param par Parameter vector from MINUIT (unused)
* \return Always returns 0.0
*
* \note Prints "not implemented yet" message to stdout
*/
Double_t PRunNonMusr::CalcChiSquareExpected(const std::vector<Double_t>& par)
{
@@ -140,12 +243,32 @@ Double_t PRunNonMusr::CalcChiSquareExpected(const std::vector<Double_t>& par)
// CalcMaxLikelihood
//--------------------------------------------------------------------------
/**
* <p>Calculate log maximum-likelihood. Currently not implemented since not clear what to be done.
* \brief Calculates maximum likelihood (NOT IMPLEMENTED for non-μSR).
*
* <b>return:</b>
* - log maximum-likelihood value == 1.0
* Maximum likelihood fitting is not implemented for general x-y data because:
*
* \param par parameter vector iterated by minuit2
* 1. <b>Distribution-dependent:</b> The likelihood function depends on the
* underlying statistical distribution of the data points, which varies:
* - Poisson: For counting experiments (like μSR histograms)
* - Gaussian: For averaged measurements with known errors
* - Other: Problem-specific distributions (binomial, exponential, etc.)
*
* 2. <b>Gaussian case equivalence:</b> If errors are Gaussian, maximum likelihood
* is mathematically equivalent to χ² minimization (already implemented).
*
* 3. <b>Implementation complexity:</b> Supporting arbitrary likelihood functions
* would require users to specify the distribution, adding complexity without
* clear benefit for most non-μSR applications.
*
* For general x-y data with Gaussian errors, use χ² fitting via CalcChiSquare().
* For non-Gaussian statistics, users should implement custom fitting outside musrfit.
*
* \param par Parameter vector from MINUIT (unused)
* \return Always returns 1.0
*
* \note Prints "not implemented yet" message to stdout
*
* \see CalcChiSquare() for standard least-squares fitting (recommended for non-μSR)
*/
Double_t PRunNonMusr::CalcMaxLikelihood(const std::vector<Double_t>& par)
{
@@ -158,7 +281,20 @@ Double_t PRunNonMusr::CalcMaxLikelihood(const std::vector<Double_t>& par)
// CalcTheory
//--------------------------------------------------------------------------
/**
* <p>Calculate theory for a given set of fit-parameters.
* \brief Evaluates theory function (empty implementation for non-μSR).
*
* For non-μSR data, theory calculation is performed on-demand within
* CalcChiSquare() rather than pre-calculating and storing theory values.
*
* This design choice is made because:
* - Theory is evaluated at arbitrary x-values from the data file
* - No need for high-resolution theory grid (data defines x-points)
* - Simpler and more efficient to evaluate during χ² loop
* - Avoids storing redundant theory array
*
* This empty method exists solely to satisfy the PRunBase interface requirement.
*
* \see CalcChiSquare() for on-demand theory evaluation at each data point
*/
void PRunNonMusr::CalcTheory()
{
@@ -168,9 +304,28 @@ void PRunNonMusr::CalcTheory()
// GetNoOfFitBins (public)
//--------------------------------------------------------------------------
/**
* <p>Calculate the number of fitted bins for the current fit range.
* \brief Calculates and returns the number of x-y points within the fit range.
*
* <b>return:</b> number of fitted bins.
* Counts data points where fFitStartTime ≤ x ≤ fFitEndTime (both inclusive).
* This count is essential for:
* - Degrees of freedom: ν = N_points - N_params
* - Reduced χ²: χ²_red = χ² / ν
* - Statistical quality assessment: χ²/ν ≈ 1 indicates good fit
*
* Algorithm:
* 1. Reset counter: fNoOfFitBins = 0
* 2. Loop through all x-values in fData.GetX()
* 3. For each x-value:
* - If fFitStartTime ≤ x ≤ fFitEndTime → increment counter
* 4. Return final count
*
* The fit range (fFitStartTime, fFitEndTime) is specified in the MSR file
* RUN or GLOBAL block "fit" entry, in the same units as the x-axis data.
*
* \return Number of data points within fit range
*
* \note This method recalculates the count each time it's called (not cached),
* allowing for dynamic fit range changes.
*/
UInt_t PRunNonMusr::GetNoOfFitBins()
{