def connectUsingSynChan(self, synName, prePath, post_path
            , weight, threshold, delay
            ):
        """
        Connect two compartments using SynChan
        """

        postcomp = moose.Compartment(post_path)

        # We usually try to reuse an existing SynChan - event based SynChans
        # have an array of weights and delays and can represent multiple
        # synapses i.e.  a new element of the weights and delays array is
        # created every time a 'synapse' message connects to the SynChan (from
        # 'event' of spikegen) BUT for a graded synapse with a lookup table
        # output connected to 'activation' message, not to 'synapse' message, we
        # make a new synapse everytime ALSO for a saturating synapse i.e.
        # KinSynChan, we always make a new synapse as KinSynChan is not meant to
        # represent multiple synapses
        libsyn = moose.SynChan(self.libraryPath+'/'+synName)
        gradedchild = utils.get_child_Mstring(libsyn, 'graded')

        # create a new synapse
        if libsyn.className == 'KinSynChan' or gradedchild.value == 'True': 
            synNameFull = moose_methods.moosePath(synName
                    , utils.underscorize(prePath)
                    )
            synObj = self.makeNewSynapse(synName, postcomp, synNameFull)
        else:
            # See debug/bugs for more details.
            # NOTE: Change the debug/bugs to enable/disable this bug.
            if bugs.BUG_NetworkML_500:
                utils.dump("INFO"
                        , "See the code. There might be a bug here"
                        , frame = inspect.currentframe()
                        )
                synNameFull = moose_methods.moosePath(synName
                        , utils.underscorize(prePath)
                        )
                synObj = self.makeNewSynapse(synName, postcomp, synNameFull)

            else: # If the above bug is fixed.
                synNameFull = synName
                if not moose.exists(post_path+'/'+synNameFull):
                    synObj = self.makeNewSynapse(synName, postcomp, synNameFull)

        # wrap the synapse in this compartment
        synPath = moose_methods.moosePath(post_path, synNameFull)
        syn = moose.SynChan(synPath)

        gradedchild = utils.get_child_Mstring(syn, 'graded')

        # weights are set at the end according to whether the synapse is graded
        # or event-based


        # connect pre-comp Vm (if graded) OR spikegen/timetable (if event-based)
        # to the synapse

        # graded synapse
        if gradedchild.value=='True': 
            table = moose.Table(syn.path+"/graded_table")
            # always connect source to input - else 'cannot create message'
            # error.
            precomp = moose.Compartment(prePath)
            self.connectWrapper(precomp, "VmOut", table, "msgInput")

            # since there is no weight field for a graded synapse
            # (no 'synapse' message connected),
            # I set the Gbar to weight*Gbar
            syn.Gbar = weight * syn.Gbar

        # Event based synapse
        else: 
            # synapse could be connected to spikegen at pre-compartment OR a
            # file!
            if 'file' not in prePath:
                precomp = moose.Compartment(prePath)
                if not moose.exists(prePath+'/IaF_spikegen'):
                    # if spikegen for this synapse doesn't exist in this
                    # compartment, create it spikegens for different synapse_types
                    # can have different thresholds
                    if not moose.exists(prePath+'/'+synName+'_spikegen'):
                        spikegen = moose.SpikeGen(prePath+'/'+synName+'_spikegen')
                        # spikegens for different synapse_types can have different
                        # thresholds
                        spikegen.threshold = threshold
                        # This ensures that spike is generated only on leading edge.
                        spikegen.edgeTriggered = 1 

                        # usually events are raised at every time step that Vm >
                        # Threshold, can set either edgeTriggered as above or
                        # refractT
                        #spikegen.refractT = 0.25e-3 


                    # wrap the spikegen in this compartment
                    spikegen = moose.SpikeGen(prePath+'/'+synName+'_spikegen') 
                else:
                    spikegen = moose.SpikeGen(prePath+'/IaF_spikegen')

                # connect the spikegen to the synapse note that you need to use
                # Synapse (auto-created) under SynChan to get/set weights ,
                # addSpike-s etc.  can get the Synapse element by
                # moose.Synapse(syn.path+'/synapse') or syn.synapse Synpase is
                # an array element, first add to it, to addSpike-s, get/set
                # weights, etc.


                syn.numSynapses += 1
                m = self.connectSynapse(spikegen, syn)

            else:
                # if connected to a file, create a timetable,
                # put in a field specifying the connected filenumbers to this segment,
                # and leave it for simulation-time connection
                ## prePath is 'file[+<glomnum>]_<filenum1>[_<filenum2>...]' i.e. glomnum could be present
                filesplit = prePath.split('+')
                if len(filesplit) == 2:
                    glomsplit = filesplit[1].split('_', 1)
                    glomstr = '_'+glomsplit[0]
                    filenums = glomsplit[1]
                else:
                    glomstr = ''
                    filenums = prePath.split('_', 1)[1]
                tt_path = postcomp.path+'/'+synNameFull+glomstr+'_tt'
                if not moose.exists(tt_path):
                    # if timetable for this synapse doesn't exist in this
                    # compartment, create it, and add the field 'fileNumbers'
                    tt = moose.TimeTable(tt_path)
                    tt.addField('fileNumbers')
                    tt.setField('fileNumbers',filenums)

                    # Be careful to connect the timetable only once while
                    # creating it as below: note that you need to use Synapse
                    # (auto-created) under SynChan to get/set weights ,
                    # addSpike-s etc.  can get the Synapse element by
                    # moose.Synapse(syn.path+'/synapse') or syn.synapse Synpase
                    # is an array element, first add to it, to addSpike-s,
                    # get/set weights, etc.
                    syn.numSynapses += 1
                    m = self.connectSynapse(spikegen, syn.synapse)
                else:
                    # if it exists, append file number to the field 'fileNumbers'
                    tt = moose.TimeTable(tt_path)
                    # append filenumbers from
                    # 'file[+<glomnum>]_<filenumber1>[_<filenumber2>...]'
                    filenums = moose_methods.moosePath(tt.getField('fileNumbers')
                            , filenums)
                    tt.setField('fileNumbers', filenums)

            # syn.Gbar remains the same, but we play with the weight which is a
            # factor to Gbar 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 first
            # argument below is the array index, we connect to the latest
            # synapse created above But KinSynChan ignores weight of the
            # synapse, so set the Gbar for it
            if libsyn.className == 'KinSynChan':
                syn.Gbar = weight*syn.Gbar
            else:
                # note that you need to use Synapse (auto-created) under SynChan
                # to get/set weights , addSpike-s etc.  can get the Synpase
                # element by moose.Synapse(syn.path+'/synapse') or syn.synapse
                syn.synapse[-1].weight = weight
            syn.synapse[-1].delay = delay # seconds
示例#2
0
    def connectUsingSynChan(self, synName, prePath, post_path, weight,
                            threshold, delay):
        """
        Connect two compartments using SynChan
        """

        postcomp = moose.Compartment(post_path)

        # We usually try to reuse an existing SynChan - event based SynChans
        # have an array of weights and delays and can represent multiple
        # synapses i.e.  a new element of the weights and delays array is
        # created every time a 'synapse' message connects to the SynChan (from
        # 'event' of spikegen) BUT for a graded synapse with a lookup table
        # output connected to 'activation' message, not to 'synapse' message, we
        # make a new synapse everytime ALSO for a saturating synapse i.e.
        # KinSynChan, we always make a new synapse as KinSynChan is not meant to
        # represent multiple synapses
        libsyn = moose.SynChan(self.libraryPath + '/' + synName)
        gradedchild = utils.get_child_Mstring(libsyn, 'graded')

        # create a new synapse
        if libsyn.className == 'KinSynChan' or gradedchild.value == 'True':
            synNameFull = moose_methods.moosePath(synName,
                                                  utils.underscorize(prePath))
            synObj = self.makeNewSynapse(synName, postcomp, synNameFull)
        else:
            # See debug/bugs for more details.
            # NOTE: Change the debug/bugs to enable/disable this bug.
            if bugs.BUG_NetworkML_500:
                utils.dump("INFO",
                           "See the code. There might be a bug here",
                           frame=inspect.currentframe())
                synNameFull = moose_methods.moosePath(
                    synName, utils.underscorize(prePath))
                synObj = self.makeNewSynapse(synName, postcomp, synNameFull)

            else:  # If the above bug is fixed.
                synNameFull = synName
                if not moose.exists(post_path + '/' + synNameFull):
                    synObj = self.makeNewSynapse(synName, postcomp,
                                                 synNameFull)

        # wrap the synapse in this compartment
        synPath = moose_methods.moosePath(post_path, synNameFull)
        syn = moose.SynChan(synPath)

        gradedchild = utils.get_child_Mstring(syn, 'graded')

        # weights are set at the end according to whether the synapse is graded
        # or event-based

        # connect pre-comp Vm (if graded) OR spikegen/timetable (if event-based)
        # to the synapse

        # graded synapse
        if gradedchild.value == 'True':
            table = moose.Table(syn.path + "/graded_table")
            # always connect source to input - else 'cannot create message'
            # error.
            precomp = moose.Compartment(prePath)
            self.connectWrapper(precomp, "VmOut", table, "msgInput")

            # since there is no weight field for a graded synapse
            # (no 'synapse' message connected),
            # I set the Gbar to weight*Gbar
            syn.Gbar = weight * syn.Gbar

        # Event based synapse
        else:
            # synapse could be connected to spikegen at pre-compartment OR a
            # file!
            if 'file' not in prePath:
                precomp = moose.Compartment(prePath)
                if not moose.exists(prePath + '/IaF_spikegen'):
                    # if spikegen for this synapse doesn't exist in this
                    # compartment, create it spikegens for different synapse_types
                    # can have different thresholds
                    if not moose.exists(prePath + '/' + synName + '_spikegen'):
                        spikegen = moose.SpikeGen(prePath + '/' + synName +
                                                  '_spikegen')
                        # spikegens for different synapse_types can have different
                        # thresholds
                        spikegen.threshold = threshold
                        # This ensures that spike is generated only on leading edge.
                        spikegen.edgeTriggered = 1

                        # usually events are raised at every time step that Vm >
                        # Threshold, can set either edgeTriggered as above or
                        # refractT
                        #spikegen.refractT = 0.25e-3

                    # wrap the spikegen in this compartment
                    spikegen = moose.SpikeGen(prePath + '/' + synName +
                                              '_spikegen')
                else:
                    spikegen = moose.SpikeGen(prePath + '/IaF_spikegen')

                # connect the spikegen to the synapse note that you need to use
                # Synapse (auto-created) under SynChan to get/set weights ,
                # addSpike-s etc.  can get the Synapse element by
                # moose.Synapse(syn.path+'/synapse') or syn.synapse Synpase is
                # an array element, first add to it, to addSpike-s, get/set
                # weights, etc.

                syn.numSynapses += 1
                m = self.connectSynapse(spikegen, syn)

            else:
                # if connected to a file, create a timetable,
                # put in a field specifying the connected filenumbers to this segment,
                # and leave it for simulation-time connection
                ## prePath is 'file[+<glomnum>]_<filenum1>[_<filenum2>...]' i.e. glomnum could be present
                filesplit = prePath.split('+')
                if len(filesplit) == 2:
                    glomsplit = filesplit[1].split('_', 1)
                    glomstr = '_' + glomsplit[0]
                    filenums = glomsplit[1]
                else:
                    glomstr = ''
                    filenums = prePath.split('_', 1)[1]
                tt_path = postcomp.path + '/' + synNameFull + glomstr + '_tt'
                if not moose.exists(tt_path):
                    # if timetable for this synapse doesn't exist in this
                    # compartment, create it, and add the field 'fileNumbers'
                    tt = moose.TimeTable(tt_path)
                    tt.addField('fileNumbers')
                    tt.setField('fileNumbers', filenums)

                    # Be careful to connect the timetable only once while
                    # creating it as below: note that you need to use Synapse
                    # (auto-created) under SynChan to get/set weights ,
                    # addSpike-s etc.  can get the Synapse element by
                    # moose.Synapse(syn.path+'/synapse') or syn.synapse Synpase
                    # is an array element, first add to it, to addSpike-s,
                    # get/set weights, etc.
                    syn.numSynapses += 1
                    m = self.connectSynapse(spikegen, syn.synapse)
                else:
                    # if it exists, append file number to the field 'fileNumbers'
                    tt = moose.TimeTable(tt_path)
                    # append filenumbers from
                    # 'file[+<glomnum>]_<filenumber1>[_<filenumber2>...]'
                    filenums = moose_methods.moosePath(
                        tt.getField('fileNumbers'), filenums)
                    tt.setField('fileNumbers', filenums)

            # syn.Gbar remains the same, but we play with the weight which is a
            # factor to Gbar 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 first
            # argument below is the array index, we connect to the latest
            # synapse created above But KinSynChan ignores weight of the
            # synapse, so set the Gbar for it
            if libsyn.className == 'KinSynChan':
                syn.Gbar = weight * syn.Gbar
            else:
                # note that you need to use Synapse (auto-created) under SynChan
                # to get/set weights , addSpike-s etc.  can get the Synpase
                # element by moose.Synapse(syn.path+'/synapse') or syn.synapse
                syn.synapse[-1].weight = weight
            syn.synapse[-1].delay = delay  # seconds
示例#3
0
    def addSegment(self, cellName, segnum, segment):

        """
        Adding segment to cell.
        """
        run_dia = 0.0
        running_comp = None
        running_dia_nums = 0
        segmentname = segment.attrib['name']

        debug.printDebug("DEBUG"
                , "Adding segment {} in cell {}".format(segmentname, cellName)
                )

        # cable is an optional attribute. WARNING: Here I assume it is always
        # present.
        cableid = segment.attrib['cable']
        segmentid = segment.attrib['id']

        # Old cableid still running, hence don't start a new compartment, skip
        # to next segment.
        if cableid == self.running_cableid:
            self.cellDictBySegmentId[cellName][1][segmentid] = running_comp
            proximal = segment.find('./{'+self.mml+'}proximal')
            if proximal is not None:
                run_dia += float(proximal.attrib["diameter"])*self.length_factor
                running_dia_nums += 1
            distal = segment.find('./{'+self.mml+'}distal')
            if distal is not None:
                run_dia += float(distal.attrib["diameter"])*self.length_factor
                running_dia_nums += 1

        # new cableid starts, hence start a new compartment; also finish
        # previous / last 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!

            # just segmentname is NOT unique - eg: mitral bbmit exported from
            # NEURON.
            mooseCompname = moose_methods.moosePath(segmentname, segmentid)
            mooseComppath = self.mooseCell.path + '/' + mooseCompname
            mooseComp = moose.Compartment(mooseComppath)
            self.cellDictBySegmentId[cellName][1][segmentid] = mooseComp

            # Cables are grouped and densities set for cablegroups. Hence I
            # need to refer to segment according to which cable they belong
            # to..
            self.cellDictByCableId[cellName][1][cableid] = mooseComp
            self.running_cableid = cableid
            running_segid = segmentid
            running_comp = mooseComp
            run_dia = 0.0
            running_dia_nums = 0

            if 'parent' in segment.attrib:
                # I assume the parent is created before the child so that I can
                # immediately # connect the child.
                parentid = segment.attrib['parent']
                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
                run_dia += float(proximal.attrib["diameter"])*self.length_factor
                running_dia_nums += 1
            distal = segment.find('./{'+self.mml+'}distal')
            if distal is not None:
                run_dia += 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 = run_dia / 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:
                debug.printDebug(
                    "STEP"
                    , "Set up compartment/section %s" % running_comp.name
                )
示例#4
0
    def addSegment(self, cellName, segnum, segment):
        """
        Adding segment to cell.
        """
        run_dia = 0.0
        running_comp = None
        running_dia_nums = 0
        segmentname = segment.attrib['name']

        debug.printDebug(
            "DEBUG",
            "Adding segment {} in cell {}".format(segmentname, cellName))

        # cable is an optional attribute. WARNING: Here I assume it is always
        # present.
        cableid = segment.attrib['cable']
        segmentid = segment.attrib['id']

        # Old cableid still running, hence don't start a new compartment, skip
        # to next segment.
        if cableid == self.running_cableid:
            self.cellDictBySegmentId[cellName][1][segmentid] = running_comp
            proximal = segment.find('./{' + self.mml + '}proximal')
            if proximal is not None:
                run_dia += float(
                    proximal.attrib["diameter"]) * self.length_factor
                running_dia_nums += 1
            distal = segment.find('./{' + self.mml + '}distal')
            if distal is not None:
                run_dia += float(
                    distal.attrib["diameter"]) * self.length_factor
                running_dia_nums += 1

        # new cableid starts, hence start a new compartment; also finish
        # previous / last 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!

            # just segmentname is NOT unique - eg: mitral bbmit exported from
            # NEURON.
            mooseCompname = moose_methods.moosePath(segmentname, segmentid)
            mooseComppath = self.mooseCell.path + '/' + mooseCompname
            mooseComp = moose.Compartment(mooseComppath)
            self.cellDictBySegmentId[cellName][1][segmentid] = mooseComp

            # Cables are grouped and densities set for cablegroups. Hence I
            # need to refer to segment according to which cable they belong
            # to..
            self.cellDictByCableId[cellName][1][cableid] = mooseComp
            self.running_cableid = cableid
            running_segid = segmentid
            running_comp = mooseComp
            run_dia = 0.0
            running_dia_nums = 0

            if 'parent' in segment.attrib:
                # I assume the parent is created before the child so that I can
                # immediately # connect the child.
                parentid = segment.attrib['parent']
                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
                run_dia += float(
                    proximal.attrib["diameter"]) * self.length_factor
                running_dia_nums += 1
            distal = segment.find('./{' + self.mml + '}distal')
            if distal is not None:
                run_dia += 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 = run_dia / 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:
                debug.printDebug(
                    "STEP",
                    "Set up compartment/section %s" % running_comp.name)