def test_arange_linspace(): # For dimensionless values, the unit-safe functions should give the same results assert_equal(brian2.arange(5), np.arange(5)) assert_equal(brian2.arange(1, 5), np.arange(1, 5)) assert_equal(brian2.arange(10, step=2), np.arange(10, step=2)) assert_equal(brian2.arange(0, 5, 0.5), np.arange(0, 5, 0.5)) assert_equal(brian2.linspace(0, 1), np.linspace(0, 1)) assert_equal(brian2.linspace(0, 1, 10), np.linspace(0, 1, 10)) # Make sure units are checked assert_raises(DimensionMismatchError, lambda: brian2.arange(1*mV, 5)) assert_raises(DimensionMismatchError, lambda: brian2.arange(1*mV, 5*mV)) assert_raises(DimensionMismatchError, lambda: brian2.arange(1, 5*mV)) assert_raises(DimensionMismatchError, lambda: brian2.arange(1*mV, 5*ms)) assert_raises(DimensionMismatchError, lambda: brian2.arange(1*mV, 5*mV, step=1*ms)) assert_raises(DimensionMismatchError, lambda: brian2.arange(1*ms, 5*mV)) # Check correct functioning with units assert_quantity(brian2.arange(5*mV, step=1*mV), float(mV)*np.arange(5, step=1), mV) assert_quantity(brian2.arange(1*mV, 5*mV, 1*mV), float(mV)*np.arange(1, 5, 1), mV) assert_quantity(brian2.linspace(1*mV, 2*mV), float(mV)*np.linspace(1, 2), mV) # Check errors for arange with incorrect numbers of arguments/duplicate arguments assert_raises(TypeError, lambda: brian2.arange()) assert_raises(TypeError, lambda: brian2.arange(0, 5, 1, 0)) assert_raises(TypeError, lambda: brian2.arange(0, stop=1)) assert_raises(TypeError, lambda: brian2.arange(0, 5, stop=1)) assert_raises(TypeError, lambda: brian2.arange(0, 5, start=1)) assert_raises(TypeError, lambda: brian2.arange(0, 5, 1, start=1)) assert_raises(TypeError, lambda: brian2.arange(0, 5, 1, stop=2)) assert_raises(TypeError, lambda: brian2.arange(0, 5, 1, step=2))
def test_arange_linspace(): # For dimensionless values, the unit-safe functions should give the same results assert_equal(brian2.arange(5), np.arange(5)) assert_equal(brian2.arange(1, 5), np.arange(1, 5)) assert_equal(brian2.arange(10, step=2), np.arange(10, step=2)) assert_equal(brian2.arange(0, 5, 0.5), np.arange(0, 5, 0.5)) assert_equal(brian2.linspace(0, 1), np.linspace(0, 1)) assert_equal(brian2.linspace(0, 1, 10), np.linspace(0, 1, 10)) # Make sure units are checked assert_raises(DimensionMismatchError, lambda: brian2.arange(1*mV, 5)) assert_raises(DimensionMismatchError, lambda: brian2.arange(1*mV, 5*mV)) assert_raises(DimensionMismatchError, lambda: brian2.arange(1, 5*mV)) assert_raises(DimensionMismatchError, lambda: brian2.arange(1*mV, 5*ms)) assert_raises(DimensionMismatchError, lambda: brian2.arange(1*mV, 5*mV, step=1*ms)) assert_raises(DimensionMismatchError, lambda: brian2.arange(1*ms, 5*mV)) # Check correct functioning with units assert_quantity(brian2.arange(5*mV, step=1*mV), float(mV)*np.arange(5, step=1), mV) assert_quantity(brian2.arange(1*mV, 5*mV, 1*mV), float(mV)*np.arange(1, 5, 1), mV) assert_quantity(brian2.linspace(1*mV, 2*mV), float(mV)*np.linspace(1, 2), mV) # Check errors for arange with incorrect numbers of arguments/duplicate arguments assert_raises(TypeError, lambda: brian2.arange()) assert_raises(TypeError, lambda: brian2.arange(0, 5, 1, 0)) assert_raises(TypeError, lambda: brian2.arange(0, stop=1)) assert_raises(TypeError, lambda: brian2.arange(0, 5, stop=1)) assert_raises(TypeError, lambda: brian2.arange(0, 5, start=1)) assert_raises(TypeError, lambda: brian2.arange(0, 5, 1, start=1)) assert_raises(TypeError, lambda: brian2.arange(0, 5, 1, stop=2)) assert_raises(TypeError, lambda: brian2.arange(0, 5, 1, step=2))
def main4(plot=True): # what if we want to keep the input spike exactly the same throughout different taus? # Solution: We run PoissonGroup once, store all the spikes, and use the stored spikes across the multiple runs bs.start_scope() num_inputs = 100 input_rate = 10 * bs.Hz w = 0.1 tau_range = bs.linspace(1, 10, 30) * bs.ms output_rates = [] P = bs.PoissonGroup(num_inputs, rates=input_rate) p_monitor = bs.SpikeMonitor(P) one_second = 1 * bs.second """ Note that in the code above, we created Network objects. The reason is that in the loop, if we just called run it would try to simulate all the objects, including the Poisson neurons P, and we only want to run that once. We use Network to specify explicitly which objects we want to include. """ net = bs.Network(P, p_monitor) net.run(one_second) # keeps a copy of the spikes that are generated by the PoissonGroup during that explicit run earlier spikes_i = p_monitor.i spikes_t = p_monitor.t # Construct network that we run each time sgg = bs.SpikeGeneratorGroup(num_inputs, spikes_i, spikes_t) eqs = ''' dv/dt = -v/tau : 1 ''' G = bs.NeuronGroup(1, eqs, threshold='v>1', reset='v=0', method='exact') S = bs.Synapses(sgg, G, on_pre='v += w') S.connect() # fully connected network g_monitor = bs.SpikeMonitor(G) # store the current state of the network net = bs.Network(sgg, G, S, g_monitor) net.store() for tau in tau_range: net.restore() net.run(one_second) output_rates.append(g_monitor.num_spikes / bs.second) if plot: plt.clf() plt.plot(tau_range / bs.ms, output_rates) plt.xlabel(r'$\tau$ (ms)') plt.ylabel('Firing Rate (spikes/s)') # there is much less noise compared to before where we used different PoissonGroup everytime plt.show()
def main2(): # STDP curve tau_pre = 20*bs.ms tau_post = 20*bs.ms A_pre = 0.01 A_post = -A_pre * 1.05 delta_t = bs.linspace(-50, 50, 100)*bs.ms W = bs.where(delta_t > 0, A_pre*bs.exp(-delta_t/tau_pre), A_post*bs.exp(delta_t/tau_post)) plt.plot(delta_t/bs.ms, W) plt.xlabel(r'$\Delta t$ (ms)') plt.ylabel('W') plt.axhline(0, ls='-', c='k') # add horizontal line across the axis plt.show()
def run_network(): monitor_dict={} defaultclock.dt= 0.01*ms C=281*pF gL=30*nS EL=-70.6*mV VT=-50.4*mV DeltaT=2*mV tauw=40*ms a=4*nS b=0.08*nA I=8*nA Vcut="vm>2*mV"# practical threshold condition N=10 reset = 'vm=Vr;w+=b' eqs=""" dvm/dt=(gL*(EL-vm)+gL*DeltaT*exp((vm-VT)/DeltaT)+I-w)/C : volt dw/dt=(a*(vm-EL)-w)/tauw : amp Vr:volt """ neuron=NeuronGroup(N,model=eqs,threshold=Vcut,reset=reset) neuron.vm=EL neuron.w=a*(neuron.vm-EL) neuron.Vr=linspace(-48.3*mV,-47.7*mV,N) # bifurcation parameter #run(25*msecond,report='text') # we discard the first spikes MSpike=SpikeMonitor(neuron, variables=['vm']) # record Vr and w at spike times MPopRate = PopulationRateMonitor(neuron) MMultiState = StateMonitor(neuron, ['w','vm'], record=[6,7,8,9]) run(10*msecond,report='text') monitor_dict['SpikeMonitor']=MSpike monitor_dict['MultiState']=MMultiState monitor_dict['PopulationRateMonitor']=MPopRate return monitor_dict
def run_network(): monitor_dict = {} defaultclock.dt = 0.01 * ms C = 281 * pF gL = 30 * nS EL = -70.6 * mV VT = -50.4 * mV DeltaT = 2 * mV tauw = 40 * ms a = 4 * nS b = 0.08 * nA I = 8 * nA Vcut = "vm>2*mV" # practical threshold condition N = 10 reset = 'vm=Vr;w+=b' eqs = """ dvm/dt=(gL*(EL-vm)+gL*DeltaT*exp((vm-VT)/DeltaT)+I-w)/C : volt dw/dt=(a*(vm-EL)-w)/tauw : amp Vr:volt """ neuron = NeuronGroup(N, model=eqs, threshold=Vcut, reset=reset) neuron.vm = EL neuron.w = a * (neuron.vm - EL) neuron.Vr = linspace(-48.3 * mV, -47.7 * mV, N) # bifurcation parameter #run(25*msecond,report='text') # we discard the first spikes MSpike = SpikeMonitor(neuron, variables=['vm']) # record Vr and w at spike times MPopRate = PopulationRateMonitor(neuron) MMultiState = StateMonitor(neuron, ['w', 'vm'], record=[6, 7, 8, 9]) run(10 * msecond, report='text') monitor_dict['SpikeMonitor'] = MSpike monitor_dict['MultiState'] = MMultiState monitor_dict['PopulationRateMonitor'] = MPopRate return monitor_dict
def main3(plot=True): # even faster # will not always work # Since there is only single output neuron in the model above, # we can make multiple output neurons and make each time constants a parameter of the grop bs.start_scope() num_inputs = 100 input_rate = 10 * bs.Hz w = 0.1 tau_range = bs.linspace(1, 10, 30) * bs.ms num_tau = len(tau_range) P = bs.PoissonGroup(num_inputs, rates=input_rate) eqs = """ dv/dt = -v/tau : 1 tau : second """ # set output neurons with the same number of taus that you want to try with G = bs.NeuronGroup(num_tau, eqs, threshold='v>1', reset='v=0', method='exact') # set the taus for each individual neurons separately # (didn't know that this was possible) G.tau = tau_range S = bs.Synapses(P, G, on_pre='v += w') S.connect() spike_monitor = bs.SpikeMonitor(G) # Now we can just run once with no loop bs.run(1 * bs.second) # and each counts correspond to neuron with different taus output_rates = spike_monitor.count / bs.second # firing rate is count/duration if plot: plt.plot(tau_range / bs.ms, output_rates) plt.xlabel(r'$\tau$ (ms)') plt.ylabel('Firing rate (sp/s)') plt.show()
def run_net(traj): """Creates and runs BRIAN network based on the parameters in `traj`.""" eqs = traj.eqs # Create a namespace dictionairy namespace = traj.Net.f_to_dict(short_names=True, fast_access=True) # Create the Neuron Group neuron = NeuronGroup(traj.N, model=eqs, threshold=traj.Vcut, reset=traj.reset, namespace=namespace) neuron.vm = traj.EL neuron.w = traj.a * (neuron.vm - traj.EL) neuron.Vr = linspace(-48.3 * mV, -47.7 * mV, traj.N) # bifurcation parameter # Run the network initially for 100 milliseconds print('Initial Run') net = Network(neuron) net.run(100 * ms, report='text') # we discard the first spikes # Create a Spike Monitor MSpike = SpikeMonitor(neuron) net.add(MSpike) # Create a State Monitor for the membrane voltage, record from neurons 1-3 MStateV = StateMonitor(neuron, variables=['vm'], record=[1, 2, 3]) net.add(MStateV) # Now record for 500 milliseconds print('Measurement run') net.run(500 * ms, report='text') # Add the BRAIN monitors traj.v_standard_result = Brian2MonitorResult traj.f_add_result('SpikeMonitor', MSpike) traj.f_add_result('StateMonitorV', MStateV)
def main2(plot=True): # Optimizing the code from main1 by only making the networks just once before the loop # running multiple separate simulations bs.start_scope() num_inputs = 100 input_rate = 10 * bs.Hz weight = 0.1 # range of time constants tau_range = bs.linspace(start=1, stop=10, num=30) * bs.ms # storing output rates output_rates = [] P = bs.PoissonGroup(num_inputs, rates=input_rate) eqs = """ dv/dt = -v/tau : 1 """ G = bs.NeuronGroup(1, eqs, threshold='v>1', reset='v=0', method='exact') # connect the external spike source with the neurons # instead of connecting the same neurons like in previous examples S = bs.Synapses(P, G, on_pre='v += weight') S.connect() # visualise_connectivity(S) spike_monitor = bs.SpikeMonitor(source=G) bs.store() # stores the current state of the network for tau in tau_range: # calling this allows for resetting of the network to its original state bs.restore() bs.run(1 * bs.second) n_spikes = spike_monitor.num_spikes output_rates.append(n_spikes / bs.second) if plot: plt.clf() plt.plot(tau_range / bs.ms, output_rates) plt.xlabel(r'$\tau$ (ms)') plt.ylabel('Firing Rate (spikes/s)') plt.show()
def main1(plot=True): # running multiple separate simulations # this simulation checks to see the effect that different time constant have in LIF neuron firing given poisson spikes bs.start_scope() num_inputs = 100 input_rate = 10 * bs.Hz weight = 0.1 # range of time constants tau_range = bs.linspace(start=1, stop=10, num=30) * bs.ms # storing output rates output_rates = [] for tau in tau_range: # introducing some external spike source P = bs.PoissonGroup(num_inputs, rates=input_rate) eqs = """ dv/dt = -v/tau : 1 """ G = bs.NeuronGroup(1, eqs, threshold='v>1', reset='v=0', method='exact') # connect the external spike source with the neurons # instead of connecting the same neurons like in previous examples S = bs.Synapses(P, G, on_pre='v += weight') S.connect() spike_monitor = bs.SpikeMonitor(source=G) bs.run(1 * bs.second) n_spikes = spike_monitor.num_spikes output_rates.append(n_spikes / bs.second) if plot: plt.plot(tau_range / bs.ms, output_rates) plt.xlabel(r'$\tau$ (ms)') plt.ylabel('Firing Rate (spikes/s)') plt.show()
dApre/dt = -Apre / taupre : 1 (event-driven) dApost/dt = -Apost / taupost : 1 (event-driven) ''' on_pre = ''' Apre += dApre * (w_max-w)**mu w = clip(w + Apost, 0, w_max) ''' on_post = ''' Apost += dApost * w**mu w = clip(w + Apre, 0, w_max) ''' N_in = 2000 N_out = 100 N_bins = 100 default_rate = F * (1000 / N_in) postsyn_rates = b2.linspace(0.1, 99, N_out) * b2.Hz if __name__ == '__main__': input_neurons = b2.PoissonGroup(N=N_in, rates=default_rate, name='inputgroup') output_neurons_rates = b2.PoissonGroup(N=N_out, rates=postsyn_rates, name='outputgroup_rates') output_neurons_mu = b2.NeuronGroup(N_out, eqs_neurons, threshold='v>vt', reset='v = vr', method='linear') # output_neurons_mu = b2.PoissonGroup( # N=N_out,