Example #1
0
def reset_brian2(sleep_time: float = 0.25, **kwargs) -> None:
    device.reinit()
    device.activate()
    gc.collect()
    # workaround https://github.com/brian-team/brian2/issues/905
    sleep(sleep_time)
    setup_brian2(**kwargs)
Example #2
0
 def runtest(self):
     import matplotlib as _mpl
     _mpl.use('Agg')
     import numpy as np
     from brian2 import prefs
     from brian2.utils.filetools import ensure_directory_of_file
     prefs.codegen.target = self.codegen_target
     prefs.core.default_float_dtype = self.dtype
     # Move to the file's directory for the run, so that it can do relative
     # imports and load files (e.g. figure style files)
     curdir = os.getcwd()
     os.chdir(os.path.dirname(self.filename))
     sys.path.append(os.path.dirname(self.filename))
     try:
         runpy.run_path(self.filename, run_name='__main__')
         if self.codegen_target == 'cython' and self.dtype == np.float64:
             for fignum in _mpl.pyplot.get_fignums():
                 fname = os.path.relpath(self.filename, self.example_dir)
                 fname = fname.replace('/', '.').replace('\\\\', '.')
                 fname = fname.replace('.py', '.%d.png' % fignum)
                 fname = os.path.abspath(
                     os.path.join(
                         self.example_dir,
                         '../docs_sphinx/resources/examples_images/',
                         fname))
                 ensure_directory_of_file(fname)
                 _mpl.pyplot.figure(fignum).savefig(fname)
     finally:
         _mpl.pyplot.close('all')
         os.chdir(curdir)
         sys.path.remove(os.path.dirname(self.filename))
         device.reinit()
         set_device('runtime')
Example #3
0
def test_synapse_init():
    # check initializations validity for synapse variables
    start_scope()
    set_device('exporter')
    eqn = 'dv/dt = -v/tau :1'
    tau = 1 * ms
    w = 1
    P = NeuronGroup(5, eqn, method='euler', threshold='v>0.8')
    Q = NeuronGroup(10, eqn, method='euler', threshold='v>0.9')
    S = Synapses(P, Q, 'g :1', on_pre='v += w')
    S.connect()
    # allowable
    S.g['i>10'] = 10
    S.g[-1] = -1
    S.g[10000] = 'rand() + w + w'
    mon = StateMonitor(S, 'g', record=[0, 1])
    run(1 * ms)
    # not allowable
    with pytest.raises(NotImplementedError):
        S.g[0:1000] = -1
        run(0.5 * ms)
    with pytest.raises(NotImplementedError):
        S.g[0:1] = 'rand() + 10'
        run(0.25 * ms)
    with pytest.raises(NotImplementedError):
        _ = StateMonitor(S, 'g', S.g[0:10])
    device.reinit()
Example #4
0
def run_around_tests():
    yield
    device.reinit()
    device.activate()
    # workaround for cpp generation errors when running multiple tests in a row (reinit might take some time?)
    # Network.__instances__() shows multiple instance of the network containing same objects
    sleep(1)
Example #5
0
def test_ExportDevice_options():
    """
    Test the run and build options of ExportDevice
    """
    # test1
    set_device('exporter')
    grp = NeuronGroup(10, 'eqn = 1:1', method='exact')
    run(100 * ms)
    _ = StateMonitor(grp, 'eqn', record=False)
    with pytest.raises(RuntimeError):
        run(100 * ms)

    # test2
    device.reinit()
    with pytest.raises(RuntimeError):
        device.build()

    # test3
    start_scope()
    net = Network()
    set_device('exporter', build_on_run=False)
    grp = NeuronGroup(10, 'eqn = 1:1', method='exact')
    net.add(grp)
    net.run(10 * ms)
    pogrp = PoissonGroup(10, rates=10 * Hz)
    net.add(pogrp)
    net.run(10 * ms)
    mon = StateMonitor(grp, 'eqn', record=False)
    net.add(mon)
    net.run(10 * ms)
    device.build()
    device.reinit()
Example #6
0
def test_simple_syntax():
    """
    Simple example
    """
    set_device('markdown')
    N = 10
    tau = 10 * ms
    v_th = 0.9 * volt
    v_rest = -79 * mV
    eqn = 'dv/dt = (v_th - v)/tau :volt'
    refractory = 'randn() * tau / N'
    rates = 'rand() * 5 * Hz'
    group = NeuronGroup(N, eqn, method='euler', threshold='v > v_th',
                        reset='v = v_rest; v = rand() * v_rest',
                        refractory=refractory,
                        events={'custom': 'v > v_th + 10 * mV',
                        'custom_1': 'v > v_th - 10 * mV'})
    group.run_on_event('custom', 'v = v_rest')
    group.run_on_event('custom_1', 'v = v_rest - 0.001 * mV')
    spikegen = SpikeGeneratorGroup(N, [0, 1, 2], [1, 2, 3] * ms,
                                   period=5 * ms)
    po_grp = PoissonGroup(N - 1, rates=rates)
    syn = Synapses(spikegen, group, model='w :volt',
                   on_pre='v = rand() * w + v_th; v = rand() * w',
                   on_post='v = rand() * w + v_rest; v = rand() * w',
                   delay=tau, method='euler')
    group.v[:] = v_rest
    group.v['i%2 == 0'] = 'rand() * v_rest'
    group.v[0:5] = 'v_rest + 10 * mV'
    condition = 'abs(i-j)<=5'
    syn.connect(condition=condition, p=0.999, n=2)
    syn.w = '1 * mV'
    net = Network(group, spikegen, po_grp, syn)
    mon = StateMonitor(syn, 'w', record=True)
    mon2 = SpikeMonitor(po_grp)
    mon3 = EventMonitor(group, 'custom')
    net.add(mon, mon2, mon3)
    net.run(0.01 * ms)
    md_str = device.md_text
    assert _markdown_lint(md_str)
    check = 'randn({sin({$w$}|$v_rest$ - $v$|/{\tau}})})'
    assert _markdown_lint(check)
    # check invalid strings
    with pytest.raises(SyntaxError):
        check = '**Initializing values at starting:*'
        assert _markdown_lint(check)
        check = '- Variable v$ of with $-79. mV$ to all members'
        assert _markdown_lint(check)
        check = 'randn({sin(})})'
        assert _markdown_lint(check)
        check = 'randn({sin({$w$}|$v_rest$ - $v$|/{\tau})})'
        assert _markdown_lint(check)
    device.reinit()
Example #7
0
def test_synapse_connect_generator():
    # connector test 3
    start_scope()
    set_device('exporter', build_on_run=False)
    tau = 1 * ms
    eqn = 'dv/dt = (1 - v)/tau :1'
    Source = NeuronGroup(10, eqn, method='exact', threshold='v>0.9')
    S1 = Synapses(Source, Source)
    nett2 = Network(Source, S1)
    S1.connect(j='k for k in range(0, i+1)')
    nett2.run(1 * ms)
    connect3 = device.runs[0]['initializers_connectors'][0]
    assert connect3['j'] == 'k for k in range(0, i+1)'
    device.reinit()
Example #8
0
def test_synapse_connect_ij():
    # connector test 2
    start_scope()
    set_device('exporter', build_on_run=False)
    tau = 10 * ms
    eqn = 'dv/dt = (1 - v)/tau :1'
    my_prob = -1
    Source = NeuronGroup(10, eqn, method='exact', threshold='v>0.9')
    S1 = Synapses(Source, Source)
    nett = Network(Source, S1)
    S1.connect(i=[0, 1], j=[1, 2], p='my_prob')
    nett.run(1 * ms)
    connect2 = device.runs[0]['initializers_connectors'][0]
    assert connect2['i'] == [0, 1]
    assert connect2['j'] == [1, 2]
    assert connect2['identifiers']['my_prob'] == -1
    with pytest.raises(KeyError):
        connect2['condition']
    device.reinit()
Example #9
0
def test_user_options():
    """
    Test user options and error raising
    """
    link = '<img src="https://render.githubusercontent.com/render/math?math='
    my_expander = MdExpander(github_md=True, author='Brian', add_meta=True)
    set_device('markdown', expander=my_expander)
    grp = NeuronGroup(1, 'w :1')
    run(0*ms)
    string = device.md_text
    regex = '_Filename: .*\
             \nAuthor: .*\
             \nDate and localtime: .*\
             \nBrian version: .*'

    assert re.match(regex, string)
    assert _markdown_lint(string)
    assert '$' not in string
    assert link in string
    device.reinit()

    set_device('markdown', filename=10)
    with pytest.raises(Exception):
        run(0*ms)
    device.reinit()

    set_device('markdown', expander=NeuronGroup)
    with pytest.raises(NotImplementedError):
        run(0*ms)
    device.reinit()
Example #10
0
def test_synapse_connect_cond():
    # check connectors
    start_scope()
    set_device('exporter')
    eqn = 'dv/dt = (1 - v)/tau :1'
    tau = 1 * ms
    P = NeuronGroup(5, eqn, method='euler', threshold='v>0.8')
    Q = NeuronGroup(10, eqn, method='euler', threshold='v>0.9')
    w = 1
    tata = 2
    bye = 2
    my_prob = -1
    S = Synapses(P, Q, on_pre='v += w')
    S.connect('tata > bye', p='my_prob', n=5)
    run(1 * ms)
    connect = device.runs[0]['initializers_connectors'][0]
    assert connect['probability'] == 'my_prob'
    assert connect['n_connections'] == 5
    assert connect['type'] == 'connect'
    assert connect['identifiers']['tata'] == bye
    with pytest.raises(KeyError):
        connect['i']
        connect['j']
    device.reinit()
Example #11
0
def test_custom_expander():
    """
    Test custom expander class
    """
    class Custom(MdExpander):

        def expand_NeuronGroup(self, grp_dict):
            idt = self.expand_identifiers(grp_dict['identifiers'])
            return "This is my custom neurongroup: " + grp_dict['name'] + idt

        def expand_StateMonitor(self, mon_dict):
            return "I monitor " + mon_dict['source']

        def expand_identifiers(self, identifiers):
            return 'Identifiers are not shown'

    custom_expander = Custom(brian_verbose=True)
    set_device('markdown', expander=custom_expander)
    # check custom expander
    v_rest = -79 * mV
    rate = 10 * Hz
    grp = NeuronGroup(10, 'v = v_rest:volt')
    mon = StateMonitor(grp, 'v', record=True)
    pog = PoissonGroup(10, rates=rate)
    run(0.1*ms)
    text = device.md_text
    assert _markdown_lint(text)
    # brian_verbose check
    assert 'NeuronGroup' in text
    assert 'StateMonitor' in text
    assert 'Activity recorder' not in text
    assert 'Initializing' in text
    assert 'Identifiers are not shown' in text
    assert 'I monitor ' in text
    assert 'This is my custom neurongroup: neurongroup' in text
    device.reinit()
Example #12
0
def experiment(wGen=3500, wInp=3500, connectivity=None, mismatch=None, \
    N=200, Ninp=4, currents=None, Ngx=5, Ngy=5, Ngz=8, direct_input=False, \
    indices=None, times=None, stretch_factor=None, duration=None, ro_time=None, \
    modulations=None, snr=None, num_samples=None, Y=None, \
    plot=False, store=False, title=None, exp_dir=None, dt=100*us, remove_device=False):
    """
    Run an experiment on a reservoir with given properties and evaluate
    its performance in terms of clustering inputs of different classes.

    Parameters
    ----------
    wGen : float
        weight of the generator synapses

    wInp : float
        weight of the input synapses

    connectivity : dict
        contains the two connectivity matrices as
        i and j indices to be used in the connect method
        of the synapse object in Brian2

    N : int
        number of neurons in the reservoir
        
    Ninp : int
        number of input neurons

    currents : dict
        dictionary with values of different currents for the input and
        reservoir neurons and synapses

    Ngx : int
        number of reservoir neurons in the x-axis of the grid

    Ngy : int
        number of reservoir neurons in the y-axis of the grid

    Ngz : int
        number of reservoir neurons in the z-axis of the grid

    direct_input: bool
        wheter the input to the reservoir should be coming from
        the generators directly or not

    indices : list
        spike generator neuron indices

    times : list
        spike generator spiking times

    stretch_factor : int
        time steching factor to adapt radioML signals to DPI
        operation time scales

    duration : float
        time length of the concatenated stimulus in ms

    ro_time : float
        width of the time interval from which to read out
        the activity of one sample in ms

    modulations : list
        modulation classes in the input stimulus

    snr : float
        signal-to-noise level of the input stimulus

    num_samples : int
        number of samples per modulation class

    Y : list
        labels of the samples in the input stimulus

    plot : object
        object of key/value pairs to plot different
        aspects of the experiment

    store : bool
        flag to store the results from the experiment

    title : string
        unique title for the experiment

    exp_dir : path
        path to the experiment directory where to store
        the plots

    dt : float (us)
        time step of the simulation in us

    remove_device : bool
        wheter the device folder should be removed after
        the experiment or not

    Returns
    -------
    score : float
        performance metric of the reservoir (higher is better)      
    """
    params = dict(locals())
    start = time.perf_counter()
    # Set C++ backend and time step
    if title is None:
        title = 'srres_{}'.format(os.getpid())
    directory = '../brian2_devices/' + title
    set_device('cpp_standalone', directory=directory, build_on_run=True)
    device.reinit()
    device.activate(directory=directory, build_on_run=True)
    defaultclock.dt = dt
    # Setup network components
    components = {
        'generator': None,
        'layers': {},
        'synapses': {},
        'monitors': {}
    }
    components = setup_generator(components)
    if not direct_input:
        components = setup_input_layer(components, connectivity, mismatch,
                                       Ninp, currents, wGen)
    components = setup_reservoir_layer(components, connectivity, mismatch, N,
                                       currents, wInp, direct_input)
    # Define neurons and synapses reset function
    components['layers']['run_reg_gRes'] = components['layers'][
        'gRes'].run_regularly("Imem=0*pA", dt=ro_time)
    components['synapses']['run_reg_sResRes'] = components['synapses'][
        'sResRes'].run_regularly("""
            Ie_syn=Io_syn
            Ii_syn=Io_syn
        """,
                                 dt=ro_time)
    # Initialize network
    network = init_network(components, indices, times)
    # Run simulation
    network.run(duration, recompile=True)
    # Readout activity
    tot_num_samples = num_samples * len(modulations)
    X, bins, edges = readout(network,
                             connectivity,
                             ro_time,
                             N,
                             tot_num_samples,
                             bin_size=5)
    # Measure reservoir perfomance
    accuracy = classify(X, Y)
    s = np.max(accuracy)
    # Plot
    if plot:
        if exp_dir is None:
            exp_dir = directory
            plots_dir = '{}/plots'.format(exp_dir)
        else:
            plots_dir = '{}/plots/{}'.format(exp_dir, title)
        if not os.path.exists(plots_dir):
            os.makedirs(plots_dir)
        if plot['raster']:
            plot_raster(network['mRes'], plots_dir)
        if plot['result']:
            plot_result(X,
                        Y,
                        bins,
                        edges,
                        modulations,
                        snr,
                        directory=plots_dir)
        if plot['network']:
            labels = ['I.up', 'I.dn', 'Q.up', 'Q.dn', 'stop']
            plot_network(connectivity, labels, directory=plots_dir)
        if plot['weights']:
            plot_weights(network, connectivity, N, directory=plots_dir)
        if plot['weights3D']:
            plot_weights_3D(network,
                            connectivity,
                            N,
                            Ngx,
                            Ngy,
                            Ngz,
                            directory=plots_dir)
        if plot['similarity']:
            max_bin = np.argmax(accuracy)
            S = cosine_similarity(list(map(lambda x: x[max_bin], X)))
            labels = [
                mod for _, mod in sorted(zip(np.unique(Y), modulations),
                                         key=lambda pair: pair[0])
            ]
            plot_similarity(S, Y, labels, directory=plots_dir)
        if plot['currents']:
            plot_currents_distributions(network, directory=plots_dir)
        if plot['accuracy']:
            plot_accuracy(accuracy, directory=plots_dir)
    if store:
        result_dir = '{}/results'.format(exp_dir)
        if not os.path.exists(result_dir):
            os.makedirs(result_dir)
        store_result(X, Y, s, params, title=title, directory=result_dir)
    # Remove device folder
    if remove_device:
        shutil.rmtree(directory, ignore_errors=True)
    print("- experiment took {} [s]".format(time.perf_counter() - start))
    return s
Example #13
0
def test_ExportDevice_basic():
    """
    Test the components and structure of the dictionary exported
    by ExportDevice
    """
    start_scope()
    set_device('exporter')

    grp = NeuronGroup(10,
                      'dv/dt = (1-v)/tau :1',
                      method='exact',
                      threshold='v > 0.5',
                      reset='v = 0',
                      refractory=2 * ms)
    tau = 10 * ms
    rate = '1/tau'
    grp.v['i > 2 and i < 5'] = -0.2
    pgrp = PoissonGroup(10, rates=rate)
    smon = SpikeMonitor(pgrp)
    smon.active = False
    netobj = Network(grp, pgrp, smon)
    netobj.run(100 * ms)
    dev_dict = device.runs
    # check the structure and components in dev_dict
    assert dev_dict[0]['duration'] == 100 * ms
    assert dev_dict[0]['inactive'][0] == smon.name
    components = dev_dict[0]['components']
    assert components['spikemonitor'][0]
    assert components['poissongroup'][0]
    assert components['neurongroup'][0]
    initializers = dev_dict[0]['initializers_connectors']
    assert initializers[0]['source'] == grp.name
    assert initializers[0]['variable'] == 'v'
    assert initializers[0]['index'] == 'i > 2 and i < 5'
    # TODO: why not a Quantity type?
    assert initializers[0]['value'] == '-0.2'
    with pytest.raises(KeyError):
        initializers[0]['identifiers']
    device.reinit()

    start_scope()
    set_device('exporter', build_on_run=False)
    tau = 10 * ms
    v0 = -70 * mV
    vth = 800 * mV
    grp = NeuronGroup(10,
                      'dv/dt = (v0-v)/tau :volt',
                      method='exact',
                      threshold='v > vth',
                      reset='v = v0',
                      refractory=2 * ms)
    v0 = -80 * mV
    grp.v[:] = 'v0 + 2 * mV'
    smon = StateMonitor(grp, 'v', record=True)
    smon.active = False
    net = Network(grp, smon)
    net.run(10 * ms)  # first run
    v0 = -75 * mV
    grp.v[3:8] = list(range(3, 8)) * mV
    smon.active = True
    net.run(20 * ms)  # second run
    v_new = -5 * mV
    grp.v['i >= 5'] = 'v0 + v_new'
    v_new = -10 * mV
    grp.v['i < 5'] = 'v0 - v_new'
    spikemon = SpikeMonitor(grp)
    net.add(spikemon)
    net.run(5 * ms)  # third run
    dev_dict = device.runs
    # check run1
    assert dev_dict[0]['duration'] == 10 * ms
    assert dev_dict[0]['inactive'][0] == smon.name
    components = dev_dict[0]['components']
    assert components['statemonitor'][0]
    assert components['neurongroup'][0]
    initializers = dev_dict[0]['initializers_connectors']
    assert initializers[0]['source'] == grp.name
    assert initializers[0]['variable'] == 'v'
    assert initializers[0]['index']
    assert initializers[0]['value'] == 'v0 + 2 * mV'
    assert initializers[0]['identifiers']['v0'] == -80 * mV
    with pytest.raises(KeyError):
        initializers[0]['identifiers']['mV']
    # check run2
    assert dev_dict[1]['duration'] == 20 * ms
    initializers = dev_dict[1]['initializers_connectors']
    assert initializers[0]['source'] == grp.name
    assert initializers[0]['variable'] == 'v'
    assert (initializers[0]['index'] == grp.indices[slice(3, 8, None)]).all()
    assert (initializers[0]['value'] == list(range(3, 8)) * mV).all()
    with pytest.raises(KeyError):
        dev_dict[1]['inactive']
        initializers[1]['identifiers']
    # check run3
    assert dev_dict[2]['duration'] == 5 * ms
    with pytest.raises(KeyError):
        dev_dict[2]['inactive']
    assert dev_dict[2]['components']['spikemonitor']
    initializers = dev_dict[2]['initializers_connectors']
    assert initializers[0]['source'] == grp.name
    assert initializers[0]['variable'] == 'v'
    assert initializers[0]['index'] == 'i >= 5'
    assert initializers[0]['value'] == 'v0 + v_new'
    assert initializers[0]['identifiers']['v0'] == -75 * mV
    assert initializers[0]['identifiers']['v_new'] == -5 * mV
    assert initializers[1]['index'] == 'i < 5'
    assert initializers[1]['value'] == 'v0 - v_new'
    assert initializers[1]['identifiers']['v_new'] == -10 * mV
    with pytest.raises(IndexError):
        initializers[2]
        dev_dict[3]
    device.reinit()
Example #14
0
def test_common_example():
    """
    Test COBAHH (brian2.readthedocs.io/en/stable/examples/COBAHH.html)
    """

    set_device('markdown')

    # Parameters
    area = 20000*umetre**2
    Cm = (1*ufarad*cm**-2) * area
    gl = (5e-5*siemens*cm**-2) * area

    El = -60*mV
    EK = -90*mV
    ENa = 50*mV
    g_na = (100*msiemens*cm**-2) * area
    g_kd = (30*msiemens*cm**-2) * area
    VT = -63*mV
    # Time constants
    taue = 5*ms
    taui = 10*ms
    # Reversal potentials
    Ee = 0*mV
    Ei = -80*mV
    we = 6*nS  # excitatory synaptic weight
    wi = 67*nS  # inhibitory synaptic weight

    # The model
    eqs = Equations('''
    dv/dt = (gl*(El-v)+ge*(Ee-v)+gi*(Ei-v)-
            g_na*(m*m*m)*h*(v-ENa)-
            g_kd*(n*n*n*n)*(v-EK))/Cm : volt
    dm/dt = alpha_m*(1-m)-beta_m*m : 1
    dn/dt = alpha_n*(1-n)-beta_n*n : 1
    dh/dt = alpha_h*(1-h)-beta_h*h : 1
    dge/dt = -ge*(1./taue) : siemens
    dgi/dt = -gi*(1./taui) : siemens
    alpha_m = 0.32*(mV**-1)*4*mV/exprel((13.0*mV-v+VT)/(4*mV))/ms : Hz
    beta_m = 0.28*(mV**-1)*5*mV/exprel((v-VT-40*mV)/(5*mV))/ms : Hz
    alpha_h = 0.128*exp((17*mV-v+VT)/(18.0*mV))/ms : Hz
    beta_h = 4./(1+exp((40*mV-v+VT)/(5*mV)))/ms : Hz
    alpha_n = 0.032*(mV**-1)*5*mV/exprel((15.*mV-v+VT)/(5.*mV))/ms : Hz
    beta_n = .5*exp((10*mV-v+VT)/(40.*mV))/ms : Hz
    ''')

    P = NeuronGroup(4000, model=eqs, threshold='v>-20*mV', refractory=3*ms,
                    method='exponential_euler')
    Pe = P[:3200]
    Pi = P[3200:]
    Ce = Synapses(Pe, P, on_pre='ge+=we')
    Ci = Synapses(Pi, P, on_pre='gi+=wi')
    Ce.connect(p=0.02)
    Ci.connect(p=0.02)

    # Initialization
    P.v = 'El + (randn() * 5 - 5)*mV'
    P.ge = '(randn() * 1.5 + 4) * 10.*nS'
    P.gi = '(randn() * 12 + 20) * 10.*nS'

    # Record a few traces
    trace = StateMonitor(P, 'v', record=[1, 10, 100])
    run(1 * second)
    md_str = device.md_text
    assert _markdown_lint(md_str)
    device.reinit()
Example #15
0
def test_from_papers_example():
    """
    Test Izhikevich_2007 example
    `brian2.readthedocs.io/en/stable/examples/frompapers.Izhikevich_2007.html`
    """
    set_device('markdown', build_on_run=False)
    # Parameters
    simulation_duration = 6 * second
    # Neurons
    taum = 10*ms
    Ee = 0*mV
    vt = -54*mV
    vr = -60*mV
    El = -74*mV
    taue = 5*ms

    # STDP
    taupre = 20*ms
    taupost = taupre
    gmax = .01
    dApre = .01
    dApost = -dApre * taupre / taupost * 1.05
    dApost *= gmax
    dApre *= gmax

    # Dopamine signaling
    tauc = 1000*ms
    taud = 200*ms
    taus = 1*ms
    epsilon_dopa = 5e-3

    # Setting the stage

    # Stimuli section
    input_indices = array([0, 1, 0, 1, 1, 0,
                           0, 1, 0, 1, 1, 0])
    input_times = array([500,  550, 1000, 1010, 1500, 1510,
                         3500, 3550, 4000, 4010, 4500, 4510])*ms
    input = SpikeGeneratorGroup(2, input_indices, input_times)

    neurons = NeuronGroup(2, '''dv/dt = (ge * (Ee-vr) + El - v) / taum : volt
                                dge/dt = -ge / taue : 1''',
                          threshold='v>vt', reset='v = vr',
                          method='exact')
    neurons.v = vr
    neurons_monitor = SpikeMonitor(neurons)

    synapse = Synapses(input, neurons,
                       model='''s: volt''',
                       on_pre='v += s')
    synapse.connect(i=[0, 1], j=[0, 1])
    synapse.s = 100. * mV

    # STDP section
    synapse_stdp = Synapses(neurons, neurons,
                    model='''mode: 1
                            dc/dt = -c / tauc : 1 (clock-driven)
                            dd/dt = -d / taud : 1 (clock-driven)
                            ds/dt = mode * c * d / taus : 1 (clock-driven)
                            dApre/dt = -Apre / taupre : 1 (event-driven)
                            dApost/dt = -Apost / taupost : 1 (event-driven)''',
                    on_pre='''ge += s
                            Apre += dApre
                            c = clip(c + mode * Apost, -gmax, gmax)
                            s = clip(s + (1-mode) * Apost, -gmax, gmax)
                            ''',
                    on_post='''Apost += dApost
                            c = clip(c + mode * Apre, -gmax, gmax)
                            s = clip(s + (1-mode) * Apre, -gmax, gmax)
                            ''',
                    method='euler'
                           )
    synapse_stdp.connect(i=0, j=1)
    synapse_stdp.mode = 0
    synapse_stdp.s = 1e-10
    synapse_stdp.c = 1e-10
    synapse_stdp.d = 0
    synapse_stdp_monitor = StateMonitor(synapse_stdp, ['s', 'c', 'd'],
                                        record=[0])
    # Dopamine signaling section
    dopamine_indices = array([0, 0, 0])
    dopamine_times = array([3520, 4020, 4520])*ms
    dopamine = SpikeGeneratorGroup(1, dopamine_indices, dopamine_times)
    dopamine_monitor = SpikeMonitor(dopamine)
    reward = Synapses(dopamine, synapse_stdp, model='''''',
                      on_pre='''d_post += epsilon_dopa''',
                      method='exact')
    reward.connect()

    # Simulation
    # Classical STDP
    synapse_stdp.mode = 0
    run(simulation_duration/2)
    # Dopamine modulated STDP
    synapse_stdp.mode = 1
    run(simulation_duration/2)
    device.build()
    md_str = device.md_text
    assert _markdown_lint(md_str)
    device.reinit()