def _setup_network(self):
     """Sets up the network (_init_network is enough)"""
     self.network = moose.LIF('network', self.N)
     moose.le('/network')
     self.network.vec.Em = self.el
     self.network.vec.thresh = self.vt
     self.network.vec.refractoryPeriod = self.refrT
     self.network.vec.Rm = self.Rm
     self.network.vec.vReset = self.vr
     self.network.vec.Cm = self.Cm
     self.network.vec.inject = self.Iinject
Beispiel #2
0
 def _setup_network(self):
     """Sets up the network (_init_network is enough)"""
     self.network = moose.LIF( 'network', self.N );
     moose.le( '/network' )
     self.network.vec.Em = self.el
     self.network.vec.thresh = self.vt
     self.network.vec.refractoryPeriod = self.refrT
     self.network.vec.Rm = self.Rm
     self.network.vec.vReset = self.vr
     self.network.vec.Cm = self.Cm
     if not noiseInj:
         self.network.vec.inject = self.Iinject
     else:
         ## inject a constant + noisy current
         ## values are set in self.simulate()
         self.noiseTables = moose.StimulusTable('noiseTables',self.N)
         moose.connect( self.noiseTables, 'output', \
             self.network, 'setInject', 'OneToOne')
Beispiel #3
0
def setupmodel(modelpath, iaf_Rm, iaf_Cm, pulse_interval):
    """Create a LeakyIaF neuron under `modelpath` and a synaptic
    channel (SynChan) in it. Create a spike generator stimulated by a
    pulse generator to give input to the synapse.
    """
    model_container = moose.Neutral(modelpath)
    data_container = moose.Neutral(datapath)
    iaf = moose.LIF('%s/iaf' % (modelpath))
    iaf.Rm = iaf_Rm
    iaf.Cm = iaf_Cm
    iaf.initVm = -0.070
    iaf.Em = -0.065
    #iaf.Vreset = -0.070
    iaf.thresh = -0.055
    # iaf.refractoryPeriod = 0.005
    syn = moose.SynChan('%s/syn' % (iaf.path))
    synh = moose.SimpleSynHandler(syn.path + '/synh')
    moose.connect(synh, 'activationOut', syn, 'activation')
    synh.synapse.num = 1
    synh.synapse[0].delay = 0.01
    syn.Ek = 0.0
    syn.Gbar = 1.0
    moose.connect(syn, 'channel', iaf, 'channel')
    moose.connect(iaf, 'VmOut', syn, 'Vm')
    sg = moose.SpikeGen('%s/spike' % (modelpath))
    sg.threshold = 0.1
    moose.connect(sg, 'spikeOut', synh.synapse[0], 'addSpike')
    pg = moose.PulseGen('%s/pulse' % (modelpath))
    pg.delay[0] = pulse_interval
    pg.width[0] = 1e-3
    pg.level[0] = 0.5
    moose.connect(pg, 'output', sg, 'Vm')
    return {
        'model': model_container,
        'iaf': iaf,
        'synchan': syn,
        'spikegen': sg,
        'pulsegen': pg
    }
Beispiel #4
0
# ###########################################

## Leaky integrate and fire neuron
Vrest = -65e-3  # V      # resting potential
Vt_base = -45e-3  # V    # threshold
Vreset = -55e-3  # V     # in current steps, Vreset is same as pedestal
R = 1e8  # Ohm
tau = 10e-3  # s
refrT = 2e-3  # s

# ###########################################
# Initialize neuron group
# ###########################################

## two neurons: index 0 will be presynaptic, 1 will be postsynaptic
network = moose.LIF('network', 2)
moose.le('/network')
network.vec.Em = Vrest
network.vec.thresh = Vt_base
network.vec.refractoryPeriod = refrT
network.vec.Rm = R
network.vec.vReset = Vreset
network.vec.Cm = tau / R
network.vec.inject = 0.
network.vec.initVm = Vrest

#############################################
# Ca Plasticity parameters: synapses (not for ExcInhNetBase)
#############################################

### Cortical slice values -- Table Suppl 2 in Graupner & Brunel 2012
def test_GB2012_STDP():
    """
    Simulate a pseudo-STDP protocol and plot the STDP kernel
    that emerges from Ca plasticity of Graupner and Brunel 2012.

    Author: Aditya Gilra, NCBS, Bangalore, October, 2014.
    """

    # ###########################################
    # Neuron models
    # ###########################################

    ## Leaky integrate and fire neuron
    Vrest = -65e-3  # V      # resting potential
    Vt_base = -45e-3  # V    # threshold
    Vreset = -55e-3  # V     # in current steps, Vreset is same as pedestal
    R = 1e8  # Ohm
    tau = 10e-3  # s
    refrT = 2e-3  # s

    # ###########################################
    # Initialize neuron group
    # ###########################################

    ## two neurons: index 0 will be presynaptic, 1 will be postsynaptic
    network = moose.LIF('network', 2)
    moose.le('/network')
    network.vec.Em = Vrest
    network.vec.thresh = Vt_base
    network.vec.refractoryPeriod = refrT
    network.vec.Rm = R
    network.vec.vReset = Vreset
    network.vec.Cm = tau / R
    network.vec.inject = 0.
    network.vec.initVm = Vrest

    tauCa = 20e-3
    tauSyn = 150.0
    CaPre = 1.0
    CaPost = 2.0
    delayD = 13.7e-3
    thetaD = 1.0
    thetaP = 1.3
    gammaD = 200.0
    gammaP = 321.808
    J = 5e-3  # V
    weight = 0.5
    bistable = True

    syn = moose.GraupnerBrunel2012CaPlasticitySynHandler('/network/syn')
    syn.numSynapses = 1
    moose.connect(syn, 'activationOut', network.vec[1], 'activation')

    # synapse from presynaptic neuron
    moose.connect(network.vec[0], 'spikeOut', syn.synapse[0], 'addSpike')

    # post-synaptic spikes also needed for STDP
    moose.connect(network.vec[1], 'spikeOut', syn, 'addPostSpike')

    syn.synapse[0].delay = 0.0
    syn.synapse[0].weight = weight
    syn.CaInit = 0.0
    syn.tauCa = tauCa
    syn.tauSyn = tauSyn
    syn.CaPre = CaPre
    syn.CaPost = CaPost
    syn.delayD = delayD
    syn.thetaD = thetaD
    syn.thetaP = thetaP
    syn.gammaD = gammaD
    syn.gammaP = gammaP
    syn.weightScale = J
    syn.weightMax = 1.0
    syn.weightMin = 0.

    syn.noisy = True
    syn.noiseSD = 1.3333
    syn.bistable = bistable

    # ###########################################
    # Setting up tables
    # ###########################################

    Vms = moose.Table('/plotVms', 2)
    moose.connect(network, 'VmOut', Vms, 'input', 'OneToOne')
    spikes = moose.Table('/plotSpikes', 2)
    moose.connect(network, 'spikeOut', spikes, 'input', 'OneToOne')
    CaTable = moose.Table('/plotCa', 1)
    moose.connect(CaTable, 'requestOut', syn, 'getCa')
    WtTable = moose.Table('/plotWeight', 1)
    moose.connect(WtTable, 'requestOut', syn.synapse[0], 'getWeight')

    dt = 1e-3
    moose.useClock(0, '/network/syn', 'process')
    moose.useClock(1, '/network', 'process')
    moose.useClock(2, '/plotSpikes', 'process')
    moose.useClock(3, '/plotVms', 'process')
    moose.useClock(3, '/plotCa', 'process')
    moose.useClock(3, '/plotWeight', 'process')
    moose.setClock(0, dt)
    moose.setClock(1, dt)
    moose.setClock(2, dt)
    moose.setClock(3, dt)
    moose.setClock(9, dt)
    moose.reinit()

    # function to make the aPlus and aMinus settle to equilibrium values
    settletime = 10e-3  # s

    def reset_settle():
        """ Call this between every pre-post pair
        to reset the neurons and make them settle to rest.
        """
        syn.synapse[0].weight = weight
        syn.Ca = 0.0
        moose.start(settletime)
        # Ca gets a jump at pre-spike+delayD
        # So this event can occur during settletime
        # So set Ca and weight once more after settletime
        syn.synapse[0].weight = weight
        syn.Ca = 0.0

    # function to inject a sharp current pulse to make neuron spike
    # immediately at a given time step
    def make_neuron_spike(nrnidx, I=1e-7, duration=1e-3):
        """ Inject a brief current pulse to
        make a neuron spike
        """
        network.vec[nrnidx].inject = I
        moose.start(duration)
        network.vec[nrnidx].inject = 0.

    dwlist_neg = []
    ddt = 10e-3  # s
    # since CaPlasticitySynHandler is event based
    # multiple pairs are needed for Ca to be registered above threshold
    # Values from Fig 2, last line of legend
    numpairs = 60  # number of spike parts per deltat
    t_between_pairs = 1.0  # time between each spike pair
    t_extent = 100e-3  # s  # STDP kernel extent,
    # t_extent > t_between_pairs/2 inverts pre-post pairing!
    # dt = tpost - tpre
    # negative dt corresponds to post before pre
    print('-----------------------------------------------')
    for deltat in np.arange(t_extent, 0.0, -ddt):
        reset_settle()
        for i in range(numpairs):
            # post neuron spike
            make_neuron_spike(1)
            moose.start(deltat)
            # pre neuron spike after deltat
            make_neuron_spike(0)
            moose.start(
                t_between_pairs)  # weight changes after pre-spike+delayD
            # must run for at least delayD after pre-spike
        dw = (syn.synapse[0].weight - weight) / weight
        print(('post before pre, dt = %1.3f s, dw/w = %1.3f' % (-deltat, dw)))
        dwlist_neg.append(dw)

    print('-----------------------------------------------')
    # positive dt corresponds to pre before post
    dwlist_pos = []
    for deltat in np.arange(ddt, t_extent + ddt, ddt):
        reset_settle()
        for i in range(numpairs):
            # pre neuron spike
            make_neuron_spike(0)
            moose.start(deltat)
            # post neuron spike after deltat
            make_neuron_spike(1)
            moose.start(t_between_pairs)
        dw = (syn.synapse[0].weight - weight) / weight
        print(('pre before post, dt = %1.3f s, dw/w = %1.3f' % (deltat, dw)))
        dwlist_pos.append(dw)

    Vmseries0 = Vms.vec[0].vector
    numsteps = len(Vmseries0)

    for t in spikes.vec[0].vector:
        Vmseries0[int(t / dt) - 1] = 30e-3  # V

    Vmseries1 = Vms.vec[1].vector

    for t in spikes.vec[1].vector:
        Vmseries1[int(t / dt) - 1] = 30e-3  # V

    timeseries = np.linspace(0., 200 * numsteps * dt, numsteps)

    # STDP curve
    up, sp = np.mean(dwlist_pos), np.std(dwlist_pos)
    un, sn = np.mean(dwlist_neg), np.std(dwlist_neg)

    expected = [
        0.32476025611655324, 0.22658173497286094, 0.02706212384326734,
        -0.2176119329016457, -0.17349820098625146, -0.049000627347906,
        0.10942145078777199, 0.015381955378225953, 0.004742824127517586,
        -0.12298343312253879
    ]
    assert np.isclose(
        dwlist_pos[1:],
        expected[1:]).all(), "Got %s \nexpected %s" % (dwlist_pos, expected)

    expected = [
        -0.07871282492831622, 0.11915009122888964, -0.028510348966579557,
        0.11812233585111875, 0.05098143255634335, -0.2303047508248669,
        0.18033418630802123, -0.019377885225611347, -0.06038610826728241,
        0.06575882890278106
    ]
    assert np.isclose(
        dwlist_neg[1:],
        expected[1:]).all(), "Got %s\nexpected %s" % (dwlist_neg, expected)

    got = (up, sp)
    expNew = (0.014485615086785508, 0.16206703949072981)
    assert np.isclose(
        got, expNew).all(), 'Expected: %s, Got: %s' % (str(expNew), str(got))
Beispiel #6
0
def makeGlobalBalanceNetwork():
    stim = moose.RandSpike('/model/stim', params['numInputs'])
    inhib = moose.LIF('/model/inhib', params['numInhib'])
    insyn = moose.SimpleSynHandler(inhib.path + '/syns', params['numInhib'])
    moose.connect(insyn, 'activationOut', inhib, 'activation', 'OneToOne')
    output = moose.LIF('/model/output', params['numOutput'])
    outsyn = moose.SimpleSynHandler(output.path + '/syns', params['numOutput'])
    moose.connect(outsyn, 'activationOut', output, 'activation', 'OneToOne')
    outInhSyn = moose.SimpleSynHandler(output.path + '/inhsyns',
                                       params['numOutput'])
    moose.connect(outInhSyn, 'activationOut', output, 'activation', 'OneToOne')

    iv = moose.vec(insyn.path + '/synapse')
    ov = moose.vec(outsyn.path + '/synapse')
    oiv = moose.vec(outInhSyn.path + '/synapse')

    assert len(iv) == 0
    assert len(ov) == 0
    assert len(oiv) == 0

    temp = moose.connect(stim, 'spikeOut', iv, 'addSpike', 'Sparse')
    inhibMatrix = moose.element(temp)
    inhibMatrix.setRandomConnectivity(params['stimToInhProb'],
                                      params['stimToInhSeed'])
    cl = inhibMatrix.connectionList

    # This can change when random-number generator changes.
    # This was before we used c++11 <random> to generate random numbers. This
    # test has changes on Tuesday 31 July 2018 11:12:35 AM IST
    #  expectedCl = [ 1,4,13,13,26,42,52,56,80,82,95,97,4,9,0,9,4,8,0,6,1,6,6,7]
    expectedCl = [0, 6, 47, 50, 56, 67, 98, 2, 0, 3, 5, 4, 8, 3]

    assert list(cl) == expectedCl, "Expected %s, got %s" % (expectedCl, cl)

    temp = moose.connect(stim, 'spikeOut', ov, 'addSpike', 'Sparse')
    excMatrix = moose.element(temp)
    excMatrix.setRandomConnectivity(params['stimToOutProb'],
                                    params['stimToOutSeed'])

    temp = moose.connect(inhib, 'spikeOut', oiv, 'addSpike', 'Sparse')
    negFFMatrix = moose.element(temp)
    negFFMatrix.setRandomConnectivity(params['inhToOutProb'],
                                      params['inhToOutSeed'])

    # print("ConnMtxEntries: ", inhibMatrix.numEntries, excMatrix.numEntries, negFFMatrix.numEntries)
    got = (inhibMatrix.numEntries, excMatrix.numEntries,
           negFFMatrix.numEntries)
    expected = (7, 62, 55)
    assert expected == got, "Expected %s, Got %s" % (expected, got)

    cl = negFFMatrix.connectionList
    numInhSyns = []
    niv = 0
    nov = 0
    noiv = 0
    for i in moose.vec(insyn):
        niv += i.synapse.num
        numInhSyns.append(i.synapse.num)
        if i.synapse.num > 0:
            i.synapse.weight = params['wtStimToInh']

    #  expected = [2,1,0,0,2,0,3,1,1,2]
    expected = [1, 0, 1, 2, 1, 1, 0, 0, 1, 0]
    assert numInhSyns == expected, "Expected %s, got %s" % (expected,
                                                            numInhSyns)

    for i in moose.vec(outsyn):
        print('111', i)
        nov += i.synapse.num
        if i.synapse.num > 0:
            i.synapse.weight = params['wtStimToOut']
    for i in moose.vec(outInhSyn):
        noiv += i.synapse.num
        #print i.synapse.num
        if i.synapse.num > 0:
            i.synapse.weight = params['wtInhToOut']

    print("SUMS: ", sum(iv.numField), sum(ov.numField), sum(oiv.numField))
    assert [1, 64,
            25] == [sum(iv.numField),
                    sum(ov.numField),
                    sum(oiv.numField)]
    print("SUMS2: ", niv, nov, noiv)
    assert [7, 62, 55] == [niv, nov, noiv]
    print("SUMS3: ", sum(insyn.vec.numSynapses), sum(outsyn.vec.numSynapses),
          sum(outInhSyn.vec.numSynapses))
    assert [7, 62, 55] == [
        sum(insyn.vec.numSynapses),
        sum(outsyn.vec.numSynapses),
        sum(outInhSyn.vec.numSynapses)
    ]

    # print(oiv.numField)
    # print(insyn.vec[1].synapse.num)
    # print(insyn.vec.numSynapses)
    # print(sum( insyn.vec.numSynapses ))
    # niv = iv.numSynapses
    # ov = iv.numSynapses

    sv = moose.vec(stim)
    sv.rate = params['randInputRate']
    sv.refractT = params['randRefractTime']
    #moose.showfield( sv[7] )

    inhib.vec.thresh = params['inhibThresh']
    inhib.vec.Rm = params['Rm']
    inhib.vec.Cm = params['Cm']
    inhib.vec.vReset = params['inhVreset']
    inhib.vec.refractoryPeriod = params['inhibRefractTime']
    output.vec.thresh = params['outputThresh']
    output.vec.Rm = params['Rm']
    output.vec.Cm = params['Cm']
    output.vec.refractoryPeriod = params['outputRefractTime']
    otab = moose.Table('/model/otab', params['numOutput'])
    moose.connect(otab, 'requestOut', output, 'getVm', 'OneToOne')
    itab = moose.Table('/model/itab', params['numInhib'])
    moose.connect(itab, 'requestOut', inhib, 'getVm', 'OneToOne')
    return inhib, output
Beispiel #7
0
    def readMorphML(self, cell, params={}, lengthUnits="micrometer"):
        """
        returns cellDict = { cellname: (segDict, cableDict) } # note: single cell only
        where segDict = { segid1 : [ segname,(proximalx,proximaly,proximalz),
            (distalx,distaly,distalz),diameter,length,[potential_syn1, ... ] ] , ... }
        segname is "<name>_<segid>" because 1) guarantees uniqueness,
            & 2) later scripts obtain segid from the compartment's name!
        and cableDict = { cablegroupname : [campartment1name, compartment2name, ... ], ... }.
        params is dict which can contain, combineSegments and/or createPotentialSynapses,
         both boolean.
        """
        if lengthUnits in ['micrometer', 'micron']:
            self.length_factor = 1e-6
        else:
            self.length_factor = 1.0
        cellname = cell.attrib["name"]
        moose.Neutral(
            '/library')  # creates /library in MOOSE tree; elif present, wraps
        _logger.info("Loading cell %s into /library ." % cellname)

        #~ moosecell = moose.Cell('/library/'+cellname)
        #using moose Neuron class - in previous version 'Cell' class Chaitanya
        moosecell = moose.Neuron('/library/' + cellname)
        self.cellDictBySegmentId[cellname] = [moosecell, {}]
        self.cellDictByCableId[cellname] = [moosecell, {}]
        self.segDict = {}
        if 'combineSegments' in params:
            self.combineSegments = params['combineSegments']
        else:
            self.combineSegments = False
        if 'createPotentialSynapses' in params:
            self.createPotentialSynapses = params['createPotentialSynapses']
        else:
            self.createPotentialSynapses = False
        _logger.info("readMorphML using combineSegments = %s" %
                     self.combineSegments)

        ###############################################
        #### load cablegroups into a dictionary
        self.cablegroupsDict = {}
        self.cablegroupsInhomoparamsDict = {}
        ## Two ways of specifying cablegroups in neuroml 1.x
        ## <cablegroup>s with list of <cable>s
        cablegroups = cell.findall(".//{" + self.mml + "}cablegroup")
        for cablegroup in cablegroups:
            cablegroupname = cablegroup.attrib['name']
            self.cablegroupsDict[cablegroupname] = []
            self.cablegroupsInhomoparamsDict[cablegroupname] = []
            for cable in cablegroup.findall(".//{" + self.mml + "}cable"):
                cableid = cable.attrib['id']
                self.cablegroupsDict[cablegroupname].append(cableid)
            # parse inhomogenous_params
            for inhomogeneous_param in cablegroup.findall(
                    ".//{" + self.mml + "}inhomogeneous_param"):
                metric = inhomogeneous_param.find(".//{" + self.mml +
                                                  "}metric")
                if metric.text == 'Path Length from root':
                    inhomoparamname = inhomogeneous_param.attrib['name']
                    inhomoparamvar = inhomogeneous_param.attrib['variable']
                    self.cablegroupsInhomoparamsDict[cablegroupname].append(\
                                (inhomoparamname,inhomoparamvar))
                else:
                    _logger.warning('Only "Path Length from root" metric is '
                                    ' supported currently, ignoring %s ' %
                                    metric.text)

        ## <cable>s with list of <meta:group>s
        cables = cell.findall(".//{" + self.mml + "}cable")
        for cable in cables:
            cableid = cable.attrib['id']
            cablegroups = cable.findall(".//{" + self.meta + "}group")
            for cablegroup in cablegroups:
                cablegroupname = cablegroup.text
                if cablegroupname in self.cablegroupsDict:
                    self.cablegroupsDict[cablegroupname].append(cableid)
                else:
                    self.cablegroupsDict[cablegroupname] = [cableid]

        ###################################################
        ## load all mechanisms in this cell into /library for later copying
        ## set which compartments have integrate_and_fire mechanism
        self.intFireCableIds = {
        }  # dict with keys as Compartments/cableIds which are IntFire
        # with mechanismnames as values
        for mechanism in cell.findall(".//{" + self.bio + "}mechanism"):
            mechanismname = mechanism.attrib["name"]
            passive = False
            if "passive_conductance" in mechanism.attrib:
                if mechanism.attrib['passive_conductance'] in [
                        "true", 'True', 'TRUE'
                ]:
                    passive = True
            if not passive:
                ## if channel does not exist in library load it from xml file
                if not moose.exists("/library/" + mechanismname):
                    _logger.info("Loading mechanism %s into library." %
                                 mechanismname)
                    cmlR = ChannelML(self.nml_params)
                    model_filename = mechanismname + '.xml'
                    model_path = neuroml_utils.find_first_file(
                        model_filename, self.model_dir)
                    if model_path is not None:
                        cmlR.readChannelMLFromFile(model_path)
                    else:
                        raise IOError(
                            'For mechanism {0}: files {1} not found under {2}.'
                            .format(mechanismname, model_filename,
                                    self.model_dir))

                    ## set those compartments to be LIF for which
                    ## any integrate_and_fire parameter is set
                    if not moose.exists("/library/" + mechanismname):
                        _logger.warn("Mechanism doesn't exist: %s " %
                                     mechanismname)
                        moose.le('/library')
                    moosemech = moose.element("/library/" + mechanismname)
                    if moose.exists(moosemech.path + "/integrate_and_fire"):
                        mooseIaF = moose.element(
                            moosemech.path + "/integrate_and_fire")  # Mstring
                        if mooseIaF.value in ['true', 'True', 'TRUE']:
                            mech_params = mechanism.findall(".//{" + self.bio +
                                                            "}parameter")
                            for parameter in mech_params:
                                parametername = parameter.attrib['name']
                                ## check for the integrate_and_fire parameters
                                if parametername in [
                                        'threshold', 't_refrac', 'v_reset',
                                        'g_refrac'
                                ]:
                                    for group in parameter.findall(".//{" +
                                                                   self.bio +
                                                                   "}group"):
                                        cablegroupname = group.text
                                        if cablegroupname == 'all':
                                            self.intFireCableIds = {
                                                'all': mechanismname
                                            }
                                            break
                                        else:
                                            for cableid in self.cablegroupsDict[
                                                    cablegroupname]:
                                                ## only one intfire mechanism is allowed in a cable
                                                ## the last one parsed will override others
                                                self.intFireCableIds[
                                                    cableid] = mechanismname
                                if 'all' in self.intFireCableIds:
                                    break

        ############################################################
        #### load morphology and connections between compartments
        ## Many neurons exported from NEURON have multiple segments in a section
        ## If self.combineSegments = True,
        ##  then combine those segments into one Compartment / section
        ##  for combining, assume segments of a compartment/section are in increasing order
        ##  and assume all segments of a compartment/section have the same cableid
        ## findall() returns elements in document order:
        running_cableid = ''
        running_segid = ''
        running_comp = None
        running_diameter = 0.0
        running_dia_nums = 0
        segments = cell.findall(".//{" + self.mml + "}segment")
        segmentstotal = len(segments)
        for segnum, segment in enumerate(segments):
            segmentname = segment.attrib['name']
            ## cable is an optional attribute. WARNING: Here I assume it is always present.
            cableid = segment.attrib['cable']
            segmentid = segment.attrib['id']
            ## if old cableid still running AND self.combineSegments == True,
            ## then don't start a new compartment, skip to next segment
            if cableid == running_cableid and self.combineSegments:
                self.cellDictBySegmentId[cellname][1][segmentid] = running_comp
                proximal = segment.find('./{' + self.mml + '}proximal')
                if proximal is not None:
                    running_diameter += float(
                        proximal.attrib["diameter"]) * self.length_factor
                    running_dia_nums += 1
                distal = segment.find('./{' + self.mml + '}distal')
                if distal is not None:
                    running_diameter += float(
                        distal.attrib["diameter"]) * self.length_factor
                    running_dia_nums += 1
            ## if (self.combineSegments and new cableid starts) or if not self.combineSegments,
            ##  then start a new compartment
            else:
                ## Create a new compartment
                ## the moose "hsolve" method assumes compartments to be
                ## asymmetric compartments and symmetrizes them
                ## but that is not what we want when translating
                ## from Neuron which has only symcompartments -- so be careful!

                ## Check if integrate_and_fire mechanism is present,
                ## if so use LIF instead of Compartment
                moosecompname = segmentname + '_' + segmentid  # just segmentname is NOT unique
                # eg: mitral bbmit exported from NEURON
                moosecomppath = moosecell.path + '/' + moosecompname
                mechanismname = None
                if 'all' in self.intFireCableIds:
                    mechanismname = self.intFireCableIds['all']
                if cableid in self.intFireCableIds:
                    mechanismname = self.intFireCableIds[cableid]
                if mechanismname is not None:  # this cableid is an intfire
                    ## create LIF (subclass of Compartment) and set to default values
                    moosecomp = moose.LIF(moosecomppath)
                    moosechannel = moose.Neutral('/library/' + mechanismname)
                    moosechannelval = moose.Mstring(moosechannel.path +
                                                    '/vReset')
                    moosecomp.vReset = moosechannelval.value
                    moosechannelval = moose.Mstring(moosechannel.path +
                                                    '/thresh')
                    moosecomp.thresh = moosechannelval.value
                    moosechannelval = moose.Mstring(moosechannel.path +
                                                    '/refracT')
                    moosecomp.refractoryPeriod = moosechannelval.value
                    ## refracG is currently not supported by moose.LIF
                    ## when you implement it, check if refracG or g_refrac
                    ## is a conductance density or a conductance, I think the former
                    #moosechannelval = moose.Mstring(moosechannel.path+'/refracG')
                else:
                    moosecomp = moose.Compartment(moosecomppath)
                self.cellDictBySegmentId[cellname][1][segmentid] = moosecomp
                ## cables are grouped and mechanism densities are set for cablegroups later.
                ## hence I will need to refer to segment according to which cable it belongs to.
                ## if combineSegments is False, there can be multiple segments per cable,
                ##  so make array of compartments for cellDictByCableId[cellname][1][cableid]
                if cableid in self.cellDictByCableId[cellname][1]:
                    self.cellDictByCableId[cellname][1][cableid].append(
                        moosecomp)
                else:
                    self.cellDictByCableId[cellname][1][cableid] = [moosecomp]
                running_cableid = cableid
                running_segid = segmentid
                running_comp = moosecomp
                running_diameter = 0.0
                running_dia_nums = 0
                if 'parent' in segment.attrib:
                    parentid = segment.attrib[
                        'parent']  # I assume the parent is created before the child
                    # so that I can immediately connect the child.
                    parent = self.cellDictBySegmentId[cellname][1][parentid]
                    ## It is always assumed that axial of parent is connected to raxial of moosesegment
                    ## THIS IS WHAT GENESIS readcell() DOES!!! UNLIKE NEURON!
                    ## THIS IS IRRESPECTIVE OF WHETHER PROXIMAL x,y,z OF PARENT = PROXIMAL x,y,z OF CHILD.
                    ## THIS IS ALSO IRRESPECTIVE OF fraction_along_parent SPECIFIED IN CABLE!
                    ## THUS THERE WILL BE NUMERICAL DIFFERENCES BETWEEN MOOSE/GENESIS and NEURON.
                    ## moosesegment sends Ra and Vm to parent, parent sends only Vm
                    ## actually for symmetric compartment, both parent and moosesegment require each other's Ra/2,
                    ## but axial and raxial just serve to distinguish ends.
                    moose.connect(parent, 'axial', moosecomp, 'raxial')
                else:
                    parent = None
                proximal = segment.find('./{' + self.mml + '}proximal')
                if proximal is None:  # If proximal tag is not present,
                    # then parent attribute MUST be present in the segment tag!
                    ## if proximal is not present, then
                    ## by default the distal end of the parent is the proximal end of the child
                    moosecomp.x0 = parent.x
                    moosecomp.y0 = parent.y
                    moosecomp.z0 = parent.z
                else:
                    moosecomp.x0 = float(
                        proximal.attrib["x"]) * self.length_factor
                    moosecomp.y0 = float(
                        proximal.attrib["y"]) * self.length_factor
                    moosecomp.z0 = float(
                        proximal.attrib["z"]) * self.length_factor
                    running_diameter += float(
                        proximal.attrib["diameter"]) * self.length_factor
                    running_dia_nums += 1
                distal = segment.find('./{' + self.mml + '}distal')
                if distal is not None:
                    running_diameter += float(
                        distal.attrib["diameter"]) * self.length_factor
                    running_dia_nums += 1
                ## finished creating new compartment

            ## Update the end position, diameter and length, and segDict of this comp/cable/section
            ## with each segment that is part of this cable (assumes contiguous segments in xml).
            ## This ensures that we don't have to do any 'closing ceremonies',
            ## if a new cable is encoutered in next iteration.
            if distal is not None:
                running_comp.x = float(distal.attrib["x"]) * self.length_factor
                running_comp.y = float(distal.attrib["y"]) * self.length_factor
                running_comp.z = float(distal.attrib["z"]) * self.length_factor
            ## Set the compartment diameter as the average diameter of all the segments in this section
            running_comp.diameter = running_diameter / float(running_dia_nums)
            ## Set the compartment length
            running_comp.length = math.sqrt((running_comp.x-running_comp.x0)**2+\
                (running_comp.y-running_comp.y0)**2+(running_comp.z-running_comp.z0)**2)
            ## NeuroML specs say that if (x0,y0,z0)=(x,y,z), then round compartment e.g. soma.
            ## In Moose set length = dia to give same surface area as sphere of dia.
            if running_comp.length == 0.0:
                running_comp.length = running_comp.diameter
            ## Set the segDict
            ## the empty list at the end below will get populated
            ## with the potential synapses on this segment, in function set_compartment_param(..)
            self.segDict[running_segid] = [running_comp.name,\
                (running_comp.x0,running_comp.y0,running_comp.z0),\
                (running_comp.x,running_comp.y,running_comp.z),\
                running_comp.diameter,running_comp.length,[]]
            if neuroml_utils.neuroml_debug:
                _logger.info('Set up compartment/section %s' %
                             running_comp.name)

        ###############################################
        #### load biophysics into the compartments
        biophysics = cell.find(".//{" + self.neuroml + "}biophysics")
        if biophysics is not None:
            ## see pg 219 (sec 13.2) of Book of Genesis for Physiological Units
            if biophysics.attrib["units"] == 'Physiological Units':
                CMfactor = 1e-2  # F/m^2 from microF/cm^2
                Cfactor = 1e-6  # F from microF
                RAfactor = 1e1  # Ohm*m from KOhm*cm
                RMfactor = 1e-1  # Ohm*m^2 from KOhm*cm^2
                Rfactor = 1e-3  # Ohm from KOhm
                Efactor = 1e-3  # V from mV
                Gfactor = 1e1  # S/m^2 from mS/cm^2
                Ifactor = 1e-6  # A from microA
                Tfactor = 1e-3  # s from ms
            else:
                CMfactor = 1.0
                Cfactor = 1.0
                RAfactor = 1.0
                RMfactor = 1.0
                Rfactor = 1.0
                Efactor = 1.0
                Gfactor = 1.0
                Ifactor = 1.0
                Tfactor = 1.0

            spec_capacitance = cell.find(".//{" + self.bio +
                                         "}spec_capacitance")
            for parameter in spec_capacitance.findall(".//{" + self.bio +
                                                      "}parameter"):
                self.set_group_compartment_param(cell, cellname, parameter,\
                 'CM', float(parameter.attrib["value"])*CMfactor, self.bio)
            spec_axial_resitance = cell.find(".//{" + self.bio +
                                             "}spec_axial_resistance")
            for parameter in spec_axial_resitance.findall(".//{" + self.bio +
                                                          "}parameter"):
                self.set_group_compartment_param(cell, cellname, parameter,\
                 'RA', float(parameter.attrib["value"])*RAfactor, self.bio)
            init_memb_potential = cell.find(".//{" + self.bio +
                                            "}init_memb_potential")
            for parameter in init_memb_potential.findall(".//{" + self.bio +
                                                         "}parameter"):
                self.set_group_compartment_param(cell, cellname, parameter,\
                 'initVm', float(parameter.attrib["value"])*Efactor, self.bio)
            chan_distrib = [
            ]  # the list for moose to parse inhomogeneous params (filled below)
            for mechanism in cell.findall(".//{" + self.bio + "}mechanism"):
                mechanismname = mechanism.attrib["name"]
                passive = False
                if "passive_conductance" in mechanism.attrib:
                    if mechanism.attrib['passive_conductance'] in [
                            "true", 'True', 'TRUE'
                    ]:
                        passive = True
                _logger.info("Loading mechanism %s " % mechanismname)
                ## ONLY creates channel if at least one parameter (like gmax) is specified in the xml
                ## Neuroml does not allow you to specify all default values.
                ## However, granule cell example in neuroconstruct has Ca ion pool without
                ## a parameter, applying default values to all compartments!
                mech_params = mechanism.findall(".//{" + self.bio +
                                                "}parameter")
                ## if no params, apply all default values to all compartments
                if len(mech_params) == 0:
                    for compartment_list in self.cellDictByCableId[cellname][
                            1].values():
                        for compartment in compartment_list:
                            self.set_compartment_param(compartment, None,
                                                       'default',
                                                       mechanismname)
                ## if params are present, apply params to specified cable/compartment groups
                for parameter in mech_params:
                    parametername = parameter.attrib['name']
                    if passive:
                        if parametername in ['gmax']:
                            self.set_group_compartment_param(cell, cellname, parameter,\
                             'RM', RMfactor*1.0/float(parameter.attrib["value"]), self.bio)
                        elif parametername in ['e', 'erev']:
                            self.set_group_compartment_param(cell, cellname, parameter,\
                             'Em', Efactor*float(parameter.attrib["value"]), self.bio)
                        elif parametername in ['inject']:
                            self.set_group_compartment_param(cell, cellname, parameter,\
                             'inject', Ifactor*float(parameter.attrib["value"]), self.bio)
                        else:
                            _logger.warning([
                                "Yo programmer of MorphML! You didn't",
                                " implement parameter %s " % parametername,
                                " in mechanism %s " % mechanismname
                            ])
                    else:
                        if parametername in ['gmax']:
                            gmaxval = float(
                                eval(parameter.attrib["value"],
                                     {"__builtins__": None}, {}))
                            self.set_group_compartment_param(cell, cellname, parameter,\
                             'Gbar', Gfactor*gmaxval, self.bio, mechanismname)
                        elif parametername in ['e', 'erev']:
                            self.set_group_compartment_param(cell, cellname, parameter,\
                             'Ek', Efactor*float(parameter.attrib["value"]), self.bio, mechanismname)
                        elif parametername in [
                                'depth'
                        ]:  # has to be type Ion Concentration!
                            self.set_group_compartment_param(cell, cellname, parameter,\
                             'thick', self.length_factor*float(parameter.attrib["value"]),\
                             self.bio, mechanismname)
                        elif parametername in ['v_reset']:
                            self.set_group_compartment_param(cell, cellname, parameter,\
                             'v_reset', Efactor*float(parameter.attrib["value"]),\
                             self.bio, mechanismname)
                        elif parametername in ['threshold']:
                            self.set_group_compartment_param(cell, cellname, parameter,\
                             'threshold', Efactor*float(parameter.attrib["value"]),\
                             self.bio, mechanismname)
                        elif parametername in ['t_refrac']:
                            self.set_group_compartment_param(cell, cellname, parameter,\
                             't_refrac', Tfactor*float(parameter.attrib["value"]),\
                             self.bio, mechanismname)
                        else:
                            _logger.warning([
                                "Yo programmer of MorphML import! You didn't",
                                " implement parameter %s " % parametername,
                                " in mechanism %s " % mechanismname
                            ])

                ## variable parameters:
                ##  varying with:
                ##  p, g, L, len, dia
                ##	p: path distance from soma, measured along dendrite, in metres.
                ##	g: geometrical distance from soma, in metres.
                ##	L: electrotonic distance (# of lambdas) from soma, along dend. No units.
                ##	len: length of compartment, in metres.
                ##	dia: for diameter of compartment, in metres.
                var_params = mechanism.findall(".//{" + self.bio +
                                               "}variable_parameter")
                if len(var_params) > 0:
                    ## if variable params are present
                    ##  and use MOOSE to apply the variable formula
                    for parameter in var_params:
                        parametername = parameter.attrib['name']
                        cablegroupstr4moose = ""
                        ## the neuroml spec says there should be a single group in a variable_parameter
                        ##  of course user can always have multiple variable_parameter tags,
                        ##  if user wants multiple groups conforming to neuroml specs.
                        group = parameter.find(".//{" + self.bio + "}group")
                        cablegroupname = group.text
                        if cablegroupname == 'all':
                            cablegroupstr4moose = "#"
                        else:
                            for cableid in self.cablegroupsDict[
                                    cablegroupname]:
                                for compartment in self.cellDictByCableId[
                                        cellname][1][cableid]:
                                    cablegroupstr4moose += "#" + compartment.name + "#,"
                            if cablegroupstr4moose[-1] == ',':
                                cablegroupstr4moose = cablegroupstr4moose[:
                                                                          -1]  # remove last comma
                        inhomo_value = parameter.find(".//{" + self.bio +
                                                      "}inhomogeneous_value")
                        inhomo_value_name = inhomo_value.attrib['param_name']
                        inhomo_value_value = inhomo_value.attrib['value']
                        if parametername == 'gmax':
                            inhomo_eqn = '(' + inhomo_value_value + ')*' + str(
                                Gfactor)
                            # careful about physiol vs SI units
                        else:
                            inhomo_eqn = inhomo_value_value
                            _logger.warning(
                                'Physiol. vs SI units translation not'
                                ' implemented for parameter ' + parametername +
                                'in channel ' +
                                mechanismname) + '. Use SI units'
                            'or ask for implementation.'
                        chan_distrib.extend(
                            (mechanismname, cablegroupstr4moose, parametername,
                             inhomo_eqn, ""))
                        # use extend, not append, moose wants it this way
            ## get mooose to parse the variable parameter gmax channel distributions
            #pu.info("Some channel parameters distributed as per "+str(chan_distrib))
            moosecell.channelDistribution = chan_distrib
            #### Connect the Ca pools and channels
            #### Am connecting these at the very end so that all channels and pools have been created
            #### Note: this function is in moose.utils not moose.neuroml.utils !
            for compartment_list in self.cellDictByCableId[cellname][1].values(
            ):
                moose_utils.connect_CaConc(compartment_list,\
                    self.temperature+neuroml_utils.ZeroCKelvin) # temperature should be in Kelvin for Nernst

        ##########################################################
        #### load connectivity / synapses into the compartments
        connectivity = cell.find(".//{" + self.neuroml + "}connectivity")
        if connectivity is not None:
            for potential_syn_loc in cell.findall(".//{" + self.nml +
                                                  "}potential_syn_loc"):
                if 'synapse_direction' in potential_syn_loc.attrib:
                    if potential_syn_loc.attrib['synapse_direction'] in [
                            'post', 'preAndOrPost'
                    ]:
                        self.set_group_compartment_param(cell, cellname, potential_syn_loc,\
                            'synapse_type', potential_syn_loc.attrib['synapse_type'],\
                            self.nml, mechanismname='synapse')
                    if potential_syn_loc.attrib['synapse_direction'] in [
                            'pre', 'preAndOrPost'
                    ]:
                        self.set_group_compartment_param(cell, cellname, potential_syn_loc,\
                            'spikegen_type', potential_syn_loc.attrib['synapse_type'],\
                            self.nml, mechanismname='spikegen')

        ##########################################################
        #### annotate each compartment with the cablegroups it belongs to
        self.cableDict = {}
        for cablegroupname in self.cablegroupsDict:
            comp_list = []
            for cableid in self.cablegroupsDict[cablegroupname]:
                for compartment in self.cellDictByCableId[cellname][1][
                        cableid]:
                    cableStringPath = compartment.path + '/cable_groups'
                    cableString = moose.Mstring(cableStringPath)
                    if cableString.value == '':
                        cableString.value += cablegroupname
                    else:
                        cableString.value += ',' + cablegroupname
                    comp_list.append(compartment.name)
            self.cableDict[cablegroupname] = comp_list

        _logger.info("Finished loading into library, cell: %s " % cellname)
        return {cellname: (self.segDict, self.cableDict)}
Beispiel #8
0
def setupModel():
    '''
    Set up two LIF neurons and connect them by an STDPSynHandler.
    Set up some tables, and reinit MOOSE before simulation.
    '''
    # ###########################################
    # Initialize neuron group
    # ###########################################

    ## two neurons: index 0 will be presynaptic, 1 will be postsynaptic
    network = moose.LIF('network', 2)
    moose.le('/network')
    network.vec.Em = Vrest
    network.vec.thresh = Vt_base
    network.vec.refractoryPeriod = refrT
    network.vec.Rm = R
    network.vec.vReset = Vreset
    network.vec.Cm = tau / R
    network.vec.inject = 0.
    network.vec.initVm = Vrest

    # ###########################################
    # Synaptic model: STDP at each pre and post spike
    # ###########################################

    # Values approx from figure in Scholarpedia article (following Bi and Poo 1998):
    # Jesper Sjoestroem and Wulfram Gerstner (2010) Spike-timing dependent plasticity.
    # Scholarpedia, 5(2):1362., revision #137369
    tauPlus = 10e-3  # s         # Apre time constant
    tauMinus = 10e-3  # s        # Apost time constant
    aPlus0 = 1.0  # at pre, Apre += Apre0
    aMinus0 = 0.25  # at post, Apost += Apost0
    weight = 5e-3  # V           # delta function synapse, adds to Vm

    syn = moose.STDPSynHandler('/network/syn')
    syn.numSynapses = 1  # 1 synapse
    # many pre-synaptic inputs can connect to a synapse
    # synapse onto postsynaptic neuron
    moose.connect(syn, 'activationOut', network.vec[1], 'activation')

    # synapse from presynaptic neuron
    moose.connect(network.vec[0], 'spikeOut', syn.synapse[0], 'addSpike')

    # post-synaptic spikes also needed for STDP
    moose.connect(network.vec[1], 'spikeOut', syn, 'addPostSpike')

    syn.synapse[0].delay = 0.0
    syn.synapse[0].weight = weight  # V
    syn.aPlus0 = aPlus0 * weight  # on every pre-spike, aPlus gets this jump
    # aMinus0 includes learning rate
    # on every pre-spike, aMinus is added to weight
    syn.tauPlus = tauPlus
    syn.aMinus0 = -aMinus0 * weight  # on every post-spike, aMinus gets this jump
    # aMinus0 includes learning rate
    # on every post-spike, aPlus is added to weight
    syn.tauMinus = tauMinus
    syn.weightMax = 2 * weight  # bounds on the weight
    syn.weightMin = 0.

    # ###########################################
    # Setting up tables
    # ###########################################

    Vms = moose.Table('/plotVms', 2)
    moose.connect(network, 'VmOut', Vms, 'input', 'OneToOne')
    spikes = moose.Table('/plotSpikes', 2)
    moose.connect(network, 'spikeOut', spikes, 'input', 'OneToOne')

    # ###########################################
    # Simulate the STDP curve with spaced pre-post spike pairs
    # ###########################################

    dt = 0.5e-5  # s
    # moose simulation
    moose.useClock(0, '/network/syn', 'process')
    moose.useClock(1, '/network', 'process')
    moose.useClock(2, '/plotSpikes', 'process')
    moose.useClock(3, '/plotVms', 'process')
    moose.setClock(0, dt)
    moose.setClock(1, dt)
    moose.setClock(2, dt)
    moose.setClock(3, dt)
    moose.setClock(9, dt)
    moose.reinit()
def make_network():
        size = 1024
        dt = 0.2
        runsteps = 50
        delayMin = 0
        delayMax = 4
        weightMax = 1
        Vmax = 1.0
        thresh = 0.4
        refractoryPeriod = 0.4
        tau = 0.5
        connectionProbability = 0.01
        random.seed( 123 )
        nprand.seed( 456 )
        t0 = time.time()

        network = moose.LIF( 'network', size );
        syns = moose.SimpleSynHandler( '/network/syns', size );
        moose.connect( syns, 'activationOut', network, 'activation', 'OneToOne' )
        moose.le( '/network' )
        syns.vec.numSynapses = [1] * size
        sv = moose.vec( '/network/syns/synapse' )
        print(('before connect t = ', time.time() - t0))
        mid = moose.connect( network, 'spikeOut', sv, 'addSpike', 'Sparse')
        print(('after connect t = ', time.time() - t0))
        #print mid.destFields
        m2 = moose.element( mid )
        m2.setRandomConnectivity( connectionProbability, 5489 )
        print(('after setting connectivity, t = ', time.time() - t0))
        #network.vec.Vm = [(Vmax*random.random()) for r in range(size)]
        network.vec.Vm = nprand.rand( size ) * Vmax
        network.vec.thresh = thresh
        network.vec.refractoryPeriod = refractoryPeriod
        network.vec.Rm = 1e10
        network.vec.Cm = 5e-9
        numSynVec = syns.vec.numSynapses
        print(('Middle of setup, t = ', time.time() - t0))
        numTotSyn = sum( numSynVec )
        print((numSynVec.size, ', tot = ', numTotSyn,  ', numSynVec = ', numSynVec))
        for item in syns.vec:
                sh = moose.element( item )
                sh.synapse.delay = delayMin +  (delayMax - delayMin ) * nprand.rand( len( sh.synapse ) )
                #sh.synapse.delay = [ (delayMin + random.random() * (delayMax - delayMin ) for r in range( len( sh.synapse ) ) ] 
                sh.synapse.weight = nprand.rand( len( sh.synapse ) ) * weightMax
        print(('after setup, t = ', time.time() - t0))

        numStats = 100
        stats = moose.SpikeStats( '/stats', numStats )
        stats.vec.windowLength = 1 # timesteps to put together.
        plots = moose.Table( '/plot', numStats )
        convergence = size / numStats
        for i in range( numStats ):
            for j in range( size/numStats ):
                k = i * convergence + j
                moose.connect( network.vec[k], 'spikeOut', stats.vec[i], 'addSpike' )
        moose.connect( plots, 'requestOut', stats, 'getMean', 'OneToOne' )

        #moose.useClock( 0, '/network/syns,/network', 'process' )
        moose.useClock( 0, '/network/syns', 'process' )
        moose.useClock( 1, '/network', 'process' )
        moose.useClock( 2, '/stats', 'process' )
        moose.useClock( 3, '/plot', 'process' )
        moose.setClock( 0, dt )
        moose.setClock( 1, dt )
        moose.setClock( 2, dt )
        moose.setClock( 3, dt )
        moose.setClock( 9, dt )
        t1 = time.time()
        moose.reinit()
        print(('reinit time t = ', time.time() - t1))
        network.vec.Vm = nprand.rand( size ) * Vmax
        print(('setting Vm , t = ', time.time() - t1))
        t1 = time.time()
        print('starting')
        moose.start(runsteps * dt)
        print(('runtime, t = ', time.time() - t1))
        print((network.vec.Vm[99:103], network.vec.Vm[900:903]))
        t = [i * dt for i in range( plots.vec[0].vector.size )]
        i = 0
        for p in plots.vec:
            pylab.plot( t, p.vector, label=str( i) )
            i += 1
        pylab.xlabel( "Time (s)" )
        pylab.ylabel( "Rate (Hz)" )
        pylab.legend()
        pylab.show()
Beispiel #10
0
def makeGlobalBalanceNetwork():
    stim = moose.RandSpike('/model/stim', params['numInputs'])
    inhib = moose.LIF('/model/inhib', params['numInhib'])
    insyn = moose.SimpleSynHandler(inhib.path + '/syns', params['numInhib'])
    moose.connect(insyn, 'activationOut', inhib, 'activation', 'OneToOne')
    output = moose.LIF('/model/output', params['numOutput'])
    outsyn = moose.SimpleSynHandler(output.path + '/syns', params['numOutput'])
    moose.connect(outsyn, 'activationOut', output, 'activation', 'OneToOne')
    outInhSyn = moose.SimpleSynHandler(output.path + '/inhsyns',
                                       params['numOutput'])
    moose.connect(outInhSyn, 'activationOut', output, 'activation', 'OneToOne')

    iv = moose.vec(insyn.path + '/synapse')
    ov = moose.vec(outsyn.path + '/synapse')
    oiv = moose.vec(outInhSyn.path + '/synapse')

    temp = moose.connect(stim, 'spikeOut', iv, 'addSpike', 'Sparse')
    inhibMatrix = moose.element(temp)
    inhibMatrix.setRandomConnectivity(params['stimToInhProb'],
                                      params['stimToInhSeed'])
    cl = inhibMatrix.connectionList
    expectedCl = [
        1, 4, 13, 13, 26, 42, 52, 56, 80, 82, 95, 97, 4, 9, 0, 9, 4, 8, 0, 6,
        1, 6, 6, 7
    ]
    assert list(cl) == expectedCl, "Expected %s, got %s" % (expectedCl, cl)

    temp = moose.connect(stim, 'spikeOut', ov, 'addSpike', 'Sparse')
    excMatrix = moose.element(temp)
    excMatrix.setRandomConnectivity(params['stimToOutProb'],
                                    params['stimToOutSeed'])

    temp = moose.connect(inhib, 'spikeOut', oiv, 'addSpike', 'Sparse')
    negFFMatrix = moose.element(temp)
    negFFMatrix.setRandomConnectivity(params['inhToOutProb'],
                                      params['inhToOutSeed'])

    # print("ConnMtxEntries: ", inhibMatrix.numEntries, excMatrix.numEntries, negFFMatrix.numEntries)
    assert (12, 57, 48) == (inhibMatrix.numEntries, excMatrix.numEntries,
                            negFFMatrix.numEntries)

    cl = negFFMatrix.connectionList
    numInhSyns = []
    niv = 0
    nov = 0
    noiv = 0
    for i in moose.vec(insyn):
        niv += i.synapse.num
        numInhSyns.append(i.synapse.num)
        if i.synapse.num > 0:
            i.synapse.weight = params['wtStimToInh']

    assert numInhSyns == [2, 1, 0, 0, 2, 0, 3, 1, 1, 2]

    for i in moose.vec(outsyn):
        nov += i.synapse.num
        if i.synapse.num > 0:
            i.synapse.weight = params['wtStimToOut']
    for i in moose.vec(outInhSyn):
        noiv += i.synapse.num
        #print i.synapse.num
        if i.synapse.num > 0:
            i.synapse.weight = params['wtInhToOut']

    # print("SUMS: ", sum( iv.numField ), sum( ov.numField ), sum( oiv.numField ))
    assert [4, 49,
            9] == [sum(iv.numField),
                   sum(ov.numField),
                   sum(oiv.numField)]
    # print("SUMS2: ", niv, nov, noiv)
    assert [12, 57, 48] == [niv, nov, noiv]
    # print("SUMS3: ", sum( insyn.vec.numSynapses ), sum( outsyn.vec.numSynapses ), sum( outInhSyn.vec.numSynapses ))
    assert [12, 57, 48] == [
        sum(insyn.vec.numSynapses),
        sum(outsyn.vec.numSynapses),
        sum(outInhSyn.vec.numSynapses)
    ]

    # print(oiv.numField)
    # print(insyn.vec[1].synapse.num)
    # print(insyn.vec.numSynapses)
    # print(sum( insyn.vec.numSynapses ))
    # niv = iv.numSynapses
    # ov = iv.numSynapses

    sv = moose.vec(stim)
    sv.rate = params['randInputRate']
    sv.refractT = params['randRefractTime']
    #moose.showfield( sv[7] )

    inhib.vec.thresh = params['inhibThresh']
    inhib.vec.Rm = params['Rm']
    inhib.vec.Cm = params['Cm']
    inhib.vec.vReset = params['inhVreset']
    inhib.vec.refractoryPeriod = params['inhibRefractTime']
    output.vec.thresh = params['outputThresh']
    output.vec.Rm = params['Rm']
    output.vec.Cm = params['Cm']
    output.vec.refractoryPeriod = params['outputRefractTime']
    otab = moose.Table('/model/otab', params['numOutput'])
    moose.connect(otab, 'requestOut', output, 'getVm', 'OneToOne')
    itab = moose.Table('/model/itab', params['numInhib'])
    moose.connect(itab, 'requestOut', inhib, 'getVm', 'OneToOne')
    return inhib, output
def main():
    """
    Simulate a pseudo-STDP protocol and plot the STDP kernel
    that emerges from Ca plasticity of Graupner and Brunel 2012.

    Author: Aditya Gilra, NCBS, Bangalore, October, 2014.
    """

    # ###########################################
    # Neuron models
    # ###########################################

    ## Leaky integrate and fire neuron
    Vrest = -65e-3  # V      # resting potential
    Vt_base = -45e-3  # V    # threshold
    Vreset = -55e-3  # V     # in current steps, Vreset is same as pedestal
    R = 1e8  # Ohm
    tau = 10e-3  # s
    refrT = 2e-3  # s

    # ###########################################
    # Initialize neuron group
    # ###########################################

    ## two neurons: index 0 will be presynaptic, 1 will be postsynaptic
    network = moose.LIF('network', 2)
    moose.le('/network')
    network.vec.Em = Vrest
    network.vec.thresh = Vt_base
    network.vec.refractoryPeriod = refrT
    network.vec.Rm = R
    network.vec.vReset = Vreset
    network.vec.Cm = tau / R
    network.vec.inject = 0.
    network.vec.initVm = Vrest

    #############################################
    # Ca Plasticity parameters: synapses (not for ExcInhNetBase)
    #############################################

    ### Cortical slice values -- Table Suppl 2 in Graupner & Brunel 2012
    ### Also used in Higgins et al 2014
    #tauCa = 22.6936e-3      # s # Ca decay time scale
    #tauSyn = 346.3615       # s # synaptic plasticity time scale
    ### in vitro values in Higgins et al 2014, faster plasticity
    #CaPre = 0.56175         # mM
    #CaPost = 1.2964         # mM
    ### in vivo values in Higgins et al 2014, slower plasticity
    ##CaPre = 0.33705         # mM
    ##CaPost = 0.74378        # mM
    #delayD = 4.6098e-3      # s # CaPre is added to Ca after this delay
    ## proxy for rise-time of NMDA
    #thetaD = 1.0            # mM # depression threshold for Ca
    #thetaP = 1.3            # mM # potentiation threshold for Ca
    #gammaD = 331.909        # factor for depression term
    #gammaP = 725.085        # factor for potentiation term

    #J = 5e-3 # V            # delta function synapse, adds to Vm
    #weight = 0.43           # initial synaptic weight
    ## gammaP/(gammaP+gammaD) = eq weight w/o noise
    ## see eqn (22), noiseSD also appears
    ## but doesn't work here,
    ## weights away from 0.4 - 0.5 screw up the STDP rule!!

    #bistable = True        # if bistable is True, use bistable potential for weights
    #noisy = False          # use noisy weight updates given by noiseSD
    #noiseSD = 3.3501        # if noisy, use noiseSD (3.3501 from Higgins et al 2014)

    ########################################

    ## DP STDP curve (Fig 2C) values -- Table Suppl 1 in Graupner & Brunel 2012
    tauCa = 20e-3  # s # Ca decay time scale
    tauSyn = 150.0  # s # synaptic plasticity time scale
    CaPre = 1.0  # arb
    CaPost = 2.0  # arb
    delayD = 13.7e-3  # s # CaPre is added to Ca after this delay
    # proxy for rise-time of NMDA
    thetaD = 1.0  # mM # depression threshold for Ca
    thetaP = 1.3  # mM # potentiation threshold for Ca
    gammaD = 200.0  # factor for depression term
    gammaP = 321.808  # factor for potentiation term

    J = 5e-3  # V            # delta function synapse, adds to Vm
    weight = 0.5  # initial synaptic weight
    # gammaP/(gammaP+gammaD) = eq weight w/o noise
    # see eqn (22), noiseSD also appears
    # but doesn't work here,
    # weights away from 0.4 - 0.5 screw up the STDP rule!!

    bistable = True  # if bistable is True, use bistable potential for weights
    noisy = False  # use noisy weight updates given by noiseSD
    noiseSD = 2.8284  # if noisy, use noiseSD (3.3501 in Higgins et al 2014)

    ##########################################

    syn = moose.GraupnerBrunel2012CaPlasticitySynHandler('/network/syn')
    syn.numSynapses = 1  # 1 synapse
    # many pre-synaptic inputs can connect to a synapse
    # synapse onto postsynaptic neuron
    moose.connect(syn, 'activationOut', network.vec[1], 'activation')

    # synapse from presynaptic neuron
    moose.connect(network.vec[0], 'spikeOut', syn.synapse[0], 'addSpike')

    # post-synaptic spikes also needed for STDP
    moose.connect(network.vec[1], 'spikeOut', syn, 'addPostSpike')

    syn.synapse[0].delay = 0.0
    syn.synapse[0].weight = weight
    syn.CaInit = 0.0
    syn.tauCa = tauCa
    syn.tauSyn = tauSyn
    syn.CaPre = CaPre
    syn.CaPost = CaPost
    syn.delayD = delayD
    syn.thetaD = thetaD
    syn.thetaP = thetaP
    syn.gammaD = gammaD
    syn.gammaP = gammaP
    syn.weightScale = J  # weight ~1, weightScale ~ J
    # weight*weightScale is activation,
    # i.e. delta-fn added to postsynaptic Vm

    syn.weightMax = 1.0  # bounds on the weight
    syn.weightMin = 0.

    syn.noisy = noisy
    syn.noiseSD = noiseSD
    syn.bistable = bistable

    # ###########################################
    # Setting up tables
    # ###########################################

    Vms = moose.Table('/plotVms', 2)
    moose.connect(network, 'VmOut', Vms, 'input', 'OneToOne')
    spikes = moose.Table('/plotSpikes', 2)
    moose.connect(network, 'spikeOut', spikes, 'input', 'OneToOne')
    CaTable = moose.Table('/plotCa', 1)
    moose.connect(CaTable, 'requestOut', syn, 'getCa')
    WtTable = moose.Table('/plotWeight', 1)
    moose.connect(WtTable, 'requestOut', syn.synapse[0], 'getWeight')

    # ###########################################
    # Simulate the STDP curve with spaced pre-post spike pairs
    # ###########################################

    dt = 1e-3  # s
    # moose simulation
    moose.useClock(0, '/network/syn', 'process')
    moose.useClock(1, '/network', 'process')
    moose.useClock(2, '/plotSpikes', 'process')
    moose.useClock(3, '/plotVms', 'process')
    moose.useClock(3, '/plotCa', 'process')
    moose.useClock(3, '/plotWeight', 'process')
    moose.setClock(0, dt)
    moose.setClock(1, dt)
    moose.setClock(2, dt)
    moose.setClock(3, dt)
    moose.setClock(9, dt)
    moose.reinit()

    # function to make the aPlus and aMinus settle to equilibrium values
    settletime = 100e-3  # s

    def reset_settle():
        """ Call this between every pre-post pair
        to reset the neurons and make them settle to rest.
        """
        syn.synapse[0].weight = weight
        syn.Ca = 0.0
        moose.start(settletime)
        # Ca gets a jump at pre-spike+delayD
        # So this event can occur during settletime
        # So set Ca and weight once more after settletime
        syn.synapse[0].weight = weight
        syn.Ca = 0.0

    # function to inject a sharp current pulse to make neuron spike
    # immediately at a given time step
    def make_neuron_spike(nrnidx, I=1e-7, duration=1e-3):
        """ Inject a brief current pulse to
        make a neuron spike
        """
        network.vec[nrnidx].inject = I
        moose.start(duration)
        network.vec[nrnidx].inject = 0.

    dwlist_neg = []
    ddt = 2e-3  # s
    # since CaPlasticitySynHandler is event based
    # multiple pairs are needed for Ca to be registered above threshold
    # Values from Fig 2, last line of legend
    numpairs = 60  # number of spike parts per deltat
    t_between_pairs = 1.0  # time between each spike pair
    t_extent = 100e-3  # s  # STDP kernel extent,
    # t_extent > t_between_pairs/2 inverts pre-post pairing!
    # dt = tpost - tpre
    # negative dt corresponds to post before pre
    print('-----------------------------------------------')
    for deltat in arange(t_extent, 0.0, -ddt):
        reset_settle()
        for i in range(numpairs):
            # post neuron spike
            make_neuron_spike(1)
            moose.start(deltat)
            # pre neuron spike after deltat
            make_neuron_spike(0)
            moose.start(
                t_between_pairs)  # weight changes after pre-spike+delayD
            # must run for at least delayD after pre-spike
        dw = (syn.synapse[0].weight - weight) / weight
        print(('post before pre, dt = %1.3f s, dw/w = %1.3f' % (-deltat, dw)))
        dwlist_neg.append(dw)
    print('-----------------------------------------------')
    # positive dt corresponds to pre before post
    dwlist_pos = []
    for deltat in arange(ddt, t_extent + ddt, ddt):
        reset_settle()
        for i in range(numpairs):
            # pre neuron spike
            make_neuron_spike(0)
            moose.start(deltat)
            # post neuron spike after deltat
            make_neuron_spike(1)
            moose.start(t_between_pairs)
        dw = (syn.synapse[0].weight - weight) / weight
        print(('pre before post, dt = %1.3f s, dw/w = %1.3f' % (deltat, dw)))
        dwlist_pos.append(dw)
    print('-----------------------------------------------')
    print(('Each of the above pre-post pairs was repeated',\
            numpairs,'times, with',t_between_pairs,'s between pairs.'))
    print()
    print('Due to event based updates, Ca decays suddenly at events:')
    print('pre-spike, pre-spike + delayD, and post-spike;')
    print('apart from the usual CaPre and CaPost jumps at')
    print('pre-spike + delayD and post-spike respectively.')
    print(
        'Because of the event based update, multiple pre-post pairs are used.')
    print()
    print('If you reduce the t_between_pairs,')
    print(
        ' you\'ll see potentiation for the LTD part without using any triplet rule!'
    )
    print()
    print("If you turn on noise, the weights fluctuate too much,")
    print(" not sure if there's a bug in my noise implementation.")
    print('-----------------------------------------------')

    # ###########################################
    # Plot the simulated Vm-s and STDP curve
    # ###########################################

    # insert spikes so that Vm reset doesn't look weird
    Vmseries0 = Vms.vec[0].vector
    numsteps = len(Vmseries0)
    for t in spikes.vec[0].vector:
        Vmseries0[int(t / dt) - 1] = 30e-3  # V
    Vmseries1 = Vms.vec[1].vector
    for t in spikes.vec[1].vector:
        Vmseries1[int(t / dt) - 1] = 30e-3  # V

    timeseries = linspace(0., 1000 * numsteps * dt, numsteps)
    # Voltage plots
    figure(facecolor='w')
    plot(timeseries, Vmseries0, color='r')  # pre neuron's vm
    plot(timeseries, Vmseries1, color='b')  # post neuron's vm
    xlabel('time (ms)')
    ylabel('Vm (V)')
    title("pre (r) and post (b) neurons' Vm")

    # Ca plots for the synapse
    figure(facecolor='w')
    plot(timeseries, CaTable.vector[:len(timeseries)], color='r')
    plot((timeseries[0],timeseries[-1]),(thetaP,thetaP),color='k',\
        linestyle='dashed',label='pot thresh')
    plot((timeseries[0],timeseries[-1]),(thetaD,thetaD),color='b',\
        linestyle='dashed',label='dep thresh')
    legend()
    xlabel('time (ms)')
    ylabel('Ca (arb)')
    title("Ca conc in the synapse")

    # Weight plots for the synapse
    figure(facecolor='w')
    plot(timeseries, WtTable.vector[:len(timeseries)], color='r')
    xlabel('time (ms)')
    ylabel('Efficacy')
    title("Efficacy of the synapse")

    # STDP curve
    fig = figure(facecolor='w')
    ax = fig.add_subplot(111)
    ax.plot(arange(-t_extent, 0, ddt) * 1000, array(dwlist_neg), '.-r')
    ax.plot(
        arange(ddt, (t_extent + ddt), ddt) * 1000, array(dwlist_pos), '.-b')
    xmin, xmax = ax.get_xlim()
    ymin, ymax = ax.get_ylim()
    ax.set_xticks([xmin, 0, xmax])
    ax.set_yticks([ymin, 0, ymax])
    ax.plot((0, 0), (ymin, ymax), linestyle='dashed', color='k')
    ax.plot((xmin, xmax), (0, 0), linestyle='dashed', color='k')
    ax.set_xlabel('$t_{post}-t_{pre}$ (ms)')
    ax.set_ylabel('$\Delta w / w$')
    fig.tight_layout()
    #fig.subplots_adjust(hspace=0.3,wspace=0.5) # use after tight_layout()

    show()