.. currentmodule:: brian2 .. Kremer_et_al_2011_barrel_cortex: Example: Kremer_et_al_2011_barrel_cortex ======================================== .. only:: html .. |launchbinder| image:: http://mybinder.org/badge.svg .. _launchbinder: https://mybinder.org/v2/gh/brian-team/brian2-binder/master?filepath=examples/frompapers/Kremer_et_al_2011_barrel_cortex.ipynb .. note:: You can launch an interactive, editable version of this example without installing any local files using the Binder service (although note that at some times this may be slow or fail to open): |launchbinder|_ Late Emergence of the Whisker Direction Selectivity Map in the Rat Barrel Cortex. Kremer Y, Leger JF, Goodman DF, Brette R, Bourdieu L (2011). J Neurosci 31(29):10689-700. Development of direction maps with pinwheels in the barrel cortex. Whiskers are deflected with random moving bars. N.B.: network construction can be long. :: from brian2 import * import time t1 = time.time() # PARAMETERS # Neuron numbers M4, M23exc, M23inh = 22, 25, 12 # size of each barrel (in neurons) N4, N23exc, N23inh = M4**2, M23exc**2, M23inh**2 # neurons per barrel barrelarraysize = 5 # Choose 3 or 4 if memory error Nbarrels = barrelarraysize**2 # Stimulation stim_change_time = 5*ms Fmax = .5/stim_change_time # maximum firing rate in layer 4 (.5 spike / stimulation) # Neuron parameters taum, taue, taui = 10*ms, 2*ms, 25*ms El = -70*mV Vt, vt_inc, tauvt = -55*mV, 2*mV, 50*ms # adaptive threshold # STDP taup, taud = 5*ms, 25*ms Ap, Ad= .05, -.04 # EPSPs/IPSPs EPSP, IPSP = 1*mV, -1*mV EPSC = EPSP * (taue/taum)**(taum/(taue-taum)) IPSC = IPSP * (taui/taum)**(taum/(taui-taum)) Ap, Ad = Ap*EPSC, Ad*EPSC # Layer 4, models the input stimulus eqs_layer4 = ''' rate = int(is_active)*clip(cos(direction - selectivity), 0, inf)*Fmax: Hz is_active = abs((barrel_x + 0.5 - bar_x) * cos(direction) + (barrel_y + 0.5 - bar_y) * sin(direction)) < 0.5: boolean barrel_x : integer # The x index of the barrel barrel_y : integer # The y index of the barrel selectivity : 1 # Stimulus parameters (same for all neurons) bar_x = cos(direction)*(t - stim_start_time)/(5*ms) + stim_start_x : 1 (shared) bar_y = sin(direction)*(t - stim_start_time)/(5*ms) + stim_start_y : 1 (shared) direction : 1 (shared) # direction of the current stimulus stim_start_time : second (shared) # start time of the current stimulus stim_start_x : 1 (shared) # start position of the stimulus stim_start_y : 1 (shared) # start position of the stimulus ''' layer4 = NeuronGroup(N4*Nbarrels, eqs_layer4, threshold='rand() < rate*dt', method='euler', name='layer4') layer4.barrel_x = '(i // N4) % barrelarraysize + 0.5' layer4.barrel_y = 'i // (barrelarraysize*N4) + 0.5' layer4.selectivity = '(i%N4)/(1.0*N4)*2*pi' # for each barrel, selectivity between 0 and 2*pi stimradius = (11+1)*.5 # Chose a new randomly oriented bar every 60ms runner_code = ''' direction = rand()*2*pi stim_start_x = barrelarraysize / 2.0 - cos(direction)*stimradius stim_start_y = barrelarraysize / 2.0 - sin(direction)*stimradius stim_start_time = t ''' layer4.run_regularly(runner_code, dt=60*ms, when='start') # Layer 2/3 # Model: IF with adaptive threshold eqs_layer23 = ''' dv/dt=(ge+gi+El-v)/taum : volt dge/dt=-ge/taue : volt dgi/dt=-gi/taui : volt dvt/dt=(Vt-vt)/tauvt : volt # adaptation barrel_idx : integer x : 1 # in "barrel width" units y : 1 # in "barrel width" units ''' layer23 = NeuronGroup(Nbarrels*(N23exc+N23inh), eqs_layer23, threshold='v>vt', reset='v = El; vt += vt_inc', refractory=2*ms, method='euler', name='layer23') layer23.v = El layer23.vt = Vt # Subgroups for excitatory and inhibitory neurons in layer 2/3 layer23exc = layer23[:Nbarrels*N23exc] layer23inh = layer23[Nbarrels*N23exc:] # Layer 2/3 excitatory # The units for x and y are the width/height of a single barrel layer23exc.x = '(i % (barrelarraysize*M23exc)) * (1.0/M23exc)' layer23exc.y = '(i // (barrelarraysize*M23exc)) * (1.0/M23exc)' layer23exc.barrel_idx = 'floor(x) + floor(y)*barrelarraysize' # Layer 2/3 inhibitory layer23inh.x = 'i % (barrelarraysize*M23inh) * (1.0/M23inh)' layer23inh.y = 'i // (barrelarraysize*M23inh) * (1.0/M23inh)' layer23inh.barrel_idx = 'floor(x) + floor(y)*barrelarraysize' print("Building synapses, please wait...") # Feedforward connections (plastic) feedforward = Synapses(layer4, layer23exc, model='''w:volt dA_source/dt = -A_source/taup : volt (event-driven) dA_target/dt = -A_target/taud : volt (event-driven)''', on_pre='''ge+=w A_source += Ap w = clip(w+A_target, 0*volt, EPSC)''', on_post=''' A_target += Ad w = clip(w+A_source, 0*volt, EPSC)''', name='feedforward') # Connect neurons in the same barrel with 50% probability feedforward.connect('(barrel_x_pre + barrelarraysize*barrel_y_pre) == barrel_idx_post', p=0.5) feedforward.w = EPSC*.5 print('excitatory lateral') # Excitatory lateral connections recurrent_exc = Synapses(layer23exc, layer23, model='w:volt', on_pre='ge+=w', name='recurrent_exc') recurrent_exc.connect(p='.15*exp(-.5*(((x_pre-x_post)/.4)**2+((y_pre-y_post)/.4)**2))') recurrent_exc.w['jexcitatory recurrent_exc.w['j>=Nbarrels*N23exc'] = EPSC # excitatory->inhibitory # Inhibitory lateral connections print('inhibitory lateral') recurrent_inh = Synapses(layer23inh, layer23exc, on_pre='gi+=IPSC', name='recurrent_inh') recurrent_inh.connect(p='exp(-.5*(((x_pre-x_post)/.2)**2+((y_pre-y_post)/.2)**2))') if get_device().__class__.__name__=='RuntimeDevice': print('Total number of connections') print('feedforward: %d' % len(feedforward)) print('recurrent exc: %d' % len(recurrent_exc)) print('recurrent inh: %d' % len(recurrent_inh)) t2 = time.time() print("Construction time: %.1fs" % (t2 - t1)) run(5*second, report='text') # Calculate the preferred direction of each cell in layer23 by doing a # vector average of the selectivity of the projecting layer4 cells, weighted # by the synaptic weight. _r = bincount(feedforward.j, weights=feedforward.w * cos(feedforward.selectivity_pre)/feedforward.N_incoming, minlength=len(layer23exc)) _i = bincount(feedforward.j, weights=feedforward.w * sin(feedforward.selectivity_pre)/feedforward.N_incoming, minlength=len(layer23exc)) selectivity_exc = (arctan2(_r, _i) % (2*pi))*180./pi scatter(layer23.x[:Nbarrels*N23exc], layer23.y[:Nbarrels*N23exc], c=selectivity_exc[:Nbarrels*N23exc], edgecolors='none', marker='s', cmap='hsv') vlines(np.arange(barrelarraysize), 0, barrelarraysize, 'k') hlines(np.arange(barrelarraysize), 0, barrelarraysize, 'k') clim(0, 360) colorbar() show() .. image:: ../resources/examples_images/frompapers.Kremer_et_al_2011_barrel_cortex.1.png