Ejemplo n.º 1
0
def test_set_interval_warning():
    clock = Clock(dt=0.1 * ms)
    with catch_logs() as logs:
        clock.set_interval(0 * second, 1000 * second)  # no problem
    assert len(logs) == 0
    with catch_logs() as logs:
        clock.set_interval(0 * second, 10000000000 * second)  # too long
    assert len(logs) == 1
    assert logs[0][1].endswith('many_timesteps')
Ejemplo n.º 2
0
def test_warning_internal_variables():
    group1 = SimpleGroup(namespace=None, variables={'N': Constant('N', 5)})
    group2 = SimpleGroup(namespace=None, variables={'N': Constant('N', 7)})
    with catch_logs() as l:
        group1.resolve_all(['N'],
                           run_namespace={'N':
                                          5})  # should not raise a warning
        assert len(l) == 0, 'got warnings: %s' % str(l)
    with catch_logs() as l:
        group2.resolve_all(['N'], run_namespace={'N':
                                                 5})  # should raise a warning
        assert len(l) == 1, 'got warnings: %s' % str(l)
        assert l[0][1].endswith('.resolution_conflict')
Ejemplo n.º 3
0
def test_missing_refractory_warning():
    # Forgotten refractory argument
    with catch_logs() as l:
        group = NeuronGroup(1, 'dv/dt = -v / (10*ms) : 1 (unless refractory)',
                            threshold='v > 1', reset='v = 0')
    assert len(l) == 1
    assert l[0][0] == 'WARNING' and l[0][1].endswith('no_refractory')
Ejemplo n.º 4
0
def test_math_functions(func, needs_c99_support):
    '''
    Test that math functions give the same result, regardless of whether used
    directly or in generated Python or C++ code.
    '''
    if not get_device() == RuntimeDevice or prefs.codegen.target != 'numpy':
        if needs_c99_support and not compiler_supports_c99():
            pytest.skip('Support for function "{}" needs a compiler with C99 '
                        'support.')
    test_array = np.array([-1, -0.5, 0, 0.5, 1])

    with catch_logs() as _:  # Let's suppress warnings about illegal values
        # Calculate the result directly
        numpy_result = func(test_array)

        # Calculate the result in a somewhat complicated way by using a
        # subexpression in a NeuronGroup
        if func.__name__ == 'absolute':
            # we want to use the name abs instead of absolute
            func_name = 'abs'
        else:
            func_name = func.__name__
        G = NeuronGroup(
            len(test_array), '''func = {func}(variable) : 1
                           variable : 1'''.format(func=func_name))
        G.variable = test_array
        mon = StateMonitor(G, 'func', record=True)
        net = Network(G, mon)
        net.run(defaultclock.dt)

        assert_allclose(
            numpy_result,
            mon.func_.flatten(),
            err_msg='Function %s did not return the correct values' %
            func.__name__)
def test_check_for_invalid_values_linear_integrator():
    # A differential equation that cannot be solved by the linear
    # integrator should return nan values to warn the user, and not silently
    # return incorrect values. See discussion on
    # https://github.com/angela-team/angela2/issues/626
    a = 0.0 / ms
    b = 1.0 / ms
    c = -0.5 / ms
    d = -0.1 / ms
    eqs = '''
    dx/dt = a * x + b * y : 1
    dy/dt = c * x + d * y : 1
    '''
    G = NeuronGroup(1,
                    eqs,
                    threshold='x > 100',
                    reset='x = 0',
                    method='exact',
                    method_options={'simplify': False})
    G.x = 1
    angelaLogger._log_messages.clear(
    )  # because the log message is set to be shown only once
    with catch_logs() as clog:
        try:
            run(1 * ms)
            # this check allows for the possibility that we improve the linear
            # integrator in the future so that it can handle this equation
            if numpy.isnan(G.x[0]):
                assert 'invalid_values' in repr(clog)
            else:
                assert G.x[0] != 0
        except angelaObjectException as exc:
            assert isinstance(exc.__cause__, UnsupportedEquationsException)
Ejemplo n.º 6
0
def test_explicit_namespace():
    ''' Test resolution with an explicitly provided namespace '''
    group = SimpleGroup(namespace={'variable': 42}, variables={})

    # Explicitly provided
    with catch_logs() as l:
        assert group._resolve('variable', {}).get_value_with_unit() == 42
        assert len(l) == 0

    # Value from an explicit run namespace
    with catch_logs() as l:
        assert group._resolve('yet_another_var',
                              run_namespace={
                                  'yet_another_var': 17
                              }).get_value_with_unit() == 17
        assert len(l) == 0
Ejemplo n.º 7
0
def test_delete_directory():
    set_device('cpp_standalone', build_on_run=True, directory=None)
    group = NeuronGroup(10, 'dv/dt = -v / (10*ms) : volt', method='exact')
    group.v = np.arange(10) * mV  # uses the static array mechanism
    run(defaultclock.dt)
    # Add a new file
    dummy_file = os.path.join(device.project_dir, 'results', 'dummy.txt')
    open(dummy_file, 'w').flush()
    assert os.path.isfile(dummy_file)
    with catch_logs() as logs:
        device.delete(directory=True)
    assert len(logs) == 1
    assert os.path.isfile(dummy_file)
    with catch_logs() as logs:
        device.delete(directory=True, force=True)
    assert len(logs) == 0
    # everything should be deleted
    assert not os.path.exists(device.project_dir)
Ejemplo n.º 8
0
def test_warning():
    from angela2.core.functions import DEFAULT_FUNCTIONS
    from angela2.units.stdunits import cm as angela_cm
    # Name in external namespace clashes with unit/function name
    exp = 23
    cm = 42
    group = SimpleGroup(namespace=None, variables={})
    namespace = get_local_namespace(level=0)
    with catch_logs() as l:
        resolved = group.resolve_all(['exp'], namespace)['exp']
        assert resolved == DEFAULT_FUNCTIONS['exp']
        assert len(l) == 1, 'got warnings: %s' % str(l)
        assert l[0][1].endswith('.resolution_conflict')
    with catch_logs() as l:
        resolved = group.resolve_all(['cm'], namespace)['cm']
        assert resolved.get_value_with_unit() == angela_cm
        assert len(l) == 1, 'got warnings: %s' % str(l)
        assert l[0][1].endswith('.resolution_conflict')
Ejemplo n.º 9
0
def test_state_variables_group_as_index_problematic():
    G = NeuronGroup(10, 'v : 1')
    SG = G[4:9]
    G.v = 1
    tests = [('i', 1), ('N', 1), ('N + i', 2), ('v', 0)]
    for value, n_warnings in tests:
        with catch_logs() as l:
            G.v.__setitem__(SG, value)
            assert len(l) == n_warnings, 'expected %d, got %d warnings' % (
                n_warnings, len(l))
            assert all([
                entry[1].endswith('ambiguous_string_expression') for entry in l
            ])
def test_spikegenerator_extreme_period():
    '''
    Basic test for `SpikeGeneratorGroup`.
    '''
    indices = np.array([0, 1, 2])
    times   = np.array([0, 1, 2]) * ms
    SG = SpikeGeneratorGroup(5, indices, times, period=1e6*second)
    s_mon = SpikeMonitor(SG)
    with catch_logs() as l:
        run(10*ms)

    assert_equal(s_mon.i, np.array([0, 1, 2]))
    assert_allclose(s_mon.t, [0, 1, 2]*ms)
    assert len(l) == 1 and l[0][1].endswith('spikegenerator_long_period')
def test_poissongroup_namespace():
    rate_const = 0 * Hz
    P = PoissonGroup(1,
                     rates='rate_const',
                     namespace={'rate_const': 1 / defaultclock.dt},
                     name='poissongroup_%s' % (uuid.uuid4().hex))
    P2 = PoissonGroup(1, rates='rate_const')
    mon = SpikeMonitor(P)
    mon2 = SpikeMonitor(P2)
    with catch_logs() as l:
        run(2 * defaultclock.dt)
        assert len(l) == 1
        assert l[0][1].endswith('resolution_conflict')
    assert mon.num_spikes == 2
    assert mon2.num_spikes == 0
def test_spikegenerator_multiple_runs():
    indices = np.zeros(5)
    times = np.arange(5)*ms
    spike_gen = SpikeGeneratorGroup(1, indices, times)  # all good
    spike_mon = SpikeMonitor(spike_gen)
    run(5*ms)
    # Setting the same spike times again should not do anything, since they are
    # before the start of the current simulation
    spike_gen.set_spikes(indices, times)
    # however, a warning should be raised
    with catch_logs() as l:
        run(5*ms)
        device.build(direct_call=False, **device.build_options)
    assert len(l) == 1 and l[0][1].endswith('ignored_spikes')
    assert spike_mon.num_spikes == 5
def test_multiple_noise_variables_deterministic_noise(
        fake_randn_randn_fixture):
    all_eqs = [
        '''dx/dt = y : 1
                          dy/dt = -y / (10*ms) + dt**-.5*0.5*ms**-1.5 + dt**-.5*0.5*ms**-1.5: Hz
                     ''', '''dx/dt = y + dt**-.5*0.5*ms**-0.5: 1
                        dy/dt = -y / (10*ms) + dt**-.5*0.5 * ms**-1.5 : Hz
                '''
    ]
    all_eqs_noise = [
        '''dx/dt = y : 1
                          dy/dt = -y / (10*ms) + xi_1 * ms**-1.5 + xi_2 * ms**-1.5: Hz
                     ''', '''dx/dt = y + xi_1*ms**-0.5: 1
                        dy/dt = -y / (10*ms) + xi_2 * ms**-1.5 : Hz
                     '''
    ]
    for eqs, eqs_noise in zip(all_eqs, all_eqs_noise):
        G = NeuronGroup(2, eqs, method='euler')
        G.x = [5, 17]
        G.y = [25, 5] * Hz
        mon = StateMonitor(G, ['x', 'y'], record=True)
        net = Network(G, mon)
        net.run(10 * ms)
        no_noise_x, no_noise_y = mon.x[:], mon.y[:]

        for method_name, method in [('euler', euler), ('heun', heun)]:
            with catch_logs('WARNING'):
                G = NeuronGroup(2, eqs_noise, method=method)
                G.x = [5, 17]
                G.y = [25, 5] * Hz
                mon = StateMonitor(G, ['x', 'y'], record=True)
                net = Network(G, mon)
                net.run(10 * ms)
            assert_allclose(mon.x[:],
                            no_noise_x,
                            err_msg='Method %s gave incorrect results' %
                            method_name)
            assert_allclose(mon.y[:],
                            no_noise_y,
                            err_msg='Method %s gave incorrect results' %
                            method_name)
def test_multiple_noise_variables_extended():
    # Some actual simulations with multiple noise variables
    eqs = '''dx/dt = y : 1
             dy/dt = - 1*ms**-1*y - 40*ms**-2*x : Hz
            '''
    all_eqs_noise = [
        '''dx/dt = y : 1
                        dy/dt = noise_factor*ms**-1.5*xi_1 + noise_factor*ms**-1.5*xi_2
                           - 1*ms**-1*y - 40*ms**-2*x : Hz
                     ''', '''dx/dt = y + noise_factor*ms**-0.5*xi_1: 1
                        dy/dt = noise_factor*ms**-1.5*xi_2
                            - 1*ms**-1*y - 40*ms**-2*x : Hz
                     '''
    ]
    G = NeuronGroup(2, eqs, method='euler')
    G.x = [0.5, 1]
    G.y = [0, 0.5] * Hz
    mon = StateMonitor(G, ['x', 'y'], record=True)
    net = Network(G, mon)
    net.run(10 * ms)
    no_noise_x, no_noise_y = mon.x[:], mon.y[:]

    for eqs_noise in all_eqs_noise:
        for method_name, method in [('euler', euler), ('heun', heun)]:
            with catch_logs('WARNING'):
                G = NeuronGroup(2, eqs_noise, method=method)
                G.x = [0.5, 1]
                G.y = [0, 0.5] * Hz
                mon = StateMonitor(G, ['x', 'y'], record=True)
                net = Network(G, mon)
                # We run it deterministically, but still we'd detect major errors (e.g.
                # non-stochastic terms that are added twice, see #330
                net.run(10 * ms, namespace={'noise_factor': 0})
            assert_allclose(mon.x[:],
                            no_noise_x,
                            err_msg='Method %s gave incorrect results' %
                            method_name)
            assert_allclose(mon.y[:],
                            no_noise_y,
                            err_msg='Method %s gave incorrect results' %
                            method_name)
Ejemplo n.º 15
0
def test_synapses_access_subgroups_problematic():
    G1 = NeuronGroup(5, 'x:1')
    G2 = NeuronGroup(10, 'y:1')
    SG1 = G1[2:5]
    SG2 = G2[4:9]
    S = Synapses(G1, G2, 'w:1')
    S.connect()

    # Note that "j" is not ambiguous, because the equivalent in the target group
    # is called "i" (this previously raised a warning)
    tests = [
        ((SG1, slice(None)), 'i', 1),
        ((SG1, slice(None)), 'i + N_pre', 2),
        ((SG1, slice(None)), 'N_pre', 1),
        ((slice(None), SG2), 'j', 0),
        ((slice(None), SG2), 'N_post', 1),
        ((slice(None), SG2), 'N', 1),
        ((SG1, SG2), 'i', 1),
        ((SG1, SG2), 'i + j', 1),
        ((SG1, SG2), 'N_pre', 1),
        ((SG1, SG2), 'j', 0),
        ((SG1, SG2), 'N_post', 1),
        ((SG1, SG2), 'N', 1),
        # These should not raise a warning
        ((SG1, SG2), 'w', 0),
        ((SG1, SG2), 'x_pre', 0),
        ((SG1, SG2), 'y_post', 0),
        ((SG1, SG2), 'y', 0)
    ]
    for item, value, n_warnings in tests:
        with catch_logs() as l:
            S.w.__setitem__(item, value)
            assert len(l) == n_warnings, 'expected %d, got %d warnings' % (
                n_warnings, len(l))
            assert all([
                entry[1].endswith('ambiguous_string_expression') for entry in l
            ])
Ejemplo n.º 16
0
def test_rate_monitor_smoothed_rate():
    # Test the filter response by having a single spiking neuron
    G = SpikeGeneratorGroup(1, [0], [1]*ms)
    r_mon = PopulationRateMonitor(G)
    run(3*ms)
    index = int(np.round(1*ms/defaultclock.dt))
    except_index = np.array([idx for idx in range(len(r_mon.rate))
                             if idx != index])
    assert_array_equal(r_mon.rate[except_index], 0*Hz)
    assert_allclose(r_mon.rate[index], 1/defaultclock.dt)
    ### Flat window
    # Using a flat window of size = dt should not change anything
    assert_allclose(r_mon.rate, r_mon.smooth_rate(window='flat', width=defaultclock.dt))
    smoothed = r_mon.smooth_rate(window='flat', width=5*defaultclock.dt)
    assert_array_equal(smoothed[:index-2], 0*Hz)
    assert_array_equal(smoothed[index+3:], 0*Hz)
    assert_allclose(smoothed[index-2:index+3], 0.2/defaultclock.dt)
    with catch_logs(log_level=logging.INFO):
        smoothed2 = r_mon.smooth_rate(window='flat', width=5.4*defaultclock.dt)
        assert_array_equal(smoothed, smoothed2)

    ### Gaussian window
    width = 5*defaultclock.dt
    smoothed = r_mon.smooth_rate(window='gaussian', width=width)
    # 0 outside of window
    assert_array_equal(smoothed[:index-10], 0*Hz)
    assert_array_equal(smoothed[index+11:], 0*Hz)
    # Gaussian around the spike
    gaussian = np.exp(-(r_mon.t[index-10:index+11] - 1*ms)**2/(2*width**2))
    gaussian /= sum(gaussian)
    assert_allclose(smoothed[index-10:index+11], 1/defaultclock.dt*gaussian)

    ### Arbitrary window
    window = np.ones(5)
    smoothed_flat = r_mon.smooth_rate(window='flat', width=5*defaultclock.dt)
    smoothed_custom = r_mon.smooth_rate(window=window)
    assert_allclose(smoothed_flat, smoothed_custom)
def test_locally_constant_check():
    default_dt = defaultclock.dt
    # The linear state update can handle additive time-dependent functions
    # (e.g. a TimedArray) but only if it can be safely assumed that the function
    # is constant over a single time check
    ta0 = TimedArray(np.array([1]), dt=default_dt)  # ok
    ta1 = TimedArray(np.array([1]), dt=2 * default_dt)  # ok
    ta2 = TimedArray(np.array([1]), dt=default_dt / 2)  # not ok
    ta3 = TimedArray(np.array([1]), dt=default_dt * 1.5)  # not ok

    for ta_func, ok in zip([ta0, ta1, ta2, ta3], [True, True, False, False]):
        # additive
        G = NeuronGroup(1,
                        'dv/dt = -v/(10*ms) + ta(t)*Hz : 1',
                        method='exact',
                        namespace={'ta': ta_func})
        net = Network(G)
        if ok:
            # This should work
            net.run(0 * ms)
        else:
            # This should not
            with catch_logs():
                with pytest.raises(angelaObjectException) as exc:
                    net.run(0 * ms)
                    assert exc.errisinstance(UnsupportedEquationsException)

        # multiplicative
        G = NeuronGroup(1,
                        'dv/dt = -v*ta(t)/(10*ms) : 1',
                        method='exact',
                        namespace={'ta': ta_func})
        net = Network(G)
        if ok:
            # This should work
            net.run(0 * ms)
        else:
            # This should not
            with catch_logs():
                with pytest.raises(angelaObjectException) as exc:
                    net.run(0 * ms)
                    assert exc.errisinstance(UnsupportedEquationsException)

    # If the argument is more than just "t", we cannot guarantee that it is
    # actually locally constant
    G = NeuronGroup(1,
                    'dv/dt = -v*ta(t/2.0)/(10*ms) : 1',
                    method='exact',
                    namespace={'ta': ta0})
    net = Network(G)
    with pytest.raises(angelaObjectException) as exc:
        net.run(0 * ms)
        assert exc.errisinstance(UnsupportedEquationsException)

    # Arbitrary functions are not constant over a time step
    G = NeuronGroup(1,
                    'dv/dt = -v/(10*ms) + sin(2*pi*100*Hz*t)*Hz : 1',
                    method='exact')
    net = Network(G)
    with pytest.raises(angelaObjectException) as exc:
        net.run(0 * ms)
        assert exc.errisinstance(UnsupportedEquationsException)

    # Stateful functions aren't either
    G = NeuronGroup(1, 'dv/dt = -v/(10*ms) + rand()*Hz : 1', method='exact')
    net = Network(G)
    with pytest.raises(angelaObjectException) as exc:
        net.run(0 * ms)
        assert exc.errisinstance(UnsupportedEquationsException)

    # Neither is "t" itself
    G = NeuronGroup(1, 'dv/dt = -v/(10*ms) + t/second**2 : 1', method='exact')
    net = Network(G)
    with pytest.raises(angelaObjectException) as exc:
        net.run(0 * ms)
        assert exc.errisinstance(UnsupportedEquationsException)

    # But if the argument is not referring to t, all should be well
    G = NeuronGroup(1,
                    'dv/dt = -v/(10*ms) + sin(2*pi*100*Hz*5*second)*Hz : 1',
                    method='exact')
    net = Network(G)
    net.run(0 * ms)
def test_determination():
    '''
    Test the determination of suitable state updaters.
    '''
    # To save some typing
    apply_stateupdater = StateUpdateMethod.apply_stateupdater

    eqs = Equations('dv/dt = -v / (10*ms) : 1')
    # Just make sure that state updaters know about the two state variables
    variables = {'v': Variable(name='v'), 'w': Variable(name='w')}

    # all methods should work for these equations.
    # First, specify them explicitly (using the object)
    for integrator in (
            linear,
            euler,
            exponential_euler,  #TODO: Removed "independent" here due to the issue in sympy 0.7.4
            rk2,
            rk4,
            heun,
            milstein):
        with catch_logs() as logs:
            returned = apply_stateupdater(eqs, variables, method=integrator)
            assert len(logs) == 0, 'Got %d unexpected warnings: %s' % (
                len(logs), str([l[2] for l in logs]))

    # Equation with multiplicative noise, only milstein and heun should work
    eqs = Equations('dv/dt = -v / (10*ms) + v*xi*second**-.5: 1')
    for integrator in (linear, independent, euler, exponential_euler, rk2,
                       rk4):
        with pytest.raises(UnsupportedEquationsException):
            apply_stateupdater(eqs, variables, integrator)

    for integrator in (heun, milstein):
        with catch_logs() as logs:
            returned = apply_stateupdater(eqs, variables, method=integrator)
            assert len(logs) == 0, 'Got %d unexpected warnings: %s' % (
                len(logs), str([l[2] for l in logs]))

    # Arbitrary functions (converting equations into abstract code) should
    # always work
    my_stateupdater = lambda eqs, vars, options: 'x_new = x'
    with catch_logs() as logs:
        returned = apply_stateupdater(eqs, variables, method=my_stateupdater)
        # No warning here
        assert len(logs) == 0

    # Specification with names
    eqs = Equations('dv/dt = -v / (10*ms) : 1')
    for name, integrator in [
        ('exact', exact),
        ('linear', linear),
        ('euler', euler),
            #('independent', independent), #TODO: Removed "independent" here due to the issue in sympy 0.7.4
        ('exponential_euler', exponential_euler),
        ('rk2', rk2),
        ('rk4', rk4),
        ('heun', heun),
        ('milstein', milstein)
    ]:
        with catch_logs() as logs:
            returned = apply_stateupdater(eqs, variables, method=name)
            # No warning here
            assert len(logs) == 0

    # Now all except heun and milstein should refuse to work
    eqs = Equations('dv/dt = -v / (10*ms) + v*xi*second**-.5: 1')
    for name in [
            'linear', 'exact', 'independent', 'euler', 'exponential_euler',
            'rk2', 'rk4'
    ]:
        with pytest.raises(UnsupportedEquationsException):
            apply_stateupdater(eqs, variables, method=name)

    # milstein should work
    with catch_logs() as logs:
        apply_stateupdater(eqs, variables, method='milstein')
        assert len(logs) == 0

    # heun should work
    with catch_logs() as logs:
        apply_stateupdater(eqs, variables, method='heun')
        assert len(logs) == 0

    # non-existing name
    with pytest.raises(ValueError):
        apply_stateupdater(eqs, variables, method='does_not_exist')

    # Automatic state updater choice should return linear for linear equations,
    # euler for non-linear, non-stochastic equations and equations with
    # additive noise, heun for equations with multiplicative noise
    # Because it is somewhat fragile, the "independent" state updater is not
    # included in this list
    all_methods = [
        'linear', 'exact', 'exponential_euler', 'euler', 'heun', 'milstein'
    ]
    eqs = Equations('dv/dt = -v / (10*ms) : 1')
    with catch_logs(log_level=logging.INFO) as logs:
        apply_stateupdater(eqs, variables, all_methods)
        assert len(logs) == 1
        assert ('linear' in logs[0][2]) or ('exact' in logs[0][2])

    # This is conditionally linear
    eqs = Equations('''dv/dt = -(v + w**2)/ (10*ms) : 1
                       dw/dt = -w/ (10*ms) : 1''')
    with catch_logs(log_level=logging.INFO) as logs:
        apply_stateupdater(eqs, variables, all_methods)
        assert len(logs) == 1
        assert 'exponential_euler' in logs[0][2]

    # # Do not test for now
    # eqs = Equations('dv/dt = sin(t) / (10*ms) : 1')
    # assert apply_stateupdater(eqs, variables) is independent

    eqs = Equations('dv/dt = -sqrt(v) / (10*ms) : 1')
    with catch_logs(log_level=logging.INFO) as logs:
        apply_stateupdater(eqs, variables, all_methods)
        assert len(logs) == 1
        assert "'euler'" in logs[0][2]

    eqs = Equations('dv/dt = -v / (10*ms) + 0.1*second**-.5*xi: 1')
    with catch_logs(log_level=logging.INFO) as logs:
        apply_stateupdater(eqs, variables, all_methods)
        assert len(logs) == 1
        assert "'euler'" in logs[0][2]

    eqs = Equations('dv/dt = -v / (10*ms) + v*0.1*second**-.5*xi: 1')
    with catch_logs(log_level=logging.INFO) as logs:
        apply_stateupdater(eqs, variables, all_methods)
        assert len(logs) == 1
        assert "'heun'" in logs[0][2]