Skip to content

Commit

Permalink
Merge pull request #423 from brian-team/windows_testing
Browse files Browse the repository at this point in the history
Windows testing
  • Loading branch information
mstimberg committed Mar 10, 2015
2 parents c0f69ed + 47ac7da commit 2e814bc
Show file tree
Hide file tree
Showing 17 changed files with 301 additions and 41 deletions.
11 changes: 7 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ Documentation for Brian2 can be found at http://brian2.readthedocs.org

Brian2 is released under the terms of the CeCILL 2.1 license.

.. image:: https://pypip.in/v/Brian2/badge.png
:target: https://crate.io/packages/Brian2
.. image:: https://img.shields.io/pypi/v/Brian2.svg?style=flat-square
:target: https://pypi.python.org/pypi/Brian2

Testing status for master branch
--------------------------------

.. image:: https://travis-ci.org/brian-team/brian2.png?branch=master
.. image:: https://img.shields.io/travis/brian-team/brian2/master.svg?style=flat-square
:target: https://travis-ci.org/brian-team/brian2?branch=master

.. image:: https://coveralls.io/repos/brian-team/brian2/badge.png?branch=master
.. image:: https://img.shields.io/appveyor/ci/brianteam/brian2/master.svg?style=flat-square
:target: https://ci.appveyor.com/project/brianteam/brian2/branch/master

.. image:: https://img.shields.io/coveralls/brian-team/brian2/master.svg?style=flat-square
:target: https://coveralls.io/r/brian-team/brian2?branch=master
69 changes: 69 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# CI configuration for Windows tests on appveyor
# Based on Olivier Grisel's python-appveyor-demo

environment:
global:
# SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the
# /E:ON and /V:ON options are not enabled in the batch script intepreter
# See: http://stackoverflow.com/a/13751649/163740
CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\dev\\appveyor\\run_with_env.cmd"

matrix:
- PYTHON: "C:\\Python27-conda32"
PYTHON_VERSION: "2.7.8"
PYTHON_ARCH: "32"
STANDALONE: "FALSE"

- PYTHON: "C:\\Python27-conda64"
PYTHON_VERSION: "2.7.8"
PYTHON_ARCH: "64"
STANDALONE: "FALSE"

- PYTHON: "C:\\Python34-conda32"
PYTHON_VERSION: "3.4.1"
PYTHON_ARCH: "32"
STANDALONE: "FALSE"

- PYTHON: "C:\\Python34-conda64"
PYTHON_VERSION: "3.4.1"
PYTHON_ARCH: "64"
STANDALONE: "FALSE"

- PYTHON: "C:\\Python27-conda32"
PYTHON_VERSION: "2.7.8"
PYTHON_ARCH: "32"
STANDALONE: "TRUE"

- PYTHON: "C:\\Python27-conda64"
PYTHON_VERSION: "2.7.8"
PYTHON_ARCH: "64"
STANDALONE: "TRUE"

install:
# Install Python and miniconda
- "powershell .\\dev\\appveyor\\install_python.ps1"

# Prepend newly installed Python to the PATH of this build (this cannot be
# done from inside the powershell script as it would require to restart
# the parent CMD process).
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"

# Check that we have the expected version and architecture for Python
- "python --version"
- "python -c \"import struct; print(struct.calcsize('P') * 8)\""

# Install the build dependencies of the project via conda
- "conda install --yes --quiet numpy scipy nose sphinx sympy pyparsing jinja2 ipython setuptools"
- "pip install py-cpuinfo"

build: false # Not a C# project, build stuff at the test step instead.

test_script:
# Run the test suite
- "%CMD_IN_ENV% python -c \"import sys; print(sys.executable)\""
- "%CMD_IN_ENV% python setup.py install"
- "if \"%STANDALONE%\" == \"TRUE\" (
%CMD_IN_ENV% python .\\dev\\tools\\run_nose_tests_standalone.py
) ELSE (
%CMD_IN_ENV% python .\\dev\\tools\\run_nose_tests.py
)"
20 changes: 17 additions & 3 deletions brian2/devices/cpp_standalone/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,20 @@ def build(self, directory='output',
if net().name != '_fake_network']
synapses = []
for net in networks:
synapses.extend(s for s in net.objects if isinstance(s, Synapses))
net_synapses = [s for s in net.objects if isinstance(s, Synapses)]
synapses.extend(net_synapses)
# We don't currently support pathways with scalar delays
for synapse_obj in net_synapses:
for pathway in synapse_obj._pathways:
if not isinstance(pathway.variables['delay'],
DynamicArrayVariable):
error_msg = ('The "%s" pathway uses a scalar '
'delay (instead of a delay per synapse). '
'This is not yet supported. Do not '
'specify a delay in the Synapses(...) '
'call but instead set its delay attribute '
'afterwards.') % (pathway.name)
raise NotImplementedError(error_msg)

# Not sure what the best place is to call Network.after_run -- at the
# moment the only important thing it does is to clear the objects stored
Expand Down Expand Up @@ -642,9 +655,10 @@ def build(self, directory='output',
writer.header_files.append('brianlib/'+file)

# Copy the CSpikeQueue implementation
spikequeue_h = os.path.join(directory, 'brianlib', 'spikequeue.h')
shutil.copy2(os.path.join(os.path.split(inspect.getsourcefile(Synapses))[0], 'cspikequeue.cpp'),
spikequeue_h)
os.path.join(directory, 'brianlib', 'spikequeue.h'))
shutil.copy2(os.path.join(os.path.split(inspect.getsourcefile(Synapses))[0], 'stdint_compat.h'),
os.path.join(directory, 'brianlib', 'stdint_compat.h'))

writer.source_files.extend(additional_source_files)
writer.header_files.extend(additional_header_files)
Expand Down
1 change: 0 additions & 1 deletion brian2/devices/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,5 +442,4 @@ def restore_device():

for device in all_devices.itervalues():
device.reinit()
set_device('runtime')
restore_initial_state()
2 changes: 1 addition & 1 deletion brian2/synapses/cspikequeue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include<vector>
#include<map>
#include<algorithm>
#include<stdint.h>
#include"stdint_compat.h"
#include<assert.h>
using namespace std;

Expand Down
9 changes: 6 additions & 3 deletions brian2/synapses/cythonspikequeue.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from libcpp.vector cimport vector
from libcpp.string cimport string

import cython
from cython.operator import dereference
from cython.operator cimport dereference

Expand All @@ -12,11 +13,13 @@ import numpy as np

np.import_array()

cdef extern from "inttypes.h":

cdef extern from "stdint_compat.h":
# Note that this does not actually define int32_t as int (which might be
# wrong on a 64bit system), it only tells Cython that int32_t is an int-like
# type
# wrong on a 64bit system), it only tells Cython that int32_t and int_64t
# are int-like types
ctypedef int int32_t
ctypedef int int64_t

cdef extern from "cspikequeue.cpp":
cdef cppclass CSpikeQueue[T]:
Expand Down
7 changes: 7 additions & 0 deletions brian2/synapses/stdint_compat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Work around the fact that older MSVC versions don't have stdint.h
#ifdef _MSC_VER
typedef __int32 int32_t;
typedef __int64 int64_t;
#else
#include <stdint.h>
#endif
12 changes: 11 additions & 1 deletion brian2/tests/test_cpp_standalone.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
@attr('cpp_standalone', 'standalone-only')
@with_setup(teardown=restore_device)
def test_cpp_standalone(with_output=False):
previous_device = get_device()
set_device('cpp_standalone')
##### Define the model
tau = 1*ms
Expand Down Expand Up @@ -49,10 +50,12 @@ def test_cpp_standalone(with_output=False):
assert len(M.t) == len(M.i)
assert M.t[0] == 0.
assert M.t[-1] == 100*ms - defaultclock.dt
set_device(previous_device)

@attr('cpp_standalone', 'standalone-only')
@with_setup(teardown=restore_device)
def test_multiple_connects(with_output=False):
previous_device = get_device()
set_device('cpp_standalone')
G = NeuronGroup(10, 'v:1')
S = Synapses(G, G, 'w:1')
Expand All @@ -65,10 +68,12 @@ def test_multiple_connects(with_output=False):
device.build(directory=tempdir, compile=True, run=True,
with_output=True)
assert len(S) == 2 and len(S.w[:]) == 2
set_device(previous_device)

@attr('cpp_standalone', 'standalone-only')
@with_setup(teardown=restore_device)
def test_storing_loading(with_output=False):
previous_device = get_device()
set_device('cpp_standalone')
G = NeuronGroup(10, '''v : volt
x : 1
Expand Down Expand Up @@ -103,11 +108,12 @@ def test_storing_loading(with_output=False):
assert_allclose(S.n_syn[:], n)
assert_allclose(G.b[:], b)
assert_allclose(S.b_syn[:], b)
set_device(previous_device)

@attr('cpp_standalone', 'standalone-only')
@with_setup(teardown=restore_device)
def test_openmp_consistency(with_output=False):

previous_device = get_device()
n_cells = 100
n_recorded = 10
numpy.random.seed(42)
Expand Down Expand Up @@ -201,10 +207,12 @@ def test_openmp_consistency(with_output=False):
assert_allclose(results[key1]['v'], results[key2]['v'])
assert_allclose(results[key1]['r'], results[key2]['r'])
assert_allclose(results[key1]['s'], results[key2]['s'])
set_device(previous_device)

@attr('cpp_standalone', 'standalone-only')
@with_setup(teardown=restore_device)
def test_timedarray(with_output=True):
previous_device = get_device()
set_device('cpp_standalone')

defaultclock.dt = 0.1*ms
Expand Down Expand Up @@ -233,6 +241,8 @@ def test_timedarray(with_output=True):
# only NaN
assert_equal(mon[3].y[:], np.nan)

set_device(previous_device)


if __name__=='__main__':
# Print the debug output when testing this file only but not when running
Expand Down
41 changes: 27 additions & 14 deletions brian2/tests/test_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,26 @@ def test_spike_monitor():
assert_array_equal(t, mon.t)
assert_array_equal(t_, mon.t_)


def test_synapses_state_monitor():
G = NeuronGroup(2, '')
S = Synapses(G, G, 'w: siemens')
S.connect(True)
S.w = 'j*nS'

# record from a Synapses object (all synapses connecting to neuron 1)
synapse_mon = StateMonitor(S, 'w', record=S[:, 1])
synapse_mon2 = StateMonitor(S, 'w', record=S['j==1'])

net = Network(G, S, synapse_mon, synapse_mon2)
net.run(10*ms)
# Synaptic variables
assert_allclose(synapse_mon[S[0, 1]].w, 1*nS)
assert_allclose(synapse_mon.w[1], 1*nS)
assert_allclose(synapse_mon2[S[0, 1]].w, 1*nS)
assert_allclose(synapse_mon2[S['i==0 and j==1']].w, 1*nS)
assert_allclose(synapse_mon2.w[1], 1*nS)

@attr('standalone-compatible')
@with_setup(teardown=restore_device)
def test_state_monitor():
Expand Down Expand Up @@ -63,16 +83,14 @@ def test_state_monitor():
# Use a StateMonitor recording everything
all_mon = StateMonitor(G, True, record=True)

# record from a Synapses object (all synapses connecting to neuron 1)
synapse_mon = StateMonitor(S, 'w', record=S[:, 1])
synapse_mon2 = StateMonitor(S, 'w', record=S['j==1'])

# Record synapses with explicit indices (the only way allowed in standalone)
synapse_mon = StateMonitor(S, 'w', record=np.arange(len(G)**2))

net = Network(G, S, nothing_mon,
v_mon, v_mon1,
multi_mon, multi_mon1,
all_mon,
synapse_mon, synapse_mon2)
synapse_mon)
net.run(10*ms)

# Check time recordings
Expand Down Expand Up @@ -102,12 +120,9 @@ def test_state_monitor():

assert all(all_mon[0].not_refractory[:] == True)

# Synaptic variables
assert_allclose(synapse_mon[S[0, 1]].w, 1*nS)
assert_allclose(synapse_mon.w[1], 1*nS)
assert_allclose(synapse_mon2[S[0, 1]].w, 1*nS)
assert_allclose(synapse_mon2[S['i==0 and j==1']].w, 1*nS)
assert_allclose(synapse_mon2.w[1], 1*nS)
# Synapses
assert_allclose(synapse_mon.w[:], np.tile(S.j[:]*nS,
(synapse_mon.w[:].shape[1], 1)).T)

@attr('standalone-compatible')
@with_setup(teardown=restore_device)
Expand Down Expand Up @@ -151,14 +166,12 @@ def test_rate_monitor():
assert_allclose(rate_mon.rate_, np.asarray(np.ones(10) / defaultclock.dt))

G = NeuronGroup(10, 'v : 1', threshold='v>1') # no reset
G.v[:5] = 1.1 # Half of the neurons fire every time step
G.v['i<5'] = 1.1 # Half of the neurons fire every time step
rate_mon = PopulationRateMonitor(G)
net = Network(G, rate_mon)
net.run(10*defaultclock.dt)
assert_allclose(rate_mon.rate, 0.5 * np.ones(10) / defaultclock.dt)
assert_allclose(rate_mon.rate_, 0.5 *np.asarray(np.ones(10) / defaultclock.dt))
assert_array_equal(rate_mon.rate['t>0.5*ms'],
rate_mon.rate[np.nonzero(rate_mon.t>0.5*ms)[0]])

@attr('standalone-compatible')
@with_setup(teardown=restore_device)
Expand Down
2 changes: 1 addition & 1 deletion brian2/tests/test_spatialneuron.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def test_infinitecable():
assert_allclose(v[t>0.5*ms],theory[t>0.5*ms],rtol=0.01) # 1% error tolerance (not exact because not infinite cable)


@attr('long', 'standalone-compatible')
@attr('long')
@with_setup(teardown=restore_initial_state)
def test_finitecable():
'''
Expand Down
6 changes: 3 additions & 3 deletions brian2/tests/test_spikegenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def test_spikegenerator_basic():
net.run(5*ms)
for idx in xrange(5):
generator_spikes = sorted([(idx, time) for time in times[indices==idx]])
recorded_spikes = sorted([(idx, time) for time in s_mon.t['i==%d' % idx]])
recorded_spikes = sorted([(idx, time) for time in s_mon.t[s_mon.i==idx]])
assert generator_spikes == recorded_spikes

@attr('standalone-compatible')
Expand All @@ -69,7 +69,7 @@ def test_spikegenerator_basic_sorted():
net.run(5*ms)
for idx in xrange(5):
generator_spikes = sorted([(idx, time) for time in times[indices==idx]])
recorded_spikes = sorted([(idx, time) for time in s_mon.t['i==%d' % idx]])
recorded_spikes = sorted([(idx, time) for time in s_mon.t[s_mon.i==idx]])
assert generator_spikes == recorded_spikes

@attr('standalone-compatible')
Expand All @@ -87,7 +87,7 @@ def test_spikegenerator_period():
net.run(10*ms)
for idx in xrange(5):
generator_spikes = sorted([(idx, time) for time in times[indices==idx]] + [(idx, time+5*ms) for time in times[indices==idx]])
recorded_spikes = sorted([(idx, time) for time in s_mon.t['i==%d' % idx]])
recorded_spikes = sorted([(idx, time) for time in s_mon.t[s_mon.i==idx]])
assert generator_spikes == recorded_spikes

@attr('standalone-compatible')
Expand Down
4 changes: 2 additions & 2 deletions brian2/tests/test_subgroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ def test_subexpression_no_references():
@with_setup(teardown=restore_device)
def test_synaptic_propagation():
G1 = NeuronGroup(10, 'v:1', threshold='v>1', reset='v=0')
G1.v[1::2] = 1.1 # odd numbers should spike
G1.v['i%2==1'] = 1.1 # odd numbers should spike
G2 = NeuronGroup(20, 'v:1')
SG1 = G1[1:6]
SG2 = G2[10:]
Expand Down Expand Up @@ -421,7 +421,7 @@ def test_no_reference_4():
Using subgroups without keeping an explicit reference. Synapses
'''
G1 = NeuronGroup(10, 'v:1', threshold='v>1', reset='v=0')
G1.v[1::2] = 1.1 # odd numbers should spike
G1.v['i%2==1'] = 1.1 # odd numbers should spike
G2 = NeuronGroup(20, 'v:1')
S = Synapses(G1[1:6], G2[10:], pre='v+=1')
S.connect('i==j')
Expand Down

0 comments on commit 2e814bc

Please sign in to comment.