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()
def cramer_noise(tr, GExc: NeuronGroup, GInh: NeuronGroup) -> [BrianObject]: """ Noise inspired by Cramer et al. 2020 (preprint) where a certain number Kext of incoming connections to each neuron is replaced by external noise. Related parameters: - :data:`net.standard_params.cramer_noise_active` - :data:`net.standard_params.cramer_noise_Kext` - :data:`net.standard_params.cramer_noise_rate` """ namespace = tr.netw.f_to_dict(short_names=True, fast_access=True) N = tr.N_e Kext = tr.cramer_noise_Kext p_ee_target = tr.p_ee / (1 - Kext) p_ie_target = tr.p_ie / (1 - Kext) conductance_prefix = "" if tr.syn_cond_mode == "exp" else "x" GNoise = PoissonGroup(N, rates=tr.cramer_noise_rate, dt=0.1 * ms) SynNoiseE = Synapses(source=GNoise, target=GExc, on_pre=f"{conductance_prefix}ge_post += a_ee", namespace=namespace) SynNoiseE.connect(p=Kext * p_ee_target) SynNoiseI = Synapses(source=GNoise, target=GInh, on_pre=f"{conductance_prefix}ge_post += a_ie", namespace=namespace) SynNoiseI.connect(p=Kext * p_ie_target) return [GNoise, SynNoiseE, SynNoiseI]
def echo_spike(p, tStim, tTot): start_scope() prefs.codegen.target = "numpy" ################################ # Compute properties ################################ dvInpSpike = p['nu_DV'] # Voltage increase per noise spike dvExcSpike = p['LIF_DV'] # Voltage increase per lateral spike # dvExcSpike = p['LIF_T_0'] / (1.0 * p['N'] * p['p_conn']) # Voltage increase per lateral spike print("typical spike threshold", p['LIF_T_0']) print("typical potential change per noise spike", dvInpSpike) print("typical potential change per lateral spike", dvExcSpike) ################################ # Create input population ################################ nTStimPost = int(tTot / tStim) - 1 # After input switched off, 0-input will be repeated nTStimPost*tStim timesteps patternInp = (np.random.uniform(0, 1, p['N']) < p['nu_p']).astype(int) pattern0 = np.zeros(p['N']) rates_all = np.array([patternInp] + [pattern0]*nTStimPost) * p['nu_FREQ'] rateTimedArray = TimedArray(rates_all, dt=tStim) gInp = PoissonGroup(p['N'], rates="rateTimedArray(t, i)") # gInp = PoissonGroup(p['N'], p['nu_FREQ']) ################################ # Create reservoir population ################################ gExc = brian2wrapper.NeuronGroupLIF(p['N'], p['LIF_V_0'], p['LIF_T_0'], p['LIF_V_TAU']) ################################ # Create synapses ################################ sInpExc = Synapses(gInp, gExc, on_pre='v_post += dvInpSpike', method='exact') sExcExc = Synapses(gExc, gExc, on_pre='v_post += dvExcSpike', method='exact') ################################ # Connect synapses ################################ # * Input and LIF one-to-one # * LIF neurons to each other sparsely sInpExc.connect(j='i') sExcExc.connect(p=p['p_conn']) ################################ # Init Monitors ################################ #spikemonInp = SpikeMonitor(gInp) spikemonExc = SpikeMonitor(gExc) ################################ # Run simulation ################################ run(tTot) return np.array(spikemonExc.i), np.array(spikemonExc.t)
def construct_headings_cosine(self, h, v): headings = cx_spiking.inputs.compute_cos_headings(h, N=self.N_TL2, vmin=5, vmax=100) self.headings_hz = headings * Hz self.P_HEADING = PoissonGroup(self.N_TL2, rates=self.headings_hz[0, :], name='P_HEADING') return self.P_HEADING
def initialise_memory_accumulator(self): self.CPU4_memory_stimulus = CPU_MEMORY_starting_value * np.ones( (self.T, self.N_CPU4)) * Hz self.P_CPU4_MEMORY = PoissonGroup( self.N_CPU4, rates=self.CPU4_memory_stimulus[0, :], name='P_CPU4_MEMORY') self.SPM_CPU4_MEMORY = SpikeMonitor(self.P_CPU4_MEMORY, name='SPM_P_CPU4_MEMORY') return [self.P_CPU4_MEMORY, self.SPM_CPU4_MEMORY]
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()
def construct_headings_vonmises(self, h, v): headings = cx_spiking.inputs.compute_headings(h, N=self.N_TL2 // 2, vmin=5, vmax=100) headings = np.tile(headings, 2) self.headings_hz = headings * Hz self.P_HEADING = PoissonGroup(self.N_TL2, rates=self.headings_hz[0, :], name='P_HEADING') return self.P_HEADING
def test_magic_collect(): ''' Make sure all expected objects are collected in a magic network ''' P = PoissonGroup(10, rates=100*Hz) G = NeuronGroup(10, 'v:1', threshold='False') S = Synapses(G, G, '') state_mon = StateMonitor(G, 'v', record=True) spike_mon = SpikeMonitor(G) rate_mon = PopulationRateMonitor(G) objects = collect() assert len(objects) == 6, ('expected %d objects, got %d' % (6, len(objects)))
def construct_flow(self, h, v): # Convert velocity into optical flow responses flow = cx_spiking.inputs.compute_flow(h, v, baseline=50, vmin=0, vmax=50) # flow = np.concatenate((flow, np.zeros((self.T_inbound, flow.shape[1]))), axis=0) self.flow_hz = flow * Hz self.P_FLOW = PoissonGroup(self.N_TN2, rates=self.flow_hz[0, :], name='P_FLOW') return self.P_FLOW
def test_spikemonitor(): """ Test collector function for SpikeMonitor """ # example 1 grp = NeuronGroup(5, '''dv/dt = (v0 - v)/tau :volt''', method='exact', threshold='v > v_th', reset='v = v0', name="My_Neurons") tau = 10 * ms v0 = -70 * mV v_th = 800 * mV mon = SpikeMonitor(grp, 'v', record=[0, 4]) mon_dict = collect_SpikeMonitor(mon) assert mon_dict['source'] == 'My_Neurons' assert mon_dict['variables'].sort() == ['i', 't', 'v'].sort() assert mon_dict['record'] == [0, 4] assert mon_dict['event'] == 'spike' assert mon_dict['when'] == 'thresholds' assert mon_dict['order'] == 1 # example 2 pos = PoissonGroup(5, rates=100 * Hz) smon = SpikeMonitor(pos, record=[0, 1, 2, 3, 4]) smon_dict = collect_SpikeMonitor(smon) assert smon_dict['source'] == pos.name assert 'i' in smon_dict['variables'] assert smon_dict['record'] == [0, 1, 2, 3, 4] assert smon_dict['when'] == 'thresholds' assert smon_dict['order'] == 1 # example 3 spk = SpikeGeneratorGroup(10, [2, 6, 8], [5 * ms, 10 * ms, 15 * ms]) spkmon = SpikeMonitor(spk, ['t', 'i'], record=0) smon_dict = collect_SpikeMonitor(spkmon) assert smon_dict['record'] == np.array([0]) assert 't' in smon_dict['variables'] assert smon_dict['source'] == spk.name assert smon_dict['when'] == 'thresholds' assert smon_dict['order'] == 1
def test_magic_collect(): ''' Make sure all expected objects are collected in a magic network ''' P = PoissonGroup(10, rates=100 * Hz) G = NeuronGroup(10, 'v:1') S = Synapses(G, G, '') G_runner = G.custom_operation('') S_runner = S.custom_operation('') state_mon = StateMonitor(G, 'v', record=True) spike_mon = SpikeMonitor(G) rate_mon = PopulationRateMonitor(G) objects = collect() assert len(objects) == 8, ('expected %d objects, got %d' % (8, len(objects)))
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()
def test_poissongroup(): """ Test standard dictionary representation of PoissonGroup """ # example1 N = 10 rates = numpy.arange(1, 11, step=1) * Hz poisongrp = PoissonGroup(N, rates) poisson_dict = collect_PoissonGroup(poisongrp, get_local_namespace(0)) assert poisson_dict['N'] == N assert (poisson_dict['rates'] == rates).all() assert poisson_dict['rates'].has_same_dimensions(5 * Hz) assert poisson_dict['rates'].dtype == float with pytest.raises(KeyError): assert poisson_dict['run_regularly'] # example2 F = 10 * Hz three = 3 * Hz two = 2 * Hz poisongrp = PoissonGroup(N, rates='F + two') poisongrp.run_regularly('F = F + three', dt=10 * ms, name="Run_at_0_01") poisson_dict = collect_PoissonGroup(poisongrp, get_local_namespace(0)) assert poisson_dict['rates'] == 'F + two' assert poisson_dict['run_regularly'][0]['name'] == 'Run_at_0_01' assert poisson_dict['run_regularly'][0]['code'] == 'F = F + three' assert poisson_dict['run_regularly'][0]['dt'] == 10 * ms assert poisson_dict['run_regularly'][0]['when'] == 'start' assert poisson_dict['run_regularly'][0]['order'] == 0 assert poisson_dict['identifiers']['three'] == three assert poisson_dict['identifiers']['two'] == two with pytest.raises(IndexError): poisson_dict['run_regularly'][1]
def mk_sencircuit_2cplastic(task_info): """ Creates balanced network representing sensory circuit with 2c model in the excitatory neurons. returns: groups, synapses, subgroups groups and synapses have to be added to the "Network" in order to run the simulation subgroups is used for establishing connections between the sensory and integration circuit; do not add subgroups to the "Network" psr following the published Brian1 code in DB model from Wimmer et al. 2015 - brain2 code - two-compartmental model following Naud & Sprekeler 2018 - implementation runs in cpp_standalone mode, compatible with SNEP """ from numpy import log as np_log # ------------------------------------- # Sensory circuit parameters # ------------------------------------- # populations N_E = task_info['sen']['populations']['N_E'] # total number of E neurons sub = task_info['sen']['populations']['sub'] # fraction corresponding to subpops 1,2 N_E1 = int(N_E * sub) # size of exc subpops that responds to the stimuli N_I = task_info['sen']['populations']['N_I'] # total number of I neurons N_X = task_info['sen']['populations']['N_X'] # size of external pop # local recurrent connections eps = task_info['sen']['connectivity']['eps'] # connection probability for EE, EI, IE and II w_p = task_info['sen']['connectivity']['w_p'] # relative synaptic strength within pop E1 and E2 w_m = 2 - w_p # relative synaptic strength across pop E1 and E2 gEEs = task_info['sen']['2c']['gEEs'] # weight of EE synapses, prev: 0.7589*nS gEI = task_info['sen']['connectivity']['gEI'] # weight of EI synapses, prev: 1.5179*nS gIEs = task_info['sen']['2c']['gIEs'] # weight of IE synapses, prev: 12.6491*nS gII = task_info['sen']['connectivity']['gII'] # weight of II synapses gmax = task_info['sen']['connectivity']['gmax'] # maximum synaptic weight dE = '0.5*ms + rand()*1.0*ms' # range of transmission delays of E synapses, (0.5:1.5) dI = '0.1*ms + rand()*0.8*ms' # range of transmission delays of I synapses, (0.1:0.9) # external connections epsX = task_info['sen']['connectivity']['epsX'] # connection probability for ext synapses alphaX = task_info['sen']['connectivity']['alphaX'] # 0: global input, 1: local input gXEs = task_info['sen']['2c']['gXEs'] # weight of ext to E synapses of soma gXI = task_info['sen']['connectivity']['gXI'] # weight of ext to I synapses dX = '0.5*ms + rand()*1.0*ms' # range of transmission delays of X synapses, (0.5:1.5) # neuron model CmI = task_info['sen']['neuron']['CmI'] # membrane capacitance of I neurons gleakI = task_info['sen']['neuron']['gleakI'] # leak conductance of I neurons Vl = task_info['sen']['neuron']['Vl'] # reversal potential Vt = task_info['sen']['neuron']['Vt'] # threshold potential Vr = task_info['sen']['neuron']['Vr'] # reset potential, only for inh tau_refI = task_info['sen']['neuron']['tau_refI'] # absolute refractory period of I neurons nu_ext = task_info['sen']['neuron']['nu_ext'] # rate of external Poisson neurons, prev: 12.5*Hz # soma taus = task_info['sen']['2c']['taus'] # timescale of membrane potential Cms = task_info['sen']['2c']['Cms'] # capacitance gleakEs = Cms/taus tauws = task_info['sen']['2c']['tauws'] # timescale of recovery ("slow") variable bws = task_info['sen']['2c']['bws'] # strength of spike-triggered facilitation (bws < 0) gCas = task_info['sen']['2c']['gCas'] # strenght of forward calcium spike propagation tau_refE = task_info['sen']['2c']['tau_refE'] # refractory period # dendrite taud = task_info['sen']['2c']['taud'] Cmd = task_info['sen']['2c']['Cmd'] gleakEd = Cmd/taud tauwd = task_info['sen']['2c']['tauwd'] # timescale of recovery ("slow") variable awd = task_info['sen']['2c']['awd'] # stregth of subthreshold facilitations (awd < 0) gCad = task_info['sen']['2c']['gCad'] # strength of local regenerative activity bpA = task_info['sen']['2c']['bpA'] # strength of backpropagation activity (c variable) k1 = task_info['sen']['2c']['k1'] # rectangular kernel for backpropagating activity k2 = task_info['sen']['2c']['k2'] # if t in [0.5, 2.0] we'll have backpropagating current muOUs = task_info['sen']['2c']['muOUs'] # OU parameters for background noise of soma #muOUd = task_info['sen']['2c']['muOUd'] # OU parameters for background noise of dendrites sigmaOU = task_info['sen']['2c']['sigmaOU'] tauOU = task_info['sen']['2c']['tauOU'] # synapse models VrevE = task_info['sen']['synapse']['VrevE'] # reversal potential for E synapses VrevI = task_info['sen']['synapse']['VrevI'] # reversal potential for I synapses in inh tau_decay = task_info['sen']['synapse']['tau_decay'] # decay constant of AMPA, GABA tau_rise = task_info['sen']['synapse']['tau_rise'] # rise constant of AMPA, GABA for inh VrevIsd = task_info['sen']['synapse']['VrevIsd'] # rev potential for I synapses in soma, dend # plasticity in dendrites eta0 = task_info['sen']['2c']['eta0'] tauB = task_info['sen']['2c']['tauB'] targetB = task_info['targetB'] B0 = tauB*targetB tau_update = task_info['sen']['2c']['tau_update'] eta = eta0 * tau_update / tauB validburst = task_info['sen']['2c']['validburst'] # if tau_burst = 4*ms, at 16 ms stopburst = 0.0183 min_burst_stop = task_info['sen']['2c']['min_burst_stop'] # thus, we will set it at critrefburst = 0.02 tau_burst = -validburst / np_log(min_burst_stop) * second param2c = {'gEE': gEEs, 'gEI': gEI, 'gIE': gIEs, 'gII': gII, 'gmax': gmax, 'gXEs': gXEs, 'gXI': gXI, 'gleakEs': gleakEs, 'gleakEd': gleakEd, 'gleakI': gleakI, 'Cms': Cms, 'Cmd': Cmd, 'CmI': CmI, 'Vl': Vl, 'Vt': Vt, 'Vr': Vr, 'VrevE': VrevE, 'VrevIsd': VrevIsd, 'VrevI': VrevI, 'taus': taus, 'taud': taud, 'tau_refE': tau_refE, 'tau_refI': tau_refI, 'tau_decay': tau_decay, 'tau_rise': tau_rise, 'tau_ws': tauws, 'tau_wd': tauwd, 'bws': bws, 'awd': awd, 'gCas': gCas, 'gCad': gCad, 'bpA': bpA, 'k1': k1, 'k2': k2, 'muOUs': muOUs, 'tauOU': tauOU, 'sigmaOU': sigmaOU, 'w_p': w_p, 'w_m': w_m, 'sub': sub, 'eps': eps, 'epsX': epsX, 'alphaX': alphaX, 'eta': eta, 'B0': B0, 'tauB': tauB, 'tau_burst': tau_burst, 'min_burst_stop': min_burst_stop} # numerical integration method nummethod = task_info['simulation']['nummethod'] # ------------------------------------- # Set up model and connections # ------------------------------------- # neuron equations eqss = ''' dV/dt = (-g_ea*(V-VrevE) -g_i*(V-VrevIsd) -(V-Vl))/tau + (gCas/(1+exp(-(V_d/mV + 38)/6)) + w_s + I)/Cm : volt (unless refractory) dg_ea/dt = (-g_ea + x_ea) / tau_decay : 1 dx_ea/dt = -x_ea / tau_rise : 1 dg_i/dt = (-g_i + x_i) / tau_decay : 1 dx_i/dt = -x_i / tau_rise : 1 dw_s/dt = -w_s / tau_ws : amp tau = taus : second Cm = Cms : farad I = Irec(t, i) : amp V_d : volt (linked) B : 1 (linked) burst_start : 1 (linked) burst_stop : 1 (linked) muOUd : amp (linked) ''' # dIbg/dt = (muOUs - Ibg) / tauOU + (sigmaOU * xi) / sqrt(tauOU / 2) : amp --> they have I_Ext eqsd = ''' dV_d/dt = (-g_ea*(V_d-VrevE) -(V_d-Vl))/tau + (gCad/(1+exp(-(V_d/mV + 38)/6)) + w_d + K + Ibg)/Cm : volt dg_ea/dt = (-g_ea + x_ea) / tau_decay : 1 dx_ea/dt = -x_ea / tau_rise : 1 dw_d/dt = (-w_d + awd*(V_d - Vl))/tau_wd : amp dIbg/dt = (muOUd - Ibg) / tauOU + (sigmaOU * xi) / sqrt(tauOU / 2) : amp K = bpA * (((t-lastspike_soma) >= k1) * ((t-lastspike_soma) <= k2)) : amp dB/dt = -B / tauB : 1 dburst_start/dt = -burst_start / tau_burst : 1 (unless refractory) dburst_stop/dt = -burst_stop / tau_burst : 1 tau = taud : second Cm = Cmd : farad muOUd : amp lastspike_soma : second (linked) ''' eqsI = ''' dV/dt = (-g_ea*(V-VrevE) -g_i*(V-VrevI) -(V-Vl))/tau + I/Cm : volt (unless refractory) dg_ea/dt = (-g_ea + x_ea) / tau_decay : 1 dx_ea/dt = -x_ea / tau_rise : 1 dg_i/dt = (-g_i + x_i) / tau_decay : 1 dx_i/dt = -x_i / tau_rise : 1 tau = CmI/gleakI : second Cm = CmI : farad I : amp ''' # neuron groups soma = NeuronGroup(N_E, model=eqss, method=nummethod, threshold='V>=Vt', reset='''V = Vl w_s += bws burst_start += 1 burst_stop = 1''', refractory=tau_refE, namespace=param2c, name='soma') dend = NeuronGroup(N_E, model=eqsd, method=nummethod, threshold='burst_start > 1 + min_burst_stop', reset='''B += 1 burst_start = 0''', refractory='burst_stop >= min_burst_stop', namespace=param2c, name='dend') senI = NeuronGroup(N_I, model=eqsI, method=nummethod, threshold='V>=Vt', reset='V=Vr', refractory=tau_refI, namespace=param2c, name='senI') # linked variables soma.V_d = linked_var(dend, 'V_d') soma.B = linked_var(dend, 'B') soma.burst_start = linked_var(dend, 'burst_start') soma.burst_stop = linked_var(dend, 'burst_stop') soma.muOUd = linked_var(dend, 'muOUd') dend.lastspike_soma = linked_var(soma, 'lastspike') # subgroups soma1 = soma[:N_E1] dend1 = dend[:N_E1] soma2 = soma[N_E1:] dend2 = dend[N_E1:] # update muOUd with plasticity rule dend1.muOUd = '-50*pA - rand()*100*pA' # random initialisation of weights -50:-150 pA dend1.run_regularly('muOUd = clip(muOUd - eta * (B - B0), -100*amp, 0)', dt=tau_update) # TODO: check the target vs burst rate convergence # TODO: try tau_B = 50,000 sec, but mayb\e this is not the case because you do reach the target # synapses # weight according the different subgroups condsame = '(i<N_pre*sub and j<N_post*sub) or (i>=N_pre*sub and j>=N_post*sub)' conddiff = '(i<N_pre*sub and j>=N_post*sub) or (i>=N_pre*sub and j<N_post*sub)' # AMPA: exc --> exc synSESE = Synapses(soma, soma, model='w : 1', method=nummethod, on_pre='''x_ea += w w = clip(w, 0, gmax)''', namespace=param2c, name='synSESE') synSESE.connect(p='eps') synSESE.w[condsame] = 'w_p * gEE/gleakEs * (1 + randn()*0.5)' synSESE.w[conddiff] = 'w_m * gEE/gleakEs * (1 + randn()*0.5)' synSESE.delay = dE # AMPA: exc --> inh synSESI = Synapses(soma, senI, model='w : 1', method=nummethod, on_pre='''x_ea += w w = clip(w, 0, gmax)''', namespace=param2c, name='synSESI') synSESI.connect(p='eps') synSESI.w = 'gEI/gleakI * (1 + randn()*0.5)' synSESI.delay = dE # GABA: inh --> exc synSISE = Synapses(senI, soma, model='w : 1', method=nummethod, on_pre='''x_i += w w = clip(w, 0, gmax)''', namespace=param2c, name='synSISE') synSISE.connect(p='eps') synSISE.w = 'gIE/gleakEs * (1 + randn()*0.5)' synSISE.delay = dI # GABA: inh --> inh synSISI = Synapses(senI, senI, model='w : 1', method=nummethod, on_pre='''x_i += w w = clip(w, 0, gmax)''', namespace=param2c, name='synSISI') synSISI.connect(p='eps') synSISI.w = 'gII/gleakI * (1 + randn()*0.5)' synSISI.delay = dI # external inputs and synapses extS = PoissonGroup(N_X, rates=nu_ext) synSXSEs = Synapses(extS, soma, model='w : 1', method=nummethod, on_pre='''x_ea += w w = clip(w, 0, gmax)''', namespace=param2c, name='synSXSEs') synSXSEs.connect(condition=condsame, p='epsX * (1 + alphaX)') synSXSEs.connect(condition=conddiff, p='epsX * (1 - alphaX)') synSXSEs.w = 'gXEs/gleakEs * (1 + randn()*0.5)' synSXSEs.delay = dX synSXSI = Synapses(extS, senI, model='w : 1', method=nummethod, on_pre='''x_ea += w w = clip(w, 0, gmax)''', namespace=param2c, name='synSXSI') synSXSI.connect(p='epsX') synSXSI.w = 'gXI/gleakI * (1 + randn()*0.5)' synSXSI.delay = dX # external inputs to dendrites mimicking decision circuit subDE = 240 rateDE = 40*Hz # TODO: lower rate --> 40 or 30 d = 1*ms wDS = 0.06 XDE = PoissonGroup(subDE, rates=rateDE) synXDEdend = Synapses(XDE, dend1, model='w : 1', method=nummethod, delay=d, on_pre='x_ea += w', namespace=param2c, name='synXDEdend') synXDEdend.connect(p=0.2) synXDEdend.w = 'wDS' # variables to return groups = {'soma': soma, 'dend': dend, 'SI': senI, 'SX': extS, 'XDE': XDE} subgroups = {'soma1': soma1, 'soma2': soma2, 'dend1': dend1, 'dend2': dend2} synapses = {'synSESE': synSESE, 'synSESI': synSESI, 'synSISE': synSISE, 'synSISI': synSISI, 'synSXSI': synSXSI, 'synSXSEs': synSXSEs, 'synXDEdend': synXDEdend} return groups, synapses, subgroups
def mk_sencircuit(task_info): """ Creates balanced network representing sensory circuit. returns: groups, synapses, subgroups groups and synapses have to be added to the "Network" in order to run the simulation subgroups is used for establishing connections between the sensory and integration circuit; do not add subgroups to the "Network" psr following the published Brian1 code in DB model from Wimmer et al. 2015 - brain2 code - implementation runs in cpp_standalone mode, compatible with SNEP """ # ------------------------------------- # Sensory circuit parameters # ------------------------------------- # populations N_E = task_info['sen']['populations']['N_E'] # total number of E neurons sub = task_info['sen']['populations']['sub'] # fraction corresponding to subpops 1,2 N_E1 = int(N_E * sub) # size of exc subpops that responds to the stimuli N_I = task_info['sen']['populations']['N_I'] # total number of I neurons N_X = task_info['sen']['populations']['N_X'] # size of external pop # local recurrent connections eps = task_info['sen']['connectivity']['eps'] # connection probability for EE, EI, IE and II w_p = task_info['sen']['connectivity']['w_p'] # relative synaptic strength within pop E1 and E2 w_m = 2 - w_p # relative synaptic strength across pop E1 and E2 gEE = task_info['sen']['connectivity']['gEE'] # weight of EE synapses, prev: 0.7589*nS gEI = task_info['sen']['connectivity']['gEI'] # weight of EI synapses, prev: 1.5179*nS gIE = task_info['sen']['connectivity']['gIE'] # weight of IE synapses, prev: 12.6491*nS gII = task_info['sen']['connectivity']['gII'] # weight of II synapses gmax = task_info['sen']['connectivity']['gmax'] # maximum synaptic weight dE = '0.5*ms + rand()*1.0*ms' # range of transmission delays of E synapses, (0.5:1.5) dI = '0.1*ms + rand()*0.8*ms' # range of transmission delays of I synapses, (0.1:0.9) # external connections epsX = task_info['sen']['connectivity']['epsX'] # connection probability for ext synapses alphaX = task_info['sen']['connectivity']['alphaX'] # 0: global input, 1: local input gXE = task_info['sen']['connectivity']['gXE'] # weight of ext to E synapses gXI = task_info['sen']['connectivity']['gXI'] # weight of ext to I synapses dX = '0.5*ms + rand()*1.0*ms' # range of transmission delays of X synapses, (0.5:1.5) # neuron models CmE = task_info['sen']['neuron']['CmE'] # membrane capacitance of E neurons CmI = task_info['sen']['neuron']['CmI'] # membrane capacitance of I neurons gleakE = task_info['sen']['neuron']['gleakE'] # leak conductance of E neurons gleakI = task_info['sen']['neuron']['gleakI'] # leak conductance of I neurons Vl = task_info['sen']['neuron']['Vl'] # resting potential Vt = task_info['sen']['neuron']['Vt'] # spiking threshold Vr = task_info['sen']['neuron']['Vr'] # reset potential tau_refE = task_info['sen']['neuron']['tau_refE'] # absolute refractory period of E neurons tau_refI = task_info['sen']['neuron']['tau_refI'] # absolute refractory period of I neurons nu_ext = task_info['sen']['neuron']['nu_ext'] # rate of external Poisson neurons, prev: 12.5*Hz # synapse models VrevE = task_info['sen']['synapse']['VrevE'] # reversal potential for E synapses VrevI = task_info['sen']['synapse']['VrevI'] # reversal potential for I synapses tau_decay = task_info['sen']['synapse']['tau_decay'] # decay constants of AMPA and GABA conductances tau_rise = task_info['sen']['synapse']['tau_rise'] # rise constants of AMPA and GABA conductances # namespace with params paramsen = {'gEE': gEE, 'gEI': gEI, 'gIE': gIE, 'gII': gII, 'gmax': gmax, 'gXE': gXE, 'gXI': gXI, 'gleakE': gleakE, 'gleakI': gleakI, 'CmE': CmE, 'CmI': CmI, 'Vl': Vl, 'Vt': Vt, 'Vr': Vr, 'VrevE': VrevE, 'VrevI': VrevI, 'tau_decay': tau_decay, 'tau_rise': tau_rise, 'w_p': w_p, 'w_m': w_m, 'sub': sub, 'eps': eps, 'epsX': epsX, 'alphaX': alphaX} # numerical integration method nummethod = task_info['simulation']['nummethod'] # ------------------------------------- # Set up the model and connections # ------------------------------------- # neuron equations eqsE = ''' dV/dt = (-g_ea*(V-VrevE) - g_i*(V-VrevI) - (V-Vl)) / tau + I/Cm : volt (unless refractory) dg_ea/dt = (-g_ea + x_ea) / tau_decay : 1 dx_ea/dt = -x_ea / tau_rise : 1 dg_i/dt = (-g_i + x_i) / tau_decay : 1 dx_i/dt = -x_i / tau_rise : 1 tau = CmE/gleakE : second Cm = CmE : farad I = Irec(t, i) : amp ''' eqsI = ''' dV/dt = (-g_ea*(V-VrevE) - g_i*(V-VrevI) - (V-Vl)) / tau + I/Cm : volt (unless refractory) dg_ea/dt = (-g_ea + x_ea) / tau_decay : 1 dx_ea/dt = -x_ea / tau_rise : 1 dg_i/dt = (-g_i + x_i) / tau_decay : 1 dx_i/dt = -x_i / tau_rise : 1 tau = CmI/gleakI : second Cm = CmI : farad I : amp ''' # neuron groups senE = NeuronGroup(N_E, model=eqsE, method=nummethod, threshold='V>=Vt', reset='V=Vr', refractory=tau_refE, namespace=paramsen, name='senE') senE1 = senE[:N_E1] senE2 = senE[N_E1:] senI = NeuronGroup(N_I, model=eqsI, method=nummethod, threshold='V>=Vt', reset='V=Vr', refractory=tau_refI, namespace=paramsen, name='senI') # synapses # weight according the different subgroups condsame = '(i<N_pre*sub and j<N_post*sub) or (i>=N_pre*sub and j>=N_post*sub)' conddiff = '(i<N_pre*sub and j>=N_post*sub) or (i>=N_pre*sub and j<N_post*sub)' # AMPA: exc --> exc synSESE = Synapses(senE, senE, model='w : 1', method=nummethod, on_pre='''x_ea += w w = clip(w, 0, gmax)''', namespace=paramsen, name='synSESE') synSESE.connect(p='eps') synSESE.w[condsame] = 'w_p * gEE/gleakE * (1 + randn()*0.5)' synSESE.w[conddiff] = 'w_m * gEE/gleakE * (1 + randn()*0.5)' synSESE.delay = dE # AMPA: exc --> inh synSESI = Synapses(senE, senI, model='w : 1', method=nummethod, on_pre='''x_ea += w w = clip(w, 0, gmax)''', namespace=paramsen, name='synSESI') synSESI.connect(p='eps') synSESI.w = 'gEI/gleakI * (1 + randn()*0.5)' synSESI.delay = dE # GABA: inh --> exc synSISE = Synapses(senI, senE, model='w : 1', method=nummethod, on_pre='''x_i += w w = clip(w, 0, gmax)''', namespace=paramsen, name='synSISE') synSISE.connect(p='eps') synSISE.w = 'gIE/gleakE * (1 + randn()*0.5)' synSISE.delay = dI # GABA: inh --> inh synSISI = Synapses(senI, senI, model='w : 1', method=nummethod, on_pre='''x_i += w w = clip(w, 0, gmax)''', namespace=paramsen, name='synSISI') synSISI.connect(p='eps') synSISI.w = 'gII/gleakI * (1 + randn()*0.5)' synSISI.delay = dI # external inputs and synapses extS = PoissonGroup(N_X, rates=nu_ext) synSXSE = Synapses(extS, senE, model='w : 1', method=nummethod, on_pre='''x_ea += w w = clip(w, 0, gmax)''', namespace=paramsen, name='synSXSE') synSXSE.connect(condition=condsame, p='epsX * (1 + alphaX)') synSXSE.connect(condition=conddiff, p='epsX * (1 - alphaX)') synSXSE.w = 'gXE/gleakE * (1 + randn()*0.5)' synSXSE.delay = dX synSXSI = Synapses(extS, senI, model='w : 1', method=nummethod, on_pre='''x_ea += w w = clip(w, 0, gmax)''', namespace=paramsen, name='synSXSI') synSXSI.connect(p='epsX') synSXSI.w = 'gXI/gleakI * (1 + randn()*0.5)' synSXSI.delay = dX # variables to return groups = {'SE': senE, 'SI': senI, 'SX': extS} subgroups = {'SE1': senE1, 'SE2': senE2} synapses = {'synSESE': synSESE, 'synSESI': synSESI, 'synSISE': synSISE, 'synSISI': synSISI, 'synSXSI': synSXSI, 'synSXSE': synSXSE} return groups, synapses, subgroups
def sim_decision_making_network_full( N_Excit=400, N_Inhib=100, weight_scaling_factor=5.33, t_stimulus_start=100 * b2.ms, t_stimulus_duration=9999 * b2.ms, coherence_level=0.0, stimulus_update_interval=30 * b2.ms, mu0_mean_stimulus_Hz=40., stimulus_std_Hz=10., N_extern=1000, firing_rate_extern=9.8 * b2.Hz, w_pos=2.4, f_Subpop_size=0.25, # .15 in publication [1] max_sim_time=2000. * b2.ms, stop_condition_rate=20 * b2.Hz, monitored_subset_size=512, ): # print('Simulation starts') startting_time = time.time() t_stimulus_end = t_stimulus_start + t_stimulus_duration N_Group_A = int( N_Excit * f_Subpop_size ) # size of the excitatory subpopulation sensitive to stimulus A N_Group_B = N_Group_A # size of the excitatory subpopulation sensitive to stimulus B N_Group_Z = N_Excit - N_Group_A - N_Group_B # (1-2f)Ne excitatory neurons do not respond to either stimulus. Cm_excit = 0.5 * b2.nF # membrane capacitance of excitatory neurons G_leak_excit = 25.0 * b2.nS # leak conductance E_leak_excit = -70.0 * b2.mV # reversal potential v_spike_thr_excit = -50.0 * b2.mV # spike condition v_reset_excit = -55.0 * b2.mV # reset voltage after spike t_abs_refract_excit = 2.0 * b2.ms # absolute refractory period # specify the inhibitory interneurons: # N_Inhib = 200 Cm_inhib = 0.2 * b2.nF G_leak_inhib = 20.0 * b2.nS E_leak_inhib = -70.0 * b2.mV v_spike_thr_inhib = -50.0 * b2.mV v_reset_inhib = -55.0 * b2.mV t_abs_refract_inhib = 1.0 * b2.ms # specify the AMPA synapses E_AMPA = 0.0 * b2.mV tau_AMPA = 2.0 * b2.ms # specify the GABA synapses E_GABA = -70.0 * b2.mV tau_GABA = 2.0 * b2.ms # specify the NMDA synapses # projections from the external population g_AMPA_extern2inhib = 1.62 * b2.nS g_AMPA_extern2excit = 2.1 * b2.nS # projectsions from the inhibitory populations g_GABA_inhib2inhib = weight_scaling_factor * 1.25 * b2.nS g_GABA_inhib2excit = weight_scaling_factor * 1.60 * b2.nS # projections from the excitatory population g_AMPA_excit2excit = 2.1 * weight_scaling_factor * 0.012 * b2.nS g_AMPA_excit2inhib = 0.14 * weight_scaling_factor * 0.015 * b2.nS # weights and "adjusted" weights. w_neg = 1. - f_Subpop_size * (w_pos - 1.) / (1. - f_Subpop_size) w_ext2inhib = g_AMPA_extern2inhib / g_AMPA_excit2inhib w_ext2excit = g_AMPA_extern2excit / g_AMPA_excit2excit # other weights are 1 # Define the inhibitory population # dynamics: inhib_lif_dynamics = """ dv/dt = ( - G_leak_inhib * (v-E_leak_inhib) - g_AMPA_excit2inhib * s_AMPA * (v-E_AMPA) - g_GABA_inhib2inhib * s_GABA * (v-E_GABA) )/Cm_inhib : volt (unless refractory) ds_AMPA/dt = -s_AMPA/tau_AMPA : 1 ds_GABA/dt = -s_GABA/tau_GABA : 1 """ inhib_pop = NeuronGroup(N_Inhib, model=inhib_lif_dynamics, threshold="v>v_spike_thr_inhib", reset="v=v_reset_inhib", refractory=t_abs_refract_inhib, method="rk2") # initialize with random voltages: inhib_pop.v = rnd.uniform(v_spike_thr_inhib / b2.mV - 4., high=v_spike_thr_inhib / b2.mV - 1., size=N_Inhib) * b2.mV # Specify the excitatory population: # dynamics: excit_lif_dynamics = """ dv/dt = ( - G_leak_excit * (v-E_leak_excit) - g_AMPA_excit2excit * s_AMPA * (v-E_AMPA) - g_GABA_inhib2excit * s_GABA * (v-E_GABA) )/Cm_excit : volt (unless refractory) ds_AMPA/dt = -s_AMPA/tau_AMPA : 1 ds_GABA/dt = -s_GABA/tau_GABA : 1 """ # define the three excitatory subpopulations. # A: subpop receiving stimulus A excit_pop_A = NeuronGroup(N_Group_A, model=excit_lif_dynamics, threshold="v > v_spike_thr_excit", reset="v = v_reset_excit", refractory=t_abs_refract_excit, method="rk2") excit_pop_A.v = rnd.uniform(E_leak_excit / b2.mV, high=E_leak_excit / b2.mV + 5., size=excit_pop_A.N) * b2.mV # B: subpop receiving stimulus B excit_pop_B = NeuronGroup(N_Group_B, model=excit_lif_dynamics, threshold="v > v_spike_thr_excit", reset="v = v_reset_excit", refractory=t_abs_refract_excit, method="rk2") excit_pop_B.v = rnd.uniform(E_leak_excit / b2.mV, high=E_leak_excit / b2.mV + 5., size=excit_pop_B.N) * b2.mV # Z: non-sensitive excit_pop_Z = NeuronGroup(N_Group_Z, model=excit_lif_dynamics, threshold="v>v_spike_thr_excit", reset="v=v_reset_excit", refractory=t_abs_refract_excit, method="rk2") excit_pop_Z.v = rnd.uniform(v_reset_excit / b2.mV, high=v_spike_thr_excit / b2.mV - 1., size=excit_pop_Z.N) * b2.mV # now define the connections: # projections FROM EXTERNAL POISSON GROUP: #################################################### poisson2Inhib = PoissonInput(target=inhib_pop, target_var="s_AMPA", N=N_extern, rate=firing_rate_extern, weight=w_ext2inhib) poisson2A = PoissonInput(target=excit_pop_A, target_var="s_AMPA", N=N_extern, rate=firing_rate_extern, weight=w_ext2excit) poisson2B = PoissonInput(target=excit_pop_B, target_var="s_AMPA", N=N_extern, rate=firing_rate_extern, weight=w_ext2excit) poisson2Z = PoissonInput(target=excit_pop_Z, target_var="s_AMPA", N=N_extern, rate=firing_rate_extern, weight=w_ext2excit) ############################################################################################### # GABA projections FROM INHIBITORY population: ################################################ syn_inhib2inhib = Synapses(inhib_pop, target=inhib_pop, on_pre="s_GABA += 1.0", delay=0.5 * b2.ms) syn_inhib2inhib.connect(p=1.) syn_inhib2A = Synapses(inhib_pop, target=excit_pop_A, on_pre="s_GABA += 1.0", delay=0.5 * b2.ms) syn_inhib2A.connect(p=1.) syn_inhib2B = Synapses(inhib_pop, target=excit_pop_B, on_pre="s_GABA += 1.0", delay=0.5 * b2.ms) syn_inhib2B.connect(p=1.) syn_inhib2Z = Synapses(inhib_pop, target=excit_pop_Z, on_pre="s_GABA += 1.0", delay=0.5 * b2.ms) syn_inhib2Z.connect(p=1.) ############################################################################################### # AMPA projections FROM EXCITATORY A: ######################################################### syn_AMPA_A2A = Synapses(excit_pop_A, target=excit_pop_A, on_pre="s_AMPA += w_pos", delay=0.5 * b2.ms) syn_AMPA_A2A.connect(p=1.) syn_AMPA_A2B = Synapses(excit_pop_A, target=excit_pop_B, on_pre="s_AMPA += w_neg", delay=0.5 * b2.ms) syn_AMPA_A2B.connect(p=1.) syn_AMPA_A2Z = Synapses(excit_pop_A, target=excit_pop_Z, on_pre="s_AMPA += w_neg", delay=0.5 * b2.ms) syn_AMPA_A2Z.connect(p=1.) syn_AMPA_A2inhib = Synapses(excit_pop_A, target=inhib_pop, on_pre="s_AMPA += 1.0", delay=0.5 * b2.ms) syn_AMPA_A2inhib.connect(p=1.) ############################################################################################### # AMPA projections FROM EXCITATORY B: ######################################################### syn_AMPA_B2A = Synapses(excit_pop_B, target=excit_pop_A, on_pre="s_AMPA += w_neg", delay=0.5 * b2.ms) syn_AMPA_B2A.connect(p=1.) syn_AMPA_B2B = Synapses(excit_pop_B, target=excit_pop_B, on_pre="s_AMPA += w_pos", delay=0.5 * b2.ms) syn_AMPA_B2B.connect(p=1.) syn_AMPA_B2Z = Synapses(excit_pop_B, target=excit_pop_Z, on_pre="s_AMPA += w_neg", delay=0.5 * b2.ms) syn_AMPA_B2Z.connect(p=1.) syn_AMPA_B2inhib = Synapses(excit_pop_B, target=inhib_pop, on_pre="s_AMPA += 1.0", delay=0.5 * b2.ms) syn_AMPA_B2inhib.connect(p=1.) ############################################################################################### # AMPA projections FROM EXCITATORY Z: ######################################################### syn_AMPA_Z2A = Synapses(excit_pop_Z, target=excit_pop_A, on_pre="s_AMPA += w_neg", delay=0.5 * b2.ms) syn_AMPA_Z2A.connect(p=1.) syn_AMPA_Z2B = Synapses(excit_pop_Z, target=excit_pop_B, on_pre="s_AMPA += w_neg", delay=0.5 * b2.ms) syn_AMPA_Z2B.connect(p=1.) syn_AMPA_Z2Z = Synapses(excit_pop_Z, target=excit_pop_Z, on_pre="s_AMPA += 1.0", delay=0.5 * b2.ms) syn_AMPA_Z2Z.connect(p=1.) syn_AMPA_Z2inhib = Synapses(excit_pop_Z, target=inhib_pop, on_pre="s_AMPA += 1.0", delay=0.5 * b2.ms) syn_AMPA_Z2inhib.connect(p=1.) ############################################################################################### # Define the stimulus: two PoissonInput with time time-dependent mean. poissonStimulus2A = PoissonGroup(N_Group_A, 0. * b2.Hz) syn_Stim2A = Synapses(poissonStimulus2A, excit_pop_A, on_pre="s_AMPA+=w_ext2excit") syn_Stim2A.connect(j="i") poissonStimulus2B = PoissonGroup(N_Group_B, 0. * b2.Hz) syn_Stim2B = Synapses(poissonStimulus2B, excit_pop_B, on_pre="s_AMPA+=w_ext2excit") syn_Stim2B.connect(j="i") @network_operation(dt=stimulus_update_interval) def update_poisson_stimulus(t): if t >= t_stimulus_start and t < t_stimulus_end: offset_A = mu0_mean_stimulus_Hz * (1 + 0.01 * coherence_level) offset_B = mu0_mean_stimulus_Hz * (1 - 0.01 * coherence_level) rate_A = numpy.random.normal(offset_A, stimulus_std_Hz) rate_A = (max(0, rate_A)) * b2.Hz # avoid negative rate rate_B = numpy.random.normal(offset_B, stimulus_std_Hz) rate_B = (max(0, rate_B)) * b2.Hz poissonStimulus2A.rates = rate_A poissonStimulus2B.rates = rate_B else: poissonStimulus2A.rates = 0. poissonStimulus2B.rates = 0. ############################################################################################### def get_monitors(pop, monitored_subset_size): monitored_subset_size = min(monitored_subset_size, pop.N) idx_monitored_neurons = sample(range(pop.N), monitored_subset_size) rate_monitor = PopulationRateMonitor(pop) spike_monitor = SpikeMonitor(pop, record=idx_monitored_neurons) voltage_monitor = StateMonitor(pop, "v", record=idx_monitored_neurons) return rate_monitor, spike_monitor, voltage_monitor, idx_monitored_neurons # collect data of a subset of neurons: rate_monitor_inhib, spike_monitor_inhib, voltage_monitor_inhib, idx_monitored_neurons_inhib = \ get_monitors(inhib_pop, monitored_subset_size) rate_monitor_A, spike_monitor_A, voltage_monitor_A, idx_monitored_neurons_A = \ get_monitors(excit_pop_A, monitored_subset_size) rate_monitor_B, spike_monitor_B, voltage_monitor_B, idx_monitored_neurons_B = \ get_monitors(excit_pop_B, monitored_subset_size) rate_monitor_Z, spike_monitor_Z, voltage_monitor_Z, idx_monitored_neurons_Z = \ get_monitors(excit_pop_Z, monitored_subset_size) if stop_condition_rate is None: b2.run(max_sim_time) else: sim_sum = 0. * b2.ms sim_batch = 25. * b2.ms samples_in_batch = int(floor(sim_batch / b2.defaultclock.dt)) avg_rate_in_batch = 0 while (sim_sum < max_sim_time) and (avg_rate_in_batch < stop_condition_rate): b2.run(sim_batch) avg_A = numpy.mean(rate_monitor_A.rate[-samples_in_batch:]) avg_B = numpy.mean(rate_monitor_B.rate[-samples_in_batch:]) avg_rate_in_batch = max(avg_A, avg_B) sim_sum += sim_batch print("Time elapsed =", time.time() - startting_time, 'seconds') ret_vals = dict() ret_vals["rate_monitor_A"] = rate_monitor_A ret_vals["spike_monitor_A"] = spike_monitor_A ret_vals["voltage_monitor_A"] = voltage_monitor_A ret_vals["idx_monitored_neurons_A"] = idx_monitored_neurons_A ret_vals["rate_monitor_B"] = rate_monitor_B ret_vals["spike_monitor_B"] = spike_monitor_B ret_vals["voltage_monitor_B"] = voltage_monitor_B ret_vals["idx_monitored_neurons_B"] = idx_monitored_neurons_B ret_vals["rate_monitor_Z"] = rate_monitor_Z ret_vals["spike_monitor_Z"] = spike_monitor_Z ret_vals["voltage_monitor_Z"] = voltage_monitor_Z ret_vals["idx_monitored_neurons_Z"] = idx_monitored_neurons_Z ret_vals["rate_monitor_inhib"] = rate_monitor_inhib ret_vals["spike_monitor_inhib"] = spike_monitor_inhib ret_vals["voltage_monitor_inhib"] = voltage_monitor_inhib ret_vals["idx_monitored_neurons_inhib"] = idx_monitored_neurons_inhib return ret_vals
def mk_sencircuit_2c(task_info): """ Creates balanced network representing sensory circuit with 2c model in the excitatory neurons. returns: groups, synapses, subgroups groups and synapses have to be added to the "Network" in order to run the simulation subgroups is used for establishing connections between the sensory and integration circuit; do not add subgroups to the "Network" psr following the published Brian1 code in DB model from Wimmer et al. 2015 - brain2 code - two-compartmental model following Naud & Sprekeler 2018 - implementation runs in cpp_standalone mode, compatible with SNEP """ # ------------------------------------- # Sensory circuit parameters # ------------------------------------- # populations N_E = task_info['sen']['populations']['N_E'] # total number of E neurons sub = task_info['sen']['populations']['sub'] # fraction corresponding to subpops 1,2 N_E1 = int(N_E * sub) # size of exc subpops that responds to the stimuli N_I = task_info['sen']['populations']['N_I'] # total number of I neurons N_X = task_info['sen']['populations']['N_X'] # size of external pop # local recurrent connections eps = task_info['sen']['connectivity']['eps'] # connection probability for EE, EI, IE and II w_p = task_info['sen']['connectivity']['w_p'] # relative synaptic strength within pop E1 and E2 w_m = 2 - w_p # relative synaptic strength across pop E1 and E2 gEEs = task_info['sen']['2c']['gEEs'] # weight of EE synapses, prev: 0.7589*nS gEI = task_info['sen']['connectivity']['gEI'] # weight of EI synapses, prev: 1.5179*nS gIEs = task_info['sen']['2c']['gIEs'] # weight of IE synapses, prev: 12.6491*nS gII = task_info['sen']['connectivity']['gII'] # weight of II synapses gmax = task_info['sen']['connectivity']['gmax'] # maximum synaptic weight dE = '0.5*ms + rand()*1.0*ms' # range of transmission delays of E synapses, (0.5:1.5) dI = '0.1*ms + rand()*0.8*ms' # range of transmission delays of I synapses, (0.1:0.9) # external connections epsX = task_info['sen']['connectivity']['epsX'] # connection probability for ext synapses alphaX = task_info['sen']['connectivity']['alphaX'] # 0: global input, 1: local input gXEs = task_info['sen']['2c']['gXEs'] # weight of ext to E synapses of soma gXI = task_info['sen']['connectivity']['gXI'] # weight of ext to I synapses dX = '0.5*ms + rand()*1.0*ms' # range of transmission delays of X synapses, (0.5:1.5) # neuron model CmI = task_info['sen']['neuron']['CmI'] # membrane capacitance of I neurons gleakI = task_info['sen']['neuron']['gleakI'] # leak conductance of I neurons Vl = task_info['sen']['neuron']['Vl'] # reversal potential Vt = task_info['sen']['neuron']['Vt'] # threshold potential Vr = task_info['sen']['neuron']['Vr'] # reset potential, only for inh tau_refI = task_info['sen']['neuron']['tau_refI'] # absolute refractory period of I neurons nu_ext = task_info['sen']['neuron']['nu_ext'] # rate of external Poisson neurons, prev: 12.5*Hz # soma taus = task_info['sen']['2c']['taus'] # timescale of membrane potential Cms = task_info['sen']['2c']['Cms'] # capacitance gleakEs = Cms/taus tauws = task_info['sen']['2c']['tauws'] # timescale of recovery ("slow") variable bws = task_info['sen']['2c']['bws'] # strength of spike-triggered facilitation (bws < 0) gCas = task_info['sen']['2c']['gCas'] # strenght of forward calcium spike propagation tau_refE = task_info['sen']['2c']['tau_refE'] # refractory period # dendrite taud = task_info['sen']['2c']['taud'] Cmd = task_info['sen']['2c']['Cmd'] gleakEd = Cmd/taud tauwd = task_info['sen']['2c']['tauwd'] # timescale of recovery ("slow") variable awd = task_info['sen']['2c']['awd'] # stregth of subthreshold facilitations (awd < 0) gCad = task_info['sen']['2c']['gCad'] # strength of local regenerative activity bpA = task_info['sen']['2c']['bpA'] # strength of backpropagation activity (c variable) k1 = task_info['sen']['2c']['k1'] # rectangular kernel for backpropagating activity k2 = task_info['sen']['2c']['k2'] # if t in [0.5, 2.0] we'll have backpropagating current muOUd = task_info['sen']['2c']['muOUd'] # OU parameters for background noise of dendrites sigmaOU = task_info['sen']['2c']['sigmaOU'] tauOU = task_info['sen']['2c']['tauOU'] # synapse models VrevE = task_info['sen']['synapse']['VrevE'] # reversal potential for E synapses VrevI = task_info['sen']['synapse']['VrevI'] # reversal potential for I synapses in inh tau_decay = task_info['sen']['synapse']['tau_decay'] # decay constant of AMPA, GABA tau_rise = task_info['sen']['synapse']['tau_rise'] # rise constant of AMPA, GABA for inh VrevIsd = task_info['sen']['synapse']['VrevIsd'] # rev potential for I synapses in soma, dend #tau_decayE = task_info['sen']['synapse']['tau_decaysd'] # rise constants of AMPA conductances # in Wimmer are decayE = decayI = 5, Naud decayE = 1, decayI = 5 ! # TODO: try both approaches and decide which one to use. param2c = {'gEE': gEEs, 'gEI': gEI, 'gIE': gIEs, 'gII': gII, 'gmax': gmax, 'gXEs': gXEs, 'gXI': gXI, 'gleakEs': gleakEs, 'gleakEd': gleakEd, 'gleakI': gleakI, 'Cms': Cms, 'Cmd': Cmd, 'CmI': CmI, 'Vl': Vl, 'Vt': Vt, 'Vr': Vr, 'VrevE': VrevE, 'VrevIsd': VrevIsd, 'VrevI': VrevI, 'taus': taus, 'taud': taud, 'tau_refE': tau_refE, 'tau_refI': tau_refI, 'tau_decay': tau_decay, 'tau_rise': tau_rise, 'tau_ws': tauws, 'tau_wd': tauwd, 'bws': bws, 'awd': awd, 'gCas': gCas, 'gCad': gCad, 'bpA': bpA, 'k1': k1, 'k2': k2, 'muOUd': muOUd, 'tauOU': tauOU, 'sigmaOU': sigmaOU, 'w_p': w_p, 'w_m': w_m, 'sub': sub, 'eps': eps, 'epsX': epsX, 'alphaX': alphaX} # numerical integration method nummethod = task_info['simulation']['nummethod'] # ------------------------------------- # Set up model and connections # ------------------------------------- # neuron equations eqss = ''' dV/dt = (-g_ea*(V-VrevE) -g_i*(V-VrevIsd) -(V-Vl))/tau + (gCas/(1+exp(-(V_d/mV + 38)/6)) + w_s + I)/Cm : volt (unless refractory) dg_ea/dt = (-g_ea + x_ea) / tau_decay : 1 dx_ea/dt = -x_ea / tau_rise : 1 dg_i/dt = (-g_i + x_i) / tau_decay : 1 dx_i/dt = -x_i / tau_rise : 1 dw_s/dt = -w_s / tau_ws : amp tau = taus : second Cm = Cms : farad I = Irec(t, i) : amp V_d : volt (linked) ''' eqsd = ''' dV_d/dt = (-g_ea*(V_d-VrevE) -(V_d-Vl))/tau + (gCad/(1+exp(-(V_d/mV + 38)/6)) + w_d + K + Ibg)/Cm : volt dg_ea/dt = (-g_ea + x_ea) / tau_decay : 1 dx_ea/dt = -x_ea / tau_rise : 1 dw_d/dt = (-w_d + awd*(V_d - Vl))/tau_wd : amp dIbg/dt = (muOUd - Ibg) / tauOU + (sigmaOU * xi) / sqrt(tauOU / 2) : amp K = bpA * (((t-lastspike_soma) >= k1) * ((t-lastspike_soma) <= k2)) : amp tau = taud : second Cm = Cmd : farad muOUd : amp lastspike_soma : second (linked) ''' eqsI = ''' dV/dt = (-g_ea*(V-VrevE) -g_i*(V-VrevI) -(V-Vl))/tau + I/Cm : volt (unless refractory) dg_ea/dt = (-g_ea + x_ea) / tau_decay : 1 dx_ea/dt = -x_ea / tau_rise : 1 dg_i/dt = (-g_i + x_i) / tau_decay : 1 dx_i/dt = -x_i / tau_rise : 1 tau = CmI/gleakI : second Cm = CmI : farad I : amp ''' # neuron groups soma = NeuronGroup(N_E, model=eqss, method=nummethod, threshold='V>=Vt', reset='''V = Vl w_s += bws''', refractory=tau_refE, namespace=param2c, name='soma') dend = NeuronGroup(N_E, model=eqsd, method=nummethod, namespace=param2c, name='dend') senI = NeuronGroup(N_I, model=eqsI, method=nummethod, threshold='V>=Vt', reset='V=Vr', refractory=tau_refI, namespace=param2c, name='senI') # linked variables soma.V_d = linked_var(dend, 'V_d') dend.lastspike_soma = linked_var(soma, 'lastspike') # subgroups soma1 = soma[:N_E1] dend1 = dend[:N_E1] soma2 = soma[N_E1:] dend2 = dend[N_E1:] # synapses # weight according the different subgroups condsame = '(i<N_pre*sub and j<N_post*sub) or (i>=N_pre*sub and j>=N_post*sub)' conddiff = '(i<N_pre*sub and j>=N_post*sub) or (i>=N_pre*sub and j<N_post*sub)' # AMPA: exc --> exc synSESE = Synapses(soma, soma, model='w : 1', method=nummethod, on_pre='''x_ea += w w = clip(w, 0, gmax)''', namespace=param2c, name='synSESE') synSESE.connect(p='eps') synSESE.w[condsame] = 'w_p * gEE/gleakEs * (1 + randn()*0.5)' synSESE.w[conddiff] = 'w_m * gEE/gleakEs * (1 + randn()*0.5)' synSESE.delay = dE # AMPA: exc --> inh synSESI = Synapses(soma, senI, model='w : 1', method=nummethod, on_pre='''x_ea += w w = clip(w, 0, gmax)''', namespace=param2c, name='synSESI') synSESI.connect(p='eps') synSESI.w = 'gEI/gleakI * (1 + randn()*0.5)' synSESI.delay = dE # GABA: inh --> exc synSISE = Synapses(senI, soma, model='w : 1', method=nummethod, on_pre='''x_i += w w = clip(w, 0, gmax)''', namespace=param2c, name='synSISE') synSISE.connect(p='eps') synSISE.w = 'gIE/gleakEs * (1 + randn()*0.5)' synSISE.delay = dI # GABA: inh --> inh synSISI = Synapses(senI, senI, model='w : 1', method=nummethod, on_pre='''x_i += w w = clip(w, 0, gmax)''', namespace=param2c, name='synSISI') synSISI.connect(p='eps') synSISI.w = 'gII/gleakI * (1 + randn()*0.5)' synSISI.delay = dI # external inputs and synapses extS = PoissonGroup(N_X, rates=nu_ext) synSXSEs = Synapses(extS, soma, model='w : 1', method=nummethod, on_pre='''x_ea += w w = clip(w, 0, gmax)''', namespace=param2c, name='synSXSEs') synSXSEs.connect(condition=condsame, p='epsX * (1 + alphaX)') synSXSEs.connect(condition=conddiff, p='epsX * (1 - alphaX)') synSXSEs.w = 'gXEs/gleakEs * (1 + randn()*0.5)' synSXSEs.delay = dX synSXSI = Synapses(extS, senI, model='w : 1', method=nummethod, on_pre='''x_ea += w w = clip(w, 0, gmax)''', namespace=param2c, name='synSXSI') synSXSI.connect(p='epsX') synSXSI.w = 'gXI/gleakI * (1 + randn()*0.5)' synSXSI.delay = dX # variables to return groups = {'soma': soma, 'dend': dend, 'SI': senI, 'SX': extS} subgroups = {'soma1': soma1, 'soma2': soma2, 'dend1': dend1, 'dend2': dend2} synapses = {'synSESE': synSESE, 'synSESI': synSESI, 'synSISE': synSISE, 'synSISI': synSISI, 'synSXSI': synSXSI, 'synSXSEs': synSXSEs} return groups, synapses, subgroups
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()
def run_net(tr): # prefs.codegen.target = 'numpy' # prefs.codegen.target = 'cython' if tr.n_threads > 1: prefs.devices.cpp_standalone.openmp_threads = tr.n_threads set_device('cpp_standalone', directory='./builds/%.4d' % (tr.v_idx), build_on_run=False) # set brian 2 and numpy random seeds seed(tr.random_seed) np.random.seed(tr.random_seed + 11) print("Started process with id ", str(tr.v_idx)) T = tr.T1 + tr.T2 + tr.T3 + tr.T4 + tr.T5 namespace = tr.netw.f_to_dict(short_names=True, fast_access=True) namespace['idx'] = tr.v_idx defaultclock.dt = tr.netw.sim.dt # collect all network components dependent on configuration # (e.g. poisson vs. memnoise) and add them to the Brian 2 # network object later netw_objects = [] if tr.external_mode == 'memnoise': neuron_model = tr.condlif_memnoise elif tr.external_mode == 'poisson': raise NotImplementedError #neuron_model = tr.condlif_poisson if tr.syn_cond_mode == 'exp': neuron_model += tr.syn_cond_EE_exp print("Using EE exp mode") elif tr.syn_cond_mode == 'alpha': neuron_model += tr.syn_cond_EE_alpha print("Using EE alpha mode") elif tr.syn_cond_mode == 'biexp': neuron_model += tr.syn_cond_EE_biexp namespace['invpeakEE'] = (tr.tau_e / tr.tau_e_rise) ** \ (tr.tau_e_rise / (tr.tau_e - tr.tau_e_rise)) print("Using EE biexp mode") if tr.syn_cond_mode_EI == 'exp': neuron_model += tr.syn_cond_EI_exp print("Using EI exp mode") elif tr.syn_cond_mode_EI == 'alpha': neuron_model += tr.syn_cond_EI_alpha print("Using EI alpha mode") elif tr.syn_cond_mode_EI == 'biexp': neuron_model += tr.syn_cond_EI_biexp namespace['invpeakEI'] = (tr.tau_i / tr.tau_i_rise) ** \ (tr.tau_i_rise / (tr.tau_i - tr.tau_i_rise)) print("Using EI biexp mode") GExc = NeuronGroup( N=tr.N_e, model=neuron_model, threshold=tr.nrnEE_thrshld, reset=tr.nrnEE_reset, #method=tr.neuron_method, name='GExc', namespace=namespace) GInh = NeuronGroup( N=tr.N_i, model=neuron_model, threshold='V > Vt', reset='V=Vr_i', #method=tr.neuron_method, name='GInh', namespace=namespace) if tr.external_mode == 'memnoise': # GExc.mu, GInh.mu = [0.*mV] + (tr.N_e-1)*[tr.mu_e], tr.mu_i # GExc.sigma, GInh.sigma = [0.*mV] + (tr.N_e-1)*[tr.sigma_e], tr.sigma_i GExc.mu, GInh.mu = tr.mu_e, tr.mu_i GExc.sigma, GInh.sigma = tr.sigma_e, tr.sigma_i GExc.Vt, GInh.Vt = tr.Vt_e, tr.Vt_i GExc.V , GInh.V = np.random.uniform(tr.Vr_e/mV, tr.Vt_e/mV, size=tr.N_e)*mV, \ np.random.uniform(tr.Vr_i/mV, tr.Vt_i/mV, size=tr.N_i)*mV netw_objects.extend([GExc, GInh]) if tr.external_mode == 'poisson': if tr.PInp_mode == 'pool': PInp = PoissonGroup(tr.NPInp, rates=tr.PInp_rate, namespace=namespace, name='poissongroup_exc') sPN = Synapses(target=GExc, source=PInp, model=tr.poisson_mod, on_pre='gfwd_post += a_EPoi', namespace=namespace, name='synPInpExc') sPN_src, sPN_tar = generate_N_connections(N_tar=tr.N_e, N_src=tr.NPInp, N=tr.NPInp_1n) elif tr.PInp_mode == 'indep': PInp = PoissonGroup(tr.N_e, rates=tr.PInp_rate, namespace=namespace) sPN = Synapses(target=GExc, source=PInp, model=tr.poisson_mod, on_pre='gfwd_post += a_EPoi', namespace=namespace, name='synPInp_inhInh') sPN_src, sPN_tar = range(tr.N_e), range(tr.N_e) sPN.connect(i=sPN_src, j=sPN_tar) if tr.PInp_mode == 'pool': PInp_inh = PoissonGroup(tr.NPInp_inh, rates=tr.PInp_inh_rate, namespace=namespace, name='poissongroup_inh') sPNInh = Synapses(target=GInh, source=PInp_inh, model=tr.poisson_mod, on_pre='gfwd_post += a_EPoi', namespace=namespace) sPNInh_src, sPNInh_tar = generate_N_connections(N_tar=tr.N_i, N_src=tr.NPInp_inh, N=tr.NPInp_inh_1n) elif tr.PInp_mode == 'indep': PInp_inh = PoissonGroup(tr.N_i, rates=tr.PInp_inh_rate, namespace=namespace) sPNInh = Synapses(target=GInh, source=PInp_inh, model=tr.poisson_mod, on_pre='gfwd_post += a_EPoi', namespace=namespace) sPNInh_src, sPNInh_tar = range(tr.N_i), range(tr.N_i) sPNInh.connect(i=sPNInh_src, j=sPNInh_tar) netw_objects.extend([PInp, sPN, PInp_inh, sPNInh]) if tr.syn_noise: if tr.syn_noise_type == 'additive': synEE_mod = '''%s %s''' % (tr.synEE_noise_add, tr.synEE_mod) synEI_mod = '''%s %s''' % (tr.synEE_noise_add, tr.synEE_mod) elif tr.syn_noise_type == 'multiplicative': synEE_mod = '''%s %s''' % (tr.synEE_noise_mult, tr.synEE_mod) synEI_mod = '''%s %s''' % (tr.synEE_noise_mult, tr.synEE_mod) else: synEE_mod = '''%s %s''' % (tr.synEE_static, tr.synEE_mod) synEI_mod = '''%s %s''' % (tr.synEE_static, tr.synEE_mod) if tr.scl_active: synEE_mod = '''%s %s''' % (synEE_mod, tr.synEE_scl_mod) synEI_mod = '''%s %s''' % (synEI_mod, tr.synEI_scl_mod) if tr.syn_cond_mode == 'exp': synEE_pre_mod = mod.synEE_pre_exp elif tr.syn_cond_mode == 'alpha': synEE_pre_mod = mod.synEE_pre_alpha elif tr.syn_cond_mode == 'biexp': synEE_pre_mod = mod.synEE_pre_biexp synEE_post_mod = mod.syn_post if tr.stdp_active: synEE_pre_mod = '''%s %s''' % (synEE_pre_mod, mod.syn_pre_STDP) synEE_post_mod = '''%s %s''' % (synEE_post_mod, mod.syn_post_STDP) if tr.synEE_rec: synEE_pre_mod = '''%s %s''' % (synEE_pre_mod, mod.synEE_pre_rec) synEE_post_mod = '''%s %s''' % (synEE_post_mod, mod.synEE_post_rec) # E<-E advanced synapse model SynEE = Synapses(target=GExc, source=GExc, model=synEE_mod, on_pre=synEE_pre_mod, on_post=synEE_post_mod, namespace=namespace, dt=tr.synEE_mod_dt) if tr.istdp_active and tr.istdp_type == 'dbexp': if tr.syn_cond_mode_EI == 'exp': EI_pre_mod = mod.synEI_pre_exp elif tr.syn_cond_mode_EI == 'alpha': EI_pre_mod = mod.synEI_pre_alpha elif tr.syn_cond_mode_EI == 'biexp': EI_pre_mod = mod.synEI_pre_biexp synEI_pre_mod = '''%s %s''' % (EI_pre_mod, mod.syn_pre_STDP) synEI_post_mod = '''%s %s''' % (mod.syn_post, mod.syn_post_STDP) elif tr.istdp_active and tr.istdp_type == 'sym': if tr.syn_cond_mode_EI == 'exp': EI_pre_mod = mod.synEI_pre_sym_exp elif tr.syn_cond_mode_EI == 'alpha': EI_pre_mod = mod.synEI_pre_sym_alpha elif tr.syn_cond_mode_EI == 'biexp': EI_pre_mod = mod.synEI_pre_sym_biexp synEI_pre_mod = '''%s %s''' % (EI_pre_mod, mod.syn_pre_STDP) synEI_post_mod = '''%s %s''' % (mod.synEI_post_sym, mod.syn_post_STDP) if tr.istdp_active and tr.synEI_rec: synEI_pre_mod = '''%s %s''' % (synEI_pre_mod, mod.synEI_pre_rec) synEI_post_mod = '''%s %s''' % (synEI_post_mod, mod.synEI_post_rec) if tr.istdp_active: SynEI = Synapses(target=GExc, source=GInh, model=synEI_mod, on_pre=synEI_pre_mod, on_post=synEI_post_mod, namespace=namespace, dt=tr.synEE_mod_dt) else: model = '''a : 1 syn_active : 1''' SynEI = Synapses(target=GExc, source=GInh, model=model, on_pre='gi_post += a', namespace=namespace) #other simple SynIE = Synapses(target=GInh, source=GExc, on_pre='ge_post += a_ie', namespace=namespace) SynII = Synapses(target=GInh, source=GInh, on_pre='gi_post += a_ii', namespace=namespace) sEE_src, sEE_tar = generate_full_connectivity(tr.N_e, same=True) SynEE.connect(i=sEE_src, j=sEE_tar) SynEE.syn_active = 0 SynEE.taupre, SynEE.taupost = tr.taupre, tr.taupost if tr.istdp_active and tr.istrct_active: print('istrct active') sEI_src, sEI_tar = generate_full_connectivity(Nsrc=tr.N_i, Ntar=tr.N_e, same=False) SynEI.connect(i=sEI_src, j=sEI_tar) SynEI.syn_active = 0 else: print('istrct not active') if tr.weight_mode == 'init': sEI_src, sEI_tar = generate_connections(tr.N_e, tr.N_i, tr.p_ei) # print('Index Zero will not get inhibition') # sEI_src, sEI_tar = np.array(sEI_src), np.array(sEI_tar) # sEI_src, sEI_tar = sEI_src[sEI_tar > 0],sEI_tar[sEI_tar > 0] elif tr.weight_mode == 'load': fpath = os.path.join(tr.basepath, tr.weight_path) with open(fpath + 'synei_a.p', 'rb') as pfile: synei_a_init = pickle.load(pfile) sEI_src, sEI_tar = synei_a_init['i'], synei_a_init['j'] SynEI.connect(i=sEI_src, j=sEI_tar) if tr.istdp_active: SynEI.taupre, SynEI.taupost = tr.taupre_EI, tr.taupost_EI sIE_src, sIE_tar = generate_connections(tr.N_i, tr.N_e, tr.p_ie) sII_src, sII_tar = generate_connections(tr.N_i, tr.N_i, tr.p_ii, same=True) SynIE.connect(i=sIE_src, j=sIE_tar) SynII.connect(i=sII_src, j=sII_tar) tr.f_add_result('sEE_src', sEE_src) tr.f_add_result('sEE_tar', sEE_tar) tr.f_add_result('sIE_src', sIE_src) tr.f_add_result('sIE_tar', sIE_tar) tr.f_add_result('sEI_src', sEI_src) tr.f_add_result('sEI_tar', sEI_tar) tr.f_add_result('sII_src', sII_src) tr.f_add_result('sII_tar', sII_tar) if tr.syn_noise: SynEE.syn_sigma = tr.syn_sigma SynEE.run_regularly('a = clip(a,0,amax)', when='after_groups', name='SynEE_noise_clipper') if tr.syn_noise and tr.istdp_active: SynEI.syn_sigma = tr.syn_sigma SynEI.run_regularly('a = clip(a,0,amax)', when='after_groups', name='SynEI_noise_clipper') SynEE.insert_P = tr.insert_P SynEE.p_inactivate = tr.p_inactivate SynEE.stdp_active = 1 print('Setting maximum EE weight threshold to ', tr.amax) SynEE.amax = tr.amax if tr.istdp_active: SynEI.insert_P = tr.insert_P_ei SynEI.p_inactivate = tr.p_inactivate_ei SynEI.stdp_active = 1 SynEI.amax = tr.amax SynEE.syn_active, SynEE.a = init_synapses('EE', tr) SynEI.syn_active, SynEI.a = init_synapses('EI', tr) # recording of stdp in T4 SynEE.stdp_rec_start = tr.T1 + tr.T2 + tr.T3 SynEE.stdp_rec_max = tr.T1 + tr.T2 + tr.T3 + tr.stdp_rec_T if tr.istdp_active: SynEI.stdp_rec_start = tr.T1 + tr.T2 + tr.T3 SynEI.stdp_rec_max = tr.T1 + tr.T2 + tr.T3 + tr.stdp_rec_T # synaptic scaling if tr.netw.config.scl_active: if tr.syn_scl_rec: SynEE.scl_rec_start = tr.T1 + tr.T2 + tr.T3 SynEE.scl_rec_max = tr.T1 + tr.T2 + tr.T3 + tr.scl_rec_T else: SynEE.scl_rec_start = T + 10 * second SynEE.scl_rec_max = T if tr.sig_ATotalMax == 0.: GExc.ANormTar = tr.ATotalMax else: GExc.ANormTar = np.random.normal(loc=tr.ATotalMax, scale=tr.sig_ATotalMax, size=tr.N_e) SynEE.summed_updaters['AsumEE_post']._clock = Clock( dt=tr.dt_synEE_scaling) synee_scaling = SynEE.run_regularly(tr.synEE_scaling, dt=tr.dt_synEE_scaling, when='end', name='synEE_scaling') if tr.istdp_active and tr.netw.config.iscl_active: if tr.syn_iscl_rec: SynEI.scl_rec_start = tr.T1 + tr.T2 + tr.T3 SynEI.scl_rec_max = tr.T1 + tr.T2 + tr.T3 + tr.scl_rec_T else: SynEI.scl_rec_start = T + 10 * second SynEI.scl_rec_max = T if tr.sig_iATotalMax == 0.: GExc.iANormTar = tr.iATotalMax else: GExc.iANormTar = np.random.normal(loc=tr.iATotalMax, scale=tr.sig_iATotalMax, size=tr.N_e) SynEI.summed_updaters['AsumEI_post']._clock = Clock( dt=tr.dt_synEE_scaling) synei_scaling = SynEI.run_regularly(tr.synEI_scaling, dt=tr.dt_synEE_scaling, when='end', name='synEI_scaling') # # intrinsic plasticity # if tr.netw.config.it_active: # GExc.h_ip = tr.h_ip # GExc.run_regularly(tr.intrinsic_mod, dt = tr.it_dt, when='end') # structural plasticity if tr.netw.config.strct_active: if tr.strct_mode == 'zero': if tr.turnover_rec: strct_mod = '''%s %s''' % (tr.strct_mod, tr.turnover_rec_mod) else: strct_mod = tr.strct_mod strctplst = SynEE.run_regularly(strct_mod, dt=tr.strct_dt, when='end', name='strct_plst_zero') elif tr.strct_mode == 'thrs': if tr.turnover_rec: strct_mod_thrs = '''%s %s''' % (tr.strct_mod_thrs, tr.turnover_rec_mod) else: strct_mod_thrs = tr.strct_mod_thrs strctplst = SynEE.run_regularly(strct_mod_thrs, dt=tr.strct_dt, when='end', name='strct_plst_thrs') if tr.istdp_active and tr.netw.config.istrct_active: if tr.strct_mode == 'zero': if tr.turnover_rec: strct_mod_EI = '''%s %s''' % (tr.strct_mod, tr.turnoverEI_rec_mod) else: strct_mod_EI = tr.strct_mod strctplst_EI = SynEI.run_regularly(strct_mod_EI, dt=tr.strct_dt, when='end', name='strct_plst_EI') elif tr.strct_mode == 'thrs': raise NotImplementedError netw_objects.extend([SynEE, SynEI, SynIE, SynII]) # keep track of the number of active synapses sum_target = NeuronGroup(1, 'c : 1 (shared)', dt=tr.csample_dt) sum_model = '''NSyn : 1 (constant) c_post = (1.0*syn_active_pre)/NSyn : 1 (summed)''' sum_connection = Synapses(target=sum_target, source=SynEE, model=sum_model, dt=tr.csample_dt, name='get_active_synapse_count') sum_connection.connect() sum_connection.NSyn = tr.N_e * (tr.N_e - 1) if tr.adjust_insertP: # homeostatically adjust growth rate growth_updater = Synapses(sum_target, SynEE) growth_updater.run_regularly('insert_P_post *= 0.1/c_pre', when='after_groups', dt=tr.csample_dt, name='update_insP') growth_updater.connect(j='0') netw_objects.extend([sum_target, sum_connection, growth_updater]) if tr.istdp_active and tr.istrct_active: # keep track of the number of active synapses sum_target_EI = NeuronGroup(1, 'c : 1 (shared)', dt=tr.csample_dt) sum_model_EI = '''NSyn : 1 (constant) c_post = (1.0*syn_active_pre)/NSyn : 1 (summed)''' sum_connection_EI = Synapses(target=sum_target_EI, source=SynEI, model=sum_model_EI, dt=tr.csample_dt, name='get_active_synapse_count_EI') sum_connection_EI.connect() sum_connection_EI.NSyn = tr.N_e * tr.N_i if tr.adjust_EI_insertP: # homeostatically adjust growth rate growth_updater_EI = Synapses(sum_target_EI, SynEI) growth_updater_EI.run_regularly('insert_P_post *= 0.1/c_pre', when='after_groups', dt=tr.csample_dt, name='update_insP_EI') growth_updater_EI.connect(j='0') netw_objects.extend( [sum_target_EI, sum_connection_EI, growth_updater_EI]) # -------------- recording ------------------ GExc_recvars = [] if tr.memtraces_rec: GExc_recvars.append('V') if tr.vttraces_rec: GExc_recvars.append('Vt') if tr.getraces_rec: GExc_recvars.append('ge') if tr.gitraces_rec: GExc_recvars.append('gi') if tr.gfwdtraces_rec and tr.external_mode == 'poisson': GExc_recvars.append('gfwd') GInh_recvars = GExc_recvars GExc_stat = StateMonitor(GExc, GExc_recvars, record=list(range(tr.nrec_GExc_stat)), dt=tr.GExc_stat_dt) GInh_stat = StateMonitor(GInh, GInh_recvars, record=list(range(tr.nrec_GInh_stat)), dt=tr.GInh_stat_dt) # SynEE stat SynEE_recvars = [] if tr.synee_atraces_rec: SynEE_recvars.append('a') if tr.synee_activetraces_rec: SynEE_recvars.append('syn_active') if tr.synee_Apretraces_rec: SynEE_recvars.append('Apre') if tr.synee_Aposttraces_rec: SynEE_recvars.append('Apost') SynEE_stat = StateMonitor(SynEE, SynEE_recvars, record=range(tr.n_synee_traces_rec), when='end', dt=tr.synEE_stat_dt) if tr.istdp_active: # SynEI stat SynEI_recvars = [] if tr.synei_atraces_rec: SynEI_recvars.append('a') if tr.synei_activetraces_rec: SynEI_recvars.append('syn_active') if tr.synei_Apretraces_rec: SynEI_recvars.append('Apre') if tr.synei_Aposttraces_rec: SynEI_recvars.append('Apost') SynEI_stat = StateMonitor(SynEI, SynEI_recvars, record=range(tr.n_synei_traces_rec), when='end', dt=tr.synEI_stat_dt) netw_objects.append(SynEI_stat) if tr.adjust_insertP: C_stat = StateMonitor(sum_target, 'c', dt=tr.csample_dt, record=[0], when='end') insP_stat = StateMonitor(SynEE, 'insert_P', dt=tr.csample_dt, record=[0], when='end') netw_objects.extend([C_stat, insP_stat]) if tr.istdp_active and tr.adjust_EI_insertP: C_EI_stat = StateMonitor(sum_target_EI, 'c', dt=tr.csample_dt, record=[0], when='end') insP_EI_stat = StateMonitor(SynEI, 'insert_P', dt=tr.csample_dt, record=[0], when='end') netw_objects.extend([C_EI_stat, insP_EI_stat]) GExc_spks = SpikeMonitor(GExc) GInh_spks = SpikeMonitor(GInh) GExc_rate = PopulationRateMonitor(GExc) GInh_rate = PopulationRateMonitor(GInh) if tr.external_mode == 'poisson': PInp_spks = SpikeMonitor(PInp) PInp_rate = PopulationRateMonitor(PInp) netw_objects.extend([PInp_spks, PInp_rate]) if tr.synee_a_nrecpoints == 0 or tr.sim.T2 == 0 * second: SynEE_a_dt = 2 * (tr.T1 + tr.T2 + tr.T3 + tr.T4 + tr.T5) else: SynEE_a_dt = tr.sim.T2 / tr.synee_a_nrecpoints # make sure that choice of SynEE_a_dt does lead # to execessively many recordings - this can # happen if t1 >> t2. estm_nrecs = int(T / SynEE_a_dt) if estm_nrecs > 3 * tr.synee_a_nrecpoints: print('''Estimated number of EE weight recordings (%d) exceeds desired number (%d), increasing SynEE_a_dt''' % (estm_nrecs, tr.synee_a_nrecpoints)) SynEE_a_dt = T / tr.synee_a_nrecpoints SynEE_a = StateMonitor(SynEE, ['a', 'syn_active'], record=range(tr.N_e * (tr.N_e - 1)), dt=SynEE_a_dt, when='end', order=100) if tr.istrct_active: record_range = range(tr.N_e * tr.N_i) else: record_range = range(len(sEI_src)) if tr.synei_a_nrecpoints > 0 and tr.sim.T2 > 0 * second: SynEI_a_dt = tr.sim.T2 / tr.synei_a_nrecpoints estm_nrecs = int(T / SynEI_a_dt) if estm_nrecs > 3 * tr.synei_a_nrecpoints: print('''Estimated number of EI weight recordings (%d) exceeds desired number (%d), increasing SynEI_a_dt''' % (estm_nrecs, tr.synei_a_nrecpoints)) SynEI_a_dt = T / tr.synei_a_nrecpoints SynEI_a = StateMonitor(SynEI, ['a', 'syn_active'], record=record_range, dt=SynEI_a_dt, when='end', order=100) netw_objects.append(SynEI_a) netw_objects.extend([ GExc_stat, GInh_stat, SynEE_stat, SynEE_a, GExc_spks, GInh_spks, GExc_rate, GInh_rate ]) if (tr.synEEdynrec and (2 * tr.syndynrec_npts * tr.syndynrec_dt < tr.sim.T2)): SynEE_dynrec = StateMonitor(SynEE, ['a'], record=range(tr.N_e * (tr.N_e - 1)), dt=tr.syndynrec_dt, name='SynEE_dynrec', when='end', order=100) SynEE_dynrec.active = False netw_objects.extend([SynEE_dynrec]) if (tr.synEIdynrec and (2 * tr.syndynrec_npts * tr.syndynrec_dt < tr.sim.T2)): SynEI_dynrec = StateMonitor(SynEI, ['a'], record=record_range, dt=tr.syndynrec_dt, name='SynEI_dynrec', when='end', order=100) SynEI_dynrec.active = False netw_objects.extend([SynEI_dynrec]) net = Network(*netw_objects) def set_active(*argv): for net_object in argv: net_object.active = True def set_inactive(*argv): for net_object in argv: net_object.active = False ### Simulation periods # --------- T1 --------- # initial recording period, # all recorders active T1T3_recorders = [ GExc_spks, GInh_spks, SynEE_stat, GExc_stat, GInh_stat, GExc_rate, GInh_rate ] if tr.istdp_active: T1T3_recorders.append(SynEI_stat) set_active(*T1T3_recorders) if tr.external_mode == 'poisson': set_active(PInp_spks, PInp_rate) net.run(tr.sim.T1, report='text', report_period=300 * second, profile=True) # --------- T2 --------- # main simulation period # only active recordings are: # 1) turnover 2) C_stat 3) SynEE_a set_inactive(*T1T3_recorders) if tr.T2_spks_rec: set_active(GExc_spks, GInh_spks) if tr.external_mode == 'poisson': set_inactive(PInp_spks, PInp_rate) run_T2_syndynrec(net, tr, netw_objects) # --------- T3 --------- # second recording period, # all recorders active set_active(*T1T3_recorders) if tr.external_mode == 'poisson': set_active(PInp_spks, PInp_rate) run_T3_split(net, tr) # --------- T4 --------- # record STDP and scaling weight changes to file # through the cpp models set_inactive(*T1T3_recorders) if tr.external_mode == 'poisson': set_inactive(PInp_spks, PInp_rate) run_T4(net, tr) # --------- T5 --------- # freeze network and record Exc spikes # for cross correlations if tr.scl_active: synee_scaling.active = False if tr.istdp_active and tr.netw.config.iscl_active: synei_scaling.active = False if tr.strct_active: strctplst.active = False if tr.istdp_active and tr.istrct_active: strctplst_EI.active = False SynEE.stdp_active = 0 if tr.istdp_active: SynEI.stdp_active = 0 set_active(GExc_rate, GInh_rate) set_active(GExc_spks, GInh_spks) run_T5(net, tr) SynEE_a.record_single_timestep() if tr.synei_a_nrecpoints > 0 and tr.sim.T2 > 0. * second: SynEI_a.record_single_timestep() device.build(directory='builds/%.4d' % (tr.v_idx), clean=True, compile=True, run=True, debug=False) # ----------------------------------------- # save monitors as raws in build directory raw_dir = 'builds/%.4d/raw/' % (tr.v_idx) if not os.path.exists(raw_dir): os.makedirs(raw_dir) with open(raw_dir + 'namespace.p', 'wb') as pfile: pickle.dump(namespace, pfile) with open(raw_dir + 'gexc_stat.p', 'wb') as pfile: pickle.dump(GExc_stat.get_states(), pfile) with open(raw_dir + 'ginh_stat.p', 'wb') as pfile: pickle.dump(GInh_stat.get_states(), pfile) with open(raw_dir + 'synee_stat.p', 'wb') as pfile: pickle.dump(SynEE_stat.get_states(), pfile) if tr.istdp_active: with open(raw_dir + 'synei_stat.p', 'wb') as pfile: pickle.dump(SynEI_stat.get_states(), pfile) if ((tr.synEEdynrec or tr.synEIdynrec) and (2 * tr.syndynrec_npts * tr.syndynrec_dt < tr.sim.T2)): if tr.synEEdynrec: with open(raw_dir + 'syneedynrec.p', 'wb') as pfile: pickle.dump(SynEE_dynrec.get_states(), pfile) if tr.synEIdynrec: with open(raw_dir + 'syneidynrec.p', 'wb') as pfile: pickle.dump(SynEI_dynrec.get_states(), pfile) with open(raw_dir + 'synee_a.p', 'wb') as pfile: SynEE_a_states = SynEE_a.get_states() if tr.crs_crrs_rec: SynEE_a_states['i'] = list(SynEE.i) SynEE_a_states['j'] = list(SynEE.j) pickle.dump(SynEE_a_states, pfile) if tr.synei_a_nrecpoints > 0 and tr.sim.T2 > 0. * second: with open(raw_dir + 'synei_a.p', 'wb') as pfile: SynEI_a_states = SynEI_a.get_states() if tr.crs_crrs_rec: SynEI_a_states['i'] = list(SynEI.i) SynEI_a_states['j'] = list(SynEI.j) pickle.dump(SynEI_a_states, pfile) if tr.adjust_insertP: with open(raw_dir + 'c_stat.p', 'wb') as pfile: pickle.dump(C_stat.get_states(), pfile) with open(raw_dir + 'insP_stat.p', 'wb') as pfile: pickle.dump(insP_stat.get_states(), pfile) if tr.istdp_active and tr.adjust_EI_insertP: with open(raw_dir + 'c_EI_stat.p', 'wb') as pfile: pickle.dump(C_EI_stat.get_states(), pfile) with open(raw_dir + 'insP_EI_stat.p', 'wb') as pfile: pickle.dump(insP_EI_stat.get_states(), pfile) with open(raw_dir + 'gexc_spks.p', 'wb') as pfile: pickle.dump(GExc_spks.get_states(), pfile) with open(raw_dir + 'ginh_spks.p', 'wb') as pfile: pickle.dump(GInh_spks.get_states(), pfile) if tr.external_mode == 'poisson': with open(raw_dir + 'pinp_spks.p', 'wb') as pfile: pickle.dump(PInp_spks.get_states(), pfile) with open(raw_dir + 'gexc_rate.p', 'wb') as pfile: pickle.dump(GExc_rate.get_states(), pfile) if tr.rates_rec: pickle.dump(GExc_rate.smooth_rate(width=25 * ms), pfile) with open(raw_dir + 'ginh_rate.p', 'wb') as pfile: pickle.dump(GInh_rate.get_states(), pfile) if tr.rates_rec: pickle.dump(GInh_rate.smooth_rate(width=25 * ms), pfile) if tr.external_mode == 'poisson': with open(raw_dir + 'pinp_rate.p', 'wb') as pfile: pickle.dump(PInp_rate.get_states(), pfile) if tr.rates_rec: pickle.dump(PInp_rate.smooth_rate(width=25 * ms), pfile) # ----------------- add raw data ------------------------ fpath = 'builds/%.4d/' % (tr.v_idx) from pathlib import Path Path(fpath + 'turnover').touch() turnover_data = np.genfromtxt(fpath + 'turnover', delimiter=',') os.remove(fpath + 'turnover') with open(raw_dir + 'turnover.p', 'wb') as pfile: pickle.dump(turnover_data, pfile) Path(fpath + 'turnover_EI').touch() turnover_EI_data = np.genfromtxt(fpath + 'turnover_EI', delimiter=',') os.remove(fpath + 'turnover_EI') with open(raw_dir + 'turnover_EI.p', 'wb') as pfile: pickle.dump(turnover_EI_data, pfile) Path(fpath + 'spk_register').touch() spk_register_data = np.genfromtxt(fpath + 'spk_register', delimiter=',') os.remove(fpath + 'spk_register') with open(raw_dir + 'spk_register.p', 'wb') as pfile: pickle.dump(spk_register_data, pfile) Path(fpath + 'spk_register_EI').touch() spk_register_EI_data = np.genfromtxt(fpath + 'spk_register_EI', delimiter=',') os.remove(fpath + 'spk_register_EI') with open(raw_dir + 'spk_register_EI.p', 'wb') as pfile: pickle.dump(spk_register_EI_data, pfile) Path(fpath + 'scaling_deltas').touch() scaling_deltas_data = np.genfromtxt(fpath + 'scaling_deltas', delimiter=',') os.remove(fpath + 'scaling_deltas') with open(raw_dir + 'scaling_deltas.p', 'wb') as pfile: pickle.dump(scaling_deltas_data, pfile) Path(fpath + 'scaling_deltas_EI').touch() scaling_deltas_data = np.genfromtxt(fpath + 'scaling_deltas_EI', delimiter=',') os.remove(fpath + 'scaling_deltas_EI') with open(raw_dir + 'scaling_deltas_EI.p', 'wb') as pfile: pickle.dump(scaling_deltas_data, pfile) with open(raw_dir + 'profiling_summary.txt', 'w+') as tfile: tfile.write(str(profiling_summary(net))) # --------------- cross-correlations --------------------- if tr.crs_crrs_rec: GExc_spks = GExc_spks.get_states() synee_a = SynEE_a_states wsize = 100 * pq.ms for binsize in [1 * pq.ms, 2 * pq.ms, 5 * pq.ms]: wlen = int(wsize / binsize) ts, idxs = GExc_spks['t'], GExc_spks['i'] idxs = idxs[ts > tr.T1 + tr.T2 + tr.T3 + tr.T4] ts = ts[ts > tr.T1 + tr.T2 + tr.T3 + tr.T4] ts = ts - (tr.T1 + tr.T2 + tr.T3 + tr.T4) sts = [ neo.SpikeTrain(ts[idxs == i] / second * pq.s, t_stop=tr.T5 / second * pq.s) for i in range(tr.N_e) ] crs_crrs, syn_a = [], [] for f, (i, j) in enumerate(zip(synee_a['i'], synee_a['j'])): if synee_a['syn_active'][-1][f] == 1: crs_crr, cbin = cch(BinnedSpikeTrain(sts[i], binsize=binsize), BinnedSpikeTrain(sts[j], binsize=binsize), cross_corr_coef=True, border_correction=True, window=(-1 * wlen, wlen)) crs_crrs.append(list(np.array(crs_crr).T[0])) syn_a.append(synee_a['a'][-1][f]) fname = 'crs_crrs_wsize%dms_binsize%fms_full' % (wsize / pq.ms, binsize / pq.ms) df = { 'cbin': cbin, 'crs_crrs': np.array(crs_crrs), 'syn_a': np.array(syn_a), 'binsize': binsize, 'wsize': wsize, 'wlen': wlen } with open('builds/%.4d/raw/' % (tr.v_idx) + fname + '.p', 'wb') as pfile: pickle.dump(df, pfile) GInh_spks = GInh_spks.get_states() synei_a = SynEI_a_states wsize = 100 * pq.ms for binsize in [1 * pq.ms, 2 * pq.ms, 5 * pq.ms]: wlen = int(wsize / binsize) ts_E, idxs_E = GExc_spks['t'], GExc_spks['i'] idxs_E = idxs_E[ts_E > tr.T1 + tr.T2 + tr.T3 + tr.T4] ts_E = ts_E[ts_E > tr.T1 + tr.T2 + tr.T3 + tr.T4] ts_E = ts_E - (tr.T1 + tr.T2 + tr.T3 + tr.T4) ts_I, idxs_I = GInh_spks['t'], GInh_spks['i'] idxs_I = idxs_I[ts_I > tr.T1 + tr.T2 + tr.T3 + tr.T4] ts_I = ts_I[ts_I > tr.T1 + tr.T2 + tr.T3 + tr.T4] ts_I = ts_I - (tr.T1 + tr.T2 + tr.T3 + tr.T4) sts_E = [ neo.SpikeTrain(ts_E[idxs_E == i] / second * pq.s, t_stop=tr.T5 / second * pq.s) for i in range(tr.N_e) ] sts_I = [ neo.SpikeTrain(ts_I[idxs_I == i] / second * pq.s, t_stop=tr.T5 / second * pq.s) for i in range(tr.N_i) ] crs_crrs, syn_a = [], [] for f, (i, j) in enumerate(zip(synei_a['i'], synei_a['j'])): if synei_a['syn_active'][-1][f] == 1: crs_crr, cbin = cch(BinnedSpikeTrain(sts_I[i], binsize=binsize), BinnedSpikeTrain(sts_E[j], binsize=binsize), cross_corr_coef=True, border_correction=True, window=(-1 * wlen, wlen)) crs_crrs.append(list(np.array(crs_crr).T[0])) syn_a.append(synei_a['a'][-1][f]) fname = 'EI_crrs_wsize%dms_binsize%fms_full' % (wsize / pq.ms, binsize / pq.ms) df = { 'cbin': cbin, 'crs_crrs': np.array(crs_crrs), 'syn_a': np.array(syn_a), 'binsize': binsize, 'wsize': wsize, 'wlen': wlen } with open('builds/%.4d/raw/' % (tr.v_idx) + fname + '.p', 'wb') as pfile: pickle.dump(df, pfile) # ----------------- clean up --------------------------- shutil.rmtree('builds/%.4d/results/' % (tr.v_idx)) shutil.rmtree('builds/%.4d/static_arrays/' % (tr.v_idx)) shutil.rmtree('builds/%.4d/brianlib/' % (tr.v_idx)) shutil.rmtree('builds/%.4d/code_objects/' % (tr.v_idx)) # ---------------- plot results -------------------------- #os.chdir('./analysis/file_based/') if tr.istdp_active: from src.analysis.overview_winh import overview_figure overview_figure('builds/%.4d' % (tr.v_idx), namespace) else: from src.analysis.overview import overview_figure overview_figure('builds/%.4d' % (tr.v_idx), namespace) from src.analysis.synw_fb import synw_figure synw_figure('builds/%.4d' % (tr.v_idx), namespace) if tr.istdp_active: synw_figure('builds/%.4d' % (tr.v_idx), namespace, connections='EI') from src.analysis.synw_log_fb import synw_log_figure synw_log_figure('builds/%.4d' % (tr.v_idx), namespace) if tr.istdp_active: synw_log_figure('builds/%.4d' % (tr.v_idx), namespace, connections='EI')
def run_net(tr): # prefs.codegen.target = 'numpy' # prefs.codegen.target = 'cython' if tr.n_threads > 1: prefs.devices.cpp_standalone.openmp_threads = tr.n_threads set_device('cpp_standalone', directory='./builds/%.4d' % (tr.v_idx), build_on_run=False) print("Started process with id ", str(tr.v_idx)) T = tr.T1 + tr.T2 + tr.T3 + tr.T4 + tr.T5 namespace = tr.netw.f_to_dict(short_names=True, fast_access=True) namespace['idx'] = tr.v_idx defaultclock.dt = tr.netw.sim.dt # collect all network components dependent on configuration # (e.g. poisson vs. memnoise) and add them to the Brian 2 # network object later netw_objects = [] if tr.external_mode == 'memnoise': neuron_model = tr.condlif_memnoise elif tr.external_mode == 'poisson': neuron_model = tr.condlif_poisson GExc = NeuronGroup( N=tr.N_e, model=neuron_model, threshold=tr.nrnEE_thrshld, reset=tr.nrnEE_reset, #method=tr.neuron_method, namespace=namespace) GInh = NeuronGroup( N=tr.N_i, model=neuron_model, threshold='V > Vt', reset='V=Vr_i', #method=tr.neuron_method, namespace=namespace) if tr.external_mode == 'memnoise': GExc.mu, GInh.mu = tr.mu_e, tr.mu_i GExc.sigma, GInh.sigma = tr.sigma_e, tr.sigma_i GExc.Vt, GInh.Vt = tr.Vt_e, tr.Vt_i GExc.V , GInh.V = np.random.uniform(tr.Vr_e/mV, tr.Vt_e/mV, size=tr.N_e)*mV, \ np.random.uniform(tr.Vr_i/mV, tr.Vt_i/mV, size=tr.N_i)*mV netw_objects.extend([GExc, GInh]) synEE_pre_mod = mod.synEE_pre synEE_post_mod = mod.synEE_post if tr.external_mode == 'poisson': if tr.PInp_mode == 'pool': PInp = PoissonGroup(tr.NPInp, rates=tr.PInp_rate, namespace=namespace, name='poissongroup_exc') sPN = Synapses(target=GExc, source=PInp, model=tr.poisson_mod, on_pre='gfwd_post += a_EPoi', namespace=namespace, name='synPInpExc') sPN_src, sPN_tar = generate_N_connections(N_tar=tr.N_e, N_src=tr.NPInp, N=tr.NPInp_1n) elif tr.PInp_mode == 'indep': PInp = PoissonGroup(tr.N_e, rates=tr.PInp_rate, namespace=namespace) sPN = Synapses(target=GExc, source=PInp, model=tr.poisson_mod, on_pre='gfwd_post += a_EPoi', namespace=namespace, name='synPInp_inhInh') sPN_src, sPN_tar = range(tr.N_e), range(tr.N_e) sPN.connect(i=sPN_src, j=sPN_tar) if tr.PInp_mode == 'pool': PInp_inh = PoissonGroup(tr.NPInp_inh, rates=tr.PInp_inh_rate, namespace=namespace, name='poissongroup_inh') sPNInh = Synapses(target=GInh, source=PInp_inh, model=tr.poisson_mod, on_pre='gfwd_post += a_EPoi', namespace=namespace) sPNInh_src, sPNInh_tar = generate_N_connections(N_tar=tr.N_i, N_src=tr.NPInp_inh, N=tr.NPInp_inh_1n) elif tr.PInp_mode == 'indep': PInp_inh = PoissonGroup(tr.N_i, rates=tr.PInp_inh_rate, namespace=namespace) sPNInh = Synapses(target=GInh, source=PInp_inh, model=tr.poisson_mod, on_pre='gfwd_post += a_EPoi', namespace=namespace) sPNInh_src, sPNInh_tar = range(tr.N_i), range(tr.N_i) sPNInh.connect(i=sPNInh_src, j=sPNInh_tar) netw_objects.extend([PInp, sPN, PInp_inh, sPNInh]) if tr.syn_noise: synEE_mod = '''%s %s''' % (tr.synEE_noise, tr.synEE_mod) else: synEE_mod = '''%s %s''' % (tr.synEE_static, tr.synEE_mod) if tr.stdp_active: synEE_pre_mod = '''%s %s''' % (synEE_pre_mod, mod.synEE_pre_STDP) synEE_post_mod = '''%s %s''' % (synEE_post_mod, mod.synEE_post_STDP) if tr.synEE_rec: synEE_pre_mod = '''%s %s''' % (synEE_pre_mod, mod.synEE_pre_rec) synEE_post_mod = '''%s %s''' % (synEE_post_mod, mod.synEE_post_rec) # E<-E advanced synapse model, rest simple SynEE = Synapses(target=GExc, source=GExc, model=synEE_mod, on_pre=synEE_pre_mod, on_post=synEE_post_mod, namespace=namespace, dt=tr.synEE_mod_dt) SynIE = Synapses(target=GInh, source=GExc, on_pre='ge_post += a_ie', namespace=namespace) SynEI = Synapses(target=GExc, source=GInh, on_pre='gi_post += a_ei', namespace=namespace) SynII = Synapses(target=GInh, source=GInh, on_pre='gi_post += a_ii', namespace=namespace) if tr.strct_active: sEE_src, sEE_tar = generate_full_connectivity(tr.N_e, same=True) SynEE.connect(i=sEE_src, j=sEE_tar) SynEE.syn_active = 0 else: srcs_full, tars_full = generate_full_connectivity(tr.N_e, same=True) SynEE.connect(i=srcs_full, j=tars_full) SynEE.syn_active = 0 sIE_src, sIE_tar = generate_connections(tr.N_i, tr.N_e, tr.p_ie) sEI_src, sEI_tar = generate_connections(tr.N_e, tr.N_i, tr.p_ei) sII_src, sII_tar = generate_connections(tr.N_i, tr.N_i, tr.p_ii, same=True) SynIE.connect(i=sIE_src, j=sIE_tar) SynEI.connect(i=sEI_src, j=sEI_tar) SynII.connect(i=sII_src, j=sII_tar) tr.f_add_result('sIE_src', sIE_src) tr.f_add_result('sIE_tar', sIE_tar) tr.f_add_result('sEI_src', sEI_src) tr.f_add_result('sEI_tar', sEI_tar) tr.f_add_result('sII_src', sII_src) tr.f_add_result('sII_tar', sII_tar) if tr.syn_noise: SynEE.syn_sigma = tr.syn_sigma SynEE.insert_P = tr.insert_P SynEE.p_inactivate = tr.p_inactivate SynEE.stdp_active = 1 ATM_vals = np.random.normal(loc=tr.ATotalMax, scale=tr.ATotalMax_sd, size=tr.N_e * (tr.N_e - 1)) assert np.min(ATM_vals) > 0. SynEE.ATotalMax = ATM_vals # make randomly chosen synapses active at beginning rs = np.random.uniform(size=tr.N_e * (tr.N_e - 1)) initial_active = (rs < tr.p_ee).astype('int') initial_a = initial_active * tr.a_ee SynEE.syn_active = initial_active SynEE.a = initial_a # recording of stdp in T4 SynEE.stdp_rec_start = tr.T1 + tr.T2 + tr.T3 SynEE.stdp_rec_max = tr.T1 + tr.T2 + tr.T3 + tr.stdp_rec_T # synaptic scaling if tr.netw.config.scl_active: if tr.syn_scl_rec: SynEE.scl_rec_start = tr.T1 + tr.T2 + tr.T3 SynEE.scl_rec_max = tr.T1 + tr.T2 + tr.T3 + tr.scl_rec_T else: SynEE.scl_rec_start = T + 10 * second SynEE.scl_rec_max = T SynEE.summed_updaters['Asum_post']._clock = Clock( dt=tr.dt_synEE_scaling) synscaling = SynEE.run_regularly(tr.synEE_scaling, dt=tr.dt_synEE_scaling, when='end', name='syn_scaling') # # intrinsic plasticity # if tr.netw.config.it_active: # GExc.h_ip = tr.h_ip # GExc.run_regularly(tr.intrinsic_mod, dt = tr.it_dt, when='end') # structural plasticity if tr.netw.config.strct_active: if tr.strct_mode == 'zero': if tr.turnover_rec: strct_mod = '''%s %s''' % (tr.strct_mod, tr.turnover_rec_mod) else: strct_mod = tr.strct_mod strctplst = SynEE.run_regularly(strct_mod, dt=tr.strct_dt, when='end', name='strct_plst_zero') elif tr.strct_mode == 'thrs': if tr.turnover_rec: strct_mod_thrs = '''%s %s''' % (tr.strct_mod_thrs, tr.turnover_rec_mod) else: strct_mod_thrs = tr.strct_mod_thrs strctplst = SynEE.run_regularly(strct_mod_thrs, dt=tr.strct_dt, when='end', name='strct_plst_thrs') netw_objects.extend([SynEE, SynEI, SynIE, SynII]) # keep track of the number of active synapses sum_target = NeuronGroup(1, 'c : 1 (shared)', dt=tr.csample_dt) sum_model = '''NSyn : 1 (constant) c_post = (1.0*syn_active_pre)/NSyn : 1 (summed)''' sum_connection = Synapses(target=sum_target, source=SynEE, model=sum_model, dt=tr.csample_dt, name='get_active_synapse_count') sum_connection.connect() sum_connection.NSyn = tr.N_e * (tr.N_e - 1) if tr.adjust_insertP: # homeostatically adjust growth rate growth_updater = Synapses(sum_target, SynEE) growth_updater.run_regularly('insert_P_post *= 0.1/c_pre', when='after_groups', dt=tr.csample_dt, name='update_insP') growth_updater.connect(j='0') netw_objects.extend([sum_target, sum_connection, growth_updater]) # -------------- recording ------------------ GExc_recvars = [] if tr.memtraces_rec: GExc_recvars.append('V') if tr.vttraces_rec: GExc_recvars.append('Vt') if tr.getraces_rec: GExc_recvars.append('ge') if tr.gitraces_rec: GExc_recvars.append('gi') if tr.gfwdtraces_rec and tr.external_mode == 'poisson': GExc_recvars.append('gfwd') GInh_recvars = GExc_recvars GExc_stat = StateMonitor(GExc, GExc_recvars, record=[0, 1, 2], dt=tr.GExc_stat_dt) GInh_stat = StateMonitor(GInh, GInh_recvars, record=[0, 1, 2], dt=tr.GInh_stat_dt) SynEE_recvars = [] if tr.synee_atraces_rec: SynEE_recvars.append('a') if tr.synee_activetraces_rec: SynEE_recvars.append('syn_active') if tr.synee_Apretraces_rec: SynEE_recvars.append('Apre') if tr.synee_Aposttraces_rec: SynEE_recvars.append('Apost') SynEE_stat = StateMonitor(SynEE, SynEE_recvars, record=range(tr.n_synee_traces_rec), when='end', dt=tr.synEE_stat_dt) if tr.adjust_insertP: C_stat = StateMonitor(sum_target, 'c', dt=tr.csample_dt, record=[0], when='end') insP_stat = StateMonitor(SynEE, 'insert_P', dt=tr.csample_dt, record=[0], when='end') netw_objects.extend([C_stat, insP_stat]) GExc_spks = SpikeMonitor(GExc) GInh_spks = SpikeMonitor(GInh) GExc_rate = PopulationRateMonitor(GExc) GInh_rate = PopulationRateMonitor(GInh) if tr.external_mode == 'poisson': PInp_spks = SpikeMonitor(PInp) PInp_rate = PopulationRateMonitor(PInp) netw_objects.extend([PInp_spks, PInp_rate]) if tr.synee_a_nrecpoints == 0: SynEE_a_dt = 10 * tr.sim.T2 else: SynEE_a_dt = tr.sim.T2 / tr.synee_a_nrecpoints SynEE_a = StateMonitor(SynEE, ['a', 'syn_active'], record=range(tr.N_e * (tr.N_e - 1)), dt=SynEE_a_dt, when='end', order=100) netw_objects.extend([ GExc_stat, GInh_stat, SynEE_stat, SynEE_a, GExc_spks, GInh_spks, GExc_rate, GInh_rate ]) net = Network(*netw_objects) def set_active(*argv): for net_object in argv: net_object.active = True def set_inactive(*argv): for net_object in argv: net_object.active = False ### Simulation periods # --------- T1 --------- # initial recording period, # all recorders active set_active(GExc_spks, GInh_spks, SynEE_stat, GExc_stat, GInh_stat, GExc_rate, GInh_rate) if tr.external_mode == 'poisson': set_active(PInp_spks, PInp_rate) net.run(tr.sim.T1, report='text', report_period=300 * second, profile=True) # --------- T2 --------- # main simulation period # only active recordings are: # 1) turnover 2) C_stat 3) SynEE_a set_inactive(GExc_spks, GInh_spks, SynEE_stat, GExc_stat, GInh_stat, GExc_rate, GInh_rate) if tr.external_mode == 'poisson': set_inactive(PInp_spks, PInp_rate) net.run(tr.sim.T2, report='text', report_period=300 * second, profile=True) # --------- T3 --------- # second recording period, # all recorders active set_active(GExc_spks, GInh_spks, SynEE_stat, GExc_stat, GInh_stat, GExc_rate, GInh_rate) if tr.external_mode == 'poisson': set_active(PInp_spks, PInp_rate) net.run(tr.sim.T3, report='text', report_period=300 * second, profile=True) # --------- T4 --------- # record STDP and scaling weight changes to file # through the cpp models set_inactive(GExc_spks, GInh_spks, SynEE_stat, GExc_stat, GInh_stat, GExc_rate, GInh_rate) if tr.external_mode == 'poisson': set_inactive(PInp_spks, PInp_rate) net.run(tr.sim.T4, report='text', report_period=300 * second, profile=True) # --------- T5 --------- # freeze network and record Exc spikes # for cross correlations synscaling.active = False strctplst.active = False SynEE.stdp_active = 0 set_active(GExc_spks) net.run(tr.sim.T5, report='text', report_period=300 * second, profile=True) SynEE_a.record_single_timestep() device.build(directory='builds/%.4d' % (tr.v_idx), clean=True, compile=True, run=True, debug=False) # ----------------------------------------- # save monitors as raws in build directory raw_dir = 'builds/%.4d/raw/' % (tr.v_idx) if not os.path.exists(raw_dir): os.makedirs(raw_dir) with open(raw_dir + 'namespace.p', 'wb') as pfile: pickle.dump(namespace, pfile) with open(raw_dir + 'gexc_stat.p', 'wb') as pfile: pickle.dump(GExc_stat.get_states(), pfile) with open(raw_dir + 'ginh_stat.p', 'wb') as pfile: pickle.dump(GInh_stat.get_states(), pfile) with open(raw_dir + 'synee_stat.p', 'wb') as pfile: pickle.dump(SynEE_stat.get_states(), pfile) with open(raw_dir + 'synee_a.p', 'wb') as pfile: SynEE_a_states = SynEE_a.get_states() if tr.crs_crrs_rec: SynEE_a_states['i'] = list(SynEE.i) SynEE_a_states['j'] = list(SynEE.j) pickle.dump(SynEE_a_states, pfile) if tr.adjust_insertP: with open(raw_dir + 'c_stat.p', 'wb') as pfile: pickle.dump(C_stat.get_states(), pfile) with open(raw_dir + 'insP_stat.p', 'wb') as pfile: pickle.dump(insP_stat.get_states(), pfile) with open(raw_dir + 'gexc_spks.p', 'wb') as pfile: pickle.dump(GExc_spks.get_states(), pfile) with open(raw_dir + 'ginh_spks.p', 'wb') as pfile: pickle.dump(GInh_spks.get_states(), pfile) if tr.external_mode == 'poisson': with open(raw_dir + 'pinp_spks.p', 'wb') as pfile: pickle.dump(PInp_spks.get_states(), pfile) with open(raw_dir + 'gexc_rate.p', 'wb') as pfile: pickle.dump(GExc_rate.get_states(), pfile) if tr.rates_rec: pickle.dump(GExc_rate.smooth_rate(width=25 * ms), pfile) with open(raw_dir + 'ginh_rate.p', 'wb') as pfile: pickle.dump(GInh_rate.get_states(), pfile) if tr.rates_rec: pickle.dump(GInh_rate.smooth_rate(width=25 * ms), pfile) if tr.external_mode == 'poisson': with open(raw_dir + 'pinp_rate.p', 'wb') as pfile: pickle.dump(PInp_rate.get_states(), pfile) if tr.rates_rec: pickle.dump(PInp_rate.smooth_rate(width=25 * ms), pfile) # ----------------- add raw data ------------------------ fpath = 'builds/%.4d/' % (tr.v_idx) from pathlib import Path Path(fpath + 'turnover').touch() turnover_data = np.genfromtxt(fpath + 'turnover', delimiter=',') os.remove(fpath + 'turnover') with open(raw_dir + 'turnover.p', 'wb') as pfile: pickle.dump(turnover_data, pfile) Path(fpath + 'spk_register').touch() spk_register_data = np.genfromtxt(fpath + 'spk_register', delimiter=',') os.remove(fpath + 'spk_register') with open(raw_dir + 'spk_register.p', 'wb') as pfile: pickle.dump(spk_register_data, pfile) Path(fpath + 'scaling_deltas').touch() scaling_deltas_data = np.genfromtxt(fpath + 'scaling_deltas', delimiter=',') os.remove(fpath + 'scaling_deltas') with open(raw_dir + 'scaling_deltas.p', 'wb') as pfile: pickle.dump(scaling_deltas_data, pfile) with open(raw_dir + 'profiling_summary.txt', 'w+') as tfile: tfile.write(str(profiling_summary(net))) # --------------- cross-correlations --------------------- if tr.crs_crrs_rec: GExc_spks = GExc_spks.get_states() synee_a = SynEE_a_states wsize = 100 * pq.ms for binsize in [1 * pq.ms, 2 * pq.ms, 5 * pq.ms]: wlen = int(wsize / binsize) ts, idxs = GExc_spks['t'], GExc_spks['i'] idxs = idxs[ts > tr.T1 + tr.T2 + tr.T3 + tr.T4] ts = ts[ts > tr.T1 + tr.T2 + tr.T3 + tr.T4] ts = ts - (tr.T1 + tr.T2 + tr.T3 + tr.T4) sts = [ neo.SpikeTrain(ts[idxs == i] / second * pq.s, t_stop=tr.T5 / second * pq.s) for i in range(tr.N_e) ] crs_crrs, syn_a = [], [] for f, (i, j) in enumerate(zip(synee_a['i'], synee_a['j'])): if synee_a['syn_active'][-1][f] == 1: crs_crr, cbin = cch(BinnedSpikeTrain(sts[i], binsize=binsize), BinnedSpikeTrain(sts[j], binsize=binsize), cross_corr_coef=True, border_correction=True, window=(-1 * wlen, wlen)) crs_crrs.append(list(np.array(crs_crr).T[0])) syn_a.append(synee_a['a'][-1][f]) fname = 'crs_crrs_wsize%dms_binsize%fms_full' % (wsize / pq.ms, binsize / pq.ms) df = { 'cbin': cbin, 'crs_crrs': np.array(crs_crrs), 'syn_a': np.array(syn_a), 'binsize': binsize, 'wsize': wsize, 'wlen': wlen } with open('builds/%.4d/raw/' % (tr.v_idx) + fname + '.p', 'wb') as pfile: pickle.dump(df, pfile) # ----------------- clean up --------------------------- shutil.rmtree('builds/%.4d/results/' % (tr.v_idx)) # ---------------- plot results -------------------------- #os.chdir('./analysis/file_based/') from analysis.overview_fb import overview_figure overview_figure('builds/%.4d' % (tr.v_idx), namespace) from analysis.synw_fb import synw_figure synw_figure('builds/%.4d' % (tr.v_idx), namespace) from analysis.synw_log_fb import synw_log_figure synw_log_figure('builds/%.4d' % (tr.v_idx), namespace)
def run_net(tr): # prefs.codegen.target = 'numpy' # prefs.codegen.target = 'cython' set_device('cpp_standalone', directory='./builds/%.4d' % (tr.v_idx), build_on_run=False) print("Started process with id ", str(tr.v_idx)) T = tr.T1 + tr.T2 + tr.T3 namespace = tr.netw.f_to_dict(short_names=True, fast_access=True) namespace['idx'] = tr.v_idx defaultclock.dt = tr.netw.sim.dt GExc = NeuronGroup( N=tr.N_e, model=tr.condlif_sig, threshold=tr.nrnEE_thrshld, reset=tr.nrnEE_reset, #method=tr.neuron_method, namespace=namespace) GInh = NeuronGroup( N=tr.N_i, model=tr.condlif_sig, threshold='V > Vt', reset='V=Vr_i', #method=tr.neuron_method, namespace=namespace) # set initial thresholds fixed, init. potentials uniformly distrib. GExc.sigma, GInh.sigma = tr.sigma_e, tr.sigma_i GExc.Vt, GInh.Vt = tr.Vt_e, tr.Vt_i GExc.V , GInh.V = np.random.uniform(tr.Vr_e/mV, tr.Vt_e/mV, size=tr.N_e)*mV, \ np.random.uniform(tr.Vr_i/mV, tr.Vt_i/mV, size=tr.N_i)*mV print("need to fix?") synEE_pre_mod = mod.synEE_pre synEE_post_mod = mod.synEE_post if tr.PInp_mode == 'pool': PInp = PoissonGroup(tr.NPInp, rates=tr.PInp_rate, namespace=namespace) sPN = Synapses(target=GExc, source=PInp, model=tr.poisson_mod, on_pre='ge_post += a_EPoi', namespace=namespace) sPN_src, sPN_tar = generate_connections(N_tar=tr.N_e, N_src=tr.NPInp, p=tr.p_EPoi) elif tr.PInp_mode == 'indep': PInp = PoissonGroup(tr.N_e, rates=tr.PInp_rate, namespace=namespace) sPN = Synapses(target=GExc, source=PInp, model=tr.poisson_mod, on_pre='ge_post += a_EPoi', namespace=namespace) sPN_src, sPN_tar = range(tr.N_e), range(tr.N_e) sPN.connect(i=sPN_src, j=sPN_tar) if tr.PInp_mode == 'pool': sPNInh = Synapses(target=GInh, source=PInp, model=tr.poisson_mod, on_pre='ge_post += a_EPoi', namespace=namespace) sPNInh_src, sPNInh_tar = generate_connections(N_tar=tr.N_i, N_src=tr.NPInp, p=tr.p_EPoi) elif tr.PInp_mode == 'indep': PInp_inh = PoissonGroup(tr.N_i, rates=tr.PInp_rate, namespace=namespace) sPNInh = Synapses(target=GInh, source=PInp_inh, model=tr.poisson_mod, on_pre='ge_post += a_EPoi', namespace=namespace) sPNInh_src, sPNInh_tar = range(tr.N_i), range(tr.N_i) sPNInh.connect(i=sPNInh_src, j=sPNInh_tar) if tr.stdp_active: synEE_pre_mod = '''%s %s''' % (synEE_pre_mod, mod.synEE_pre_STDP) synEE_post_mod = '''%s %s''' % (synEE_post_mod, mod.synEE_post_STDP) if tr.synEE_rec: synEE_pre_mod = '''%s %s''' % (synEE_pre_mod, mod.synEE_pre_rec) synEE_post_mod = '''%s %s''' % (synEE_post_mod, mod.synEE_post_rec) # E<-E advanced synapse model, rest simple SynEE = Synapses( target=GExc, source=GExc, model=tr.synEE_mod, on_pre=synEE_pre_mod, on_post=synEE_post_mod, #method=tr.synEE_method, namespace=namespace) SynIE = Synapses(target=GInh, source=GExc, on_pre='ge_post += a_ie', namespace=namespace) SynEI = Synapses(target=GExc, source=GInh, on_pre='gi_post += a_ei', namespace=namespace) SynII = Synapses(target=GInh, source=GInh, on_pre='gi_post += a_ii', namespace=namespace) if tr.strct_active: sEE_src, sEE_tar = generate_full_connectivity(tr.N_e, same=True) SynEE.connect(i=sEE_src, j=sEE_tar) SynEE.syn_active = 0 else: srcs_full, tars_full = generate_full_connectivity(tr.N_e, same=True) SynEE.connect(i=srcs_full, j=tars_full) SynEE.syn_active = 0 sIE_src, sIE_tar = generate_connections(tr.N_i, tr.N_e, tr.p_ie) sEI_src, sEI_tar = generate_connections(tr.N_e, tr.N_i, tr.p_ei) sII_src, sII_tar = generate_connections(tr.N_i, tr.N_i, tr.p_ii, same=True) SynIE.connect(i=sIE_src, j=sIE_tar) SynEI.connect(i=sEI_src, j=sEI_tar) SynII.connect(i=sII_src, j=sII_tar) tr.f_add_result('sIE_src', sIE_src) tr.f_add_result('sIE_tar', sIE_tar) tr.f_add_result('sEI_src', sEI_src) tr.f_add_result('sEI_tar', sEI_tar) tr.f_add_result('sII_src', sII_src) tr.f_add_result('sII_tar', sII_tar) SynEE.a = tr.a_ee SynEE.insert_P = tr.insert_P SynEE.p_inactivate = tr.p_inactivate # make synapse active at beginning SynEE.run_regularly(tr.synEE_p_activate, dt=T, when='start', order=-100) # synaptic scaling if tr.netw.config.scl_active: SynEE.summed_updaters['Asum_post']._clock = Clock( dt=tr.dt_synEE_scaling) SynEE.run_regularly(tr.synEE_scaling, dt=tr.dt_synEE_scaling, when='end') # intrinsic plasticity if tr.netw.config.it_active: GExc.h_ip = tr.h_ip GExc.run_regularly(tr.intrinsic_mod, dt=tr.it_dt, when='end') # structural plasticity if tr.netw.config.strct_active: if tr.strct_mode == 'zero': if tr.turnover_rec: strct_mod = '''%s %s''' % (tr.strct_mod, tr.turnover_rec_mod) else: strct_mod = tr.strct_mod SynEE.run_regularly(strct_mod, dt=tr.strct_dt, when='end') elif tr.strct_mode == 'thrs': if tr.turnover_rec: strct_mod_thrs = '''%s %s''' % (tr.strct_mod_thrs, tr.turnover_rec_mod) else: strct_mod_thrs = tr.strct_mod_thrs SynEE.run_regularly(strct_mod_thrs, dt=tr.strct_dt, when='end') # -------------- recording ------------------ #run(tr.sim.preT) GExc_recvars = [] if tr.memtraces_rec: GExc_recvars.append('V') if tr.vttraces_rec: GExc_recvars.append('Vt') if tr.getraces_rec: GExc_recvars.append('ge') if tr.gitraces_rec: GExc_recvars.append('gi') GInh_recvars = GExc_recvars GExc_stat = StateMonitor(GExc, GExc_recvars, record=[0, 1, 2], dt=tr.GExc_stat_dt) GInh_stat = StateMonitor(GInh, GInh_recvars, record=[0, 1, 2], dt=tr.GInh_stat_dt) SynEE_recvars = [] if tr.synee_atraces_rec: SynEE_recvars.append('a') if tr.synee_Apretraces_rec: SynEE_recvars.append('Apre') if tr.synee_Aposttraces_rec: SynEE_recvars.append('Apost') SynEE_stat = StateMonitor(SynEE, SynEE_recvars, record=range(tr.n_synee_traces_rec), when='end', dt=tr.synEE_stat_dt) GExc_spks = SpikeMonitor(GExc) GInh_spks = SpikeMonitor(GInh) PInp_spks = SpikeMonitor(PInp) GExc_rate = PopulationRateMonitor(GExc) GInh_rate = PopulationRateMonitor(GInh) PInp_rate = PopulationRateMonitor(PInp) SynEE_a = StateMonitor(SynEE, ['a', 'syn_active'], record=range(tr.N_e * (tr.N_e - 1)), dt=T / tr.synee_a_nrecpoints, when='end', order=100) if tr.PInp_mode == 'indep': net = Network(GExc, GInh, PInp, sPN, sPNInh, SynEE, SynEI, SynIE, SynII, GExc_stat, GInh_stat, SynEE_stat, SynEE_a, GExc_spks, GInh_spks, PInp_spks, GExc_rate, GInh_rate, PInp_rate, PInp_inh) else: net = Network(GExc, GInh, PInp, sPN, sPNInh, SynEE, SynEI, SynIE, SynII, GExc_stat, GInh_stat, SynEE_stat, SynEE_a, GExc_spks, GInh_spks, PInp_spks, GExc_rate, GInh_rate, PInp_rate) net.run(tr.sim.T1, report='text') # SynEE_a.record_single_timestep() recorders = [ GExc_spks, GInh_spks, PInp_spks, SynEE_stat, GExc_stat, GInh_stat ] rate_recorders = [GExc_rate, GInh_rate, PInp_rate] for rcc in recorders: rcc.active = False net.run(tr.sim.T2, report='text') recorders = [ SynEE_stat, GExc_stat, GInh_stat, GExc_rate, GInh_rate, PInp_rate ] for rcc in recorders: rcc.active = True if tr.spks_rec: GExc_spks.active = True GInh_spks.active = True # PInp_spks.active=True net.run(tr.sim.T3, report='text') device.build(directory='../builds/%.4d' % (tr.v_idx), clean=True) # save monitors as raws in build directory raw_dir = '../builds/%.4d/raw/' % (tr.v_idx) if not os.path.exists(raw_dir): os.makedirs(raw_dir) with open(raw_dir + 'namespace.p', 'wb') as pfile: pickle.dump(namespace, pfile) with open(raw_dir + 'gexc_stat.p', 'wb') as pfile: pickle.dump(GExc_stat.get_states(), pfile) with open(raw_dir + 'ginh_stat.p', 'wb') as pfile: pickle.dump(GInh_stat.get_states(), pfile) with open(raw_dir + 'synee_stat.p', 'wb') as pfile: pickle.dump(SynEE_stat.get_states(), pfile) with open(raw_dir + 'synee_a.p', 'wb') as pfile: pickle.dump(SynEE_a.get_states(), pfile) with open(raw_dir + 'gexc_spks.p', 'wb') as pfile: pickle.dump(GExc_spks.get_states(), pfile) with open(raw_dir + 'ginh_spks.p', 'wb') as pfile: pickle.dump(GInh_spks.get_states(), pfile) with open(raw_dir + 'pinp_spks.p', 'wb') as pfile: pickle.dump(PInp_spks.get_states(), pfile) with open(raw_dir + 'gexc_rate.p', 'wb') as pfile: pickle.dump(GExc_rate.get_states(), pfile) pickle.dump(GExc_rate.smooth_rate(width=25 * ms), pfile) with open(raw_dir + 'ginh_rate.p', 'wb') as pfile: pickle.dump(GInh_rate.get_states(), pfile) pickle.dump(GInh_rate.smooth_rate(width=25 * ms), pfile) with open(raw_dir + 'pinp_rate.p', 'wb') as pfile: pickle.dump(PInp_rate.get_states(), pfile) pickle.dump(PInp_rate.smooth_rate(width=25 * ms), pfile) # ----------------- add raw data ------------------------ fpath = '../builds/%.4d/' % (tr.v_idx) from pathlib import Path Path(fpath + 'turnover').touch() turnover_data = np.genfromtxt(fpath + 'turnover', delimiter=',') os.remove(fpath + 'turnover') with open(raw_dir + 'turnover.p', 'wb') as pfile: pickle.dump(turnover_data, pfile) Path(fpath + 'spk_register').touch() spk_register_data = np.genfromtxt(fpath + 'spk_register', delimiter=',') os.remove(fpath + 'spk_register') with open(raw_dir + 'spk_register.p', 'wb') as pfile: pickle.dump(spk_register_data, pfile)
plasticity rule. Sebastian Schmitt, 2021 """ import itertools import numpy as np import matplotlib.pyplot as plt from brian2 import TimedArray, PoissonGroup, NeuronGroup, Synapses, StateMonitor, PopulationRateMonitor from brian2 import defaultclock, run from brian2 import Hz, ms, second # The synaptic weight from the steady stimulus is plastic steady_stimulus = TimedArray([50] * Hz, dt=40 * second) steady_poisson = PoissonGroup(1, rates='steady_stimulus(t)') # The synaptic weight from the varying stimulus is static varying_stimulus = TimedArray([25 * Hz, 50 * Hz, 0 * Hz, 35 * Hz, 0 * Hz], dt=10 * second) varying_poisson = PoissonGroup(1, rates='varying_stimulus(t)') # dw_plus/dw_minus determines scales the steady stimulus rate to the target firing rate, must not be larger 1 # the magntude of dw_plus and dw_minus determines the "speed" of the homeostasis parameters = { 'tau': 10 * ms, # membrane time constant 'dw_plus': 0.05, # weight increment on pre spike 'dw_minus': 0.05, # weight increment on post spike 'w_max': 2, # maximum plastic weight 'w_initial': 0 # initial plastic weight }
def strong_mem_noise_on_group(G: NeuronGroup): GNoise = PoissonGroup(G.N, rates=tr.strong_mem_noise_rate) SynNoise = Synapses(source=GNoise, target=G, on_pre="V_post += 20*mV") SynNoise.connect(condition="i==j") return [GNoise, SynNoise]
def brian2(self) -> BrianObject: return PoissonGroup(self.n, self.rate, name=self.name)
def sim_decision_making_network( N_Excit=384, N_Inhib=96, weight_scaling_factor=5.33, t_stimulus_start=100 * b2.ms, t_stimulus_duration=9999 * b2.ms, coherence_level=0., stimulus_update_interval=30 * b2.ms, mu0_mean_stimulus_Hz=160., stimulus_std_Hz=20., N_extern=1000, firing_rate_extern=9.8 * b2.Hz, w_pos=1.90, f_Subpop_size=0.25, # .15 in publication [1] max_sim_time=1000. * b2.ms, stop_condition_rate=None, monitored_subset_size=512): """ Args: N_Excit (int): total number of neurons in the excitatory population N_Inhib (int): nr of neurons in the inhibitory populations weight_scaling_factor: When increasing the number of neurons by 2, the weights should be scaled down by 1/2 t_stimulus_start (Quantity): time when the stimulation starts t_stimulus_duration (Quantity): duration of the stimulation coherence_level (int): coherence of the stimulus. Difference in mean between the PoissonGroups "left" stimulus and "right" stimulus stimulus_update_interval (Quantity): the mean of the stimulating PoissonGroups is re-sampled at this interval mu0_mean_stimulus_Hz (float): maximum mean firing rate of the stimulus if c=+1 or c=-1. Each neuron in the populations "Left" and "Right" receives an independent poisson input. stimulus_std_Hz (float): std deviation of the stimulating PoissonGroups. N_extern (int): nr of neurons in the stimulus independent poisson background population firing_rate_extern (int): firing rate of the stimulus independent poisson background population w_pos (float): Scaling (strengthening) of the recurrent weights within the subpopulations "Left" and "Right" f_Subpop_size (float): fraction of the neurons in the subpopulations "Left" and "Right". #left = #right = int(f_Subpop_size*N_Excit). max_sim_time (Quantity): simulated time. stop_condition_rate (Quantity): An optional stopping criteria: If not None, the simulation stops if the firing rate of either subpopulation "Left" or "Right" is above stop_condition_rate. monitored_subset_size (int): max nr of neurons for which a state monitor is registered. Returns: A dictionary with the following keys (strings): "rate_monitor_A", "spike_monitor_A", "voltage_monitor_A", "idx_monitored_neurons_A", "rate_monitor_B", "spike_monitor_B", "voltage_monitor_B", "idx_monitored_neurons_B", "rate_monitor_Z", "spike_monitor_Z", "voltage_monitor_Z", "idx_monitored_neurons_Z", "rate_monitor_inhib", "spike_monitor_inhib", "voltage_monitor_inhib", "idx_monitored_neurons_inhib" """ print("simulating {} neurons. Start: {}".format(N_Excit + N_Inhib, time.ctime())) t_stimulus_end = t_stimulus_start + t_stimulus_duration N_Group_A = int( N_Excit * f_Subpop_size ) # size of the excitatory subpopulation sensitive to stimulus A N_Group_B = N_Group_A # size of the excitatory subpopulation sensitive to stimulus B N_Group_Z = N_Excit - N_Group_A - N_Group_B # (1-2f)Ne excitatory neurons do not respond to either stimulus. Cm_excit = 0.5 * b2.nF # membrane capacitance of excitatory neurons G_leak_excit = 25.0 * b2.nS # leak conductance E_leak_excit = -70.0 * b2.mV # reversal potential v_spike_thr_excit = -50.0 * b2.mV # spike condition v_reset_excit = -60.0 * b2.mV # reset voltage after spike t_abs_refract_excit = 2. * b2.ms # absolute refractory period # specify the inhibitory interneurons: # N_Inhib = 200 Cm_inhib = 0.2 * b2.nF G_leak_inhib = 20.0 * b2.nS E_leak_inhib = -70.0 * b2.mV v_spike_thr_inhib = -50.0 * b2.mV v_reset_inhib = -60.0 * b2.mV t_abs_refract_inhib = 1.0 * b2.ms # specify the AMPA synapses E_AMPA = 0.0 * b2.mV tau_AMPA = 2.5 * b2.ms # specify the GABA synapses E_GABA = -70.0 * b2.mV tau_GABA = 5.0 * b2.ms # specify the NMDA synapses E_NMDA = 0.0 * b2.mV tau_NMDA_s = 100.0 * b2.ms tau_NMDA_x = 2. * b2.ms alpha_NMDA = 0.5 * b2.kHz # projections from the external population g_AMPA_extern2inhib = 1.62 * b2.nS g_AMPA_extern2excit = 2.1 * b2.nS # projectsions from the inhibitory populations g_GABA_inhib2inhib = weight_scaling_factor * 1.25 * b2.nS g_GABA_inhib2excit = weight_scaling_factor * 1.60 * b2.nS # projections from the excitatory population g_AMPA_excit2excit = weight_scaling_factor * 0.012 * b2.nS g_AMPA_excit2inhib = weight_scaling_factor * 0.015 * b2.nS g_NMDA_excit2excit = weight_scaling_factor * 0.040 * b2.nS g_NMDA_excit2inhib = weight_scaling_factor * 0.045 * b2.nS # stronger projection to inhib. # weights and "adjusted" weights. w_neg = 1. - f_Subpop_size * (w_pos - 1.) / (1. - f_Subpop_size) # We use the same postsyn AMPA and NMDA conductances. Adjust the weights coming from different sources: w_ext2inhib = g_AMPA_extern2inhib / g_AMPA_excit2inhib w_ext2excit = g_AMPA_extern2excit / g_AMPA_excit2excit # other weights are 1 # print("w_neg={}, w_ext2inhib={}, w_ext2excit={}".format(w_neg, w_ext2inhib, w_ext2excit)) # Define the inhibitory population # dynamics: inhib_lif_dynamics = """ s_NMDA_total : 1 # the post synaptic sum of s. compare with s_NMDA_presyn dv/dt = ( - G_leak_inhib * (v-E_leak_inhib) - g_AMPA_excit2inhib * s_AMPA * (v-E_AMPA) - g_GABA_inhib2inhib * s_GABA * (v-E_GABA) - g_NMDA_excit2inhib * s_NMDA_total * (v-E_NMDA)/(1.0+1.0*exp(-0.062*v/volt)/3.57) )/Cm_inhib : volt (unless refractory) ds_AMPA/dt = -s_AMPA/tau_AMPA : 1 ds_GABA/dt = -s_GABA/tau_GABA : 1 """ inhib_pop = NeuronGroup(N_Inhib, model=inhib_lif_dynamics, threshold="v>v_spike_thr_inhib", reset="v=v_reset_inhib", refractory=t_abs_refract_inhib, method="rk2") # initialize with random voltages: inhib_pop.v = rnd.uniform(v_spike_thr_inhib / b2.mV - 4., high=v_spike_thr_inhib / b2.mV - 1., size=N_Inhib) * b2.mV # Specify the excitatory population: # dynamics: excit_lif_dynamics = """ s_NMDA_total : 1 # the post synaptic sum of s. compare with s_NMDA_presyn dv/dt = ( - G_leak_excit * (v-E_leak_excit) - g_AMPA_excit2excit * s_AMPA * (v-E_AMPA) - g_GABA_inhib2excit * s_GABA * (v-E_GABA) - g_NMDA_excit2excit * s_NMDA_total * (v-E_NMDA)/(1.0+1.0*exp(-0.062*v/volt)/3.57) )/Cm_excit : volt (unless refractory) ds_AMPA/dt = -s_AMPA/tau_AMPA : 1 ds_GABA/dt = -s_GABA/tau_GABA : 1 ds_NMDA/dt = -s_NMDA/tau_NMDA_s + alpha_NMDA * x * (1-s_NMDA) : 1 dx/dt = -x/tau_NMDA_x : 1 """ # define the three excitatory subpopulations. # A: subpop receiving stimulus A excit_pop_A = NeuronGroup(N_Group_A, model=excit_lif_dynamics, threshold="v>v_spike_thr_excit", reset="v=v_reset_excit", refractory=t_abs_refract_excit, method="rk2") excit_pop_A.v = rnd.uniform(E_leak_excit / b2.mV, high=E_leak_excit / b2.mV + 5., size=excit_pop_A.N) * b2.mV # B: subpop receiving stimulus B excit_pop_B = NeuronGroup(N_Group_B, model=excit_lif_dynamics, threshold="v>v_spike_thr_excit", reset="v=v_reset_excit", refractory=t_abs_refract_excit, method="rk2") excit_pop_B.v = rnd.uniform(E_leak_excit / b2.mV, high=E_leak_excit / b2.mV + 5., size=excit_pop_B.N) * b2.mV # Z: non-sensitive excit_pop_Z = NeuronGroup(N_Group_Z, model=excit_lif_dynamics, threshold="v>v_spike_thr_excit", reset="v=v_reset_excit", refractory=t_abs_refract_excit, method="rk2") excit_pop_Z.v = rnd.uniform(v_reset_excit / b2.mV, high=v_spike_thr_excit / b2.mV - 1., size=excit_pop_Z.N) * b2.mV # now define the connections: # projections FROM EXTERNAL POISSON GROUP: #################################################### poisson2Inhib = PoissonInput(target=inhib_pop, target_var="s_AMPA", N=N_extern, rate=firing_rate_extern, weight=w_ext2inhib) poisson2A = PoissonInput(target=excit_pop_A, target_var="s_AMPA", N=N_extern, rate=firing_rate_extern, weight=w_ext2excit) poisson2B = PoissonInput(target=excit_pop_B, target_var="s_AMPA", N=N_extern, rate=firing_rate_extern, weight=w_ext2excit) poisson2Z = PoissonInput(target=excit_pop_Z, target_var="s_AMPA", N=N_extern, rate=firing_rate_extern, weight=w_ext2excit) ############################################################################################### # GABA projections FROM INHIBITORY population: ################################################ syn_inhib2inhib = Synapses(inhib_pop, target=inhib_pop, on_pre="s_GABA += 1.0", delay=0.5 * b2.ms) syn_inhib2inhib.connect(p=1.) syn_inhib2A = Synapses(inhib_pop, target=excit_pop_A, on_pre="s_GABA += 1.0", delay=0.5 * b2.ms) syn_inhib2A.connect(p=1.) syn_inhib2B = Synapses(inhib_pop, target=excit_pop_B, on_pre="s_GABA += 1.0", delay=0.5 * b2.ms) syn_inhib2B.connect(p=1.) syn_inhib2Z = Synapses(inhib_pop, target=excit_pop_Z, on_pre="s_GABA += 1.0", delay=0.5 * b2.ms) syn_inhib2Z.connect(p=1.) ############################################################################################### # AMPA projections FROM EXCITATORY A: ######################################################### syn_AMPA_A2A = Synapses(excit_pop_A, target=excit_pop_A, on_pre="s_AMPA += w_pos", delay=0.5 * b2.ms) syn_AMPA_A2A.connect(p=1.) syn_AMPA_A2B = Synapses(excit_pop_A, target=excit_pop_B, on_pre="s_AMPA += w_neg", delay=0.5 * b2.ms) syn_AMPA_A2B.connect(p=1.) syn_AMPA_A2Z = Synapses(excit_pop_A, target=excit_pop_Z, on_pre="s_AMPA += 1.0", delay=0.5 * b2.ms) syn_AMPA_A2Z.connect(p=1.) syn_AMPA_A2inhib = Synapses(excit_pop_A, target=inhib_pop, on_pre="s_AMPA += 1.0", delay=0.5 * b2.ms) syn_AMPA_A2inhib.connect(p=1.) ############################################################################################### # AMPA projections FROM EXCITATORY B: ######################################################### syn_AMPA_B2A = Synapses(excit_pop_B, target=excit_pop_A, on_pre="s_AMPA += w_neg", delay=0.5 * b2.ms) syn_AMPA_B2A.connect(p=1.) syn_AMPA_B2B = Synapses(excit_pop_B, target=excit_pop_B, on_pre="s_AMPA += w_pos", delay=0.5 * b2.ms) syn_AMPA_B2B.connect(p=1.) syn_AMPA_B2Z = Synapses(excit_pop_B, target=excit_pop_Z, on_pre="s_AMPA += 1.0", delay=0.5 * b2.ms) syn_AMPA_B2Z.connect(p=1.) syn_AMPA_B2inhib = Synapses(excit_pop_B, target=inhib_pop, on_pre="s_AMPA += 1.0", delay=0.5 * b2.ms) syn_AMPA_B2inhib.connect(p=1.) ############################################################################################### # AMPA projections FROM EXCITATORY Z: ######################################################### syn_AMPA_Z2A = Synapses(excit_pop_Z, target=excit_pop_A, on_pre="s_AMPA += 1.0", delay=0.5 * b2.ms) syn_AMPA_Z2A.connect(p=1.) syn_AMPA_Z2B = Synapses(excit_pop_Z, target=excit_pop_B, on_pre="s_AMPA += 1.0", delay=0.5 * b2.ms) syn_AMPA_Z2B.connect(p=1.) syn_AMPA_Z2Z = Synapses(excit_pop_Z, target=excit_pop_Z, on_pre="s_AMPA += 1.0", delay=0.5 * b2.ms) syn_AMPA_Z2Z.connect(p=1.) syn_AMPA_Z2inhib = Synapses(excit_pop_Z, target=inhib_pop, on_pre="s_AMPA += 1.0", delay=0.5 * b2.ms) syn_AMPA_Z2inhib.connect(p=1.) ############################################################################################### # NMDA projections FROM EXCITATORY to INHIB, A,B,Z @network_operation() def update_nmda_sum(): sum_sNMDA_A = sum(excit_pop_A.s_NMDA) sum_sNMDA_B = sum(excit_pop_B.s_NMDA) sum_sNMDA_Z = sum(excit_pop_Z.s_NMDA) # note the _ at the end of s_NMDA_total_ disables unit checking inhib_pop.s_NMDA_total_ = (1.0 * sum_sNMDA_A + 1.0 * sum_sNMDA_B + 1.0 * sum_sNMDA_Z) excit_pop_A.s_NMDA_total_ = (w_pos * sum_sNMDA_A + w_neg * sum_sNMDA_B + w_neg * sum_sNMDA_Z) excit_pop_B.s_NMDA_total_ = (w_neg * sum_sNMDA_A + w_pos * sum_sNMDA_B + w_neg * sum_sNMDA_Z) excit_pop_Z.s_NMDA_total_ = (1.0 * sum_sNMDA_A + 1.0 * sum_sNMDA_B + 1.0 * sum_sNMDA_Z) # set a self-recurrent synapse to introduce a delay when updating the intermediate # gating variable x syn_x_A2A = Synapses(excit_pop_A, excit_pop_A, on_pre="x += 1.", delay=0.5 * b2.ms) syn_x_A2A.connect(j="i") syn_x_B2B = Synapses(excit_pop_B, excit_pop_B, on_pre="x += 1.", delay=0.5 * b2.ms) syn_x_B2B.connect(j="i") syn_x_Z2Z = Synapses(excit_pop_Z, excit_pop_Z, on_pre="x += 1.", delay=0.5 * b2.ms) syn_x_Z2Z.connect(j="i") ############################################################################################### # Define the stimulus: two PoissonInput with time time-dependent mean. poissonStimulus2A = PoissonGroup(N_Group_A, 0. * b2.Hz) syn_Stim2A = Synapses(poissonStimulus2A, excit_pop_A, on_pre="s_AMPA+=w_ext2excit") syn_Stim2A.connect(j="i") poissonStimulus2B = PoissonGroup(N_Group_B, 0. * b2.Hz) syn_Stim2B = Synapses(poissonStimulus2B, excit_pop_B, on_pre="s_AMPA+=w_ext2excit") syn_Stim2B.connect(j="i") @network_operation(dt=stimulus_update_interval) def update_poisson_stimulus(t): if t >= t_stimulus_start and t < t_stimulus_end: offset_A = mu0_mean_stimulus_Hz * (0.5 + 0.5 * coherence_level) offset_B = mu0_mean_stimulus_Hz * (0.5 - 0.5 * coherence_level) rate_A = numpy.random.normal(offset_A, stimulus_std_Hz) rate_A = (max(0, rate_A)) * b2.Hz # avoid negative rate rate_B = numpy.random.normal(offset_B, stimulus_std_Hz) rate_B = (max(0, rate_B)) * b2.Hz poissonStimulus2A.rates = rate_A poissonStimulus2B.rates = rate_B # print("stim on. rate_A= {}, rate_B = {}".format(rate_A, rate_B)) else: # print("stim off") poissonStimulus2A.rates = 0. poissonStimulus2B.rates = 0. ############################################################################################### def get_monitors(pop, monitored_subset_size): """ Internal helper. Args: pop: monitored_subset_size: Returns: """ monitored_subset_size = min(monitored_subset_size, pop.N) idx_monitored_neurons = sample(range(pop.N), monitored_subset_size) rate_monitor = PopulationRateMonitor(pop) # record parameter: record=idx_monitored_neurons is not supported??? spike_monitor = SpikeMonitor(pop, record=idx_monitored_neurons) voltage_monitor = StateMonitor(pop, "v", record=idx_monitored_neurons) return rate_monitor, spike_monitor, voltage_monitor, idx_monitored_neurons # collect data of a subset of neurons: rate_monitor_inhib, spike_monitor_inhib, voltage_monitor_inhib, idx_monitored_neurons_inhib = \ get_monitors(inhib_pop, monitored_subset_size) rate_monitor_A, spike_monitor_A, voltage_monitor_A, idx_monitored_neurons_A = \ get_monitors(excit_pop_A, monitored_subset_size) rate_monitor_B, spike_monitor_B, voltage_monitor_B, idx_monitored_neurons_B = \ get_monitors(excit_pop_B, monitored_subset_size) rate_monitor_Z, spike_monitor_Z, voltage_monitor_Z, idx_monitored_neurons_Z = \ get_monitors(excit_pop_Z, monitored_subset_size) if stop_condition_rate is None: b2.run(max_sim_time) else: sim_sum = 0. * b2.ms sim_batch = 100. * b2.ms samples_in_batch = int(floor(sim_batch / b2.defaultclock.dt)) avg_rate_in_batch = 0 while (sim_sum < max_sim_time) and (avg_rate_in_batch < stop_condition_rate): b2.run(sim_batch) avg_A = numpy.mean(rate_monitor_A.rate[-samples_in_batch:]) avg_B = numpy.mean(rate_monitor_B.rate[-samples_in_batch:]) avg_rate_in_batch = max(avg_A, avg_B) sim_sum += sim_batch print("sim end: {}".format(time.ctime())) ret_vals = dict() ret_vals["rate_monitor_A"] = rate_monitor_A ret_vals["spike_monitor_A"] = spike_monitor_A ret_vals["voltage_monitor_A"] = voltage_monitor_A ret_vals["idx_monitored_neurons_A"] = idx_monitored_neurons_A ret_vals["rate_monitor_B"] = rate_monitor_B ret_vals["spike_monitor_B"] = spike_monitor_B ret_vals["voltage_monitor_B"] = voltage_monitor_B ret_vals["idx_monitored_neurons_B"] = idx_monitored_neurons_B ret_vals["rate_monitor_Z"] = rate_monitor_Z ret_vals["spike_monitor_Z"] = spike_monitor_Z ret_vals["voltage_monitor_Z"] = voltage_monitor_Z ret_vals["idx_monitored_neurons_Z"] = idx_monitored_neurons_Z ret_vals["rate_monitor_inhib"] = rate_monitor_inhib ret_vals["spike_monitor_inhib"] = spike_monitor_inhib ret_vals["voltage_monitor_inhib"] = voltage_monitor_inhib ret_vals["idx_monitored_neurons_inhib"] = idx_monitored_neurons_inhib return ret_vals
from brian2 import Hz, second, ms from teili import Neurons, Connections, TeiliNetwork from teili.models.neuron_models import LinearLIF as neuron_model from teili.models.synapse_models import Exponential as static_synapse_model from teili.models.synapse_models import ExponentialStdp as plastic_synapse_model from speed.teili2orca import Speed # Defining the network N = 1000 F = 8 * Hz Net = TeiliNetwork() input = PoissonGroup(N, rates=F) neurons = Neurons(2, equation_builder=neuron_model(num_inputs=1), name='neurons') S = Connections(input, neurons, equation_builder=plastic_synapse_model(), name='stdp_synapse') S.connect() S.weight = 1.0 S.w_plast = 'rand()' S.dApre = 0.01 S.taupre = 20 * ms S.taupost = 20 * ms