Skip to content

Commit 3ad05f3

Browse files
author
Andrew Davison
authored
Merge pull request #624 from apdavison/issue622
Fix for #622
2 parents 5b77d9e + f96be63 commit 3ad05f3

4 files changed

Lines changed: 58 additions & 7 deletions

File tree

pyNN/brian/projections.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from pyNN import common
1212
from pyNN.standardmodels.synapses import TsodyksMarkramSynapse
1313
from pyNN.core import is_listlike
14+
from .populations import PopulationView
1415
from pyNN.parameters import ParameterSpace
1516
from pyNN.space import Space
1617
from . import simulator
@@ -139,7 +140,7 @@ def _partition(self, indices):
139140
else:
140141
partitions = [indices]
141142
return partitions
142-
143+
143144
def _localize_index(self, index):
144145
"""determine which group the postsynaptic index belongs to """
145146
if isinstance(self.post, common.Assembly):
@@ -192,7 +193,7 @@ def _set_attributes(self, connection_parameters):
192193
value = value.T
193194
filtered_value = value[syn_obj.postsynaptic, syn_obj.presynaptic]
194195
setattr(syn_obj, name, filtered_value)
195-
196+
196197
def _get_attributes_as_arrays(self, attribute_names, multiple_synapses='sum'):
197198
if isinstance(self.post, common.Assembly) or isinstance(self.pre, common.Assembly):
198199
raise NotImplementedError
@@ -215,8 +216,12 @@ def _get_attributes_as_list(self, attribute_names):
215216
for name in attribute_names:
216217
if name == "presynaptic_index":
217218
value = self._brian_synapses[0][0].presynaptic
219+
if isinstance(self.pre, PopulationView):
220+
value = self.pre.id_to_index(value)
218221
elif name == "postsynaptic_index":
219222
value = self._brian_synapses[0][0].postsynaptic
223+
if isinstance(self.post, PopulationView):
224+
value = self.post.id_to_index(value)
220225
else:
221226
data_obj = getattr(self._brian_synapses[0][0], name).data
222227
if hasattr(data_obj, "tolist"):

pyNN/common/populations.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,25 @@ def index_in_grandparent(self, indices):
923923
else:
924924
return indices_in_parent
925925

926+
def __eq__(self, other):
927+
"""
928+
Determine whether two views are the same.
929+
"""
930+
return not self.__ne__(other)
931+
932+
def __ne__(self, other):
933+
"""
934+
Determine whether two views are different.
935+
"""
936+
# We can't use the self.mask, as different masks can select the same cells
937+
# (e.g. slices vs arrays), therefore we have to use self.all_cells
938+
if isinstance(other, PopulationView):
939+
return self.parent != other.parent or not numpy.array_equal(self.all_cells, other.all_cells)
940+
elif isinstance(other, Population):
941+
return self.parent != other or not numpy.array_equal(self.all_cells, other.all_cells)
942+
else:
943+
return True
944+
926945
def describe(self, template='populationview_default.txt', engine='default'):
927946
"""
928947
Returns a human-readable description of the population view.

pyNN/connectors.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ def _standard_connect(self, projection, connection_map_generator, distance_map=N
191191
# `source_mask` - boolean numpy array, indicating which of the pre-synaptic neurons should be connected to,
192192
# or a single boolean, meaning connect to all/none of the pre-synaptic neurons
193193
# It can also be an array of addresses
194-
_proceed = False
194+
_proceed = False
195195
if source_mask is True or source_mask.any():
196196
_proceed = True
197197
elif type(source_mask) == numpy.ndarray:
@@ -206,7 +206,7 @@ def _standard_connect(self, projection, connection_map_generator, distance_map=N
206206
source_mask = numpy.arange(projection.pre.size, dtype=int)
207207
elif source_mask.dtype == bool:
208208
source_mask = source_mask.nonzero()[0]
209-
209+
210210
# Evaluate the lazy arrays containing the synaptic parameters
211211
connection_parameters = {}
212212
for name, map in parameter_space.items():
@@ -275,6 +275,10 @@ def __init__(self, allow_self_connections=True, safe=True,
275275
def connect(self, projection):
276276
if not self.allow_self_connections and projection.pre == projection.post:
277277
connection_map = LazyArray(lambda i, j: i != j, shape=projection.shape)
278+
# there is a more complicated scenario, where we connect two different
279+
# views of the same population. In this case, something other than i != j
280+
# will be needed. It should at least be documented that we currently
281+
# don't handle this situation.
278282
elif self.allow_self_connections == 'NoMutual' and projection.pre == projection.post:
279283
connection_map = LazyArray(lambda i, j: i > j, shape=projection.shape)
280284
else:
@@ -559,7 +563,7 @@ class FromFileConnector(FromListConnector):
559563
560564
# columns = ["i", "j", "weight", "delay", "U", "tau_rec"]
561565
562-
Note that the header requires `#` at the beginning of the line.
566+
Note that the header requires `#` at the beginning of the line.
563567
564568
`distributed`:
565569
if this is True, then each node will read connections from a file
@@ -1015,7 +1019,7 @@ def connect(self, projection):
10151019

10161020
# Assume that targets are equally distributed over processes
10171021
targets_per_process = int(len(projection.post) / num_processes)
1018-
1022+
10191023
# Calculate the number of synapses on each process
10201024
bino = RandomDistribution('binomial',
10211025
[self.n, targets_per_process / len(projection.post)],
@@ -1031,7 +1035,7 @@ def connect(self, projection):
10311035
sum_dist += targets_per_process
10321036
sum_partitions += num_conns_on_vp[k]
10331037

1034-
# Draw random sources and targets
1038+
# Draw random sources and targets
10351039
connections = [[] for i in range(projection.post.size)]
10361040
possible_targets = numpy.arange(projection.post.size)[projection.post._mask_local]
10371041
for i in range(num_conns_on_vp[rank]):

test/system/scenarios/test_connectors.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,29 @@ def issue309(sim):
201201
sim.end()
202202

203203

204+
@register()
205+
def issue622(sim):
206+
sim.setup()
207+
pop = sim.Population(10, sim.IF_cond_exp, {}, label="pop")
208+
209+
view1 = sim.PopulationView(pop, [2,3,4])
210+
view2 = sim.PopulationView(pop, [2,3,4])
211+
212+
proj1 = sim.Projection(view1, view2, sim.AllToAllConnector(allow_self_connections = False), sim.StaticSynapse(
213+
weight=0.015, delay=1.0), receptor_type='excitatory')
214+
proj2 = sim.Projection(view1, view1, sim.AllToAllConnector(allow_self_connections = False), sim.StaticSynapse(
215+
weight=0.015, delay=1.0), receptor_type='excitatory')
216+
217+
218+
w1 = proj1.get("weight", "list")
219+
w2 = proj2.get("weight", "list")
220+
221+
assert_equal(w1, w2)
222+
assert_equal(sorted(w1),
223+
sorted([(0.0, 1.0, 0.015), (0.0, 2.0, 0.015), (1.0, 0.0, 0.015),
224+
(1.0, 2.0, 0.015), (2.0, 0.0, 0.015), (2.0, 1.0, 0.015)]))
225+
226+
204227
if __name__ == '__main__':
205228
from pyNN.utility import get_simulator
206229
sim, args = get_simulator()

0 commit comments

Comments
 (0)