def test_connection_holder_matrix_multiple_items(): data_items = ["source", "target", "delay", "weight"] connection_holder = ConnectionHolder(data_items_to_return=data_items, as_list=False, n_pre_atoms=2, n_post_atoms=2) connections = numpy.array([(0, 0, 1, 10), (0, 0, 2, 20), (0, 1, 3, 30)], AbstractSynapseDynamics.NUMPY_CONNECTORS_DTYPE) connection_holder.add_connections(connections)
def _get_synaptic_data(self, as_list, data_to_get, fixed_values=None, notify=None): """ :param bool as_list: :param list(int) data_to_get: :param list(tuple(str,int)) fixed_values: :param callable(ConnectionHolder,None) notify: :rtype: ConnectionHolder """ # pylint: disable=too-many-arguments post_vertex = self.__projection_edge.post_vertex pre_vertex = self.__projection_edge.pre_vertex # If in virtual board mode, the connection data should be set if self.__virtual_connection_list is not None: connection_holder = ConnectionHolder( data_to_get, as_list, pre_vertex.n_atoms, post_vertex.n_atoms, self.__virtual_connection_list, fixed_values=fixed_values, notify=notify) connection_holder.finish() return connection_holder # if not virtual board, make connection holder to be filled in at # possible later date connection_holder = ConnectionHolder(data_to_get, as_list, pre_vertex.n_atoms, post_vertex.n_atoms, fixed_values=fixed_values, notify=notify) # If we haven't run, add the holder to get connections, and return it # and set up a callback for after run to fill in this connection holder if not get_simulator().has_ran: self.__synapse_information.add_pre_run_connection_holder( connection_holder) return connection_holder # Otherwise, get the connections now, as we have ran and therefore can # get them connections = post_vertex.get_connections_from_machine( get_simulator().transceiver, get_simulator().placements, self.__projection_edge, self.__synapse_information) if connections is not None: connection_holder.add_connections(connections) connection_holder.finish() return connection_holder
def _generate_holder_for_edge(edge, data_holders): # build connection holders connection_holder = ConnectionHolder( None, True, edge.pre_vertex.n_atoms, edge.post_vertex.n_atoms) for synapse_information in edge.synapse_information: edge.post_vertex.add_pre_run_connection_holder( connection_holder, edge, synapse_information) # store for the report generations data_holders[edge, synapse_information] = connection_holder
def _get_synaptic_data( self, as_list, data_to_get, fixed_values=None, notify=None, handle_time_out_configuration=True): # pylint: disable=too-many-arguments post_vertex = self._projection_edge.post_vertex pre_vertex = self._projection_edge.pre_vertex # If in virtual board mode, the connection data should be set if self._virtual_connection_list is not None: post_vertex = self._projection_edge.post_vertex pre_vertex = self._projection_edge.pre_vertex connection_holder = ConnectionHolder( data_to_get, as_list, pre_vertex.n_atoms, post_vertex.n_atoms, self._virtual_connection_list, fixed_values=fixed_values, notify=notify) connection_holder.finish() return connection_holder # if not virtual board, make connection holder to be filled in at # possible later date connection_holder = ConnectionHolder( data_to_get, as_list, pre_vertex.n_atoms, post_vertex.n_atoms, fixed_values=fixed_values, notify=notify) # If we haven't run, add the holder to get connections, and return it # and set up a callback for after run to fill in this connection holder if not self._spinnaker_control.has_ran: post_vertex.add_pre_run_connection_holder( connection_holder, self._projection_edge, self._synapse_information) return connection_holder # Otherwise, get the connections now, as we have ran and therefore can # get them self.__get_projection_data( data_to_get, pre_vertex, post_vertex, connection_holder, handle_time_out_configuration) return connection_holder
def _get_synaptic_data(self, as_list, data_to_get, fixed_values=None, notify=None, handle_time_out_configuration=True): # pylint: disable=too-many-arguments post_vertex = self.__projection_edge.post_vertex pre_vertex = self.__projection_edge.pre_vertex # If in virtual board mode, the connection data should be set if self.__virtual_connection_list is not None: post_vertex = self.__projection_edge.post_vertex pre_vertex = self.__projection_edge.pre_vertex connection_holder = ConnectionHolder( data_to_get, as_list, pre_vertex.n_atoms, post_vertex.n_atoms, self.__virtual_connection_list, fixed_values=fixed_values, notify=notify) connection_holder.finish() return connection_holder # if not virtual board, make connection holder to be filled in at # possible later date connection_holder = ConnectionHolder(data_to_get, as_list, pre_vertex.n_atoms, post_vertex.n_atoms, fixed_values=fixed_values, notify=notify) # If we haven't run, add the holder to get connections, and return it # and set up a callback for after run to fill in this connection holder if not self.__spinnaker_control.has_ran: post_vertex.add_pre_run_connection_holder( connection_holder, self.__projection_edge, self.__synapse_information) return connection_holder # Otherwise, get the connections now, as we have ran and therefore can # get them self.__get_projection_data(data_to_get, pre_vertex, post_vertex, connection_holder, handle_time_out_configuration) return connection_holder
def __init__(self, spinnaker_control, connector, synapse_dynamics_stdp, target, pre_synaptic_population, post_synaptic_population, rng, machine_time_step, user_max_delay, label, time_scale_factor): # pylint: disable=too-many-arguments, too-many-locals self._spinnaker_control = spinnaker_control self._projection_edge = None self._host_based_synapse_list = None self._has_retrieved_synaptic_list_from_machine = False self._requires_mapping = True self._label = None if not isinstance(post_synaptic_population._get_vertex, AbstractAcceptsIncomingSynapses): raise ConfigurationException( "postsynaptic population is not designed to receive" " synaptic projections") # sort out synapse type synapse_type = post_synaptic_population._get_vertex\ .get_synapse_id_by_target(target) if synapse_type is None: raise ConfigurationException( "Synapse target {} not found in {}".format( target, post_synaptic_population.label)) # set the plasticity dynamics for the post pop (allows plastic stuff # when needed) post_synaptic_population._get_vertex.set_synapse_dynamics( synapse_dynamics_stdp) # Set and store information for future processing self._synapse_information = SynapseInformation(connector, synapse_dynamics_stdp, synapse_type) connector.set_projection_information(pre_synaptic_population, post_synaptic_population, rng, machine_time_step) # handle max delay max_delay = synapse_dynamics_stdp.get_delay_maximum(connector) if max_delay is None: max_delay = user_max_delay # check if all delays requested can fit into the natively supported # delays in the models post_vertex_max_supported_delay_ms = \ post_synaptic_population._get_vertex \ .get_maximum_delay_supported_in_ms(machine_time_step) if max_delay > (post_vertex_max_supported_delay_ms + _delay_extension_max_supported_delay): raise ConfigurationException( "The maximum delay {} for projection is not supported".format( max_delay)) if max_delay > user_max_delay / (machine_time_step / 1000.0): logger.warning("The end user entered a max delay" " for which the projection breaks") # check that the projection edges label is not none, and give an # auto generated label if set to None if label is None: label = "projection edge {}".format( spinnaker_control.none_labelled_edge_count) spinnaker_control.increment_none_labelled_edge_count() # Find out if there is an existing edge between the populations edge_to_merge = self._find_existing_edge( pre_synaptic_population._get_vertex, post_synaptic_population._get_vertex) if edge_to_merge is not None: # If there is an existing edge, add the connector edge_to_merge.add_synapse_information(self._synapse_information) self._projection_edge = edge_to_merge else: # If there isn't an existing edge, create a new one self._projection_edge = ProjectionApplicationEdge( pre_synaptic_population._get_vertex, post_synaptic_population._get_vertex, self._synapse_information, label=label) # add edge to the graph spinnaker_control.add_application_edge( self._projection_edge, constants.SPIKE_PARTITION_ID) # If the delay exceeds the post vertex delay, add a delay extension if max_delay > post_vertex_max_supported_delay_ms: delay_edge = self._add_delay_extension( pre_synaptic_population, post_synaptic_population, max_delay, post_vertex_max_supported_delay_ms, machine_time_step, time_scale_factor) self._projection_edge.delay_edge = delay_edge # add projection to the SpiNNaker control system spinnaker_control.add_projection(self) # If there is a virtual board, we need to hold the data in case the # user asks for it self._virtual_connection_list = None if spinnaker_control.use_virtual_board: self._virtual_connection_list = list() pre_vertex = pre_synaptic_population._get_vertex post_vertex = post_synaptic_population._get_vertex connection_holder = ConnectionHolder(None, False, pre_vertex.n_atoms, post_vertex.n_atoms, self._virtual_connection_list) post_vertex.add_pre_run_connection_holder( connection_holder, self._projection_edge, self._synapse_information)
def test_connection_holder(data_items, fixed_values, as_list): all_values = None n_items = 0 if data_items is not None or fixed_values is not None: all_values = list() elif as_list: n_items = 4 if data_items is not None: all_values.extend(data_items) n_items += len(data_items) if fixed_values is not None: all_values.extend([item[0] for item in fixed_values]) n_items += len(fixed_values) test_data_items = data_items if test_data_items is None and fixed_values is None: test_data_items = ["source", "target", "weight", "delay"] connection_holder = ConnectionHolder(data_items_to_return=all_values, as_list=as_list, n_pre_atoms=2, n_post_atoms=2, fixed_values=fixed_values) connections = numpy.array([(0, 0, 1, 10), (0, 0, 2, 20), (0, 1, 3, 30)], AbstractSynapseDynamics.NUMPY_CONNECTORS_DTYPE) connection_holder.add_connections(connections) if as_list: # Just a list so should be the same length as connections assert len(connection_holder) == len(connections) # Check that the selected item values are correct for i in range(len(connections)): # Go through each of the selected fields p = 0 if test_data_items is not None: p = len(test_data_items) for j, item in enumerate(test_data_items): item_index = connections.dtype.names.index(item) # Check that the value matches with the correct field value if n_items == 1: assert connection_holder[i] == \ connections[i][item_index] else: assert connection_holder[i][j] == \ connections[i][item_index] if fixed_values is not None: for j, item in enumerate(fixed_values): if n_items == 1: assert connection_holder[i] == item[1] else: assert connection_holder[i][p + j] == item[1] else: if n_items == 0: assert len(connection_holder) == 0 else: # Should have n_items matrices returned, each of which is a 2x2 # matrix if n_items == 1: assert len(connection_holder) == 2 assert len(connection_holder[0]) == 2 assert len(connection_holder[1]) == 2 else: assert len(connection_holder) == n_items for matrix in connection_holder: assert len(matrix) == 2 assert len(matrix[0]) == 2 assert len(matrix[1]) == 2 # Should have the values in the appropriate places # Go through each of the selected fields p = 0 if test_data_items is not None: p = len(test_data_items) for j, item in enumerate(test_data_items): # Check that the value matches with the correct field value item_index = connections.dtype.names.index(item) if n_items == 1: matrix = connection_holder else: matrix = connection_holder[j] assert matrix[0, 0] == connections[1][item_index] assert matrix[0, 1] == connections[2][item_index] assert math.isnan(matrix[1, 0]) assert math.isnan(matrix[1, 1]) if fixed_values is not None: for j, item in enumerate(fixed_values): if n_items == 1: matrix = connection_holder else: matrix = connection_holder[j + p] assert matrix[0, 0] == item[1] assert matrix[0, 1] == item[1] assert math.isnan(matrix[1, 0]) assert math.isnan(matrix[1, 1])
def __init__(self, pre_synaptic_population, post_synaptic_population, connector, synapse_type=None, source=None, receptor_type=None, space=None, label=None): """ :param ~spynnaker.pyNN.models.populations.PopulationBase \ pre_synaptic_population: :param ~spynnaker.pyNN.models.populations.PopulationBase \ post_synaptic_population: :param AbstractConnector connector: :param AbstractSynapseDynamics synapse_type: :param None source: Unsupported; must be None :param str receptor_type: :param ~pyNN.space.Space space: :param str label: """ # pylint: disable=too-many-arguments, too-many-locals if source is not None: raise NotImplementedError( "sPyNNaker {} does not yet support multi-compartmental " "cells.".format(__version__)) sim = get_simulator() self.__projection_edge = None self.__host_based_synapse_list = None self.__has_retrieved_synaptic_list_from_machine = False self.__requires_mapping = True self.__label = label pre_is_view = self.__check_population(pre_synaptic_population, connector) post_is_view = self.__check_population(post_synaptic_population, connector) # set default label if label is None: # set the projection's label to a default (maybe non-unique!) self.__label = ("from pre {} to post {} with connector {}".format( pre_synaptic_population.label, post_synaptic_population.label, connector)) # give an auto generated label for the underlying edge label = "projection edge {}".format(sim.none_labelled_edge_count) sim.increment_none_labelled_edge_count() # Handle default synapse type if synapse_type is None: synapse_dynamics = SynapseDynamicsStatic() else: synapse_dynamics = synapse_type # set the space function as required if space is None: space = PyNNSpace() connector.set_space(space) pre_vertex = pre_synaptic_population._vertex post_vertex = post_synaptic_population._vertex if not isinstance(post_vertex, AbstractAcceptsIncomingSynapses): raise ConfigurationException( "postsynaptic population is not designed to receive" " synaptic projections") # sort out synapse type synaptic_type = post_vertex.get_synapse_id_by_target(receptor_type) synapse_type_from_dynamics = False if synaptic_type is None: synaptic_type = synapse_dynamics.get_synapse_id_by_target( receptor_type) synapse_type_from_dynamics = True if synaptic_type is None: raise ConfigurationException( "Synapse target {} not found in {}".format( receptor_type, post_synaptic_population.label)) # as a from-list connector can have plastic parameters, grab those ( # if any) and add them to the synapse dynamics object if isinstance(connector, FromListConnector): connector._apply_parameters_to_synapse_type(synaptic_type) # round the delays to multiples of full timesteps # (otherwise SDRAM estimation calculations can go wrong) if ((not isinstance(synapse_dynamics.delay, RandomDistribution)) and (not isinstance(synapse_dynamics.delay, str))): synapse_dynamics.set_delay( numpy.rint( numpy.array(synapse_dynamics.delay) * machine_time_step_per_ms()) * machine_time_step_ms()) # set the plasticity dynamics for the post pop (allows plastic stuff # when needed) post_vertex.set_synapse_dynamics(synapse_dynamics) # get rng if needed rng = connector.rng if hasattr(connector, "rng") else None # Set and store synapse information for future processing self.__synapse_information = SynapseInformation( connector, pre_synaptic_population, post_synaptic_population, pre_is_view, post_is_view, rng, synapse_dynamics, synaptic_type, receptor_type, sim.use_virtual_board, synapse_type_from_dynamics, synapse_dynamics.weight, synapse_dynamics.delay) # Set projection information in connector connector.set_projection_information(self.__synapse_information) # Find out if there is an existing edge between the populations edge_to_merge = self._find_existing_edge(pre_vertex, post_vertex) if edge_to_merge is not None: # If there is an existing edge, add the connector edge_to_merge.add_synapse_information(self.__synapse_information) self.__projection_edge = edge_to_merge else: # If there isn't an existing edge, create a new one and add it self.__projection_edge = ProjectionApplicationEdge( pre_vertex, post_vertex, self.__synapse_information, label=label) sim.add_application_edge(self.__projection_edge, SPIKE_PARTITION_ID) # add projection to the SpiNNaker control system sim.add_projection(self) # If there is a virtual board, we need to hold the data in case the # user asks for it self.__virtual_connection_list = None if sim.use_virtual_board: self.__virtual_connection_list = list() connection_holder = ConnectionHolder( None, False, pre_vertex.n_atoms, post_vertex.n_atoms, self.__virtual_connection_list) self.__synapse_information.add_pre_run_connection_holder( connection_holder) # If the target is a population, add to the list of incoming # projections if isinstance(post_vertex, AbstractPopulationVertex): post_vertex.add_incoming_projection(self) # If the source is a poisson, add to the list of outgoing projections if isinstance(pre_vertex, SpikeSourcePoissonVertex): pre_vertex.add_outgoing_projection(self)