Model/Component/Parameter Module

Model/Component/Parameter (MCP) system for spectroscopy fitting.

This module implements the hierarchical model construction system that is the heart of trspecfit. It provides classes for building complex spectral models from reusable components with flexible parameter management.

Core Classes

ModelContainer for spectral components and parameters

Represents a complete 1D or 2D spectral model built from components. Handles parameter management, model evaluation, and plotting.

ComponentIndividual spectral, temporal, or profile function

Wraps functions from trspecfit.functions (energy/time/profile) into model-ready objects with parameter management and axis handling.

ParParameter with optional time-dependence and profile variation

Extends lmfit.Parameter to support time-varying parameters through the Dynamics system, profile-varying parameters through the Profile system, and handles parameter expressions/constraints.

DynamicsModel subclass for time-dependent behavior

Special Model type that describes how parameters evolve over time, with support for multi-cycle dynamics and convolution kernels.

ProfileModel subclass for auxiliary-axis parameter variation

Special Model type that describes how a parameter varies over an auxiliary physical axis (e.g. depth, position, fluence). Used for inhomogeneous averaging over the auxiliary dimension.

Architecture

The MCP system uses composition to build models from bottom-up:

Par (values + time-dependence + profile variation)
  ↓
Component (function + parameters)
  ↓
Model (components + combination rules)
  ↓
Spectrum (1D or 2D evaluated model)

Key Features

  • Hierarchical model construction from reusable components

  • Automatic parameter naming and numbering for multi-component models

  • Time-dependent parameters via Dynamics models

  • Profile-varying parameters via Profile models (auxiliary-axis averaging)

  • Expression-based parameter constraints and relationships

  • Support for convolution with instrumental response functions

  • Multi-cycle dynamics with subcycle support

  • Automatic component combination (addition, convolution, backgrounds)

class trspecfit.mcp.Model(model_name: str = 'test')[source]

Bases: object

Define a 2D time- and energy-resolved fit model using lmfit.

Model is the top-level container for spectral fitting. It manages a collection of Component objects and their parameters, handles model evaluation, and provides methods for fitting and visualization.

Parameters:

model_name (str, default='test') – Name identifier for this model (used in file I/O and plotting)

name

Model identifier

Type:

str

yaml_f_name

Name of YAML file this model was loaded from (without extension)

Type:

str or None

peak_fcts

Function objects for all components (extracted from Component.fct)

Type:

list

components

Component objects that define this model’s behavior

Type:

list of Component

lmfit_par_list

Flattened list of all individual parameters (spectral + temporal + profile)

Type:

list of lmfit.Parameter

lmfit_pars

Complete parameter object for fitting (from lmfit_par_list)

Type:

lmfit.Parameters

parameter_names

Names of all parameters in the model

Type:

list of str

component_spectra

Individual component spectra from last evaluation (when store_1d=1)

Type:

list of ndarray

value_1d

1D spectrum (sum of all components) from last evaluation

Type:

ndarray or None

value_2d

2D spectrum (time × energy) from last evaluation

Type:

ndarray or None

const

Constants for residual function (x, data, package, function_str, …)

Type:

tuple or None

args

Arguments for fit function (model, dim)

Type:

tuple or None

result

Fit results from fit_wrapper [par_ini, par_fin, conf_ci, emcee_fin, emcee_ci]

Type:

list

parent_file

Parent File object (set when model is loaded)

Type:

File or None

dim

Dimensionality (1 for energy/time only, 2 for time+energy)

Type:

int or None

energy

Energy axis for spectral components

Type:

ndarray or None

time

Time axis for temporal dynamics

Type:

ndarray or None

aux_axis

Auxiliary physical axis (e.g. depth, position) for Profile models

Type:

ndarray or None

Notes

Component Combination: Components are combined in reverse order (last to first) via the Model.combine() static method, which handles: - Addition (regular peaks) - Convolution (with kernels) - Background addition (requires existing spectrum)

Parameter Management: All parameters are stored in a flat lmfit.Parameters object for fitting. Time-dependent parameters add additional parameters from their Dynamics models to this flat structure. Profile-varying parameters add parameters from their Profile models similarly.

Inheritance: Model attributes (energy, time, aux_axis, parent_file) are inherited by: - Components (need axes for evaluation) - Parameters (need time axis for dynamics) - Dynamics models (need time axis and parent reference) - Profile models (need aux_axis and parent reference)

See also

Component

Individual spectral/temporal/profile components

Par

Parameters with optional time-dependence and profile variation

Dynamics

Model subclass for time-dependent parameters

Profile

Model subclass for auxiliary-axis parameter variation

File.load_model

Load models from YAML definitions

property plot_config: PlotConfig

Get plot configuration from parent File.

Models inherit plot settings from their parent File, ensuring consistent plotting across all models for the same dataset.

Returns:

Configuration object with plot settings (axes, colors, DPI, etc.)

Return type:

PlotConfig

describe(detail: int = 0) None[source]

Display information about model structure and parameters.

Parameters:

detail (int, default=0) – Level of detail to display: - 0: Component list and parameters only - 1+: Also plot initial guess and (for 2D) data comparison

visualize(*, rendering: Literal['graphviz', 'string'] = 'graphviz', collapse_profiles: bool = True) str | None[source]

Display the model’s dependency graph.

Builds a GraphIR from this model and renders it as a DAG.

Parameters:
  • rendering ({'graphviz', 'string'}, default='graphviz') –

    How to render the graph:

    • 'graphviz': Render inline SVG via the graphviz Python package (install with pip install "trspecfit[lab]" or pip install graphviz; also requires the dot system binary). Falls back to 'string' with a warning if the package is not installed.

    • 'string': Print the raw DOT source and return it.

  • collapse_profiles (bool, default=True) – When True, per-sample profile nodes are collapsed into single representative nodes showing the sample count, keeping profile models readable.

Returns:

The DOT source string when rendering='string', otherwise None (the graph is displayed inline).

Return type:

str or None

add_components(comps_list: list[Component]) None[source]

Add components to model and initialize their parameters.

This is the primary method for building up a model. It takes a list of Component objects, assigns them appropriate names/prefixes, creates their parameters, and updates the model’s parameter structure.

Parameters:

comps_list (list of Component) – Components to add to this model. Components should already have their parameter dictionaries populated via Component.add_pars().

Notes

Component Naming: Components are expected to have their names already set from YAML parsing (e.g., GLP_01, GLP_02, Offset, Shirley). The numbering is handled during YAML parsing, not here.

Parameter Naming:

Parameter names are constructed as: prefix + component_name + ‘_’ + param_name

  • For Dynamics models: prefix = model.name (e.g., 'GLP_01_x0_')

  • For regular models: prefix = '' (e.g., 'GLP_01_A')

Component Preparation: Each component receives: - energy/time axes from model - parent_model reference (for finding other parameters) - subcycle time axis (for multi-cycle Dynamics) - kernel time axis (for convolution components)

Model Updates: After adding components, the model’s lmfit_pars and parameter_names are automatically updated via self.update().

find_par_by_name(par_name: str) tuple[int | None, int | None][source]

Find the component and parameter indices for a given parameter name.

Searches through all components and their parameters to locate the indices needed to access a specific parameter by name (exact match).

Parameters:

par_name (str) – Full parameter name to search for (e.g., ‘GLP_01_x0’, ‘Offset_y0’)

Returns:

  • ci (int or None) – Component index in self.components, or None if not found

  • pi (int or None) – Parameter index in component.pars, or None if not found

print_all_pars(detail: int = 0) None[source]

Print information on all parameters individually.

Debugging utility to inspect parameter structure and values. For routine parameter inspection, use model.describe() or model.lmfit_pars.pretty_print().

Parameters:

detail (int, default=0) – Verbosity level passed to each Par.describe() call.

update() None[source]

Update model from bottom up: parameters → components → model.

Recompiles all parameters from all components and recreates the flattened lmfit parameter structures. Call this after modifying parameter structure. (automatically called after add_components, add_profile, add_dynamics)

update_value(new_par_values: list[float] | ndarray, par_select: str | list[str] = 'all') None[source]

Update model from top down: model → components → parameters.

Updates parameter values in the model’s lmfit_pars based on new values (e.g., from optimizer). Used during fitting to apply proposed parameter values before model evaluation.

Parameters:
  • new_par_values (array-like) – New parameter values to apply. Length must match number of parameters being updated.

  • par_select (str or list of str, default='all') –

    Which parameters to update:

    • ’all’: Update all parameters in order

    • list: Update only parameters with names in this list

Notes

Called by spectra.fit_model_mcp() on every iteration during fitting to update model parameters before evaluation. Does not trigger model re-evaluation; call create_value_1d() or create_value_2d() after updating values.

add_dynamics(dynamics_model: Dynamics, frequency: float = -1) None[source]

Add temporal dynamics model to a parameter.

Makes a parameter time-dependent by attaching a Dynamics model that describes how the parameter evolves over time. The Dynamics model name must match the parameter name exactly.

Parameters:
  • dynamics_model (Dynamics) – Dynamics instance describing time evolution. The model name must match a parameter in this model (e.g., ‘GLP_01_x0’).

  • frequency (float, default=-1) – Repetition frequency for cyclic dynamics (Hz): - -1: Single cycle over entire time axis - >0: Dynamics repeat at this frequency

add_profile(profile_model: Profile) None[source]

Add a profile variation to a parameter over the auxiliary axis.

Makes a parameter vary over aux_axis by attaching a Profile model. During Component.value(), the component is evaluated at every aux_axis point with the profile value substituted for this parameter, and the average is returned (uniform integration over the auxiliary dimension).

The Profile model name must match the target parameter name exactly, using the same convention as Dynamics (e.g., 'GLP_01_A').

Parameters:

profile_model (Profile) – Profile instance describing the parameter variation over aux_axis. Its name must match a parameter in this model.

Raises:

ValueError – If the parameter is not found, is expression-linked, or if aux_axis has not been set on this model.

get_all_parameters() list[Par][source]

Get all Par objects from all components in this model.

get_vary_levels() dict[str, str][source]

Get vary level for every lmfit parameter name in this model.

Walks the Par tree including Dynamics and Profile sub-model parameters at any nesting depth, returning a mapping from lmfit parameter name to vary level ("project", "file", or "static").

Returns:

{lmfit_param_name: vary_level} for all parameters.

Return type:

dict of str to str

static combine(value: ndarray, comp: Component, t_ind: int = 0) ndarray[source]

Combine component value with input spectrum via addition or convolution.

This is the core method that defines how components are combined to build up a complete spectrum. Components are processed in reverse order (last to first) during model evaluation.

Parameters:
  • value (ndarray) – Current spectrum being built up

  • comp (Component) – Component to add/convolve with current spectrum

  • t_ind (int, default=0) – Time index for evaluation (for time-dependent parameters)

Returns:

Updated spectrum after combining with component

Return type:

ndarray

create_value_1d(t_ind: int = 0, *, store_1d: int = 0, return_1d: int = 0) ndarray | None[source]

Evaluate model to create 1D spectrum (energy or time).

Combines all components according to their types (addition, convolution, background) to generate the complete model spectrum at a specific time point (or for a Dynamics model, the complete time evolution).

Parameters:
  • t_ind (int, default=0) – Time index for evaluation. For energy-resolved models, this selects which time point to evaluate. For Dynamics models, affects which parameters have time-dependence applied.

  • store_1d (int, default=0) – If 1, store individual component spectra in self.component_spectra for later plotting or analysis.

  • return_1d (int, default=0) – If 1, return the computed spectrum. Otherwise return None and store in self.value_1d only.

Returns:

If return_1d=1, returns the 1D spectrum. Otherwise returns None. Spectrum is always stored in self.value_1d regardless of return setting.

Return type:

ndarray or None

Notes

Component Combination Order: Components are combined in REVERSE order (last to first): 1. Initialize with last component 2. Combine with second-to-last, third-to-last, etc. 3. This allows backgrounds to access the sum of all peaks

Stored Components: When store_1d=1, self.component_spectra contains individual contributions in the ORIGINAL order (not reversed). This matches the order components were defined and makes plotting intuitive.

Performance: For 2D models, this function is called repeatedly (once per time point). If components have no time-dependence, their evaluation could be cached, but current implementation re-evaluates for simplicity and correctness with convolution/background interactions.

create_value_2d(t_ind: list[int] | None = None) None[source]

Evaluate model to create 2D spectrum (time × energy).

Generates the complete time- and energy-resolved spectrum by calling create_value_1d() for each time point. This is where time-dependent parameters dynamically modify the model at each time step.

Parameters:

t_ind (list of int or None, optional) – Time index range to process: - None (default): Process entire time axis - [start, stop]: Process self.time[start:stop] only

Notes

Performance: Evaluation time scales linearly with: - Number of time points (len(self.time)) - Number of energy points (len(self.energy)) - Model complexity (number of components, time-dependent parameters)

Memory: Result stored in self.value_2d has shape (n_time, n_energy). For 1000 time points × 500 energy points × 8 bytes/float: ~4 MB per model evaluation.

Time-Dependence: For each time point t_i: 1. Time-dependent parameters evaluate their Dynamics at t_i 2. Model components use these parameter values 3. 1D spectrum computed and stored in value_2d[t_i, :]

plot_1d(t_ind: int = 0, *, plot_sum: bool = True, x_lim: tuple[float, float] | None = None, y_lim: tuple[float, float] | None = None, save_img: int = 0, save_path: str = '', config: PlotConfig | None = None, **plot_kwargs) None[source]

Plot 1D model spectrum (energy or time).

Visualizes model evaluation results, either as sum of all components or as individual component contributions. Useful for checking initial guesses and understanding fit results.

Parameters:
  • t_ind (int, default=0) – Time index for energy-resolved models. Ignored for Dynamics models which show time evolution.

  • plot_sum (bool, default=True) – Component display mode: - True: Plot only sum of all components - False: Plot each component separately

  • x_lim (tuple of float, optional) – X-axis display range (min, max) in axis coordinates

  • y_lim (tuple of float, optional) – Y-axis display range (min, max)

  • save_img (int, default=0) – Save/display control: - 0: Display only - 1: Display and save - -1: Save only (no display)

  • save_path (str, default='') – Path for saving figure (if save_img != 0)

  • config (PlotConfig, optional) – Override the model’s inherited plot configuration for this call. If None, uses the model’s own plot_config.

  • **plot_kwargs (dict) – Per-call overrides for any PlotConfig field (e.g. colors, ticksize, legend). Applied on top of config.

plot_2d(save_img: int = 0, save_path: str = '', x_lim: tuple[float, float] | None = None, y_lim: tuple[float, float] | None = None, z_lim: tuple[float, float] | None = None, config: PlotConfig | None = None, **plot_kwargs) None[source]

Plot 2D time-and-energy spectrum as heatmap.

Visualizes the complete 2D model evaluation showing how the spectrum evolves over time. Essential for understanding time-dependent models before and after fitting.

Parameters:
  • save_img (int, default=0) – Save/display control: - 0: Display only - 1: Display and save - -1: Save only (no display)

  • save_path (str, default='') – Path for saving figure (if save_img != 0)

  • x_lim (tuple of float, optional) – Energy axis display range (min, max)

  • y_lim (tuple of float, optional) – Time axis display range (min, max)

  • z_lim (tuple of float, optional) – Color scale limits (min, max)

  • config (PlotConfig, optional) – Override the model’s inherited plot configuration for this call. If None, uses the model’s own plot_config.

  • **plot_kwargs (dict) – Per-call overrides for any PlotConfig field (e.g. z_colormap, ticksize). Applied on top of config.

class trspecfit.mcp.Component(comp_name: str, package: ModuleType | None = None, comp_subcycle: int = 0)[source]

Bases: object

Individual spectral, temporal, or profile component with parameter management.

Component wraps a function from trspecfit.functions (energy, time, or profile) into a model-ready object with parameter management, axis handling, and integration within the Model/Component/Parameter hierarchy.

Parameters:
  • comp_name (str) – Component name, possibly with numbering (e.g., ‘GLP_01’, ‘expFun_02’). Numbering is typically assigned during YAML parsing.

  • package (module, optional) – Python module containing the component function (fcts_energy, fcts_time, or fcts_profile). Defaults to fcts_energy.

  • comp_subcycle (int, default=0) – Subcycle number for multi-cycle Dynamics models: - 0: Active for entire time axis (default) - 1, 2, …: Active only during specific subcycle

package

Module containing the function (fcts_energy, fcts_time, or fcts_profile)

Type:

module

comp_name

Full component name including any numbering

Type:

str

fct_str

Base function name without numbering (e.g., ‘GLP’, ‘expFun’)

Type:

str

N

Component number (e.g., 1, 2) or -1 if unnumbered

Type:

int

comp_type

Component type determining combination method: - ‘add’: Regular addition (peaks, lineshapes) - ‘back’: Background (requires existing spectrum) - ‘conv’: Convolution kernel - ‘none’: Placeholder (no operation)

Type:

str

par_dict

Parameter specifications from YAML: {name: [value, vary, min, max]}

Type:

dict

subcycle

Subcycle number for multi-cycle dynamics

Type:

int

time_n_sub

Binary mask (1=active, 0=inactive) for subcycle timing

Type:

ndarray or None

time_norm

Normalized time axis (resets to 0 at each subcycle start)

Type:

ndarray or None

pars

Parameter objects for this component

Type:

list of Par

lmfit_par_list

Flattened list of lmfit parameters

Type:

list of lmfit.Parameter

lmfit_pars

lmfit.Parameters object built from lmfit_par_list

Type:

lmfit.Parameters

time

Time axis (inherited from model, or kernel axis for convolutions)

Type:

ndarray or None

energy

Energy axis (inherited from model)

Type:

ndarray or None

aux_axis

Auxiliary physical axis (inherited from model, used by Profile components)

Type:

ndarray or None

parent_model

Parent model reference (for parameter lookups)

Type:

Model or None

Notes

Component Properties:

The Component class provides several computed properties for accessing function information:

  • fct : callable - Function object (auto-updates if package or fct_str changes)

  • fct_specs : inspect.FullArgSpec - Function signature information

  • fct_args : list of str - Function argument names

  • prefix : str - Prefix for parameter names (’’ for exceptions, comp_name+’_’ otherwise)

  • name : str - Component display name

  • package_name : str - Name of the package module (e.g. ‘fcts_energy’)

property fct: Callable

Function object for this component.

Automatically retrieves function from package using fct_str. Updates dynamically if package or fct_str changes.

Returns:

Function object (e.g., fcts_energy.GLP, fcts_time.expFun)

Return type:

callable

property fct_specs: FullArgSpec

Function signature specifications.

Returns:

Complete function signature information

Return type:

inspect.FullArgSpec

property fct_args: list[str]

Function argument names.

Returns:

Argument names from function signature

Return type:

list of str

property prefix: str

Prefix for parameter names.

Returns:

Parameter prefix: comp_name + ‘_’: For regular components

Return type:

str

property name: str

Component display name.

Returns:

Component name (same as comp_name)

Return type:

str

property package_name: str

Name of the package this component belongs to.

Returns:

Package name (e.g., ‘fcts_energy’, ‘fcts_time’)

Return type:

str

add_pars(par_info_dict: dict[str, list]) None[source]

Add parameter specifications to component.

Stores parameter information that will be used to create Par objects when create_pars() is called. Typically populated from YAML model definitions.

Parameters:

par_info_dict (dict) – Parameter specifications: {name: [value, vary, min, max]} for constrained or {name: [value], vary} for unconstrained parameters, or {name: [‘expression’]} for dependent parameters

Notes

Does not create the actual Par objects yet - that happens in create_pars(). This separation allows parameters to be defined before axes are known.

create_pars(prefix: str = '') None[source]

Create Par objects from parameter dictionary.

Populates self.pars with Par objects for each entry in self.par_dict. Uses two-pass approach to handle expression parameters that may reference parameters defined later in the component.

Parameters:

prefix (str, default='') – Prefix to prepend to parameter names (e.g., for Dynamics models)

Notes

Two-Pass Creation: 1. First pass: Create all Par objects with values/bounds 2. Second pass: Set expressions (so forward references work)

This ensures expressions like ‘GLP_02_A’ work even when GLP_02 is defined after GLP_01 in the component list.

update_lmfit_par_list() None[source]

Update flattened list of lmfit parameters and lmfit.Parameters object.

Collects all lmfit.Parameter objects from all Par objects in this component and stores them in a flat list. This includes both spectral and temporal parameters (if any Par has time-dependence or a profile).

Notes

Called automatically by Model.update(). Users typically don’t need to call this directly.

The flattened list is used by Model to construct the complete lmfit.Parameters object for fitting.

describe(detail: int = 1) None[source]

Print component information.

Parameters:

detail (int, default=1) – Detail level: - 0: Function name only - 1+: Function name, type, subcycle, and parameters

create_t_kernel() ndarray[source]

Create time axis for convolution kernel.

Convolution kernels need a time axis that extends beyond the data time axis to properly handle edge effects. This method creates an appropriately sized kernel axis based on the kernel width.

Returns:

Kernel time axis, centered at 0 and extending ±(width * kernel_parameter)

Return type:

ndarray

value(t_ind: int = 0, **kwargs) ndarray[source]

Evaluate component at specific time point.

Computes the component’s contribution to the spectrum using current parameter values. Handles time-dependent parameters, subcycle masking, and passes appropriate axes.

Parameters:
  • t_ind (int, default=0) – Time index for evaluation (affects time-dependent parameters)

  • **kwargs (dict) – Additional arguments passed to function (e.g., spectrum for backgrounds)

Returns:

Component value as function of energy or time

Return type:

ndarray

Notes

Parameter Evaluation: Each Par object is evaluated at t_ind, which: - Returns current value for time-independent parameters - Returns value(t_ind) for time-dependent parameters (via Dynamics)

Subcycle Handling: For multi-cycle Dynamics models (subcycle != 0): - Uses time_norm instead of time (resets to 0 each subcycle) - Multiplies result by time_n_sub mask (1=active, 0=inactive)

Background Functions: Background functions receive the ‘spectrum’ kwarg containing the current peak sum, which they use to compute backgrounds like Shirley.

plot(t_ind: int = 0, *, plot_traces: bool = True, plot_every: int = 1, plot_max: int | None = None, save_img: int = 0, config: PlotConfig | None = None, plot_kwargs: dict | None = None, **kwargs) None[source]

Plot component as standalone spectrum/dynamics.

Quick visualization of individual component behavior, useful for debugging component definitions and understanding parameter effects.

Parameters:
  • t_ind (int, default=0) – Time index for evaluation

  • plot_traces (bool, default=True) – For components with profile-varying parameter(s) (p_vary=True): - True: plot one trace per aux-axis point - False: plot single combined trace (average over aux-axis traces) For all other components, a single trace is plotted.

  • plot_every (int, default=1) – When plotting individual aux-axis traces (plot_traces=True), show every N-th curve (N=1 means show all curves).

  • plot_max (int or None, default=None) – Optional hard cap on number of individual aux-axis curves to plot. First plot_max traces are shown (spaced according to plot_every).

  • save_img (int, default=0) – 0: display, 1: save+display, -1: save only, -2: close (no display/save)

  • config (PlotConfig, optional) – Override the inherited plot configuration for this call. If None, falls back to the parent model’s plot_config.

  • plot_kwargs (dict, optional) – Per-call overrides for any PlotConfig field (e.g. colors, ticksize). Applied on top of config.

  • **kwargs (dict) – Additional arguments passed to component function. Background components require spectrum to be provided.

class trspecfit.mcp.Par(name: str, info: list[Any] | None = None)[source]

Bases: object

Parameter with optional time-dependence, profile variation, and expression support.

Par extends lmfit.Parameter to support: - Time-varying parameters via Dynamics models - Profile-varying parameters via Profile models (auxiliary-axis averaging) - Expression-based constraints referencing other parameters - Tracking of time-dependent expression references

Parameters:
  • name (str) – Parameter name (typically prefixed with component name)

  • info (list, default=[]) – Parameter specification: - [value, vary, min, max]: Standard parameter - [‘expression’]: Expression-based parameter

name

Parameter name

Type:

str

info

Parameter specification from initialization

Type:

list

lmfit_par

lmfit Parameters object (contains 1+ parameters)

Type:

lmfit.Parameters

t_vary

Whether parameter has time-dependence (via Dynamics)

Type:

bool

t_model

Dynamics model describing time evolution (if t_vary=True)

Type:

Dynamics or None

p_vary

Whether parameter varies over the auxiliary axis (via Profile)

Type:

bool

p_model

Profile model describing variation over aux_axis (if p_vary=True)

Type:

Profile or None

lmfit_par_list

Flattened list of all lmfit parameters (spectral + temporal + profile)

Type:

list

expr_refs_time_dep

Whether expression references time-dependent parameters

Type:

bool

expr_string

Original expression string (for expression parameters)

Type:

str or None

expr_refs

Parameter names referenced in expression

Type:

list of str

parent_model

Parent model reference (for finding other parameters)

Type:

Model or None

Notes

Time-Dependence:

When t_vary=True, the parameter value at time t is:

value(t) = base_value + dynamics_model.value_1d[t]

Profile Variation:

When p_vary=True, Component.value() evaluates the component at every aux_axis point with the profile value added to the base parameter value, then returns the uniform average (integration over auxiliary dimension).

Expression Handling:

Expressions are evaluated using asteval (same as lmfit) for safety. Can reference other parameters, including time-dependent ones.

Expression + Dynamics:

A parameter can have an expression that references a time-dependent parameter. In this case, expr_refs_time_dep=True and the expression is re-evaluated at each time point during model evaluation.

Parameter Flattening:

lmfit_par_list contains all parameters defining this Par:

  • Without time/profile-dependence: 1 parameter (the spectral one)

  • With time-dependence: N parameters (spectral + all from Dynamics model)

  • With profile variation: M parameters (spectral + all from Profile model)

  • Both: N + M - 1 parameters (spectral counted once)

describe(detail: int = 0) None[source]

Print parameter information.

Parameters:

detail (int, default=0) – Detail level for display (passed to t_model.describe if applicable)

create(*, prefix: str = '', suffix: str = '', expr_skip: bool = False) None[source]

Create lmfit parameter from info specification.

Initializes the lmfit.Parameters object with the parameter defined by self.info. Handles both standard parameters and expression-based parameters.

Parameters:
  • prefix (str, default='') – Prefix to prepend to parameter name

  • suffix (str, default='') – Suffix to append to parameter name

  • expr_skip (bool, default=False) – If True and info is expression, create with dummy value first (expression set later in two-pass creation)

Notes

For expression parameters, expr_skip=True creates a temporary parameter with dummy value. The actual expression is set in a second pass (see Component.create_pars) to handle forward references.

update(t_model: Dynamics) None[source]

Add time-dependence to parameter via Dynamics model.

Converts a static parameter into a time-dependent one by attaching a Dynamics model that describes temporal evolution.

Parameters:

t_model (Dynamics) – Dynamics model describing time evolution

value(t_ind: int = 0, *, update_t_model: bool = True, aux_ind: int | None = None) float[source]

Get parameter value at specific time point and aux-axis index.

Returns the parameter value, accounting for time-dependence, profile-dependence, and expressions that reference either.

Parameters:
  • t_ind (int, default=0) – Time index for evaluation

  • update_t_model (bool, default=True) – If True, recompute Dynamics model before evaluation. Set False when calling repeatedly during 2D model evaluation.

  • aux_ind (int or None, default=None) – Auxiliary axis index for profile evaluation. When set, p_vary parameters return base + profile.value_1d[aux_ind], and expressions referencing p_vary parameters are re-evaluated with the profiled values.

Returns:

Parameter value at time point t_ind

Return type:

float

analyze_expression_dependencies(all_parameters: list[Par]) None[source]

Analyze expression for time-dependent parameter references.

Checks if this parameter’s expression references any time-dependent parameters. If so, sets expr_refs_time_dep flag so value() can handle dynamic expression evaluation. Called automatically after adding time-dependence to any parameter.

Parameters:

all_parameters (list of Par) – All parameters in parent model (to check time-dependence)

get_all_parameters() list[Par][source]

Get all parameters from parent model.

Returns:

All parameters in parent model

Return type:

list of Par

class trspecfit.mcp.Dynamics(model_name: str)[source]

Bases: Model

Time-dependence model for parameters with multi-cycle support.

Dynamics is a specialized Model that describes how a parameter evolves over time. It uses temporal functions (from trspecfit.functions.time) to model dynamics like exponential decays, rises, oscillations, and can include convolution with instrumental response functions.

The name of a Dynamics model must match the parameter it describes (e.g., ‘GLP_01_x0’ for the x0 parameter of the GLP_01 component).

Parameters:

model_name (str) – Name matching the parameter to control (e.g., ‘GLP_01_x0’)

All Model attributes, plus
frequency

Repetition frequency for cyclic dynamics (Hz): - -1: Single cycle over entire time axis (default) - >0: Dynamics repeat at this frequency

Type:

float

subcycles

Number of subcycles within each main cycle: - 0: No subcycles (single dynamics for entire cycle) - N>0: N different dynamics that activate sequentially

Type:

int

time_norm

Normalized time that resets to 0 at start of each subcycle

Type:

ndarray or None

n_sub

Subcycle number active at each time point (1, 2, …, subcycles)

Type:

ndarray or None

n_counter

Cumulative subcycle counter (increments each subcycle)

Type:

ndarray or None

Notes

Single Cycle (frequency=-1): Dynamics apply once over the entire time axis. Appropriate for: - Single pump-probe experiments - Irreversible reactions - One-time perturbations

Multi-Cycle (frequency>0): Dynamics repeat periodically. Appropriate for: - Lock-in detection experiments - Periodic excitation (lasers, electrical pulses) - Steady-state oscillations

Subcycles: Within each main cycle, different dynamics can activate sequentially. Example: pump-probe-pump experiments where: - Subcycle 1: First pump response - Subcycle 2: Second pump response

Components are assigned to subcycles via comp_subcycle parameter: - subcycle=0: Active for all times (e.g., IRF convolution) - subcycle=1,2,…: Active only during that subcycle

Time Normalization: For multi-cycle dynamics: - time_norm resets to 0 at each subcycle start - n_sub tracks which subcycle is active (1, 2, 3, …) - n_counter cumulative count of subcycles

Evaluation: The dynamics model evaluates to value_1d, which is added to the base parameter value: param_total(t) = param_base + dynamics.value_1d[t]

set_frequency(frequency: float) None[source]

Set repetition frequency and update time normalization.

Configures the Dynamics for cyclic behavior and updates all components with proper subcycle timing information.

Parameters:

frequency (float) – Repetition frequency in Hz: - -1: No repetition (single cycle) - >0: Repeat at this frequency

Raises:

ValueError – If frequency > 0 and subcycles == 0 (single dynamics model). Multi-cycle requires at least 2 entries in model_info.

Notes

After setting frequency: - time_norm, n_sub, n_counter are computed via normalize_time() - Each component receives time_n_sub mask (1=active, 0=inactive) - Components with subcycle>0 use time_norm instead of time

model_info length and subcycle assignment:

The number of entries in model_info determines the subcycle structure. The first entry is always the global component (subcycle=0), which evaluates on the raw time axis regardless of frequency. The remaining entries are repeating subcycles.

  • 1 entry: single dynamics, no frequency support (subcycles=0)

  • 2 entries: e.g. ["none", "MonoExp"] or ["IRF", "MonoExp"]. The first model applies globally (IRF convolution or no-op placeholder), the second repeats at the set frequency as a single full-period cycle (subcycles=1).

  • 3+ entries: e.g. ["IRF", "ModelA", "ModelB"]. First model is global, the rest are subcycles that alternate within each period (subcycles=len-1).

Component Updates: For each component: - time_n_sub mask applied (zeros where subcycle doesn’t match) - Normalized time axis inherited (if subcycle != 0)

normalize_time(time_unit: int = 0, *, show_plot: bool = False) None[source]

Normalize time axis for multi-cycle dynamics with subcycles.

Creates normalized time arrays that reset periodically based on frequency and subcycle count. This enables complex multi-cycle dynamics like pump-probe-pump experiments.

Parameters:
  • time_unit (int, default=0) – Power of 10 for time units (currently unused)

  • show_plot (bool, default=False) – If True, plot normalized time arrays

Examples

>>> t_model = Dynamics('param')
>>> t_model.time = np.array([0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3])
>>> t_model.frequency = 10  # 10 Hz = 0.1 s period
>>> t_model.subcycles = 2   # Two subcycles per period
>>> t_model.normalize_time()
>>>
>>> print(t_model.time_norm)  # Resets every 0.05 s (half period)
[0, 0.05, 0, 0.05, 0, 0.05, 0]
>>> print(t_model.n_sub)  # Which subcycle (1 or 2)
[1, 1, 2, 2, 1, 1, 2]
>>> print(t_model.n_counter)  # Cumulative count
[1, 1, 2, 2, 3, 3, 4]

Notes

Normalization Logic: - Subcycle duration = 1 / (frequency * subcycles) - time_norm resets to 0 at start of each subcycle - n_sub cycles through 1, 2, …, subcycles - n_counter increments by 1 each subcycle

Negative Times: Times t < 0 are assigned: - time_norm = 0 - n_sub = 0 (baseline/pre-trigger) - n_counter = 0

No Repetition (frequency=-1): - time_norm = time (unchanged) - n_sub = 0 (all zeros) - n_counter = 0 (all zeros)

Validation: Raises ValueError for: - frequency < 0 and != -1

Note: subcycles=0 with frequency > 0 is rejected upstream in set_frequency(). - subcycles > 1 with frequency = -1 (inconsistent)

Note: subcycles=1 is rejected at model load time (File.load_model).

class trspecfit.mcp.Profile(model_name: str)[source]

Bases: Model

Profile model: parameter variation over an auxiliary physical axis.

A Profile model describes how one or more spectral parameters vary across an auxiliary axis (e.g. depth, position, fluence). When a parameter has p_vary=True, Component.value() evaluates the component at every point along aux_axis and returns the uniform average — physically representing integration over the auxiliary dimension.

Analogous to Dynamics (which varies parameters over the time axis), but simpler: no frequency or subcycles.

Parameters:

model_name (str) – Name of this Profile model. Must match the name of the parameter in the parent model that it describes (same convention as Dynamics).

parent_model

Reference to the parent energy/2D model. Set by Model.add_profile().

Type:

Model or None

aux_axis

The auxiliary axis this profile is evaluated over. Inherited from the parent model when add_profile() is called.

Type:

ndarray or None

Notes

Profile model components use functions from fcts_profile and are evaluated with aux_axis as their x-axis.

Multiple p_vary parameters on the same component share the same aux_axis and are evaluated jointly at each aux point (correlated variation).

Profile model parameters can themselves be time-dependent (t_vary=True), enabling spectral diffusion: inhomogeneous broadening that evolves in time.