def run_stdp(NE,NI,v_init,C_e,C_ii,C_ie,mon_bin,dt): from brian.neurongroup import NeuronGroup from brian.monitor import PopulationRateMonitor from brian.stdunits import mV, ms, nS, pF, pA, Hz from brian.units import second from brian.equations import Equations from brian.network import Network from brian.connections import Connection from brian.stdp import STDP from brian.clock import Clock runtime = 10*second eta = 1e-2 # Learning rate tau_stdp = 20*ms # STDP time constant alpha = 3*Hz*tau_stdp*2 # Target rate parameter gmax = 100 # Maximum inhibitory weight eqs_neurons=''' dv/dt=(-gl*(v-el)-(g_ampa*w*v+g_gaba*(v-er)*w)+bgcurrent)/memc : volt dg_ampa/dt = -g_ampa/tau_ampa : 1 dg_gaba/dt = -g_gaba/tau_gaba : 1 ''' namespace = {'tau_ampa':5.0*ms,'tau_gaba':10.0*ms, 'bgcurrent':200*pA,'memc':200.0*pF, 'el':-60*mV,'w':1.*nS,'gl':10.0*nS,'er':-80*mV} eqs_neurons = Equations(eqs_neurons, ** namespace) clock = Clock(dt) neurons=NeuronGroup(NE+NI,model=eqs_neurons,clock=clock, threshold=-50.*mV,reset=-60*mV,refractory=5*ms) neurons.v = v_init Pe=neurons.subgroup(NE) Pi=neurons.subgroup(NI) rme = PopulationRateMonitor(Pe,mon_bin) rmi = PopulationRateMonitor(Pi,mon_bin) con_e = Connection(Pe,neurons,'g_ampa') con_ie = Connection(Pi,Pe,'g_gaba') con_ii = Connection(Pi,Pi,'g_gaba') con_e.connect_from_sparse(C_e, column_access=True) con_ie.connect_from_sparse(C_ie, column_access=True) con_ii.connect_from_sparse(C_ii, column_access=True) eqs_istdp = ''' dA_pre/dt=-A_pre/tau_stdp : 1 dA_post/dt=-A_post/tau_stdp : 1 ''' stdp_params = {'tau_stdp':tau_stdp, 'eta':eta, 'alpha':alpha} eqs_istdp = Equations(eqs_istdp, **stdp_params) stdp_ie = STDP(con_ie, eqs=eqs_istdp, pre='''A_pre+=1. w+=(A_post-alpha)*eta''', post='''A_post+=1. w+=A_pre*eta''', wmax=gmax) net = Network(neurons, con_e, con_ie, con_ii, stdp_ie, rme, rmi) net.run(runtime,report='text') return (rme.times,rme.rate), (rmi.times,rmi.rate)
def __init__(self, N, clock, params=default_params): # x=input # r=firing rate # a=adaptation signal # e=efficacy # tau_r1 = firing rate rise time constant # tau_r2 = firing rate decay rate # tau_ar = adaptation rate # tau_a = adaptation recovery rate # eta = rate - adaptation gain eqs=Equations(''' dr/dt=x/tau_r1-r/tau_r2 : 1 da/dt=(eta*r)/tau_ar-a/tau_a : 1 e=1.0-a : 1 tau_a : second tau_r1 : second tau_r2 : second tau_ar : second eta : 1 x : 1 ''') NeuronGroup.__init__(self, N, model=eqs, compile=True, freeze=True, clock=clock) self.N=N self.params=params self.tau_a=self.params.tau_a self.tau_r1=self.params.tau_r1 self.tau_r2=self.params.tau_r2 self.tau_ar=self.params.tau_ar self.eta=self.params.eta
def __init__(self, P, V, I, clock=None): eqs = Equations(''' record : units_record command : units_command ''', units_record=P.unit(V), units_command=P.unit(I)) NeuronGroup.__init__(self, len(P), model=eqs, clock=clock) self._P = P self._V = V self._I = I
def test_incorrect_pre_reference(): G = NeuronGroup(1, '''v : 1 x : 1''', threshold='v>1', reset='v=0') G.v = 1.1 # spikes G2 = NeuronGroup(10, '') # The pre-synaptic x variable should be 10 in the end, because 10 synapses # were created and all of them increase the pre-synaptic variable by 1. # This does not work in Brian 1 (but it does work in Brian 2), we therefore # only throw an error to avoid this problem. assert_raises(ValueError, lambda: Synapses(G, G2, pre='x_pre += 1'))
def __getattr__(self, x): if (x != 'morphology') and ((x in self.morphology._namedkid) or all([c in 'LR123456789' for c in x])): # subtree return self[x] else: return NeuronGroup.__getattr__(self, x)
def test_construction_multiple_synapses(): ''' Test the construction of synapses with multiple synapses per connection. ''' G = NeuronGroup(20, model='v:1', threshold=NoThreshold()) subgroup1, subgroup2 = G[:10], G[10:] syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') # create all-to-all connections with three synapses per connection syn[:, :] = 3 assert len(syn) == 3 * 10 * 10 # set the weights to the same value for all synapses syn.w[:, :] = 2 # set the delays syn.delay[:, :] = 1 * ms all_weights = np.array([ syn.w[i, j, syn_idx] for i in xrange(len(subgroup1)) for j in xrange(len(subgroup2)) for syn_idx in xrange(3) ]) assert (all_weights == 2).all() all_delays = np.array([ syn.delay[i, j, syn_idx] for i in xrange(len(subgroup1)) for j in xrange(len(subgroup2)) for syn_idx in xrange(3) ]) assert (all_delays == 1 * ms).all()
def __init__(self, morphology=None, model=None, threshold=None, reset=NoReset(), refractory=0 * ms, level=0, clock=None, unit_checking=True, compile=False, freeze=False, cm=0.9 * uF / cm ** 2, Ri=150 * ohm * cm): clock = guess_clock(clock) N = len(morphology) # number of compartments # Equations for morphology eqs_morphology = Equations(""" diameter : um length : um x : um y : um z : um area : um**2 """) # Create the state updater if isinstance(model, str): model = Equations(model, level=level + 1) model += Equations(''' v:volt # membrane potential #Im:amp/cm**2 # membrane current (should we have it?) ''') full_model = model + eqs_morphology Group.__init__(self, full_model, N, unit_checking=unit_checking) self._eqs = model self._state_updater = SpatialStateUpdater(model, clock) var_names = full_model._diffeq_names self.cm = cm # could be a vector? self.Ri = Ri S0 = {} # Fill missing units for key, value in full_model._units.iteritems(): if not key in S0: S0[key] = 0 * value self._S0 = [0] * len(var_names) for var, i in zip(var_names, count()): self._S0[i] = S0[var] NeuronGroup.__init__(self, N, model=self._state_updater, threshold=threshold, reset=reset, refractory=refractory, level=level + 1, clock=clock, unit_checking=unit_checking) # Insert morphology self.morphology = morphology self.morphology.compress(diameter=self.diameter, length=self.length, x=self.x, y=self.y, z=self.z, area=self.area)
def test_max_delay(): '''Test that changing delays after compression works. ''' reinit_default_clock() inp = SpikeGeneratorGroup(1, [(0, 1 * ms)]) G = NeuronGroup(1, model='v:1') mon = StateMonitor(G, 'v', record=True) # one synapse syn = Synapses(inp, G, model='w:1', pre='v+=w', max_delay=5 * ms) syn[:, :] = 1 syn.w[:, :] = 1 syn.delay[:, :] = 0 * ms net = Network(inp, G, syn, mon) net.run(defaultclock.dt) syn.delay[:, :] = 5 * ms net.run(6.5 * ms) # spike should arrive at 5 + 1 ms assert (mon[0][mon.times >= 6 * ms] == 1).all() assert (mon[0][mon.times < 6 * ms] == 0).all() # same as above but with two synapses reinit_default_clock() mon.reinit() G.reinit() syn = Synapses(inp, G, model='w:1', pre='v+=w', max_delay=5 * ms) syn[:, :] = 2 syn.w[:, :] = 1 syn.delay[:, :] = [0 * ms, 0 * ms] net = Network(inp, G, syn, mon) net.run(defaultclock.dt) syn.delay[:, :] = [5 * ms, 5 * ms] net.run(6.5 * ms) # spike should arrive at 5 + 1 ms assert (mon[0][mon.times >= 6 * ms] == 2).all() assert (mon[0][mon.times < 6 * ms] == 0).all()
def test_max_delay(): '''Test that changing delays after compression works. ''' reinit_default_clock() inp = SpikeGeneratorGroup(1, [(0, 1*ms)]) G = NeuronGroup(1, model='v:1') mon = StateMonitor(G, 'v', record=True) # one synapse syn = Synapses(inp, G, model='w:1', pre='v+=w', max_delay=5*ms) syn[:, :] = 1 syn.w[:, :] = 1 syn.delay[:, :] = 0 * ms net = Network(inp, G, syn, mon) net.run(defaultclock.dt) syn.delay[:, :] = 5 * ms net.run(6.5*ms) # spike should arrive at 5 + 1 ms assert (mon[0][mon.times >= 6 * ms] == 1).all() assert (mon[0][mon.times < 6 * ms] == 0).all() # same as above but with two synapses reinit_default_clock() mon.reinit() G.reinit() syn = Synapses(inp, G, model='w:1', pre='v+=w', max_delay=5*ms) syn[:, :] = 2 syn.w[:, :] = 1 syn.delay[:, :] = [0 * ms, 0 * ms] net = Network(inp, G, syn, mon) net.run(defaultclock.dt) syn.delay[:, :] = [5 * ms, 5 * ms] net.run(6.5*ms) # spike should arrive at 5 + 1 ms assert (mon[0][mon.times >= 6 * ms] == 2).all() assert (mon[0][mon.times < 6 * ms] == 0).all()
def __init__(self, params=default_params, pyr_params=pyr_params(), inh_params=inh_params(), background_input=None, task_inputs=None, clock=defaultclock): self.params=params self.pyr_params=pyr_params self.inh_params=inh_params self.background_input=background_input self.task_inputs=task_inputs ## Set up equations # Exponential integrate-and-fire neuron eqs = exp_IF(params.C, params.gL, params.EL, params.VT, params.DeltaT) eqs += Equations('g_muscimol : nS') # AMPA conductance - recurrent input current eqs += exp_synapse('g_ampa_r', params.tau_ampa, siemens) eqs += Current('I_ampa_r=g_ampa_r*(E-vm): amp', E=params.E_ampa) # AMPA conductance - background input current eqs += exp_synapse('g_ampa_b', params.tau_ampa, siemens) eqs += Current('I_ampa_b=g_ampa_b*(E-vm): amp', E=params.E_ampa) # AMPA conductance - task input current eqs += exp_synapse('g_ampa_x', params.tau_ampa, siemens) eqs += Current('I_ampa_x=g_ampa_x*(E-vm): amp', E=params.E_ampa) # Voltage-dependent NMDA conductance eqs += biexp_synapse('g_nmda', params.tau1_nmda, params.tau2_nmda, siemens) eqs += Equations('g_V = 1/(1+(Mg/3.57)*exp(-0.062 *vm/mV)) : 1 ', Mg=params.Mg) eqs += Current('I_nmda=g_V*g_nmda*(E-vm): amp', E=params.E_nmda) # GABA-A conductance eqs += exp_synapse('g_gaba_a', params.tau_gaba_a, siemens) eqs += Current('I_gaba_a=g_gaba_a*(E-vm): amp', E=params.E_gaba_a) eqs +=InjectedCurrent('I_dcs: amp') NeuronGroup.__init__(self, params.network_group_size, model=eqs, threshold=-20*mV, refractory=1*ms, reset=params.Vr, compile=True, freeze=True, clock=clock) self.init_subpopulations() self.init_connectivity(clock)
def __init__(self, source, n_per_channel=1, params=None): params = ZhangSynapse._get_parameters(params) c_0, c_1 = params['c_0'], params['c_1'] s_0, s_1 = params['s_0'], params['s_1'] R_A = params['R_A'] eqs = ''' # time-varying discharge rate, input into this model s : Hz # discharge-history effect (Equation 20 in differential equation form) H = c_0*e_0 + c_1*e_1 : 1 de_0/dt = -e_0/s_0 : 1 de_1/dt = -e_1/s_1 : 1 # final time-varying discharge rate for the Poisson process, equation 19 R = s * (1 - H) : Hz ''' def reset_func(P, spikes): P.e_0[spikes] = 1.0 P.e_1[spikes] = 1.0 # make sure that the s value is first updated in # ZhangSynapseRate, then this NeuronGroup is # updated clock=Clock(dt=source.clock.dt, t=source.clock.t, order=source.clock.order + 1) @network_operation(clock=clock, when='start') def distribute_input(): self.s[:] = source.s.repeat(n_per_channel) NeuronGroup.__init__(self, len(source) * n_per_channel, model=eqs, threshold=PoissonThreshold('R'), reset=CustomRefractoriness(resetfun=reset_func, period=R_A), clock=clock ) self.contained_objects += [distribute_input]
def __getattr__(self, name): if name == 'var_index': raise AttributeError if not hasattr(self, 'var_index'): raise AttributeError if (name=='delay_pre') or (name=='delay'): # default: delay is presynaptic delay if len(self._delay_pre)>1: return [SynapticDelayVariable(delay_pre,self,name) for delay_pre in self._delay_pre] else: return SynapticDelayVariable(self._delay_pre[0],self,name) elif name=='delay_post': return SynapticDelayVariable(self._delay_post,self,name) try: x=self.state(name) return SynapticVariable(x,self,name) except KeyError: return NeuronGroup.__getattr__(self,name)
def create_netobjs(stim, params): C = params['Cap'] KappaN = params['Kappan'] KappaP = params['Kappap'] I0N = params['I0n'] I0P = params['I0p'] Ut = params['Ut'] Delta_t = (Ut / KappaP) #Feed-Forward parameters i_inj = params['i_inj'] i_injinh1 = params['i_injinh1'] i_injinh2 = params['i_injinh2'] i_injinh3 = params['i_injinh3'] i_injinh4 = params['i_injinh4'] i_leak = params['i_leak'] tau_syn_E = params['tau_syn_E'] tau_syn_I = params['tau_syn_I'] tau_synloc_E = params['tau_synloc_E'] tau_synloc_IE = params['tau_synloc_IE'] v_thresh = params['v_thresh'] w_syn_E1 = params['w_syn_E1'] w_syn_E2 = params['w_syn_E2'] w_syn_I = params['w_syn_I'] w_synloc_E = params['w_synloc_E'] w_synloc_EE = params['w_synloc_EE'] w_synloc_EI = params['w_synloc_EI'] w_synloc_IE = params['w_synloc_IE'] w_synloc_S = params['w_synloc_S'] ##Feed-Back parameters #w =dict() #w['e'] =1e-11 #w['i'] =5e-11/N_IP1 #w['ei'] =2e-11/N_EP1 eqs = Equations(''' dV/dt=(-I_lk + I_fb + I_in + Ia + Iloce - Iloci - Ii)/C: volt I_fb = I0P*exp((V-v_thresh)/Delta_t) : amp I_in : amp I_lk = i_leak : amp dIa/dt=-Ia/tau_syn_E: amp dIloce/dt=-Iloce/tau_synloc_E: amp dIloci/dt=-Iloci/tau_synloc_IE: amp dIi/dt=-Ii/tau_syn_I: amp ''') EIP = NeuronGroup(N, model=eqs, reset=0, threshold=1.5, refractory=.001) EP1 = EIP[:N_EP1] IP1 = EIP[N_EP1:] EP1.I_in = np.random.normal(1, sigma_mismatch, N_EP1) * i_inj IP1.I_in = np.random.normal(1,sigma_mismatch,N_IP1)*\ np.array([i_injinh1, i_injinh2, i_injinh3, i_injinh4]) #Create connections between population v_loclat = np.zeros([N_EP1]) v_loclat[N_EP1 / 2] = w_synloc_S v_loclat[[N_EP1 / 2 - 1, N_EP1 / 2 + 1]] = w_synloc_E v_loclat[[N_EP1 / 2 - 2, N_EP1 / 2 + 2]] = w_synloc_EE v_loclat[[N_EP1 / 2 - 3, N_EP1 / 2 + 3]] = w_synloc_EE / 2 v_loclat = np.roll(v_loclat, -N_EP1 / 2) W = np.array([np.roll(v_loclat, i) for i in range(N_EP1)]) W *= np.random.normal(1, sigma_mismatch, W.shape) ConnE = Connection(EP1, EP1, 'Iloce') ConnE.connect(EP1, EP1, W) ConnEI = Connection(EP1, IP1, 'Iloce') ConnEI.connect( EP1, IP1, W=w_synloc_EI * np.random.normal(1, sigma_mismatch, [len(EP1), len(IP1)])) ConnIE = Connection(IP1, EP1, 'Iloci') ConnIE.connect( IP1, EP1, W=w_synloc_IE * np.random.normal(1, sigma_mismatch, [len(IP1), len(EP1)])) M_EIP = SpikeMonitor(EIP) MV_EIP = StateMonitor(EIP, 'V', record=range(0, N), timestep=int(1 * ms / defaultclock.dt)) @network_operation def update_mpot(): EIP.V[EIP.V < 0.] = 0. # ME_EP1= StateMonitor(EP1,'Ie',record=range(0,N_EP1),timestep=int(1*ms/defaultclock.dt)) # MI_EP1= StateMonitor(EP1,'Ii',record=range(0,N_EP1),timestep=int(1*ms/defaultclock.dt)) # MW_EP1= StateMonitor(EP1,'Ia',record=range(0,N_EP1),timestep=int(1*ms/defaultclock.dt)) netobjs = { 'EIP': EIP, 'update_mpot': update_mpot, 'ConnE': ConnE, 'ConnEI': ConnEI, 'ConnIE': ConnIE, #'M_In1': M_In1, 'M_EIP': M_EIP, 'MV_EIP': MV_EIP } return netobjs, M_EIP, MV_EIP
def test_construction_and_access(): ''' Test various ways of constructing and accessing synapses. ''' G = NeuronGroup(20, model='v:1', threshold=NoThreshold()) subgroup1, subgroup2 = G[:10], G[10:] syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') # single synaptic indices syn[3, 4] = True syn.w[3, 4] = 0.25 syn.delay[3, 4] = 1 * ms for i in xrange(len(subgroup1)): for j in xrange(len(subgroup2)): if i == 3 and j == 4: assert syn.w[i, j] == 0.25 assert syn.delay[i, j] == 1 * ms else: assert len(syn.w[i, j]) == 0 assert len(syn.delay[i, j]) == 0 # illegal target index def illegal_index(): syn[3, 10] = True assert_raises(ValueError, illegal_index) # illegal source index def illegal_index(): #@DuplicatedSignature syn[10, 4] = True assert_raises(ValueError, illegal_index) # target slice syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn[3, :] = True syn.w[3, :] = 0.25 syn.delay[3, :] = 1 * ms for i in xrange(len(subgroup1)): for j in xrange(len(subgroup2)): if i == 3: assert syn.w[i, j] == 0.25 assert syn.delay[i, j] == 1 * ms else: assert len(syn.w[i, j]) == 0 assert len(syn.delay[i, j]) == 0 # access with slice assert (syn.w[3, :] == 0.25).all() assert (syn.delay[3, :] == 1 * ms).all() # source slice syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn[:, 4] = True syn.w[:, 4] = 0.25 syn.delay[:, 4] = 1 * ms for i in xrange(len(subgroup1)): for j in xrange(len(subgroup2)): if j == 4: assert syn.w[i, j] == 0.25 assert syn.delay[i, j] == 1 * ms else: assert len(syn.w[i, j]) == 0 assert len(syn.delay[i, j]) == 0 # access with slice assert (syn.w[:, 4] == 0.25).all() assert (syn.delay[:, 4] == 1 * ms).all() # Use string initialization for synaptic variable syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn[:, 4] = True # synapses from even source index have weight 1, uneven --> weight 0.5 # same for delays (1ms and 0.5ms) syn.w[:, 4] = '(i % 2 == 0) * 0.5 + 0.5' syn.delay[:, 4] = '(i % 2 == 0) * 0.5 * ms + 0.5 * ms' assert (syn.w[::2, 4] == 1).all() assert (syn.w[1::2, 4] == 0.5).all() assert (syn.delay[::2, 4] == 1 * ms).all() assert (syn.delay[1::2, 4] == 0.5 * ms).all() # Use string initialization with a numpy function and constant syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn[:, 4] = True syn.w[:, 4] = '0.5 + 0.5 * np.cos(i / (1.0 * n) * np.pi)' syn.delay[:, 4] = '0.0005 + 0.0005 * np.cos(i / (1.0 * n) * np.pi)' assert (syn.w[:, 4] == 0.5 + 0.5 * np.cos(np.arange(len(subgroup1)) / (1.0 * len(subgroup1)) * np.pi)).all() # possible delays are always multiples of dt delays = 0.5 * ms + 0.5 * ms * np.cos( np.arange(len(subgroup1)) / (1.0 * len(subgroup1)) * np.pi) delays_rounded_to_dt = (delays / defaultclock.dt).astype( np.int) * defaultclock.dt assert (syn.delay[:, 4] == delays_rounded_to_dt).all()
def __init__(self, params=default_params, pyr_params=pyr_params(), inh_params=inh_params(), plasticity_params=plasticity_params(), background_input=None, task_inputs=None, clock=defaultclock): self.params = params self.pyr_params = pyr_params self.inh_params = inh_params self.plasticity_params = plasticity_params self.background_input = background_input self.task_inputs = task_inputs ## Set up equations # Exponential integrate-and-fire neuron eqs = exp_IF(params.C, params.gL, params.EL, params.VT, params.DeltaT) eqs += Equations('g_muscimol : nS') # AMPA conductance - recurrent input current eqs += exp_synapse('g_ampa_r', params.tau_ampa, siemens) eqs += Current('I_ampa_r=g_ampa_r*(E-vm): amp', E=params.E_ampa) # AMPA conductance - background input current eqs += exp_synapse('g_ampa_b', params.tau_ampa, siemens) eqs += Current('I_ampa_b=g_ampa_b*(E-vm): amp', E=params.E_ampa) # AMPA conductance - task input current eqs += exp_synapse('g_ampa_x', params.tau_ampa, siemens) eqs += Current('I_ampa_x=g_ampa_x*(E-vm): amp', E=params.E_ampa) # Voltage-dependent NMDA conductance eqs += biexp_synapse('g_nmda', params.tau1_nmda, params.tau2_nmda, siemens) eqs += Equations('g_V = 1/(1+(Mg/3.57)*exp(-0.062 *vm/mV)) : 1 ', Mg=params.Mg) eqs += Current('I_nmda=g_V*g_nmda*(E-vm): amp', E=params.E_nmda) # GABA-A conductance eqs += exp_synapse('g_gaba_a', params.tau_gaba_a, siemens) eqs += Current('I_gaba_a=(g_gaba_a+g_muscimol)*(E-vm): amp', E=params.E_gaba_a) eqs += InjectedCurrent('I_dcs: amp') # Total synaptic conductance eqs += Equations( 'g_syn=g_ampa_r+g_ampa_x+g_ampa_b+g_V*g_nmda+g_gaba_a : siemens') eqs += Equations( 'g_syn_exc=g_ampa_r+g_ampa_x+g_ampa_b+g_V*g_nmda : siemens') # Total synaptic current eqs += Equations( 'I_abs=(I_ampa_r**2)**.5+(I_ampa_b**2)**.5+(I_ampa_x**2)**.5+(I_nmda**2)**.5+(I_gaba_a**2)**.5 : amp' ) NeuronGroup.__init__(self, params.network_group_size, model=eqs, threshold=-20 * mV, refractory=1 * ms, reset=params.Vr, compile=True, freeze=True, clock=clock) self.init_subpopulations() self.init_connectivity(clock)
def __init__(self, morphology=None, model=None, threshold=None, reset=NoReset(), refractory=0 * ms, level=0, clock=None, unit_checking=True, compile=False, freeze=False, implicit=True, Cm=0.9 * uF / cm ** 2, Ri=150 * ohm * cm, bc_type = 2, diffeq_nonzero=True): clock = guess_clock(clock) N = len(morphology) # number of compartments if isinstance(model, str): model = Equations(model, level=level + 1) model += Equations(''' v:volt # membrane potential ''') # Process model equations (Im) to extract total conductance and the remaining current if use_sympy: try: membrane_eq=model._string['Im'] # the membrane equation except: raise TypeError,"The transmembrane current Im must be defined" # Check conditional linearity ids=get_identifiers(membrane_eq) _namespace=dict.fromkeys(ids,1.) # there is a possibility of problems here (division by zero) _namespace['v']=AffineFunction() eval(membrane_eq,model._namespace['v'],_namespace) try: eval(membrane_eq,model._namespace['v'],_namespace) except: # not linear raise TypeError,"The membrane current must be linear with respect to v" # Extracts the total conductance from Im, and the remaining current z=symbolic_eval(membrane_eq) symbol_v=sympy.Symbol('v') b=z.subs(symbol_v,0) a=-sympy.simplify(z.subs(symbol_v,1)-b) gtot_str="_gtot="+str(a)+": siemens/cm**2" I0_str="_I0="+str(b)+": amp/cm**2" model+=Equations(gtot_str+"\n"+I0_str,level=level+1) # better: explicit insertion with namespace of v else: raise TypeError,"The Sympy package must be installed for SpatialNeuron" # Equations for morphology (isn't it a duplicate??) eqs_morphology = Equations(""" diameter : um length : um x : um y : um z : um area : um**2 """) full_model = model + eqs_morphology NeuronGroup.__init__(self, N, model=full_model, threshold=threshold, reset=reset, refractory=refractory, level=level + 1, clock=clock, unit_checking=unit_checking, implicit=implicit) self.model_with_diffeq_nonzero = diffeq_nonzero self._state_updater = SpatialStateUpdater(self, clock) self.Cm = ones(len(self))*Cm self.Ri = Ri self.bc_type = bc_type #default boundary condition on leaves self.bc = ones(len(self)) # boundary conditions on branch points self.changed = True # Insert morphology self.morphology = morphology self.morphology.compress(diameter=self.diameter, length=self.length, x=self.x, y=self.y, z=self.z, area=self.area)
def __init__(self, source, target = None, model = None, pre = None, post = None, max_delay = 0*ms, level = 0, clock = None,code_namespace=None, unit_checking = True, method = None, freeze = False, implicit = False, order = 1): # model (state updater) related target=target or source # default is target=source # Check clocks. For the moment we enforce the same clocks for all objects clock = clock or source.clock if source.clock!=target.clock: raise ValueError,"Source and target groups must have the same clock" if pre is None: pre_list=[] elif isSequenceType(pre) and not isinstance(pre,str): # a list of pre codes pre_list=pre else: pre_list=[pre] pre_list=[flattened_docstring(pre) for pre in pre_list] if post is not None: post=flattened_docstring(post) # Pre and postsynaptic indexes (synapse -> pre/post) self.presynaptic=DynamicArray1D(0,dtype=smallest_inttype(len(source))) # this should depend on number of neurons self.postsynaptic=DynamicArray1D(0,dtype=smallest_inttype(len(target))) # this should depend on number of neurons if not isinstance(model,SynapticEquations): model=SynapticEquations(model,level=level+1) # Insert the lastupdate variable if necessary (if it is mentioned in pre/post, or if there is event-driven code) expr=re.compile(r'\blastupdate\b') if (len(model._eventdriven)>0) or \ any([expr.search(pre) for pre in pre_list]) or \ (post is not None and expr.search(post) is not None): model+='\nlastupdate : second\n' pre_list=[pre+'\nlastupdate=t\n' for pre in pre_list] if post is not None: post=post+'\nlastupdate=t\n' # Identify pre and post variables in the model string # They are identified by _pre and _post suffixes # or no suffix for postsynaptic variables ids=set() for RHS in model._string.itervalues(): ids.update(get_identifiers(RHS)) pre_ids = [id[:-4] for id in ids if id[-4:]=='_pre'] post_ids = [id[:-5] for id in ids if id[-5:]=='_post'] post_vars = [var for var in source.var_index if isinstance(var,str)] # postsynaptic variables post_ids2 = list(ids.intersection(set(post_vars))) # post variables without the _post suffix # remember whether our equations refer to any variables in the pre- or # postsynaptic group. This is important for the state-updater, e.g. the # equations can no longer be solved as linear equations. model.refers_others = (len(pre_ids) + len(post_ids) + len(post_ids2) > 0) # Insert static equations for pre and post variables S=self for name in pre_ids: model.add_eq(name+'_pre', 'S.source.'+name+'[S.presynaptic[:]]', source.unit(name), global_namespace={'S':S}) for name in post_ids: model.add_eq(name+'_post', 'S.target.'+name+'[S.postsynaptic[:]]', target.unit(name), global_namespace={'S':S}) for name in post_ids2: # we have to change the name of the variable to avoid problems with equation processing if name not in model._string: # check that it is not already defined model.add_eq(name, 'S.target.state_(__'+name+')[S.postsynaptic[:]]', target.unit(name), global_namespace={'S':S,'__'+name:name}) self.source=source self.target=target NeuronGroup.__init__(self, 0,model=model,clock=clock,level=level+1,unit_checking=unit_checking,method=method,freeze=freeze,implicit=implicit,order=order) ''' At this point we have: * a state matrix _S with all variables * units, state dictionary with each value being a row of _S + the static equations * subgroups of synapses * link_var (i.e. we can link two synapses objects) * __len__ * __setattr__: we can write S.w=array of values * var_index is a dictionary from names to row index in _S * num_states() Things we have that we don't want: * LS structure (but it will not be filled since the object does not spike) * (from Group) __getattr_ needs to be rewritten * a complete state updater, but we need to extract parameters and event-driven parts * The state matrix is not dynamic Things we may need to add: * _pre and _post suffixes ''' self._iscompressed=False # True if compress() has already been called # Look for event-driven code in the differential equations if use_sympy: eqs=self._eqs # an Equations object #vars=eqs._diffeq_names_nonzero # Dynamic variables vars=eqs._eventdriven.keys() var_set=set(vars) for var,RHS in eqs._eventdriven.iteritems(): ids=get_identifiers(RHS) if len(set(list(ids)+[var]).intersection(var_set))==1: # no external dynamic variable # Now we test if it is a linear equation _namespace=dict.fromkeys(ids,1.) # there is a possibility of problems here (division by zero) # plus units problems? (maybe not since these are identifiers too) # another option is to use random numbers, but that doesn't solve all problems _namespace[var]=AffineFunction() try: eval(RHS,eqs._namespace[var],_namespace) except: # not linear raise TypeError,"Cannot turn equation for "+var+" into event-driven code" z=symbolic_eval(RHS) symbol_var=sympy.Symbol(var) symbol_t=sympy.Symbol('t')-sympy.Symbol('lastupdate') b=z.subs(symbol_var,0) a=sympy.simplify(z.subs(symbol_var,1)-b) if a==0: expr=symbol_var+b*symbol_t else: expr=-b/a+sympy.exp(a*symbol_t)*(symbol_var+b/a) expr=var+'='+str(expr) # Replace pre and post code # N.B.: the differential equations are kept, we will probably want to remove them! pre_list=[expr+'\n'+pre for pre in pre_list] if post is not None: post=expr+'\n'+post else: raise TypeError,"Cannot turn equation for "+var+" into event-driven code" elif len(self._eqs._eventdriven)>0: raise TypeError,"The Sympy package must be installed to produce event-driven code" if len(self._eqs._diffeq_names_nonzero)==0: self._state_updater=None # Set last spike to -infinity if 'lastupdate' in self.var_index: self.lastupdate=-1e6 # _S is turned to a dynamic array - OK this is probably not good! we may lose references at this point S=self._S self._S=DynamicArray(S.shape) self._S[:]=S # Pre and postsynaptic delays (synapse -> delay_pre/delay_post) self._delay_pre=[DynamicArray1D(len(self),dtype=np.int16) for _ in pre_list] # max 32767 delays self._delay_post=DynamicArray1D(len(self),dtype=np.int16) # Actually only useful if there is a post code! # Pre and postsynaptic synapses (i->synapse indexes) max_synapses=2147483647 # it could be explicitly reduced by a keyword # We use a loop instead of *, otherwise only 1 dynamic array is created self.synapses_pre=[DynamicArray1D(0,dtype=smallest_inttype(max_synapses)) for _ in range(len(self.source))] self.synapses_post=[DynamicArray1D(0,dtype=smallest_inttype(max_synapses)) for _ in range(len(self.target))] # Code generation self._binomial = lambda n,p:np.random.binomial(np.array(n,dtype=int),p) self.contained_objects = [] self.codes=[] self.namespaces=[] self.queues=[] for i,pre in enumerate(pre_list): code,_namespace=self.generate_code(pre,level+1,code_namespace=code_namespace) self.codes.append(code) self.namespaces.append(_namespace) self.queues.append(SpikeQueue(self.source, self.synapses_pre, self._delay_pre[i], max_delay = max_delay)) if post is not None: code,_namespace=self.generate_code(post,level+1,direct=True,code_namespace=code_namespace) self.codes.append(code) self.namespaces.append(_namespace) self.queues.append(SpikeQueue(self.target, self.synapses_post, self._delay_post, max_delay = max_delay)) self.queues_namespaces_codes = zip(self.queues, self.namespaces, self.codes) self.contained_objects+=self.queues
def test_model_definition(): ''' Tests various ways of defining models. Note that this test only checks for whether the interface accepts what it is supposed to accept, not whether the Synapses class actually does what it is supposed to do... ''' G = NeuronGroup(1, model='v:1', threshold=NoThreshold()) # model, pre and post string syn = Synapses(G, model='w:1', pre='v+=w', post='v+=w') # list of pre codes syn = Synapses(G, model='w:1', pre=['v+=w', 'v+=1']) # an equation object model = SynapticEquations('w:1') syn = Synapses(G, model=model, pre='v+=w') ############################################################################ # Some more complex examples from the docs ############################################################################ # event-driven simulations model = '''w:1 dApre/dt=-Apre/taupre : 1 (event-driven) dApost/dt=-Apost/taupost : 1 (event-driven)''' syn = Synapses(G, model=model) model = '''w : 1 p : 1''' syn = Synapses(G, model=model, pre="v+=w*(rand()<p)") syn = Synapses(G, model='''x : 1 u : 1 w : 1''', pre='''u=U+(u-U)*exp(-(t-lastupdate)/tauf) x=1+(x-1)*exp(-(t-lastupdate)/taud) i+=w*u*x x*=(1-u) u+=U*(1-u)''') # lumped variables a = 1 / (10 * ms) b = 1 / (20 * ms) c = 1 / (30 * ms) neurons = NeuronGroup(1, model="""dv/dt=(gtot-v)/(10*ms) : 1 gtot : 1""") S = Synapses(neurons, model='''dg/dt=-a*g+b*x*(1-g) : 1 dx/dt=-c*x : 1 w : 1 # synaptic weight ''', pre='x+=w') neurons.gtot = S.g v0 = 0 tau = 5 * ms neurons = NeuronGroup(1, model='''dv/dt=(v0-v+Igap)/tau : 1 Igap : 1''') S = Synapses(neurons, model='''w:1 # gap junction conductance Igap=w*(v_pre-v_post): 1''') neurons.Igap = S.Igap # static equations in synaptic model V_L = -70 * mV C_m = 0.5 * nF g_m = 25 * nS V_E1 = 0 * mV V_E2 = -20 * mV g_1 = 0.1 * nS g_2 = 0.2 * nS tau1 = 5 * ms tau2 = 50 * ms neurons = NeuronGroup( 1, model='''dV/dt = (-1/C_m)*((g_m)*(V-V_L) + I_tot) : volt I_tot : amp''', reset=-55 * mV, threshold=-50 * mV) S = Synapses(neurons, model='''I_tot = I_1 + I_2 : amp I_1 = sI_1*g_1*(V_post-V_E1) : amp dsI_1/dt = -sI_1 / tau1 : 1 I_2 = sI_2*g_2*(V_post-V_E2) : amp dsI_2/dt = -sI_2 / tau1 : 1 ''', pre='sI_1 += 1; sI_2 += 1') S[:, :] = True neurons.I_tot = S.I_tot
def __init__(self, morphology=None, model=None, threshold=None, reset=NoReset(), refractory=0 * ms, level=0, clock=None, unit_checking=True, compile=False, freeze=False, Cm=0.9 * uF / cm ** 2, Ri=150 * ohm * cm): clock = guess_clock(clock) N = len(morphology) # number of compartments if isinstance(model, str): model = Equations(model, level=level + 1) model += Equations(''' v:volt # membrane potential ''') # Process model equations (Im) to extract total conductance and the remaining current if use_sympy: try: membrane_eq=model._string['Im'] # the membrane equation except: raise TypeError,"The transmembrane current Im must be defined" # Check conditional linearity ids=get_identifiers(membrane_eq) _namespace=dict.fromkeys(ids,1.) # there is a possibility of problems here (division by zero) _namespace['v']=AffineFunction() eval(membrane_eq,model._namespace['v'],_namespace) try: eval(membrane_eq,model._namespace['v'],_namespace) except: # not linear raise TypeError,"The membrane current must be linear with respect to v" # Extracts the total conductance from Im, and the remaining current z=symbolic_eval(membrane_eq) symbol_v=sympy.Symbol('v') b=z.subs(symbol_v,0) a=-sympy.simplify(z.subs(symbol_v,1)-b) gtot_str="_gtot="+str(a)+": siemens/cm**2" I0_str="_I0="+str(b)+": amp/cm**2" model+=Equations(gtot_str+"\n"+I0_str,level=level+1) # better: explicit insertion with namespace of v else: raise TypeError,"The Sympy package must be installed for SpatialNeuron" # Equations for morphology (isn't it a duplicate??) eqs_morphology = Equations(""" diameter : um length : um x : um y : um z : um area : um**2 """) full_model = model + eqs_morphology # Create the state updater NeuronGroup.__init__(self, N, model=full_model, threshold=threshold, reset=reset, refractory=refractory, level=level + 1, clock=clock, unit_checking=unit_checking, implicit=True) #Group.__init__(self, full_model, N, unit_checking=unit_checking, level=level+1) #self._eqs = model #var_names = full_model._diffeq_names self.Cm = Cm # could be a vector? self.Ri = Ri self._state_updater = SpatialStateUpdater(self, clock) #S0 = {} # Fill missing units #for key, value in full_model._units.iteritems(): # if not key in S0: # S0[key] = 0 * value #self._S0 = [0] * len(var_names) #for var, i in zip(var_names, count()): # self._S0[i] = S0[var] # Insert morphology self.morphology = morphology self.morphology.compress(diameter=self.diameter, length=self.length, x=self.x, y=self.y, z=self.z, area=self.area)
self._P.state(self._I)[:] = -self.record # Inject if self._estimation: I = 2. * (rand() - .5) * self._amp + self._DC self.record = -I # Record self._Vrec.append(V[0]) self._Irec.append(I) if self._compensation: # Compensate self._lastI[self._posI] = -self.record[0] self._posI = (self._posI - 1) % self._ktail V[0] = V[0] - sum( self.Ke * self._lastI[range(self._posI, self._ktail) + range(0, self._posI)]) self._J += self.clock._dt * self._gain2 * (self.command - V) self.record = -(self._gain * (self.command - V) + self._J) if __name__ == '__main__': from brian import * taum = 20 * ms gl = 20 * nS Cm = taum * gl eqs = Equations('dv/dt=(-gl*v+i_inj)/Cm : volt') + electrode( 50 * Mohm, 10 * pF, vm='v', i_cmd=.5 * nA) neuron = NeuronGroup(1, model=eqs) M = StateMonitor(neuron, 'v_el', record=True) run(100 * ms) plot(M.times / ms, M[0] / mV) show()
def test_construction_single_synapses(): ''' Test the construction of synapses with a single synapse per connection. ''' G = NeuronGroup(20, model='v:1', threshold=NoThreshold()) # specifying only one group should use it as source and target syn = Synapses(G, model='w:1') assert syn.source is syn.target # specifying source and target with subgroups subgroup1, subgroup2 = G[:10], G[10:] syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') assert syn.source is subgroup1 assert syn.target is subgroup2 # create all-to-all connections syn[:, :] = True assert len(syn) == 10 * 10 # deleting a synapse should not work def delete_synapse(): syn[0, 0] = False assert_raises(ValueError, delete_synapse) # set the weights syn.w[:, :] = 2 # set the delays syn.delay[:, :] = 1 * ms all_weights = np.array([ syn.w[i, j] for i in xrange(len(subgroup1)) for j in xrange(len(subgroup2)) ]) assert (all_weights == 2).all() all_delays = np.array([ syn.delay[i, j] for i in xrange(len(subgroup1)) for j in xrange(len(subgroup2)) ]) assert (all_delays == 1 * ms).all() # create one-to-one connections syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn[:, :] = 'i == j' syn.w[:, :] = 2 assert len(syn) == len(subgroup1) for i in xrange(len(subgroup1)): for j in xrange(len(subgroup2)): if i == j: assert syn.w[i, j] == 2 else: assert len(syn.w[i, j]) == 0 net = Network(G, syn) net.run(defaultclock.dt) # adding synapses should not work after the simulation has already been run def adding_a_synapse(): syn[0, 1] = True assert_raises(AttributeError, adding_a_synapse) syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn.connect_one_to_one(subgroup1, subgroup2) syn.w[:, :] = 2 assert len(syn) == len(subgroup1) for i in xrange(len(subgroup1)): for j in xrange(len(subgroup2)): if i == j: assert syn.w[i, j] == 2 else: assert len(syn.w[i, j]) == 0 # Calling connect_one_to_one without specifying groups should use the full # source or target group syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn.connect_one_to_one(subgroup1) assert len(syn) == len(subgroup1) syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn.connect_one_to_one(post=subgroup2) assert len(syn) == len(subgroup1) syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn.connect_one_to_one() assert len(syn) == len(subgroup1) # connect_one_to_one should only work with subgroups of the same size assert_raises(TypeError, lambda: syn.connect_one_to_one(G[:2], G[:1])) # create random connections # the only two cases that can be tested exactly are 0 and 100% connection # probability syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') # floats are interpreted as connection probabilities syn[:, :] = 0.0 assert len(syn) == 0 syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn.connect_random(subgroup1, subgroup2, 0.0) assert len(syn) == 0 syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn[:, :] = 1.0 assert len(syn) == 10 * 10 # set the weights syn.w[:, :] = 2 # set the delays syn.delay[:, :] = 1 * ms all_weights = np.array([ syn.w[i, j] for i in xrange(len(subgroup1)) for j in xrange(len(subgroup2)) ]) assert (all_weights == 2).all() all_delays = np.array([ syn.delay[i, j] for i in xrange(len(subgroup1)) for j in xrange(len(subgroup2)) ]) assert (all_delays == 1 * ms).all() syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn.connect_random(subgroup1, subgroup2, 1.0) assert len(syn) == 10 * 10 # set the weights syn.w[:, :] = 2 # set the delays syn.delay[:, :] = 1 * ms all_weights = np.array([ syn.w[i, j] for i in xrange(len(subgroup1)) for j in xrange(len(subgroup2)) ]) assert (all_weights == 2).all() all_delays = np.array([ syn.delay[i, j] for i in xrange(len(subgroup1)) for j in xrange(len(subgroup2)) ]) assert (all_delays == 1 * ms).all() # Calling connect_random without specifying groups should use the full # source or target group syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn.connect_random(subgroup1, sparseness=1.0) assert len(syn) == 10 * 10 syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn.connect_random(post=subgroup2, sparseness=1.0) assert len(syn) == 10 * 10 syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn.connect_random(sparseness=1.0) assert len(syn) == 10 * 10 # Just test that probabilities between zero and one work at all syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn.connect_random(subgroup1, subgroup2, 0.3) syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn[:, :] = 0.3 # Test that probabilities outside of the legal range raise an error syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') assert_raises(ValueError, lambda: syn.connect_random(subgroup1, subgroup2, 1.3)) assert_raises(ValueError, lambda: syn.connect_random(subgroup1, subgroup2, -.3)) def wrong_probability(): syn[:, :] = -0.3 assert_raises(ValueError, wrong_probability) def wrong_probability(): #@DuplicatedSignature syn[:, :] = 1.3 assert_raises(ValueError, wrong_probability) # this test requires python 2.6 if sys.version_info[0] >= 2 and sys.version_info[1] >= 6: # Running a model with a synapses object with 0 synapses should raise a warning syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") # Trigger a warning. syn.compress() # Verify some things assert len(w) == 1 # use arrays as neuron indices instead of slices or ints syn = Synapses(subgroup1, subgroup2, model='w:1', pre='v += w') syn[np.arange(5), np.arange(5)] = True syn.w[np.arange(5), np.arange(5)] = 2 syn.delay[np.arange(5), np.arange(5)] = 5 * ms assert len(syn) == 5 * 5 assert all([syn.w[i, j] == 2 for i in xrange(5) for j in xrange(5)]) assert all( [syn.delay[i, j] == 5 * ms for i in xrange(5) for j in xrange(5)]) assert all([ len(syn.w[i, j]) == 0 for i in xrange(5, len(subgroup1)) for j in xrange(5, len(subgroup2)) ]) assert all([ len(syn.delay[i, j]) == 0 for i in xrange(5, len(subgroup1)) for j in xrange(5, len(subgroup2)) ]) # Create a synapse without a model (e.g. a simple connection with constant # weights syn = Synapses(subgroup1, subgroup2, model='', pre='v+=1')
def __init__(self, morphology=None, model=None, threshold=None, reset=NoReset(), refractory=0 * ms, level=0, clock=None, unit_checking=True, compile=False, freeze=False, Cm=0.9 * uF / cm**2, Ri=150 * ohm * cm): clock = guess_clock(clock) N = len(morphology) # number of compartments if isinstance(model, str): model = Equations(model, level=level + 1) model += Equations(''' v:volt # membrane potential ''') # Process model equations (Im) to extract total conductance and the remaining current if use_sympy: try: membrane_eq = model._string['Im'] # the membrane equation except: raise TypeError, "The transmembrane current Im must be defined" # Check conditional linearity ids = get_identifiers(membrane_eq) _namespace = dict.fromkeys( ids, 1. ) # there is a possibility of problems here (division by zero) _namespace['v'] = AffineFunction() eval(membrane_eq, model._namespace['v'], _namespace) try: eval(membrane_eq, model._namespace['v'], _namespace) except: # not linear raise TypeError, "The membrane current must be linear with respect to v" # Extracts the total conductance from Im, and the remaining current z = symbolic_eval(membrane_eq) symbol_v = sympy.Symbol('v') b = z.subs(symbol_v, 0) a = -sympy.simplify(z.subs(symbol_v, 1) - b) gtot_str = "_gtot=" + str(a) + ": siemens/cm**2" I0_str = "_I0=" + str(b) + ": amp/cm**2" model += Equations( gtot_str + "\n" + I0_str, level=level + 1) # better: explicit insertion with namespace of v else: raise TypeError, "The Sympy package must be installed for SpatialNeuron" # Equations for morphology (isn't it a duplicate??) eqs_morphology = Equations(""" diameter : um length : um x : um y : um z : um area : um**2 """) full_model = model + eqs_morphology # Create the state updater NeuronGroup.__init__(self, N, model=full_model, threshold=threshold, reset=reset, refractory=refractory, level=level + 1, clock=clock, unit_checking=unit_checking, implicit=True) #Group.__init__(self, full_model, N, unit_checking=unit_checking, level=level+1) #self._eqs = model #var_names = full_model._diffeq_names self.Cm = Cm # could be a vector? self.Ri = Ri self._state_updater = SpatialStateUpdater(self, clock) #S0 = {} # Fill missing units #for key, value in full_model._units.iteritems(): # if not key in S0: # S0[key] = 0 * value #self._S0 = [0] * len(var_names) #for var, i in zip(var_names, count()): # self._S0[i] = S0[var] # Insert morphology self.morphology = morphology self.morphology.compress(diameter=self.diameter, length=self.length, x=self.x, y=self.y, z=self.z, area=self.area)
def test_model_definition(): ''' Tests various ways of defining models. Note that this test only checks for whether the interface accepts what it is supposed to accept, not whether the Synapses class actually does what it is supposed to do... ''' G = NeuronGroup(1, model='v:1', threshold=NoThreshold()) # model, pre and post string syn = Synapses(G, model='w:1', pre='v+=w', post='v+=w') # list of pre codes syn = Synapses(G, model='w:1', pre=['v+=w', 'v+=1']) # an equation object model = SynapticEquations('w:1') syn = Synapses(G, model=model, pre='v+=w') ############################################################################ # Some more complex examples from the docs ############################################################################ # event-driven simulations model='''w:1 dApre/dt=-Apre/taupre : 1 (event-driven) dApost/dt=-Apost/taupost : 1 (event-driven)''' syn = Synapses(G, model=model) model ='''w : 1 p : 1''' syn = Synapses(G, model=model, pre="v+=w*(rand()<p)") syn = Synapses(G, model='''x : 1 u : 1 w : 1''', pre='''u=U+(u-U)*exp(-(t-lastupdate)/tauf) x=1+(x-1)*exp(-(t-lastupdate)/taud) i+=w*u*x x*=(1-u) u+=U*(1-u)''') # lumped variables a = 1 / (10 * ms) b = 1 / (20 * ms) c = 1 / (30 * ms) neurons = NeuronGroup(1, model="""dv/dt=(gtot-v)/(10*ms) : 1 gtot : 1""") S=Synapses(neurons, model='''dg/dt=-a*g+b*x*(1-g) : 1 dx/dt=-c*x : 1 w : 1 # synaptic weight ''', pre='x+=w') neurons.gtot = S.g v0 = 0 tau = 5 * ms neurons = NeuronGroup(1, model='''dv/dt=(v0-v+Igap)/tau : 1 Igap : 1''') S=Synapses(neurons, model='''w:1 # gap junction conductance Igap=w*(v_pre-v_post): 1''') neurons.Igap = S.Igap # static equations in synaptic model V_L = -70 * mV C_m = 0.5 * nF g_m = 25 * nS V_E1 = 0 * mV V_E2 = -20 * mV g_1 = 0.1 * nS g_2 = 0.2 * nS tau1 = 5 * ms tau2 = 50 * ms neurons = NeuronGroup(1, model='''dV/dt = (-1/C_m)*((g_m)*(V-V_L) + I_tot) : volt I_tot : amp''', reset=-55*mV, threshold=-50*mV) S=Synapses(neurons, model='''I_tot = I_1 + I_2 : amp I_1 = sI_1*g_1*(V_post-V_E1) : amp dsI_1/dt = -sI_1 / tau1 : 1 I_2 = sI_2*g_2*(V_post-V_E2) : amp dsI_2/dt = -sI_2 / tau1 : 1 ''', pre='sI_1 += 1; sI_2 += 1') S[:, :] = True neurons.I_tot = S.I_tot
def __init__(self, morphology=None, model=None, threshold=None, reset=NoReset(), refractory=0 * ms, level=0, clock=None, unit_checking=True, compile=False, freeze=False, implicit=True, Cm=0.9 * uF / cm**2, Ri=150 * ohm * cm, bc_type=2, diffeq_nonzero=True): clock = guess_clock(clock) N = len(morphology) # number of compartments if isinstance(model, str): model = Equations(model, level=level + 1) model += Equations(''' v:volt # membrane potential ''') # Process model equations (Im) to extract total conductance and the remaining current if use_sympy: try: membrane_eq = model._string['Im'] # the membrane equation except: raise TypeError, "The transmembrane current Im must be defined" # Check conditional linearity ids = get_identifiers(membrane_eq) _namespace = dict.fromkeys( ids, 1. ) # there is a possibility of problems here (division by zero) _namespace['v'] = AffineFunction() eval(membrane_eq, model._namespace['v'], _namespace) try: eval(membrane_eq, model._namespace['v'], _namespace) except: # not linear raise TypeError, "The membrane current must be linear with respect to v" # Extracts the total conductance from Im, and the remaining current z = symbolic_eval(membrane_eq) symbol_v = sympy.Symbol('v') b = z.subs(symbol_v, 0) a = -sympy.simplify(z.subs(symbol_v, 1) - b) gtot_str = "_gtot=" + str(a) + ": siemens/cm**2" I0_str = "_I0=" + str(b) + ": amp/cm**2" model += Equations( gtot_str + "\n" + I0_str, level=level + 1) # better: explicit insertion with namespace of v else: raise TypeError, "The Sympy package must be installed for SpatialNeuron" # Equations for morphology (isn't it a duplicate??) eqs_morphology = Equations(""" diameter : um length : um x : um y : um z : um area : um**2 """) full_model = model + eqs_morphology NeuronGroup.__init__(self, N, model=full_model, threshold=threshold, reset=reset, refractory=refractory, level=level + 1, clock=clock, unit_checking=unit_checking, implicit=implicit) self.model_with_diffeq_nonzero = diffeq_nonzero self._state_updater = SpatialStateUpdater(self, clock) self.Cm = ones(len(self)) * Cm self.Ri = Ri self.bc_type = bc_type #default boundary condition on leaves self.bc = ones(len(self)) # boundary conditions on branch points self.changed = True # Insert morphology self.morphology = morphology self.morphology.compress(diameter=self.diameter, length=self.length, x=self.x, y=self.y, z=self.z, area=self.area)
def __init__( self, params=default_params, pyr_params=pyr_params(), inh_params=inh_params(), plasticity_params=plasticity_params(), background_input=None, task_inputs=None, clock=defaultclock, ): self.params = params self.pyr_params = pyr_params self.inh_params = inh_params self.plasticity_params = plasticity_params self.background_input = background_input self.task_inputs = task_inputs ## Set up equations # Exponential integrate-and-fire neuron eqs = exp_IF(params.C, params.gL, params.EL, params.VT, params.DeltaT) eqs += Equations("g_muscimol : nS") # AMPA conductance - recurrent input current eqs += exp_synapse("g_ampa_r", params.tau_ampa, siemens) eqs += Current("I_ampa_r=g_ampa_r*(E-vm): amp", E=params.E_ampa) # AMPA conductance - background input current eqs += exp_synapse("g_ampa_b", params.tau_ampa, siemens) eqs += Current("I_ampa_b=g_ampa_b*(E-vm): amp", E=params.E_ampa) # AMPA conductance - task input current eqs += exp_synapse("g_ampa_x", params.tau_ampa, siemens) eqs += Current("I_ampa_x=g_ampa_x*(E-vm): amp", E=params.E_ampa) # Voltage-dependent NMDA conductance eqs += biexp_synapse("g_nmda", params.tau1_nmda, params.tau2_nmda, siemens) eqs += Equations("g_V = 1/(1+(Mg/3.57)*exp(-0.062 *vm/mV)) : 1 ", Mg=params.Mg) eqs += Current("I_nmda=g_V*g_nmda*(E-vm): amp", E=params.E_nmda) # GABA-A conductance eqs += exp_synapse("g_gaba_a", params.tau_gaba_a, siemens) eqs += Current("I_gaba_a=(g_gaba_a+g_muscimol)*(E-vm): amp", E=params.E_gaba_a) eqs += InjectedCurrent("I_dcs: amp") # Total synaptic conductance eqs += Equations("g_syn=g_ampa_r+g_ampa_x+g_ampa_b+g_V*g_nmda+g_gaba_a : siemens") eqs += Equations("g_syn_exc=g_ampa_r+g_ampa_x+g_ampa_b+g_V*g_nmda : siemens") # Total synaptic current eqs += Equations( "I_abs=(I_ampa_r**2)**.5+(I_ampa_b**2)**.5+(I_ampa_x**2)**.5+(I_nmda**2)**.5+(I_gaba_a**2)**.5 : amp" ) NeuronGroup.__init__( self, params.network_group_size, model=eqs, threshold=-20 * mV, refractory=1 * ms, reset=params.Vr, compile=True, freeze=True, clock=clock, ) self.init_subpopulations() self.init_connectivity(clock)