Esempio n. 1
0
def _rescale_connections(connections, weight_scales, synapse_info):
    """ Scale the connection data into machine values

    :param ~numpy.ndarray connections: The connections to be rescaled
    :param list(float) weight_scales: The weight scale of each synapse type
    :param SynapseInformation synapse_info:
        The synapse information of the connections
    """
    # Return the delays values to milliseconds
    connections["delay"] /= machine_time_step_per_ms()
    # Undo the weight scaling
    connections["weight"] /= weight_scales[synapse_info.synapse_type]
    return connections
    def write_parameters(self, spec, weight_scales):

        # Write parameters
        spec.write_value(data=self.__accumulator_depression_plus_one,
                         data_type=DataType.INT32)
        spec.write_value(data=self.__accumulator_potentiation_minus_one,
                         data_type=DataType.INT32)

        # Convert mean times into machine timesteps
        time_step_per_ms = machine_time_step_per_ms()

        mean_pre_timesteps = float(self.__mean_pre_window * time_step_per_ms)
        mean_post_timesteps = float(self.__mean_post_window * time_step_per_ms)

        # Write lookup tables
        self._write_exp_dist_lut(spec, mean_pre_timesteps)
        self._write_exp_dist_lut(spec, mean_post_timesteps)
Esempio n. 3
0
    def gen_data(self):
        """ The data to be written for this connection

        :rtype: ~numpy.ndarray(~numpy.uint32)
        """
        connector = self.__synapse_information.connector
        synapse_dynamics = self.__synapse_information.synapse_dynamics
        items = list()
        items.append(
            numpy.array([
                self.__synaptic_matrix_offset,
                self.__delayed_synaptic_matrix_offset, self.__max_row_n_words,
                self.__max_delayed_row_n_words, self.__max_row_n_synapses,
                self.__max_delayed_row_n_synapses,
                self.__pre_vertex_slice.lo_atom,
                self.__pre_vertex_slice.n_atoms, self.__max_stage,
                self.__max_delay_per_stage,
                DataType.S1615.encode_as_int(machine_time_step_per_ms()),
                self.__synapse_information.synapse_type,
                synapse_dynamics.gen_matrix_id, connector.gen_connector_id,
                connector.gen_weights_id(self.__synapse_information.weights),
                connector.gen_delays_id(self.__synapse_information.delays)
            ],
                        dtype=numpy.uint32))
        items.append(synapse_dynamics.gen_matrix_params)
        items.append(
            connector.gen_connector_params(
                self.__pre_slices, self.__post_slices, self.__pre_vertex_slice,
                self.__post_vertex_slice,
                self.__synapse_information.synapse_type,
                self.__synapse_information))
        items.append(
            connector.gen_weights_params(self.__synapse_information.weights,
                                         self.__pre_vertex_slice,
                                         self.__post_vertex_slice))
        items.append(
            connector.gen_delay_params(self.__synapse_information.delays,
                                       self.__pre_vertex_slice,
                                       self.__post_vertex_slice))
        return items
Esempio n. 4
0
def get_synapses(connections, synapse_info, n_delay_stages, n_synapse_types,
                 weight_scales, app_edge, pre_vertex_slice, post_vertex_slice,
                 max_row_info, gen_undelayed, gen_delayed):
    """ Get the synapses as an array of words for non-delayed synapses and\
        an array of words for delayed synapses. This is used to prepare\
        information for *deployment to SpiNNaker*.

    :param ~numpy.ndarray connections:
        The connections to get the synapses from
    :param SynapseInformation synapse_info:
        The synapse information to convert to synapses
    :param int n_delay_stages:
        The number of delay stages in total to be represented
    :param int n_synapse_types:
        The number of synapse types in total to be represented
    :param list(float) weight_scales:
        The scaling of the weights for each synapse type
    :param ~pacman.model.graphs.appplication.ApplicationEdge app_edge:
        The incoming machine edge that the synapses are on
    :param ~pacman.model.graphs.common.Slice pre_vertex_slice:
        The slice of the pre-vertex to get the synapses for
    :param ~pacman.model.graphs.common.Slice post_vertex_slice:
        The slice of the post-vertex to get the synapses for
    :param MaxRowInfo max_row_info:
        The maximum row information for the synapses
    :param bool gen_undelayed:
        Whether to generate undelayed data
    :param bool gen_delayed:
        Whether to generate delayed data
    :return:
        (``row_data``, ``delayed_row_data``, ``delayed_source_ids``,
        ``stages``) where:

        * ``row_data`` is the undelayed connectivity data arranged into a
            row per source, each row the same length
        * ``delayed_row_data`` is the delayed connectivity data arranged
            into a row per source per delay stage, each row the same length
        * ``delayed_source_ids`` is the machine-vertex-local source neuron
            id of each connection of the delayed vertices
        * ``stages`` is the delay stage of each delayed connection
    :rtype:
        tuple(~numpy.ndarray, ~numpy.ndarray, ~numpy.ndarray,
        ~numpy.ndarray)
    """
    # pylint: disable=too-many-arguments, too-many-locals
    # pylint: disable=assignment-from-no-return
    # Get delays in timesteps
    max_delay = app_edge.post_vertex.splitter.max_support_delay()

    # Convert delays to timesteps
    connections["delay"] = numpy.rint(connections["delay"] *
                                      machine_time_step_per_ms())

    # Scale weights
    if not synapse_info.synapse_type_from_dynamics:
        connections["weight"] = (connections["weight"] *
                                 weight_scales[synapse_info.synapse_type])

    # Split the connections up based on the delays
    if max_delay is not None:
        plastic_delay_mask = (connections["delay"] <= max_delay)
        undelayed_connections = connections[numpy.where(plastic_delay_mask)]
        delayed_connections = connections[numpy.where(~plastic_delay_mask)]
    else:
        undelayed_connections = connections
        delayed_connections = numpy.zeros(
            0, dtype=AbstractConnector.NUMPY_SYNAPSES_DTYPE)

    # Get the data for the connections
    row_data = numpy.zeros(0, dtype="uint32")
    if gen_undelayed and max_row_info.undelayed_max_n_synapses:
        # Get which row each connection will go into
        undelayed_row_indices = (undelayed_connections["source"] -
                                 pre_vertex_slice.lo_atom)
        row_data = _get_row_data(undelayed_connections, undelayed_row_indices,
                                 pre_vertex_slice.n_atoms, post_vertex_slice,
                                 n_synapse_types,
                                 synapse_info.synapse_dynamics,
                                 max_row_info.undelayed_max_n_synapses,
                                 max_row_info.undelayed_max_words)

        del undelayed_row_indices
    del undelayed_connections

    # Get the data for the delayed connections
    delayed_row_data = numpy.zeros(0, dtype="uint32")
    stages = numpy.zeros(0, dtype="uint32")
    delayed_source_ids = numpy.zeros(0, dtype="uint32")
    if gen_delayed and max_row_info.delayed_max_n_synapses:
        # Get the delay stages and which row each delayed connection will
        # go into
        stages = numpy.floor(
            (numpy.round(delayed_connections["delay"] - 1.0)) /
            max_delay).astype("uint32")
        delayed_row_indices = (
            (delayed_connections["source"] - pre_vertex_slice.lo_atom) +
            ((stages - 1) * pre_vertex_slice.n_atoms))
        delayed_connections["delay"] -= max_delay * stages
        delayed_source_ids = (delayed_connections["source"] -
                              pre_vertex_slice.lo_atom)

        # Get the data
        delayed_row_data = _get_row_data(
            delayed_connections, delayed_row_indices,
            pre_vertex_slice.n_atoms * n_delay_stages, post_vertex_slice,
            n_synapse_types, synapse_info.synapse_dynamics,
            max_row_info.delayed_max_n_synapses,
            max_row_info.delayed_max_words)
        del delayed_row_indices
    del delayed_connections

    return row_data, delayed_row_data, delayed_source_ids, stages
Esempio n. 5
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)