def _extract_connection_property_sets(cls, dynamics_properties, namespace): """ Identifies properties in the provided DynmaicsProperties that can be treated as a property of the connection (i.e. are not referenced anywhere except within the OnEvent blocks event port). """ component_class = dynamics_properties.component_class varying_params = set( component_class.parameter(p.name) for p in dynamics_properties.properties if p.value.nineml_type != 'SingleValue') # Get list of ports refereneced (either directly or indirectly) by # time derivatives and on-conditions not_permitted = set(p.name for p in component_class.required_for( chain(component_class.all_time_derivatives(), component_class.all_on_conditions())).parameters) # If varying params intersects parameters that are referenced in time # derivatives they can not be redefined as connection parameters if varying_params & not_permitted: raise Pype9UnflattenableSynapseException() conn_params = defaultdict(set) for on_event in component_class.all_on_events(): on_event_params = set(component_class.required_for( on_event.state_assignments).parameters) conn_params[on_event.src_port_name] |= (varying_params & on_event_params) return [ ConnectionPropertySet( append_namespace(prt, namespace), [Property(append_namespace(p.name, namespace), dynamics_properties.property(p.name).quantity) for p in params]) for prt, params in conn_params.iteritems() if params]
def _extract_connection_property_sets(cls, dynamics_properties, namespace): """ Identifies properties in the provided DynmaicsProperties that can be treated as a property of the connection (i.e. are not referenced anywhere except within the OnEvent blocks event port). """ component_class = dynamics_properties.component_class varying_params = set( component_class.parameter(p.name).id for p in dynamics_properties.properties if p.value.nineml_type != 'SingleValue') # Get list of ports refereneced (either directly or indirectly) by # time derivatives and on-conditions not_permitted = set(p.id for p in component_class.required_for( chain(component_class.all_time_derivatives(), component_class.all_on_conditions())).parameters) # If varying params intersects parameters that are referenced in time # derivatives they can not be redefined as connection parameters if varying_params & not_permitted: raise Pype9UnflattenableSynapseException() conn_params = defaultdict(dict) for on_event in component_class.all_on_events(): for param in component_class.required_for( on_event.state_assignments).parameters: if param.id in varying_params: conn_params[on_event.src_port_name][param.id] = param return [ ConnectionPropertySet( append_namespace(prt, namespace), [Property(append_namespace(p.name, namespace), dynamics_properties.property(p.name).quantity) for p in params.values()]) for prt, params in conn_params.items()]
def test_multi_dynamics_accessors(self): for class_name, mutli_class_name, non_ns_property in ( (('Dynamics', 'MultiDynamics', 'component_class'), ('DynamicsProperties', 'MultiDynamicsProperties', 'component'))): cls = all_types[class_name] for elem in list(instances_of_all_types[mutli_class_name].values()): if elem.key == 'multiDynPropB_dynamics': regimes = list(elem.regimes) regimes[0].on_conditions regimes[1].on_conditions flat_elem = elem.flatten(elem.name) for child_type in cls.nineml_children: accessor_name = child_type._child_accessor_name() if accessor_name.endswith('_port'): continue # Already covered in previous test all_sc_nums = [] all_sc_names = [] all_sc_members = [] for sub_comp in elem.sub_components: comp = getattr(sub_comp, non_ns_property) c_num = self._num_members(comp, accessor_name) c_names = self._member_names(comp, accessor_name) c_members = self._members(comp, accessor_name) sc_num = self._num_members(sub_comp, accessor_name) sc_names = self._member_names(sub_comp, accessor_name) sc_members = self._members(sub_comp, accessor_name) sc_acc_members = self._accessor_members( sub_comp, accessor_name, sc_names) self.assertEqual(sc_num, c_num) self.assertEqual(sc_names, [append_namespace(n, sub_comp.name) for n in c_names]) self.assertEqual(c_members, [sc._object for sc in sc_members]) self.assertEqual(sc_members, sc_acc_members) all_sc_nums.append(sc_num) all_sc_names.extend(sc_names) all_sc_members.extend(sc_members) num = self._num_members(elem, accessor_name) names = self._member_names(elem, accessor_name) members = self._members(elem, accessor_name) # Basic consistency checks self.assertEqual(num, len(names)) self.assertEqual(num, len(members)) self.assertEqual( members, self._accessor_members(elem, accessor_name, names)) # Check with flatttened version flat_num = self._num_members(flat_elem, accessor_name) flat_names = self._member_names(flat_elem, accessor_name) flat_members = self._members(flat_elem, accessor_name) self.assertEqual( flat_members, self._accessor_members(flat_elem, accessor_name, names)) self.assertEqual(num, flat_num) self.assertEqual(names, flat_names) self.assertEqual( members, flat_members, "Members don't match flat members:\n{}".format( '\n\n'.join( m.find_mismatch(f) for m, f in zip( members, flat_members)))) if class_name == 'Dynamics' and accessor_name in ( 'alias', 'constant', 'state_variable', 'regime'): if accessor_name == 'regime': # All combination of sub-regimes self.assertEqual(num, product(all_sc_nums)) else: # Additional members representing local port # connections and reduce ports are appended to list # of certain members when flattening. self.assertGreaterEqual(num, sum(all_sc_nums)) else: self.assertEqual(num, sum(all_sc_nums)) self.assertEqual(names, sorted(all_sc_names)) self.assertEqual( members, sorted(all_sc_members, key=lambda e: e.key))
def _flatten_synapse(cls, projection_model): """ Flattens the reponse and plasticity dynamics into a single synapse element (will be 9MLv2 format) and updates the port connections to match the changed object. """ role2name = {'response': 'psr', 'plasticity': 'pls'} syn_comps = { role2name['response']: projection_model.response, role2name['plasticity']: projection_model.plasticity} # Get all projection port connections that don't project to/from # the "pre" population and convert them into local MultiDynamics # port connections of the synapse syn_internal_conns = ( pc.__class__( sender_name=role2name[pc.sender_role], receiver_name=role2name[pc.receiver_role], send_port=pc.send_port_name, receive_port=pc.receive_port_name) for pc in projection_model.port_connections if (pc.sender_role in ('plasticity', 'response') and pc.receiver_role in ('plasticity', 'response'))) receive_conns = [pc for pc in projection_model.port_connections if (pc.sender_role in ('pre', 'post') and pc.receiver_role in ('plasticity', 'response'))] send_conns = [pc for pc in projection_model.port_connections if (pc.sender_role in ('plasticity', 'response') and pc.receiver_role in ('pre', 'post'))] syn_exps = chain( (BasePortExposure.from_port(pc.send_port, role2name[pc.sender_role]) for pc in send_conns), (BasePortExposure.from_port(pc.receive_port, role2name[pc.receiver_role]) for pc in receive_conns)) synapse = MultiDynamicsProperties( name=(projection_model.name + '_syn'), sub_components=syn_comps, port_connections=syn_internal_conns, port_exposures=syn_exps) port_connections = list(chain( (pc.__class__(sender_role=pc.sender_role, receiver_role='synapse', send_port=pc.send_port_name, receive_port=append_namespace( pc.receive_port_name, role2name[pc.receiver_role])) for pc in receive_conns), (pc.__class__(sender_role='synapse', receiver_role=pc.receiver_role, send_port=append_namespace( pc.send_port_name, role2name[pc.sender_role]), receive_port=pc.receive_port_name) for pc in send_conns), (pc for pc in projection_model.port_connections if (pc.sender_role in ('pre', 'post') and pc.receiver_role in ('pre', 'post'))))) # A bit of a hack in order to bind the port_connections dummy_container = namedtuple('DummyContainer', 'pre post synapse')( projection_model.pre, projection_model.post, synapse) for port_connection in port_connections: port_connection.bind(dummy_container, to_roles=True) return synapse, port_connections
def test_multi_dynamics_accessors(self): for class_name, mutli_class_name, non_ns_property in ( (('Dynamics', 'MultiDynamics', 'component_class'), ('DynamicsProperties', 'MultiDynamicsProperties', 'component'))): cls = all_types[class_name] for elem in list( instances_of_all_types[mutli_class_name].values()): if elem.key == 'multiDynPropB_dynamics': regimes = list(elem.regimes) regimes[0].on_conditions regimes[1].on_conditions flat_elem = elem.flatten(elem.name) for child_type in cls.nineml_children: accessor_name = child_type._child_accessor_name() if accessor_name.endswith('_port'): continue # Already covered in previous test all_sc_nums = [] all_sc_names = [] all_sc_members = [] for sub_comp in elem.sub_components: comp = getattr(sub_comp, non_ns_property) c_num = self._num_members(comp, accessor_name) c_names = self._member_names(comp, accessor_name) c_members = self._members(comp, accessor_name) sc_num = self._num_members(sub_comp, accessor_name) sc_names = self._member_names(sub_comp, accessor_name) sc_members = self._members(sub_comp, accessor_name) sc_acc_members = self._accessor_members( sub_comp, accessor_name, sc_names) self.assertEqual(sc_num, c_num) self.assertEqual(sc_names, [ append_namespace(n, sub_comp.name) for n in c_names ]) self.assertEqual(c_members, [sc._object for sc in sc_members]) self.assertEqual(sc_members, sc_acc_members) all_sc_nums.append(sc_num) all_sc_names.extend(sc_names) all_sc_members.extend(sc_members) num = self._num_members(elem, accessor_name) names = self._member_names(elem, accessor_name) members = self._members(elem, accessor_name) # Basic consistency checks self.assertEqual(num, len(names)) self.assertEqual(num, len(members)) self.assertEqual( members, self._accessor_members(elem, accessor_name, names)) # Check with flatttened version flat_num = self._num_members(flat_elem, accessor_name) flat_names = self._member_names(flat_elem, accessor_name) flat_members = self._members(flat_elem, accessor_name) self.assertEqual( flat_members, self._accessor_members(flat_elem, accessor_name, names)) self.assertEqual(num, flat_num) self.assertEqual(names, flat_names) self.assertEqual( members, flat_members, "Members don't match flat members:\n{}".format( '\n\n'.join( m.find_mismatch(f) for m, f in zip(members, flat_members)))) if class_name == 'Dynamics' and accessor_name in ( 'alias', 'constant', 'state_variable', 'regime'): if accessor_name == 'regime': # All combination of sub-regimes self.assertEqual(num, product(all_sc_nums)) else: # Additional members representing local port # connections and reduce ports are appended to list # of certain members when flattening. self.assertGreaterEqual(num, sum(all_sc_nums)) else: self.assertEqual(num, sum(all_sc_nums)) self.assertEqual(names, sorted(all_sc_names)) self.assertEqual( members, sorted(all_sc_members, key=lambda e: e.key))
def _flatten_synapse(cls, projection_model): """ Flattens the reponse and plasticity dynamics into a single synapse element (will be 9MLv2 format) and updates the port connections to match the changed object. """ role2name = {'response': 'psr', 'plasticity': 'pls'} syn_comps = { role2name['response']: projection_model.response, role2name['plasticity']: projection_model.plasticity} # Get all projection port connections that don't project to/from # the "pre" population and convert them into local MultiDynamics # port connections of the synapse syn_internal_conns = ( pc.__class__( sender_name=role2name[pc.sender_role], receiver_name=role2name[pc.receiver_role], send_port_name=pc.send_port_name, receive_port_name=pc.receive_port_name) for pc in projection_model.port_connections if (pc.sender_role in ('plasticity', 'response') and pc.receiver_role in ('plasticity', 'response'))) receive_conns = [pc for pc in projection_model.port_connections if (pc.sender_role in ('pre', 'post') and pc.receiver_role in ('plasticity', 'response'))] send_conns = [pc for pc in projection_model.port_connections if (pc.sender_role in ('plasticity', 'response') and pc.receiver_role in ('pre', 'post'))] syn_exps = chain( (BasePortExposure.from_port(pc.send_port, role2name[pc.sender_role]) for pc in send_conns), (BasePortExposure.from_port(pc.receive_port, role2name[pc.receiver_role]) for pc in receive_conns)) synapse = MultiDynamicsProperties( name=(projection_model.name + '_syn'), sub_components=syn_comps, port_connections=syn_internal_conns, port_exposures=syn_exps) port_connections = list(chain( (pc.__class__(sender_role=pc.sender_role, receiver_role='synapse', send_port_name=pc.send_port_name, receive_port_name=append_namespace( pc.receive_port_name, role2name[pc.receiver_role])) for pc in receive_conns), (pc.__class__(sender_role='synapse', receiver_role=pc.receiver_role, send_port_name=append_namespace( pc.send_port_name, role2name[pc.sender_role]), receive_port_name=pc.receive_port_name) for pc in send_conns), (pc for pc in projection_model.port_connections if (pc.sender_role in ('pre', 'post') and pc.receiver_role in ('pre', 'post'))))) # A bit of a hack in order to bind the port_connections dummy_container = namedtuple('DummyContainer', 'pre post synapse')( projection_model.pre, projection_model.post, synapse) for port_connection in port_connections: port_connection.bind(dummy_container, to_roles=True) return synapse, port_connections