def __init__(self, n_neurons, e_rev_E, e_rev_I):
        self._units = {E_REV_E: "mV", E_REV_I: "mV"}

        self._n_neurons = n_neurons
        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[E_REV_E] = e_rev_E
        self._data[E_REV_I] = e_rev_I
Example #2
0
class SynapseTypeDelta(AbstractSynapseType):
    """ This represents a synapse type with two delta synapses
    """
    __slots__ = ["_data"]

    def __init__(self, n_neurons, initial_input_exc, initial_input_inh):
        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[INITIAL_INPUT_EXC] = initial_input_exc
        self._data[INITIAL_INPUT_INH] = initial_input_inh

    @overrides(AbstractSynapseType.get_n_synapse_types)
    def get_n_synapse_types(self):
        return 2

    @overrides(AbstractSynapseType.get_synapse_id_by_target)
    def get_synapse_id_by_target(self, target):
        if target == "excitatory":
            return 0
        elif target == "inhibitory":
            return 1
        return None

    @overrides(AbstractSynapseType.get_synapse_targets)
    def get_synapse_targets(self):
        return "excitatory", "inhibitory"

    @overrides(AbstractSynapseType.get_n_synapse_type_parameters)
    def get_n_synapse_type_parameters(self):
        return 2

    @overrides(AbstractSynapseType.get_synapse_type_parameters)
    def get_synapse_type_parameters(self):
        return [
            NeuronParameter(self._data[INITIAL_INPUT_EXC], DataType.S1615),
            NeuronParameter(self._data[INITIAL_INPUT_INH], DataType.S1615)
        ]

    @overrides(AbstractSynapseType.get_synapse_type_parameter_types)
    def get_synapse_type_parameter_types(self):
        return []

    @overrides(AbstractSynapseType.get_n_cpu_cycles_per_neuron)
    def get_n_cpu_cycles_per_neuron(self):
        return 0

    @property
    def isyn_exc(self):
        return self._data[INITIAL_INPUT_EXC]

    @isyn_exc.setter
    def isyn_exc(self, new_value):
        self._data.set_value(key=INITIAL_INPUT_EXC, value=new_value)

    @property
    def isyn_inh(self):
        return self._data[INITIAL_INPUT_INH]

    @isyn_inh.setter
    def isyn_inh(self, new_value):
        self._data.set_value(key=INITIAL_INPUT_INH, value=new_value)
    def __init__(self, n_neurons, du_th, tau_th, v_thresh):
        self._n_neurons = n_neurons

        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[DU_TH] = du_th
        self._data[DU_TH_INV] = self._data[DU_TH].apply_operation(
            lambda x: 1.0 / x)
        self._data[TAU_TH] = tau_th
        self._data[TAU_TH_INV] = self._data[TAU_TH].apply_operation(
            lambda x: 1.0 / x)
        self._data[V_THRESH] = v_thresh
class InputTypeConductance(AbstractInputType, AbstractContainsUnits):
    """ The conductance input type
    """
    __slots__ = ["_data", "_n_neurons", "_units"]

    def __init__(self, n_neurons, e_rev_E, e_rev_I):
        self._units = {E_REV_E: "mV", E_REV_I: "mV"}

        self._n_neurons = n_neurons
        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[E_REV_E] = e_rev_E
        self._data[E_REV_I] = e_rev_I

    @property
    def e_rev_E(self):
        return self._data[E_REV_E]

    @e_rev_E.setter
    def e_rev_E(self, e_rev_E):
        self._data.set_value(key=E_REV_E, value=e_rev_E)

    @property
    def e_rev_I(self):
        return self._data[E_REV_I]

    @e_rev_I.setter
    def e_rev_I(self, e_rev_I):
        self._data.set_value(key=E_REV_I, value=e_rev_I)

    def get_global_weight_scale(self):
        return 1024.0

    def get_n_input_type_parameters(self):
        return 2

    def get_input_type_parameters(self):
        return [
            NeuronParameter(self._data[E_REV_E],
                            _CONDUCTANTCE_TYPES.E_REV_E.data_type),
            NeuronParameter(self._data[E_REV_I],
                            _CONDUCTANTCE_TYPES.E_REV_I.data_type)
        ]

    def get_input_type_parameter_types(self):
        return [item.data_type for item in _CONDUCTANTCE_TYPES]

    def get_n_cpu_cycles_per_neuron(self, n_synapse_types):
        return 10

    @overrides(AbstractContainsUnits.get_units)
    def get_units(self, variable):
        return self._units[variable]
Example #5
0
class ThresholdTypeStatic(AbstractThresholdType, AbstractContainsUnits):
    """ A threshold that is a static value
    """
    __slots__ = ["_data", "_n_neurons", "_units"]

    def __init__(self, n_neurons, v_thresh):
        self._units = {V_THRESH: "mV"}

        self._n_neurons = n_neurons
        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[V_THRESH] = v_thresh

    @property
    def v_thresh(self):
        return self._data[V_THRESH]

    @v_thresh.setter
    def v_thresh(self, v_thresh):
        self._data.set_value(key=V_THRESH, value=v_thresh)

    @overrides(AbstractThresholdType.get_n_threshold_parameters)
    def get_n_threshold_parameters(self):
        return 1

    @overrides(AbstractThresholdType.get_threshold_parameters)
    def get_threshold_parameters(self):
        return [
            NeuronParameter(self._data[V_THRESH],
                            _STATIC_TYPES.V_THRESH.data_type)
        ]

    @overrides(AbstractThresholdType.get_threshold_parameter_types)
    def get_threshold_parameter_types(self):
        return [item.data_type for item in _STATIC_TYPES]

    @overrides(AbstractThresholdType.get_n_cpu_cycles_per_neuron)
    def get_n_cpu_cycles_per_neuron(self):

        # Just a comparison, but 2 just in case!
        return 2

    @overrides(AbstractContainsUnits.get_units)
    def get_units(self, variable):
        return self._units[variable]
    def __init__(self, n_neurons, tau_syn_E, tau_syn_E2,
                 tau_syn_I, initial_input_exc, initial_input_exc2,
                 initial_input_inh):
        # pylint: disable=too-many-arguments
        self._units = {
            TAU_SYN_E: "mV",
            TAU_SYN_E2: "mV",
            TAU_SYN_I: 'mV',
            GSYN_EXC: "uS",
            GSYN_INH: "uS"}

        self._n_neurons = n_neurons
        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[TAU_SYN_E] = tau_syn_E
        self._data[TAU_SYN_E2] = tau_syn_E2
        self._data[TAU_SYN_I] = tau_syn_I
        self._data[INITIAL_INPUT_EXC] = initial_input_exc
        self._data[INITIAL_INPUT_EXC2] = initial_input_exc2
        self._data[INITIAL_INPUT_INH] = initial_input_inh
    def __init__(self, n_neurons, exc_response, exc_exp_response,
                 tau_syn_E, inh_response, inh_exp_response, tau_syn_I):
        # pylint: disable=too-many-arguments
        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[EXC_RESPONSE] = exc_response
        self._data[EXC_EXP_RESPONSE] = exc_exp_response
        self._data[TAU_SYN_E] = tau_syn_E
        self._data[INH_RESPONSE] = inh_response
        self._data[INH_EXP_RESPONSE] = inh_exp_response
        self._data[TAU_SYN_I] = tau_syn_I

        self._exc_response = convert_param_to_numpy(exc_response, n_neurons)
        self._exc_exp_response = convert_param_to_numpy(
            exc_exp_response, n_neurons)
        self._tau_syn_E = convert_param_to_numpy(tau_syn_E, n_neurons)

        self._inh_response = convert_param_to_numpy(inh_response, n_neurons)
        self._inh_exp_response = convert_param_to_numpy(
            inh_exp_response, n_neurons)
        self._tau_syn_I = convert_param_to_numpy(tau_syn_I, n_neurons)
Example #8
0
    def __init__(self, n_neurons, a, b, c, d, v_init, u_init, i_offset):
        # pylint: disable=too-many-arguments
        self._units = {
            A: "ms",
            B: "ms",
            C: "mV",
            D: "mV/ms",
            V_INIT: "mV",
            U_INIT: "mV/ms",
            I_OFFSET: "nA"
        }

        self._n_neurons = n_neurons
        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[A] = a
        self._data[B] = b
        self._data[C] = c
        self._data[D] = d
        self._data[V_INIT] = v_init
        self._data[U_INIT] = u_init
        self._data[I_OFFSET] = i_offset
    def __init__(self, n_neurons, tau_syn_E, tau_syn_I,
                 initial_input_exc=0.0, initial_input_inh=0.0):
        # pylint: disable=too-many-arguments
        self._units = {
            TAU_SYN_E: "mV",
            TAU_SYN_I: 'mV',
            GSYN_EXC: "uS",
            GSYN_INH: "uS"}

        self._n_neurons = n_neurons
        self._data = SpynnakerRangeDictionary(size=n_neurons)
        self._data[TAU_SYN_E] = tau_syn_E
        self._data[TAU_SYN_I] = tau_syn_I
        self._data[GSYN_EXC] = initial_input_exc
        self._data[GSYN_INH] = initial_input_inh
Example #10
0
class NeuronModelIzh(AbstractNeuronModel, AbstractContainsUnits):
    __slots__ = ["_data", "_n_neurons", "_units"]

    def __init__(self, n_neurons, a, b, c, d, v_init, u_init, i_offset):
        # pylint: disable=too-many-arguments
        self._units = {
            A: "ms",
            B: "ms",
            C: "mV",
            D: "mV/ms",
            V_INIT: "mV",
            U_INIT: "mV/ms",
            I_OFFSET: "nA"
        }

        self._n_neurons = n_neurons
        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[A] = a
        self._data[B] = b
        self._data[C] = c
        self._data[D] = d
        self._data[V_INIT] = v_init
        self._data[U_INIT] = u_init
        self._data[I_OFFSET] = i_offset

    @property
    def a(self):
        return self._data[A]

    @a.setter
    def a(self, a):
        self._data.set_value(key=A, value=a)

    @property
    def b(self):
        return self._data[B]

    @b.setter
    def b(self, b):
        self._data.set_value(key=B, value=b)

    @property
    def c(self):
        return self._data[C]

    @c.setter
    def c(self, c):
        self._data.set_value(key=C, value=c)

    @property
    def d(self):
        return self._data[D]

    @d.setter
    def d(self, d):
        self._data.set_value(key=D, value=d)

    @property
    def i_offset(self):
        return self._data[I_OFFSET]

    @i_offset.setter
    def i_offset(self, i_offset):
        self._data.set_value(key=I_OFFSET, value=i_offset)

    @property
    def v_init(self):
        return self._data[V_INIT]

    @v_init.setter
    def v_init(self, v_init):
        self._data.set_value(key=V_INIT, value=v_init)

    @property
    def u_init(self):
        return self._data[U_INIT]

    @u_init.setter
    def u_init(self, u_init):
        self._data.set_value(key=U_INIT, value=u_init)

    def initialize_v(self, v_init):
        self._data.set_value(key=V_INIT, value=v_init)

    def initialize_u(self, u_init):
        self._data.set_value(key=U_INIT, value=u_init)

    @overrides(AbstractNeuronModel.get_n_neural_parameters)
    def get_n_neural_parameters(self):
        return 8

    @inject_items({"machine_time_step": "MachineTimeStep"})
    @overrides(AbstractNeuronModel.get_neural_parameters,
               additional_arguments={'machine_time_step'})
    def get_neural_parameters(self, machine_time_step):
        # pylint: disable=arguments-differ
        return [
            # REAL A
            NeuronParameter(self._data[A], _IZH_TYPES.A.data_type),

            # REAL B
            NeuronParameter(self._data[B], _IZH_TYPES.B.data_type),

            # REAL C
            NeuronParameter(self._data[C], _IZH_TYPES.C.data_type),

            # REAL D
            NeuronParameter(self._data[D], _IZH_TYPES.D.data_type),

            # REAL V
            NeuronParameter(self._data[V_INIT], _IZH_TYPES.V_INIT.data_type),

            # REAL U
            NeuronParameter(self._data[U_INIT], _IZH_TYPES.U_INIT.data_type),

            # offset current [nA]
            # REAL I_offset;
            NeuronParameter(self._data[I_OFFSET],
                            _IZH_TYPES.I_OFFSET.data_type),

            # current timestep - simple correction for threshold
            # REAL this_h;
            NeuronParameter(machine_time_step / 1000.0,
                            _IZH_TYPES.THIS_H.data_type)
        ]

    @overrides(AbstractNeuronModel.get_neural_parameter_types)
    def get_neural_parameter_types(self):
        return [item.data_type for item in _IZH_TYPES]

    @overrides(AbstractNeuronModel.get_n_global_parameters)
    def get_n_global_parameters(self):
        return 1

    @inject_items({"machine_time_step": "MachineTimeStep"})
    @overrides(AbstractNeuronModel.get_global_parameters,
               additional_arguments={'machine_time_step'})
    def get_global_parameters(self, machine_time_step):
        # pylint: disable=arguments-differ
        return [
            NeuronParameter(machine_time_step / 1000.0,
                            _IZH_GLOBAL_TYPES.TIMESTEP.data_type)
        ]

    @overrides(AbstractNeuronModel.get_global_parameter_types)
    def get_global_parameter_types(self):
        return [item.data_type for item in _IZH_GLOBAL_TYPES]

    @overrides(AbstractNeuronModel.set_neural_parameters)
    def set_neural_parameters(self, neural_parameters, vertex_slice):
        self._data[V_INIT][vertex_slice.as_slice] = neural_parameters[4]
        self._data[U_INIT][vertex_slice.as_slice] = neural_parameters[5]

    def get_n_cpu_cycles_per_neuron(self):

        # A bit of a guess
        return 150

    @overrides(AbstractContainsUnits.get_units)
    def get_units(self, variable):
        return self._units[variable]
Example #11
0
    def __init__(self, n_neurons, v_thresh):
        self._units = {V_THRESH: "mV"}

        self._n_neurons = n_neurons
        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[V_THRESH] = v_thresh
class AdditionalInputCa2Adaptive(AbstractAdditionalInput):
    __slots__ = ["_data", "_n_neurons"]

    def __init__(self, n_neurons, tau_ca2, i_ca2, i_alpha):
        self._n_neurons = n_neurons
        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[TAU_CA2] = tau_ca2
        self._data[I_CA2] = i_ca2
        self._data[I_ALPHA] = i_alpha

    @property
    def tau_ca2(self):
        return self._data[TAU_CA2]

    @tau_ca2.setter
    def tau_ca2(self, tau_ca2):
        self._data.set_value(key=TAU_CA2, value=tau_ca2)

    @property
    def i_ca2(self):
        return self._i_ca2

    @i_ca2.setter
    def i_ca2(self, i_ca2):
        self._data.set_value(key=I_CA2, value=i_ca2)

    @property
    def i_alpha(self):
        return self._i_alpha

    @i_alpha.setter
    def i_alpha(self, i_alpha):
        self._data.set_value(key=I_ALPHA, value=i_alpha)

    def _exp_tau_ca2(self, machine_time_step):
        return self._data[TAU_CA2].apply_operation(
            operation=lambda x: numpy.exp(
                float(-machine_time_step) / (1000.0 * x)))

    def get_n_parameters(self):
        return 3

    @inject_items({"machine_time_step": "MachineTimeStep"})
    def get_parameters(self, machine_time_step):
        # pylint: disable=arguments-differ
        return [
            NeuronParameter(self._exp_tau_ca2(machine_time_step),
                            _CA2_TYPES.EXP_TAU_CA2.data_type),
            NeuronParameter(self._data[I_CA2], _CA2_TYPES.I_CA2.data_type),
            NeuronParameter(self._data[I_ALPHA], _CA2_TYPES.I_ALPHA.data_type)
        ]

    def get_parameter_types(self):
        return [item.data_type for item in _CA2_TYPES]

    def set_parameters(self, parameters, vertex_slice):

        # Can ignore anything that isn't a state variable
        self._data[I_CA2][vertex_slice.slice] = parameters[1]

    def get_n_cpu_cycles_per_neuron(self):
        return 3

    def get_dtcm_usage_per_neuron_in_bytes(self):
        return 12

    def get_sdram_usage_per_neuron_in_bytes(self):
        return 12
 def __init__(self, n_neurons, tau_ca2, i_ca2, i_alpha):
     self._n_neurons = n_neurons
     self._data = SpynakkerRangeDictionary(size=n_neurons)
     self._data[TAU_CA2] = tau_ca2
     self._data[I_CA2] = i_ca2
     self._data[I_ALPHA] = i_alpha
class SynapseTypeExponential(AbstractSynapseType, AbstractContainsUnits):
    __slots__ = [
        "_data",
        "_n_neurons",
        "_units"]

    def __init__(self, n_neurons, tau_syn_E, tau_syn_I,
                 initial_input_exc=0.0, initial_input_inh=0.0):
        # pylint: disable=too-many-arguments
        self._units = {
            TAU_SYN_E: "mV",
            TAU_SYN_I: 'mV',
            GSYN_EXC: "uS",
            GSYN_INH: "uS"}

        self._n_neurons = n_neurons
        self._data = SpynnakerRangeDictionary(size=n_neurons)
        self._data[TAU_SYN_E] = tau_syn_E
        self._data[TAU_SYN_I] = tau_syn_I
        self._data[GSYN_EXC] = initial_input_exc
        self._data[GSYN_INH] = initial_input_inh

    @property
    def tau_syn_E(self):
        return self._data[TAU_SYN_E]

    @tau_syn_E.setter
    def tau_syn_E(self, tau_syn_E):
        self._data.set_value(key=TAU_SYN_E, value=tau_syn_E)

    @property
    def tau_syn_I(self):
        return self._data[TAU_SYN_I]

    @tau_syn_I.setter
    def tau_syn_I(self, tau_syn_I):
        self._data.set_value(key=TAU_SYN_I, value=tau_syn_I)

    @property
    def isyn_exc(self):
        return self._data[GSYN_EXC]

    @isyn_exc.setter
    def isyn_exc(self, new_value):
        self._data.set_value(key=GSYN_EXC, value=new_value)

    @property
    def isyn_inh(self):
        return self._data[GSYN_INH]

    @isyn_inh.setter
    def isyn_inh(self, new_value):
        self._data.set_value(key=GSYN_INH, value=new_value)

    @overrides(AbstractSynapseType.get_n_synapse_types)
    def get_n_synapse_types(self):
        return 2

    @overrides(AbstractSynapseType.get_synapse_id_by_target)
    def get_synapse_id_by_target(self, target):
        if target == "excitatory":
            return 0
        elif target == "inhibitory":
            return 1
        return None

    @overrides(AbstractSynapseType.get_synapse_targets)
    def get_synapse_targets(self):
        return "excitatory", "inhibitory"

    @overrides(AbstractSynapseType.get_n_synapse_type_parameters)
    def get_n_synapse_type_parameters(self):
        return 6

    @inject_items({"machine_time_step": "MachineTimeStep"})
    def get_synapse_type_parameters(self, machine_time_step):
        # pylint: disable=arguments-differ
        e_decay, e_init = get_exponential_decay_and_init(
            self._data[TAU_SYN_E], machine_time_step)
        i_decay, i_init = get_exponential_decay_and_init(
            self._data[TAU_SYN_I], machine_time_step)

        return [
            NeuronParameter(e_decay, _EXP_TYPES.E_DECAY.data_type),
            NeuronParameter(e_init, _EXP_TYPES.E_INIT.data_type),
            NeuronParameter(i_decay, _EXP_TYPES.I_DECAY.data_type),
            NeuronParameter(i_init, _EXP_TYPES.I_INIT.data_type),
            NeuronParameter(
                self._data[GSYN_EXC], _EXP_TYPES.INITIAL_EXC.data_type),
            NeuronParameter(
                self._data[GSYN_INH], _EXP_TYPES.INITIAL_INH.data_type)
        ]

    @overrides(AbstractSynapseType.get_synapse_type_parameter_types)
    def get_synapse_type_parameter_types(self):
        return [item.data_type for item in _EXP_TYPES]

    @overrides(AbstractSynapseType.get_n_cpu_cycles_per_neuron)
    def get_n_cpu_cycles_per_neuron(self):

        # A guess
        return 100

    @overrides(AbstractContainsUnits.get_units)
    def get_units(self, variable):
        return self._units[variable]
class ThresholdTypeMaassStochastic(AbstractThresholdType):
    """ A stochastic threshold
    """
    __slots__ = ["_data", "_n_neurons"]

    def __init__(self, n_neurons, du_th, tau_th, v_thresh):
        self._n_neurons = n_neurons

        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[DU_TH] = du_th
        self._data[DU_TH_INV] = self._data[DU_TH].apply_operation(
            lambda x: 1.0 / x)
        self._data[TAU_TH] = tau_th
        self._data[TAU_TH_INV] = self._data[TAU_TH].apply_operation(
            lambda x: 1.0 / x)
        self._data[V_THRESH] = v_thresh

    @property
    def v_thresh(self):
        return self._data[V_THRESH]

    @v_thresh.setter
    def v_thresh(self, v_thresh):
        self._data.set_value(key=V_THRESH, value=v_thresh)

    @property
    def du_th(self):
        return self._data[DU_TH]

    @du_th.setter
    def du_th(self, du_th):
        self._data.set_value(key=DU_TH, value=du_th)

    @property
    def tau_th(self):
        return self._data[TAU_TH]

    @tau_th.setter
    def tau_th(self, tau_th):
        self._data.set_value(key=TAU_TH, value=tau_th)

    @property
    def _du_th_inv(self):
        return self._data[DU_TH_INV]

    @property
    def _tau_th_inv(self):
        return self._data[TAU_TH_INV]

    @overrides(AbstractThresholdType.get_n_threshold_parameters)
    def get_n_threshold_parameters(self):
        return 3

    @overrides(AbstractThresholdType.get_threshold_parameters)
    def get_threshold_parameters(self):
        return [
            NeuronParameter(self._data[DU_TH_INV],
                            _MAASS_TYPES.DU_TH.data_type),
            NeuronParameter(self._data[TAU_TH_INV],
                            _MAASS_TYPES.TAU_TH.data_type),
            NeuronParameter(self._data[V_THRESH],
                            _MAASS_TYPES.V_THRESH.data_type)
        ]

    @overrides(AbstractThresholdType.get_threshold_parameter_types)
    def get_threshold_parameter_types(self):
        return [item.data_type for item in _MAASS_TYPES]

    @overrides(AbstractThresholdType.get_n_cpu_cycles_per_neuron)
    def get_n_cpu_cycles_per_neuron(self):
        return 30
Example #16
0
 def __init__(self, n_neurons, initial_input_exc, initial_input_inh):
     self._data = SpynakkerRangeDictionary(size=n_neurons)
     self._data[INITIAL_INPUT_EXC] = initial_input_exc
     self._data[INITIAL_INPUT_INH] = initial_input_inh
Example #17
0
class SynapseTypeAlpha(AbstractSynapseType):
    __slots__ = [
        "_data",
        "_exc_exp_response",
        "_exc_response",
        "_inh_exp_response",
        "_inh_response",
        "_tau_syn_E",
        "_tau_syn_I"]

    def __init__(self, n_neurons, exc_response, exc_exp_response,
                 tau_syn_E, inh_response, inh_exp_response, tau_syn_I):
        # pylint: disable=too-many-arguments
        self._data = SpynakkerRangeDictionary(size=n_neurons)
        self._data[EXC_RESPONSE] = exc_response
        self._data[EXC_EXP_RESPONSE] = exc_exp_response
        self._data[TAU_SYN_E] = tau_syn_E
        self._data[INH_RESPONSE] = inh_response
        self._data[INH_EXP_RESPONSE] = inh_exp_response
        self._data[TAU_SYN_I] = tau_syn_I

        self._exc_response = convert_param_to_numpy(exc_response, n_neurons)
        self._exc_exp_response = convert_param_to_numpy(
            exc_exp_response, n_neurons)
        self._tau_syn_E = convert_param_to_numpy(tau_syn_E, n_neurons)

        self._inh_response = convert_param_to_numpy(inh_response, n_neurons)
        self._inh_exp_response = convert_param_to_numpy(
            inh_exp_response, n_neurons)
        self._tau_syn_I = convert_param_to_numpy(tau_syn_I, n_neurons)

    @property
    def exc_response(self):
        return self._data[EXC_RESPONSE]

    @exc_response.setter
    def exc_response(self, exc_response):
        self._data.set_value(key=EXC_RESPONSE, value=exc_response)

    @property
    def tau_syn_E(self):
        return self._data[TAU_SYN_E]

    @tau_syn_E.setter
    def tau_syn_E(self, tau_syn_E):
        self._data.set_value(key=TAU_SYN_E, value=tau_syn_E)

    @property
    def inh_response(self):
        return self._data[INH_RESPONSE]

    @inh_response.setter
    def inh_response(self, inh_response):
        self._data.set_value(key=INH_RESPONSE, value=inh_response)

    @property
    def tau_syn_I(self):
        return self._data[TAU_SYN_I]

    @tau_syn_I.setter
    def tau_syn_I(self, tau_syn_I):
        self._data.set_value(key=TAU_SYN_I, value=tau_syn_I)

    @overrides(AbstractSynapseType.get_n_synapse_types)
    def get_n_synapse_types(self):
        return 2  # EX and IH

    @overrides(AbstractSynapseType.get_synapse_id_by_target)
    def get_synapse_id_by_target(self, target):

        if target == "excitatory":
            return 0
        elif target == "inhibitory":
            return 1
        return None

    @overrides(AbstractSynapseType.get_synapse_targets)
    def get_synapse_targets(self):
        return "excitatory", "inhibitory"

    @overrides(AbstractSynapseType.get_n_synapse_type_parameters)
    def get_n_synapse_type_parameters(self):
        return 8

    @inject_items({"machine_time_step": "MachineTimeStep"})
    def get_synapse_type_parameters(self, machine_time_step):
        # pylint: disable=arguments-differ
        e_decay, _ = get_exponential_decay_and_init(
            self._data[TAU_SYN_E], machine_time_step)

        i_decay, _ = get_exponential_decay_and_init(
            self._data[TAU_SYN_I], machine_time_step)

        # pre-multiply constants (convert to millisecond)
        dt_divided_by_tau_syn_E_sqr = self._data[TAU_SYN_E].apply_operation(
            lambda x: (float(machine_time_step) / 1000.0) / (x * x))
        dt_divided_by_tau_syn_I_sqr = self._data[TAU_SYN_I].apply_operation(
            lambda x: (float(machine_time_step) / 1000.0) / (x * x))

        return [
            # linear term buffer
            NeuronParameter(self._data[EXC_RESPONSE],
                            _COMB_EXP_TYPES.RESPONSE_EXC.data_type),
            # exponential term buffer
            NeuronParameter(self._data[EXC_EXP_RESPONSE],
                            _COMB_EXP_TYPES.RESPONSE_EXC_EXP.data_type),
            # evolution parameters
            NeuronParameter(dt_divided_by_tau_syn_E_sqr,
                            _COMB_EXP_TYPES.CONST_EXC.data_type),
            NeuronParameter(e_decay, _COMB_EXP_TYPES.DECAY_EXC.data_type),

            NeuronParameter(self._data[INH_RESPONSE],
                            _COMB_EXP_TYPES.RESPONSE_INH.data_type),
            NeuronParameter(self._data[INH_EXP_RESPONSE],
                            _COMB_EXP_TYPES.RESPONSE_INH_EXP.data_type),
            NeuronParameter(dt_divided_by_tau_syn_I_sqr,
                            _COMB_EXP_TYPES.CONST_INH.data_type),
            NeuronParameter(i_decay, _COMB_EXP_TYPES.DECAY_INH.data_type),
        ]

    @overrides(AbstractSynapseType.get_synapse_type_parameter_types)
    def get_synapse_type_parameter_types(self):
        return [item.data_type for item in DataType]

    @overrides(AbstractSynapseType.get_n_cpu_cycles_per_neuron)
    def get_n_cpu_cycles_per_neuron(self):
        # a guess
        return 100