Reference#

cleosim module#

class cleosim.CLSimulator(brian_network: brian2.core.network.Network)[source]#

Bases: object

The centerpiece of cleosim. Integrates simulation components and runs.

Parameters

brian_network (Network) – The Brian network forming the core model

get_state() dict[source]#

Return current recorder measurements.

Returns

A dictionary of name: state pairs for all recorders in the simulator.

Return type

dict

inject_device(device: cleosim.base.InterfaceDevice, *neuron_groups: brian2.groups.neurongroup.NeuronGroup, **kwparams: Any) None[source]#

Inject InterfaceDevice into the network, connecting to specified neurons.

Calls connect_to_neuron_group() for each group with kwparams and adds the device’s brian_objects to the simulator’s network.

Automatically called by inject_recorder() and inject_stimulator().

Parameters

device (InterfaceDevice) – Device to inject

inject_recorder(recorder: cleosim.base.Recorder, *neuron_groups: brian2.groups.neurongroup.NeuronGroup, **kwparams) None[source]#

Inject recorder into given neuron groups.

Recorder.connect_to_neuron_group() is called for each group.

Parameters
  • recorder (Recorder) – The recorder to inject into the simulation

  • *neuron_groups (NeuronGroup) – The groups to inject the recorder into

  • **kwparams (any) – Passed on to Recorder.connect_to_neuron_group() function. Necessary for parameters that can vary by neuron group, such as inhibitory/excitatory cell type

inject_stimulator(stimulator: cleosim.base.Stimulator, *neuron_groups: brian2.groups.neurongroup.NeuronGroup, **kwparams) None[source]#

Inject stimulator into given neuron groups.

Stimulator.connect_to_neuron_group() is called for each group.

Parameters
  • stimulator (Stimulator) – The stimulator to inject

  • *neuron_groups (NeuronGroup) – The groups to inject the stimulator into

  • **kwparams (any) – Passed on to Stimulator.connect_to_neuron_group() function. Necessary for parameters that can vary by neuron group, such as opsin expression levels.

io_processor: cleosim.base.IOProcessor#
network: brian2.core.network.Network#
recorders = 'set[Recorder]'#
reset(**kwargs)[source]#

Reset the simulator to a neutral state

Restores the Brian Network to where it was when the CLSimulator was last modified (last injection, IOProcessor change). Calls reset() on stimulators, recorders, and IOProcessor.

run(duration: brian2.units.fundamentalunits.Quantity, **kwparams) None[source]#

Run simulation.

Parameters
  • duration (brian2 temporal Quantity) – Length of simulation

  • **kwparams (additional arguments passed to brian2.run()) – level has a default value of 1

set_io_processor(io_processor, communication_period=None) None[source]#

Set simulator IO processor

Will replace any previous IOProcessor so there is only one at a time. A Brian NetworkOperation is created to govern communication between the Network and the IOProcessor.

Parameters

io_processor (IOProcessor) –

stimulators = 'set[Stimulator]'#
update_stimulators(ctrl_signals) None[source]#

Update stimulators with output from the IOProcessor

Parameters

ctrl_signals (dict) – {stimulator_name: ctrl_signal} dictionary with values to update each stimulator.

class cleosim.IOProcessor[source]#

Bases: abc.ABC

Abstract class for implementing sampling, signal processing and control

This must be implemented by the user with their desired closed-loop use case, though most users will find the LatencyIOProcessor() class more useful, since delay handling is already defined.

abstract get_ctrl_signal(time) dict[source]#

Get per-stimulator control signal from the IOProcessor.

Parameters

time (Brian 2 temporal Unit) – Current timestep

Returns

A {‘stimulator_name’: value} dictionary for updating stimulators.

Return type

dict

abstract is_sampling_now(time) bool[source]#

Determines whether the processor will take a sample at this timestep.

Parameters

time (Brian 2 temporal Unit) – Current timestep.

Return type

bool

abstract put_state(state_dict: dict, time) None[source]#

Deliver network state to the IOProcessor.

Parameters
  • state_dict (dict) – A dictionary of recorder measurements, as returned by get_state()

  • time (brian2 temporal Unit) – The current simulation timestep. Essential for simulating control latency and for time-varying control.

reset(**kwargs) None[source]#
sample_period_ms: float#

Determines how frequently the processor takes samples

class cleosim.InterfaceDevice(name: str)[source]#

Bases: abc.ABC

Base class for devices to be injected into the network

Parameters

name (str) – Unique identifier for the device.

add_self_to_plot(ax: mpl_toolkits.mplot3d.axes3d.Axes3D, axis_scale_unit: brian2.units.fundamentalunits.Unit, **kwargs) list[matplotlib.artist.Artist][source]#

Add device to an existing plot

Should only be called by plot().

Parameters
  • ax (Axes3D) – The existing matplotlib Axes object

  • axis_scale_unit (Unit) – The unit used to label axes and define chart limits

  • **kwargs (optional) –

Returns

A list of artists used to render the device. Needed for use in conjunction with VideoVisualizer.

Return type

list[Artist]

brian_objects: set#

All the Brian objects added to the network by this device. Must be kept up-to-date in connect_to_neuron_group() and other functions so that those objects can be automatically added to the network when the device is injected.

abstract connect_to_neuron_group(neuron_group: brian2.groups.neurongroup.NeuronGroup, **kwparams) None[source]#

Connect device to given neuron_group.

If your device introduces any objects which Brian must keep track of, such as a NeuronGroup, Synapses, or Monitor, make sure to add these to self.brian_objects.

Parameters
  • neuron_group (NeuronGroup) –

  • **kwparams (optional, passed from inject_recorder or) – inject_stimulator

init_for_simulator(simulator: cleosim.base.CLSimulator) None[source]#

Initialize device for simulator on initial injection

This function is called only the first time a device is injected into a simulator and performs any operations that are independent of the individual neuron groups it is connected to.

Parameters

simulator (CLSimulator) – simulator being injected into

name: str#

Unique identifier for device. Used as a key in output/input dicts

sim: cleosim.base.CLSimulator#

The simulator the device is injected into

update_artists(*args, **kwargs) list[matplotlib.artist.Artist][source]#

Update the artists used to render the device

Used to set the artists’ state at every frame of a video visualization. The current state would be passed in *args or **kwargs

Parameters

artists (list[Artist]) – the artists used to render the device originally, i.e., which were returned from the first add_self_to_plot() call.

Returns

The artists that were actually updated. Needed for efficient blit rendering, where only updated artists are re-rendered.

Return type

list[Artist]

class cleosim.Recorder(name: str)[source]#

Bases: cleosim.base.InterfaceDevice

Device for taking measurements of the network.

Parameters

name (str) – Unique identifier for the device.

brian_objects: set#

All the Brian objects added to the network by this device. Must be kept up-to-date in connect_to_neuron_group() and other functions so that those objects can be automatically added to the network when the device is injected.

abstract get_state() Any[source]#

Return current measurement.

name: str#

Unique identifier for device. Used as a key in output/input dicts

reset(**kwargs) None[source]#

Reset the recording device to a neutral state

sim: cleosim.base.CLSimulator#

The simulator the device is injected into

class cleosim.Stimulator(name: str, default_value, save_history: bool = False)[source]#

Bases: cleosim.base.InterfaceDevice

Device for manipulating the network

Parameters
default_value: Any#

The default value of the device—used on initialization and on reset()

init_for_simulator(simulator: cleosim.base.CLSimulator) None[source]#

Initialize device for simulator on initial injection

This function is called only the first time a device is injected into a simulator and performs any operations that are independent of the individual neuron groups it is connected to.

Parameters

simulator (CLSimulator) – simulator being injected into

reset(**kwargs) None[source]#

Reset the stimulator device to a neutral state

save_history: bool#

Determines whether t_ms and values are recorded

t_ms: list[float]#

Times stimulator was updated, stored if save_history

update(ctrl_signal) None[source]#

Set the stimulator value.

By default this simply sets value to ctrl_signal. You will want to implement this method if your stimulator requires additional logic. Use super.update(self, value) to preserve the self.value attribute logic

Parameters

ctrl_signal (any) – The value the stimulator is to take.

value: Any#

The current value of the stimulator device

values: list[Any]#

Values taken by the stimulator at each update() call, stored if save_history

cleosim.coordinates module#

Contains functions for assigning neuron coordinates and visualizing

cleosim.coordinates.assign_coords(neuron_group: brian2.groups.neurongroup.NeuronGroup, x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray, unit: brian2.units.fundamentalunits.Unit = mmetre)[source]#

Assign arbitrary coordinates to neuron group.

Parameters
  • neuron_group (NeuronGroup) – neurons to be assigned coordinates

  • x (np.ndarray) – x positions to assign (preferably 1D with no unit)

  • y (np.ndarray) – y positions to assign (preferably 1D with no unit)

  • z (np.ndarray) – z positions to assign (preferably 1D with no unit)

  • unit (Unit, optional) – Brian unit determining what scale to use for coordinates, by default mm

cleosim.coordinates.assign_coords_grid_rect_prism(neuron_group: brian2.groups.neurongroup.NeuronGroup, xlim: Tuple[float, float], ylim: Tuple[float, float], zlim: Tuple[float, float], shape: Tuple[int, int, int], unit: brian2.units.fundamentalunits.Unit = mmetre) None[source]#

Assign grid coordinates to neurons in a rectangular grid

Parameters
  • neuron_group (NeuronGroup) – The neuron group to assign coordinates to

  • xlim (Tuple[float, float]) – xmin, xmax, with no unit

  • ylim (Tuple[float, float]) – ymin, ymax, with no unit

  • zlim (Tuple[float, float]) – zmin, zmax with no unit

  • shape (Tuple[int, int, int]) – n_x, n_y, n_z tuple representing the shape of the resulting grid

  • unit (Unit, optional) – Brian unit determining what scale to use for coordinates, by default mm

Raises

ValueError – When the shape is incompatible with the number of neurons in the group

cleosim.coordinates.assign_coords_rand_cylinder(neuron_group: brian2.groups.neurongroup.NeuronGroup, xyz_start: Tuple[float, float, float], xyz_end: Tuple[float, float, float], radius: float, unit: brian2.units.fundamentalunits.Unit = mmetre) None[source]#

Assign random coordinates within a cylinder.

Parameters
  • neuron_group (NeuronGroup) – neurons to assign coordinates to

  • xyz_start (Tuple[float, float, float]) – starting position of cylinder without unit

  • xyz_end (Tuple[float, float, float]) – ending position of cylinder without unit

  • radius (float) – radius of cylinder without unit

  • unit (Unit, optional) – Brian unit to scale other params, by default mm

cleosim.coordinates.assign_coords_rand_rect_prism(neuron_group: brian2.groups.neurongroup.NeuronGroup, xlim: Tuple[float, float], ylim: Tuple[float, float], zlim: Tuple[float, float], unit: brian2.units.fundamentalunits.Unit = mmetre) None[source]#

Assign random coordinates to neurons within a rectangular prism

Parameters
  • neuron_group (NeuronGroup) – neurons to assign coordinates to

  • xlim (Tuple[float, float]) – xmin, xmax without unit

  • ylim (Tuple[float, float]) – ymin, ymax without unit

  • zlim (Tuple[float, float]) – zmin, zmax without unit

  • unit (Unit, optional) – Brian unit to specify scale implied in limits, by default mm

cleosim.coordinates.assign_coords_uniform_cylinder(neuron_group: brian2.groups.neurongroup.NeuronGroup, xyz_start: Tuple[float, float, float], xyz_end: Tuple[float, float, float], radius: float, unit: brian2.units.fundamentalunits.Unit = mmetre) None[source]#

Assign uniformly spaced coordinates within a cylinder.

Parameters
  • neuron_group (NeuronGroup) – neurons to assign coordinates to

  • xyz_start (Tuple[float, float, float]) – starting position of cylinder without unit

  • xyz_end (Tuple[float, float, float]) – ending position of cylinder without unit

  • radius (float) – radius of cylinder without unit

  • unit (Unit, optional) – Brian unit to scale other params, by default mm

cleosim.electrodes module#

Contains probes, coordinate convenience functions, signals, spiking, and LFP

class cleosim.electrodes.MultiUnitSpiking(name: str, perfect_detection_radius: brian2.units.fundamentalunits.Quantity, half_detection_radius: Optional[brian2.units.fundamentalunits.Quantity] = None, cutoff_probability: float = 0.01, save_history: bool = False)[source]#

Bases: cleosim.electrodes.spiking.Spiking

Detects spikes per channel, that is, unsorted.

Parameters
  • name (str) – Unique identifier for signal

  • perfect_detection_radius (Quantity) – Radius (with Brian unit) within which all spikes are detected

  • half_detection_radius (Quantity, optional) – Radius (with Brian unit) within which half of all spikes are detected

  • cutoff_probability (float, optional) – Spike detection probability below which neurons will not be considered, by default 0.01. For computational efficiency.

  • save_history (bool, optional) – If True, will save t_ms (spike times), i (neuron or channel index), and t_samp_ms (sample times) as attributes. By default False

connect_to_neuron_group(neuron_group: brian2.groups.neurongroup.NeuronGroup, **kwparams) None[source]#

Configure signal to record from specified neuron group

Parameters

neuron_group (NeuronGroup) – group to record from

cutoff_probability: float#

Spike detection probability below which neurons will not be considered. For computational efficiency.

get_state() tuple[NDArray[Any, ..., UInt[64]], NDArray[Any, ..., Float[64]], NDArray[Any, ..., UInt[64]]][source]#

Return spikes since method was last called (i, t_ms, y)

Returns

(i, t_ms, y) where i is channel (for multi-unit) or neuron (for sorted) spike indices, t_ms is spike times, and y is a spike count vector suitable for control- theoretic uses—i.e., a 0 for every channel/neuron that hasn’t spiked and a 1 for a single spike.

Return type

tuple[NDArray[np.uint], NDArray[float], NDArray[np.uint]]

half_detection_radius: Quantity#

Radius (with Brian unit) within which half of all spikes are detected

i: NDArray[Any, np.uint]#

Channel (for multi-unit) or neuron (for sorted) indices of spikes, stored if save_history

i_probe_by_i_ng: bidict#

(neuron_group, i_ng) keys, i_probe values. bidict for converting between neuron group indices and the indices the probe uses

perfect_detection_radius: Quantity#

Radius (with Brian unit) within which all spikes are detected

save_history: bool#

Determines whether t_ms, i, and t_samp_ms are recorded

t_ms: NDArray[Any, float]#

Spike times in ms, stored if save_history

t_samp_ms: NDArray[Any, float]#

Sample times in ms when each spike was recorded, stored if save_history

class cleosim.electrodes.Probe(name: str, coords: brian2.units.fundamentalunits.Quantity, signals: collections.abc.Iterable[cleosim.electrodes.probes.Signal] = [])[source]#

Bases: cleosim.base.Recorder

Picks up specified signals across an array of electrodes.

Visualization kwargs
  • marker (str, optional) – The marker used to represent each contact. “x” by default.

  • size (float, optional) – The size of each contact marker. 40 by default.

  • color (Any, optional) – The color of contact markers. “xkcd:dark gray” by default.

Parameters
  • name (str) – Unique identifier for device

  • coords (Quantity) – Coordinates of n electrodes. Must be an n x 3 array (with unit) where columns represent x, y, and z

  • signals (Iterable[Signal], optional) – Signals to record with probe, by default []. Can be specified later with add_signals().

Raises

ValueError – When coords aren’t n x 3

add_self_to_plot(ax: mpl_toolkits.mplot3d.axes3d.Axes3D, axis_scale_unit: brian2.units.fundamentalunits.Unit, **kwargs) list[matplotlib.artist.Artist][source]#

Add device to an existing plot

Should only be called by plot().

Parameters
  • ax (Axes3D) – The existing matplotlib Axes object

  • axis_scale_unit (Unit) – The unit used to label axes and define chart limits

  • **kwargs (optional) –

Returns

A list of artists used to render the device. Needed for use in conjunction with VideoVisualizer.

Return type

list[Artist]

add_signals(*signals: cleosim.electrodes.probes.Signal) None[source]#

Add signals to the probe for recording

Parameters

*signals (Signal) – signals to add

connect_to_neuron_group(neuron_group: brian2.groups.neurongroup.NeuronGroup, **kwparams: Any) None[source]#

Configure probe to record from given neuron group

Will call Signal.connect_to_neuron_group() for each signal

Parameters
  • neuron_group (NeuronGroup) – neuron group to connect to, i.e., record from

  • **kwparams (Any) – Passed in to signals’ connect functions, needed for some signals

coords: Quantity#

n x 3 array (with Brian length unit) specifying contact locations

get_state() dict[source]#

Get current state from probe, i.e., all signals

Returns

{‘signal_name’: value} dict with signal states

Return type

dict

n: int#

Number of electrode contacts in the probe

reset(**kwargs)[source]#

Reset the probe to a neutral state

Calls reset() on each signal

signals: list[Signal]#

Signals recorded by the probe

property xs: brian2.units.fundamentalunits.Quantity#

x coordinates of recording contacts

Returns

x coordinates represented as a Brian quantity, that is, including units. Should be like a 1D array.

Return type

Quantity

property ys: brian2.units.fundamentalunits.Quantity#

y coordinates of recording contacts

Returns

y coordinates represented as a Brian quantity, that is, including units. Should be like a 1D array.

Return type

Quantity

property zs: brian2.units.fundamentalunits.Quantity#

z coordinates of recording contacts

Returns

z coordinates represented as a Brian quantity, that is, including units. Should be like a 1D array.

Return type

Quantity

class cleosim.electrodes.Signal(name: str)[source]#

Bases: abc.ABC

Base class representing something an electrode can record

Constructor must be called at beginning of children constructors.

Parameters

name (str) – Unique identifier used when reading the state from the network

brian_objects: set#

All Brian objects created by the signal. Must be kept up-to-date for automatic injection into the network

abstract connect_to_neuron_group(neuron_group: brian2.groups.neurongroup.NeuronGroup, **kwparams)[source]#

Configure signal to record from specified neuron group

Parameters

neuron_group (NeuronGroup) – group to record from

abstract get_state() Any[source]#

Get the signal’s current value

init_for_probe(probe: cleosim.electrodes.probes.Probe) None[source]#

Called when attached to a probe.

Ensures signal can access probe and is only attached to one

Parameters

probe (Probe) – Probe to attach to

Raises

ValueError – When signal already attached to another probe

name: str#

Unique identifier used to organize probe output

probe: cleosim.electrodes.probes.Probe#

The probe the signal is configured to record for.

reset(**kwargs) None[source]#

Reset signal to a neutral state

class cleosim.electrodes.SortedSpiking(name: str, perfect_detection_radius: brian2.units.fundamentalunits.Quantity, half_detection_radius: Optional[brian2.units.fundamentalunits.Quantity] = None, cutoff_probability: float = 0.01, save_history: bool = False)[source]#

Bases: cleosim.electrodes.spiking.Spiking

Detect spikes identified by neuron indices.

The indices used by the probe do not correspond to those coming from neuron groups, since the probe must consider multiple potential groups and within a group ignores those neurons that are too far away to be easily detected.

Parameters
  • name (str) – Unique identifier for signal

  • perfect_detection_radius (Quantity) – Radius (with Brian unit) within which all spikes are detected

  • half_detection_radius (Quantity, optional) – Radius (with Brian unit) within which half of all spikes are detected

  • cutoff_probability (float, optional) – Spike detection probability below which neurons will not be considered, by default 0.01. For computational efficiency.

  • save_history (bool, optional) – If True, will save t_ms (spike times), i (neuron or channel index), and t_samp_ms (sample times) as attributes. By default False

connect_to_neuron_group(neuron_group: brian2.groups.neurongroup.NeuronGroup, **kwparams) None[source]#

Configure sorted spiking signal to record from given neuron group

Parameters

neuron_group (NeuronGroup) – group to record from

cutoff_probability: float#

Spike detection probability below which neurons will not be considered. For computational efficiency.

get_state() tuple[NDArray[Any, ..., UInt[64]], NDArray[Any, ..., Float[64]], NDArray[Any, ..., UInt[64]]][source]#

Return spikes since method was last called (i, t_ms, y)

Returns

(i, t_ms, y) where i is channel (for multi-unit) or neuron (for sorted) spike indices, t_ms is spike times, and y is a spike count vector suitable for control- theoretic uses—i.e., a 0 for every channel/neuron that hasn’t spiked and a 1 for a single spike.

Return type

tuple[NDArray[np.uint], NDArray[float], NDArray[np.uint]]

half_detection_radius: Quantity#

Radius (with Brian unit) within which half of all spikes are detected

i: NDArray[Any, np.uint]#

Channel (for multi-unit) or neuron (for sorted) indices of spikes, stored if save_history

i_probe_by_i_ng: bidict#

(neuron_group, i_ng) keys, i_probe values. bidict for converting between neuron group indices and the indices the probe uses

perfect_detection_radius: Quantity#

Radius (with Brian unit) within which all spikes are detected

save_history: bool#

Determines whether t_ms, i, and t_samp_ms are recorded

t_ms: NDArray[Any, float]#

Spike times in ms, stored if save_history

t_samp_ms: NDArray[Any, float]#

Sample times in ms when each spike was recorded, stored if save_history

class cleosim.electrodes.Spiking(name: str, perfect_detection_radius: brian2.units.fundamentalunits.Quantity, half_detection_radius: Optional[brian2.units.fundamentalunits.Quantity] = None, cutoff_probability: float = 0.01, save_history: bool = False)[source]#

Bases: cleosim.electrodes.probes.Signal

Base class for probabilistically detecting spikes

Parameters
  • name (str) – Unique identifier for signal

  • perfect_detection_radius (Quantity) – Radius (with Brian unit) within which all spikes are detected

  • half_detection_radius (Quantity, optional) – Radius (with Brian unit) within which half of all spikes are detected

  • cutoff_probability (float, optional) – Spike detection probability below which neurons will not be considered, by default 0.01. For computational efficiency.

  • save_history (bool, optional) – If True, will save t_ms (spike times), i (neuron or channel index), and t_samp_ms (sample times) as attributes. By default False

connect_to_neuron_group(neuron_group: brian2.groups.neurongroup.NeuronGroup, **kwparams) numpy.ndarray[source]#

Configure signal to record from specified neuron group

Parameters

neuron_group (NeuronGroup) – Neuron group to record from

Returns

num_neurons_to_consider x num_channels array of spike detection probabilities, for use in subclasses

Return type

np.ndarray

cutoff_probability: float#

Spike detection probability below which neurons will not be considered. For computational efficiency.

abstract get_state() tuple[NDArray[Any, ..., UInt[64]], NDArray[Any, ..., Float[64]], NDArray[Any, ..., UInt[64]]][source]#

Return spikes since method was last called (i, t_ms, y)

Returns

(i, t_ms, y) where i is channel (for multi-unit) or neuron (for sorted) spike indices, t_ms is spike times, and y is a spike count vector suitable for control- theoretic uses—i.e., a 0 for every channel/neuron that hasn’t spiked and a 1 for a single spike.

Return type

tuple[NDArray[np.uint], NDArray[float], NDArray[np.uint]]

half_detection_radius: Quantity#

Radius (with Brian unit) within which half of all spikes are detected

i: NDArray[Any, np.uint]#

Channel (for multi-unit) or neuron (for sorted) indices of spikes, stored if save_history

i_probe_by_i_ng: bidict#

(neuron_group, i_ng) keys, i_probe values. bidict for converting between neuron group indices and the indices the probe uses

perfect_detection_radius: Quantity#

Radius (with Brian unit) within which all spikes are detected

reset(**kwargs) None[source]#

Reset signal to a neutral state

save_history: bool#

Determines whether t_ms, i, and t_samp_ms are recorded

t_ms: NDArray[Any, float]#

Spike times in ms, stored if save_history

t_samp_ms: NDArray[Any, float]#

Sample times in ms when each spike was recorded, stored if save_history

class cleosim.electrodes.TKLFPSignal(name: str, uLFP_threshold_uV: float = 0.001, save_history: bool = False)[source]#

Bases: cleosim.electrodes.probes.Signal

Records the Teleńczuk kernel LFP approximation.

Requires tklfp_type='exc'|'inh' to specify cell type on injection.

An orientation keyword argument can also be specified on injection, which should be an array of shape (n_neurons, 3) representing which way is “up,” that is, towards the surface of the cortex, for each neuron. If a single vector is given, it is taken to be the orientation for all neurons in the group. [0, 0, -1] is the default, meaning the negative z axis is “up.” As stated elsewhere, CLEOSim’s convention is that z=0 corresponds to the cortical surface and increasing z values represent increasing depth.

TKLFP is computed from spikes using the tklfp package.

Parameters
  • name (str) – Unique identifier for signal, used to identify signal output in Probe.get_state()

  • uLFP_threshold_uV (float, optional) – Sets uLFP_threshold_uV, by default 1e-3

  • save_history (bool, optional) – Sets save_history to determine whether output is recorded, by default False

connect_to_neuron_group(neuron_group: brian2.groups.neurongroup.NeuronGroup, **kwparams)[source]#

Configure signal to record from specified neuron group

Parameters

neuron_group (NeuronGroup) – group to record from

get_state() numpy.ndarray[source]#

Get the signal’s current value

init_for_probe(probe: cleosim.electrodes.probes.Probe)[source]#

Called when attached to a probe.

Ensures signal can access probe and is only attached to one

Parameters

probe (Probe) – Probe to attach to

Raises

ValueError – When signal already attached to another probe

lfp_uV: nptyping.types._ndarray.NDArray[Any, Any, nptyping.types._number.Float]#

Approximated LFP from every call to get_state(), recorded if save_history. Shape is (n_samples, n_channels).

reset(**kwargs) None[source]#

Reset signal to a neutral state

save_history: bool#

Whether to record output from every timestep in lfp_uV. Output is stored every time get_state() is called.

t_ms: nptyping.types._ndarray.NDArray[Any, nptyping.types._number.Float]#

Times at which LFP is recorded, in ms, stored if save_history

uLFP_threshold_uV: float#

Threshold, in microvolts, above which the uLFP for a single spike is guaranteed to be considered. This determines the buffer length of past spikes, since the uLFP from a long-past spike becomes negligible and is ignored.

cleosim.electrodes.concat_coords(*coords: brian2.units.fundamentalunits.Quantity) brian2.units.fundamentalunits.Quantity[source]#

Combine multiple coordinate Quantity arrays into one

Parameters

*coords (Quantity) – Multiple coordinate n x 3 Quantity arrays to combine

Returns

A single n x 3 combined Quantity array

Return type

Quantity

cleosim.electrodes.linear_shank_coords(array_length: brian2.units.fundamentalunits.Quantity, channel_count: int, start_location: brian2.units.fundamentalunits.Quantity = array([0., 0., 0.]) * metre, direction: Tuple[float, float, float] = (0, 0, 1)) brian2.units.fundamentalunits.Quantity[source]#

Generate coordinates in a linear pattern

Parameters
  • array_length (Quantity) – Distance from the first to the last contact (with a Brian unit)

  • channel_count (int) – Number of coordinates to generate, i.e. electrode contacts

  • start_location (Quantity, optional) – x, y, z coordinate (with unit) for the start of the electrode array, by default (0, 0, 0)*mm

  • direction (Tuple[float, float, float], optional) – x, y, z vector indicating the direction in which the array extends, by default (0, 0, 1), meaning pointing straight down

Returns

channel_count x 3 array of coordinates, where the 3 columns represent x, y, and z

Return type

Quantity

cleosim.electrodes.poly2_shank_coords(array_length: brian2.units.fundamentalunits.Quantity, channel_count: int, intercol_space: brian2.units.fundamentalunits.Quantity, start_location: brian2.units.fundamentalunits.Quantity = array([0., 0., 0.]) * metre, direction: Tuple[float, float, float] = (0, 0, 1)) brian2.units.fundamentalunits.Quantity[source]#

Generate NeuroNexus-style Poly2 array coordinates

Poly2 refers to 2 parallel columns with staggered contacts. See https://www.neuronexus.com/products/electrode-arrays/up-to-15-mm-depth for more detail.

Parameters
  • array_length (Quantity) – Length from the beginning to the end of the two-column array, as measured in the center

  • channel_count (int) – Total (not per-column) number of coordinates (recording contacts) desired

  • intercol_space (Quantity) – Distance between columns (with Brian unit)

  • start_location (Quantity, optional) – Where to place the beginning of the array, by default (0, 0, 0)*mm

  • direction (Tuple[float, float, float], optional) – x, y, z vector indicating the direction in which the two columns extend; by default (0, 0, 1), meaning straight down.

Returns

channel_count x 3 array of coordinates, where the 3 columns represent x, y, and z

Return type

Quantity

cleosim.electrodes.poly3_shank_coords(array_length: brian2.units.fundamentalunits.Quantity, channel_count: int, intercol_space: brian2.units.fundamentalunits.Quantity, start_location: brian2.units.fundamentalunits.Quantity = array([0., 0., 0.]) * metre, direction: Tuple[float, float, float] = (0, 0, 1)) brian2.units.fundamentalunits.Quantity[source]#

Generate NeuroNexus Poly3-style array coordinates

Poly3 refers to three parallel columns of electrodes. The middle column will be longest if the channel count isn’t divisible by three and the side columns will be centered vertically with respect to the middle.

Parameters
  • array_length (Quantity) – Length from beginning to end of the array as measured along the center column

  • channel_count (int) – Total (not per-column) number of coordinates to generate (i.e., electrode contacts)

  • intercol_space (Quantity) – Spacing between columns, with Brian unit

  • start_location (Quantity, optional) – Location of beginning of the array, that is, the first contact in the center column, by default (0, 0, 0)*mm

  • direction (Tuple[float, float, float], optional) – x, y, z vector indicating the direction along which the array extends, by default (0, 0, 1), meaning straight down

Returns

channel_count x 3 array of coordinates, where the 3 columns represent x, y, and z

Return type

Quantity

cleosim.electrodes.tetrode_shank_coords(array_length: brian2.units.fundamentalunits.Quantity, tetrode_count: int, start_location: brian2.units.fundamentalunits.Quantity = array([0., 0., 0.]) * metre, direction: Tuple[float, float, float] = (0, 0, 1), tetrode_width: brian2.units.fundamentalunits.Quantity = 25. * umetre) brian2.units.fundamentalunits.Quantity[source]#

Generate coordinates for a linear array of tetrodes

See https://www.neuronexus.com/products/electrode-arrays/up-to-15-mm-depth to visualize NeuroNexus-style arrays.

Parameters
  • array_length (Quantity) – Distance from the center of the first tetrode to the last (with a Brian unit)

  • tetrode_count (int) – Number of tetrodes desired

  • start_location (Quantity, optional) – Center location of the first tetrode in the array, by default (0, 0, 0)*mm

  • direction (Tuple[float, float, float], optional) – x, y, z vector determining the direction in which the linear array extends, by default (0, 0, 1), meaning straight down.

  • tetrode_width (Quantity, optional) – Distance between contacts in a single tetrode. Not the diagonal distance, but the length of one side of the square. By default 25*umeter, as in NeuroNexus probes.

Returns

(tetrode_count*4) x 3 array of coordinates, where 3 columns represent x, y, and z

Return type

Quantity

cleosim.electrodes.tile_coords(coords: brian2.units.fundamentalunits.Quantity, num_tiles: int, tile_vector: brian2.units.fundamentalunits.Quantity) brian2.units.fundamentalunits.Quantity[source]#

Tile (repeat) coordinates to produce multi-shank/matrix arrays

Parameters
  • coords (Quantity) – The n x 3 coordinates array to tile

  • num_tiles (int) – Number of times to tile (repeat) the coordinates. For example, if you are tiling linear shank coordinates to produce multi-shank coordinates, this would be the desired number of shanks

  • tile_vector (Quantity) – x, y, z array with Brian unit determining both the length and direction of the tiling

Returns

(n * num_tiles) x 3 array of coordinates, where the 3 columns represent x, y, and z

Return type

Quantity

cleosim.opto module#

Contains opsin models, parameters, and OptogeneticIntervention device

cleosim.opto.ChR2_four_state = {'E': 0. * volt, 'Gb0': 16.1 * hertz, 'Gd1': 105. * hertz, 'Gd2': 13.8 * hertz, 'Gf0': 37.3 * hertz, 'Gr0': 0.33 * hertz, 'g0': 114. * nsiemens, 'gamma': 0.00742, 'k1': 4.15 * khertz, 'k2': 0.868 * khertz, 'kb': 63. * hertz, 'kf': 58.1 * hertz, 'p': 0.833, 'phim': 2.33e+23 * metre ** -2 * second ** -1, 'q': 1.94, 'v0': 43. * mvolt, 'v1': 17.1 * mvolt}#

Parameters for the 4-state ChR2 model.

Taken from try.projectpyrho.org’s default 4-state params.

class cleosim.opto.FourStateModel(params: dict)[source]#

Bases: cleosim.opto.MarkovModel

4-state model from PyRhO (Evans et al. 2016).

rho_rel is channel density relative to standard model fit; modifying it post-injection allows for heterogeneous opsin expression.

IOPTO_VAR_NAME and V_VAR_NAME are substituted on injection.

Parameters

params (dict) – dict defining params in the model

init_opto_syn_vars(opto_syn: brian2.synapses.synapses.Synapses) None[source]#

Initializes appropriate variables in Synapses implementing the model

Can also be used to reset the variables.

Parameters

opto_syn (Synapses) – The synapses object implementing this model

model: str = '\n        dC1/dt = Gd1*O1 + Gr0*C2 - Ga1*C1 : 1 (clock-driven)\n        dO1/dt = Ga1*C1 + Gb*O2 - (Gd1+Gf)*O1 : 1 (clock-driven)\n        dO2/dt = Ga2*C2 + Gf*O1 - (Gd2+Gb)*O2 : 1 (clock-driven)\n        C2 = 1 - C1 - O1 - O2 : 1\n        # dC2/dt = Gd2*O2 - (Gr0+Ga2)*C2 : 1 (clock-driven)\n\n        Theta = int(phi > 0*phi) : 1\n        Hp = Theta * phi**p/(phi**p + phim**p) : 1\n        Ga1 = k1*Hp : hertz\n        Ga2 = k2*Hp : hertz\n        Hq = Theta * phi**q/(phi**q + phim**q) : 1\n        Gf = kf*Hq + Gf0 : hertz\n        Gb = kb*Hq + Gb0 : hertz\n\n        fphi = O1 + gamma*O2 : 1\n        fv = (1 - exp(-(V_VAR_NAME_post-E)/v0)) / -2 : 1\n\n        IOPTO_VAR_NAME_post = -g0*fphi*fv*(V_VAR_NAME_post-E)*rho_rel : ampere (summed)\n        rho_rel : 1\n    '#

Basic Brian model equations string.

Should contain a rho_rel term reflecting relative expression levels. Will likely also contain special NeuronGroup-dependent symbols such as V_VAR_NAME to be replaced on injection in modify_model_and_params_for_ng().

class cleosim.opto.MarkovModel(params: dict)[source]#

Bases: cleosim.opto.OpsinModel

Base class for Markov state models à la Evans et al., 2016

Parameters

params (dict) – dict defining params in the model

required_vars: list[Tuple[str, brian2.units.fundamentalunits.Unit]] = [('Iopto', amp), ('v', volt)]#

Default names of state variables required in the neuron group, along with units, e.g., [(‘Iopto’, amp)].

It is assumed that non-default values can be passed in on injection as a keyword argument [default_name]_var_name=[non_default_name] and that these are found in the model string as [DEFAULT_NAME]_VAR_NAME before replacement.

class cleosim.opto.OpsinModel[source]#

Bases: abc.ABC

Base class for opsin model

init_opto_syn_vars(opto_syn: brian2.synapses.synapses.Synapses) None[source]#

Initializes appropriate variables in Synapses implementing the model

Can also be used to reset the variables.

Parameters

opto_syn (Synapses) – The synapses object implementing this model

model: str#

Basic Brian model equations string.

Should contain a rho_rel term reflecting relative expression levels. Will likely also contain special NeuronGroup-dependent symbols such as V_VAR_NAME to be replaced on injection in modify_model_and_params_for_ng().

modify_model_and_params_for_ng(neuron_group: brian2.groups.neurongroup.NeuronGroup, injct_params: dict, model='class-defined') Tuple[brian2.equations.equations.Equations, dict][source]#

Adapt model for given neuron group on injection

This enables the specification of variable names differently for each neuron group, allowing for custom names and avoiding conflicts.

Parameters
  • neuron_group (NeuronGroup) – NeuronGroup this opsin model is being connected to

  • injct_params (dict) – kwargs passed in on injection, could contain variable names to plug into the model

Keyword Arguments

model (str, optional) – Model to start with, by default that defined for the class. This allows for prior string manipulations before it can be parsed as an Equations object.

Returns

A tuple containing an Equations object and a parameter dictionary, constructed from model and params, respectively, with modified names for use in opto_syns

Return type

Equations, dict

params: dict#

Parameter values for model, passed in as a namespace dict

required_vars: list[Tuple[str, brian2.units.fundamentalunits.Unit]]#

Default names of state variables required in the neuron group, along with units, e.g., [(‘Iopto’, amp)].

It is assumed that non-default values can be passed in on injection as a keyword argument [default_name]_var_name=[non_default_name] and that these are found in the model string as [DEFAULT_NAME]_VAR_NAME before replacement.

class cleosim.opto.OptogeneticIntervention(name: str, opsin_model: cleosim.opto.OpsinModel, light_model_params: dict, location: brian2.units.fundamentalunits.Quantity = array([0., 0., 0.]) * metre, direction: Tuple[float, float, float] = (0, 0, 1), max_Irr0_mW_per_mm2: Optional[float] = None, save_history: bool = False)[source]#

Bases: cleosim.base.Stimulator

Enables optogenetic stimulation of the network.

Essentially “transfects” neurons and provides a light source. Under the hood, it delivers current via a Brian Synapses object.

Requires neurons to have 3D spatial coordinates already assigned. Also requires that the neuron model has a current term (by default Iopto) which is assumed to be positive (unlike the convention in many opsin modeling papers, where the current is described as negative).

See connect_to_neuron_group() for optional keyword parameters that can be specified when calling cleosim.CLSimulator.inject_stimulator().

Visualization kwargs
  • n_points (int, optional) – The number of points used to represent light intensity in space. By default 1e4.

  • T_threshold (float, optional) – The transmittance below which no points are plotted. By default 1e-3.

  • intensity (float, optional) – How bright the light appears, should be between 0 and 1. By default 0.5.

  • rasterized (bool, optional) – Whether to render as rasterized in vector output, True by default. Useful since so many points makes later rendering and editing slow.

Parameters
  • name (str) – Unique identifier for stimulator

  • opsin_model (OpsinModel) – OpsinModel object defining how light affects target neurons. See FourStateModel and ProportionalCurrentModel for examples.

  • light_model_params (dict) – Parameters for the light propagation model in Foutz et al., 2012. See default_blue for an example.

  • location (Quantity, optional) – (x, y, z) coords with Brian unit specifying where to place the base of the light source, by default (0, 0, 0)*mm

  • direction (Tuple[float, float, float], optional) – (x, y, z) vector specifying direction in which light source is pointing, by default (0, 0, 1)

  • max_Irr0_mW_per_mm2 (float, optional) – Set max_Irr0_mW_per_mm2.

  • save_history (bool, optional) – Determines whether values and t_ms are saved.

add_self_to_plot(ax, axis_scale_unit, **kwargs) matplotlib.collections.PathCollection[source]#

Add device to an existing plot

Should only be called by plot().

Parameters
  • ax (Axes3D) – The existing matplotlib Axes object

  • axis_scale_unit (Unit) – The unit used to label axes and define chart limits

  • **kwargs (optional) –

Returns

A list of artists used to render the device. Needed for use in conjunction with VideoVisualizer.

Return type

list[Artist]

connect_to_neuron_group(neuron_group: brian2.groups.neurongroup.NeuronGroup, **kwparams: Any) None[source]#

Configure opsin and light source to stimulate given neuron group.

Parameters

neuron_group (NeuronGroup) – The neuron group to stimulate with the given opsin and light source

Keyword Arguments
  • p_expression (float) – Probability (0 <= p <= 1) that a given neuron in the group will express the opsin. 1 by default.

  • rho_rel (float) – The expression level, relative to the standard model fit, of the opsin. 1 by default. For heterogeneous expression, this would have to be modified in the opsin synapse post-injection, e.g., opto.opto_syns["neuron_group_name"].rho_rel = ...

  • Iopto_var_name (str) – The name of the variable in the neuron group model representing current from the opsin

  • v_var_name (str) – The name of the variable in the neuron group model representing membrane potential

max_Irr0_mW_per_mm2: float#

The maximum irradiance the light source can emit.

Usually determined by hardware in a real experiment.

max_Irr0_mW_per_mm2_viz: float#

Maximum irradiance for visualization purposes.

i.e., the level at or above which the light appears maximally bright. Only relevant in video visualization.

opto_syns: dict[str, Synapses]#

Stores the synapse objects implementing the opsin model, with NeuronGroup name keys and Synapse values.

reset(**kwargs)[source]#

Reset the stimulator device to a neutral state

update(Irr0_mW_per_mm2: float)[source]#

Set the light intensity, in mW/mm2 (without unit)

Parameters

Irr0_mW_per_mm2 (float) – Desired light intensity for light source

update_artists(artists: list[matplotlib.artist.Artist], value, *args, **kwargs) list[matplotlib.artist.Artist][source]#

Update the artists used to render the device

Used to set the artists’ state at every frame of a video visualization. The current state would be passed in *args or **kwargs

Parameters

artists (list[Artist]) – the artists used to render the device originally, i.e., which were returned from the first add_self_to_plot() call.

Returns

The artists that were actually updated. Needed for efficient blit rendering, where only updated artists are re-rendered.

Return type

list[Artist]

class cleosim.opto.ProportionalCurrentModel(Iopto_per_mW_per_mm2: brian2.units.fundamentalunits.Quantity)[source]#

Bases: cleosim.opto.OpsinModel

A simple model delivering current proportional to light intensity

Parameters

Iopto_per_mW_per_mm2 (Quantity) – How much current (in amps or unitless, depending on neuron model) to deliver per mW/mm2

model: str = '\n        IOPTO_VAR_NAME_post = gain * Irr * rho_rel : IOPTO_UNIT (summed)\n        rho_rel : 1\n    '#

Basic Brian model equations string.

Should contain a rho_rel term reflecting relative expression levels. Will likely also contain special NeuronGroup-dependent symbols such as V_VAR_NAME to be replaced on injection in modify_model_and_params_for_ng().

modify_model_and_params_for_ng(neuron_group: brian2.groups.neurongroup.NeuronGroup, injct_params: dict) Tuple[brian2.equations.equations.Equations, dict][source]#

Adapt model for given neuron group on injection

This enables the specification of variable names differently for each neuron group, allowing for custom names and avoiding conflicts.

Parameters
  • neuron_group (NeuronGroup) – NeuronGroup this opsin model is being connected to

  • injct_params (dict) – kwargs passed in on injection, could contain variable names to plug into the model

Keyword Arguments

model (str, optional) – Model to start with, by default that defined for the class. This allows for prior string manipulations before it can be parsed as an Equations object.

Returns

A tuple containing an Equations object and a parameter dictionary, constructed from model and params, respectively, with modified names for use in opto_syns

Return type

Equations, dict

cleosim.opto.default_blue = {'K': 125. * metre ** -1, 'NAfib': 0.37, 'R0': 100. * umetre, 'S': 7370. * metre ** -1, 'ntis': 1.36, 'wavelength': 0.473 * umetre}#

Light parameters for 473 nm wavelength delivered via an optic fiber.

From Foutz et al., 2012

cleosim.processing module#

Classes and functions for constructing and configuring an IOProcessor.

class cleosim.processing.ConstantDelay(delay_ms: float)[source]#

Bases: cleosim.processing.delays.Delay

Simply adds a constant delay to the computation

Parameters

delay_ms (float) – Desired delay in milliseconds

compute()[source]#

Compute delay.

class cleosim.processing.Delay[source]#

Bases: abc.ABC

Abstract base class for computing delays.

abstract compute() float[source]#

Compute delay.

class cleosim.processing.FiringRateEstimator(tau_ms: float, sample_period_ms: float, **kwargs)[source]#

Bases: cleosim.processing.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]

delay: Delay#

The delay object determining compute latency for the block

save_history: bool#

Whether to record t_in_ms, t_out_ms, and values with every timestep

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 cleosim.processing.GaussianDelay(loc: float, scale: float)[source]#

Bases: cleosim.processing.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

compute() float[source]#

Compute delay.

class cleosim.processing.LatencyIOProcessor(sample_period_ms: float, **kwargs)[source]#

Bases: cleosim.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

time (Brian 2 temporal Unit) – Current timestep

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)[source]#

Deliver network state to the IOProcessor.

Parameters
  • state_dict (dict) – A dictionary of recorder measurements, as returned by get_state()

  • time (brian2 temporal Unit) – 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 cleosim.processing.PIController(ref_signal: callable, Kp: float, Ki: float = 0, sample_period_ms: float = 0, **kwargs: Any)[source]#

Bases: cleosim.processing.base.ProcessingBlock

Simple PI controller.

compute_output() requires a sample_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 cleosim.processing.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
  • input (Any) – Data to be processed. Passed in from process().

  • **kwargs (Any) – optional key-value argument pairs passed from process(). Could be used to pass in such values as the IO processor’s walltime or the measurement time for time- dependent functions.

Returns

output

Return type

Any

delay: cleosim.processing.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]

save_history: bool#

Whether to record t_in_ms, t_out_ms, and values with every timestep

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 cleosim.processing.RecordOnlyProcessor(sample_period_ms, **kwargs)[source]#

Bases: cleosim.processing.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.

cleosim.visualization module#

Tools for visualizing models and simulations

class cleosim.visualization.VideoVisualizer(devices: collections.abc.Iterable[Union[cleosim.base.InterfaceDevice, Tuple[cleosim.base.InterfaceDevice, dict]]] = 'all', dt: brian2.units.fundamentalunits.Quantity = 1. * msecond)[source]#

Bases: cleosim.base.InterfaceDevice

Device for visualizing a simulation.

Must be injected after all other devices and before the simulation is run.

Parameters
  • devices (Iterable[Union[InterfaceDevice, Tuple[InterfaceDevice, dict]]], optional) – list of devices or (device, vis_kwargs) tuples to include in the plot, just as in the plot() function, by default “all”, which will include all recorders and stimulators currently injected when this visualizer is injected into the simulator.

  • dt (Brian 2 temporal Quantity, optional) – length of each frame—that is, every dt the visualizer takes a snapshot of the network, by default 1*ms

brian_objects: set#

All the Brian objects added to the network by this device. Must be kept up-to-date in connect_to_neuron_group() and other functions so that those objects can be automatically added to the network when the device is injected.

connect_to_neuron_group(neuron_group: brian2.groups.neurongroup.NeuronGroup, **kwparams) None[source]#

Connect device to given neuron_group.

If your device introduces any objects which Brian must keep track of, such as a NeuronGroup, Synapses, or Monitor, make sure to add these to self.brian_objects.

Parameters
  • neuron_group (NeuronGroup) –

  • **kwparams (optional, passed from inject_recorder or) – inject_stimulator

generate_Animation(plotargs: dict, slowdown_factor: float = 10, **figargs: Any) matplotlib.animation.Animation[source]#

Create a matplotlib Animation object from the recorded simulation

Parameters
  • plotargs (dict) – dictionary of arguments as taken by plot(). can include xlim, ylim, zlim, colors, axis_scale_unit, invert_z, and/or scatterargs. neuron groups and devices are automatically added and **figargs are specified separately.

  • slowdown_factor (float, optional) – how much slower the animation will be rendered, as a multiple of real-time, by default 10

  • **figargs (Any, optional) – keyword arguments passed to plt.figure(), such as figsize

Returns

An Animation object capturing the desired visualization. See matplotlib’s docs for saving and rendering options.

Return type

matplotlib.animation.Animation

init_for_simulator(simulator: cleosim.base.CLSimulator)[source]#

Initialize device for simulator on initial injection

This function is called only the first time a device is injected into a simulator and performs any operations that are independent of the individual neuron groups it is connected to.

Parameters

simulator (CLSimulator) – simulator being injected into

name: str#

Unique identifier for device. Used as a key in output/input dicts

sim: cleosim.base.CLSimulator#

The simulator the device is injected into

cleosim.visualization.plot(*neuron_groups: brian2.groups.neurongroup.NeuronGroup, xlim: Optional[Tuple[float, float]] = None, ylim: Optional[Tuple[float, float]] = None, zlim: Optional[Tuple[float, float]] = None, colors: Optional[collections.abc.Iterable] = None, axis_scale_unit: brian2.units.fundamentalunits.Unit = mmetre, devices: collections.abc.Iterable[Union[cleosim.base.InterfaceDevice, Tuple[cleosim.base.InterfaceDevice, dict]]] = [], invert_z: bool = True, scatterargs: dict = {}, **figargs: Any) None[source]#

Visualize neurons and interface devices

Parameters
  • xlim (Tuple[float, float], optional) – xlim for plot, determined automatically by default

  • ylim (Tuple[float, float], optional) – ylim for plot, determined automatically by default

  • zlim (Tuple[float, float], optional) – zlim for plot, determined automatically by default

  • colors (Iterable, optional) – colors, one for each neuron group, automatically determined by default

  • axis_scale_unit (Unit, optional) – Brian unit to scale lim params, by default mm

  • devices (Iterable[Union[InterfaceDevice, Tuple[InterfaceDevice, dict]]], optional) – devices to add to the plot or (device, kwargs) tuples. add_self_to_plot() is called for each, using the kwargs dict if given. By default []

  • invert_z (bool, optional) – whether to invert z-axis, by default True to reflect the convention that +z represents depth from cortex surface

  • scatterargs (dict, optional) – arguments passed to plt.scatter() for each neuron group, such as marker

  • **figargs (Any, optional) – keyword arguments passed to plt.figure(), such as figsize

Raises

ValueError – When neuron group doesn’t have x, y, and z already defined

cleosim.recorders module#

Contains basic recorders.

class cleosim.recorders.GroundTruthSpikeRecorder(name)[source]#

Bases: cleosim.base.Recorder

Reports the number of spikes seen since last queried for each neuron.

This amounts effectively to the number of spikes per control period. Note: this will only work for one neuron group at the moment.

Parameters

name (str) – Unique identifier for the device.

brian_objects: set#

All the Brian objects added to the network by this device. Must be kept up-to-date in connect_to_neuron_group() and other functions so that those objects can be automatically added to the network when the device is injected.

connect_to_neuron_group(neuron_group)[source]#

Connect device to given neuron_group.

If your device introduces any objects which Brian must keep track of, such as a NeuronGroup, Synapses, or Monitor, make sure to add these to self.brian_objects.

Parameters
  • neuron_group (NeuronGroup) –

  • **kwparams (optional, passed from inject_recorder or) – inject_stimulator

get_state() nptyping.types._ndarray.NDArray[Any, nptyping.types._number.UInt][source]#
Returns

n_neurons-length array with spike counts over the latest control period.

Return type

NDArray[(n_neurons,), np.uint]

name: str#

Unique identifier for device. Used as a key in output/input dicts

sim: CLSimulator#

The simulator the device is injected into

class cleosim.recorders.RateRecorder(name: str, index: int)[source]#

Bases: cleosim.base.Recorder

Records firing rate from a single neuron.

Firing rate comes from Brian’s PopulationRateMonitor

Parameters
  • name (str) – Unique device name

  • index (int) – index of neuron to record

brian_objects: set#

All the Brian objects added to the network by this device. Must be kept up-to-date in connect_to_neuron_group() and other functions so that those objects can be automatically added to the network when the device is injected.

connect_to_neuron_group(neuron_group)[source]#

Connect device to given neuron_group.

If your device introduces any objects which Brian must keep track of, such as a NeuronGroup, Synapses, or Monitor, make sure to add these to self.brian_objects.

Parameters
  • neuron_group (NeuronGroup) –

  • **kwparams (optional, passed from inject_recorder or) – inject_stimulator

get_state()[source]#

Return current measurement.

name: str#

Unique identifier for device. Used as a key in output/input dicts

sim: CLSimulator#

The simulator the device is injected into

class cleosim.recorders.VoltageRecorder(name: str, voltage_var_name: str = 'v')[source]#

Bases: cleosim.base.Recorder

Records the voltage of a single neuron group.

Parameters
  • name (str) – Unique device name

  • voltage_var_name (str, optional) – Name of variable representing membrane voltage, by default “v”

brian_objects: set#

All the Brian objects added to the network by this device. Must be kept up-to-date in connect_to_neuron_group() and other functions so that those objects can be automatically added to the network when the device is injected.

connect_to_neuron_group(neuron_group)[source]#

Connect device to given neuron_group.

If your device introduces any objects which Brian must keep track of, such as a NeuronGroup, Synapses, or Monitor, make sure to add these to self.brian_objects.

Parameters
  • neuron_group (NeuronGroup) –

  • **kwparams (optional, passed from inject_recorder or) – inject_stimulator

get_state() brian2.units.fundamentalunits.Quantity[source]#
Returns

Current voltage of target neuron group

Return type

Quantity

name: str#

Unique identifier for device. Used as a key in output/input dicts

sim: CLSimulator#

The simulator the device is injected into

cleosim.stimulators module#

Contains basic stimulators.

class cleosim.stimulators.StateVariableSetter(name: str, variable_to_ctrl: str, unit: brian2.units.fundamentalunits.Unit, start_value: float = 0)[source]#

Bases: cleosim.base.Stimulator

Sets the given state variable of target neuron groups.

Parameters
  • name (str) – Unique device name

  • variable_to_ctrl (str) – Name of state variable to control

  • unit (Unit) – Unit of that state variable: will be used in update()

  • start_value (float, optional) – Starting variable value, by default 0

brian_objects: set#

All the Brian objects added to the network by this device. Must be kept up-to-date in connect_to_neuron_group() and other functions so that those objects can be automatically added to the network when the device is injected.

connect_to_neuron_group(neuron_group)[source]#

Connect device to given neuron_group.

If your device introduces any objects which Brian must keep track of, such as a NeuronGroup, Synapses, or Monitor, make sure to add these to self.brian_objects.

Parameters
  • neuron_group (NeuronGroup) –

  • **kwparams (optional, passed from inject_recorder or) – inject_stimulator

default_value: Any#

The default value of the device—used on initialization and on reset()

name: str#

Unique identifier for device. Used as a key in output/input dicts

save_history: bool#

Determines whether t_ms and values are recorded

sim: CLSimulator#

The simulator the device is injected into

t_ms: list[float]#

Times stimulator was updated, stored if save_history

update(ctrl_signal: float) None[source]#

Set state variable of target neuron groups

Parameters

ctrl_signal (float) – Value to update variable to, without unit. The unit provided on initialization is automatically multiplied.

value: Any#

The current value of the stimulator device

values: list[Any]#

Values taken by the stimulator at each update() call, stored if save_history

cleosim.utilities module#

Assorted utilities for developers.

cleosim.utilities.get_orth_vectors_for_v(v)[source]#

Returns w1, w2 as 1x3 row vectors

cleosim.utilities.modify_model_with_eqs(neuron_group, eqs_to_add)[source]#

Adapted from _create_variables() from neurongroup.py from Brian2 source code v2.3.0.2

cleosim.utilities.style_plots_for_docs()[source]#
cleosim.utilities.uniform_cylinder_rθz(n, rmax, zmax)[source]#
cleosim.utilities.wavelength_to_rgb(wavelength_nm, gamma=0.8)[source]#

taken from http://www.noah.org/wiki/Wavelength_to_RGB_in_Python This converts a given wavelength of light to an approximate RGB color value. The wavelength must be given in nanometers in the range from 380 nm through 750 nm (789 THz through 400 THz).

Based on code by Dan Bruton http://www.physics.sfasu.edu/astro/color/spectra.html

cleosim.utilities.xyz_from_rθz(rs, thetas, zs, xyz_start, xyz_end)[source]#

Convert from cylindrical to Cartesian coordinates.