Exemple #1
0
    def __init__(self, source, synapses, delays,
                 max_delay = 0*ms, maxevents = INITIAL_MAXSPIKESPER_DT,
                 precompute_offsets = True):
        self.source = source #NeuronGroup
        self.delays = delays
        self.synapses = synapses
        self._precompute_offsets=precompute_offsets

        self._max_delay=max_delay
        if max_delay>0: # do not precompute offsets if delays can change
            self._precompute_offsets=False
        
        # number of time steps, maximum number of spikes per time step
        nsteps = int(np.floor((max_delay)/(self.source.clock.dt)))+1
        self.X = np.zeros((nsteps, maxevents), dtype = self.synapses[0].dtype) # target synapses
        self.X_flat = self.X.reshape(nsteps*maxevents,)
        self.currenttime = 0
        self.n = np.zeros(nsteps, dtype = int) # number of events in each time step
        
        self._offsets = None # precalculated offsets
        
        # Compiled version
        self._useweave = get_global_preference('useweave')
        self._cpp_compiler = get_global_preference('weavecompiler')
        self._extra_compile_args = ['-O3']
        if self._cpp_compiler == 'gcc':
            self._extra_compile_args += get_global_preference('gcc_options') # ['-march=native', '-ffast-math']
        if self._useweave: # no need to precompute offsets if weave is used
            self._precompute_offsets=False

        super(SpikeQueue, self).__init__(source, 
                                         record = False)
Exemple #2
0
 def __init__(self, threshold_state=1, state=0):
     self.threshold_state = threshold_state # State variable representing the threshold
     self.state = state
     self._useaccel = get_global_preference('useweave')
     self._cpp_compiler = get_global_preference('weavecompiler')
     self._extra_compile_args = ['-O3']
     if self._cpp_compiler == 'gcc':
         self._extra_compile_args += get_global_preference('gcc_options') # ['-march=native', '-ffast-math']
Exemple #3
0
 def __init__(self, threshold_state=1, state=0):
     self.threshold_state = threshold_state # State variable representing the threshold
     self.state = state
     self._useaccel = get_global_preference('useweave')
     self._cpp_compiler = get_global_preference('weavecompiler')
     self._extra_compile_args = ['-O3']
     if self._cpp_compiler == 'gcc':
         self._extra_compile_args += get_global_preference('gcc_options') # ['-march=native', '-ffast-math']
Exemple #4
0
 def __init__(self, code_str, namespace, pre_code=None, post_code=None):
     Code.__init__(self, code_str, namespace, pre_code=pre_code,
                   post_code=post_code)
     self._weave_compiler = get_global_preference('weavecompiler')
     self._extra_compile_args = ['-O3']
     if self._weave_compiler == 'gcc':
         self._extra_compile_args += get_global_preference('gcc_options')
     self.code_compiled = 0
Exemple #5
0
 def __init__(self, code_str, namespace, pre_code=None, post_code=None):
     Code.__init__(self,
                   code_str,
                   namespace,
                   pre_code=pre_code,
                   post_code=post_code)
     self._weave_compiler = get_global_preference('weavecompiler')
     self._extra_compile_args = ['-O3']
     if self._weave_compiler == 'gcc':
         self._extra_compile_args += get_global_preference('gcc_options')
     self.code_compiled = 0
Exemple #6
0
    def __init__(self,
                 source,
                 synapses,
                 delays,
                 max_delay=0 * ms,
                 maxevents=INITIAL_MAXSPIKESPER_DT,
                 precompute_offsets=True):
        self.source = source  #NeuronGroup
        self.delays = delays
        self.synapses = synapses
        self._precompute_offsets = precompute_offsets

        self._max_delay = max_delay
        if max_delay > 0:  # do not precompute offsets if delays can change
            self._precompute_offsets = False

        # number of time steps, maximum number of spikes per time step
        nsteps = int(np.floor((max_delay) / (self.source.clock.dt))) + 1
        self.X = np.zeros((nsteps, maxevents),
                          dtype=self.synapses[0].dtype)  # target synapses
        self.X_flat = self.X.reshape(nsteps * maxevents, )
        self.currenttime = 0
        self.n = np.zeros(nsteps,
                          dtype=int)  # number of events in each time step

        self._offsets = None  # precalculated offsets

        # Compiled version
        self._useweave = get_global_preference('useweave')
        self._cpp_compiler = get_global_preference('weavecompiler')
        self._extra_compile_args = ['-O3']
        if self._cpp_compiler == 'gcc':
            self._extra_compile_args += get_global_preference(
                'gcc_options')  # ['-march=native', '-ffast-math']
        if self._useweave:  # no need to precompute offsets if weave is used
            self._precompute_offsets = False

        super(SpikeQueue, self).__init__(source, record=False)
Exemple #7
0
def select_threshold(expr, eqs, level=0):
    '''
    Automatically selects the appropriate Threshold object from a string.
    
    Matches the following patterns:
    
    var_name > or >= const : Threshold
    var_name > or >= var_name : VariableThreshold
    others : StringThreshold
    '''
    global CThreshold, PythonThreshold
    use_codegen = (get_global_preference('usecodegen') and
                   get_global_preference('usecodegenthreshold'))
    use_weave = (get_global_preference('useweave') and
                 get_global_preference('usecodegenweave'))
    if use_codegen:
        if CThreshold is None:
            from brian.experimental.codegen.threshold import (CThreshold,
                                                              PythonThreshold)
        if use_weave:
            log_warn('brian.threshold', 'Using codegen CThreshold')
            return CThreshold(expr, level=level + 1)
        else:
            log_warn('brian.threshold', 'Using codegen PythonThreshold')
            return PythonThreshold(expr, level=level + 1)
    # plan:
    # - see if it matches A > B or A >= B, if not select StringThreshold
    # - check if A, B both match diffeq variable names, and if so
    #   select VariableThreshold
    # - check that A is a variable name, if not select StringThreshold
    # - extract all the identifiers from B, and if none of them are
    #   callable, assume it is a constant, try to eval it and then use
    #   Threshold. If not, or if eval fails, use StringThreshold.
    # This misses the case of e.g. V>10*mV*exp(1) because exp will be
    # callable, but in general a callable means that it could be
    # non-constant.
    expr = expr.strip()
    eqs.prepare()
    ns = namespace(expr, level=level + 1)
    s = re.search(r'^\s*(\w+)\s*>=?(.+)', expr)
    if not s:
        return StringThreshold(expr, level=level + 1)
    A = s.group(1)
    B = s.group(2).strip()
    if A not in eqs._diffeq_names:
        return StringThreshold(expr, level=level + 1)
    if B in eqs._diffeq_names:
        return VariableThreshold(B, A)
    try:
        vars = get_identifiers(B)
    except SyntaxError:
        return StringThreshold(expr, level=level + 1)
    all_vars = eqs._eq_names + eqs._diffeq_names + eqs._alias.keys() + ['t']
    for v in vars:
        if v not in ns or v in all_vars or callable(ns[v]):
            return StringThreshold(expr, level=level + 1)
    try:
        val = eval(B, ns)
    except:
        return StringThreshold(expr, level=level + 1)
    return Threshold(val, A)
Exemple #8
0
def test():
    """
    :class:`Threshold`
    ~~~~~~~~~~~~~~~~~~
    
    Initialised as ``Threshold(threshold[,state=0])``
    
    Causes a spike whenever the given state variable is above
    the threshold value.
    
    :class:`NoThreshold`
    ~~~~~~~~~~~~~~~~~~~~
    
    Does nothing, initialised as ``NoThreshold()``
    
    Functional thresholds
    ~~~~~~~~~~~~~~~~~~~~~
    
    Initialised as::
    
        FunThreshold(thresholdfun)
        SimpleFunThreshold(thresholdfun[,state=0])
    
    Threshold functions return a boolean array the same size as the
    number of neurons in the group, where if the returned array is
    True at index i then neuron i fires.
    
    The arguments passed to the :class:`FunThreshold` function are the
    full array of state variables for the group in order.
    
    The argument passed to the :class:`SimpleFunThreshold` function is the
    array of length N corresponding to the given state variable.
    
    :class:`VariableThreshold`
    ~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    Initialised as ``VariableThreshold(threshold_state[,state=0])``
    
    Causes a spike whenever the state variable defined by state
    is above the state variable defined by threshold_state.
    
    :class:`EmpiricalThreshold`
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    Initialised as::
    
        EmpiricalThreshold(threshold[,refractory=1*msecond[,state=0[,clock]]])
    
    Causes a spike when the given state variable exceeds the threshold value,
    but only if there has been no spike within the refractory period. Will
    use the given clock if specified, otherwise the standard guessing procedure
    is used.
    
    Poisson thresholds
    ~~~~~~~~~~~~~~~~~~
    
    Initialised as::
    
        PoissonThreshold([state=0])
        HomogeneousPoissonThreshold([state=0])
    
    The Poisson process gets the rates from the specified state variable, the
    homogeneous version uses the rates from the specified variable of the first
    neuron in the group.      
    """
    reinit_default_clock()

    # test that Threshold works as expected with default state
    G = NeuronGroup(3, model=LazyStateUpdater(), reset=Reset(0.), threshold=Threshold(1.), init=(0.,))
    M = SpikeMonitor(G, True)
    net = Network(G, M)
    net.run(1 * msecond)
    assert (len(M.spikes) == 0)
    G.state(0)[:] = array([0.5, 1.5, 2.5])
    net.run(1 * msecond)
    i, t = zip(*sorted(M.spikes, key=itemgetter(0)))
    assert (i == (1, 2))
    for s in t: assert (is_approx_equal(s, 1 * msecond))

    # test that Threshold works as expected with specified state
    def test_specified_state(G):
        M = SpikeMonitor(G, True)
        net = Network(G, M)
        net.run(1 * msecond)
        assert (len(M.spikes) == 0)
        net.reinit()
        G.state(0)[:] = array([0.5, 1.5, 2.5])
        net.run(1 * msecond)
        assert (len(M.spikes) == 0)
        net.reinit()
        G.state(1)[:] = array([0.5, 1.5, 2.5])
        net.run(1 * msecond)
        i, t = zip(*sorted(M.spikes, key=itemgetter(0)))
        assert (i == (1, 2))
        for s in t: assert (is_approx_equal(s, 0 * msecond))
    G = NeuronGroup(3, model=LazyStateUpdater(numstatevariables=2),
                    reset=Reset(0., state=1), threshold=Threshold(1., state=1),
                    init=(0., 0.))
    test_specified_state(G)
    # use string threshold
    eqs = '''v : 1
             w : 1
          '''
    G = NeuronGroup(3, model=eqs, reset=Reset(0., state=1), threshold='w > 1')
    test_specified_state(G)
    
    # test that VariableThreshold works as expected
    def test_variable_threshold(G):    
        M = SpikeMonitor(G, True)
        net = Network(G, M)
        get_default_clock().reinit()
        G.state(2)[:] = array([1., 2., 3.]) # the thresholds
        G.state(1)[:] = array([4., 1., 2.]) # the values
        net.run(1 * msecond)
        i, t = zip(*sorted(M.spikes, key=itemgetter(0)))
        assert (i == (0,))
        assert (is_approx_equal(t[0], 0 * second))

    G = NeuronGroup(3, model=LazyStateUpdater(numstatevariables=3),
                    reset=Reset(0., state=1),
                    threshold=VariableThreshold(2, state=1), init=(0., 0., 0.))
    test_variable_threshold(G)
    
    # use string threshold
    eqs = '''v : 1
             w : 1
             x : 1
          '''
    G = NeuronGroup(3, model=eqs, reset=Reset(0., state=1),
                    threshold='w > x')
    test_variable_threshold(G)
    
    # test that FunThreshold works as expected
    def f(S0, S1):
        return S0 > S1 * S1
    G = NeuronGroup(3, model=LazyStateUpdater(numstatevariables=2), reset=Reset(0.), threshold=FunThreshold(f), init=(0., 0.))
    G.state(0)[:] = array([2., 3., 10.])
    G.state(1)[:] = array([1., 2., 3.]) # the square root of the threshold values
    M = SpikeMonitor(G, True)
    net = Network(G, M)
    get_default_clock().reinit()
    net.run(1 * msecond)
    i, t = zip(*sorted(M.spikes, key=itemgetter(0)))
    assert (i == (0, 2))
    for s in t: assert (is_approx_equal(s, 0 * msecond))

    # test that SimpleFunThreshold works as expected
    def f(S):
        return S > 1.
    G = NeuronGroup(3, model=LazyStateUpdater(), reset=Reset(0.), threshold=SimpleFunThreshold(f), init=(0.,))
    G.state(0)[:] = array([0.5, 1.5, 2.5])
    M = SpikeMonitor(G, True)
    net = Network(G, M)
    get_default_clock().reinit()
    net.run(1 * msecond)
    i, t = zip(*sorted(M.spikes, key=itemgetter(0)))
    assert (i == (1, 2))
    for s in t: assert (is_approx_equal(s, 0 * msecond))

    # test that EmpiricalThreshold works as expected
    G = NeuronGroup(1, model=LazyStateUpdater(numstatevariables=2), reset=NoReset(), threshold=EmpiricalThreshold(1., refractory=0.5 * msecond, state=1), init=(0., 2.))
    M = SpikeMonitor(G, True)
    net = Network(G, M)
    get_default_clock().reinit()
    net.run(1.6 * msecond)
    i, t = zip(*sorted(M.spikes, key=itemgetter(1)))
    assert (i == (0, 0, 0, 0))
    for i, s in enumerate(t): assert (is_approx_equal(s, i * 0.5 * msecond))

    # test that PoissonThreshold works
    def test_poisson_threshold(G):
        init = float(1. / get_default_clock().dt) # should cause spiking at every time interval        
        G.state(0)[:] = array([0., init, 0.])
        M = SpikeMonitor(G, True)
        net = Network(G, M)
        net.run(1 * msecond)
        assert (len(M.spikes))
        i, t = zip(*sorted(M.spikes, key=itemgetter(1)))
        assert (all(j == 1 for j in i))
    
    G = NeuronGroup(3, model=LazyStateUpdater(), reset=NoReset(),
                    threshold=PoissonThreshold())
    test_poisson_threshold(G)
    
    # Poisson threshold via a string threshold using the rand() function
    eqs = '''v : 1
             w : 1
             x : 1
          '''
    
    # A threshold with rand in it is not supported by CThreshold
    if not (get_global_preference('usecodegen') and
            get_global_preference('usecodegenthreshold') and
            get_global_preference('useweave') and
            get_global_preference('usecodegenweave')):            
        G = NeuronGroup(3, model=eqs, reset=NoReset(), threshold='rand() < v')
        test_poisson_threshold(G)
        
    G = NeuronGroup(3, model=eqs, reset=NoReset(), threshold=StringThreshold('rand() < v'))
    test_poisson_threshold(G)



    # test that HomogeneousPoissonThreshold works
    init = float(1. / get_default_clock().dt) # should cause spiking at every time interval
    G = NeuronGroup(3, model=LazyStateUpdater(), reset=NoReset(), threshold=HomogeneousPoissonThreshold())
    M = SpikeMonitor(G, True)
    net = Network(G, M)
    G.state(0)[:] = array([0., init, 0.]) # should do nothing, because only first neuron is looked at 
    net.run(1 * msecond)
    assert (len(M.spikes) == 0)
    G.state(0)[:] = array([init, 0., 0.]) # should do nothing, because only first neuron is looked at 
    net.run(1 * msecond)
Exemple #9
0
def select_threshold(expr, eqs, level=0):
    '''
    Automatically selects the appropriate Threshold object from a string.
    
    Matches the following patterns:
    
    var_name > or >= const : Threshold
    var_name > or >= var_name : VariableThreshold
    others : StringThreshold
    '''
    global CThreshold, PythonThreshold
    use_codegen = (get_global_preference('usecodegen') and
                   get_global_preference('usecodegenthreshold'))
    use_weave = (get_global_preference('useweave') and
                 get_global_preference('usecodegenweave'))
    if use_codegen:
        if CThreshold is None:
            from brian.experimental.codegen.threshold import (CThreshold,
                                                              PythonThreshold)
        if use_weave:
            log_warn('brian.threshold', 'Using codegen CThreshold')
            return CThreshold(expr, level=level + 1)
        else:
            log_warn('brian.threshold', 'Using codegen PythonThreshold')
            return PythonThreshold(expr, level=level + 1)
    # plan:
    # - see if it matches A > B or A >= B, if not select StringThreshold
    # - check if A, B both match diffeq variable names, and if so
    #   select VariableThreshold
    # - check that A is a variable name, if not select StringThreshold
    # - extract all the identifiers from B, and if none of them are
    #   callable, assume it is a constant, try to eval it and then use
    #   Threshold. If not, or if eval fails, use StringThreshold.
    # This misses the case of e.g. V>10*mV*exp(1) because exp will be
    # callable, but in general a callable means that it could be
    # non-constant.
    expr = expr.strip()
    eqs.prepare()
    ns = namespace(expr, level=level + 1)
    s = re.search(r'^\s*(\w+)\s*>=?(.+)', expr)
    if not s:
        return StringThreshold(expr, level=level + 1)
    A = s.group(1)
    B = s.group(2).strip()
    if A not in eqs._diffeq_names:
        return StringThreshold(expr, level=level + 1)
    if B in eqs._diffeq_names:
        return VariableThreshold(B, A)
    try:
        vars = get_identifiers(B)
    except SyntaxError:
        return StringThreshold(expr, level=level + 1)
    all_vars = eqs._eq_names + eqs._diffeq_names + eqs._alias.keys() + ['t']
    for v in vars:
        if v not in ns or v in all_vars or callable(ns[v]):
            return StringThreshold(expr, level=level + 1)
    try:
        val = eval(B, ns)
    except:
        return StringThreshold(expr, level=level + 1)
    return Threshold(val, A)
Exemple #10
0
def test():
    """
    :class:`Threshold`
    ~~~~~~~~~~~~~~~~~~
    
    Initialised as ``Threshold(threshold[,state=0])``
    
    Causes a spike whenever the given state variable is above
    the threshold value.
    
    :class:`NoThreshold`
    ~~~~~~~~~~~~~~~~~~~~
    
    Does nothing, initialised as ``NoThreshold()``
    
    Functional thresholds
    ~~~~~~~~~~~~~~~~~~~~~
    
    Initialised as::
    
        FunThreshold(thresholdfun)
        SimpleFunThreshold(thresholdfun[,state=0])
    
    Threshold functions return a boolean array the same size as the
    number of neurons in the group, where if the returned array is
    True at index i then neuron i fires.
    
    The arguments passed to the :class:`FunThreshold` function are the
    full array of state variables for the group in order.
    
    The argument passed to the :class:`SimpleFunThreshold` function is the
    array of length N corresponding to the given state variable.
    
    :class:`VariableThreshold`
    ~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    Initialised as ``VariableThreshold(threshold_state[,state=0])``
    
    Causes a spike whenever the state variable defined by state
    is above the state variable defined by threshold_state.
    
    :class:`EmpiricalThreshold`
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    Initialised as::
    
        EmpiricalThreshold(threshold[,refractory=1*msecond[,state=0[,clock]]])
    
    Causes a spike when the given state variable exceeds the threshold value,
    but only if there has been no spike within the refractory period. Will
    use the given clock if specified, otherwise the standard guessing procedure
    is used.
    
    Poisson thresholds
    ~~~~~~~~~~~~~~~~~~
    
    Initialised as::
    
        PoissonThreshold([state=0])
        HomogeneousPoissonThreshold([state=0])
    
    The Poisson process gets the rates from the specified state variable, the
    homogeneous version uses the rates from the specified variable of the first
    neuron in the group.      
    """
    reinit_default_clock()

    # test that Threshold works as expected with default state
    G = NeuronGroup(3,
                    model=LazyStateUpdater(),
                    reset=Reset(0.),
                    threshold=Threshold(1.),
                    init=(0., ))
    M = SpikeMonitor(G, True)
    net = Network(G, M)
    net.run(1 * msecond)
    assert (len(M.spikes) == 0)
    G.state(0)[:] = array([0.5, 1.5, 2.5])
    net.run(1 * msecond)
    i, t = zip(*sorted(M.spikes, key=itemgetter(0)))
    assert (i == (1, 2))
    for s in t:
        assert (is_approx_equal(s, 1 * msecond))

    # test that Threshold works as expected with specified state
    def test_specified_state(G):
        M = SpikeMonitor(G, True)
        net = Network(G, M)
        net.run(1 * msecond)
        assert (len(M.spikes) == 0)
        net.reinit()
        G.state(0)[:] = array([0.5, 1.5, 2.5])
        net.run(1 * msecond)
        assert (len(M.spikes) == 0)
        net.reinit()
        G.state(1)[:] = array([0.5, 1.5, 2.5])
        net.run(1 * msecond)
        i, t = zip(*sorted(M.spikes, key=itemgetter(0)))
        assert (i == (1, 2))
        for s in t:
            assert (is_approx_equal(s, 0 * msecond))

    G = NeuronGroup(3,
                    model=LazyStateUpdater(numstatevariables=2),
                    reset=Reset(0., state=1),
                    threshold=Threshold(1., state=1),
                    init=(0., 0.))
    test_specified_state(G)
    # use string threshold
    eqs = '''v : 1
             w : 1
          '''
    G = NeuronGroup(3, model=eqs, reset=Reset(0., state=1), threshold='w > 1')
    test_specified_state(G)

    # test that VariableThreshold works as expected
    def test_variable_threshold(G):
        M = SpikeMonitor(G, True)
        net = Network(G, M)
        get_default_clock().reinit()
        G.state(2)[:] = array([1., 2., 3.])  # the thresholds
        G.state(1)[:] = array([4., 1., 2.])  # the values
        net.run(1 * msecond)
        i, t = zip(*sorted(M.spikes, key=itemgetter(0)))
        assert (i == (0, ))
        assert (is_approx_equal(t[0], 0 * second))

    G = NeuronGroup(3,
                    model=LazyStateUpdater(numstatevariables=3),
                    reset=Reset(0., state=1),
                    threshold=VariableThreshold(2, state=1),
                    init=(0., 0., 0.))
    test_variable_threshold(G)

    # use string threshold
    eqs = '''v : 1
             w : 1
             x : 1
          '''
    G = NeuronGroup(3, model=eqs, reset=Reset(0., state=1), threshold='w > x')
    test_variable_threshold(G)

    # test that FunThreshold works as expected
    def f(S0, S1):
        return S0 > S1 * S1

    G = NeuronGroup(3,
                    model=LazyStateUpdater(numstatevariables=2),
                    reset=Reset(0.),
                    threshold=FunThreshold(f),
                    init=(0., 0.))
    G.state(0)[:] = array([2., 3., 10.])
    G.state(1)[:] = array([1., 2.,
                           3.])  # the square root of the threshold values
    M = SpikeMonitor(G, True)
    net = Network(G, M)
    get_default_clock().reinit()
    net.run(1 * msecond)
    i, t = zip(*sorted(M.spikes, key=itemgetter(0)))
    assert (i == (0, 2))
    for s in t:
        assert (is_approx_equal(s, 0 * msecond))

    # test that SimpleFunThreshold works as expected
    def f(S):
        return S > 1.

    G = NeuronGroup(3,
                    model=LazyStateUpdater(),
                    reset=Reset(0.),
                    threshold=SimpleFunThreshold(f),
                    init=(0., ))
    G.state(0)[:] = array([0.5, 1.5, 2.5])
    M = SpikeMonitor(G, True)
    net = Network(G, M)
    get_default_clock().reinit()
    net.run(1 * msecond)
    i, t = zip(*sorted(M.spikes, key=itemgetter(0)))
    assert (i == (1, 2))
    for s in t:
        assert (is_approx_equal(s, 0 * msecond))

    # test that EmpiricalThreshold works as expected
    G = NeuronGroup(1,
                    model=LazyStateUpdater(numstatevariables=2),
                    reset=NoReset(),
                    threshold=EmpiricalThreshold(1.,
                                                 refractory=0.5 * msecond,
                                                 state=1),
                    init=(0., 2.))
    M = SpikeMonitor(G, True)
    net = Network(G, M)
    get_default_clock().reinit()
    net.run(1.6 * msecond)
    i, t = zip(*sorted(M.spikes, key=itemgetter(1)))
    assert (i == (0, 0, 0, 0))
    for i, s in enumerate(t):
        assert (is_approx_equal(s, i * 0.5 * msecond))

    # test that PoissonThreshold works
    def test_poisson_threshold(G):
        init = float(1. / get_default_clock().dt
                     )  # should cause spiking at every time interval
        G.state(0)[:] = array([0., init, 0.])
        M = SpikeMonitor(G, True)
        net = Network(G, M)
        net.run(1 * msecond)
        assert (len(M.spikes))
        i, t = zip(*sorted(M.spikes, key=itemgetter(1)))
        assert (all(j == 1 for j in i))

    G = NeuronGroup(3,
                    model=LazyStateUpdater(),
                    reset=NoReset(),
                    threshold=PoissonThreshold())
    test_poisson_threshold(G)

    # Poisson threshold via a string threshold using the rand() function
    eqs = '''v : 1
             w : 1
             x : 1
          '''

    # A threshold with rand in it is not supported by CThreshold
    if not (get_global_preference('usecodegen')
            and get_global_preference('usecodegenthreshold')
            and get_global_preference('useweave')
            and get_global_preference('usecodegenweave')):
        G = NeuronGroup(3, model=eqs, reset=NoReset(), threshold='rand() < v')
        test_poisson_threshold(G)

    G = NeuronGroup(3,
                    model=eqs,
                    reset=NoReset(),
                    threshold=StringThreshold('rand() < v'))
    test_poisson_threshold(G)

    # test that HomogeneousPoissonThreshold works
    init = float(
        1. /
        get_default_clock().dt)  # should cause spiking at every time interval
    G = NeuronGroup(3,
                    model=LazyStateUpdater(),
                    reset=NoReset(),
                    threshold=HomogeneousPoissonThreshold())
    M = SpikeMonitor(G, True)
    net = Network(G, M)
    G.state(0)[:] = array(
        [0., init,
         0.])  # should do nothing, because only first neuron is looked at
    net.run(1 * msecond)
    assert (len(M.spikes) == 0)
    G.state(0)[:] = array(
        [init, 0.,
         0.])  # should do nothing, because only first neuron is looked at
    net.run(1 * msecond)