improve the doxygen docu of PTheory.*

This commit is contained in:
2025-11-23 17:47:46 +01:00
parent e940ad09b4
commit d8ae606a55
2 changed files with 500 additions and 139 deletions

View File

@@ -53,16 +53,18 @@ extern std::vector<void*> gGlobalUserFcn;
// Constructor
//--------------------------------------------------------------------------
/**
* <p> Constructor.
* \brief Parses the THEORY block and builds a binary expression tree.
*
* <p> The theory block his parsed and mapped to a tree. Every line (except the '+')
* is a theory object by itself, i.e. the whole theory is build up recursivly.
* Example:
* The constructor recursively parses the theory block from the MSR file and
* builds a binary tree structure. Each theory function becomes a node, with
* multiplication creating right children and addition creating left children.
*
* <b>Example Theory Block:</b>
* \verbatim
Theory block:
a 1
tf 2 3
se 4
THEORY
a 1 # asymmetry
tf 2 3 # TFieldCos (phase, frequency)
se 4 # simpleExp (rate)
+
a 5
tf 6 7
@@ -72,7 +74,7 @@ extern std::vector<void*> gGlobalUserFcn;
tf 10 11
\endverbatim
*
* <p> This is mapped into the following binary tree:
* <b>Resulting Binary Tree:</b>
* \verbatim
a 1
+/ \*
@@ -85,11 +87,40 @@ extern std::vector<void*> gGlobalUserFcn;
se 8
\endverbatim
*
* \param msrInfo msr-file handler
* \param runNo msr-file run number
* \param hasParent flag needed in order to know if PTheory is the root object or a child
* false (default) means this is the root object
* true means this is part of an already existing object tree
* The tree is evaluated as: (a1 * tf23 * se4) + (a5 * tf67 * se8) + (a9 * tf1011)
*
* <b>Parsing Algorithm:</b>
* -# Initialize member variables and static counters (lineNo, depth)
* -# Get current line from theory block (skip if beyond end)
* -# Remove comments: text after '(' or '#'
* -# Tokenize line into function name and parameters
* -# Search fgTheoDataBase for function (by name or abbreviation)
* -# Validate parameter count (except for polynom and userFcn)
* -# For each parameter token:
* - If "mapN": resolve via RUN block map vector
* - If "funN": get function index + MSR_PARAM_FUN_OFFSET
* - Otherwise: direct parameter number (1-based → 0-based)
* -# If next line is not '+': increment depth, create fMul child recursively
* -# If depth=0 and next line is '+': skip '+', create fAdd child recursively
* -# For root node: call MakeCleanAndTidyTheoryBlock() to format output
* -# For userFcn: load shared library and instantiate class object
*
* <b>User Function Handling:</b>
* User functions require special parsing:
* - Token 1: shared library name (e.g., "libMyFunc.so")
* - Token 2: class name (e.g., "TMyFunction")
* - Token 3+: parameters
* The library is loaded via gSystem->Load() and the class instantiated via
* TClass::GetClass()->New().
*
* \param msrInfo Pointer to MSR file handler (NOT owned, must outlive PTheory)
* \param runNo Zero-based run number for map parameter resolution
* \param hasParent false (default) for root theory node, true for child nodes.
* Controls reset of static line/depth counters.
*
* \warning Sets fValid=false on errors. Always check IsValid() after construction.
*
* \see fgTheoDataBase, SearchDataBase(), IsValid()
*/
PTheory::PTheory(PMsrHandler *msrInfo, UInt_t runNo, const Bool_t hasParent) : fMsrInfo(msrInfo)
{
@@ -328,7 +359,18 @@ PTheory::PTheory(PMsrHandler *msrInfo, UInt_t runNo, const Bool_t hasParent) : f
// Destructor
//--------------------------------------------------------------------------
/**
* <p>Destructor
* \brief Destructor that recursively cleans up the expression tree.
*
* Releases all resources allocated by this theory node and its children:
* -# Clears parameter number vector (fParamNo)
* -# Clears user function parameter cache (fUserParam)
* -# Clears LF integral caches (fLFIntegral, fDynLFFuncValue)
* -# Recursively deletes child nodes via CleanUp()
* -# Deletes user function object if present
* -# Clears global user function vector
*
* \note Child nodes (fAdd, fMul) are deleted via CleanUp() which traverses
* the entire tree recursively.
*/
PTheory::~PTheory()
{
@@ -353,11 +395,22 @@ PTheory::~PTheory()
// IsValid
//--------------------------------------------------------------------------
/**
* <p>Checks if the theory tree is valid.
* \brief Recursively checks if the entire theory expression tree is valid.
*
* <b>return:</b>
* - true if valid
* - false otherwise
* Traverses the binary tree and checks fValid for this node and all
* descendant nodes. A theory tree is valid only if ALL nodes are valid.
*
* <b>Validation logic:</b>
* - If fMul and fAdd both exist: return fValid && fMul->IsValid() && fAdd->IsValid()
* - If only fMul exists: return fValid && fMul->IsValid()
* - If only fAdd exists: return fValid && fAdd->IsValid()
* - If leaf node: return fValid
*
* \return true if this node and all descendants are valid, false otherwise
*
* \note Should always be called after construction to verify successful parsing.
* A single invalid node anywhere in the tree causes the entire theory
* to be marked invalid.
*/
Bool_t PTheory::IsValid()
{
@@ -379,14 +432,38 @@ Bool_t PTheory::IsValid()
//--------------------------------------------------------------------------
/**
* <p>Evaluates the theory tree.
* \brief Evaluates the theory expression tree at a given time point.
*
* <b>return:</b>
* - theory value for the given sets of parameters
* Recursively evaluates the binary tree, combining function values according
* to the tree structure (multiplication for consecutive lines, addition for
* '+' separated sections).
*
* \param t time for single histogram, asymmetry, and mu-minus fits, x-axis value non-muSR fits
* \param paramValues vector with the parameters
* \param funcValues vector with the functions (i.e. functions of the parameters)
* <b>Evaluation Algorithm:</b>
* Based on tree structure, one of four cases applies:
* -# fMul && fAdd: this_func(t) * fMul->Func(t) + fAdd->Func(t)
* -# fMul only: this_func(t) * fMul->Func(t)
* -# fAdd only: this_func(t) + fAdd->Func(t)
* -# Leaf node: this_func(t)
*
* <b>Parameter Resolution:</b>
* Within each function, parameters are accessed via fParamNo indices:
* - If fParamNo[i] < MSR_PARAM_FUN_OFFSET: use paramValues[fParamNo[i]]
* - If fParamNo[i] >= MSR_PARAM_FUN_OFFSET: use funcValues[fParamNo[i] - MSR_PARAM_FUN_OFFSET]
*
* <b>LF Caching:</b>
* Longitudinal field functions (StaticGaussKTLF, DynamicLorentzKTLF, etc.)
* use cached integral values that are recalculated only when parameters change.
* This is handled transparently within each LF function.
*
* \param t Time in microseconds for μSR fits, or x-axis value for non-μSR data
* \param paramValues Vector of current fit parameter values from FITPARAMETER block
* \param funcValues Vector of evaluated function values from FUNCTIONS block
*
* \return Evaluated polarization/asymmetry value at time t
*
* \note This method is const but uses mutable members for LF caching.
*
* \see Constant(), TFCos(), StaticGaussKT(), etc. for individual function implementations
*/
Double_t PTheory::Func(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
{
@@ -765,13 +842,22 @@ void PTheory::CleanUp(PTheory *theo)
//--------------------------------------------------------------------------
/**
* <p>Searches the internal look up table for the theory name, and if found
* set some internal variables to proper values.
* \brief Searches fgTheoDataBase for a theory function by name or abbreviation.
*
* <b>return:</b>
* - index of the theory function
* Performs case-insensitive search through the theory database to find a
* matching function. If found, sets fType and fNoOfParam member variables.
*
* \param name theory name
* <b>Search matches either:</b>
* - Full function name (e.g., "simplExpo", "TFieldCos")
* - Abbreviation (e.g., "se", "tf")
*
* \param name Function name or abbreviation to search for
*
* \return Index in fgTheoDataBase (0 to THEORY_MAX-1), or THEORY_UNDEFINED (-1) if not found
*
* \note Side effects: Sets fType and fNoOfParam when function is found.
*
* \see fgTheoDataBase
*/
Int_t PTheory::SearchDataBase(TString name)
{
@@ -793,11 +879,19 @@ Int_t PTheory::SearchDataBase(TString name)
// GetUserFcnIdx (private)
//--------------------------------------------------------------------------
/**
* <p>Counts the number of user functions in the theory block up to lineNo.
* \brief Counts user function occurrences in theory block up to a given line.
*
* <b>return:</b> to number of user functions found up to lineNo
* Scans the theory block from line 1 to lineNo (inclusive) and counts
* how many lines contain "userFcn". This index is used to:
* - Identify which global user function object to use
* - Track multiple user functions in a single theory
*
* \param lineNo current line number in the theory block
* \param lineNo Current line number being parsed (1-based in theory block)
*
* \return Index of current user function (0-based count), or -1 if no userFcn
* entries found up to lineNo
*
* \note The search is case-insensitive ("userFcn", "USERFCN", etc. all match).
*/
Int_t PTheory::GetUserFcnIdx(UInt_t lineNo) const
{
@@ -823,10 +917,28 @@ Int_t PTheory::GetUserFcnIdx(UInt_t lineNo) const
// MakeCleanAndTidyTheoryBlock private
//--------------------------------------------------------------------------
/**
* <p>Takes the theory block form the msr-file, and makes a nicely formated
* theory block.
* \brief Reformats the theory block with consistent spacing and comments.
*
* \param fullTheoryBlock msr-file text lines of the theory block
* Processes each line in the theory block to produce clean, well-formatted
* output suitable for writing back to MSR files. Formatting includes:
* - Function name left-aligned in 10-character field
* - Parameters right-aligned in 6-character fields
* - Comment string appended showing parameter names
*
* <b>Example transformation:</b>
* \verbatim
* Input: "tf 2 3"
* Output: "TFieldCos 2 3 (phase frequency)"
* \endverbatim
*
* Special handling for:
* - '+' lines: left unchanged
* - polynom: delegated to MakeCleanAndTidyPolynom()
* - userFcn: delegated to MakeCleanAndTidyUserFcn()
*
* \param fullTheoryBlock Pointer to theory block lines (modified in place)
*
* \note Called only by root theory node (hasParent=false) after successful parsing.
*/
void PTheory::MakeCleanAndTidyTheoryBlock(PMsrLines *fullTheoryBlock)
{
@@ -914,10 +1026,16 @@ void PTheory::MakeCleanAndTidyTheoryBlock(PMsrLines *fullTheoryBlock)
// MakeCleanAndTidyPolynom private
//--------------------------------------------------------------------------
/**
* <p>Prettifies a polynom theory line.
* \brief Formats a polynomial theory line with proper spacing.
*
* \param i line index of the theory polynom line to be prettified
* \param fullTheoryBlock msr-file text lines of the theory block
* Polynomial functions have variable parameter count, so they require
* special formatting. Creates output in format:
* \verbatim
* polynom tshift p0 p1 p2 ... pn (tshift p0 p1 ... pn)
* \endverbatim
*
* \param i Line index (1-based) in the theory block
* \param fullTheoryBlock Pointer to theory block lines (modified in place)
*/
void PTheory::MakeCleanAndTidyPolynom(UInt_t i, PMsrLines *fullTheoryBlock)
{
@@ -971,10 +1089,16 @@ void PTheory::MakeCleanAndTidyPolynom(UInt_t i, PMsrLines *fullTheoryBlock)
// MakeCleanAndTidyUserFcn private
//--------------------------------------------------------------------------
/**
* <p>Prettifies a user function theory line.
* \brief Formats a user function theory line with proper spacing.
*
* \param i line index of the user function line to be prettified
* \param fullTheoryBlock msr-file text lines of the theory block
* User functions have variable structure (library, class, parameters),
* so they require special formatting. Creates output in format:
* \verbatim
* userFcn libName.so ClassName param1 param2 ... paramN
* \endverbatim
*
* \param i Line index (1-based) in the theory block
* \param fullTheoryBlock Pointer to theory block lines (modified in place)
*/
void PTheory::MakeCleanAndTidyUserFcn(UInt_t i, PMsrLines *fullTheoryBlock)
{
@@ -1010,15 +1134,20 @@ void PTheory::MakeCleanAndTidyUserFcn(UInt_t i, PMsrLines *fullTheoryBlock)
//--------------------------------------------------------------------------
/**
* <p> theory function: Const
* \f[ = const \f]
* \brief Returns a constant value (baseline, background).
*
* <b>meaning of paramValues:</b> const
* Mathematical form:
* \f[ P(t) = c \f]
*
* <b>return:</b> function value
* Used for constant offsets, fixed backgrounds, or baseline corrections.
*
* \param paramValues vector with the parameters
* \param funcValues vector with the functions (i.e. functions of the parameters)
* <b>Parameters:</b>
* - fParamNo[0]: Constant value c
*
* \param paramValues Vector of fit parameter values
* \param funcValues Vector of evaluated function values
*
* \return Constant value c
*/
Double_t PTheory::Constant(const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
{
@@ -1038,15 +1167,22 @@ Double_t PTheory::Constant(const PDoubleVector& paramValues, const PDoubleVector
//--------------------------------------------------------------------------
/**
* <p> theory function: Asymmetry
* \f[ = A \f]
* \brief Returns the initial asymmetry value.
*
* <b>meaning of paramValues:</b> \f$A\f$
* Mathematical form:
* \f[ P(t) = A \f]
*
* <b>return:</b> function value
* The asymmetry represents the initial polarization of the muon beam and is
* typically used as a multiplicative prefactor for oscillating/relaxing functions.
* Typical values range from 0.15 to 0.30 depending on detector geometry.
*
* \param paramValues vector with the parameters
* \param funcValues vector with the functions (i.e. functions of the parameters)
* <b>Parameters:</b>
* - fParamNo[0]: Asymmetry value A
*
* \param paramValues Vector of fit parameter values
* \param funcValues Vector of evaluated function values
*
* \return Asymmetry value A
*/
Double_t PTheory::Asymmetry(const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
{
@@ -1066,17 +1202,25 @@ Double_t PTheory::Asymmetry(const PDoubleVector& paramValues, const PDoubleVecto
//--------------------------------------------------------------------------
/**
* <p> theory function: simple exponential
* \f[ = \exp\left(-\lambda t\right) \f] or
* \f[ = \exp\left(-\lambda [t-t_{\rm shift}] \right) \f]
* \brief Simple exponential relaxation function.
*
* <b>meaning of paramValues:</b> \f$\lambda\f$ [, \f$t_{\rm shift}\f$]
* Mathematical form:
* \f[ P(t) = \exp\left(-\lambda t\right) \f]
* or with time shift:
* \f[ P(t) = \exp\left(-\lambda [t-t_{\rm shift}] \right) \f]
*
* <b>return:</b> function value
* Represents exponential muon spin relaxation due to dynamic fluctuations
* in the fast-fluctuation limit (BPP-type relaxation).
*
* \param t time in \f$(\mu\mathrm{s})\f$, or x-axis value for non-muSR fit
* \param paramValues parameter values
* \param funcValues vector with the functions (i.e. functions of the parameters)
* <b>Parameters:</b>
* - fParamNo[0]: Relaxation rate λ (μs⁻¹)
* - fParamNo[1]: (optional) Time shift t_shift (μs)
*
* \param t Time in μs
* \param paramValues Vector of fit parameter values
* \param funcValues Vector of evaluated function values
*
* \return Exponential relaxation value at time t
*/
Double_t PTheory::SimpleExp(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
{
@@ -1106,17 +1250,29 @@ Double_t PTheory::SimpleExp(Double_t t, const PDoubleVector& paramValues, const
//--------------------------------------------------------------------------
/**
* <p> theory function: generalized exponential
* \f[ = \exp\left(-[\lambda t]^\beta\right) \f] or
* \f[ = \exp\left(-[\lambda (t-t_{\rm shift})]^\beta\right) \f]
* \brief Generalized (stretched) exponential relaxation function.
*
* <b>meaning of paramValues:</b> \f$\lambda\f$, \f$\beta\f$ [, \f$t_{\rm shift}\f$]
* Mathematical form:
* \f[ P(t) = \exp\left(-[\lambda t]^\beta\right) \f]
* or with time shift:
* \f[ P(t) = \exp\left(-[\lambda (t-t_{\rm shift})]^\beta\right) \f]
*
* <b>return:</b> function value
* The stretched exponential (Kohlrausch function) represents relaxation
* in systems with a distribution of correlation times:
* - β = 1: Simple exponential
* - β < 1: Stretched exponential (distributed relaxation)
* - β = 2: Gaussian relaxation
*
* \param t time in \f$(\mu\mathrm{s})\f$, or x-axis value for non-muSR fit
* \param paramValues parameter values
* \param funcValues vector with the functions (i.e. functions of the parameters)
* <b>Parameters:</b>
* - fParamNo[0]: Relaxation rate λ (μs⁻¹)
* - fParamNo[1]: Stretching exponent β
* - fParamNo[2]: (optional) Time shift t_shift (μs)
*
* \param t Time in μs
* \param paramValues Vector of fit parameter values
* \param funcValues Vector of evaluated function values
*
* \return Stretched exponential value at time t
*/
Double_t PTheory::GeneralExp(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
{
@@ -1154,17 +1310,26 @@ Double_t PTheory::GeneralExp(Double_t t, const PDoubleVector& paramValues, const
//--------------------------------------------------------------------------
/**
* <p> theory function: simple Gaussian
* \f[ = \exp\left(-1/2 [\sigma t]^2\right) \f] or
* \f[ = \exp\left(-1/2 [\sigma (t-t_{\rm shift})]^2\right) \f]
* \brief Simple Gaussian relaxation function.
*
* <b>meaning of paramValues:</b> \f$\sigma\f$ [, \f$t_{\rm shift}\f$]
* Mathematical form:
* \f[ P(t) = \exp\left(-\frac{1}{2} [\sigma t]^2\right) \f]
* or with time shift:
* \f[ P(t) = \exp\left(-\frac{1}{2} [\sigma (t-t_{\rm shift})]^2\right) \f]
*
* <b>return:</b> function value
* Represents Gaussian muon spin relaxation due to static random fields
* with a Gaussian distribution. The parameter σ = γ_μ ΔB where ΔB is the
* RMS field width.
*
* \param t time in \f$(\mu\mathrm{s})\f$, or x-axis value for non-muSR fit
* \param paramValues parameter values
* \param funcValues vector with the functions (i.e. functions of the parameters)
* <b>Parameters:</b>
* - fParamNo[0]: Relaxation rate σ (μs⁻¹)
* - fParamNo[1]: (optional) Time shift t_shift (μs)
*
* \param t Time in μs
* \param paramValues Vector of fit parameter values
* \param funcValues Vector of evaluated function values
*
* \return Gaussian relaxation value at time t
*/
Double_t PTheory::SimpleGauss(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
{
@@ -1194,17 +1359,33 @@ Double_t PTheory::SimpleGauss(Double_t t, const PDoubleVector& paramValues, cons
//--------------------------------------------------------------------------
/**
* <p> theory function: static Gaussian Kubo-Toyabe in zero applied field
* \f[ = \frac{1}{3} + \frac{2}{3} \left[1-(\sigma t)^2\right] \exp\left[-1/2 (\sigma t)^2\right] \f] or
* \f[ = \frac{1}{3} + \frac{2}{3} \left[1-(\sigma \{t-t_{\rm shift}\})^2\right] \exp\left[-1/2 (\sigma \{t-t_{\rm shift}\})^2\right] \f]
* \brief Static Gaussian Kubo-Toyabe relaxation function in zero field.
*
* <b>meaning of paramValues:</b> \f$\sigma\f$ [, \f$t_{\rm shift}\f$]
* Mathematical form:
* \f[ P(t) = \frac{1}{3} + \frac{2}{3} \left[1-(\sigma t)^2\right] \exp\left[-\frac{1}{2} (\sigma t)^2\right] \f]
* or with time shift:
* \f[ P(t) = \frac{1}{3} + \frac{2}{3} \left[1-(\sigma \{t-t_{\rm shift}\})^2\right] \exp\left[-\frac{1}{2} (\sigma \{t-t_{\rm shift}\})^2\right] \f]
*
* <b>return:</b> function value
* The Kubo-Toyabe function describes muon spin relaxation in a powder sample
* with random static nuclear magnetic moments creating a Gaussian field
* distribution at the muon site.
*
* \param t time in \f$(\mu\mathrm{s})\f$, or x-axis value for non-muSR fit
* \param paramValues parameter values
* \param funcValues vector with the functions (i.e. functions of the parameters)
* Physical interpretation:
* - 1/3 component: Muons with spin parallel to local field (unrelaxed)
* - 2/3 component: Muons with spin perpendicular to local field (relaxing)
* - Recovery at long times: Partial repolarization to 1/3
*
* <b>Parameters:</b>
* - fParamNo[0]: Relaxation rate σ = γ_μ ΔB (μs⁻¹), where ΔB is RMS field
* - fParamNo[1]: (optional) Time shift t_shift (μs)
*
* \param t Time in μs
* \param paramValues Vector of fit parameter values
* \param funcValues Vector of evaluated function values
*
* \return Gaussian Kubo-Toyabe value at time t
*
* \see StaticGaussKTLF() for longitudinal field version
*/
Double_t PTheory::StaticGaussKT(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
{