From b7e71abc59dfa760b7ebda185ab1d95c5eb9d8c3 Mon Sep 17 00:00:00 2001 From: Andrew Rowley Date: Fri, 16 Nov 2018 11:32:07 +0000 Subject: [PATCH 1/6] Fix labels and add report --- spynnaker/pyNN/abstract_spinnaker_common.py | 22 ++++++++++++++++++- .../pyNN/models/pynn_population_common.py | 20 ++++++++++------- .../pyNN/models/pynn_projection_common.py | 10 +++++++-- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index cac088251ab..e7bfb368fcf 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -21,6 +21,7 @@ # general imports from six import add_metaclass +from collections import defaultdict import logging import math import os @@ -303,13 +304,32 @@ def stop(self, turn_off_machine=None, clear_routing_tables=None, self.reset_number_of_neurons_per_core() globals_variables.unset_simulator() + def _write_report(self): + incoming_projections = defaultdict(list) + outgoing_projections = defaultdict(list) + for projection in self._projections: + incoming_projections[projection.post_population].append(projection) + outgoing_projections[projection.pre_population].append(projection) + filename = os.path.join( + self._report_default_directory, "pynn_network.txt") + with open(filename, "w") as f: + f.write("*** Populations:\n") + for population in self._populations: + f.write("Population {}, Model {}".format( + population.label, population.cell_type)) + f.write("Outgoing Projections:") + for projection in outgoing_projections[population]: + f.write(" Projection from {}, connector {}".format( + projection.pre_population.label, projection.connector)) + def run(self, run_time): """ Run the model created. :param run_time: the time (in milliseconds) to run the simulation for """ - # pylint: disable=protected-access + self._write_report() + # pylint: disable=protected-access # extra post run algorithms self._dsg_algorithm = "SpynnakerDataSpecificationWriter" for projection in self._projections: diff --git a/spynnaker/pyNN/models/pynn_population_common.py b/spynnaker/pyNN/models/pynn_population_common.py index c75ef53ec8f..6994afc1bc4 100644 --- a/spynnaker/pyNN/models/pynn_population_common.py +++ b/spynnaker/pyNN/models/pynn_population_common.py @@ -52,9 +52,19 @@ def __init__( self, spinnaker_control, size, label, constraints, model, structure, initial_values, additional_parameters=None): # pylint: disable=too-many-arguments - self._label = label size = self._roundsize(size) + self._label = label + if self._label is None: + if isinstance(model, ApplicationVertex): + self._label = model.label + if self._label is None: + self._label = "Population {}".format( + globals_variables.get_simulator() + .none_labelled_vertex_count) + globals_variables.get_simulator()\ + .increment_none_labelled_vertex_count() + # Use a provided model to create a vertex if isinstance(model, AbstractPyNNModel): if size is not None and size <= 0: @@ -64,7 +74,7 @@ def __init__( if additional_parameters is not None: population_parameters.update(additional_parameters) self._vertex = model.create_vertex( - size, label, constraints, **population_parameters) + size, self._label, constraints, **population_parameters) # Use a provided application vertex directly elif isinstance(model, ApplicationVertex): @@ -78,8 +88,6 @@ def __init__( elif size != self._vertex.n_atoms: raise ConfigurationException( "Vertex size does not match Population size") - if label is None: - self._label = self._vertex.label if constraints is not None: self._vertex.add_constraints(constraints) @@ -89,10 +97,6 @@ def __init__( "Model must be either an AbstractPyNNModel or an" " ApplicationVertex") - if self._label is None: - self._label = "Population {}".format( - globals_variables.get_simulator().none_labelled_vertex_count) - # Introspect properties of the vertex self._vertex_population_settable = \ isinstance(self._vertex, AbstractPopulationSettable) diff --git a/spynnaker/pyNN/models/pynn_projection_common.py b/spynnaker/pyNN/models/pynn_projection_common.py index adc667a65ca..eb64d5946d0 100644 --- a/spynnaker/pyNN/models/pynn_projection_common.py +++ b/spynnaker/pyNN/models/pynn_projection_common.py @@ -1,6 +1,7 @@ from pacman.model.constraints.partitioner_constraints \ import SameAtomsAsVertexConstraint -from spinn_front_end_common.utilities import helpful_functions +from spinn_front_end_common.utilities import helpful_functions,\ + globals_variables from spynnaker.pyNN.models.abstract_models \ import AbstractAcceptsIncomingSynapses @@ -46,7 +47,12 @@ def __init__( self._host_based_synapse_list = None self._has_retrieved_synaptic_list_from_machine = False self._requires_mapping = True - self._label = None + self._label = label + if self._label is None: + self._label = "Edge {}".format( + globals_variables.get_simulator().none_labelled_edge_count) + globals_variables.get_simulator().\ + increment_none_labelled_edge_count() if not isinstance(post_synaptic_population._get_vertex, AbstractAcceptsIncomingSynapses): From 7f6ddf90bb04fe1e82c2d5ae421e5494fa454d52 Mon Sep 17 00:00:00 2001 From: Andrew Rowley Date: Fri, 16 Nov 2018 13:29:18 +0000 Subject: [PATCH 2/6] Fix report --- spynnaker/pyNN/abstract_spinnaker_common.py | 28 +++++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index e7bfb368fcf..3c1fb070ed7 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -308,19 +308,31 @@ def _write_report(self): incoming_projections = defaultdict(list) outgoing_projections = defaultdict(list) for projection in self._projections: - incoming_projections[projection.post_population].append(projection) - outgoing_projections[projection.pre_population].append(projection) + connector = projection._synapse_information.connector + incoming_projections[connector._post_population].append(projection) + outgoing_projections[connector._pre_population].append(projection) filename = os.path.join( self._report_default_directory, "pynn_network.txt") with open(filename, "w") as f: f.write("*** Populations:\n") for population in self._populations: - f.write("Population {}, Model {}".format( - population.label, population.cell_type)) - f.write("Outgoing Projections:") - for projection in outgoing_projections[population]: - f.write(" Projection from {}, connector {}".format( - projection.pre_population.label, projection.connector)) + f.write("Population {}, Model {}\n".format( + population.label, population.celltype)) + outgoing = outgoing_projections[population] + f.write(" {} Outgoing Projections:\n".format(len(outgoing))) + for projection in outgoing: + connector = projection._synapse_information.connector + post = connector._post_population + f.write(" Projection to {}, connector {}\n".format( + post.label, str(connector))) + incoming = incoming_projections[population] + f.write(" {} Incoming Projections:\n".format(len(incoming))) + for projection in incoming: + connector = projection._synapse_information.connector + pre = connector._pre_population + f.write(" Projection from {}, connector {}\n" + .format(pre.label, str(connector))) + f.write("\n") def run(self, run_time): """ Run the model created. From f626e8e083b838e3af3b3f2b0faf1109d931c5ce Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Tue, 23 Mar 2021 12:10:38 +0000 Subject: [PATCH 3/6] Population info is in the synapse_information, not the connector --- spynnaker/pyNN/abstract_spinnaker_common.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index 497b42a7fe5..973b97f54de 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -356,9 +356,9 @@ def _write_report(self): incoming_projections = defaultdict(list) outgoing_projections = defaultdict(list) for projection in self._projections: - connector = projection._synapse_information.connector - incoming_projections[connector._post_population].append(projection) - outgoing_projections[connector._pre_population].append(projection) + info = projection._synapse_information + incoming_projections[info.post_population].append(projection) + outgoing_projections[info.pre_population].append(projection) filename = os.path.join( self._report_default_directory, _PYNN_NETWORK_REPORT) From fc273602ef0166aea772957af41dbbd2cb728b7a Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Tue, 23 Mar 2021 12:30:14 +0000 Subject: [PATCH 4/6] Limit number of places where we read non-public properties Add progress bar, "productionize"-code --- spynnaker/pyNN/abstract_spinnaker_common.py | 61 +++++++++++++-------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index 973b97f54de..8b153b4492a 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -33,6 +33,7 @@ SpynnakerSimulatorInterface) from spynnaker.pyNN.utilities.extracted_data import ExtractedData from spynnaker import __version__ as version +from spinn_utilities.progress_bar import ProgressBar logger = FormatAdapter(logging.getLogger(__name__)) _PYNN_NETWORK_REPORT = "pynn_network.txt" @@ -352,35 +353,48 @@ def stop(self, turn_off_machine=None, clear_routing_tables=None, self.reset_number_of_neurons_per_core() unset_simulator(self) - def _write_report(self): - incoming_projections = defaultdict(list) - outgoing_projections = defaultdict(list) - for projection in self._projections: - info = projection._synapse_information - incoming_projections[info.post_population].append(projection) - outgoing_projections[info.pre_population].append(projection) + def __write_population_graph_report(self, filename): + """ Report the pyNN population/projection-level graph. - filename = os.path.join( - self._report_default_directory, _PYNN_NETWORK_REPORT) + :param str filename: What file to write the report to. + :raises IOError: If the file isn't writable. + """ with open(filename, "w") as f: + progress = ProgressBar( + "Describing Final Simulation Graph", + len(self._projections) + len(self._projections)) + + # Invert the relations to pop->proj(info) + incoming_projections = defaultdict(list) + outgoing_projections = defaultdict(list) + for projection in progress.over( + self._projections, finish_at_end=False): + info = projection._synapse_information + incoming_projections[info.post_population].append(info) + outgoing_projections[info.pre_population].append(info) + f.write("*** Populations:\n") - for population in self._populations: + for population in progress.over(self._populations): f.write("Population {}, Model {}\n".format( population.label, population.celltype)) + + # NB: getting a defaulted empty list is fine here outgoing = outgoing_projections[population] - f.write(" {} Outgoing Projections:\n".format(len(outgoing))) - for projection in outgoing: - connector = projection._synapse_information.connector - post = connector._post_population - f.write(" Projection to {}, connector {}\n".format( - post.label, str(connector))) + f.write(" {} Outgoing Projections:\n".format( + len(outgoing))) + for info in outgoing: + f.write( + " Projection to {}, connector {}\n".format( + info.post_population.label, str(info.connector))) + + # NB: getting a defaulted empty list is fine here incoming = incoming_projections[population] - f.write(" {} Incoming Projections:\n".format(len(incoming))) - for projection in incoming: - connector = projection._synapse_information.connector - pre = connector._pre_population - f.write(" Projection from {}, connector {}\n" - .format(pre.label, str(connector))) + f.write(" {} Incoming Projections:\n".format( + len(incoming))) + for info in incoming: + f.write( + " Projection from {}, connector {}\n".format( + info.pre_population.label, str(info.connector))) f.write("\n") def run(self, run_time, sync_time=0.0): @@ -395,7 +409,8 @@ def run(self, run_time, sync_time=0.0): :rtype: None """ # pylint: disable=protected-access - self._write_report() + self.__write_population_graph_report(os.path.join( + self._report_default_directory, _PYNN_NETWORK_REPORT)) # extra post run algorithms self._dsg_algorithm = "SpynnakerDataSpecificationWriter" From 4f7f74332144b3a4da1690b3c8a181999b2580f9 Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Tue, 23 Mar 2021 12:33:05 +0000 Subject: [PATCH 5/6] It would help if I put the arguments the right way round --- spynnaker/pyNN/abstract_spinnaker_common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index 8b153b4492a..d40213d82b3 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -361,8 +361,8 @@ def __write_population_graph_report(self, filename): """ with open(filename, "w") as f: progress = ProgressBar( - "Describing Final Simulation Graph", - len(self._projections) + len(self._projections)) + len(self._projections) + len(self._projections), + "Describing Final Simulation Graph") # Invert the relations to pop->proj(info) incoming_projections = defaultdict(list) From d96fc3a4466761d91d96b47f9b5102c67f9ccbf3 Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Tue, 23 Mar 2021 12:44:49 +0000 Subject: [PATCH 6/6] Put import in order I prefer --- spynnaker/pyNN/abstract_spinnaker_common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py index d40213d82b3..c5476127063 100644 --- a/spynnaker/pyNN/abstract_spinnaker_common.py +++ b/spynnaker/pyNN/abstract_spinnaker_common.py @@ -19,6 +19,7 @@ import os from spinn_utilities.abstract_base import AbstractBase from spinn_utilities.log import FormatAdapter +from spinn_utilities.progress_bar import ProgressBar from spinn_front_end_common.interface.abstract_spinnaker_base import ( AbstractSpinnakerBase) from spinn_front_end_common.utilities.constants import ( @@ -33,7 +34,6 @@ SpynnakerSimulatorInterface) from spynnaker.pyNN.utilities.extracted_data import ExtractedData from spynnaker import __version__ as version -from spinn_utilities.progress_bar import ProgressBar logger = FormatAdapter(logging.getLogger(__name__)) _PYNN_NETWORK_REPORT = "pynn_network.txt"