From 79d1d5a850896fbb3d922203bba04bb25c9f237e Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 26 Jul 2021 09:45:02 +0100 Subject: [PATCH 1/3] Fix array_connector max calculations --- .../connectors/abstract_connector.py | 4 +-- .../connectors/array_connector.py | 28 +++++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py index ac98ae13e6..1455973a5f 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/abstract_connector.py @@ -278,7 +278,7 @@ def _get_n_connections_from_pre_vertex_with_delay_maximum( def get_n_connections_from_pre_vertex_maximum( self, post_vertex_slice, synapse_info, min_delay=None, max_delay=None): - """ Get the maximum number of connections between those from any + """ Get the maximum number of connections from any neuron in the pre vertex to the neurons in the post_vertex_slice, for connections with a delay between min_delay and max_delay (inclusive) if both specified (otherwise all connections). @@ -297,7 +297,7 @@ def get_n_connections_from_pre_vertex_maximum( @abstractmethod def get_n_connections_to_post_vertex_maximum(self, synapse_info): - """ Get the maximum number of connections between those to any neuron + """ Get the maximum number of connections to any neuron in the post vertex from neurons in the pre vertex. :param SynapseInformation synapse_info: diff --git a/spynnaker/pyNN/models/neural_projections/connectors/array_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/array_connector.py index 854e93e602..5d3a2b1826 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/array_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/array_connector.py @@ -74,24 +74,40 @@ def get_delay_minimum(self, synapse_info): def get_n_connections_from_pre_vertex_maximum( self, post_vertex_slice, synapse_info, min_delay=None, max_delay=None): - n_connections = 0 + max_connections_row = 0 post_lo = post_vertex_slice.lo_atom post_hi = post_vertex_slice.hi_atom + # Max number per row is required for i in range(self.__array_dims[0]): + n_connections_row = 0 for j in range(post_lo, post_hi+1): if self.__array[i, j] == 1: - n_connections += 1 + n_connections_row += 1 + + if n_connections_row > max_connections_row: + max_connections_row = n_connections_row if min_delay is None and max_delay is None: - return n_connections + return max_connections_row return self._get_n_connections_from_pre_vertex_with_delay_maximum( - synapse_info.delays, self.__n_total_connections, n_connections, - min_delay, max_delay, synapse_info) + synapse_info.delays, self.__n_total_connections, + max_connections_row, min_delay, max_delay, synapse_info) @overrides(AbstractConnector.get_n_connections_to_post_vertex_maximum) def get_n_connections_to_post_vertex_maximum(self, synapse_info): - return self.__n_total_connections + # Max number per column is required + max_connections_col = 0 + for j in range(self.__array_dims[1]): + n_connections_col = 0 + for i in range(self.__array_dims[0]): + if self.__array[i, j] == 1: + n_connections_col = 0 + + if n_connections_col > max_connections_col: + max_connections_col = n_connections_col + + return max_connections_col @overrides(AbstractConnector.get_weight_maximum) def get_weight_maximum(self, synapse_info): From d22c5cf49b657546fa7ef3c3055617624f09ced7 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Tue, 27 Jul 2021 12:39:25 +0100 Subject: [PATCH 2/3] Add a test for a larger array in the ArrayConnector --- .../test_array_connector.py | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/spynnaker_integration_tests/test_array_connector/test_array_connector.py b/spynnaker_integration_tests/test_array_connector/test_array_connector.py index d95d81df7c..52563edf5d 100644 --- a/spynnaker_integration_tests/test_array_connector/test_array_connector.py +++ b/spynnaker_integration_tests/test_array_connector/test_array_connector.py @@ -119,6 +119,61 @@ def do_run(plot): return v, spikes, v2, spikes2 +def do_larger_array(plot): + p.setup(timestep=1.0) + + n_i = 64 + n_e = 64 + + spikeArray = {'spike_times': [0]} + input_pop = p.Population(n_e, p.SpikeSourceArray(**spikeArray), + label='inputSpikes') + excit_pop = p.Population(n_e, p.IF_curr_exp, label='excit') + inhit_pop = p.Population(n_i, p.IF_curr_exp, label='inhib') + input_projec = p.Projection(input_pop, excit_pop, p.AllToAllConnector(), + synapse_type=p.StaticSynapse(weight=5), + receptor_type='excitatory') + + ie_conn = numpy.ones((n_i, n_e)) + for i in range(n_e): + ie_conn[i, i] = 0 + + ei_projec = p.Projection(excit_pop, inhit_pop, p.OneToOneConnector(), + synapse_type=p.StaticSynapse(weight=2), + receptor_type='inhibitory') + + ie_projec = p.Projection(inhit_pop, excit_pop, p.ArrayConnector(ie_conn), + synapse_type=p.StaticSynapse(weight=3), + receptor_type='excitatory') + + excit_pop.record(["spikes", "v"]) + + runtime = 1000 + p.run(runtime) + + ie_conns = ie_projec.get(['weight', 'delay'], 'list') + v = excit_pop.get_data("v") + spikes = excit_pop.get_data("spikes") + + if plot: + Figure( + # raster plot of the presynaptic neurons' spike times + Panel(spikes.segments[0].spiketrains, + yticks=True, markersize=1.2, xlim=(0, runtime), xticks=True), + # membrane potential of the postsynaptic neurons + Panel(v.segments[0].filter(name='v')[0], + ylabel="Membrane potential (mV)", + data_labels=[inhit_pop.label], yticks=True, + xlim=(0, runtime), xticks=True), + title="Testing ArrayConnector", + annotations="Simulated with {}".format(p.name()) + ) + plt.show() + + p.end() + + return v, spikes, ie_conns + class ArrayConnectorTest(BaseTestCase): @@ -133,6 +188,17 @@ def a_run(self): def test_a_run(self): self.runsafe(self.a_run) + def larger_array(self): + v, spikes, conns = do_larger_array(plot=False) + # checks go here + spikes_test = neo_convertor.convert_spikes(spikes) + self.assertEqual(4032, len(conns)) + self.assertEqual(640, len(spikes_test)) + + def test_larger_array(self): + self.runsafe(self.larger_array) + if __name__ == '__main__': v, spikes, v2, spikes2 = do_run(plot=True) + v, spikes, conns = do_larger_array(plot=True) From 5e03837903e9f72b0cc8ef5652ee52b0fa22cdcf Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Tue, 27 Jul 2021 12:42:58 +0100 Subject: [PATCH 3/3] flake8 --- .../test_array_connector/test_array_connector.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/spynnaker_integration_tests/test_array_connector/test_array_connector.py b/spynnaker_integration_tests/test_array_connector/test_array_connector.py index 52563edf5d..1115b520e9 100644 --- a/spynnaker_integration_tests/test_array_connector/test_array_connector.py +++ b/spynnaker_integration_tests/test_array_connector/test_array_connector.py @@ -119,6 +119,7 @@ def do_run(plot): return v, spikes, v2, spikes2 + def do_larger_array(plot): p.setup(timestep=1.0) @@ -127,20 +128,20 @@ def do_larger_array(plot): spikeArray = {'spike_times': [0]} input_pop = p.Population(n_e, p.SpikeSourceArray(**spikeArray), - label='inputSpikes') + label='inputSpikes') excit_pop = p.Population(n_e, p.IF_curr_exp, label='excit') inhit_pop = p.Population(n_i, p.IF_curr_exp, label='inhib') - input_projec = p.Projection(input_pop, excit_pop, p.AllToAllConnector(), - synapse_type=p.StaticSynapse(weight=5), - receptor_type='excitatory') + p.Projection(input_pop, excit_pop, p.AllToAllConnector(), + synapse_type=p.StaticSynapse(weight=5), + receptor_type='excitatory') ie_conn = numpy.ones((n_i, n_e)) for i in range(n_e): ie_conn[i, i] = 0 - ei_projec = p.Projection(excit_pop, inhit_pop, p.OneToOneConnector(), - synapse_type=p.StaticSynapse(weight=2), - receptor_type='inhibitory') + p.Projection(excit_pop, inhit_pop, p.OneToOneConnector(), + synapse_type=p.StaticSynapse(weight=2), + receptor_type='inhibitory') ie_projec = p.Projection(inhit_pop, excit_pop, p.ArrayConnector(ie_conn), synapse_type=p.StaticSynapse(weight=3),