environmentaltools.temporal.fourier_expansion

environmentaltools.temporal.fourier_expansion(data: DataFrame, par: list, param: dict)[source]

Estimate time-varying distribution parameters using Fourier expansion.

Performs non-stationary analysis by expanding distribution parameters as Fourier series of varying orders. Tests multiple mode combinations and optimizes parameters via maximum likelihood estimation.

Parameters:
  • data (pd.DataFrame) – Time series data with normalized time column ‘n’ in [0,1]

  • par (list or dict) – Initial parameter guesses (can be empty list for automatic initialization)

  • param (dict) –

    Configuration dictionary containing:

    • ’basis_function’dict

      Contains ‘order’ specifying maximum Fourier order to test

    • ’no_fun’int

      Number of distribution functions (1, 2, or 3)

    • ’initial_parameters’dict

      Contains ‘make’ (bool) and ‘mode’ (tuple) for custom mode

    • ’var’str

      Variable name to analyze

    • Other fitting parameters

Returns:

  • par (dict) – Dictionary of fitted parameters keyed by mode tuple e.g., {(1,): [params], (2,): [params], …}

  • nllf (dict) – Negative log-likelihood values for each mode

  • mode (list) – List of mode tuples tested [(1,), (2,), …, (order,)]

Notes

Mode tuples specify Fourier order for each parameter:

  • 1 function: modes = [(1,), (2,), …, (order,)]

  • 2 functions: modes = [(i,1), …, (order,j)]

  • 3 functions: modes = [(1,i,1), …, (order,order,i)]

The function incrementally builds parameter vectors, starting from stationary (order 0) and progressively adding Fourier terms.

Uses L-BFGS-B optimization with bounds to ensure valid parameters.

See also

initial_params

Constructs initial parameter vectors

fit

Core optimization function

negative_log_likelihood

Objective function

Examples

>>> param = {
...     'basis_function': {'order': 3},
...     'no_fun': 1,
...     'initial_parameters': {'make': False},
...     'var': 'Hs'
... }
>>> par, nllf, modes = fourier_expansion(df, [], param)
>>> best_mode = min(nllf, key=nllf.get)
>>> print(f"Best mode: {best_mode}, NLLF: {nllf[best_mode]}")