ezmsg.simbiophys.dynamic_colored_noise#

Dynamic colored noise generation with time-varying spectral exponent.

Generates 1/f^β noise where β can change dynamically based on input. Uses the Kasdin IIR filter method with stateful processing for continuity across chunks.

Reference:

N. Jeremy Kasdin, “Discrete Simulation of Colored Noise and Stochastic Processes and 1/f^α Power Law Noise Generation,” Proceedings of the IEEE, Vol. 83, No. 5, May 1995, pages 802-827.

Functions

compute_kasdin_coefficients(beta, n_poles)[source]#

Compute IIR filter coefficients for 1/f^β noise using Kasdin’s method.

The coefficients are computed using the recurrence relation:

a₀ = 1 aₖ = (k - 1 - β/2) · aₖ₋₁ / k for k = 1, 2, …, n_poles

Parameters:
  • beta (float) – Spectral exponent. Common values: - 0: white noise - 1: pink noise (1/f) - 2: brown/red noise (1/f²) TODO: jit / vectorize over multiple values of beta

  • n_poles (int) – Number of IIR filter poles. More poles extend accuracy to lower frequencies but increase computation. 5 is a reasonable default.

Return type:

ndarray[tuple[Any, ...], dtype[float64]]

Returns:

Array of shape (n_poles,) containing filter coefficients a₁ through aₙ.

Classes

class ColoredNoiseFilterState(delay_line, coeffs)[source]#

Bases: object

State for a single channel’s colored noise filter.

Parameters:
delay_line: ndarray[tuple[Any, ...], dtype[float64]]#

Previous output samples (filter memory).

coeffs: ndarray[tuple[Any, ...], dtype[float64]]#

Current filter coefficients (exponentially smoothed).

__init__(delay_line, coeffs)#
Parameters:
Return type:

None

class DynamicColoredNoiseSettings(output_fs=None, n_poles=5, smoothing_tau=0.01, initial_beta=1.0, scale=1.0, seed=None)[source]#

Bases: Settings

Parameters:
output_fs: float | None = None#

Output sampling rate in Hz. If None, output rate matches input rate.

n_poles: int = 5#

Number of IIR filter poles. More poles extend accuracy to lower frequencies. Default 5 provides good balance.

smoothing_tau: float = 0.01#

Time constant (in seconds) for exponential smoothing of coefficient changes. Coefficients reach ~63% of target in τ seconds, ~95% in 3τ seconds. Set to 0 for instantaneous changes (no smoothing). Default 0.01 (10ms) provides smooth transitions without sluggishness.

initial_beta: float = 1.0#

Initial spectral exponent before any input is received.

scale: float = 1.0#

Output amplitude scaling factor.

seed: int | None = None#

Random seed for reproducibility. If None, uses system entropy.

__init__(output_fs=None, n_poles=5, smoothing_tau=0.01, initial_beta=1.0, scale=1.0, seed=None)#
Parameters:
Return type:

None

class DynamicColoredNoiseState[source]#

Bases: object

filter_states: list[ColoredNoiseFilterState]#

Per-channel filter states.

rng: Generator | None = None#

Random number generator.

sample_remainder: float = 0.0#

Fractional sample accumulator for resampling.

output_gain: float = 0.0#

Time step between output samples (1/output_fs).

samples_per_bin: float = 1.0#

Number of output samples per input sample.

alpha: float = 1.0#

Exponential smoothing factor for coefficient updates.

class DynamicColoredNoiseTransformer(*args, **kwargs)[source]#

Bases: BaseStatefulTransformer[DynamicColoredNoiseSettings, AxisArray, AxisArray, DynamicColoredNoiseState]

Transform spectral exponent (β) input into colored noise output.

Input: AxisArray with β values. Shape can be:
  • (n_samples,) for single-channel output

  • (n_samples, n_channels) for multi-channel output

Output: AxisArray with colored noise having spectral density ~ 1/f^β.

If output_fs is set, output will be resampled to that rate.

The transformer maintains filter state across chunks to ensure continuity (no discontinuities at chunk boundaries). When β changes, coefficients are exponentially smoothed with time constant smoothing_tau to avoid transients.

Each input β sample is treated as a “bin” - all output samples generated within that bin use that β value as the target. Coefficient smoothing handles transitions between bins.

Example

>>> settings = DynamicColoredNoiseSettings(
...     output_fs=30000.0,  # 30 kHz output
...     n_poles=5,
...     smoothing_tau=0.01,  # 10ms time constant
...     initial_beta=1.0
... )
>>> transformer = DynamicColoredNoiseTransformer(settings)
>>> # Input: β values at 100 Hz
>>> beta_input = AxisArray(np.full((100, 2), 1.5), dims=["time", "ch"], ...)
>>> noise_output = transformer(beta_input)  # Output at 30 kHz
class DynamicColoredNoiseUnit(*args, settings=None, **kwargs)[source]#

Bases: BaseTransformerUnit[DynamicColoredNoiseSettings, AxisArray, AxisArray, DynamicColoredNoiseTransformer]

Unit wrapper for DynamicColoredNoiseTransformer.

Parameters:

settings (Settings | None)

SETTINGS#

alias of DynamicColoredNoiseSettings

compute_kasdin_coefficients(beta, n_poles)[source]#

Compute IIR filter coefficients for 1/f^β noise using Kasdin’s method.

The coefficients are computed using the recurrence relation:

a₀ = 1 aₖ = (k - 1 - β/2) · aₖ₋₁ / k for k = 1, 2, …, n_poles

Parameters:
  • beta (float) – Spectral exponent. Common values: - 0: white noise - 1: pink noise (1/f) - 2: brown/red noise (1/f²) TODO: jit / vectorize over multiple values of beta

  • n_poles (int) – Number of IIR filter poles. More poles extend accuracy to lower frequencies but increase computation. 5 is a reasonable default.

Return type:

ndarray[tuple[Any, ...], dtype[float64]]

Returns:

Array of shape (n_poles,) containing filter coefficients a₁ through aₙ.

class ColoredNoiseFilterState(delay_line, coeffs)[source]#

Bases: object

State for a single channel’s colored noise filter.

Parameters:
delay_line: ndarray[tuple[Any, ...], dtype[float64]]#

Previous output samples (filter memory).

coeffs: ndarray[tuple[Any, ...], dtype[float64]]#

Current filter coefficients (exponentially smoothed).

__init__(delay_line, coeffs)#
Parameters:
Return type:

None

class DynamicColoredNoiseSettings(output_fs=None, n_poles=5, smoothing_tau=0.01, initial_beta=1.0, scale=1.0, seed=None)[source]#

Bases: Settings

Parameters:
output_fs: float | None = None#

Output sampling rate in Hz. If None, output rate matches input rate.

n_poles: int = 5#

Number of IIR filter poles. More poles extend accuracy to lower frequencies. Default 5 provides good balance.

smoothing_tau: float = 0.01#

Time constant (in seconds) for exponential smoothing of coefficient changes. Coefficients reach ~63% of target in τ seconds, ~95% in 3τ seconds. Set to 0 for instantaneous changes (no smoothing). Default 0.01 (10ms) provides smooth transitions without sluggishness.

initial_beta: float = 1.0#

Initial spectral exponent before any input is received.

scale: float = 1.0#

Output amplitude scaling factor.

seed: int | None = None#

Random seed for reproducibility. If None, uses system entropy.

__init__(output_fs=None, n_poles=5, smoothing_tau=0.01, initial_beta=1.0, scale=1.0, seed=None)#
Parameters:
Return type:

None

class DynamicColoredNoiseState[source]#

Bases: object

filter_states: list[ColoredNoiseFilterState]#

Per-channel filter states.

rng: Generator | None = None#

Random number generator.

sample_remainder: float = 0.0#

Fractional sample accumulator for resampling.

output_gain: float = 0.0#

Time step between output samples (1/output_fs).

samples_per_bin: float = 1.0#

Number of output samples per input sample.

alpha: float = 1.0#

Exponential smoothing factor for coefficient updates.

class DynamicColoredNoiseTransformer(*args, **kwargs)[source]#

Bases: BaseStatefulTransformer[DynamicColoredNoiseSettings, AxisArray, AxisArray, DynamicColoredNoiseState]

Transform spectral exponent (β) input into colored noise output.

Input: AxisArray with β values. Shape can be:
  • (n_samples,) for single-channel output

  • (n_samples, n_channels) for multi-channel output

Output: AxisArray with colored noise having spectral density ~ 1/f^β.

If output_fs is set, output will be resampled to that rate.

The transformer maintains filter state across chunks to ensure continuity (no discontinuities at chunk boundaries). When β changes, coefficients are exponentially smoothed with time constant smoothing_tau to avoid transients.

Each input β sample is treated as a “bin” - all output samples generated within that bin use that β value as the target. Coefficient smoothing handles transitions between bins.

Example

>>> settings = DynamicColoredNoiseSettings(
...     output_fs=30000.0,  # 30 kHz output
...     n_poles=5,
...     smoothing_tau=0.01,  # 10ms time constant
...     initial_beta=1.0
... )
>>> transformer = DynamicColoredNoiseTransformer(settings)
>>> # Input: β values at 100 Hz
>>> beta_input = AxisArray(np.full((100, 2), 1.5), dims=["time", "ch"], ...)
>>> noise_output = transformer(beta_input)  # Output at 30 kHz
class DynamicColoredNoiseUnit(*args, settings=None, **kwargs)[source]#

Bases: BaseTransformerUnit[DynamicColoredNoiseSettings, AxisArray, AxisArray, DynamicColoredNoiseTransformer]

Unit wrapper for DynamicColoredNoiseTransformer.

Parameters:

settings (Settings | None)

SETTINGS#

alias of DynamicColoredNoiseSettings