improve the doxygen docu of PRunListCollection.*

This commit is contained in:
2025-11-15 08:27:51 +01:00
parent 26b87e0659
commit 278fd47e52
2 changed files with 830 additions and 53 deletions

View File

@@ -35,10 +35,28 @@
// Constructor
//--------------------------------------------------------------------------
/**
* <p>Constructor.
* \brief Constructor initializing the run collection manager.
*
* \param msrInfo pointer to the msr-file handler
* \param data pointer to the run-data handler
* Creates an empty collection ready to receive processed run objects via Add() calls.
* The collection maintains separate lists for each fit type (single histogram, asymmetry,
* RRF variants, etc.) and dispatches operations to the appropriate lists.
*
* Initialization:
* - Stores pointers to MSR file handler and raw data handler (not owned)
* - Sets theory calculation mode flag (for plotting vs. fitting)
* - All run lists start empty; populated via subsequent Add() calls
*
* The typical workflow is:
* 1. Create PRunListCollection
* 2. Call Add() for each RUN block in MSR file
* 3. Use Get*Chisq() or Get*MaximumLikelihood() during fitting
* 4. Use Get*() accessors for visualization and analysis
*
* \param msrInfo Pointer to MSR file handler (must remain valid for object lifetime)
* \param data Pointer to raw data handler for loading histogram files
* \param theoAsData Theory calculation mode: true = at data points only, false = high-resolution grid
*
* \see Add() for adding processed runs to the collection
*/
PRunListCollection::PRunListCollection(PMsrHandler *msrInfo, PRunDataHandler *data, Bool_t theoAsData) :
fMsrInfo(msrInfo), fData(data), fTheoAsData(theoAsData)
@@ -49,7 +67,24 @@ PRunListCollection::PRunListCollection(PMsrHandler *msrInfo, PRunDataHandler *da
// Destructor
//--------------------------------------------------------------------------
/**
* <p>Destructor
* \brief Destructor that cleans up all run objects.
*
* Systematically destroys all PRunBase-derived objects in the collection:
* 1. Calls CleanUp() on each run object to release internal resources
* 2. Explicitly calls destructor to free memory
* 3. Clears the vector to release the pointer storage
*
* This process is repeated for all seven run type lists:
* - Single histogram runs
* - Single histogram RRF runs
* - Asymmetry runs
* - Asymmetry RRF runs
* - β-NMR asymmetry runs
* - μ⁻ (mu-minus) runs
* - Non-μSR runs
*
* The MSR handler (fMsrInfo) and data handler (fData) are NOT deleted
* as they are owned by the calling code.
*/
PRunListCollection::~PRunListCollection()
{
@@ -100,14 +135,35 @@ PRunListCollection::~PRunListCollection()
// Add (public)
//--------------------------------------------------------------------------
/**
* <p>Adds a processed set of data to the handler.
* \brief Adds a processed run to the appropriate list based on fit type.
*
* <b>return:</b>
* - true if a processed data set could be added successfully
* - false otherwise
* Creates a new PRunBase-derived object for the specified MSR file RUN block and
* adds it to the appropriate type-specific list. The method performs fit type
* dispatching by:
* 1. Reading fit type from the RUN block (if specified)
* 2. Falling back to GLOBAL block fit type if not specified in RUN
* 3. Creating the appropriate run object based on fit type
* 4. Calling PrepareData() on the new object to load and process data
* 5. Checking validity and returning success/failure status
*
* \param runNo msr-file run number
* \param tag tag showing what shall be done: kFit == fitting, kView == viewing
* Supported fit types and corresponding classes:
* - PRUN_SINGLE_HISTO → PRunSingleHisto
* - PRUN_SINGLE_HISTO_RRF → PRunSingleHistoRRF
* - PRUN_ASYMMETRY → PRunAsymmetry
* - PRUN_ASYMMETRY_RRF → PRunAsymmetryRRF
* - PRUN_ASYMMETRY_BNMR → PRunAsymmetryBNMR
* - PRUN_MU_MINUS → PRunMuMinus
* - PRUN_NON_MUSR → PRunNonMusr
*
* If data preprocessing fails (e.g., file not found, invalid t0, theory errors),
* the run object is still added to the list but marked as invalid, and this
* method returns false.
*
* \param runNo MSR file run number (0-based index into RUN blocks)
* \param tag Operation mode: kFit (for fitting), kView (for display/plotting)
* \return True if run was added and initialized successfully, false if initialization failed
*
* \see PRunBase::PrepareData() for data preprocessing details
*/
Bool_t PRunListCollection::Add(Int_t runNo, EPMusrHandleTag tag)
{
@@ -167,15 +223,32 @@ Bool_t PRunListCollection::Add(Int_t runNo, EPMusrHandleTag tag)
// SetFitRange (public)
//--------------------------------------------------------------------------
/**
* <p>Set the current fit range in bins. The string has the structure:
* 'fit_range fgb0+n00 lgb0-n01 [fgb1+n10 lgb-n11 fgb2+n20 lgb2-n21 .. fgbN+nN0 lgbN-nN1]'
* where fgb is the first good bin, lgb is the last good bin. nXY are offsets in bins.
* N is the number of runs in the msr-file.
* \brief Sets fit range in bin units using string specification (COMMANDS block syntax).
*
* <p>This means there are 2 options: (i) a globle fit range in bins for <em>all</em> runs in the
* msr-file, or (ii) each run block in the msr-file needs its individual range.
* Parses and applies fit range specified in bin offsets from t0 markers.
* This method supports the COMMANDS block FIT_RANGE syntax used for dynamic
* range adjustments during optimization.
*
* \param fitRange string holding the fit range(s).
* String format:
* - Single range: "fit_range fgb+n0 lgb-n1"
* - Multiple ranges: "fit_range fgb0+n00 lgb0-n01 fgb1+n10 lgb1-n11 ..."
*
* Where:
* - fgb = first good bin (t0 marker from MSR file)
* - lgb = last good bin (end marker, often from data_range or automatic)
* - nXY = offset in bins (can be positive or negative)
*
* Example:
* - "fit_range fgb+10 lgb-20" → Start 10 bins after t0, end 20 bins before last good bin
* - For multiple runs, each gets its own fgb/lgb pair in sequence
*
* This method broadcasts the range specification to all run objects in all lists.
* Each run's SetFitRangeBin() method interprets the string based on its position
* in the MSR file.
*
* \param fitRange String holding fit range specification in bin offsets
*
* \see SetFitRange(PDoublePairVector) for time-based range specification
*/
void PRunListCollection::SetFitRange(const TString fitRange)
{
@@ -199,11 +272,33 @@ void PRunListCollection::SetFitRange(const TString fitRange)
// SetFitRange (public)
//--------------------------------------------------------------------------
/**
* <p>Set the current fit range in time. If fitRange.size()==1 the given fit range will be used for all the runs,
* otherwise fitRange.size()==the number of runs in the msr-file, and for each run there will be an individual
* fit range.
* \brief Sets fit range in time units (microseconds from t0).
*
* \param fitRange vector holding the fit range(s).
* Applies time-based fit ranges to all runs in the collection. This is the
* standard method for specifying fit ranges in the MSR file FIT block or
* during interactive range adjustments.
*
* Range specification modes:
* - <b>Global range:</b> fitRange.size() == 1
* - Same (start, end) time pair applies to all runs
* - Example: {(0.1, 10.0)} → All runs fit from 0.1 μs to 10.0 μs after t0
*
* - <b>Individual ranges:</b> fitRange.size() == number of MSR file runs
* - Each run gets its own (start, end) time pair
* - fitRange[i] corresponds to MSR file RUN block i
* - Example: {(0.1, 10.0), (0.2, 8.0)} → Run 0: 0.1-10.0 μs, Run 1: 0.2-8.0 μs
*
* Processing steps for each run:
* 1. SetFitRange() updates internal start/end time members
* 2. CalcNoOfFitBins() recalculates bin indices (fStartTimeBin, fEndTimeBin)
*
* The bin recalculation is necessary because the fit range is initially specified
* in time but χ² calculation operates on bin indices.
*
* \param fitRange Vector of (start_time, end_time) pairs in microseconds (μs) from t0
*
* \see SetFitRange(TString) for bin-based range specification
* \see PRunBase::CalcNoOfFitBins() for time-to-bin conversion
*/
void PRunListCollection::SetFitRange(const PDoublePairVector fitRange)
{
@@ -239,12 +334,21 @@ void PRunListCollection::SetFitRange(const PDoublePairVector fitRange)
// GetSingleHistoChisq (public)
//--------------------------------------------------------------------------
/**
* <p>Calculates chi-square of <em>all</em> single histogram runs of a msr-file.
* \brief Calculates total χ² for all single histogram runs (global fit metric).
*
* <b>return:</b>
* - chi-square of all single histogram runs of the msr-file
* Sums the chi-squared statistic over all single histogram runs in the collection:
* \f[ \chi^2_{\rm total} = \sum_{i=1}^{N_{\rm runs}} \chi^2_i \f]
*
* \param par fit parameter vector
* where each run's χ² is:
* \f[ \chi^2_i = \sum_{j=1}^{N_{\rm bins,i}} \frac{(y_j^{\rm data} - y_j^{\rm theory})^2}{\sigma_j^2} \f]
*
* This is the objective function minimized by MINUIT during global fitting of
* multiple single histogram runs. Called repeatedly during each fit iteration.
*
* \param par Parameter vector from MINUIT with current parameter values
* \return Total χ² summed over all single histogram runs
*
* \see PRunSingleHisto::CalcChiSquare() for per-run χ² calculation
*/
Double_t PRunListCollection::GetSingleHistoChisq(const std::vector<Double_t>& par) const
{
@@ -281,12 +385,19 @@ Double_t PRunListCollection::GetSingleHistoRRFChisq(const std::vector<Double_t>&
// GetAsymmetryChisq (public)
//--------------------------------------------------------------------------
/**
* <p>Calculates chi-square of <em>all</em> asymmetry runs of a msr-file.
* \brief Calculates total χ² for all asymmetry runs (global fit metric).
*
* <b>return:</b>
* - chi-square of all asymmetry runs of the msr-file
* Sums the chi-squared statistic over all asymmetry runs in the collection.
* For asymmetry fits, χ² is calculated from the asymmetry values:
* \f[ A_i = \frac{F_i - \alpha B_i}{F_i + \alpha B_i} \f]
*
* \param par fit parameter vector
* with proper error propagation. This is the objective function for global
* asymmetry fits involving multiple runs (e.g., temperature or field scans).
*
* \param par Parameter vector from MINUIT with current parameter values
* \return Total χ² summed over all asymmetry runs
*
* \see PRunAsymmetry::CalcChiSquare() for per-run asymmetry χ² calculation
*/
Double_t PRunListCollection::GetAsymmetryChisq(const std::vector<Double_t>& par) const
{

View File

@@ -44,81 +44,747 @@
#include "PRunNonMusr.h"
/**
* <p>Handler class handling all processed data of an msr-file. All calls of minuit2 are going through this class.
* \brief Manager class for all processed μSR run data during fitting.
*
* PRunListCollection is the central orchestrator for musrfit, managing all processed
* run data and serving as the interface between the MINUIT minimizer and the various
* run types. It acts as a container and dispatcher for different fit types, routing
* χ² and maximum likelihood calculations to the appropriate run objects.
*
* \section architecture Architecture
*
* The collection maintains separate lists for each fit type:
* - <b>Single Histogram:</b> Basic time-differential μSR (one detector)
* - <b>Single Histogram RRF:</b> Single detector in rotating reference frame
* - <b>Asymmetry:</b> Forward-backward asymmetry fits
* - <b>Asymmetry RRF:</b> Asymmetry in rotating reference frame
* - <b>Asymmetry β-NMR:</b> Beta-detected NMR asymmetry
* - <b>Mu-Minus:</b> Negative muon fits (different lifetime)
* - <b>Non-μSR:</b> General time-series data fits
*
* \section responsibilities Core Responsibilities
*
* <b>Run management:</b>
* - Creating and storing PRunBase-derived objects for each run
* - Organizing runs by fit type for efficient access
* - Managing run lifetime and cleanup
*
* <b>MINUIT interface:</b>
* - Aggregating χ² from all runs of each type
* - Providing maximum likelihood calculations
* - Supporting both global fits (all runs) and single run evaluation
* - Calculating degrees of freedom (total bins fitted)
*
* <b>Fit range management:</b>
* - Dynamically updating fit ranges via COMMAND block
* - Supporting both time-based and bin-based range specifications
* - Applying ranges to appropriate run lists
*
* <b>Data access:</b>
* - Retrieving processed data for plotting
* - Accessing metadata (field, temperature, energy)
* - Supporting access by index or run number
*
* \section workflow Typical Workflow
*
* 1. <b>Construction:</b> Pass MSR handler and data handler
* 2. <b>Add runs:</b> Call Add() for each RUN block to create appropriate run objects
* 3. <b>Fitting:</b> MINUIT calls Get*Chisq() methods to evaluate fit quality
* 4. <b>Visualization:</b> Retrieve processed data via Get*() methods for plotting
*
* \section fit_types Fit Type Dispatching
*
* The collection routes operations based on fit type:
* - <b>fittype 0:</b> Single histogram → fRunSingleHistoList
* - <b>fittype 1:</b> Asymmetry → fRunAsymmetryList
* - <b>fittype 2:</b> Single histogram RRF → fRunSingleHistoRRFList
* - <b>fittype 3:</b> Asymmetry RRF → fRunAsymmetryRRFList
* - <b>fittype 4:</b> Mu-minus → fRunMuMinusList
* - <b>fittype 5:</b> β-NMR asymmetry → fRunAsymmetryBNMRList
* - <b>fittype 6:</b> Non-μSR → fRunNonMusrList
*
* \section global_fits Global Fitting
*
* For global fits (multiple runs sharing parameters):
* - Get*Chisq() methods sum χ² over all runs of that type
* - Each run is fitted with the same parameter set
* - Total χ² = Σ χ²_i across all runs
* - Degrees of freedom = Σ N_bins,i - N_parameters
*
* \section example_usage Example Usage
*
* \code
* // Create collection
* PRunListCollection collection(msrInfo, dataHandler);
*
* // Add all runs from MSR file
* for (UInt_t i = 0; i < msrInfo->GetMsrRunList()->size(); i++) {
* collection.Add(i, kFit);
* }
*
* // MINUIT minimization (called internally)
* Double_t chisq = collection.GetAsymmetryChisq(parameters);
*
* // Retrieve data for plotting
* PRunData *data = collection.GetAsymmetry(0);
* \endcode
*
* \section thread_safety Thread Safety
* NOT thread-safe. MINUIT evaluation must be serialized. For parallel fitting
* of independent datasets, create separate PRunListCollection instances.
*
* \see PRunBase for individual run processing
* \see PMsrHandler for MSR file configuration
* \see PRunDataHandler for raw data access
*/
class PRunListCollection
{
public:
/**
* \brief Constructor that initializes the collection.
*
* Creates an empty collection ready to receive runs via Add(). Does not
* automatically load runs - caller must explicitly add each run.
*
* \param msrInfo Pointer to MSR file handler (must remain valid for object lifetime)
* \param data Pointer to raw data handler (must remain valid for object lifetime)
* \param theoAsData If true, theory calculated only at data points; if false, extra points for visualization
*/
PRunListCollection(PMsrHandler *msrInfo, PRunDataHandler *data, Bool_t theoAsdata=false);
/**
* \brief Virtual destructor that cleans up all run objects.
*
* Calls CleanUp() and destructor for all run objects in all lists.
* Clears all run vectors. Does NOT delete fMsrInfo or fData (owned externally).
*/
virtual ~PRunListCollection();
/**
* \brief Enumeration for data access mode.
*
* Controls how runs are retrieved by Get*() methods:
* - <b>kIndex:</b> Retrieve by position in the list (0-based)
* - <b>kRunNo:</b> Retrieve by run number from MSR file
*/
enum EDataSwitch { kIndex, kRunNo };
/**
* \brief Adds a run to the appropriate list based on fit type.
*
* Creates a PRunBase-derived object matching the fit type specified in the
* MSR file RUN block, processes the data, and adds it to the corresponding
* internal list. This is the primary method for populating the collection.
*
* The method:
* 1. Determines fit type from MSR RUN block (fittype 0-6)
* 2. Creates appropriate PRunBase-derived object (PRunAsymmetry, etc.)
* 3. Object loads and processes data in its constructor
* 4. Adds object to correct list (fRunAsymmetryList, etc.)
*
* \param runNo Run number (0-based index into MSR file RUN blocks)
* \param tag Operation mode: kFit (fitting), kView (visualization only)
* \return True if run added successfully, false if creation/processing failed
*
* \note Invalid runs (failed data loading) are still added but marked invalid
*/
virtual Bool_t Add(Int_t runNo, EPMusrHandleTag tag);
/**
* \brief Sets fit range for all runs (time-based or bin-based).
*
* Updates the fitting window for all runs in the collection. Supports:
* - Single range applied to all runs
* - Individual ranges per run
*
* \param fitRange Vector of (start, end) pairs in microseconds
*
* If one pair: applies to all runs. If multiple: fitRange[i] applies to run i.
*/
virtual void SetFitRange(const PDoublePairVector fitRange);
/**
* \brief Sets fit range from string specification (bin-based).
*
* Parses and applies bin-based fit ranges from FIT_RANGE command.
* Format: "fgb[+offset] lgb[-offset]" for each run.
*
* \param fitRange String with fit range specification
*
* Example: "10+5 200-10" → bins [15, 190]
*/
virtual void SetFitRange(const TString fitRange);
//--- Chi-square calculation methods (for global fits) ---
/**
* \brief Calculates total χ² for all single histogram runs.
*
* Sums χ² over all runs in fRunSingleHistoList. Each run compares its
* measured data with theory at the given parameters.
*
* \param par Parameter vector from MINUIT
* \return Σ χ²_i for all single histogram runs
*/
virtual Double_t GetSingleHistoChisq(const std::vector<Double_t>& par) const;
/** \brief Calculates total χ² for all single histogram RRF runs.
* \param par Parameter vector from MINUIT
* \return Σ χ²_i for all RRF single histogram runs */
virtual Double_t GetSingleHistoRRFChisq(const std::vector<Double_t>& par) const;
/** \brief Calculates total χ² for all asymmetry runs.
* \param par Parameter vector from MINUIT
* \return Σ χ²_i for all asymmetry runs */
virtual Double_t GetAsymmetryChisq(const std::vector<Double_t>& par) const;
/** \brief Calculates total χ² for all asymmetry RRF runs.
* \param par Parameter vector from MINUIT
* \return Σ χ²_i for all RRF asymmetry runs */
virtual Double_t GetAsymmetryRRFChisq(const std::vector<Double_t>& par) const;
/** \brief Calculates total χ² for all β-NMR asymmetry runs.
* \param par Parameter vector from MINUIT
* \return Σ χ²_i for all β-NMR runs */
virtual Double_t GetAsymmetryBNMRChisq(const std::vector<Double_t>& par) const;
/** \brief Calculates total χ² for all mu-minus runs.
* \param par Parameter vector from MINUIT
* \return Σ χ²_i for all mu-minus runs */
virtual Double_t GetMuMinusChisq(const std::vector<Double_t>& par) const;
/** \brief Calculates total χ² for all non-μSR runs.
* \param par Parameter vector from MINUIT
* \return Σ χ²_i for all non-μSR runs */
virtual Double_t GetNonMusrChisq(const std::vector<Double_t>& par) const;
//--- Single run chi-square methods ---
/**
* \brief Calculates expected χ² for a single run by index.
*
* Returns expected χ² based on theory and error estimates for one run.
* Useful for evaluating fit quality and error bar estimation.
*
* \param par Parameter vector from MINUIT
* \param idx Run index (searches all lists sequentially)
* \return Expected χ² for the specified run
*/
virtual Double_t GetSingleRunChisqExpected(const std::vector<Double_t>& par, const UInt_t idx) const;
/**
* \brief Calculates χ² for a single run by index.
*
* Evaluates χ² for one specific run, searching across all fit type lists.
* Used for individual run analysis or diagnostics.
*
* \param par Parameter vector from MINUIT
* \param idx Run index (absolute index across all run lists)
* \return χ² for the specified run
*/
virtual Double_t GetSingleRunChisq(const std::vector<Double_t>& par, const UInt_t idx) const;
//! \name Maximum Likelihood Calculation Methods (Global Fits)
//@{
/**
* \brief Calculates total maximum likelihood for all single histogram runs.
*
* Computes the negative 2×log-likelihood summed over all single histogram runs:
* \f[ -2\ln L_{\rm total} = \sum_{i=1}^{N_{\rm runs}} (-2\ln L_i) \f]
*
* For each run, the maximum likelihood is calculated using Poisson statistics:
* \f[ -2\ln L = 2\sum_{j=1}^{N_{\rm bins}} \left[y_j^{\rm theory} - y_j^{\rm data} \ln(y_j^{\rm theory})\right] \f]
*
* Maximum likelihood fitting is preferred over χ² for low-count data (< 10-20 counts/bin)
* where Gaussian approximations break down. It naturally handles Poisson statistics
* without requiring error estimates.
*
* \param par Parameter vector from MINUIT
* \return Total -2×ln(L) summed over all single histogram runs
*
* \see CalcMaxLikelihood() in PRunBase for implementation details
*/
virtual Double_t GetSingleHistoMaximumLikelihood(const std::vector<Double_t>& par) const;
/**
* \brief Calculates total maximum likelihood for all single histogram RRF runs.
*
* Computes -2×ln(L) summed over all single histogram rotating reference frame runs.
* Uses the same Poisson likelihood formula as GetSingleHistoMaximumLikelihood(),
* but applied to RRF-transformed data.
*
* \param par Parameter vector from MINUIT
* \return Total -2×ln(L) summed over all single histogram RRF runs
*/
virtual Double_t GetSingleHistoRRFMaximumLikelihood(const std::vector<Double_t>& par) const;
/**
* \brief Calculates total maximum likelihood for all asymmetry runs.
*
* Computes -2×ln(L) summed over all asymmetry runs. For asymmetry data,
* the likelihood is applied to the reconstructed forward/backward histograms
* rather than directly to the asymmetry values.
*
* \param par Parameter vector from MINUIT
* \return Total -2×ln(L) summed over all asymmetry runs
*/
virtual Double_t GetAsymmetryMaximumLikelihood(const std::vector<Double_t>& par) const;
/**
* \brief Calculates total maximum likelihood for all asymmetry RRF runs.
*
* Computes -2×ln(L) summed over all asymmetry rotating reference frame runs.
* Combines RRF transformation with asymmetry analysis in likelihood calculation.
*
* \param par Parameter vector from MINUIT
* \return Total -2×ln(L) summed over all asymmetry RRF runs
*/
virtual Double_t GetAsymmetryRRFMaximumLikelihood(const std::vector<Double_t>& par) const;
/**
* \brief Calculates total maximum likelihood for all β-NMR asymmetry runs.
*
* Computes -2×ln(L) summed over all beta-detected NMR asymmetry runs.
* Handles helicity-dependent measurements with appropriate likelihood formula.
*
* \param par Parameter vector from MINUIT
* \return Total -2×ln(L) summed over all β-NMR asymmetry runs
*/
virtual Double_t GetAsymmetryBNMRMaximumLikelihood(const std::vector<Double_t>& par) const;
/**
* \brief Calculates total maximum likelihood for all μ⁻ runs.
*
* Computes -2×ln(L) summed over all negative muon runs. Negative muons have
* different decay characteristics than positive muons.
*
* \param par Parameter vector from MINUIT
* \return Total -2×ln(L) summed over all μ⁻ runs
*/
virtual Double_t GetMuMinusMaximumLikelihood(const std::vector<Double_t>& par) const;
/**
* \brief Calculates total maximum likelihood for all non-μSR runs.
*
* Computes -2×ln(L) summed over all general time-series (non-μSR) data runs.
* Uses the same Poisson likelihood framework applied to generic x-y data.
*
* \param par Parameter vector from MINUIT
* \return Total -2×ln(L) summed over all non-μSR runs
*/
virtual Double_t GetNonMusrMaximumLikelihood(const std::vector<Double_t>& par) const;
//@}
//! \name Single Run Maximum Likelihood Methods
//@{
/**
* \brief Calculates expected maximum likelihood for a single run (theoretical expectation).
*
* Computes the expected -2×ln(L) value based on the theory predictions and error
* estimates for a specific run. Useful for statistical diagnostics and validating
* error bars. For properly estimated errors and valid model, expected likelihood
* should be comparable to actual likelihood.
*
* \param par Parameter vector from MINUIT
* \param idx Run index (absolute index across all run lists)
* \return Expected -2×ln(L) for the specified run
*
* \note Not all run types implement this method; some may return 0.0
*/
virtual Double_t GetSingleRunMaximumLikelihoodExpected(const std::vector<Double_t>& par, const UInt_t idx) const;
/**
* \brief Calculates maximum likelihood for a single run.
*
* Computes -2×ln(L) for a specific run identified by absolute index.
* This is useful for identifying problematic runs in a global fit or
* for analyzing individual run contributions to the total likelihood.
*
* \param par Parameter vector from MINUIT
* \param idx Run index (absolute index across all run lists)
* \return -2×ln(L) for the specified run
*/
virtual Double_t GetSingleRunMaximumLikelihood(const std::vector<Double_t>& par, const UInt_t idx) const;
//@}
//! \name Fit Statistics Methods
//@{
/**
* \brief Returns the number of bins fitted for a specific run.
*
* Queries a single run to determine how many data bins fall within its
* fit range. This depends on:
* - The fit time range (start/end times from FIT block)
* - Time resolution and bin packing settings
* - Valid data range after background subtraction
*
* Used for calculating degrees of freedom: ν = N_bins_total - N_params
*
* \param idx Run index (absolute index across all run lists)
* \return Number of bins included in the fit for this run
*
* \see GetTotalNoOfBinsFitted() for total across all runs
*/
virtual UInt_t GetNoOfBinsFitted(const UInt_t idx) const;
/**
* \brief Returns total number of bins fitted across all runs.
*
* Sums the number of fitted bins over all runs in the collection:
* \f[ N_{\rm bins,total} = \sum_{i=1}^{N_{\rm runs}} N_{\rm bins,i} \f]
*
* This is the numerator for calculating reduced chi-squared:
* \f[ \chi^2_{\rm red} = \frac{\chi^2}{N_{\rm bins,total} - N_{\rm params}} \f]
*
* For a good fit: χ²_red ≈ 1.0
*
* \return Total number of bins across all runs within fit ranges
*
* \see GetNoOfBinsFitted() for single run bin count
*/
virtual UInt_t GetTotalNoOfBinsFitted() const;
//@}
virtual UInt_t GetNoOfSingleHisto() const { return fRunSingleHistoList.size(); } ///< returns the number of single histogram data sets present in the msr-file
virtual UInt_t GetNoOfSingleHistoRRF() const { return fRunSingleHistoRRFList.size(); } ///< returns the number of single histogram RRF data sets present in the msr-file
virtual UInt_t GetNoOfAsymmetry() const { return fRunAsymmetryList.size(); } ///< returns the number of asymmetry data sets present in the msr-file
virtual UInt_t GetNoOfAsymmetryRRF() const { return fRunAsymmetryRRFList.size(); } ///< returns the number of asymmetry RRF data sets present in the msr-file
virtual UInt_t GetNoOfAsymmetryBNMR() const { return fRunAsymmetryBNMRList.size(); } ///< returns the number of asymmetry BNMR data sets present in the msr-file
virtual UInt_t GetNoOfMuMinus() const { return fRunMuMinusList.size(); } ///< returns the number of mu minus data sets present in the msr-file
virtual UInt_t GetNoOfNonMusr() const { return fRunNonMusrList.size(); } ///< returns the number of non-muSR data sets present in the msr-file
//! \name Run Count Accessors
//@{
/**
* \brief Returns the number of single histogram runs in the collection.
* \return Count of single histogram data sets from MSR file
*/
virtual UInt_t GetNoOfSingleHisto() const { return fRunSingleHistoList.size(); }
/**
* \brief Returns the number of single histogram RRF runs in the collection.
* \return Count of single histogram rotating reference frame data sets from MSR file
*/
virtual UInt_t GetNoOfSingleHistoRRF() const { return fRunSingleHistoRRFList.size(); }
/**
* \brief Returns the number of asymmetry runs in the collection.
* \return Count of asymmetry data sets from MSR file
*/
virtual UInt_t GetNoOfAsymmetry() const { return fRunAsymmetryList.size(); }
/**
* \brief Returns the number of asymmetry RRF runs in the collection.
* \return Count of asymmetry rotating reference frame data sets from MSR file
*/
virtual UInt_t GetNoOfAsymmetryRRF() const { return fRunAsymmetryRRFList.size(); }
/**
* \brief Returns the number of β-NMR asymmetry runs in the collection.
* \return Count of beta-detected NMR asymmetry data sets from MSR file
*/
virtual UInt_t GetNoOfAsymmetryBNMR() const { return fRunAsymmetryBNMRList.size(); }
/**
* \brief Returns the number of μ⁻ runs in the collection.
* \return Count of negative muon data sets from MSR file
*/
virtual UInt_t GetNoOfMuMinus() const { return fRunMuMinusList.size(); }
/**
* \brief Returns the number of non-μSR runs in the collection.
* \return Count of general time-series (non-μSR) data sets from MSR file
*/
virtual UInt_t GetNoOfNonMusr() const { return fRunNonMusrList.size(); }
//@}
//! \name Processed Data Accessors
//@{
/**
* \brief Retrieves processed data for a single histogram run.
*
* Provides access to the PRunData object containing background-corrected,
* packed histogram data with theory values and error bars.
*
* \param index Run identifier (interpretation depends on tag parameter)
* \param tag Access mode:
* - kIndex (default): Direct index into single histogram list (0-based)
* - kRunNumber: MSR file run number
* \return Pointer to PRunData object, or nullptr if index is invalid
*
* \see PRunData for data structure contents
*/
virtual PRunData* GetSingleHisto(UInt_t index, EDataSwitch tag=kIndex);
virtual PRunData* GetSingleHistoRRF(UInt_t index, EDataSwitch tag=kIndex);
virtual PRunData* GetAsymmetry(UInt_t index, EDataSwitch tag=kIndex);
virtual PRunData* GetAsymmetryRRF(UInt_t index, EDataSwitch tag=kIndex);
virtual PRunData* GetAsymmetryBNMR(UInt_t index, EDataSwitch tag=kIndex);
virtual PRunData* GetMuMinus(UInt_t index, EDataSwitch tag=kIndex);
virtual PRunData* GetNonMusr(UInt_t index, EDataSwitch tag=kIndex);
/**
* \brief Retrieves processed data for a single histogram RRF run.
*
* Provides access to RRF-transformed single histogram data including
* filtered theory curves and RRF-specific metadata.
*
* \param index Run identifier (interpretation depends on tag parameter)
* \param tag Access mode:
* - kIndex (default): Direct index into single histogram RRF list
* - kRunNumber: MSR file run number
* \return Pointer to PRunData object, or nullptr if index is invalid
*/
virtual PRunData* GetSingleHistoRRF(UInt_t index, EDataSwitch tag=kIndex);
/**
* \brief Retrieves processed data for an asymmetry run.
*
* Provides access to calculated asymmetry data with proper error propagation,
* including α-corrected forward/backward combinations.
*
* \param index Run identifier (interpretation depends on tag parameter)
* \param tag Access mode:
* - kIndex (default): Direct index into asymmetry list
* - kRunNumber: MSR file run number
* \return Pointer to PRunData object, or nullptr if index is invalid
*/
virtual PRunData* GetAsymmetry(UInt_t index, EDataSwitch tag=kIndex);
/**
* \brief Retrieves processed data for an asymmetry RRF run.
*
* Provides access to RRF-transformed asymmetry data combining asymmetry
* calculation with rotating reference frame analysis.
*
* \param index Run identifier (interpretation depends on tag parameter)
* \param tag Access mode:
* - kIndex (default): Direct index into asymmetry RRF list
* - kRunNumber: MSR file run number
* \return Pointer to PRunData object, or nullptr if index is invalid
*/
virtual PRunData* GetAsymmetryRRF(UInt_t index, EDataSwitch tag=kIndex);
/**
* \brief Retrieves processed data for a β-NMR asymmetry run.
*
* Provides access to beta-detected NMR asymmetry data with helicity-dependent
* analysis and appropriate error handling.
*
* \param index Run identifier (interpretation depends on tag parameter)
* \param tag Access mode:
* - kIndex (default): Direct index into β-NMR asymmetry list
* - kRunNumber: MSR file run number
* \return Pointer to PRunData object, or nullptr if index is invalid
*/
virtual PRunData* GetAsymmetryBNMR(UInt_t index, EDataSwitch tag=kIndex);
/**
* \brief Retrieves processed data for a μ⁻ run.
*
* Provides access to negative muon data accounting for different decay
* properties compared to positive muons.
*
* \param index Run identifier (interpretation depends on tag parameter)
* \param tag Access mode:
* - kIndex (default): Direct index into μ⁻ list
* - kRunNumber: MSR file run number
* \return Pointer to PRunData object, or nullptr if index is invalid
*/
virtual PRunData* GetMuMinus(UInt_t index, EDataSwitch tag=kIndex);
/**
* \brief Retrieves processed data for a non-μSR run.
*
* Provides access to general time-series data (x-y pairs) processed through
* the same framework as μSR data but without μSR-specific assumptions.
*
* \param index Run identifier (interpretation depends on tag parameter)
* \param tag Access mode:
* - kIndex (default): Direct index into non-μSR list
* - kRunNumber: MSR file run number
* \return Pointer to PRunData object, or nullptr if index is invalid
*/
virtual PRunData* GetNonMusr(UInt_t index, EDataSwitch tag=kIndex);
//@}
//! \name Experimental Metadata Accessors
//@{
/**
* \brief Retrieves temperature information for a specific run.
*
* Returns temperature data extracted from the raw data file header.
* Temperature may be recorded as a time-series (multiple values) or
* a single value depending on the data acquisition system.
*
* \param runName Run identifier string (e.g., "2425" or "/path/to/run2425.root")
* \return Pointer to vector of (time, temperature) pairs, or nullptr if not available
*
* \note Temperature units depend on the data file format (typically Kelvin or Celsius)
*/
virtual const PDoublePairVector *GetTemp(const TString &runName) const;
/**
* \brief Retrieves magnetic field value for a specific run.
*
* Returns the applied magnetic field extracted from the raw data file header.
* This is typically the field measured at the sample position.
*
* \param runName Run identifier string (e.g., "2425" or "/path/to/run2425.root")
* \return Magnetic field value in Gauss, or PMUSR_UNDEFINED if not available
*
* \note Field values may be recorded in various units (G, T, Oe) depending on facility
*/
virtual Double_t GetField(const TString &runName) const;
/**
* \brief Retrieves beam energy for a specific run.
*
* Returns the muon beam implantation energy extracted from the raw data file header.
* Energy determines the stopping profile (implantation depth) in the sample.
*
* \param runName Run identifier string (e.g., "2425" or "/path/to/run2425.root")
* \return Beam energy in keV, or PMUSR_UNDEFINED if not available
*
* \note Low-energy muons (LE-μSR) typically: 1-30 keV; surface muons: ~4 MeV
*/
virtual Double_t GetEnergy(const TString &runName) const;
/**
* \brief Retrieves experimental setup identifier for a specific run.
*
* Returns the beamline or spectrometer name extracted from the raw data file header.
* This identifies the experimental station where data was collected.
*
* \param runName Run identifier string (e.g., "2425" or "/path/to/run2425.root")
* \return Setup name string (e.g., "GPS", "LTF", "DOLLY"), or nullptr if not available
*
* \note Setup names are facility-specific (PSI: GPS, LTF, HAL-9500; ISIS: EMU, ARGUS, etc.)
*/
virtual const Char_t* GetSetup(const TString &runName) const;
/**
* \brief Retrieves x-axis label for plotting.
*
* Returns the appropriate x-axis title based on fit type and run settings.
* Typically "Time (μs)" for time-domain fits, "Frequency (MHz)" for Fourier transforms,
* or custom labels for non-μSR data.
*
* \param runName Run identifier string (e.g., "2425" or "/path/to/run2425.root")
* \param idx Run index within the specified fit type
* \return X-axis title string, or nullptr if not available
*
* \see PRunData for plot axis information storage
*/
virtual const Char_t* GetXAxisTitle(const TString &runName, const UInt_t idx) const;
/**
* \brief Retrieves y-axis label for plotting.
*
* Returns the appropriate y-axis title based on fit type:
* - Single histogram: "Counts" or "Positron Rate (MHz)"
* - Asymmetry: "Asymmetry" or "Asymmetry (%)"
* - Custom labels for non-μSR data
*
* \param runName Run identifier string (e.g., "2425" or "/path/to/run2425.root")
* \param idx Run index within the specified fit type
* \return Y-axis title string, or nullptr if not available
*
* \see PRunData for plot axis information storage
*/
virtual const Char_t* GetYAxisTitle(const TString &runName, const UInt_t idx) const;
//@}
private:
Bool_t fTheoAsData; ///< if true: calculate theory points only at the data points
PMsrHandler *fMsrInfo; ///< pointer to the msr-file handler
PRunDataHandler *fData; ///< pointer to the run-data handler
/**
* \brief Theory calculation mode flag.
*
* Controls whether theory is calculated at:
* - true: Only at data point times (efficient for fitting, exact data-theory comparison)
* - false: On a high-resolution grid (smooth curves for visualization)
*
* Set from MSR PLOT block. For fitting, always uses fTheoAsData=true internally
* regardless of this setting. This flag primarily affects plotting and export.
*/
Bool_t fTheoAsData;
std::vector<PRunSingleHisto*> fRunSingleHistoList; ///< stores all processed single histogram data
std::vector<PRunSingleHistoRRF*> fRunSingleHistoRRFList; ///< stores all processed single histogram RRF data
std::vector<PRunAsymmetry*> fRunAsymmetryList; ///< stores all processed asymmetry data
std::vector<PRunAsymmetryRRF*> fRunAsymmetryRRFList; ///< stores all processed asymmetry RRF data
std::vector<PRunAsymmetryBNMR*> fRunAsymmetryBNMRList; ///< stores all processed asymmetry BNMR data
std::vector<PRunMuMinus*> fRunMuMinusList; ///< stores all processed mu-minus data
std::vector<PRunNonMusr*> fRunNonMusrList; ///< stores all processed non-muSR data
/**
* \brief Pointer to MSR file handler (not owned).
*
* Provides access to all MSR file content including PARAMETER, THEORY, FUNCTIONS,
* RUN, COMMANDS, FOURIER, and PLOT blocks. Must remain valid for the lifetime
* of this PRunListCollection object.
*
* \warning This pointer is NOT owned by PRunListCollection and will not be deleted.
*/
PMsrHandler *fMsrInfo;
/**
* \brief Pointer to raw data handler (not owned).
*
* Provides access to raw histogram data files via unified interface supporting
* multiple formats (ROOT, NeXus, MUD, PSI-BIN, etc.). Used during Add() calls
* to load data for each run.
*
* \warning This pointer is NOT owned by PRunListCollection and will not be deleted.
*/
PRunDataHandler *fData;
/**
* \brief Collection of single histogram run objects.
*
* Each element is a PRunSingleHisto object containing processed data for one
* single-detector histogram fit. Objects are heap-allocated and owned by this
* vector; deleted in destructor.
*
* \see PRunSingleHisto for single histogram fit implementation
*/
std::vector<PRunSingleHisto*> fRunSingleHistoList;
/**
* \brief Collection of single histogram RRF run objects.
*
* Each element is a PRunSingleHistoRRF object containing RRF-transformed
* single histogram data with Kaiser filtering. Objects are owned by this vector.
*
* \see PRunSingleHistoRRF for RRF single histogram implementation
*/
std::vector<PRunSingleHistoRRF*> fRunSingleHistoRRFList;
/**
* \brief Collection of asymmetry run objects.
*
* Each element is a PRunAsymmetry object containing calculated asymmetry data
* from forward/backward detector pairs. Objects are owned by this vector.
*
* \see PRunAsymmetry for asymmetry fit implementation
*/
std::vector<PRunAsymmetry*> fRunAsymmetryList;
/**
* \brief Collection of asymmetry RRF run objects.
*
* Each element is a PRunAsymmetryRRF object combining asymmetry calculation
* with RRF transformation for high-frequency analysis. Objects are owned by this vector.
*
* \see PRunAsymmetryRRF for RRF asymmetry implementation
*/
std::vector<PRunAsymmetryRRF*> fRunAsymmetryRRFList;
/**
* \brief Collection of β-NMR asymmetry run objects.
*
* Each element is a PRunAsymmetryBNMR object for beta-detected NMR measurements
* with helicity-dependent analysis. Objects are owned by this vector.
*
* \see PRunAsymmetryBNMR for β-NMR asymmetry implementation
*/
std::vector<PRunAsymmetryBNMR*> fRunAsymmetryBNMRList;
/**
* \brief Collection of μ⁻ (negative muon) run objects.
*
* Each element is a PRunMuMinus object for negative muon measurements with
* different decay characteristics than μ⁺. Objects are owned by this vector.
*
* \see PRunMuMinus for negative muon fit implementation
*/
std::vector<PRunMuMinus*> fRunMuMinusList;
/**
* \brief Collection of non-μSR run objects.
*
* Each element is a PRunNonMusr object for general time-series (x-y) data fits
* using the musrfit framework without μSR-specific assumptions. Objects are owned.
*
* \see PRunNonMusr for generic time-series fit implementation
*/
std::vector<PRunNonMusr*> fRunNonMusrList;
};
#endif // _PRUNLISTCOLLECTION_H_