コード例 #1
0
def printNetTree():
    """ Prints all the cells under /, and recursive prints the cell tree for each cell. """
    root = _moose.Neutral('/')
    for id in root.children:  # all subelements of 'root'
        if _moose.Neutral(id).className == 'Cell':
            cell = _moose.Cell(id)
            print "-------------------- CELL : ", cell.name, " ---------------------------"
            printCellTree(cell)
コード例 #2
0
def setupTable(name,
               obj,
               qtyname,
               tables_path=None,
               threshold=None,
               spikegen=None):
    """ Sets up a table with 'name' which stores 'qtyname' field from 'obj'.
    The table is created under tables_path if not None, else under obj.path . """
    if tables_path is None:
        tables_path = obj.path + '/data'
    ## in case tables_path does not exist, below wrapper will create it
    tables_path_obj = _moose.Neutral(tables_path)
    qtyTable = _moose.Table(tables_path_obj.path + '/' + name)
    ## stepMode no longer supported, connect to 'input'/'spike' message dest to record Vm/spiktimes
    # qtyTable.stepMode = TAB_BUF
    if spikegen is None:
        if threshold is None:
            ## below is wrong! reads qty twice every clock tick!
            #_moose.connect( obj, qtyname+'Out', qtyTable, "input")
            ## this is the correct method
            _moose.connect(qtyTable, "requestOut", obj, 'get' + qtyname)
        else:
            ## create new spikegen
            spikegen = _moose.SpikeGen(tables_path_obj.path + '/' + name +
                                       '_spikegen')
            ## connect the compartment Vm to the spikegen
            _moose.connect(obj, "VmOut", spikegen, "Vm")
            ## spikegens for different synapse_types can have different thresholds
            spikegen.threshold = threshold
            spikegen.edgeTriggered = 1  # This ensures that spike is generated only on leading edge.
    else:
        _moose.connect(spikegen, 'spikeOut', qtyTable,
                       'input')  ## spikeGen gives spiketimes
    return qtyTable
コード例 #3
0
def get_matching_children(parent, names):
    """ Returns non-recursive children of 'parent' MOOSE object
    with their names containing any of the strings in list 'names'. """
    matchlist = []
    for childID in parent.children:
        child = _moose.Neutral(childID)
        for name in names:
            if name in child.name:
                matchlist.append(childID)
    return matchlist
コード例 #4
0
def df_traverse(root, operation, *args):
    """Traverse the tree in a depth-first manner and apply the
    operation using *args. The first argument is the root object by
    default."""
    if hasattr(root, '_visited'):
        return
    operation(root, *args)
    for child in root.children:
        childNode = _moose.Neutral(child)
        df_traverse(childNode, operation, *args)
    root._visited = True
コード例 #5
0
def main():
    _moose.Neutral('/cable')
    c1 = _moose.Compartment('/cable/a')
    c2 = _moose.Compartment('/cable/b')
    c1.connect('raxial', c2, 'axial')
    p = _moose.PulseGen('/pulse1')
    p.delay[0] = 0.01
    p.level[0] = 1e-9
    p.width[0] = 0.10
    p.delay[1] = 0.08
    p.connect('output', c1, 'injectMsg')
    s = Spice()
    print s.writeSpice(output='test_spice.spice')
コード例 #6
0
def printRecursiveTree(elementid, level):
    """ Recursive helper function for printCellTree,
    specify depth/'level' to recurse and print subelements under MOOSE 'elementid'. """
    spacefill = '  ' * level
    element = _moose.Neutral(elementid)
    for childid in element.children:
        childobj = _moose.Neutral(childid)
        classname = childobj.className
        if classname in ['SynChan', 'KinSynChan']:
            childobj = _moose.SynChan(childid)
            print spacefill + "|--", childobj.name, childobj.className, 'Gbar=', childobj.Gbar, 'numSynapses=', childobj.numSynapses
            return  # Have yet to figure out the children of SynChan, currently not going deeper
        elif classname in ['HHChannel', 'HHChannel2D']:
            childobj = _moose.HHChannel(childid)
            print spacefill + "|--", childobj.name, childobj.className, 'Gbar=', childobj.Gbar, 'Ek=', childobj.Ek
        elif classname in ['CaConc']:
            childobj = _moose.CaConc(childid)
            print spacefill + "|--", childobj.name, childobj.className, 'thick=', childobj.thick, 'B=', childobj.B
        elif classname in ['Mg_block']:
            childobj = _moose.Mg_block(childid)
            print spacefill + "|--", childobj.name, childobj.className, 'CMg', childobj.CMg, 'KMg_A', childobj.KMg_A, 'KMg_B', childobj.KMg_B
        elif classname in ['SpikeGen']:
            childobj = _moose.SpikeGen(childid)
            print spacefill + "|--", childobj.name, childobj.className, 'threshold', childobj.threshold
        elif classname in ['Func']:
            childobj = _moose.Func(childid)
            print spacefill + "|--", childobj.name, childobj.className, 'expr', childobj.expr
        elif classname in [
                'Table'
        ]:  # Table gives segfault if printRecursiveTree is called on it
            return  # so go no deeper
        #for inmsg in childobj.inMessages():
        #    print spacefill+"  |---", inmsg
        #for outmsg in childobj.outMessages():
        #    print spacefill+"  |---", outmsg
        if len(childobj.children) > 0:
            printRecursiveTree(childid, level + 1)
コード例 #7
0
def blockChannels(cell, channel_list):
    """
    Sets gmax to zero for channels of the 'cell' specified in 'channel_list'
    Substring matches in channel_list are allowed
    e.g. 'K' should block all K channels (ensure that you don't use capital K elsewhere in your channel name!)
    """
    for compartmentid in cell.children:  # compartments
        comp = _moose.Compartment(compartmentid)
        for childid in comp.children:
            child = _moose.Neutral(childid)
            if child.className in ['HHChannel', 'HHChannel2D']:
                chan = _moose.HHChannel(childid)
                for channame in channel_list:
                    if channame in chan.name:
                        chan.Gbar = 0.0
コード例 #8
0
def setup_vclamp(compartment, name, delay1, width1, level1, gain=0.5e-5):
    """
    Sets up a voltage clamp with 'name' on MOOSE 'compartment' object:
    adapted from squid.g in DEMOS (moose/genesis)
    Specify the 'delay1', 'width1' and 'level1' of the voltage to be applied to the compartment.
    Typically you need to adjust the PID 'gain'
    For perhaps the Davison 4-compartment mitral or the Davison granule:
    0.5e-5 optimal gain - too high 0.5e-4 drives it to oscillate at high frequency,
    too low 0.5e-6 makes it have an initial overshoot (due to Na channels?)
    Returns a MOOSE table with the PID output.
    """
    ## If /elec doesn't exists it creates /elec and returns a reference to it.
    ## If it does, it just returns its reference.
    _moose.Neutral('/elec')
    pulsegen = _moose.PulseGen('/elec/pulsegen' + name)
    vclamp = _moose.DiffAmp('/elec/vclamp' + name)
    vclamp.saturation = 999.0
    vclamp.gain = 1.0
    lowpass = _moose.RC('/elec/lowpass' + name)
    lowpass.R = 1.0
    lowpass.C = 50e-6  # 50 microseconds tau
    PID = _moose.PIDController('/elec/PID' + name)
    PID.gain = gain
    PID.tau_i = 20e-6
    PID.tau_d = 5e-6
    PID.saturation = 999.0
    # All connections should be written as source.connect('',destination,'')
    pulsegen.connect('outputSrc', lowpass, 'injectMsg')
    lowpass.connect('outputSrc', vclamp, 'plusDest')
    vclamp.connect('outputSrc', PID, 'commandDest')
    PID.connect('outputSrc', compartment, 'injectMsg')
    compartment.connect('VmSrc', PID, 'sensedDest')

    pulsegen.trigMode = 0  # free run
    pulsegen.baseLevel = -70e-3
    pulsegen.firstDelay = delay1
    pulsegen.firstWidth = width1
    pulsegen.firstLevel = level1
    pulsegen.secondDelay = 1e6
    pulsegen.secondLevel = -70e-3
    pulsegen.secondWidth = 0.0

    vclamp_I = _moose.Table("/elec/vClampITable" + name)
    vclamp_I.stepMode = TAB_BUF  #TAB_BUF: table acts as a buffer.
    vclamp_I.connect("inputRequest", PID, "output")
    vclamp_I.useClock(PLOTCLOCK)

    return vclamp_I
コード例 #9
0
def tweak_field(moose_wildcard, field, assignment_string):
    """Tweak a specified field of all objects that match the
    moose_wildcard using assignment string. All identifiers in
    assignment string must be fields of the target object.

    Example:

    tweak_field('/mycell/##[Class=Compartment]', 'Rm', '1.5 / (3.1416 * diameter * length')

    will assign Rm to every compartment in mycell such that the
    specific membrane resistance is 1.5 Ohm-m2.
    """
    if not isinstance(moose_wildcard, str):
        raise TypeError('moose_wildcard must be a string.')
    id_list = _moose.getWildcardList(moose_wildcard, True)
    expression = parser.expr(assignment_string)
    expr_list = expression.tolist()

    # This is a hack: I just tried out some possible syntax trees and
    # hand coded the replacement such that any identifier is replaced
    # by moose_obj.identifier
    def replace_fields_with_value(x):
        if len(x) > 1:
            if x[0] == symbol.power and x[1][0] == symbol.atom and x[1][1][
                    0] == token.NAME:
                field = x[1][1][1]
                x[1] = [symbol.atom, [token.NAME, 'moose_obj']]
                x.append(
                    [symbol.trailer, [token.DOT, '.'], [token.NAME, field]])
            for item in x:
                if isinstance(item, list):
                    replace_fields_with_value(item)
        return x

    tmp = replace_fields_with_value(expr_list)
    new_expr = parser.sequence2st(tmp)
    code = new_expr.compile()
    for moose_id in id_list:
        moose_obj = eval('_moose.%s(moose_id)' %
                         (_moose.Neutral(moose_id).className))
        value = eval(code)
        _moose.setField(moose_id, field, str(value))
コード例 #10
0
    def test_autoposition(self):
        """Simple check for automatic generation of positions.

        A spherical soma is created with 20 um diameter. A 100
        compartment cable is created attached to it with each
        compartment of length 100 um.

        """
        testid = 'test%s' % (uuid.uuid4())
        container = _moose.Neutral('/test')
        model = _moose.Neuron('/test/%s' % (testid))
        soma = _moose.Compartment('%s/soma' % (model.path))
        soma.diameter = 20e-6
        soma.length = 0.0
        parent = soma
        comps = []
        for ii in range(100):
            comp = _moose.Compartment('%s/comp_%d' % (model.path, ii))
            comp.diameter = 10e-6
            comp.length = 100e-6
            _moose.connect(parent, 'raxial', comp, 'axial')
            comps.append(comp)
            parent = comp
        soma = autoposition(model)
        sigfig = 8
        self.assertAlmostEqual(soma.x0, 0.0, sigfig)
        self.assertAlmostEqual(soma.y0, 0.0, sigfig)
        self.assertAlmostEqual(soma.z0, 0.0, sigfig)
        self.assertAlmostEqual(soma.x, 0.0, sigfig)
        self.assertAlmostEqual(soma.y, 0.0, sigfig)
        self.assertAlmostEqual(soma.z, soma.diameter / 2.0, sigfig)
        for ii, comp in enumerate(comps):
            print comp.path, ii
            self.assertAlmostEqual(comp.x0, 0, sigfig)
            self.assertAlmostEqual(comp.y0, 0.0, sigfig)
            self.assertAlmostEqual(comp.z0, soma.diameter / 2.0 + ii * 100e-6,
                                   sigfig)
            self.assertAlmostEqual(comp.x, 0.0, sigfig)
            self.assertAlmostEqual(comp.y, 0.0, sigfig)
            self.assertAlmostEqual(comp.z,
                                   soma.diameter / 2.0 + (ii + 1) * 100e-6,
                                   sigfig)
コード例 #11
0
def setup_iclamp(compartment, name, delay1, width1, level1):
    """
    Sets up a current clamp with 'name' on MOOSE 'compartment' object:
    Specify the 'delay1', 'width1' and 'level1' of the current pulse to be applied to the compartment.
    Returns the MOOSE pulsegen that sends the current pulse.
    """
    ## If /elec doesn't exists it creates /elec and returns a reference to it.
    ## If it does, it just returns its reference.
    _moose.Neutral('/elec')
    pulsegen = _moose.PulseGen('/elec/pulsegen' + name)
    iclamp = _moose.DiffAmp('/elec/iclamp' + name)
    iclamp.saturation = 1e6
    iclamp.gain = 1.0
    pulsegen.trigMode = 0  # free run
    pulsegen.baseLevel = 0.0
    pulsegen.firstDelay = delay1
    pulsegen.firstWidth = width1
    pulsegen.firstLevel = level1
    pulsegen.secondDelay = 1e6  # to avoid repeat
    pulsegen.secondLevel = 0.0
    pulsegen.secondWidth = 0.0
    pulsegen.connect('output', iclamp, 'plusIn')
    iclamp.connect('output', compartment, 'injectMsg')
    return pulsegen
コード例 #12
0
def resetSim(simpaths, simdt, plotdt, simmethod='hsolve'):
    """ For each of the MOOSE paths in simpaths, this sets the clocks and finally resets MOOSE.
    If simmethod=='hsolve', it sets up hsolve-s for each Neuron under simpaths, and clocks for hsolve-s too. """
    print 'Solver:', simmethod
    _moose.setClock(INITCLOCK, simdt)
    _moose.setClock(ELECCLOCK, simdt)  # The hsolve and ee methods use clock 1
    _moose.setClock(
        CHANCLOCK,
        simdt)  # hsolve uses clock 2 for mg_block, nmdachan and others.
    _moose.setClock(POOLCLOCK, simdt)  # Ca/ion pools & funcs use clock 3
    _moose.setClock(STIMCLOCK, simdt)  # Ca/ion pools & funcs use clock 3
    _moose.setClock(PLOTCLOCK, plotdt)  # for tables
    for simpath in simpaths:
        ## User can connect [qty]Out of an element to input of Table or
        ## requestOut of Table to get[qty] of the element.
        ## Scheduling the Table to a clock tick, will call process() of the Table
        ## which will send a requestOut and overwrite any value set by input(),
        ## thus adding garbage value to the vector. Hence schedule only if
        ## input message is not connected to the Table.
        for table in _moose.wildcardFind(simpath + '/##[TYPE=Table]'):
            if len(table.neighbors['input']) == 0:
                _moose.useClock(PLOTCLOCK, table.path, 'process')
        _moose.useClock(ELECCLOCK, simpath + '/##[TYPE=PulseGen]', 'process')
        _moose.useClock(STIMCLOCK, simpath + '/##[TYPE=DiffAmp]', 'process')
        _moose.useClock(STIMCLOCK, simpath + '/##[TYPE=VClamp]', 'process')
        _moose.useClock(STIMCLOCK, simpath + '/##[TYPE=PIDController]',
                        'process')
        _moose.useClock(STIMCLOCK, simpath + '/##[TYPE=RC]', 'process')
        _moose.useClock(STIMCLOCK, simpath + '/##[TYPE=TimeTable]', 'process')
        _moose.useClock(ELECCLOCK, simpath + '/##[TYPE=LeakyIaF]', 'process')
        _moose.useClock(ELECCLOCK, simpath + '/##[TYPE=IntFire]', 'process')
        _moose.useClock(ELECCLOCK, simpath + '/##[TYPE=IzhikevichNrn]',
                        'process')
        _moose.useClock(ELECCLOCK, simpath + '/##[TYPE=SpikeGen]', 'process')
        _moose.useClock(ELECCLOCK, simpath + '/##[TYPE=Interpol]', 'process')
        _moose.useClock(ELECCLOCK, simpath + '/##[TYPE=Interpol2D]', 'process')
        _moose.useClock(CHANCLOCK, simpath + '/##[TYPE=HHChannel2D]',
                        'process')
        _moose.useClock(CHANCLOCK, simpath + '/##[TYPE=SynChan]', 'process')
        ## If simmethod is not hsolve, set clocks for the biophysics,
        ## else just put a clock on the hsolve:
        ## hsolve takes care of the clocks for the biophysics
        if 'hsolve' not in simmethod.lower():
            print 'Using exp euler'
            _moose.useClock(INITCLOCK, simpath + '/##[TYPE=Compartment]',
                            'init')
            _moose.useClock(ELECCLOCK, simpath + '/##[TYPE=Compartment]',
                            'process')
            _moose.useClock(CHANCLOCK, simpath + '/##[TYPE=HHChannel]',
                            'process')
            _moose.useClock(POOLCLOCK, simpath + '/##[TYPE=CaConc]', 'process')
            _moose.useClock(POOLCLOCK, simpath + '/##[TYPE=Func]', 'process')
        else:  # use hsolve, one hsolve for each Neuron
            print 'Using hsolve'
            element = _moose.Neutral(simpath)
            for childid in element.children:
                childobj = _moose.Neutral(childid)
                classname = childobj.className
                if classname in ['Neuron']:
                    neuronpath = childobj.path
                    h = _moose.HSolve(neuronpath + '/solve')
                    h.dt = simdt
                    h.target = neuronpath
                    _moose.useClock(INITCLOCK, h.path, 'process')
    _moose.reinit()
コード例 #13
0
def apply_to_tree(moose_wildcard, python_filter=None, value=None):
    """
    Select objects by a moose/genesis wildcard, apply a python filter on them and apply a value on them.

    moose_wildcard - this follows GENESIS convention.

    {path}/#[{condition}] returns all elements directly under {path} that satisfy condition. For example:

    '/mynetwork/mycell_0/#[TYPE=Compartment]'

    will return all Compartment objects directly under mycell_0 in mynetwork.

    '{path}/##[{condition}]' will recursively go through all the
    objects that are under {path} (i.e. children, grandchildren,
    great-grandchildren and so on up to the leaf level) and a list of
    the ones meet {condition} will be obtained.

    Thus, '/mynetwork/##[TYPE=Compartment]' will return all
    compartments under mynetwork or its children, or children thereof
    and so on.

    python_filter - if a single string, it will be taken as a
    fieldname, and value will be assigned to this field. It can also
    be a lambda function returning True or False which will be applied
    to each id in the id list returned by moose wildcard
    search. Remember, the argument to the lambda will be an Id, so it
    is up to you to wrap it into a moose object of appropriate type. An example is:

    lambda moose_id: Compartment(moose_id).diameter <  2e-6

    If your moose_wildcard selected objects of Compartment class, then
    this lambda function will select only those with diameter less
    than 2 um.

    value - can be a lambda function to apply arbitrary operations on
    the selected objects.

    If python_filter is a string it, the return
    value of applying the lambda for value() will assigned to the
    field specified by python_filter.

    But if it is value is a data object and {python_filter} is a
    string, then {value} will be assigned to the field named
    {python_filter}.


    If you want to assign Rm = 1e6 for each compartment in mycell
    whose name match 'axon_*':

    apply_to_tree('/mycell/##[Class=Compartment]',
            lambda x: 'axon_' in Neutral(x).name,
            lambda x: setattr(Compartment(x), 'Rm', 1e6))

    [you must use setattr to assign value to a field because lambda
    functions don't allow assignments].
    """
    if not isinstance(moose_wildcard, str):
        raise TypeError('moose_wildcard must be a string.')
    id_list = _moose.getWildcardList(moose_wildcard, True)
    if isinstance(python_filter, types.LambdaType):
        id_list = [moose_id for moose_id in id_list if python_filter(moose_id)]
    elif isinstance(python_filter, str):
        id_list = [
            moose_id for moose_id in id_list if hasattr(
                eval('_moose.%s(moose_id)' %
                     (_moose.Neutral(moose_id).className)), python_filter)
        ]
    else:
        pass
    if isinstance(value, types.LambdaType):
        if isinstance(python_filter, str):
            for moose_id in id_list:
                moose_obj = eval('_moose.%s(moose_id)' %
                                 (_moose.Neutral(moose_id).className))
                setattr(moose_obj, python_filter, value(moose_id))
        else:
            for moose_id in id_list:
                value(moose_id)
    else:
        if isinstance(python_filter, str):
            for moose_id in id_list:
                moose_obj = eval('_moose.%s(moose_id)' %
                                 (_moose.Neutral(moose_id).className))
                setattr(moose_obj, python_filter, value)
        else:
            raise TypeError(
                'Second argument must be a string specifying a field to assign to when third argument is a value'
            )
コード例 #14
0
    def test_printtree(self):
        s = _moose.Neutral('/cell')
        soma = _moose.Neutral('%s/soma' % (s.path))
        d1 = _moose.Neutral('%s/d1' % (soma.path))
        d2 = _moose.Neutral('%s/d2' % (soma.path))
        d3 = _moose.Neutral('%s/d3' % (d1.path))
        d4 = _moose.Neutral('%s/d4' % (d1.path))
        d5 = _moose.Neutral('%s/d5' % (s.path))
        orig_stdout = sys.stdout
        sys.stdout = _sio()
        printtree(s)
        expected = """
cell
|
|__ soma
|  |
|  |__ d1
|  |  |
|  |  |__ d3
|  |  |
|  |  |__ d4
|  |
|  |__ d2
|
|__ d5
"""
        self.assertEqual(sys.stdout.getvalue(), expected)
        sys.stdout = _sio()
        s1 = _moose.Neutral('cell1')
        c1 = _moose.Neutral('%s/c1' % (s1.path))
        c2 = _moose.Neutral('%s/c2' % (c1.path))
        c3 = _moose.Neutral('%s/c3' % (c1.path))
        c4 = _moose.Neutral('%s/c4' % (c2.path))
        c5 = _moose.Neutral('%s/c5' % (c3.path))
        c6 = _moose.Neutral('%s/c6' % (c3.path))
        c7 = _moose.Neutral('%s/c7' % (c4.path))
        c8 = _moose.Neutral('%s/c8' % (c5.path))
        printtree(s1)
        expected1 = """
cell1
|
|__ c1
   |
   |__ c2
   |  |
   |  |__ c4
   |     |
   |     |__ c7
   |
   |__ c3
      |
      |__ c5
      |  |
      |  |__ c8
      |
      |__ c6
"""
        self.assertEqual(sys.stdout.getvalue(), expected1)
コード例 #15
0
def connect_CaConc(compartment_list, temperature=None):
    """ Connect the Ca pools and channels within each of the compartments in compartment_list
     Ca channels should have a child Mstring named 'ion' with value set in MOOSE.
     Ca dependent channels like KCa should have a child Mstring called 'ionDependency' with value set in MOOSE.
     Call this only after instantiating cell so that all channels and pools have been created. """
    for compartment in compartment_list:
        caconc = None
        for child in compartment.children:
            neutralwrap = _moose.Neutral(child)
            if neutralwrap.className == 'CaConc':
                caconc = _moose.CaConc(child)
                break
        if caconc is not None:
            child = get_child_Mstring(caconc, 'phi')
            if child is not None:
                caconc.B = float(
                    child.value
                )  # B = phi by definition -- see neuroml 1.8.1 defn
            else:
                ## B has to be set for caconc based on thickness of Ca shell and compartment l and dia,
                ## OR based on the Mstring phi under CaConc path.
                ## I am using a translation from Neuron for mitral cell, hence this method.
                ## In Genesis, gmax / (surfacearea*thick) is set as value of B!
                caconc.B = 1 / (2*FARADAY) / \
                    (math.pi*compartment.diameter*compartment.length * caconc.thick)
            for child in compartment.children:
                neutralwrap = _moose.Neutral(child)
                if neutralwrap.className == 'HHChannel':
                    channel = _moose.HHChannel(child)
                    ## If child Mstring 'ion' is present and is Ca, connect channel current to caconc
                    for childid in channel.children:
                        # in async13, gates which have not been created still 'exist'
                        # i.e. show up as a child, but cannot be wrapped.
                        try:
                            child = _moose.element(childid)
                            if child.className == 'Mstring':
                                child = _moose.Mstring(child)
                                if child.name == 'ion':
                                    if child.value in ['Ca', 'ca']:
                                        _moose.connect(channel, 'IkOut',
                                                       caconc, 'current')
                                        #print 'Connected IkOut of',channel.path,'to current of',caconc.path
                                ## temperature is used only by Nernst part here...
                                if child.name == 'nernst_str':
                                    nernst = _moose.Nernst(channel.path +
                                                           '/nernst')
                                    nernst_params = string.split(
                                        child.value, ',')
                                    nernst.Cout = float(nernst_params[0])
                                    nernst.valence = float(nernst_params[1])
                                    nernst.Temperature = temperature
                                    _moose.connect(nernst, 'Eout', channel,
                                                   'setEk')
                                    _moose.connect(caconc, 'concOut', nernst,
                                                   'ci')
                                    #print 'Connected Nernst',nernst.path
                        except TypeError:
                            pass

                if neutralwrap.className == 'HHChannel2D':
                    channel = _moose.HHChannel2D(child)
                    ## If child Mstring 'ionDependency' is present, connect caconc Ca conc to channel
                    for childid in channel.children:
                        # in async13, gates which have not been created still 'exist'
                        # i.e. show up as a child, but cannot be wrapped.
                        try:
                            child = _moose.element(childid)
                            if child.className == 'Mstring' and child.name == 'ionDependency':
                                child = _moose.Mstring(child)
                                if child.value in ['Ca', 'ca']:
                                    _moose.connect(caconc, 'concOut', channel,
                                                   'concen')
                                    #print 'Connected concOut of',caconc.path,'to concen of',channel.path
                        except TypeError:
                            pass