Core

Network

TeiliNetwork is a subclass of brian2.Network. It does the same thing plus some additional methods for convenience. There are properties to get all monitors, Neurons and Connections that were added to the Network.

Like in Brian2, there is an add method to which all Groups have to be added, for usage, please refer to the teili examples (in particular neuron_synapse_tutorial) and to the Brian2 documentation ().

Groups

Neurons

Neurons is a subclass of brian2.NeuronGroup and can be used in the same way. Have a look at neuron_synapse_tutorial for an introduction. In teili there are different ways to initialize a Neurons object:

import os
from teili.core.groups import Neurons
from teili.models.neuron_models import DPI
from teili.models.builder.neuron_equation_builder import NeuronEquationBuilder
# the teili way
G = Neurons(100, equation_builder=DPI(num_inputs=2))
# from a static file
path = os.path.expanduser("~")
model_path = os.path.join(path, "teiliApps", "equations", "")
neuron_model = NeuronEquationBuilder.import_eq(
    filename=model_path + 'DPI.py', num_inputs=2)
G = Neurons(100, equation_builder=neuron_model)
# or the brian2 way
G = Neurons(100, model='dv/dt = -v / tau : 1')

As in brian2 we provide a Neuron class which inherits from brian2’s NeuronGroup class. The required keyword arguments are the same as described in brian2’s neuron tutorial. See below a example use case of pre-defined neuron_models. For static neuron_model usage please refer to teiliApps/tutorials/neuron_synapse_import_eq_tutorial.py.

from teili import Neurons
from teili.models.neuron_models import DPI as neuron_model

test_neurons = Neurons(2, equation_builder=neuron_model(num_inputs=2),
                        name="test_neurons")

where num_inputs defines how many distinct inputs the NeuronGroup is expecting. This allows us to potentially treat each synaptic connection as independent and not to perform a linear summation before each current is injected into the neuron. For many simulations this is an unnecessary feature as most models expect a linear summation of all synaptic inputs. By defining the number of inputs explicitly, however, one can study branch specific inputs with a distribution of synaptic time constants which are asynchronously integrated.

Each model, whether Neuron or Connection is internally generated dynamically using the EquationBuilder. For more details please refer to NeuronEquationBuilder.

An example of the neuron_model class is shown below:

class DPI(NeuronEquationBuilder):
    """This class provides you with all equations to simulate a current-based
    exponential, adaptive leaky integrate and fire neuron as implemented on
    the neuromorphic chips by the NCS group. The neuron model follows the DPI neuron
    which was published in 2014 (Chicca et al. 2014).
    """

    def __init__(self, num_inputs=1):
        """This initializes the NeuronEquationBuilder with DPI neuron model.

        Args:
            num_inputs (int, optional): Description
        """
        NeuronEquationBuilder.__init__(self, base_unit='current', adaptation='calcium_feedback',
                                      integration_mode='exponential', leak='leaky',
                                      position='spatial', noise='none')
        self.add_input_currents(num_inputs)

The NeuronEquationBuilder has the following keyword arguments:

  • base_unit: Either set to current or voltage depending whether you want to simulate current-based hardware neuron models

  • adaptation: Toggles spike-frequency adaptation mechanism in neuron_model. Can either be set to None or calcium_feedback.

  • integration_mode: Can be set to linear, quadratic or exponential

  • leak: Toggles leaky integration. Possible values are leaky or non_leaky.

  • position: Adds positional x, y attribute to neuron in order to spatially arrange the neurons. Once the neuron_model has these attributes the user can access and set them by neuron_obj.x.

  • noise: Adds constant noise to neuron_model

The reason behind this is that the EquationBuilder has access to a set of templates defined in teili/models/builder/templates/ such that the same neuron model can easily be simulated with and without leak for example. Of course we offer the possibility of a work-around so that statically defined models can be simulated. For details please refer to the tutorial

For more information please consult the EquationBuilder section. Let’s connect neurons to one another.

Connections

The Connections class is a subclass of brian2.Synapses and can be used in the same way. Have a look at neuron_synapse_tutorial for an introduction. In teili there are different ways to initialize a Connections object:

import os
from teili.core.groups import Connections
from teili.models.synapse_models import DPISyn
from teili.models.builder.synapse_equation_builder import SynapseEquationBuilder
# the teili way
S = Connections(pre_neuron, post_neuron,
                equation_builder=DPISyn(), name="synapse_name")
# from a static file
path = os.path.expanduser("~")
model_path = os.path.join(path, "teiliApps", "equations", "")
synapse_model = = SynapseEquationBuilder.import_eq(
    model_path + 'DPISyn.py')
S = Connections(pre_neuron, post_neuron,
                equation_builder=synapse_model, name="synapse_name")
# or the brian2 way
S = Connections(pre_neuron, post_neuron, model='w : volt', on_pre='v += w')

As in brian2 we provide a Connections class which inherits from brian2’s Synapses class. The required keyword arguments are the same as described in brian2’s synapse tutorial. See below a example use case of pre-defined synapse_models. For static synapse_model usage please refer to ~/teiliApps/tutorials/neuron_synapse_builderobj_tutorial.py.

from teili.core.groups import Neurons, Connections
from teili.models.synapse_models import DPISyn as syn_model

test_synapse = Connections(test_neurons1, test_neurons2,
                           equation_builder=syn_model(),
                           name="test_synapse")

Each model, whether Neuron or Connection is internally generated dynamically using the EquationBuilder. For more details please refer to NeuronEquationBuilder or SynapseEquationBuilder

An example of the synapse_model class is shown below:

class DPISyn(SynapseEquationBuilder):
    """This class provides you with all the equations to simulate a Differential Pair
    Integrator (DPI) synapse as published in Chicca et al. 2014.
    """

    def __init__(self):
        """This class provides you with all the equations to simulate a Differential Pair
        Integrator (DPI) synapse as published in Chicca et al. 2014.
        """
        SynapseEquationBuilder.__init__(self, base_unit='DPI',
                                        plasticity='non_plastic')

The SynapseEquationBuilder has the following keyword arguments:

  • base_unit: Set to current or conductance depending whether you want to simulate current-based hardware neuron models. This keyword argument can also be set to DPI or DPIShunting for specific hardware model simulation.

  • kernel: Can be set to exponential, alpha or resonant which ultimately sets the shapes of the EPSC and IPSC.

  • plasticity: This keyword argument lets you easily generate any synapse_model with either an stdp or fusi learning rule.

The reason behind this is that the EquationBuilder has access to a set of templates defined in teili/models/builder/templates/ such that the same synapse_model can easily be simulated with and without plasticity or with different plasticity rules for example. Of course we offer the possibility of a work-around so that statically defined models can be simulated. For details please refer to the plasticity tutorial

Note

TBA Contributing guide for new templates

Tags

Each TeiliGroup has an attribute called _tags. For more information please see here for more detailed explanation of how to set and get tags from Groups.

Tags should be set as the network expands and the functionality changes. Tags are defined as:

  • mismatch: (bool) Flag to indicate if mismatch is present in the Group

  • noise: (bool) Noise input, noise connection or noise presence

  • level: (int) Level of BuildingBlock in the hierarchy. A WTA BuildingBlock which is connected directly to a sensor array is level 1. An OCTA BuildinBlock, however, is level 2 as it consists of level 1 WTAs

  • sign: (str : exc/inh/None) Sign on neuronal population. Following Dale law.

  • target_sign: (str : exc/inh/None) Sign of target population. None if not applicable.

  • num_inputs: (int) Number of inputs in Neuron population. None if not applicable.

  • bb_type: (str : WTA/ OCTA/ 3-WAY) Building block type.

  • group_type: (str : Neuron/Connection/ SpikeGen) Group type

  • connection_type: (str : rec/lateral/fb/ff/None) Connection type

Setting Tags

Tags can be set: .. code-block:: python

test_wta._set_tags({‘custom_tag’ : custom_tag }}, target_group)

Getting Tags

Specific groups can be filtered using specific tags:

test_wta.get_groups({'group_type': 'SpikeGenerator'})

All tags of a group can be obtained by:

test_wta.print_tags('n_exc')

Device Mismatch

Mismatch is an inherent property of analog VLSI devices due to fabrication variability 1. The effect of mismatch on chip behavior can be studied, for example, with Monte Carlo simulations 2. Thus, if you are simulating neuron and synapse models of neuromorphic chips, e.g. the DPI neuron (DPI) and the DPI synapse (DPISyn), you might also want to simulate device mismatch. To this end, the class method add_mismatch() allows you to add a Gaussian distributed mismatch with mean equal to the current parameter value and standard deviation set as a fraction of the current parameter value.

As an example, once Neurons and Connections are created, device mismatch can be added to some selected parameters (e.g. Itau and refP for the DPI neuron) by specifying a dictionary with parameter names as keys and standard deviation as values, as shown in the example below. If no dictionary is passed to add_mismatch() 20% mismatch will be added to all variables except for variables that are found in teili/models/parameters/no_mismatch_parameter.py.

import numpy as np
from brian2 import seed
from teili.core.groups import Neurons
from teili.models.neuron_models import DPI

test_neurons = Neurons(100, equation_builder=DPI(num_inputs=2))

Let’s assume that the estimated mismatch distribution has a standard deviation of 10% of the current value for both parameters. Then:

mismatch_param = {'Itau': 0.1, 'refP': 0.1}
test_neurons.add_mismatch(mismatch_param, seed=10)

This will change the current parameter values by drawing random values from the specified Gaussian distribution.

If you set the mismatch seed in the input parameters, the random samples will be reproducible across simulations.

Note

Note that self.add_mismatch() will automatically truncate the Gaussian distribution

at zero for the lower bound. This will prevent neuron or synapse parameters (which are mainly transistor currents for the DPI model) from being set to negative values. No upper bound is specified by default. However, if you want to manually specify the lower bound and upper bound of the mismatch Gaussian distribution, you can use the method _add_mismatch_param(), as shown below. With old_param being the current parameter value, this will draw samples from a Gaussian distribution with the following parameters:

  • mean: old_param

  • standard deviation: std * old_param

  • lower bound: lower * std * old_param + old_param

  • upper bound: upper * std * old_param + old_param

import numpy as np
from brian2 import seed
from teili.core.groups import Neurons
from teili.models.neuron_models import DPI

test_neurons = Neurons(100, equation_builder=DPI(num_inputs=2))
test_neurons._add_mismatch_param(param='Itau', std=0.1, lower=-0.2, upper = 0.2)

Note

that this option allows you to add mismatch only to one parameter at a time.

1

Sheik, Sadique, Elisabetta Chicca, and Giacomo Indiveri. “Exploiting device mismatch in neuromorphic VLSI systems to implement axonal delays.” Neural Networks (IJCNN), The 2012 International Joint Conference on. IEEE, 2012.

2

Hung, Hector, and Vladislav Adzic. “Monte Carlo simulation of device variations and mismatch in analog integrated circuits.” Proc. NCUR 2006 (2006): 1-8.