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)
Example #2
0
    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])
Example #8
0
    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)