concord-models-utils

Shared numerical primitives for all model packages

Role in the system concord-models-utils provides the mathematical building blocks that neural mass models need: sigmoid functions, ODE/SDE integrators, and noise generators. It is the simulation-side analog of concord-metrics-utils. It has no knowledge of the Model ABC or any specific model — just pure numerical code.

Package Structure

concord-models-utils/
  src/concord_models_utils/
    __init__.py       exports sigmoid, rk4_step, euler_maruyama_step, gaussian_input
    sigmoid.py        voltage-to-firing-rate transfer function
    integrators.py    RK4 and Euler-Maruyama single-step integrators
    noise.py          noise generators for stochastic input

sigmoid.py

fnsigmoid(v, e0=2.5, v0=6.0, r=0.56) → ndarray | float

Voltage-to-firing-rate sigmoid transfer function. Converts mean membrane potential to mean firing rate.

S(v) = 2 · e0 / (1 + exp(r · (v0 - v)))
ParameterTypeDescription
vndarray | floatMean membrane potential. Accepts scalars or arrays.
e0floatHalf of the maximum firing rate (Hz). Default 2.5.
v0floatPotential at half maximum firing rate (mV). Default 6.0.
rfloatSlope of the sigmoid at v0 (1/mV). Default 0.56.

The exponent is clipped to [-500, 500] to prevent numerical overflow. Default parameter values are from the Jansen-Rit (1995) model.

integrators.py

Both integrators are single-step functions — they advance the state by one time step. The model's simulate() method owns the time loop and calls these repeatedly. Extra arguments are passed through to the derivative function via *args, following the same convention as scipy.integrate.odeint.

fnrk4_step(f, y, t, dt, *args) → ndarray

Single step of the classic 4th-order Runge-Kutta method for deterministic ODEs.

ParameterTypeDescription
fcallableDerivative function f(y, t, *args) → dy/dt
yndarrayCurrent state vector
tfloatCurrent time
dtfloatTime step
*argsanyExtra arguments passed through to f

RK4 evaluates the derivative at four points within the step and takes a weighted average. Accuracy is O(dt5) per step — much better than Euler's method (O(dt2)).

fneuler_maruyama_step(f, g, y, t, dt, rng, *args) → ndarray

Single step of the Euler-Maruyama method for stochastic differential equations (SDEs).

y_{n+1} = y_n + f(y, t, *args) · dt + g(y, t, *args) · sqrt(dt) · dW
ParameterTypeDescription
fcallableDrift function f(y, t, *args) → ndarray
gcallableDiffusion function g(y, t, *args) → ndarray
yndarrayCurrent state vector
tfloatCurrent time
dtfloatTime step
rngnumpy.random.GeneratorRandom number generator for Wiener increments
*argsanyExtra arguments passed through to f and g

Used for models where noise enters directly into the state equations (state-dependent noise). For Jansen-Rit — where noise enters through the external input parameter, not the state — rk4_step is used instead.

noise.py

fngaussian_input(n_samples, mean, std, rng) → ndarray

Generate a Gaussian white noise input signal. Used to model stochastic external input arriving from other brain regions.

ParameterTypeDescription
n_samplesintNumber of samples to generate
meanfloatMean of the distribution (e.g. 220 Hz for Jansen-Rit)
stdfloatStandard deviation (e.g. 22 Hz for Jansen-Rit)
rngnumpy.random.GeneratorRandom number generator for reproducibility
Design principle All functions are stateless, pickle-safe, and take explicit rng parameters instead of using global random state. This ensures reproducible simulations and safe parallel execution for future model fitting.