Changeset 976

Show
Ignore:
Timestamp:
06/06/11 09:02:18 (12 months ago)
Author:
mhull
Message:

Chnages to nineml code, since 'bindings' have been renamed "alias'

Location:
trunk/src
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/nest/nineml.py

    r975 r976  
    7777        reduced_component = models.reduce_to_single_component( nineml_model, 
    7878                                                               componentname=name ) 
     79        reduced_component.backsub_aliases() 
     80        reduced_component.backsub_equations() 
    7981 
    8082        reduced_component.short_description = "Auto-generated 9ML neuron model for PyNN.nest" 
  • trunk/src/nineml/cells.py

    r972 r976  
    204204 
    205205class _build_nineml_celltype(type): 
    206     """ 
    207     Metaclass for building NineMLCellType subclasses 
    208     """ 
    209     def __new__(cls, name, bases, dct): 
    210         # join the neuron and synapse components into a single component 
    211         combined_model = dct["neuron_model"] 
    212         for label in dct["synapse_models"].keys(): 
    213             port_map = dct["port_map"][label] 
    214             port_map = _add_prefix(dct["synapse_models"][label], label, port_map) 
    215             dct["weight_variables"][label] = label + "_" + dct["weight_variables"][label] 
    216             combined_model = join(combined_model, 
    217                                   dct["synapse_models"][label], 
    218                                   port_map, 
    219                                   name=name) 
    220         dct["combined_model"] = combined_model 
    221         # set class attributes required for a PyNN cell type class 
    222         dct["default_parameters"] = dict((name, 1.0) 
    223                                       for name in combined_model.parameters) 
    224         dct["default_initial_values"] = dict((name, 0.0) 
    225                                           for name in combined_model.state_variables) 
    226         dct["synapse_types"] = sorted(dct["synapse_models"]) # using alphabetical order may make things easier code generators 
    227         dct["injectable"] = True # need to determine this. How?? 
    228         dct["recordable"] = [port.name for port in combined_model.analog_ports] + ['spikes', 'regime'] 
    229         dct["standard_receptor_type"] = (dct["synapse_types"] == ('excitatory', 'inhibitory')) 
    230         dct["conductance_based"] = True # how to determine this?? 
    231         dct["model_name"] = name 
    232         logger.debug("Creating class '%s' with bases %s and dictionary %s" % (name, bases, dct)) 
    233         # generate and compile code, then load the mechanism into the simulator 
    234         dct["builder"](combined_model, dct["weight_variables"]) # weight variables should really be stored within combined_model 
    235         return type.__new__(cls, name, bases, dct) 
    236      
    237      
    238  
    239 def join(c1, c2, port_map=[], name=None): 
    240     """Create a NineML component by joining the two given components.""" 
    241     logger.debug("Joining components %s and %s with port map %s" % (c1, c2, port_map)) 
    242     logger.debug("New component will have name '%s'" % name) 
    243     # combine bindings from c1 and c2 
    244     bindings = {} 
    245     for b in chain(c1.bindings, c2.bindings): 
    246         bindings[b.name] = b 
    247     # combine ports (some will later be removed) 
    248     all_ports = c1.ports_map.copy() 
    249     all_ports.update(c2.ports_map) 
    250     # event ports do not be passed to the constructor, as they are attached to transitions 
    251     for port_name, port in all_ports.items(): 
    252         if isinstance(port, nineml.EventPort): 
    253             all_ports.pop(port_name) 
    254     # connect ports. 
    255     # currently, when ports are connected they disappear. It might be better to 
    256     # explicitly keep the ports in the new component but mark them as connected 
    257     for name1, name2 in port_map: 
    258         assert name1 in c1.ports_map, "%s is not in %s" % (name1, c1.ports_map.keys()) 
    259         assert name2 in c2.ports_map, "%s is not in %s" % (name2, c2.ports_map.keys()) 
    260  
    261         port1 = c1.ports_map[name1] 
    262         port2 = c2.ports_map[name2] 
    263         assert port1.mode != port2.mode 
    264         if port1.mode == 'send': 
    265             send_port = port1 
    266             recv_port = port2 
    267             send_port_name = name1 
    268             recv_port_name = name2 
    269         else: 
    270             send_port = port2 
    271             recv_port = port1 
    272             send_port_name = name2 
    273             recv_port_name = name1 
    274         # when connecting ports in which the send port has an expression, need 
    275         # to create a binding for this expression in the new component 
    276         if send_port.expr: 
    277             func_args = c1.non_parameter_symbols.union(c2.non_parameter_symbols).intersection(send_port.expr.names) 
    278             lhs = "%s(%s)" % (send_port_name, ",".join(func_args)) 
    279             send_binding = nineml.Binding(lhs, send_port.expr.rhs) 
    280             bindings[send_binding.name] = send_binding 
    281             for eq in chain(c1.equations, c2.equations): 
    282                 if send_port_name in eq.names: 
    283                     eq.rhs = eq.rhs_name_transform({send_port_name: lhs})             
    284             if recv_port.mode == 'reduce': 
    285                 # need to retain reduce ports as they can be connected to in a future join 
    286                 if recv_port_name in bindings: 
    287                     # this reduce port has already been connected to, so combine using its reduce_op 
    288                     reduce_binding = bindings[recv_port_name] 
    289                     func_args = func_args.union(reduce_binding.args) 
    290                     lhs = "%s(%s)" % (recv_port_name, ",".join(func_args)) 
    291                     rhs = recv_port.reduce_op.join([reduce_binding.rhs, send_binding.lhs]) 
    292                 else: 
    293                     # this is the first time this reduce port has been connected to 
    294                     lhs = "%s(%s)" % (recv_port_name, ",".join(func_args)) 
    295                     rhs = send_binding.lhs 
    296                 bindings[recv_port_name] = nineml.Binding(lhs, rhs) 
    297                 recv_port.connected = True 
    298             else: 
    299                 all_ports.pop(name1) 
    300         else: 
    301             if recv_port.mode == 'reduce': 
    302                 raise NotImplementedError 
    303             else: 
    304                 all_ports.pop(name1) 
    305  
    306         if name1 != name2: 
    307             #c2.substitute(name2, name1) # need to implement this. Currently this all only works if name1 == name2 
    308                                          # probably needs to happen sooner in the function 
    309             all_ports.pop(name2) 
    310  
    311     # where parameters have become bindings due to connecting ports, replace 
    312     # bare names with function calls in the equations 
    313     for bname, binding in bindings.items(): 
    314         for eq in chain(c1.equations, c2.equations): 
    315             if bname in eq.names: 
    316                 print "#### replacing %s by %s" % (bname, binding.lhs) 
    317                 pattern = re.compile(r'%s(\([\w\, ]*\))?' % bname) 
    318                 m = pattern.search(eq.rhs) 
    319                 if m: 
    320                     eq.rhs = pattern.sub(binding.lhs, eq.rhs) 
    321                 else: 
    322                     eq.rhs = eq.rhs_name_transform({bname: binding.lhs}) 
    323  
    324     # create new regimes from all possible combinations of the regimes from the 
    325     # two components 
    326     regime_map = {} 
    327     for r1 in c1.regimes: 
    328         regime_map[r1.name] = {} 
    329         for r2 in c2.regimes: 
    330             if r1.name == r2.name: 
    331                 new_name = r1.name 
    332             else: 
    333                 new_name = "%s_AND_%s" % (r1.name, r2.name) 
    334             kwargs = {'name': new_name} 
    335             new_regime = nineml.Regime(*r1.nodes.union(r2.nodes), **kwargs) 
    336             regime_map[r1.name][r2.name] = new_regime 
    337     # create transitions between all the new regimes 
    338     transitions = [] 
    339     for r1 in c1.regimes: 
    340         for r2 in c2.regimes: 
    341             for t in r1.transitions: 
    342                 new_transition = nineml.Transition(*t.nodes, 
    343                                                    from_=regime_map[r1.name][r2.name], 
    344                                                    to=regime_map[t.to.name][r2.name], 
    345                                                    condition=t.condition) 
    346                 transitions.append(new_transition) 
    347             for t in r2.transitions: 
    348                 new_transition = nineml.Transition(*t.nodes, 
    349                                                    from_=regime_map[r1.name][r2.name], 
    350                                                    to=regime_map[r1.name][t.to.name], 
    351                                                    condition=t.condition) 
    352                 transitions.append(new_transition) 
    353  
    354     regimes = [] 
    355     for d in regime_map.values(): 
    356         regimes.extend(d.values()) 
    357     name = name or "%s__%s" % (c1.name, c2.name) 
    358     return nineml.Component(name, 
    359                             regimes=regimes, 
    360                             transitions=transitions, 
    361                             ports=all_ports.values(), 
    362                             bindings=bindings.values()) 
    363  
     206    pass 
     207 
     208#class _build_nineml_celltype(type): 
     209#    """ 
     210#    Metaclass for building NineMLCellType subclasses 
     211#    """ 
     212#    def __new__(cls, name, bases, dct): 
     213#        assert False 
     214# 
     215#        # join the neuron and synapse components into a single component 
     216#        combined_model = dct["neuron_model"] 
     217#        for label in dct["synapse_models"].keys(): 
     218#            port_map = dct["port_map"][label] 
     219#            port_map = _add_prefix(dct["synapse_models"][label], label, port_map) 
     220#            dct["weight_variables"][label] = label + "_" + dct["weight_variables"][label] 
     221#            combined_model = join(combined_model, 
     222#                                  dct["synapse_models"][label], 
     223#                                  port_map, 
     224#                                  name=name) 
     225#        dct["combined_model"] = combined_model 
     226#        # set class attributes required for a PyNN cell type class 
     227#        dct["default_parameters"] = dict((name, 1.0) 
     228#                                      for name in combined_model.parameters) 
     229#        dct["default_initial_values"] = dict((name, 0.0) 
     230#                                          for name in combined_model.state_variables) 
     231#        dct["synapse_types"] = sorted(dct["synapse_models"]) # using alphabetical order may make things easier code generators 
     232#        dct["injectable"] = True # need to determine this. How?? 
     233#        dct["recordable"] = [port.name for port in combined_model.analog_ports] + ['spikes', 'regime'] 
     234#        dct["standard_receptor_type"] = (dct["synapse_types"] == ('excitatory', 'inhibitory')) 
     235#        dct["conductance_based"] = True # how to determine this?? 
     236#        dct["model_name"] = name 
     237#        logger.debug("Creating class '%s' with bases %s and dictionary %s" % (name, bases, dct)) 
     238#        # generate and compile code, then load the mechanism into the simulator 
     239#        dct["builder"](combined_model, dct["weight_variables"]) # weight variables should really be stored within combined_model 
     240#        return type.__new__(cls, name, bases, dct) 
     241#     
     242#     
     243# 
     244#def join(c1, c2, port_map=[], name=None): 
     245#    """Create a NineML component by joining the two given components.""" 
     246#    logger.debug("Joining components %s and %s with port map %s" % (c1, c2, port_map)) 
     247#    logger.debug("New component will have name '%s'" % name) 
     248#    # combine bindings from c1 and c2 
     249#    bindings = {} 
     250#    for b in chain(c1.bindings, c2.bindings): 
     251#        bindings[b.name] = b 
     252#    # combine ports (some will later be removed) 
     253#    all_ports = c1.ports_map.copy() 
     254#    all_ports.update(c2.ports_map) 
     255#    # event ports do not be passed to the constructor, as they are attached to transitions 
     256#    for port_name, port in all_ports.items(): 
     257#        if isinstance(port, nineml.EventPort): 
     258#            all_ports.pop(port_name) 
     259#    # connect ports. 
     260#    # currently, when ports are connected they disappear. It might be better to 
     261#    # explicitly keep the ports in the new component but mark them as connected 
     262#    for name1, name2 in port_map: 
     263#        assert name1 in c1.ports_map, "%s is not in %s" % (name1, c1.ports_map.keys()) 
     264#        assert name2 in c2.ports_map, "%s is not in %s" % (name2, c2.ports_map.keys()) 
     265# 
     266#        port1 = c1.ports_map[name1] 
     267#        port2 = c2.ports_map[name2] 
     268#        assert port1.mode != port2.mode 
     269#        if port1.mode == 'send': 
     270#            send_port = port1 
     271#            recv_port = port2 
     272#            send_port_name = name1 
     273#            recv_port_name = name2 
     274#        else: 
     275#            send_port = port2 
     276#            recv_port = port1 
     277#            send_port_name = name2 
     278#            recv_port_name = name1 
     279#        # when connecting ports in which the send port has an expression, need 
     280#        # to create a binding for this expression in the new component 
     281#        if send_port.expr: 
     282#            func_args = c1.non_parameter_symbols.union(c2.non_parameter_symbols).intersection(send_port.expr.names) 
     283#            lhs = "%s(%s)" % (send_port_name, ",".join(func_args)) 
     284#            send_binding = nineml.Binding(lhs, send_port.expr.rhs) 
     285#            bindings[send_binding.name] = send_binding 
     286#            for eq in chain(c1.equations, c2.equations): 
     287#                if send_port_name in eq.names: 
     288#                    eq.rhs = eq.rhs_name_transform({send_port_name: lhs})             
     289#            if recv_port.mode == 'reduce': 
     290#                # need to retain reduce ports as they can be connected to in a future join 
     291#                if recv_port_name in bindings: 
     292#                    # this reduce port has already been connected to, so combine using its reduce_op 
     293#                    reduce_binding = bindings[recv_port_name] 
     294#                    func_args = func_args.union(reduce_binding.args) 
     295#                    lhs = "%s(%s)" % (recv_port_name, ",".join(func_args)) 
     296#                    rhs = recv_port.reduce_op.join([reduce_binding.rhs, send_binding.lhs]) 
     297#                else: 
     298#                    # this is the first time this reduce port has been connected to 
     299#                    lhs = "%s(%s)" % (recv_port_name, ",".join(func_args)) 
     300#                    rhs = send_binding.lhs 
     301#                bindings[recv_port_name] = nineml.Binding(lhs, rhs) 
     302#                recv_port.connected = True 
     303#            else: 
     304#                all_ports.pop(name1) 
     305#        else: 
     306#            if recv_port.mode == 'reduce': 
     307#                raise NotImplementedError 
     308#            else: 
     309#                all_ports.pop(name1) 
     310# 
     311#        if name1 != name2: 
     312#            #c2.substitute(name2, name1) # need to implement this. Currently this all only works if name1 == name2 
     313#                                         # probably needs to happen sooner in the function 
     314#            all_ports.pop(name2) 
     315# 
     316#    # where parameters have become bindings due to connecting ports, replace 
     317#    # bare names with function calls in the equations 
     318#    for bname, binding in bindings.items(): 
     319#        for eq in chain(c1.equations, c2.equations): 
     320#            if bname in eq.names: 
     321#                print "#### replacing %s by %s" % (bname, binding.lhs) 
     322#                pattern = re.compile(r'%s(\([\w\, ]*\))?' % bname) 
     323#                m = pattern.search(eq.rhs) 
     324#                if m: 
     325#                    eq.rhs = pattern.sub(binding.lhs, eq.rhs) 
     326#                else: 
     327#                    eq.rhs = eq.rhs_name_transform({bname: binding.lhs}) 
     328# 
     329#    # create new regimes from all possible combinations of the regimes from the 
     330#    # two components 
     331#    regime_map = {} 
     332#    for r1 in c1.regimes: 
     333#        regime_map[r1.name] = {} 
     334#        for r2 in c2.regimes: 
     335#            if r1.name == r2.name: 
     336#                new_name = r1.name 
     337#            else: 
     338#                new_name = "%s_AND_%s" % (r1.name, r2.name) 
     339#            kwargs = {'name': new_name} 
     340#            new_regime = nineml.Regime(*r1.nodes.union(r2.nodes), **kwargs) 
     341#            regime_map[r1.name][r2.name] = new_regime 
     342#    # create transitions between all the new regimes 
     343#    transitions = [] 
     344#    for r1 in c1.regimes: 
     345#        for r2 in c2.regimes: 
     346#            for t in r1.transitions: 
     347#                new_transition = nineml.Transition(*t.nodes, 
     348#                                                   from_=regime_map[r1.name][r2.name], 
     349#                                                   to=regime_map[t.to.name][r2.name], 
     350#                                                   condition=t.condition) 
     351#                transitions.append(new_transition) 
     352#            for t in r2.transitions: 
     353#                new_transition = nineml.Transition(*t.nodes, 
     354#                                                   from_=regime_map[r1.name][r2.name], 
     355#                                                   to=regime_map[r1.name][t.to.name], 
     356#                                                   condition=t.condition) 
     357#                transitions.append(new_transition) 
     358# 
     359#    regimes = [] 
     360#    for d in regime_map.values(): 
     361#        regimes.extend(d.values()) 
     362#    name = name or "%s__%s" % (c1.name, c2.name) 
     363#    return nineml.Component(name, 
     364#                            regimes=regimes, 
     365#                            transitions=transitions, 
     366#                            ports=all_ports.values(), 
     367#                            bindings=bindings.values()) 
     368# 
    364369 
    365370 
     
    382387        reduction_process = models.ModelToSingleComponentReducer(nineml_model, componentname=name) 
    383388        reduced_component = reduction_process.reducedcomponent 
     389 
     390 
     391 
     392        # Make the substitutions: 
     393        reduced_component.backsub_aliases() 
     394        reduced_component.backsub_equations() 
     395        #reduced_component.backsub_ports() 
    384396         
    385397        # New: 
     
    395407         
    396408        # Recording from bindings: 
    397         dct["recordable"] = [port.name for port in reduced_component.analog_ports] + ['spikes', 'regime'] + [binding.name for binding in reduced_component.bindings] 
     409        dct["recordable"] = [port.name for port in reduced_component.analog_ports] + ['spikes', 'regime'] + [alias.name for alias in reduced_component.aliases] 
    398410         
    399411        dct["weight_variables"] = dict([ (syn.namespace,syn.namespace+'_'+syn.weight_connector )