cleo.ioproc module#
Classes and functions for constructing and configuring an IOProcessor
.
- class cleo.ioproc.ConstantDelay(delay_ms: float)[source]#
Bases:
cleo.ioproc.delays.Delay
Simply adds a constant delay to the computation
- Parameters
delay_ms (float) – Desired delay in milliseconds
- class cleo.ioproc.FiringRateEstimator(tau_ms: float, sample_period_ms: float, **kwargs)[source]#
Bases:
cleo.ioproc.base.ProcessingBlock
Exponential filter to estimate firing rate.
Requires sample_time_ms kwarg when process is called.
- Parameters
tau_ms (float) – Time constant of filter
sample_period_ms (float) – Sampling period in milliseconds
- compute_output(input: nptyping.types._ndarray.NDArray[Any, nptyping.types._number.UInt], **kwargs) nptyping.types._ndarray.NDArray[Any, nptyping.types._number.Float] [source]#
Estimate firing rate given past and current spikes.
- Parameters
input (NDArray[(n,), np.uint]) – n-length vector of spike counts
- Keyword Arguments
sample_time_ms (float) – Time measurement was taken in milliseconds
- Returns
n-length vector of firing rates
- Return type
NDArray[(n,), float]
- t_in_ms: list[float]#
The walltime the block received each input. Only recorded if
save_history
- t_out_ms: list[float]#
The walltime of each of the block’s outputs. Only recorded if
save_history
- values: list[Any]#
Each of the block’s outputs. Only recorded if
save_history
- class cleo.ioproc.GaussianDelay(loc: float, scale: float)[source]#
Bases:
cleo.ioproc.delays.Delay
Generates normal-distributed delay.
Will return 0 when a negative value is sampled.
- Parameters
loc (float) – Center of distribution
scale (float) – Standard deviation of delay distribution
- class cleo.ioproc.LatencyIOProcessor(sample_period_ms: float, **kwargs)[source]#
Bases:
cleo.base.IOProcessor
IOProcessor capable of delivering stimulation some time after measurement.
- Parameters
sample_period_ms (float) – Determines how frequently samples are taken from the network.
- Keyword Arguments
sampling (str) –
“fixed” or “when idle”; “fixed” by default
”fixed” sampling means samples are taken on a fixed schedule, with no exceptions.
”when idle” sampling means no samples are taken before the previous sample’s output has been delivered. A sample is taken ASAP after an over-period computation: otherwise remains on schedule.
processing (str) –
“parallel” or “serial”; “parallel” by default
”parallel” computes the output time by adding the delay for a sample onto the sample time, so if the delay is 2 ms, for example, while the sample period is only 1 ms, some of the processing is happening in parallel. Output order matches input order even if the computed output time for a sample is sooner than that for a previous sample.
”serial” computes the output time by adding the delay for a sample onto the output time of the previous sample, rather than the sampling time. Note this may be of limited utility because it essentially means the entire round trip cannot be in parallel at all. More realistic is that simply each block or phase of computation must be serial. If anyone cares enough about this, it will have to be implemented in the future.
Note
It doesn’t make much sense to combine parallel computation with “when idle” sampling, because “when idle” sampling only produces one sample at a time to process.
- Raises
ValueError – For invalid sampling or processing kwargs
- get_ctrl_signal(query_time_ms)[source]#
Get per-stimulator control signal from the
IOProcessor
.- Parameters
query_time_ms (float) – Current simulation time.
- Returns
A {‘stimulator_name’: value} dictionary for updating stimulators.
- Return type
dict
- is_sampling_now(query_time_ms)[source]#
Determines whether the processor will take a sample at this timestep.
- Parameters
time (Brian 2 temporal Unit) – Current timestep.
- Return type
bool
- abstract process(state_dict: dict, sample_time_ms: float) Tuple[dict, float] [source]#
Process network state to generate output to update stimulators.
This is the function the user must implement to define the signal processing pipeline.
- Parameters
state_dict (dict) – {recorder_name: state} dictionary from
get_state()
time_ms (float) –
- Returns
{‘stim_name’: ctrl_signal} dictionary and output time in milliseconds.
- Return type
Tuple[dict, float]
- put_state(state_dict: dict, sample_time_ms: float)[source]#
Deliver network state to the
IOProcessor
.- Parameters
state_dict (dict) – A dictionary of recorder measurements, as returned by
get_state()
sample_time_ms (float) – The current simulation timestep. Essential for simulating control latency and for time-varying control.
- t_samp_ms: list[float]#
Record of sampling times—each time
put_state()
is called.
- class cleo.ioproc.PIController(ref_signal: callable, Kp: float, Ki: float = 0, sample_period_ms: float = 0, **kwargs: Any)[source]#
Bases:
cleo.ioproc.base.ProcessingBlock
Simple PI controller.
compute_output()
requires asample_time_ms
keyword argument. Only tested on controlling scalar values, but could be easily adapted to controlling a multi-dimensional state.- Parameters
ref_signal (callable) – Must return the target as a function of time in ms
Kp (float) – Gain on the proportional error
Ki (float, optional) – Gain on the integral error, by default 0
sample_period_ms (float, optional) – Rate at which processor takes samples, by default 0. Only used to compute integrated error on first sample
- compute_output(input: float, **kwargs) float [source]#
Compute control input to the system using previously specified gains.
- Parameters
input (Any) – Current system state
- Returns
Control signal
- Return type
float
- ref_signal: callable[[float], Any]#
Callable returning the target as a function of time in ms
- class cleo.ioproc.ProcessingBlock(**kwargs)[source]#
Bases:
abc.ABC
Abstract signal processing stage or control block.
It’s important to use super().__init__(**kwargs) in the base class to use the parent-class logic here.
- Keyword Arguments
delay (Delay) – Delay object which adds to the compute time
- Raises
TypeError – When delay is not a Delay object.
- abstract compute_output(input: Any, **kwargs) Any [source]#
Computes output for given input.
This is where the user will implement the desired functionality of the ProcessingBlock without regard for latency.
- Parameters
- Returns
output
- Return type
Any
- delay: cleo.ioproc.delays.Delay#
The delay object determining compute latency for the block
- process(input: Any, t_in_ms: float, **kwargs) Tuple[Any, float] [source]#
Computes and saves output and output time given input and input time.
The user should implement
compute_output()
for their child classes, which performs the computation itself without regards for timing or saving variables.- Parameters
input (Any) – Data to be processed
t_in_ms (float) – Time the block receives the input data
**kwargs (Any) – Key-value list of arguments passed to
compute_output()
- Returns
output, out time in milliseconds
- Return type
Tuple[Any, float]
- t_in_ms: list[float]#
The walltime the block received each input. Only recorded if
save_history
- t_out_ms: list[float]#
The walltime of each of the block’s outputs. Only recorded if
save_history
- values: list[Any]#
Each of the block’s outputs. Only recorded if
save_history
- class cleo.ioproc.RecordOnlyProcessor(sample_period_ms, **kwargs)[source]#
Bases:
cleo.ioproc.base.LatencyIOProcessor
Take samples without performing any control.
Use this if all you are doing is recording.
- Parameters
sample_period_ms (float) – Determines how frequently samples are taken from the network.
- Keyword Arguments
sampling (str) –
“fixed” or “when idle”; “fixed” by default
”fixed” sampling means samples are taken on a fixed schedule, with no exceptions.
”when idle” sampling means no samples are taken before the previous sample’s output has been delivered. A sample is taken ASAP after an over-period computation: otherwise remains on schedule.
processing (str) –
“parallel” or “serial”; “parallel” by default
”parallel” computes the output time by adding the delay for a sample onto the sample time, so if the delay is 2 ms, for example, while the sample period is only 1 ms, some of the processing is happening in parallel. Output order matches input order even if the computed output time for a sample is sooner than that for a previous sample.
”serial” computes the output time by adding the delay for a sample onto the output time of the previous sample, rather than the sampling time. Note this may be of limited utility because it essentially means the entire round trip cannot be in parallel at all. More realistic is that simply each block or phase of computation must be serial. If anyone cares enough about this, it will have to be implemented in the future.
Note
It doesn’t make much sense to combine parallel computation with “when idle” sampling, because “when idle” sampling only produces one sample at a time to process.
- Raises
ValueError – For invalid sampling or processing kwargs
- process(state_dict: dict, sample_time_ms: float) Tuple[dict, float] [source]#
Process network state to generate output to update stimulators.
This is the function the user must implement to define the signal processing pipeline.
- Parameters
state_dict (dict) – {recorder_name: state} dictionary from
get_state()
time_ms (float) –
- Returns
{‘stim_name’: ctrl_signal} dictionary and output time in milliseconds.
- Return type
Tuple[dict, float]
- sample_period_ms: float#
Determines how frequently the processor takes samples
- t_samp_ms: list[float]#
Record of sampling times—each time
put_state()
is called.