diff --git a/src/classes/PRunNonMusr.cpp b/src/classes/PRunNonMusr.cpp index fa6b50f68..f1e4f81ed 100644 --- a/src/classes/PRunNonMusr.cpp +++ b/src/classes/PRunNonMusr.cpp @@ -35,7 +35,21 @@ // Constructor //-------------------------------------------------------------------------- /** - *
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 //-------------------------------------------------------------------------- /** - *
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. Base Class Initialization: + * - Calls PRunBase constructor with MSR/data handlers + * - Initializes theory engine and parameter mappings + * - Sets up FUNCTIONS block evaluation + * + * 2. Raw Data Loading: + * - 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. Data Preparation: + * - 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 //-------------------------------------------------------------------------- /** - *
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 //-------------------------------------------------------------------------- /** - *
Calculate chi-square.
+ * \brief Calculates χ² between non-μSR x-y data and theory.
*
- * return:
- * - 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. Evaluate FUNCTIONS block:
+ * - Loop over user-defined functions
+ * - Compute function values using current parameters
+ * - Store in fFuncValues for use by theory
+ *
+ * 2. Calculate χ² sum:
+ * - 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 Calculate expected chi-square. Currently not implemented since not clear what to be done.
+ * \brief Calculates expected χ² (NOT IMPLEMENTED for non-μSR).
*
- * return:
- * - 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 Calculate log maximum-likelihood. Currently not implemented since not clear what to be done.
+ * \brief Calculates maximum likelihood (NOT IMPLEMENTED for non-μSR).
*
- * return:
- * - 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. Distribution-dependent: 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. Gaussian case equivalence: If errors are Gaussian, maximum likelihood
+ * is mathematically equivalent to χ² minimization (already implemented).
+ *
+ * 3. Implementation complexity: 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 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)
//--------------------------------------------------------------------------
/**
- * 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.
*
- * return: 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()
{
diff --git a/src/include/PRunNonMusr.h b/src/include/PRunNonMusr.h
index 1196c649c..a1d3d60c0 100644
--- a/src/include/PRunNonMusr.h
+++ b/src/include/PRunNonMusr.h
@@ -34,41 +34,446 @@
#include "PRunBase.h"
/**
- * Class handling the non-muSR fit type
+ * \brief Class for fitting general x-y data sets (non-μSR time series).
+ *
+ * PRunNonMusr extends the musrfit framework to handle arbitrary x-y data that doesn't
+ * originate from μSR experiments. This allows users to leverage musrfit's powerful
+ * fitting engine, theory functions, and MINUIT interface for general curve fitting tasks.
+ *
+ * \section nonmusr_purpose Purpose and Use Cases
+ *
+ * This fit type is designed for:
+ * - General time-series data: Any x vs. y measurements
+ * - Non-μSR physics: Other experimental data (e.g., optical, electrical, thermal)
+ * - Reusing μSR theory functions: Apply exponentials, oscillations, relaxations to non-μSR data
+ * - Custom data analysis: Fit arbitrary functional forms to experimental data
+ * - Method validation: Test fitting procedures on simulated or benchmark data
+ *
+ * \section nonmusr_data Data Structure
+ *
+ * Unlike μSR fits, non-μSR data is provided as simple x-y pairs:
+ * - x-axis: Independent variable (time, temperature, field, voltage, etc.)
+ * - y-axis: Dependent variable (signal, counts, current, etc.)
+ * - Errors: Optional error bars on y-values
+ * - No histograms: Data is already processed, not raw detector counts
+ * - No t0: No time-zero concept (not time-differential μSR)
+ * - No asymmetry: Direct fitting of y vs. x
+ *
+ * \section nonmusr_input Data Input Formats
+ *
+ * Non-μSR data can be loaded from:
+ * - ASCII files: Space/tab-separated columns (x, y, err)
+ * - DB files: Database format with metadata
+ * - MuSonRoot files: Special ROOT structure for non-μSR data
+ *
+ * ASCII format example:
+ * \code
+ * # x-axis y-axis error
+ * 0.0 100.5 3.2
+ * 0.1 95.3 3.1
+ * 0.2 90.8 3.0
+ * ...
+ * \endcode
+ *
+ * \section nonmusr_msr MSR File Configuration
+ *
+ * Example MSR file RUN block for non-μSR data:
+ * \code
+ * RUN data/mydata.dat DB PSI MUSR-ROOT (name beamline)
+ * fittype 12 (NonMusr)
+ * map 1 2 (x-index, y-index in data columns)
+ * xy-data 0 1 (column 0 = x, column 1 = y)
+ * packing 1 (usually 1 for pre-processed data)
+ * fit 0.0 10.0 (fit range in x-axis units)
+ * \endcode
+ *
+ * \section nonmusr_theory Theory Functions
+ *
+ * All standard musrfit theory functions can be used:
+ * - Exponentials: decay, growth, stretched exponentials
+ * - Oscillations: cosine, sine, damped oscillations
+ * - Relaxations: static/dynamic Gaussian/Lorentzian Kubo-Toyabe
+ * - Polynomials: backgrounds, baselines
+ * - User functions: Custom C++ functions
+ *
+ * Theory is evaluated at the x-values from the data file.
+ *
+ * \section nonmusr_differences Key Differences from μSR Fits
+ *
+ *
+ *
+ *
+ * \section nonmusr_limitations Limitations
+ *
+ * - No ADDRUN: Cannot combine multiple non-μSR data sets
+ * - No maximum likelihood: Only χ² fitting supported (not implemented for non-μSR)
+ * - No expected χ²: Not implemented (unclear definition for general data)
+ * - Simple error handling: Assumes independent Gaussian errors
+ *
+ * \section nonmusr_workflow Analysis Workflow
+ *
+ * 1. Prepare Data: Format as x-y(-error) columns in ASCII/DB file
+ * 2. Create MSR File: Specify file, fit type (12), xy-data indices, fit range
+ * 3. Define Theory: Use standard THEORY block functions
+ * 4. Run Fit: musrfit performs χ² minimization via MINUIT
+ * 5. Analyze Results: Standard parameter extraction, error analysis, plotting
+ *
+ * \see PRunSingleHisto for standard μSR single histogram fits
+ * \see PRunBase for base class interface and common functionality
*/
class PRunNonMusr : public PRunBase
{
public:
+ /**
+ * \brief Default constructor creating an empty, invalid non-μSR run object.
+ *
+ * Initializes all member variables to default values:
+ * - Bin counts set to 0
+ * - Packing set to 1 (no packing for x-y data)
+ * - Handle tag set to kEmpty
+ * - Raw data pointer set to nullptr
+ *
+ * This constructor is needed for creating vectors of PRunNonMusr objects.
+ * The resulting object cannot be used until properly initialized via the main constructor.
+ */
PRunNonMusr();
+
+ /**
+ * \brief Main constructor initializing a non-μSR run from MSR file and data.
+ *
+ * Performs initialization for general x-y data fitting:
+ *
+ * 1. Base Class Initialization:
+ * - Calls PRunBase constructor with MSR/data handlers
+ * - Initializes theory engine
+ *
+ * 2. Raw Data Loading:
+ * - Retrieves raw data using run name from MSR file
+ * - Validates data was successfully loaded
+ * - Marks run invalid if data cannot be loaded
+ *
+ * 3. Data Preparation:
+ * - Calls PrepareData() to process x-y data
+ * - Extracts x-y columns based on map/xy-data specification
+ * - Applies packing if specified
+ * - Sets up fit range in x-axis units
+ *
+ * The object is marked as invalid (fValid=false) if:
+ * - Raw data file cannot be loaded
+ * - PrepareData() fails (invalid column indices, missing data, etc.)
+ *
+ * \param msrInfo Pointer to MSR file handler (must remain valid)
+ * \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 points, false = high-resolution
+ *
+ * \warning Check IsValid() after construction before using for fitting
+ *
+ * \see PrepareData() for data processing details
+ */
PRunNonMusr(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t runNo, EPMusrHandleTag tag, Bool_t theoAsData);
+
+ /**
+ * \brief Virtual destructor (no cleanup needed for this class).
+ *
+ * Raw data pointer (fRawRunData) is not owned by this class and is not deleted.
+ * Base class destructor handles cleanup of theory objects and other shared resources.
+ */
virtual ~PRunNonMusr();
+ /**
+ * \brief Calculates χ² between non-μSR data and theory.
+ *
+ * Computes the chi-squared statistic for x-y data:
+ * \f[ \chi^2 = \sum_{i={\rm start}}^{\rm end} \frac{(y_i^{\rm data} - y_i^{\rm theory})^2}{\sigma_i^2} \f]
+ *
+ * where:
+ * - y_i^data is the measured y-value at x_i
+ * - y_i^theory is the theory function evaluated at x_i
+ * - σ_i is the error on y_i (from data file or assumed)
+ * - Sum runs over all points within fit range (fFitStartTime ≤ x ≤ fFitEndTime)
+ *
+ * Algorithm:
+ * 1. Evaluate FUNCTIONS block for user-defined functions
+ * 2. Loop over data points from fStartTimeBin to fEndTimeBin
+ * 3. For each point:
+ * - Get x-value from fData.GetX()
+ * - Evaluate theory at that x-value: fTheory->Func(x, par, fFuncValues)
+ * - Compute weighted squared difference
+ * 4. Sum contributions to get total χ²
+ *
+ * Unlike μSR fits, this operates on x-y data directly (not histograms).
+ * The x-axis can represent any independent variable (time, temperature, field, etc.),
+ * not just time in microseconds.
+ *
+ * \param par Parameter vector from MINUIT with current parameter values
+ * \return Chi-squared value (sum of weighted squared residuals)
+ *
+ * \note No OpenMP parallelization in this implementation (typically smaller data sets)
+ *
+ * \see CalcMaxLikelihood() - NOT IMPLEMENTED for non-μSR
+ */
virtual Double_t CalcChiSquare(const std::vector
+ * Feature μSR Fits Non-μSR Fits
+ * Data type Raw histograms Processed x-y pairs
+ * Time zero (t0) Required Not applicable
+ * Background Estimated/subtracted Included in y-data
+ * Asymmetry Calculated Not applicable
+ * Packing Rebin histograms Average x-y points
+ * Fit range Time (μs) x-axis units (arbitrary)
+ * ADDRUN Supported NOT supported