Source code for cleo.ioproc.observers
from typing import Any
import numpy as np
from nptyping import NDArray
from cleo.ioproc.base import ProcessingBlock
[docs]
class FiringRateEstimator(ProcessingBlock):
"""Exponential filter to estimate firing rate.
Requires `sample_time_ms` kwarg when process is called.
"""
def __init__(self, tau_ms: float, sample_period_ms: float, **kwargs):
"""
Parameters
----------
tau_ms : float
Time constant of filter
sample_period_ms : float
Sampling period in milliseconds
"""
super().__init__(**kwargs)
self.tau_s = tau_ms / 1000
self.T_s = sample_period_ms / 1000
self.alpha = np.exp(-sample_period_ms / tau_ms)
self.prev_rate = None
self.prev_time_ms = None
[docs]
def compute_output(
self, input: NDArray[(Any,), np.uint], **kwargs
) -> NDArray[(Any,), float]:
"""Estimate firing rate given past and current spikes.
Parameters
----------
input: NDArray[(n,), np.uint]
n-length vector of spike counts
Keyword args
------------
sample_time_ms: float
Time measurement was taken in milliseconds
Returns
-------
NDArray[(n,), float]
n-length vector of firing rates
"""
time_ms = kwargs["sample_time_ms"]
if self.prev_rate is None:
self.prev_rate = np.zeros(input.shape)
if self.prev_time_ms is None:
self.prev_time_ms = time_ms - self.T_s * 1000
intersample_period_s = (time_ms - self.prev_time_ms) / 1000
alpha = np.exp(-intersample_period_s / self.tau_s)
curr_rate = self.prev_rate * alpha + (1 - alpha) * input / intersample_period_s
self.prev_rate = curr_rate
self.prev_time_ms = time_ms
return curr_rate