Time Functions
Temporal dynamics functions for time-resolved spectroscopy.
Function Conventions
Use CamelCase naming (UpperCamelCase or lowerCamelCase) for function names.
Dynamics Functions: Signature: func(t, par1, par2, …, t0) - t: Time axis (numpy array) - par1, par2, …: Function-specific parameters - t0: Time zero (function starts at this time) - Returns: f(t) = 0 for t < t0, dynamics for t >= t0
Convolution Kernels: Signature: funcCONV(t, par1, par2, …)
t: Time differences centered at zero. Kernels must be elementwise in this argument: the kernel-matrix convolution evaluates them on a 2D matrix of time differences (see utils.arrays.conv_matrix_operator)
par1, par2, …: Kernel parameters
Returns: Kernel values (unnormalized; the convolution row-normalizes)
Every kernel additionally requires a private edge-mass companion
_<name>_edge_mass(dt_left, dt_right, **params) registered in
CONV_EDGE_MASS. It returns the exact exterior masses of the kernel
body (same normalization) beyond the data window — the analytic
integrals over (-inf, t[0]] and [t[-1], inf) used for
edge-value padding. Use cancellation-safe tail forms (erfc, direct
exp, clip) rather than CDF differences, and validate the parameters
(strictly positive, finite) — companions are the runtime backstop for
expression-driven kernel parameters that bypass model-load bound
checks. A kernel without a companion is rejected at model validation
(mcp) and scheduling (GIR).
Time Zero Convention: All dynamics functions are zero before t0 and activate at t >= t0. This reflects physical causality: response begins after excitation. Exception: erfFun is a smoothed step, so it is nonzero (approaching 0) shortly before t0; it crosses A/2 at t0.
Offsets and Baselines: Dynamics components combine by addition, so constant offsets are their own component rather than a parameter of every function: - stepFun: sharp onset to a constant value A at t0 - erfFun: Gaussian-broadened onset, rises from 0 to A around t0 For example, a decay to a nonzero plateau is expFun + stepFun sharing t0.
Time Resolution: Functions inherit time axis from Dynamics model. Consider: - Time step size relative to dynamics (dt << tau) - Time range coverage (include full decay/rise) - Kernel width appropriate for convolution
Parameter Naming
Common parameter names: - A: Amplitude (change in signal) - tau: Time constant (decay/rise time, 1/e point) - t0: Time zero (start of dynamics) - f: Frequency (for oscillations) - phi: Phase (for oscillations) - SD: Standard deviation (for Gaussian kernels) - W: FWHM (for Lorentzian kernels)
Adding New Functions
To add a new dynamics or convolution function:
Implement following conventions above
Ensure f(t<t0) = 0 for dynamics functions
Keep convolution kernels elementwise in their first argument
Test with realistic time-resolved data
- trspecfit.functions.time.boxCONV(x: ndarray, width: float) ndarray[source]
Box (rectangular) convolution kernel.
- Parameters:
x (ndarray) – Time axis (centered at 0)
width (float) – Width of rectangular window
- Returns:
Rectangular function: 1 inside width, 0 outside (hard edges)
- Return type:
ndarray
- trspecfit.functions.time.erfFun(t: ndarray, A: float, SD: float, t0: float) ndarray[source]
Error function rise (step with Gaussian broadening). erfFun ≈ stepFun ⊗ Gaussian(SD)
As a smoothed step this is the one dynamics function that is nonzero (approaching 0) shortly before t0; it crosses A/2 at t0 and rises to A.
- Parameters:
- Returns:
Error function: A/2 * (1 + erf((t-t0)/(SD*√2)))
- Return type:
ndarray
- trspecfit.functions.time.expDecayCONV(x: ndarray, tau: float) ndarray[source]
Causal exponential kernel (one-sided decay).
- Parameters:
x (ndarray) – Time axis (centered at 0)
tau (float) – Decay time constant
- Returns:
One-sided exponential: 0 for x<0, exp(-x/tau) for x≥0
- Return type:
ndarray
- trspecfit.functions.time.expFun(t: ndarray, A: float, tau: float, t0: float) ndarray[source]
Exponential decay or rise dynamics.
- Parameters:
t (ndarray) – Time axis
A (float) – Amplitude (initial change at t0). - A > 0: Jumps to A at t0, decays toward 0 - A < 0: Jumps to
-|A|at t0, rises toward 0tau (float) – Time constant (1/e time). Units: [time units] At t = t0 + tau, signal changes by factor of e (≈2.718)
t0 (float) – Time zero (start of exponential)
- Returns:
Exponential: 0 for t<t0, A*exp(-(t-t0)/tau) for t>=t0
- Return type:
ndarray
- trspecfit.functions.time.expRiseCONV(x: ndarray, tau: float) ndarray[source]
Anti-causal exponential rise kernel (mirror of expDecayCONV).
The kernel is nonzero only for x <= 0, so the convolved response at time t draws from the signal at later times: it rises before the excitation and saturates at t0.
- Parameters:
x (ndarray) – Time axis (centered at 0)
tau (float) – Rise time constant
- Returns:
One-sided exponential: exp(x/tau) for x≤0, 0 for x>0
- Return type:
ndarray
- trspecfit.functions.time.expSymCONV(x: ndarray, tau: float) ndarray[source]
Symmetric exponential kernel (double exponential). Exponential decay in both directions from center:
exp(-|x|/tau)- Parameters:
x (ndarray) – Time axis (centered at 0)
tau (float) – Decay time constant
- Returns:
Symmetric exponential kernel
- Return type:
ndarray
- trspecfit.functions.time.gaussCONV(x: ndarray, SD: float) ndarray[source]
Gaussian convolution kernel (instrumental response function).
- Parameters:
x (ndarray) – Time differences (centered at 0)
SD (float) – Standard deviation (Gaussian width). FWHM = 2.355 * SD = 2*√(2ln2) * SD
- Returns:
Gaussian kernel (unnormalized, will be normalized in convolution)
- Return type:
ndarray
- trspecfit.functions.time.linFun(t: ndarray, m: float, t0: float) ndarray[source]
Linear dynamics (constant rate of change).
- trspecfit.functions.time.none(t: ndarray) ndarray[source]
Placeholder function to define empty subcycles in a mcp.Dynamics model.
Used to define empty subcycles in multi-cycle Dynamics models without adding any time-dependent behavior. This allows subcycle numbering to work correctly when some subcycles should have no dynamics.
Usage (in model YAML file):
model_sub2: none: {}
- Parameters:
t (ndarray) – Time axis (not used)
- Returns:
Array of zeros with same shape as t
- Return type:
ndarray
- trspecfit.functions.time.sinDivX(t: ndarray, A: float, f: float, t0: float) ndarray[source]
Damped sinc function: sin(x)/x oscillation.
- trspecfit.functions.time.sinFun(t: ndarray, A: float, f: float, phi: float, t0: float) ndarray[source]
Sinusoidal oscillations (coherent dynamics).
- Parameters:
t (ndarray) – Time axis
A (float) – Oscillation amplitude (peak-to-peak = 2A)
f (float) – Frequency in [1/time units] Period = 1/f
phi (float) – Phase offset in radians - phi = 0: Sine starts at zero - phi = π/2: Starts at maximum (cosine) - phi = π: Starts at zero (negative slope)
t0 (float) – Time zero (start of oscillation)
- Returns:
Sinusoid: 0 for t<t0, A*sin(2πf(t-t0)+phi) for t>=t0 Oscillates around 0; add stepFun to shift the center line.
- Return type:
ndarray
- trspecfit.functions.time.sqrtFun(t: ndarray, A: float, t0: float) ndarray[source]
Square root rise (diffusion dynamics).
- trspecfit.functions.time.stepFun(t: ndarray, A: float, t0: float) ndarray[source]
Step function (constant offset switching on at t0).
The causal offset primitive: dynamics components combine by addition, so add stepFun to model baselines or plateaus (e.g. expFun + stepFun sharing t0 gives a decay to a nonzero plateau). For a Gaussian-broadened onset use erfFun instead.