Exemplo n.º 1
0
    def __init__(self,
                 size,
                 cellclass,
                 cellparams,
                 spinnaker,
                 label,
                 structure=None):
        """
        Instantiates a :py:object:`Population`.
        """
        if size is not None and size <= 0:
            raise exceptions.ConfigurationException(
                "A population cannot have a negative or zero size.")

        # Create a partitionable_graph vertex for the population and add it
        # to PACMAN
        cell_label = label
        if label is None:
            cell_label = "Population {}"\
                         .format(Population._non_labelled_vertex_count)
            Population._non_labelled_vertex_count += 1
        cellparams['label'] = cell_label
        cellparams['n_neurons'] = size
        cellparams['machine_time_step'] = spinnaker.machine_time_step
        cellparams['timescale_factor'] = spinnaker.timescale_factor
        cellparams['spikes_per_second'] = spinnaker.spikes_per_second
        cellparams['ring_buffer_sigma'] = spinnaker.ring_buffer_sigma
        self._vertex = cellclass(**cellparams)
        self._spinnaker = spinnaker
        self._delay_vertex = None

        # Internal structure now supported 23 November 2014 ADR
        # structure should be a valid Space.py structure type.
        # generation of positions is deferred until needed.
        if structure:
            self._structure = structure
            self._positions = None
        else:
            self._structure = None

        self._spinnaker._add_population(self)
        self._spinnaker.add_vertex(self._vertex)

        self._parameters = PyNNParametersSurrogate(self._vertex)

        # initialize common stuff
        self._size = size
        self._record_spike_file = None
        self._record_v_file = None
        self._record_gsyn_file = None

        self._spikes = None
        self._v = None
        self._gsyn = None
Exemplo n.º 2
0
 def test_surrogate_get_item(self):
     test_vertex = MyTestVertex()
     self.assertEqual(test_vertex.cm, 0.2)
     self.assertEqual(test_vertex.tau_refract, 0.0)
     self.assertEqual(test_vertex.tau_syn_E, 5.0)
     surrogate = PyNNParametersSurrogate(test_vertex)
     self.assertEqual(surrogate['cm'], 0.2)
     self.assertEqual(surrogate['tau_refract'], 0.0)
     self.assertEqual(surrogate['tau_syn_E'], 5.0)
Exemplo n.º 3
0
    def __init__(self, size, cellclass, cellparams, spinnaker, label,
                 structure=None):
        """
        Instantiates a :py:object:`Population`.
        """
        if size is not None and size <= 0:
            raise exceptions.ConfigurationException(
                "A population cannot have a negative or zero size.")

        # Create a partitionable_graph vertex for the population and add it
        # to PACMAN
        cell_label = label
        if label is None:
            cell_label = "Population {}"\
                         .format(Population._non_labelled_vertex_count)
            Population._non_labelled_vertex_count += 1
        cellparams['label'] = cell_label
        cellparams['n_neurons'] = size
        cellparams['machine_time_step'] = spinnaker.machine_time_step
        cellparams['timescale_factor'] = spinnaker.timescale_factor
        if 'spikes_per_second' not in cellparams:
            cellparams['spikes_per_second'] = spinnaker.spikes_per_second
        if 'ring_buffer_sigma' not in cellparams:
            cellparams['ring_buffer_sigma'] = spinnaker.ring_buffer_sigma
        self._vertex = cellclass(**cellparams)
        self._spinnaker = spinnaker
        self._delay_vertex = None

        # Internal structure now supported 23 November 2014 ADR
        # structure should be a valid Space.py structure type.
        # generation of positions is deferred until needed.
        if structure:
            self._structure = structure
            self._positions = None
        else:
            self._structure = None

        self._spinnaker._add_population(self)
        self._spinnaker.add_vertex(self._vertex)

        self._parameters = PyNNParametersSurrogate(self._vertex)

        # initialize common stuff
        self._size = size
        self._record_spike_file = None
        self._record_v_file = None
        self._record_gsyn_file = None

        self._spikes_cache_file = None
        self._v_cache_file = None
        self._gsyn_cache_file = None
Exemplo n.º 4
0
 def test_surrogate_set_item(self):
     test_vertex = MyTestVertex()
     self.assertEqual(test_vertex.cm, 0.2)
     self.assertEqual(test_vertex.tau_refract, 0.0)
     self.assertEqual(test_vertex.tau_syn_E, 5.0)
     surrogate = PyNNParametersSurrogate(test_vertex)
     surrogate['cm'] = 2.0
     surrogate['tau_refract'] = 10.5
     surrogate['tau_syn_E'] = 15
     self.assertEqual(surrogate['cm'], 2.0)
     self.assertEqual(surrogate['tau_refract'], 10.5)
     self.assertEqual(surrogate['tau_syn_E'], 15)
     self.assertEqual(test_vertex.cm, 2.0)
     self.assertEqual(test_vertex.tau_refract, 10.5)
     self.assertEqual(test_vertex.tau_syn_E, 15)
Exemplo n.º 5
0
class Population(object):
    """
    A collection neuron of the same types. It encapsulates a type of
    vertex used with Spiking Neural Networks, comprising n cells (atoms)
    of the same model type.

    :param int size:
        size (number of cells) of the Population.
    :param cellclass:
        specifies the neural model to use for the Population
    :param dict cellparams:
        a dictionary containing model specific parameters and values
    :param structure:
        a spatial structure
    :param string label:
        a label identifying the Population
    :returns a list of vertexes and edges
    """

    _non_labelled_vertex_count = 0

    def __init__(self, size, cellclass, cellparams, spinnaker, label,
                 structure=None):
        """
        Instantiates a :py:object:`Population`.
        """
        if size is not None and size <= 0:
            raise exceptions.ConfigurationException(
                "A population cannot have a negative or zero size.")

        # Create a partitionable_graph vertex for the population and add it
        # to PACMAN
        cell_label = label
        if label is None:
            cell_label = "Population {}"\
                         .format(Population._non_labelled_vertex_count)
            Population._non_labelled_vertex_count += 1
        cellparams['label'] = cell_label
        cellparams['n_neurons'] = size
        cellparams['machine_time_step'] = spinnaker.machine_time_step
        cellparams['timescale_factor'] = spinnaker.timescale_factor
        cellparams['spikes_per_second'] = spinnaker.spikes_per_second
        cellparams['ring_buffer_sigma'] = spinnaker.ring_buffer_sigma
        self._vertex = cellclass(**cellparams)
        self._spinnaker = spinnaker
        self._delay_vertex = None

        # Internal structure now supported 23 November 2014 ADR
        # structure should be a valid Space.py structure type.
        # generation of positions is deferred until needed.
        if structure:
            self._structure = structure
            self._positions = None
        else:
            self._structure = None

        self._spinnaker.add_vertex(self._vertex)

        self._parameters = PyNNParametersSurrogate(self._vertex)

        # initialize common stuff
        self._size = size
        self._record_spike_file = None
        self._record_v_file = None
        self._record_g_syn_file = None

        self._spikes = None
        self._v = None
        self._gsyn = None

    def __add__(self, other):
        """
        merges populations
        """
        raise NotImplementedError

    def _add_recorder(self, variable):
        """Create a new Recorder for the supplied variable."""
        raise NotImplementedError

    def all(self):
        """
        Iterator over cell ids on all nodes.
        """
        raise NotImplementedError

    @property
    def conductance_based(self):
        """
        returns a boolean based on if the population is a conductance based pop
        """
        raise NotImplementedError

    def describe(self, template='population_default.txt', engine='default'):
        """
        Returns a human-readable description of the population.

        The output may be customized by specifying a different template
        togther with an associated template engine (see ``pyNN.descriptions``).

        If template is None, then a dictionary containing the template context
        will be returned.
        """
        raise NotImplementedError

    @property
    def grandparent(self):
        raise NotImplementedError

    def get(self, paramter_name, gather=False):
        """
        Get the values of a parameter for every local cell in the population.
        """
        raise NotImplementedError

    def _get_cell_position(self, cell_id):
        """
        returns the position of a cell.
        """
        if self._structure is None:
            raise ValueError("Attempted to get the position of a cell "
                             "in an un-structured population")
        elif self._positions is None:
            self._structure.generate_positions(self._vertex.n_atoms)
        return self._positions[cell_id]

    def _get_cell_initial_value(self, cell_id, variable):
        """
        set a given cells intial value
        """
        raise NotImplementedError

    # noinspection PyPep8Naming
    def getSpikes(self, compatible_output=False, gather=True):
        """
        Return a 2-column numpy array containing cell ids and spike times for
        recorded cells.   This is read directly from the memory for the board.
        """
        if self._spikes is None:

            if not gather:
                logger.warn("Spynnaker only supports gather = true, will "
                            " execute as if gather was true anyhow")
            timer = None

            if not self._vertex.record:
                raise exceptions.ConfigurationException(
                    "This population has not been set to record spikes. "
                    "Therefore spikes cannot be retrieved. Please set this "
                    "vertex to record spikes before running this command.")

            if not self._spinnaker.has_ran:
                raise local_exceptions.SpynnakerException(
                    "The simulation has not yet ran, therefore spikes cannot"
                    " be retrieved. Please execute the simulation before"
                    " running this command")
            if conf.config.getboolean("Reports", "outputTimesForSections"):
                timer = Timer()
                timer.start_timing()
            self._spikes = self._vertex.get_spikes(
                txrx=self._spinnaker.transceiver,
                placements=self._spinnaker.placements,
                graph_mapper=self._spinnaker.graph_mapper,
                compatible_output=compatible_output)
            if conf.config.getboolean("Reports", "outputTimesForSections"):
                timer.take_sample()
        return self._spikes

    def get_spike_counts(self, gather=True):
        """
        Returns the number of spikes for each neuron.
        """
        raise NotImplementedError

    # noinspection PyUnusedLocal
    def get_gsyn(self, gather=True, compatible_output=False):
        """
        Return a 3-column numpy array containing cell ids and synaptic
        conductances for recorded cells.

        """
        if self._gsyn is None:
            timer = None
            if conf.config.getboolean("Reports", "outputTimesForSections"):
                timer = Timer()
                timer.start_timing()
            self._gsyn = self._vertex.get_gsyn(
                has_ran=self._spinnaker.has_ran,
                txrx=self._spinnaker.transceiver,
                placements=self._spinnaker.placements,
                machine_time_step=self._spinnaker.machine_time_step,
                graph_mapper=self._spinnaker.graph_mapper,
                compatible_output=compatible_output)
            if conf.config.getboolean("Reports", "outputTimesForSections"):
                timer.take_sample()
        return self._gsyn

    # noinspection PyUnusedLocal
    def get_v(self, gather=True, compatible_output=False):
        """
        Return a 3-column numpy array containing cell ids, time, and Vm for
        recorded cells.

        :param gather:
            not used - inserted to match PyNN specs
        :type gather: bool
        :param compatible_output:
            not used - inserted to match PyNN specs
        :type compatible_output: bool
        """
        if self._v is None:
            timer = None
            if conf.config.getboolean("Reports", "outputTimesForSections"):
                timer = Timer()
                timer.start_timing()
            self._v = self._vertex.get_v(
                has_ran=self._spinnaker.has_ran,
                txrx=self._spinnaker.transceiver,
                placements=self._spinnaker.placements,
                machine_time_step=self._spinnaker.machine_time_step,
                graph_mapper=self._spinnaker.graph_mapper,
                compatible_output=compatible_output)

            if conf.config.getboolean("Reports", "outputTimesForSections"):
                timer.take_sample()

        return self._v

    def id_to_index(self, cell_id):
        """
        Given the ID(s) of cell(s) in the Population, return its (their) index
        (order in the Population).
        """
        raise NotImplementedError

    def id_to_local_index(self, cell_id):
        """
        Given the ID(s) of cell(s) in the Population, return its (their) index
        (order in the Population), counting only cells on the local MPI node.
        """
        raise NotImplementedError

    def initialize(self, variable, value):
        """
        Set the initial value of one of the state variables of the neurons in
        this population.

        """
        initialize_attr = \
            getattr(self._vertex, "initialize_%s" % variable, None)
        if initialize_attr is None or not callable(initialize_attr):
            raise Exception("Vertex does not support "
                            "initialization of parameter {%s}".format(
                                variable))

        initialize_attr(value)

    def is_local(self, cell_id):
        """
        Determine whether the cell with the given ID exists on the local
        MPI node.
        """
        raise NotImplementedError

    def can_record(self, variable):
        """ Determine whether `variable` can be recorded from this population.
        """
        raise NotImplementedError

    def inject(self, current_source):
        """
        Connect a current source to all cells in the Population.
        """
        raise NotImplementedError

    def __iter__(self):
        """
        suppose to iterate over local cells
        """
        raise NotImplementedError

    def __len__(self):
        """
        Returns the total number of cells in the population.
        """
        return self._size

    @property
    def label(self):
        return self._vertex.label

    @property
    def local_size(self):
        """
        returns the number of local cells ???
        """
        raise NotImplementedError

    def mean_spike_count(self, gather=True):
        """
        Returns the mean number of spikes per neuron.
        """
        raise NotImplementedError

    def nearest(self, position):
        """
        return the neuron closest to the specified position.
        Added functionality 23 November 2014 ADR
        """
        if self._structure is None:
            raise ValueError("attempted to retrieve positions "
                             "for an un-structured population")
        elif self._positions is None:
            self._structure.generate_positions(self._vertex.n_atoms)
        position_diff = numpy.empty(self._positions.shape)
        position_diff.fill(position)
        distances = Space.distances(self._positions, position_diff)
        return distances.argmin()

    @property
    def position_generator(self):
        """
        returns a position generator. Added functionality 27 November 2014 ADR
        """
        if self._structure is None:
            raise ValueError("attempted to retrieve positions "
                             "for an un-structured population")
        else:
            return self._structure.generate_positions

    # noinspection PyPep8Naming
    def randomInit(self, distribution):
        """
        Set initial membrane potentials for all the cells in the population to
        random values.

        :param `pyNN.random.RandomDistribution` distribution:
            the distribution used to draw random values.

        """
        self.initialize('v', distribution)

    def record(self, to_file=None):
        """
        Record spikes from all cells in the Population.
        A flag is set for this population that is passed to the simulation,
        triggering spike time recording.
        """

        if not isinstance(self._vertex, AbstractPopulationRecordableVertex):
            raise Exception("This population does not support recording!")

        # Tell the vertex to record spikes
        self._vertex.set_record(True)

        # set the file to store the spikes in once retrieved
        self._record_spike_file = to_file

    def record_gsyn(self, to_file=None):
        """
        Record the synaptic conductance for all cells in the Population.
        A flag is set for this population that is passed to the simulation,
        triggering gsyn value recording.
        """
        if not isinstance(self._vertex, AbstractPopulationRecordableVertex):
            raise Exception("Vertex does not support "
                            "recording of gsyn")

        self._vertex.set_record_gsyn(True)
        self._record_g_syn_file = to_file

    def record_v(self, to_file=None):
        """
        Record the membrane potential for all cells in the Population.
        A flag is set for this population that is passed to the simulation,
        triggering potential recording.
        """
        if not isinstance(self._vertex, AbstractPopulationRecordableVertex):
            raise Exception("Vertex does not support "
                            "recording of potential")

        self._vertex.set_record_v(True)
        self._record_v_file = to_file

    @property
    def positions(self):
        """
        Returns the position array for structured populations.
        Added functionality 27 November 2014 ADR
        """
        if self._structure is None:
            raise ValueError("attempted to retrieve positions "
                             "for an un-structured population")
        elif self._positions is None:
            self._positions = self._structure.generate_positions(
                self._vertex.n_atoms)
        return self._positions

    # noinspection PyPep8Naming
    def printSpikes(self, filename, gather=True):
        """
        Write spike time information from the population to a given file.
        :param filename: the absoluete file path for where the spikes are to be
        printed in
        :param gather: Supported from the PyNN language, but Spinnaker only does
        gather = True.
        """
        if not gather:
            logger.warn("Spynnaker only supports gather = true, will execute"
                        " as if gather was true anyhow")
        spikes = self.getSpikes(compatible_output=True)
        if spikes is not None:
            first_id = 0
            num_neurons = self._vertex.n_atoms
            dimensions = self._vertex.n_atoms
            last_id = self._vertex.n_atoms - 1
            utility_calls.check_directory_exists_and_create_if_not(filename)
            spike_file = open(filename, "w")
            spike_file.write("# first_id = {}\n".format(first_id))
            spike_file.write("# n = {}\n".format(num_neurons))
            spike_file.write("# dimensions = [{}]\n".format(dimensions))
            spike_file.write("# last_id = {}\n".format(last_id))
            for (neuronId, time) in spikes:
                spike_file.write("{}\t{}\n".format(time, neuronId))
            spike_file.close()

    def print_gsyn(self, filename, gather=True):
        """
        Write conductance information from the population to a given file.
        :param filename: the absoluete file path for where the gsyn are to be
        printed in
        :param gather: Supported from the PyNN language, but Spinnaker only does
        gather = True.
        """
        time_step = (self._spinnaker.machine_time_step * 1.0) / 1000.0
        gsyn = self.get_gsyn(gather, compatible_output=True)
        first_id = 0
        num_neurons = self._vertex.n_atoms
        dimensions = self._vertex.n_atoms
        utility_calls.check_directory_exists_and_create_if_not(filename)
        file_handle = open(filename, "w")
        file_handle.write("# first_id = {}\n".format(first_id))
        file_handle.write("# n = {}\n".format(num_neurons))
        file_handle.write("# dt = {}\n".format(time_step))
        file_handle.write("# dimensions = [{}]\n".format(dimensions))
        file_handle.write("# last_id = {{}}\n".format(num_neurons - 1))
        file_handle = open(filename, "w")
        for (neuronId, time, value) in gsyn:
            file_handle.write("{}\t{}\t{}\n".format(time, neuronId, value))
        file_handle.close()

    def print_v(self, filename, gather=True):
        """
        Write membrane potential information from the population to a given
        file.
        :param filename: the absoluete file path for where the voltage are to be
        printed in
        :param gather: Supported from the PyNN language, but Spinnaker only does
        gather = True.
        """
        time_step = (self._spinnaker.machine_time_step * 1.0) / 1000.0
        v = self.get_v(gather, compatible_output=True)
        utility_calls.check_directory_exists_and_create_if_not(filename)
        file_handle = open(filename, "w")
        first_id = 0
        num_neurons = self._vertex.n_atoms
        dimensions = self._vertex.n_atoms
        file_handle.write("# first_id = {}\n".format(first_id))
        file_handle.write("# n = {}\n".format(num_neurons))
        file_handle.write("# dt = {}\n".format(time_step))
        file_handle.write("# dimensions = [{}]\n".format(dimensions))
        file_handle.write("# last_id = {}\n".format(num_neurons - 1))
        for (neuronId, time, value) in v:
            file_handle.write("{}\t{}\t{}\n".format(time, neuronId, value))
        file_handle.close()

    def rset(self, parametername, rand_distr):
        """
        'Random' set. Set the value of parametername to a value taken from
        rand_distr, which should be a RandomDistribution object.
        :param parametername: the paramter to set
        :param rand_distr: the random distrubtion object to set the paramter to
        """
        raise NotImplementedError

    def sample(self, n, rng=None):
        """
        returns a random selection fo neurons from a population in the form
        of a population view
        """
        raise NotImplementedError

    def save_positions(self, file_name):
        """
        save positions to file. Added functionality 23 November 2014 ADR
        """
        if self._structure is None:
            raise ValueError("attempted to retrieve positions "
                             "for an un-structured population")
        elif self._positions is None:
            self._structure.generate_positions(self._vertex.n_atoms)
        file_handle = open(file_name, "w")
        file_handle.write(self._positions)
        file_handle.close()

    def _set_cell_initial_value(self, cell_id, variable, value):
        """
        set a given cells intial value
        """
        raise NotImplementedError

    def _set_cell_position(self, cell_id, pos):
        """
        sets a cell to a given position
        """
        if self._structure is None:
            raise ValueError("attempted to set a position for a cell "
                             "in an un-structured population")
        elif self._positions is None:
            self._structure.generate_positions(self._vertex.n_atoms)
        self._positions[cell_id] = pos

    def _set_positions(self, positions):
        """
        sets all the positions in the population.
        """
        if self._structure is None:
            raise ValueError("attempted to set positions "
                             "in an un-structured population")
        else:
            self._positions = positions

    def set(self, parameter, value=None):
        """
        Set one or more parameters for every cell in the population.

        param can be a dict, in which case val should not be supplied, or a
        string giving the parameter name, in which case val is the parameter
        value. val can be a numeric value, or list of such
        (e.g. for setting spike times)::

          p.set("tau_m", 20.0).
          p.set({'tau_m':20, 'v_rest':-65})
        """
        if type(parameter) is str:
            if value is None:
                raise Exception("Error: No value given in set() function for "
                                "population parameter. Exiting.")
            self._parameters[parameter] = value
            return
        if type(parameter) is not dict:
                raise Exception("Error: invalid parameter type for "
                                "set() function for population parameter."
                                " Exiting.")
        # Add a dictionary-structured set of new parameters to the current set:
        self._parameters.update(parameter)

    @property
    def structure(self):
        """
        Returns the structure for the population. Added 23 November 2014 ADR
        """
        return self._structure

    # NONE PYNN API CALL
    def set_constraint(self, constraint):
        """
        Apply a constraint to a population that restricts the processor
        onto which its sub-populations will be placed.
        """
        if isinstance(constraint, AbstractConstraint):
            self._vertex.add_constraint(constraint)
        else:
            raise exceptions.ConfigurationException(
                "the constraint entered is not a recongised constraint. "
                "try again")

    # NONE PYNN API CALL
    def add_placement_constraint(self, x, y, p=None):
        """ Add a placement constraint

        :param x: The x-coordinate of the placement constraint
        :type x: int
        :param y: The y-coordinate of the placement constraint
        :type y: int
        :param p: The processor id of the placement constraint (optional)
        :type p: int
        """
        self._vertex.add_constraint(PlacerChipAndCoreConstraint(x, y, p))

    # NONE PYNN API CALL
    def set_mapping_constraint(self, constraint_dict):
        """ Add a placement constraint - for backwards compatibility

        :param constraint_dict: A dictionary containing "x", "y" and\
                    optionally "p" as keys, and ints as values
        :type constraint_dict: dict of str->int
        """
        self.add_placement_constraint(**constraint_dict)

    # NONE PYNN API CALL
    def set_model_based_max_atoms_per_core(self, new_value):
        if hasattr(self._vertex, "set_model_max_atoms_per_core"):
            self._vertex.set_model_max_atoms_per_core(new_value)
        else:
            raise exceptions.ConfigurationException(
                "This population does not support its max_atoms_per_core "
                "variable being adjusted by the end user. Sorry")

    @property
    def size(self):
        return self._vertex.n_atoms

    def tset(self, parametername, value_array):
        """
        'Topographic' set. Set the value of parametername to the values in
        value_array, which must have the same dimensions as the Population.
        """
        raise NotImplementedError

    @property
    def _get_vertex(self):
        return self._vertex

    @property
    def _internal_delay_vertex(self):
        return self._delay_vertex

    @_internal_delay_vertex.setter
    def _internal_delay_vertex(self, delay_vertex):
        self._delay_vertex = delay_vertex
Exemplo n.º 6
0
 def test_surrogate_set_item_exception(self):
     test_vertex = MyTestVertex()
     surrogate = PyNNParametersSurrogate(test_vertex)
     with self.assertRaises(Exception):
         surrogate['tau_rev_e'] = 5
Exemplo n.º 7
0
class Population(object):
    """
    A collection neuron of the same types. It encapsulates a type of
    vertex used with Spiking Neural Networks, comprising n cells (atoms)
    of the same model type.

    :param int size:
        size (number of cells) of the Population.
    :param cellclass:
        specifies the neural model to use for the Population
    :param dict cellparams:
        a dictionary containing model specific parameters and values
    :param structure:
        a spatial structure
    :param string label:
        a label identifying the Population
    :returns a list of vertexes and edges
    """

    _non_labelled_vertex_count = 0

    def __init__(self,
                 size,
                 cellclass,
                 cellparams,
                 spinnaker,
                 label,
                 structure=None):
        """
        Instantiates a :py:object:`Population`.
        """
        if size is not None and size <= 0:
            raise exceptions.ConfigurationException(
                "A population cannot have a negative or zero size.")

        # Create a partitionable_graph vertex for the population and add it
        # to PACMAN
        cell_label = label
        if label is None:
            cell_label = "Population {}"\
                         .format(Population._non_labelled_vertex_count)
            Population._non_labelled_vertex_count += 1
        cellparams['label'] = cell_label
        cellparams['n_neurons'] = size
        cellparams['machine_time_step'] = spinnaker.machine_time_step
        cellparams['timescale_factor'] = spinnaker.timescale_factor
        cellparams['spikes_per_second'] = spinnaker.spikes_per_second
        cellparams['ring_buffer_sigma'] = spinnaker.ring_buffer_sigma
        self._vertex = cellclass(**cellparams)
        self._spinnaker = spinnaker
        self._delay_vertex = None

        # Internal structure now supported 23 November 2014 ADR
        # structure should be a valid Space.py structure type.
        # generation of positions is deferred until needed.
        if structure:
            self._structure = structure
            self._positions = None
        else:
            self._structure = None

        self._spinnaker._add_population(self)
        self._spinnaker.add_vertex(self._vertex)

        self._parameters = PyNNParametersSurrogate(self._vertex)

        # initialize common stuff
        self._size = size
        self._record_spike_file = None
        self._record_v_file = None
        self._record_gsyn_file = None

        self._spikes = None
        self._v = None
        self._gsyn = None

    def __add__(self, other):
        """
        merges populations
        """
        raise NotImplementedError

    def _add_recorder(self, variable):
        """Create a new Recorder for the supplied variable."""
        raise NotImplementedError

    def all(self):
        """
        Iterator over cell ids on all nodes.
        """
        raise NotImplementedError

    @property
    def conductance_based(self):
        """
        returns a boolean based on if the population is a conductance based pop
        """
        raise NotImplementedError

    def describe(self, template='population_default.txt', engine='default'):
        """
        Returns a human-readable description of the population.

        The output may be customized by specifying a different template
        togther with an associated template engine (see ``pyNN.descriptions``).

        If template is None, then a dictionary containing the template context
        will be returned.
        """
        raise NotImplementedError

    @property
    def grandparent(self):
        raise NotImplementedError

    def get(self, paramter_name, gather=False):
        """
        Get the values of a parameter for every local cell in the population.
        """
        raise NotImplementedError

    def _get_cell_position(self, cell_id):
        """
        returns the position of a cell.
        """
        if self._structure is None:
            raise ValueError("Attempted to get the position of a cell "
                             "in an un-structured population")
        elif self._positions is None:
            self._structure.generate_positions(self._vertex.n_atoms)
        return self._positions[cell_id]

    def _get_cell_initial_value(self, cell_id, variable):
        """
        set a given cells intial value
        """
        raise NotImplementedError

    # noinspection PyPep8Naming
    def getSpikes(self, compatible_output=False, gather=True):
        """
        Return a 2-column numpy array containing cell ids and spike times for
        recorded cells.   This is read directly from the memory for the board.
        """
        if self._spikes is None:

            if not gather:
                logger.warn("Spynnaker only supports gather = true, will "
                            " execute as if gather was true anyhow")
            timer = None

            if not self._vertex.record:
                raise exceptions.ConfigurationException(
                    "This population has not been set to record spikes. "
                    "Therefore spikes cannot be retrieved. Please set this "
                    "vertex to record spikes before running this command.")

            if not self._spinnaker.has_ran:
                raise local_exceptions.SpynnakerException(
                    "The simulation has not yet run, therefore spikes cannot"
                    " be retrieved. Please execute the simulation before"
                    " running this command")
            if conf.config.getboolean("Reports", "outputTimesForSections"):
                timer = Timer()
                timer.start_timing()
            self._spikes = self._vertex.get_spikes(
                txrx=self._spinnaker.transceiver,
                placements=self._spinnaker.placements,
                graph_mapper=self._spinnaker.graph_mapper,
                compatible_output=compatible_output)
            if conf.config.getboolean("Reports", "outputTimesForSections"):
                timer.take_sample()
        return self._spikes

    def get_spike_counts(self, gather=True):
        """
        Returns the number of spikes for each neuron.
        """
        raise NotImplementedError

    # noinspection PyUnusedLocal
    def get_gsyn(self, gather=True, compatible_output=False):
        """
        Return a 3-column numpy array containing cell ids and synaptic
        conductances for recorded cells.

        """
        if self._gsyn is None:
            if not self._vertex.record_gsyn:
                raise exceptions.ConfigurationException(
                    "This population has not been set to record gsyn. "
                    "Therefore gsyn cannot be retrieved. Please set this "
                    "vertex to record gsyn before running this command.")

            if not self._spinnaker.has_ran:
                raise local_exceptions.SpynnakerException(
                    "The simulation has not yet run, therefore gsyn cannot"
                    " be retrieved. Please execute the simulation before"
                    " running this command")
            timer = None
            if conf.config.getboolean("Reports", "outputTimesForSections"):
                timer = Timer()
                timer.start_timing()
            self._gsyn = self._vertex.get_gsyn(
                has_ran=self._spinnaker.has_ran,
                txrx=self._spinnaker.transceiver,
                placements=self._spinnaker.placements,
                machine_time_step=self._spinnaker.machine_time_step,
                graph_mapper=self._spinnaker.graph_mapper,
                compatible_output=compatible_output,
                runtime=self._spinnaker._runtime)
            if conf.config.getboolean("Reports", "outputTimesForSections"):
                timer.take_sample()
        return self._gsyn

    # noinspection PyUnusedLocal
    def get_v(self, gather=True, compatible_output=False):
        """
        Return a 3-column numpy array containing cell ids, time, and Vm for
        recorded cells.

        :param gather:
            not used - inserted to match PyNN specs
        :type gather: bool
        :param compatible_output:
            not used - inserted to match PyNN specs
        :type compatible_output: bool
        """
        if self._v is None:
            if not self._vertex.record_v:
                raise exceptions.ConfigurationException(
                    "This population has not been set to record v. "
                    "Therefore v cannot be retrieved. Please set this "
                    "vertex to record v before running this command.")

            if not self._spinnaker.has_ran:
                raise local_exceptions.SpynnakerException(
                    "The simulation has not yet run, therefore v cannot"
                    " be retrieved. Please execute the simulation before"
                    " running this command")

            timer = None
            if conf.config.getboolean("Reports", "outputTimesForSections"):
                timer = Timer()
                timer.start_timing()
            self._v = self._vertex.get_v(
                has_ran=self._spinnaker.has_ran,
                txrx=self._spinnaker.transceiver,
                placements=self._spinnaker.placements,
                machine_time_step=self._spinnaker.machine_time_step,
                graph_mapper=self._spinnaker.graph_mapper,
                compatible_output=compatible_output,
                runtime=self._spinnaker._runtime)

            if conf.config.getboolean("Reports", "outputTimesForSections"):
                timer.take_sample()

        return self._v

    def id_to_index(self, cell_id):
        """
        Given the ID(s) of cell(s) in the Population, return its (their) index
        (order in the Population).
        """
        raise NotImplementedError

    def id_to_local_index(self, cell_id):
        """
        Given the ID(s) of cell(s) in the Population, return its (their) index
        (order in the Population), counting only cells on the local MPI node.
        """
        raise NotImplementedError

    def initialize(self, variable, value):
        """
        Set the initial value of one of the state variables of the neurons in
        this population.

        """
        initialize_attr = \
            getattr(self._vertex, "initialize_%s" % variable, None)
        if initialize_attr is None or not callable(initialize_attr):
            raise Exception(
                "Vertex does not support "
                "initialization of parameter {%s}".format(variable))

        initialize_attr(value)

    def is_local(self, cell_id):
        """
        Determine whether the cell with the given ID exists on the local
        MPI node.
        """
        raise NotImplementedError

    def can_record(self, variable):
        """ Determine whether `variable` can be recorded from this population.
        """
        raise NotImplementedError

    def inject(self, current_source):
        """
        Connect a current source to all cells in the Population.
        """
        raise NotImplementedError

    def __iter__(self):
        """
        suppose to iterate over local cells
        """
        raise NotImplementedError

    def __len__(self):
        """
        Returns the total number of cells in the population.
        """
        return self._size

    @property
    def label(self):
        return self._vertex.label

    @property
    def local_size(self):
        """
        returns the number of local cells ???
        """
        raise NotImplementedError

    def mean_spike_count(self, gather=True):
        """
        Returns the mean number of spikes per neuron.
        """
        raise NotImplementedError

    def nearest(self, position):
        """
        return the neuron closest to the specified position.
        Added functionality 23 November 2014 ADR
        """
        if self._structure is None:
            raise ValueError("attempted to retrieve positions "
                             "for an un-structured population")
        elif self._positions is None:
            self._structure.generate_positions(self._vertex.n_atoms)
        position_diff = numpy.empty(self._positions.shape)
        position_diff.fill(position)
        distances = Space.distances(self._positions, position_diff)
        return distances.argmin()

    @property
    def position_generator(self):
        """
        returns a position generator. Added functionality 27 November 2014 ADR
        """
        if self._structure is None:
            raise ValueError("attempted to retrieve positions "
                             "for an un-structured population")
        else:
            return self._structure.generate_positions

    # noinspection PyPep8Naming
    def randomInit(self, distribution):
        """
        Set initial membrane potentials for all the cells in the population to
        random values.

        :param `pyNN.random.RandomDistribution` distribution:
            the distribution used to draw random values.

        """
        self.initialize('v', distribution)

    def record(self, to_file=None):
        """
        Record spikes from all cells in the Population.
        A flag is set for this population that is passed to the simulation,
        triggering spike time recording.
        """

        if not isinstance(self._vertex, AbstractPopulationRecordableVertex):
            raise Exception("This population does not support recording!")

        # Tell the vertex to record spikes
        self._vertex.set_record(True)

        # set the file to store the spikes in once retrieved
        self._record_spike_file = to_file

    def record_gsyn(self, to_file=None):
        """
        Record the synaptic conductance for all cells in the Population.
        A flag is set for this population that is passed to the simulation,
        triggering gsyn value recording.
        """
        if not isinstance(self._vertex, AbstractPopulationRecordableVertex):
            raise Exception("Vertex does not support " "recording of gsyn")

        self._vertex.set_record_gsyn(True)
        self._record_gsyn_file = to_file

    def record_v(self, to_file=None):
        """
        Record the membrane potential for all cells in the Population.
        A flag is set for this population that is passed to the simulation,
        triggering potential recording.
        """
        if not isinstance(self._vertex, AbstractPopulationRecordableVertex):
            raise Exception("Vertex does not support "
                            "recording of potential")

        self._vertex.set_record_v(True)
        self._record_v_file = to_file

    @property
    def positions(self):
        """
        Returns the position array for structured populations.
        Added functionality 27 November 2014 ADR
        """
        if self._structure is None:
            raise ValueError("attempted to retrieve positions "
                             "for an un-structured population")
        elif self._positions is None:
            self._positions = self._structure.generate_positions(
                self._vertex.n_atoms)
        return self._positions

    # noinspection PyPep8Naming
    def printSpikes(self, filename, gather=True):
        """ Write spike time information from the population to a given file.
        :param filename: the absoluete file path for where the spikes are to\
                    be printed in
        :param gather: Supported from the PyNN language, but ignored here
        """
        if not gather:
            logger.warn("Spynnaker only supports gather = true, will execute"
                        " as if gather was true anyhow")
        spikes = self.getSpikes(compatible_output=True)
        if spikes is not None:
            first_id = 0
            num_neurons = self._vertex.n_atoms
            dimensions = self._vertex.n_atoms
            last_id = self._vertex.n_atoms - 1
            utility_calls.check_directory_exists_and_create_if_not(filename)
            spike_file = open(filename, "w")
            spike_file.write("# first_id = {}\n".format(first_id))
            spike_file.write("# n = {}\n".format(num_neurons))
            spike_file.write("# dimensions = [{}]\n".format(dimensions))
            spike_file.write("# last_id = {}\n".format(last_id))
            for (neuronId, time) in spikes:
                spike_file.write("{}\t{}\n".format(time, neuronId))
            spike_file.close()

    def print_gsyn(self, filename, gather=True):
        """ Write conductance information from the population to a given file.
        :param filename: the absoluete file path for where the gsyn are to be\
                    printed in
        :param gather: Supported from the PyNN language, but ignored here
        """
        time_step = (self._spinnaker.machine_time_step * 1.0) / 1000.0
        gsyn = self.get_gsyn(gather, compatible_output=True)
        first_id = 0
        num_neurons = self._vertex.n_atoms
        dimensions = self._vertex.n_atoms
        utility_calls.check_directory_exists_and_create_if_not(filename)
        file_handle = open(filename, "w")
        file_handle.write("# first_id = {}\n".format(first_id))
        file_handle.write("# n = {}\n".format(num_neurons))
        file_handle.write("# dt = {}\n".format(time_step))
        file_handle.write("# dimensions = [{}]\n".format(dimensions))
        file_handle.write("# last_id = {{}}\n".format(num_neurons - 1))
        file_handle = open(filename, "w")
        for (neuronId, time, value) in gsyn:
            file_handle.write("{}\t{}\t{}\n".format(time, neuronId, value))
        file_handle.close()

    def print_v(self, filename, gather=True):
        """ Write membrane potential information from the population to a\
            given file.
        :param filename: the absolute file path for where the voltage are to\
                     be printed in
        :param gather: Supported from the PyNN language, but ignored here
        """
        time_step = (self._spinnaker.machine_time_step * 1.0) / 1000.0
        v = self.get_v(gather, compatible_output=True)
        utility_calls.check_directory_exists_and_create_if_not(filename)
        file_handle = open(filename, "w")
        first_id = 0
        num_neurons = self._vertex.n_atoms
        dimensions = self._vertex.n_atoms
        file_handle.write("# first_id = {}\n".format(first_id))
        file_handle.write("# n = {}\n".format(num_neurons))
        file_handle.write("# dt = {}\n".format(time_step))
        file_handle.write("# dimensions = [{}]\n".format(dimensions))
        file_handle.write("# last_id = {}\n".format(num_neurons - 1))
        for (neuronId, time, value) in v:
            file_handle.write("{}\t{}\t{}\n".format(time, neuronId, value))
        file_handle.close()

    def rset(self, parametername, rand_distr):
        """
        'Random' set. Set the value of parametername to a value taken from
        rand_distr, which should be a RandomDistribution object.
        :param parametername: the paramter to set
        :param rand_distr: the random distrubtion object to set the paramter to
        """
        raise NotImplementedError

    def sample(self, n, rng=None):
        """
        returns a random selection fo neurons from a population in the form
        of a population view
        """
        raise NotImplementedError

    def save_positions(self, file_name):
        """
        save positions to file. Added functionality 23 November 2014 ADR
        """
        if self._structure is None:
            raise ValueError("attempted to retrieve positions "
                             "for an un-structured population")
        elif self._positions is None:
            self._structure.generate_positions(self._vertex.n_atoms)
        file_handle = open(file_name, "w")
        file_handle.write(self._positions)
        file_handle.close()

    def _set_cell_initial_value(self, cell_id, variable, value):
        """
        set a given cells intial value
        """
        raise NotImplementedError

    def _set_cell_position(self, cell_id, pos):
        """
        sets a cell to a given position
        """
        if self._structure is None:
            raise ValueError("attempted to set a position for a cell "
                             "in an un-structured population")
        elif self._positions is None:
            self._structure.generate_positions(self._vertex.n_atoms)
        self._positions[cell_id] = pos

    def _set_positions(self, positions):
        """
        sets all the positions in the population.
        """
        if self._structure is None:
            raise ValueError("attempted to set positions "
                             "in an un-structured population")
        else:
            self._positions = positions

    def set(self, parameter, value=None):
        """
        Set one or more parameters for every cell in the population.

        param can be a dict, in which case val should not be supplied, or a
        string giving the parameter name, in which case val is the parameter
        value. val can be a numeric value, or list of such
        (e.g. for setting spike times)::

          p.set("tau_m", 20.0).
          p.set({'tau_m':20, 'v_rest':-65})
        """
        if type(parameter) is str:
            if value is None:
                raise Exception("Error: No value given in set() function for "
                                "population parameter. Exiting.")
            self._parameters[parameter] = value
            return
        if type(parameter) is not dict:
            raise Exception("Error: invalid parameter type for "
                            "set() function for population parameter."
                            " Exiting.")
        # Add a dictionary-structured set of new parameters to the current set:
        self._parameters.update(parameter)

    @property
    def structure(self):
        """
        Returns the structure for the population. Added 23 November 2014 ADR
        """
        return self._structure

    # NONE PYNN API CALL
    def set_constraint(self, constraint):
        """
        Apply a constraint to a population that restricts the processor
        onto which its sub-populations will be placed.
        """
        if isinstance(constraint, AbstractConstraint):
            self._vertex.add_constraint(constraint)
        else:
            raise exceptions.ConfigurationException(
                "the constraint entered is not a recongised constraint. "
                "try again")

    # NONE PYNN API CALL
    def add_placement_constraint(self, x, y, p=None):
        """ Add a placement constraint

        :param x: The x-coordinate of the placement constraint
        :type x: int
        :param y: The y-coordinate of the placement constraint
        :type y: int
        :param p: The processor id of the placement constraint (optional)
        :type p: int
        """
        self._vertex.add_constraint(PlacerChipAndCoreConstraint(x, y, p))

    # NONE PYNN API CALL
    def set_mapping_constraint(self, constraint_dict):
        """ Add a placement constraint - for backwards compatibility

        :param constraint_dict: A dictionary containing "x", "y" and\
                    optionally "p" as keys, and ints as values
        :type constraint_dict: dict of str->int
        """
        self.add_placement_constraint(**constraint_dict)

    # NONE PYNN API CALL
    def set_model_based_max_atoms_per_core(self, new_value):
        if hasattr(self._vertex, "set_model_max_atoms_per_core"):
            self._vertex.set_model_max_atoms_per_core(new_value)
        else:
            raise exceptions.ConfigurationException(
                "This population does not support its max_atoms_per_core "
                "variable being adjusted by the end user. Sorry")

    @property
    def size(self):
        return self._vertex.n_atoms

    def tset(self, parametername, value_array):
        """
        'Topographic' set. Set the value of parametername to the values in
        value_array, which must have the same dimensions as the Population.
        """
        raise NotImplementedError

    def _end(self):
        """ Do final steps at the end of the simulation
        """
        if self._record_spike_file is not None:
            self.printSpikes(self._record_spike_file)
        if self._record_v_file is not None:
            self.print_v(self._record_v_file)
        if self._record_gsyn_file is not None:
            self.print_gsyn(self._record_gsyn_file)

    @property
    def _get_vertex(self):
        return self._vertex

    @property
    def _internal_delay_vertex(self):
        return self._delay_vertex

    @_internal_delay_vertex.setter
    def _internal_delay_vertex(self, delay_vertex):
        self._delay_vertex = delay_vertex