def create_cell(): """Create a single-compartment Hodgking-Huxley neuron with a synaptic channel. This uses the :func:`ionchannel.create_1comp_neuron` function for model creation. Returns a dict containing the neuron, the synchan and the synhandler for accessing the synapse, """ neuron = create_1comp_neuron('/neuron') #: SynChan for post synaptic neuron synchan = moose.SynChan('/neuron/synchan') synchan.Gbar = 1e-8 synchan.tau1 = 2e-3 synchan.tau2 = 2e-3 msg = moose.connect(neuron, 'channel', synchan, 'channel') #: Create SynHandler to handle spike event input and set the #: activation input of synchan synhandler = moose.SimpleSynHandler('/neuron/synhandler') synhandler.synapse.num = 1 synhandler.synapse[0].delay = 5e-3 moose.connect(synhandler, 'activationOut', synchan, 'activation') return {'neuron': neuron, 'synchan': synchan, 'synhandler': synhandler}
def make_synapse(path): """Create a synapse with two time constants.""" syn = moose.SynChan(path) syn.tau1 = 5.0 # ms syn.tau2 = 1.0 # ms syn.Gbar = 1.0 # mS syn.Ek = 0.0 synsh = moose.SimpleSynHandler(path + '/sh') synsh.synapse.num = 1 # syn.bufferTime = 1.0 # ms synsh.synapse.delay = 1.0 synsh.synapse.weight = 1.0 print(('Synapses:', len(synsh.synapse), 'w=', synsh.synapse[0].weight)) spikegen = moose.SpikeGen('%s/spike' % (syn.parent.path)) spikegen.edgeTriggered = False # Make it fire continuously when input is high spikegen.refractT = 10.0 # With this setting it will fire at 1 s / 10 ms = 100 Hz spikegen.threshold = 0.5 # This will send alternatind -1 and +1 to SpikeGen to make it fire spike_stim = moose.PulseGen('%s/spike_stim' % (syn.parent.path)) spike_stim.delay[0] = 50.0 spike_stim.level[0] = 1.0 spike_stim.width[0] = 100.0 moose.connect(spike_stim, 'output', spikegen, 'Vm') m = moose.connect(spikegen, 'spikeOut', synsh.synapse[0], 'addSpike') return syn, spikegen
def create_spine_with_receptor(compt, cell, index, frac): FaradayConst = 96485.3415 # s A / mol spineLength = 5.0e-6 spineDia = 4.0e-6 head = create_spine(compt, cell, index, frac, spineLength, spineDia, 0.0) gluR = moose.SynChan(head.path + '/gluR') gluR.tau1 = 4e-3 gluR.tau2 = 4e-3 gluR.Gbar = 1e-6 gluR.Ek = 10.0e-3 moose.connect(head, 'channel', gluR, 'channel', 'Single') caPool = moose.CaConc(head.path + '/ca') caPool.CaBasal = 1e-4 # 0.1 micromolar caPool.tau = 0.01 B = 1.0 / (FaradayConst * spineLength * spineDia * spineDia * math.pi / 4) B = B / 20.0 # scaling factor for Ca buffering caPool.B = B moose.connect(gluR, 'IkOut', caPool, 'current', 'Single') synHandler = moose.SimpleSynHandler(head.path + '/gluR/handler') synHandler.synapse.num = 1 moose.connect(synHandler, 'activationOut', gluR, 'activation', 'Single') return gluR
def make_synapses(spikegen, synchan, delay=5e-3): """ Create synapses from spikegens to synchans in a manner similar to OneToAll connection. spikegen: list of spikegen objects These are sources of synaptic event messages. synchan: list of synchan objects These are the targets of the synaptic event messages. delay: mean delay of synaptic transmission. Individual delays are normally distributed with sd=0.1*mean. """ scount = len(spikegen) for ii, sid in enumerate(synchan): s = moose.SynChan(sid) sh = moose.SimpleSynHandler( sid.path + "/synh" ) moose.connect( sh, "activationOut", s, "activation" ) sh.synapse.num = scount delay_list = np.random.normal(delay, delay*0.1, scount) # print delay_list for jj in range(scount): sh.synapse[jj].delay = delay_list[jj] # Connect all spikegens to this synchan except that from # same compartment - we assume if parents are same the two belong to the same compartment if s.parent.path != spikegen[jj].parent.path: m = moose.connect(spikegen[jj], 'spikeOut', moose.element(sh.path + '/synapse'), 'addSpike')
def make_NMDA(): if moose.exists('NMDA'): return NMDA = moose.SynChan('NMDA') NMDA.Ek = 0.0 NMDA.tau1 = 20.0e-3 NMDA.tau2 = 20.0e-3 NMDA.Gbar = 5 * SOMA_A block = moose.MgBlock('/library/NMDA/block') block.CMg = 1.2 # [Mg] in mM block.Zk = 2 block.KMg_A = 1.0 / 0.28 block.KMg_B = 1.0 / 62 moose.connect(NMDA, 'channelOut', block, 'origChannel', 'OneToOne') addmsg1 = moose.Mstring('/library/NMDA/addmsg1') addmsg1.value = '.. channel ./block channel' #Here we want to also tell the cell reader to _remove_ the original #Gk, Ek term going from the channel to the compartment, as this is # now handled by the MgBlock. #addmsg2 = moose.Mstring( 'NMDA/addmsg2' #addmsg2.value = 'DropMsg .. channel' addmsg1 = moose.Mstring('/library/NMDA/addmsg1') addmsg1.value = '.. VmOut ./block Vm' addmsg2 = moose.Mstring('/library/NMDA/addmsg2') addmsg2.value = './block IkOut ../Ca_conc current' addmsg3 = moose.Mstring('/library/NMDA/addmsg3') addmsg3.value = '.. VmOut . Vm' sh = moose.SimpleSynHandler('NMDA/sh') moose.connect(sh, 'activationOut', NMDA, 'activation') sh.numSynapses = 1 sh.synapse[0].weight = 1
def createSynapseOnCompartment(compt): FaradayConst = 96485.3415 # s A / mol length = compt.length dia = compt.diameter gluR = moose.SynChan(compt.path + '/gluR') gluR.tau1 = 4e-3 gluR.tau2 = 4e-3 gluR.Gbar = 1e-6 gluR.Ek = 10.0e-3 moose.connect(compt, 'channel', gluR, 'channel', 'Single') gluSyn = moose.SimpleSynHandler(compt.path + '/gluR/sh') moose.connect(gluSyn, 'activationOut', gluR, 'activation') gluSyn.synapse.num = 1 # Ca comes in through this channel, at least for this example. caPool = moose.CaConc(compt.path + '/ca') caPool.CaBasal = 1e-4 # 0.1 micromolar caPool.tau = 0.01 B = 1.0 / (FaradayConst * length * dia * dia * math.pi / 4) B = B / 20.0 # scaling factor for Ca buffering caPool.B = B moose.connect(gluR, 'IkOut', caPool, 'current', 'Single') # Provide a regular synaptic input. synInput = moose.SpikeGen('/n/elec/compt/synInput') synInput.refractT = 47e-3 synInput.threshold = -1.0 synInput.edgeTriggered = 0 synInput.Vm(0) syn = moose.element(gluSyn.path + '/synapse') moose.connect(synInput, 'spikeOut', syn, 'addSpike', 'Single') syn.weight = 0.2 syn.delay = 1.0e-3 return gluR
def make_NMDA( name ): if moose.exists( '/library/' + name ): return NMDA = moose.NMDAChan( '/library/' + name ) NMDA.Ek = 0.0 NMDA.tau1 = 20.0e-3 NMDA.tau2 = 20.0e-3 NMDA.Gbar = 5 * SOMA_A NMDA.CMg = 1.2 # [Mg]ext in mM NMDA.KMg_A = 1.0/0.28 NMDA.KMg_B = 1.0/62 NMDA.temperature = 300 # Temperature in Kelvin. NMDA.extCa = 1.5 # [Ca]ext in mM NMDA.intCa = 0.00008 # [Ca]int in mM NMDA.intCaScale = 1 # Scale factor from elec Ca units to mM NMDA.intCaOffset = 0.00008 # Basal [Ca]int in mM NMDA.condFraction = 0.02 # Fraction of conductance due to Ca addmsg1 = moose.Mstring( NMDA.path + '/addmsg1' ) addmsg1.value = '. ICaOut ../Ca_conc current' addmsg2 = moose.Mstring( NMDA.path + '/addmsg2' ) addmsg2.value = '../Ca_conc concOut . assignIntCa' sh = moose.SimpleSynHandler( NMDA.path + '/sh' ) moose.connect( sh, 'activationOut', NMDA, 'activation' ) sh.numSynapses = 1 sh.synapse[0].weight = 1 return NMDA
def many_ematrix_to_one_element(): """This is an example of event messages from multiple SpikeGen objects into a synchan. Create a SynChan element with 2 elements in synapse field. Create 5 SpikeGen elements. Connect alternet SpikeGen elements to synapse[0] and synapse[1] ... This is a minimal example. In real simulations the SpikeGens will be embedded in compartments representing axon terminals and the SynChans will be embedded in somatic/dendritic compartments. """ model = moose.Neutral('/model') # data = moose.Neutral('/data') synchan = moose.SynChan('/model/synchan') synh = moose.SimpleSynHandler('/model/synchan/synh') moose.connect(synh, 'activationOut', synchan, 'activation') synh.synapse.num = 2 num_spikegen = 5 spikegens = [ moose.SpikeGen('/model/spikegen_%d' % (ii)) for ii in range(num_spikegen) ] for ii in range(num_spikegen): msg = moose.connect(spikegens[ii], 'spikeOut', synh.synapse[ii % 2], 'addSpike') # synchan.synapse[ii].delay = ii * 1e-3 # synchan.synapse[ii].weight = (ii+1) * 0.1 for sg in spikegens: print(sg.path, '-->', end=' ') for m in sg.msgOut: print(moose.element(m).adjacent[sg].path)
def transformNMDAR( path ): for i in moose.wildcardFind( path + "/##/#NMDA#[ISA!=NMDAChan]" ): chanpath = i.path pa = i.parent i.name = '_temp' if ( chanpath[-3:] == "[0]" ): chanpath = chanpath[:-3] nmdar = moose.NMDAChan( chanpath ) sh = moose.SimpleSynHandler( chanpath + '/sh' ) moose.connect( sh, 'activationOut', nmdar, 'activation' ) sh.numSynapses = 1 sh.synapse[0].weight = 1 nmdar.Ek = i.Ek nmdar.tau1 = i.tau1 nmdar.tau2 = i.tau2 nmdar.Gbar = i.Gbar nmdar.CMg = 12 nmdar.KMg_A = 1.0 / 0.28 nmdar.KMg_B = 1.0 / 62 nmdar.temperature = 300 nmdar.extCa = 1.5 nmdar.intCa = 0.00008 nmdar.intCaScale = 1 nmdar.intCaOffset = 0.00008 nmdar.condFraction = 0.02 moose.delete( i ) moose.connect( pa, 'channel', nmdar, 'channel' ) caconc = moose.wildcardFind( pa.path + '/#[ISA=CaConcBase]' ) if ( len( caconc ) < 1 ): print('no caconcs found on ', pa.path) else: moose.connect( nmdar, 'ICaOut', caconc[0], 'current' ) moose.connect( caconc[0], 'concOut', nmdar, 'assignIntCa' )
def timetable_demo(): tt_array, sp_array = timetable_nparray() tt_file, sp_file = timetable_file() # Create a synchan inside a compartment to demonstrate how to use # TimeTable to send artificial spike events to a synapse. comp = moose.Compartment('/model/comp') comp.Em = -60e-3 comp.Rm = 1e9 comp.Cm = 1e-12 synchan = moose.SynChan('/model/comp/synchan') synchan.Gbar = 1e-6 synchan.Ek = 0.0 moose.connect(synchan, 'channel', comp, 'channel') synh = moose.SimpleSynHandler('/model/comp/synchan/synh') moose.connect(synh, 'activationOut', synchan, 'activation') synh.synapse.num = 1 moose.connect(tt_file, 'eventOut', moose.element(synh.path + '/synapse'), 'addSpike') # Data recording: record the `state` of the time table filled # using array. data = moose.Neutral('/data') tab_array = moose.Table('/data/tab_array') moose.connect(tab_array, 'requestOut', tt_array, 'getState') # Record the synaptic conductance for the other time table, which # is filled from a text file and sends spike events to a synchan. tab_file = moose.Table('/data/tab_file') moose.connect(tab_file, 'requestOut', synchan, 'getGk') # Scheduling moose.setClock(0, simdt) moose.setClock(1, simdt) moose.useClock(1, '/model/##[ISA=Compartment]', 'init') moose.useClock(1, '/model/##,/data/##', 'process') moose.reinit() moose.start(simtime) # Plotting pylab.subplot(2, 1, 1) pylab.plot(sp_array, np.ones(len(sp_array)), 'rx', label='spike times from numpy array') pylab.plot(np.linspace(0, simtime, len(tab_array.vector)), tab_array.vector, 'b-', label='TimeTable state') pylab.legend() pylab.subplot(2, 1, 2) pylab.plot(sp_file, np.ones(len(sp_file)), 'rx', label='spike times from file') pylab.plot(np.linspace(0, simtime, len(tab_file.vector)), tab_file.vector * 1e6, 'b-', label='Syn Gk (uS)') pylab.legend() pylab.show()
def setup_two_cells(): """ Create two cells with leaky integrate and fire compartments. Each cell is a single compartment a1 and b2. a1 is stimulated by a step current injection. The compartment a1 is connected to the compartment b2 through a synaptic channel. """ model = moose.Neutral('/model') data = moose.Neutral('/data') a1 = LIFComp('/model/a1') b2 = LIFComp(moose.copy(a1, '/model', 'b2')) a1.Vthreshold = 10e-3 a1.Vreset = 0 b2.Vthreshold = 10e-3 b2.Vreset = 0 syn = moose.SynChan('%s/syn' % (b2.path)) syn.tau1 = 1e-3 syn.tau2 = 5e-3 syn.Ek = 90e-3 synh = moose.SimpleSynHandler(syn.path + '/synh') moose.connect(synh, 'activationOut', syn, 'activation') synh.synapse.num += 1 # syn.numSynapses = 1 synh.synapse.delay = delayMax moose.connect(b2, 'channel', syn, 'channel') ## Single message works most of the time but occassionally gives a ## core dump # m = moose.connect(a1.spikegen, 'spikeOut', # syn.synapse.vec, 'addSpike') ## With Sparse message and random connectivity I did not get core ## dump. m = moose.connect(a1.spikegen, 'spikeOut', synh.synapse.vec, 'addSpike', 'Sparse') m.setRandomConnectivity(1.0, 1) stim = moose.PulseGen('/model/stim') stim.delay[0] = 100e-3 stim.width[0] = 1e3 stim.level[0] = 11e-9 moose.connect(stim, 'output', a1, 'injectMsg') tables = [] data = moose.Neutral('/data') for c in moose.wildcardFind('/##[ISA=Compartment]'): tab = moose.Table('%s/%s_Vm' % (data.path, c.name)) moose.connect(tab, 'requestOut', c, 'getVm') tables.append(tab) syntab = moose.Table('%s/%s' % (data.path, 'Gk')) moose.connect(syntab, 'requestOut', syn, 'getGk') tables.append(syntab) synh.synapse[0].delay = 1e-3 syn.Gbar = 1e-6 return tables
def addSynChan(compname, synparams): synchan = moose.SynChan(compname.path + '/' + synparams['name']) synchan.Gbar = synparams['Gbar'] synchan.tau1 = synparams['tau1'] synchan.tau2 = synparams['tau2'] synchan.Ek = synparams['erev'] msg = moose.connect(compname, 'channel', synchan, 'channel') sh = moose.SimpleSynHandler(synchan.path + '/' + synparams['name']) moose.connect(sh, 'activationOut', synchan, 'activation') return sh
def connect_two_intfires(): """Connect two IntFire neurons so that spike events in one gets transmitted to synapse of the other.""" if1 = moose.IntFire('if1') if2 = moose.IntFire('if2') sf1 = moose.SimpleSynHandler('if1/sh') moose.connect(sf1, 'activationOut', if1, 'activation') sf1.synapse.num = 1 syn1 = moose.element(sf1.synapse) # Connect the spike message of if2 to the first synapse on if1 moose.connect(if2, 'spikeOut', syn1, 'addSpike')
def readSynapseML(self, synapseElement, units="SI units"): if 'Physiological Units' in units: # see pg 219 (sec 13.2) of Book of Genesis Vfactor = 1e-3 # V from mV Tfactor = 1e-3 # s from ms Gfactor = 1e-3 # S from mS elif 'SI Units' in units: Vfactor = 1.0 Tfactor = 1.0 Gfactor = 1.0 else: pu.fatal("Wrong units %s exiting ..." % units) sys.exit(1) if not moose.exists('/library'): moose.Neutral('/library') synname = synapseElement.attrib['name'] if utils.neuroml_debug: pu.info("Loading synapse : %s into /library" % synname) moosesynapse = moose.SynChan('/library/' + synname) doub_exp_syn = synapseElement.find('./{' + self.cml + '}doub_exp_syn') moosesynapse.Ek = float( doub_exp_syn.attrib['reversal_potential']) * Vfactor moosesynapse.Gbar = float( doub_exp_syn.attrib['max_conductance']) * Gfactor moosesynapse.tau1 = float( doub_exp_syn.attrib['rise_time']) * Tfactor # seconds moosesynapse.tau2 = float( doub_exp_syn.attrib['decay_time']) * Tfactor # seconds ## The delay and weight can be set only after connecting a spike event generator. ## delay and weight are arrays: multiple event messages can be connected to a single synapse ## graded synapses are not supported by neuroml, so set to False here, ## see my Demo/neuroml/lobster_pyloric/STG_net.py for how to still have graded synapses moosesynapse_graded = moose.Mstring(moosesynapse.path + '/graded') moosesynapse_graded.value = 'False' moosesynapse_mgblock = moose.Mstring(moosesynapse.path + '/mgblockStr') moosesynapse_mgblock.value = 'False' ## check if STDP synapse is present or not stdp_syn = synapseElement.find('./{' + self.cml + '}stdp_syn') if stdp_syn is None: moosesynhandler = moose.SimpleSynHandler('/library/' + synname + '/handler') else: moosesynhandler = moose.STDPSynHandler('/library/' + synname + '/handler') moosesynhandler.aPlus0 = float(stdp_syn.attrib['del_weight_ltp']) moosesynhandler.aMinus0 = float(stdp_syn.attrib['del_weight_ltd']) moosesynhandler.tauPlus = float(stdp_syn.attrib['tau_ltp']) moosesynhandler.tauMinus = float(stdp_syn.attrib['tau_ltd']) moosesynhandler.weightMax = float( stdp_syn.attrib['max_syn_weight']) moosesynhandler.weightMin = 0.0 ## connect the SimpleSynHandler or the STDPSynHandler to the SynChan (double exp) moose.connect(moosesynhandler, 'activationOut', moosesynapse, 'activation')
def make_GABA( name ): if moose.exists( '/library/' + name ): return GABA = moose.SynChan( '/library/' + name ) GABA.Ek = -0.065 # V GABA.tau1 = 4.0e-3 # s GABA.tau2 = 9.0e-3 # s sh = moose.SimpleSynHandler( GABA.path + '/sh' ) moose.connect( sh, 'activationOut', GABA, 'activation' ) sh.numSynapses = 1 sh.synapse[0].weight = 1
def connect_spikegen(): """Connect a SpikeGen object to an IntFire neuron such that spike events in spikegen get transmitted to the synapse of the IntFire neuron.""" if3 = moose.IntFire('if3') sf3 = moose.SimpleSynHandler('if3/sh') moose.connect(sf3, 'activationOut', if3, 'activation') sf3.synapse.num = 1 sg = moose.SpikeGen('sg') syn = moose.element(sf3.synapse) moose.connect(sg, 'spikeOut', syn, 'addSpike')
def make_glu(): if moose.exists('glu'): return glu = moose.SynChan('glu') glu.Ek = 0.0 glu.tau1 = 2.0e-3 glu.tau2 = 9.0e-3 glu.Gbar = 40 * SOMA_A sh = moose.SimpleSynHandler('glu/sh') moose.connect(sh, 'activationOut', glu, 'activation') sh.numSynapses = 1 sh.synapse[0].weight = 1
def make_model(): sinePeriod = 50 maxFiringRate = 10 refractT = 0.05 for i in range(20): moose.setClock(i, dt) ############### Create objects ############### stim = moose.StimulusTable('stim') spike = moose.RandSpike('spike') syn = moose.SimpleSynHandler('syn') fire = moose.IntFire('fire') stats1 = moose.SpikeStats('stats1') stats2 = moose.Stats('stats2') plots = moose.Table('plots') plot1 = moose.Table('plot1') plot2 = moose.Table('plot2') plotf = moose.Table('plotf') ############### Set up parameters ############### stim.vector = [ maxFiringRate * numpy.sin(x * 2 * numpy.pi / sinePeriod) for x in range(sinePeriod) ] stim.startTime = 0 stim.stopTime = sinePeriod stim.loopTime = sinePeriod stim.stepSize = 0 stim.stepPosition = 0 stim.doLoop = 1 spike.refractT = refractT syn.synapse.num = 1 syn.synapse[0].weight = 1 syn.synapse[0].delay = 0 fire.thresh = 100 # Don't want it to spike, just to integrate fire.tau = 1.0 / maxFiringRate stats1.windowLength = int(1 / dt) stats2.windowLength = int(1 / dt) ############### Connect up circuit ############### moose.connect(stim, 'output', spike, 'setRate') moose.connect(spike, 'spikeOut', syn.synapse[0], 'addSpike') moose.connect(spike, 'spikeOut', stats1, 'addSpike') moose.connect(syn, 'activationOut', fire, 'activation') moose.connect(stats2, 'requestOut', fire, 'getVm') moose.connect(plots, 'requestOut', stim, 'getOutputValue') moose.connect(plot1, 'requestOut', stats1, 'getWmean') moose.connect(plot2, 'requestOut', stats2, 'getWmean') moose.connect(plotf, 'requestOut', fire, 'getVm')
def make_glu( name ): if moose.exists( '/library/' + name ): return glu = moose.SynChan( '/library/' + name ) glu.Ek = 0.0 glu.tau1 = 2.0e-3 glu.tau2 = 9.0e-3 sh = moose.SimpleSynHandler( glu.path + '/sh' ) moose.connect( sh, 'activationOut', glu, 'activation' ) sh.numSynapses = 1 sh.synapse[0].weight = 1 return glu
def buildSyn( name, compt, Ek, tau1, tau2, Gbar, CM ): syn = moose.SynChan( compt.path + '/' + name ) syn.Ek = Ek syn.tau1 = tau1 syn.tau2 = tau2 syn.Gbar = Gbar * compt.Cm / CM moose.connect( compt, 'channel', syn, 'channel' ) sh = moose.SimpleSynHandler( syn.path + '/sh' ) moose.connect( sh, 'activationOut', syn, 'activation' ) sh.numSynapses = 1 sh.synapse[0].weight = 1 return syn
def createSynapse(comp, numInputs): synchan = moose.SynChan(comp.path + "/synchan") synchan.Gbar = 1e-8 synchan.tau1 = 2e-3 synchan.tau2 = 2e-3 synchan.Ek = -0.01 moose.connect(comp, "channel", synchan, "channel") sh = moose.SimpleSynHandler(comp.path + "/synhandler") moose.connect(sh, "activationOut", synchan, "activation") sh.synapse.num = numInputs for i in range(numInputs): sh.synapse[i].delay = 5e-3 return sh
def setup_synapse(): """Create an intfire object and create two synapses on it.""" if4 = moose.IntFire('if4') sf4 = moose.SimpleSynHandler('if4/sh') sg1 = moose.SpikeGen('sg1') sg2 = moose.SpikeGen('sg2') sf4.synapse.num = 2 # set synapse count to 2 sf4.synapse[0].weight = 0.5 sf4.synapse[0].delay = 1e-3 sf4.synapse[1].weight = 2.0 sf4.synapse[1].delay = 2e-3 moose.connect(sg1, 'spikeOut', sf4.synapse[0], 'addSpike') moose.connect(sg2, 'spikeOut', sf4.synapse[1], 'addSpike')
def _setup_network(self): ## Set up the neurons without connections ExcInhNetBase._setup_network(self) ## Now, add in the connections... ## Each pre-synaptic spike cause Vm of post-neuron to rise by ## synaptic weight in one time step i.e. delta-fn synapse. ## Since LIF neuron is derived from Compartment class, ## conductance-based synapses (SynChan class) can also be used. ## E to E synapses can be plastic ## Two ways to do this: ## 1) Each LIF neuron has one incoming postsynaptic SynHandler, ## which collects the activation from all presynaptic neurons, ## but then a common Ca pool is used. ## 2) Each LIF neuron has multiple postsyanptic SynHandlers, ## one for each pre-synaptic neuron, i.e. one per synapse, ## then each synapse has a different Ca pool. ## Here we go with option 2) as per Higgins et al 2014 (Brunel private email) ## separate SynHandler per EE synapse, thus NmaxExc*excC if CaPlasticity: self.synsEE = moose.GraupnerBrunel2012CaPlasticitySynHandler( \ '/network/synsEE', self.NmaxExc*self.excC ) else: self.synsEE = moose.SimpleSynHandler( \ '/network/synsEE', self.NmaxExc*self.excC ) moose.useClock(0, '/network/synsEE', 'process') ## I to E synapses are not plastic self.synsIE = moose.SimpleSynHandler('/network/synsIE', self.NmaxExc) ## all synapses to I neurons are not plastic self.synsI = moose.SimpleSynHandler('/network/synsI', self.N - self.NmaxExc) ## connect all SynHandlers to their respective neurons moose.useClock(0, '/network/synsIE', 'process') moose.useClock(0, '/network/synsI', 'process')
def plain_synconn(synchan, presyn, syn_delay): shname = synchan.path + '/SH' sh = moose.SimpleSynHandler(shname) if sh.synapse.num == 0: moose.connect(sh, 'activationOut', synchan, 'activation') jj = sh.synapse.num sh.synapse.num = sh.synapse.num + 1 sh.synapse[jj].delay = syn_delay log.debug('SYNAPSE: {} index {} num {} delay {}', synchan.path, jj, sh.synapse.num, sh.synapse[jj].delay) #It is possible to set the synaptic weight here. if presyn.className == 'TimeTable': moose.connect(presyn, 'eventOut', sh.synapse[jj], 'addSpike') else: moose.connect(presyn, 'spikeOut', sh.synapse[jj], 'addSpike')
def addoneSynChan(chanpath, syncomp, gbar, calYN, GbarVar): proto = moose.element('/library/' + chanpath) log.debug('adding channel {} to {.path} from {.path}', chanpath, syncomp, proto) synchan = moose.copy(proto, syncomp, chanpath)[0] synchan.Gbar = np.random.normal(gbar, gbar * GbarVar) #bidirectional connection from synchan to compartment when not NMDA: m = moose.connect(syncomp, 'channel', synchan, 'channel') #create and connect synhandler shname = synchan.path + '/SH' sh = moose.SimpleSynHandler(shname) moose.connect(sh, 'activationOut', synchan, 'activation') return synchan
def create_model(): """Create two single compartmental neurons, neuron_A is the presynaptic neuron and neuron_B is the postsynaptic neuron. 1. The presynaptic cell's Vm is monitored by a SpikeGen object. Whenever the Vm crosses the threshold of the spikegen, it sends out a spike event message. 2. This is event message is received by a SynHandler, which passes the event as activation parameter to a SynChan object. 3. The SynChan, which is connected to the postsynaptic neuron as a channel, updates its conductance based on the activation parameter. 4. The change in conductance due to a spike may evoke an action potential in the post synaptic neuron. """ model = moose.Neutral('/model') nrn_a = create_1comp_neuron('/model/neuron_A')[0] nrn_b = create_1comp_neuron('/model/neuron_B')[0] #: SynChan for post synaptic neuron synchan = moose.SynChan('/model/neuron_B/synchan') synchan.Gbar = 1e-8 synchan.tau1 = 2e-3 synchan.tau2 = 2e-3 msg = moose.connect(nrn_b, 'channel', synchan, 'channel') #: Create SynHandler to handle spike event input and set the #: activation input of synchan synhandler = moose.SimpleSynHandler('/model/neuron_B/synhandler') synhandler.synapse.num = 1 synhandler.synapse[0].delay = 5e-3 moose.connect(synhandler, 'activationOut', synchan, 'activation') #: SpikeGen detects when presynaptic Vm crosses threshold and #: sends out a spike event spikegen = moose.SpikeGen('/model/neuron_A/spikegen') spikegen.threshold = 0.0 msg = moose.connect(nrn_a, 'VmOut', spikegen, 'Vm') msg = moose.connect(spikegen, 'spikeOut', synhandler.synapse[0], 'addSpike') return { 'presynaptic': nrn_a, 'postsynaptic': nrn_b, 'spikegen': spikegen, 'synchan': synchan, 'synhandler': synhandler }
def main(): """This is to show a 'raw' way of traversing messages.""" connectionProbability = 0.5 net = moose.IntFire('/net1', 10) syn = moose.SimpleSynHandler( '/net1/sh', 10 ) moose.connect( syn, 'activationOut', net, 'activation', 'OneToOne' ) synapse = syn.synapse.vec mid = moose.connect(net, 'spikeOut', synapse, 'addSpike', 'Sparse') # This creates a `Sparse` message from `spikeOut` source of net to `addSpike` destination on synapse. msg = moose.element(mid) msg.setRandomConnectivity(connectionProbability, 5) for n in net.vec: print(('Messages from %s.spikeOut' % (n.path))) node = moose.element(n) for dest, df in zip(node.msgDests['spikeOut'], node.msgDestFunctions['spikeOut']): print(('\t--> %s.%s' % (dest.path, df)))
def createSynapse(comp, name, numInputs, Ek, gbar=1e-9, tau1=1e-3, tau2=5e-3): path = comp.path + "/" + name if (moose.exists(path + "synchan")): return moose.element(path + "synhandler") synchan = moose.SynChan(path + "synchan") synchan.Gbar = gbar synchan.tau1 = tau1 synchan.tau2 = tau2 synchan.Ek = Ek moose.connect(comp, "channel", synchan, "channel") sh = moose.SimpleSynHandler(path + "synhandler") moose.connect(sh, "activationOut", synchan, "activation") sh.synapse.num = numInputs for i in range(numInputs): sh.synapse[i].delay = 5e-3 return sh
def __init__(self, *args): moose.SynChan.__init__(self, *args) self.Ek = -80e-3 # V # For event based synapses, I had a strength of 5e-6 S # to compensate for event-based, # but for the original graded synapses, 5e-9 S is correct. self.Gbar = 5e-9 # S # set weight on connecting the network self.tau1 = 100e-3 # s # this is Vpre dependent (see below) self.tau2 = 0.0 # single first order equation Vth = -35e-3 # V Delta = 5e-3 # V ######## Graded synapse activation inhsyntable = moose.Interpol(self.path + "/graded_table") graded = moose.Mstring(self.path + '/graded') graded.value = 'True' mgblock = moose.Mstring(self.path + '/mgblockStr') mgblock.value = 'False' # also needs a synhandler moosesynhandler = moose.SimpleSynHandler(self.path + '/handler') # connect the SimpleSynHandler or the STDPSynHandler to the SynChan (double exp) moose.connect(moosesynhandler, 'activationOut', self, 'activation') # ds/dt = s_inf/tau - s/tau = A - Bs # where A=s_inf/tau is activation, B is 1/tau # Fill up the activation and tau tables # Graded synapse tau inhtautable = moose.Interpol(self.path + "/tau_table") inhtautable.xmin = -70e-3 # V inhtautable.xmax = 0e-3 # V tau = [self.tau1] # at -70 mV tau.extend( [self.tau1*(1. - 1./(1+math.exp((Vth-vm)/Delta))) \ for vm in arange(-70e-3,0.00001e-3,70e-3/1000.)] ) inhtautable.vector = array(tau) inhtautable.connect("lookupOut", self, "setTau1") # Graded synapse activation inhsyntable.xmin = -70e-3 # V inhsyntable.xmax = 0e-3 # V act = [0.0] # at -70 mV act.extend( [1/(1+math.exp((Vth-vm)/Delta)) \ for vm in arange(-70e-3,0.00001e-3,70e-3/1000.)] ) act = array(act) / array( tau) # element-wise division # NOTE: A = s_inf/tau inhsyntable.vector = array(act) inhsyntable.connect("lookupOut", self, "activation")
def make_synapse(path): """Create a synapse with two time constants. Connect a spikegen to the synapse. Create a pulsegen to drive the spikegen.""" syn = moose.SynChan(path) syn.tau1 = 5.0 # ms syn.tau2 = 1.0 # ms syn.Gk = 1.0 # mS syn.Ek = 0.0 ## NOTE: This is old implementation. #syn.synapse.num = 1 ## syn.bufferTime = 1.0 # ms #syn.synapse.delay = 1.0 #syn.synapse.weight = 1.0 #print 'Synapses:', len(syn.synapse), 'w=', syn.synapse[0].weight # IN new implementation, there is SimpleSynHandler class which takes cares # of multiple synapses. Class SynChan does not have any .synapse field. synH = moose.SimpleSynHandler('%s/SynHandler' % path) synH.synapse.num = 1 ## syn.bufferTime = 1.0 # ms synH.synapse.delay = 1.0 synH.synapse.weight = 1.0 synH.connect('activationOut', syn, 'activation') print(('Synapses:', len(synH.synapse), 'w=', synH.synapse[0].weight)) spikegen = moose.SpikeGen('%s/spike' % (syn.parent.path)) spikegen.edgeTriggered = False # Make it fire continuously when input is high spikegen.refractT = 10.0 # With this setting it will fire at 1 s / 10 ms = 100 Hz spikegen.threshold = 0.5 # This will send alternatind -1 and +1 to SpikeGen to make it fire spike_stim = moose.PulseGen('%s/spike_stim' % (syn.parent.path)) spike_stim.delay[0] = 1.0 spike_stim.level[0] = 1.0 spike_stim.width[0] = 100.0 moose.connect(spike_stim, 'output', spikegen, 'Vm') m = moose.connect(spikegen, 'spikeOut', synH.synapse.vec, 'addSpike', 'Sparse') m.setRandomConnectivity(1.0, 1) m = moose.connect(spikegen, 'spikeOut', synH.synapse[0], 'addSpike') # this causes segfault return syn, spikegen