1""" 2Tests of the Connector classes, using the pyNN.mock backend. 3 4:copyright: Copyright 2006-2021 by the PyNN team, see AUTHORS. 5:license: CeCILL, see LICENSE for details. 6""" 7 8import unittest 9 10from pyNN import connectors, random, errors, space, recording 11import numpy as np 12import os 13import sys 14from numpy.testing import assert_array_equal, assert_array_almost_equal 15from .mocks import MockRNG, MockRNG2 16import pyNN.mock as sim 17 18 19orig_mpi_get_config = random.get_mpi_config 20 21 22def setUp(): 23 random.get_mpi_config = lambda: (0, 2) 24 25 26def tearDown(): 27 random.get_mpi_config = orig_mpi_get_config 28 29 30class TestOneToOneConnector(unittest.TestCase): 31 32 def setUp(self, sim=sim, **extra): 33 sim.setup(num_processes=2, rank=0, **extra) 34 self.p1 = sim.Population(5, sim.IF_cond_exp()) 35 self.p2 = sim.Population(5, sim.HH_cond_exp()) 36 assert_array_equal(self.p2._mask_local, np.array([0, 1, 0, 1, 0], dtype=bool)) 37 38 def tearDown(self, sim=sim): 39 sim.end() 40 41 def test_connect_with_scalar_weights_and_delays(self, sim=sim): 42 C = connectors.OneToOneConnector(safe=False) 43 syn = sim.StaticSynapse(weight=5.0, delay=0.5) 44 prj = sim.Projection(self.p1, self.p2, C, syn) 45 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 46 [(1, 1, 5.0, 0.5), 47 (3, 3, 5.0, 0.5)]) 48 49 def test_connect_with_random_weights(self, sim=sim): 50 rd = random.RandomDistribution('uniform', (0, 1), rng=MockRNG(delta=1.0)) 51 syn = sim.StaticSynapse(weight=rd, delay=0.5) 52 C = connectors.OneToOneConnector(safe=False) 53 prj = sim.Projection(self.p1, self.p2, C, syn) 54 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 55 [(1, 1, 1.0, 0.5), 56 (3, 3, 3.0, 0.5)]) 57 58 59class TestAllToAllConnector(unittest.TestCase): 60 61 def setUp(self, sim=sim, **extra): 62 sim.setup(num_processes=2, rank=1, min_delay=0.123, **extra) 63 self.p1 = sim.Population(4, sim.IF_cond_exp(), structure=space.Line()) 64 self.p2 = sim.Population(5, sim.HH_cond_exp(), structure=space.Line()) 65 assert_array_equal(self.p1._mask_local, np.array([0, 1, 0, 1], dtype=bool)) 66 assert_array_equal(self.p2._mask_local, np.array([0, 1, 0, 1, 0], dtype=bool)) 67 68 def test_connect_with_scalar_weights_and_delays(self, sim=sim): 69 C = connectors.AllToAllConnector(safe=False) 70 syn = sim.StaticSynapse(weight=5.0, delay=0.5) 71 prj = sim.Projection(self.p1, self.p2, C, syn) 72 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 73 [(0, 1, 5.0, 0.5), 74 (1, 1, 5.0, 0.5), 75 (2, 1, 5.0, 0.5), 76 (3, 1, 5.0, 0.5), 77 (0, 3, 5.0, 0.5), 78 (1, 3, 5.0, 0.5), 79 (2, 3, 5.0, 0.5), 80 (3, 3, 5.0, 0.5)]) 81 nan = np.nan 82 assert_array_equal(prj.get('weight', format='array', gather=False), 83 np.array([[nan, 5.0, nan, 5.0, nan], 84 [nan, 5.0, nan, 5.0, nan], 85 [nan, 5.0, nan, 5.0, nan], 86 [nan, 5.0, nan, 5.0, nan]])) 87 88 def test_connect_with_array_weights(self, sim=sim): 89 C = connectors.AllToAllConnector(safe=False) 90 syn = sim.StaticSynapse(weight=np.arange(0.0, 2.0, 0.1).reshape(4, 5), delay=0.5) 91 prj = sim.Projection(self.p1, self.p2, C, syn) 92 assert_array_almost_equal( 93 # use gather False because we are faking the MPI 94 np.array(prj.get(["weight", "delay"], format='list', gather=False)), 95 np.array([(0, 1, 0.1, 0.5), 96 (1, 1, 0.6, 0.5), 97 (2, 1, 1.1, 0.5), 98 (3, 1, 1.6, 0.5), 99 (0, 3, 0.3, 0.5), 100 (1, 3, 0.8, 0.5), 101 (2, 3, 1.3, 0.5), 102 (3, 3, 1.8, 0.5)])) 103 nan = np.nan 104 assert_array_almost_equal(prj.get('weight', format='array', gather=False), 105 np.array([[nan, 0.1, nan, 0.3, nan], 106 [nan, 0.6, nan, 0.8, nan], 107 [nan, 1.1, nan, 1.3, nan], 108 [nan, 1.6, nan, 1.8, nan]]), 109 9) 110 111 def test_connect_with_random_weights_parallel_safe(self, sim=sim): 112 rd = random.RandomDistribution( 113 'uniform', (0, 1), rng=MockRNG(delta=1.0, parallel_safe=True)) 114 syn = sim.StaticSynapse(weight=rd, delay=0.5) 115 C = connectors.AllToAllConnector(safe=False) 116 prj = sim.Projection(self.p1, self.p2, C, syn) 117 # note that the outer loop is over the post-synaptic cells, the inner loop over the pre-synaptic 118 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 119 [(0, 1, 4.0, 0.5), 120 (1, 1, 5.0, 0.5), 121 (2, 1, 6.0, 0.5), 122 (3, 1, 7.0, 0.5), 123 (0, 3, 12.0, 0.5), 124 (1, 3, 13.0, 0.5), 125 (2, 3, 14.0, 0.5), 126 (3, 3, 15.0, 0.5)]) 127 nan = np.nan 128 assert_array_almost_equal(prj.get('weight', format='array', gather=False), 129 np.array([[nan, 4.0, nan, 12.0, nan], 130 [nan, 5.0, nan, 13.0, nan], 131 [nan, 6.0, nan, 14.0, nan], 132 [nan, 7.0, nan, 15.0, nan]]), 133 9) 134 135 def test_connect_with_distance_dependent_weights(self, sim=sim): 136 d_expr = "d+100" 137 syn = sim.StaticSynapse(weight=d_expr, delay=0.5) 138 C = connectors.AllToAllConnector(safe=False) 139 prj = sim.Projection(self.p1, self.p2, C, syn) 140 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 141 [(0, 1, 101.0, 0.5), 142 (1, 1, 100.0, 0.5), 143 (2, 1, 101.0, 0.5), 144 (3, 1, 102.0, 0.5), 145 (0, 3, 103.0, 0.5), 146 (1, 3, 102.0, 0.5), 147 (2, 3, 101.0, 0.5), 148 (3, 3, 100.0, 0.5)]) 149 150 def test_connect_with_distance_dependent_weights_and_delays(self, sim=sim): 151 syn = sim.StaticSynapse(weight="d+100", delay="0.2+2*d") 152 C = connectors.AllToAllConnector(safe=False) 153 prj = sim.Projection(self.p1, self.p2, C, syn) 154 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 155 [(0, 1, 101.0, 2.2), 156 (1, 1, 100.0, 0.2), 157 (2, 1, 101.0, 2.2), 158 (3, 1, 102.0, 4.2), 159 (0, 3, 103.0, 6.2), 160 (1, 3, 102.0, 4.2), 161 (2, 3, 101.0, 2.2), 162 (3, 3, 100.0, 0.2)]) 163 164 def test_connect_with_delays_None(self, sim=sim): 165 syn = sim.StaticSynapse(weight=0.1, delay=None) 166 C = connectors.AllToAllConnector() 167 assert C.safe 168 assert C.allow_self_connections 169 prj = sim.Projection(self.p1, self.p2, C, syn) 170 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False)[ 171 0][3], prj._simulator.state.min_delay) 172 173 @unittest.skip('skipping this test until refactoring of delay checks is complete') 174 def test_connect_with_delays_too_small(self, sim=sim): 175 C = connectors.AllToAllConnector(safe=True) 176 syn = sim.StaticSynapse(weight=0.1, delay=0.0) 177 self.assertRaises(errors.ConnectionError, sim.Projection, self.p1, self.p2, C, syn) 178 179 @unittest.skip('skipping this tests until refactoring of delay checks is complete') 180 def test_connect_with_list_delays_too_small(self, sim=sim): 181 delays = np.ones((self.p1.size, self.p2.size), float) 182 delays[2, 3] = sim.Projection._simulator.state.min_delay - 0.01 183 syn = sim.StaticSynapse(weight=0.1, delay=delays) 184 C = connectors.AllToAllConnector() 185 self.assertRaises(errors.ConnectionError, sim.Projection, self.p1, self.p2, C, syn) 186 187 188class TestFixedProbabilityConnector(unittest.TestCase): 189 190 def setUp(self, sim=sim): 191 sim.setup(num_processes=2, rank=1, min_delay=0.123) 192 self.p1 = sim.Population(4, sim.IF_cond_exp(), structure=space.Line()) 193 self.p2 = sim.Population(5, sim.HH_cond_exp(), structure=space.Line()) 194 assert_array_equal(self.p2._mask_local, np.array([0, 1, 0, 1, 0], dtype=bool)) 195 196 def test_connect_with_default_args(self, sim=sim): 197 C = connectors.FixedProbabilityConnector(p_connect=0.85, 198 rng=MockRNG(delta=0.1, parallel_safe=True)) 199 syn = sim.StaticSynapse() 200 prj = sim.Projection(self.p1, self.p2, C, syn) 201 202 # 20 possible connections. Due to the mock RNG, only the 203 # first 9 are created (0,0), (1,0), (2,0), (3,0), (0,1), (1,1), (2,1), (3,1), (0,2) 204 # of these, (0,1), (1,1), (2,1), (3,1) are created on this node 205 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 206 [(0, 1, 0.0, 0.123), 207 (1, 1, 0.0, 0.123), 208 (2, 1, 0.0, 0.123), 209 (3, 1, 0.0, 0.123)]) 210 211 def test_connect_with_default_args_again(self, sim=sim): 212 C = connectors.FixedProbabilityConnector(p_connect=0.5, 213 rng=MockRNG2(1 - np.array([1, 0, 0, 1, 214 0, 0, 0, 1, 215 1, 1, 0, 0, 216 1, 0, 1, 0, 217 1, 1, 0, 1]), 218 parallel_safe=True)) 219 syn = sim.StaticSynapse() 220 prj = sim.Projection(self.p1, self.p2, C, syn) 221 222 # 20 possible connections. Due to the mock RNG, only the following 223 # are created (0,0), (3,0), (3,1), (0,2), (1,2), (0,3), (2,3), (0,4), (1,4), (3,4) 224 # of these, (3,1), (0,3), (2,3) are created on this node 225 # (note that the outer loop is over post-synaptic cells (columns), the inner loop over pre-synaptic (rows)) 226 nan = np.nan 227 assert_array_almost_equal(prj.get('delay', format='array', gather=False), 228 np.array([[nan, nan, nan, 0.123, nan], 229 [nan, nan, nan, nan, nan], 230 [nan, nan, nan, 0.123, nan], 231 [nan, 0.123, nan, nan, nan]]), 232 9) 233 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 234 [(3, 1, 0.0, 0.123), 235 (0, 3, 0.0, 0.123), 236 (2, 3, 0.0, 0.123)]) 237 238 def test_connect_with_probability_1(self, sim=sim): 239 # see https://github.com/NeuralEnsemble/PyNN/issues/309 240 C = connectors.FixedProbabilityConnector(p_connect=1, 241 rng=MockRNG(delta=0.01, parallel_safe=True)) 242 syn = sim.StaticSynapse() 243 prj = sim.Projection(self.p1, self.p2, C, syn) 244 245 # 20 connections, only some of which are created on this node 246 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 247 [(0, 1, 0.0, 0.123), 248 (1, 1, 0.0, 0.123), 249 (2, 1, 0.0, 0.123), 250 (3, 1, 0.0, 0.123), 251 (0, 3, 0.0, 0.123), 252 (1, 3, 0.0, 0.123), 253 (2, 3, 0.0, 0.123), 254 (3, 3, 0.0, 0.123) 255 ]) 256 257 def test_connect_with_weight_function(self, sim=sim): 258 C = connectors.FixedProbabilityConnector(p_connect=0.85, 259 rng=MockRNG(delta=0.1)) 260 syn = sim.StaticSynapse(weight=lambda d: 0.1 * d) 261 prj = sim.Projection(self.p1, self.p2, C, syn) 262 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 263 [(0, 1, 0.1, 0.123), 264 (1, 1, 0.0, 0.123), 265 (2, 1, 0.1, 0.123), 266 (3, 1, 0.2, 0.123)]) 267 268 def test_connect_with_random_delays_parallel_safe(self, sim=sim): 269 rd = random.RandomDistribution('uniform', low=0.1, high=1.1, 270 rng=MockRNG(start=1.0, delta=0.2, parallel_safe=True)) 271 syn = sim.StaticSynapse(delay=rd) 272 C = connectors.FixedProbabilityConnector(p_connect=0.5, 273 rng=MockRNG2(1 - np.array([1, 0, 0, 1, 274 0, 0, 0, 1, 275 1, 1, 0, 0, 276 1, 0, 1, 0, 277 1, 1, 0, 1]), 278 parallel_safe=True)) 279 prj = sim.Projection(self.p1, self.p2, C, syn) 280 nan = np.nan 281 assert_array_almost_equal(prj.get('delay', format='array', gather=False), 282 np.array([[nan, nan, nan, 2.0, nan], 283 [nan, nan, nan, nan, nan], 284 [nan, nan, nan, 2.2, nan], 285 [nan, 1.4, nan, nan, nan]]), 286 9) 287 288 # def test_connect_with_random_delays_parallel_unsafe(self, sim=sim): 289 # rd = random.RandomDistribution('uniform', [0.1, 1.1], rng=MockRNG(start=1.0, delta=0.2, parallel_safe=False)) 290 # syn = sim.StaticSynapse(delay=rd) 291 # C = connectors.FixedProbabilityConnector(p_connect=0.5, 292 # rng=MockRNG2(1 - np.array([1, 0, 0, 1, 293 # 0, 0, 0, 1, 294 # 1, 1, 0, 0, 295 # 1, 0, 1, 0, 296 # 1, 1, 0, 1]), 297 # parallel_safe=False)) 298 # prj = sim.Projection(self.p1, self.p2, C, syn) 299 # nan = np.nan 300 # assert_array_almost_equal(prj.get('delay', format='array', gather=False), 301 # np.array([[nan, nan, nan, 1.2, nan], 302 # [nan, nan, nan, nan, nan], 303 # [nan, nan, nan, 1.4, nan], 304 # [nan, 1.0, nan, nan, nan]]), 305 # 9) 306 307 308class TestDistanceDependentProbabilityConnector(unittest.TestCase): 309 310 def setUp(self, sim=sim): 311 sim.setup(num_processes=2, rank=1, min_delay=0.123) 312 self.p1 = sim.Population(4, sim.IF_cond_exp(), structure=space.Line()) 313 self.p2 = sim.Population(5, sim.HH_cond_exp(), structure=space.Line()) 314 assert_array_equal(self.p2._mask_local, np.array([0, 1, 0, 1, 0], dtype=bool)) 315 316 def test_connect_with_default_args(self, sim=sim): 317 C = connectors.DistanceDependentProbabilityConnector(d_expression="d<1.5", 318 rng=MockRNG(delta=0.01)) 319 syn = sim.StaticSynapse() 320 prj = sim.Projection(self.p1, self.p2, C, syn) 321 # 20 possible connections. Only those with a sufficiently small distance 322 # are created 323 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 324 [(0, 1, 0.0, 0.123), 325 (1, 1, 0.0, 0.123), 326 (2, 1, 0.0, 0.123), 327 (2, 3, 0.0, 0.123), 328 (3, 3, 0.0, 0.123)]) 329 330 331class TestFromListConnector(unittest.TestCase): 332 333 def setUp(self, sim=sim): 334 sim.setup(num_processes=2, rank=1, min_delay=0.123) 335 self.p1 = sim.Population(4, sim.IF_cond_exp(), structure=space.Line()) 336 self.p2 = sim.Population(5, sim.HH_cond_exp(), structure=space.Line()) 337 assert_array_equal(self.p2._mask_local, np.array([0, 1, 0, 1, 0], dtype=bool)) 338 339 def test_connect_with_valid_list(self, sim=sim): 340 connection_list = [ 341 (0, 0, 0.1, 0.1), 342 (3, 0, 0.2, 0.11), 343 (2, 3, 0.3, 0.12), # local 344 (2, 2, 0.4, 0.13), 345 (0, 1, 0.5, 0.14), # local 346 ] 347 C = connectors.FromListConnector(connection_list) 348 syn = sim.StaticSynapse() 349 prj = sim.Projection(self.p1, self.p2, C, syn) 350 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 351 [(0, 1, 0.5, 0.14), 352 (2, 3, 0.3, 0.12)]) 353 354 def test_connect_with_out_of_range_index(self, sim=sim): 355 connection_list = [ 356 (0, 0, 0.1, 0.1), 357 (3, 0, 0.2, 0.11), 358 (2, 3, 0.3, 0.12), # local 359 (5, 1, 0.4, 0.13), # NON-EXISTENT 360 (0, 1, 0.5, 0.14), # local 361 ] 362 C = connectors.FromListConnector(connection_list) 363 syn = sim.StaticSynapse() 364 self.assertRaises(errors.ConnectionError, sim.Projection, self.p1, self.p2, C, syn) 365 366 def test_with_plastic_synapse(self, sim=sim): 367 connection_list = [ 368 (0, 0, 0.1, 0.1, 100, 400), 369 (3, 0, 0.2, 0.11, 101, 500), 370 (2, 3, 0.3, 0.12, 102, 600), # local 371 (2, 2, 0.4, 0.13, 103, 700), 372 (0, 1, 0.5, 0.14, 104, 800), # local 373 ] 374 C = connectors.FromListConnector(connection_list, column_names=[ 375 "weight", "delay", "U", "tau_rec"]) 376 syn = sim.TsodyksMarkramSynapse(U=99, tau_facil=88.8) 377 prj = sim.Projection(self.p1, self.p2, C, syn) 378 self.assertEqual(prj.get(["weight", "delay", "tau_facil", "tau_rec", "U"], format='list', gather=False), # use gather False because we are faking the MPI 379 [(0, 1, 0.5, 0.14, 88.8, 800.0, 104.0), 380 (2, 3, 0.3, 0.12, 88.8, 600.0, 102.0)]) 381 382 def test_with_stdp_synapse(self, sim=sim): 383 connection_list = [ 384 (0, 0, 0.1, 0.1, 10.0, 0.4), 385 (3, 0, 0.2, 0.11, 10.1, 0.5), 386 (2, 3, 0.3, 0.12, 10.2, 0.6), # local 387 (2, 2, 0.4, 0.13, 10.3, 0.7), 388 (0, 1, 0.5, 0.14, 10.4, 0.8), # local 389 ] 390 C = connectors.FromListConnector(connection_list, column_names=[ 391 "weight", "delay", "tau_plus", "w_max"]) 392 syn = sim.STDPMechanism(timing_dependence=sim.SpikePairRule(tau_plus=12.3, tau_minus=33.3), 393 weight_dependence=sim.MultiplicativeWeightDependence(w_max=1.11), 394 weight=0.321, delay=0.2) 395 prj = sim.Projection(self.p1, self.p2, C, syn) 396 self.assertEqual(prj.get(["weight", "delay", "tau_plus", "tau_minus", "w_max"], format='list', gather=False), # use gather False because we are faking the MPI 397 [(0, 1, 0.5, 0.14, 10.4, 33.3, 0.8), 398 (2, 3, 0.3, 0.12, 10.2, 33.3, 0.6)]) 399 400 401class TestFromFileConnector(unittest.TestCase): 402 403 def setUp(self, sim=sim): 404 sim.setup(num_processes=2, rank=1, min_delay=0.123) 405 self.p1 = sim.Population(4, sim.IF_cond_exp(), structure=space.Line()) 406 self.p2 = sim.Population(5, sim.HH_cond_exp(), structure=space.Line()) 407 assert_array_equal(self.p2._mask_local, np.array([0, 1, 0, 1, 0], dtype=bool)) 408 self.connection_list = [ 409 (0, 0, 0.1, 0.1), 410 (3, 0, 0.2, 0.11), 411 (2, 3, 0.3, 0.12), # local 412 (2, 2, 0.4, 0.13), 413 (0, 1, 0.5, 0.14), # local 414 ] 415 416 def tearDown(self, sim=sim): 417 for path in ("test.connections", "test.connections.1", "test.connections.2"): 418 if os.path.exists(path): 419 try: 420 os.remove(path) 421 except PermissionError: 422 pass 423 424 def test_connect_with_standard_text_file_not_distributed(self, sim=sim): 425 np.savetxt("test.connections", self.connection_list) 426 C = connectors.FromFileConnector("test.connections", distributed=False) 427 syn = sim.StaticSynapse() 428 prj = sim.Projection(self.p1, self.p2, C, syn) 429 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 430 [(0, 1, 0.5, 0.14), 431 (2, 3, 0.3, 0.12)]) 432 433 def test_connect_with_standard_text_file_distributed(self, sim=sim): 434 local_connection_list = [c for c in self.connection_list if c[1] % 2 == 1] 435 np.savetxt("test.connections.1", local_connection_list) 436 C = connectors.FromFileConnector("test.connections", distributed=True) 437 syn = sim.StaticSynapse() 438 prj = sim.Projection(self.p1, self.p2, C, syn) 439 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 440 [(0, 1, 0.5, 0.14), 441 (2, 3, 0.3, 0.12)]) 442 443 def test_with_plastic_synapses_not_distributed(self, sim=sim): 444 connection_list = [ 445 (0, 0, 0.1, 0.1, 100, 100), 446 (3, 0, 0.2, 0.11, 110, 99), 447 (2, 3, 0.3, 0.12, 120, 98), # local 448 (2, 2, 0.4, 0.13, 130, 97), 449 (0, 1, 0.5, 0.14, 140, 96), # local 450 ] 451 file = recording.files.StandardTextFile("test.connections.2", mode='wb') 452 file.write(connection_list, {"columns": ["i", "j", "weight", "delay", "U", "tau_rec"]}) 453 C = connectors.FromFileConnector("test.connections.2", distributed=False) 454 syn = sim.TsodyksMarkramSynapse(tau_facil=88.8) 455 prj = sim.Projection(self.p1, self.p2, C, syn) 456 self.assertEqual(prj.get(["weight", "delay", "U", "tau_rec", "tau_facil"], format='list', gather=False), # use gather False because we are faking the MPI 457 [(0, 1, 0.5, 0.14, 140.0, 96.0, 88.8), 458 (2, 3, 0.3, 0.12, 120.0, 98.0, 88.8)]) 459 460 461class TestFixedNumberPostConnector(unittest.TestCase): 462 463 def setUp(self, sim=sim): 464 sim.setup(num_processes=2, rank=1, min_delay=0.123) 465 self.p1 = sim.Population(4, sim.IF_cond_exp(), structure=space.Line()) 466 self.p2 = sim.Population(5, sim.HH_cond_exp(), structure=space.Line()) 467 assert_array_equal(self.p2._mask_local, np.array([0, 1, 0, 1, 0], dtype=bool)) 468 469 def test_with_n_smaller_than_population_size(self, sim=sim): 470 C = connectors.FixedNumberPostConnector(n=3, rng=MockRNG(delta=1)) 471 syn = sim.StaticSynapse(weight="0.5*d") 472 prj = sim.Projection(self.p1, self.p2, C, syn) 473 # MockRNG.permutation(arr) returns the reverse of arr, so each pre neuron will connect to neurons 4, 3, 2 474 # however, only neuron 3 is on the "local" (fake MPI) node 475 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 476 [(0, 3, 1.5, 0.123), 477 (1, 3, 1.0, 0.123), 478 (2, 3, 0.5, 0.123), 479 (3, 3, 0.0, 0.123)]) 480 481 def test_with_n_larger_than_population_size(self, sim=sim): 482 C = connectors.FixedNumberPostConnector(n=7, rng=MockRNG(delta=1)) 483 syn = sim.StaticSynapse() 484 prj = sim.Projection(self.p1, self.p2, C, syn) 485 # each pre neuron will connect to all post neurons (population size 5 is less than n), then to 4, 3 (MockRNG.permutation) 486 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 487 [(0, 1, 0.0, 0.123), 488 (1, 1, 0.0, 0.123), 489 (2, 1, 0.0, 0.123), 490 (3, 1, 0.0, 0.123), 491 (0, 3, 0.0, 0.123), 492 (0, 3, 0.0, 0.123), 493 (1, 3, 0.0, 0.123), 494 (1, 3, 0.0, 0.123), 495 (2, 3, 0.0, 0.123), 496 (2, 3, 0.0, 0.123), 497 (3, 3, 0.0, 0.123), 498 (3, 3, 0.0, 0.123)]) 499 500 def test_with_n_larger_than_population_size_no_self_connections(self, sim=sim): 501 C = connectors.FixedNumberPostConnector( 502 n=7, allow_self_connections=False, rng=MockRNG(delta=1)) 503 syn = sim.StaticSynapse() 504 prj = sim.Projection(self.p2, self.p2, C, syn) 505 # connections as follows: (pre - list of post) 506 # 0 - 1 2 3 4 4 3 2 507 # 1 - 0 2 3 4 4 3 2 508 # 2 - 0 1 3 4 4 3 1 509 # 3 - 0 1 2 4 4 2 1 510 # 4 - 0 1 2 3 3 2 1 511 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 512 [(0, 1, 0.0, 0.123), 513 (2, 1, 0.0, 0.123), 514 (2, 1, 0.0, 0.123), 515 (3, 1, 0.0, 0.123), 516 (3, 1, 0.0, 0.123), 517 (4, 1, 0.0, 0.123), 518 (4, 1, 0.0, 0.123), 519 (0, 3, 0.0, 0.123), 520 (0, 3, 0.0, 0.123), 521 (1, 3, 0.0, 0.123), 522 (1, 3, 0.0, 0.123), 523 (2, 3, 0.0, 0.123), 524 (2, 3, 0.0, 0.123), 525 (4, 3, 0.0, 0.123), 526 (4, 3, 0.0, 0.123), ]) 527 528 def test_with_replacement(self, sim=sim): 529 C = connectors.FixedNumberPostConnector(n=3, with_replacement=True, rng=MockRNG(delta=1)) 530 syn = sim.StaticSynapse() 531 prj = sim.Projection(self.p1, self.p2, C, syn) 532 # 0 - 0 1 2 533 # 1 - 3 4 0 534 # 2 - 1 2 3 535 # 3 - 4 0 1 536 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 537 [(0, 1, 0.0, 0.123), 538 (2, 1, 0.0, 0.123), 539 (3, 1, 0.0, 0.123), 540 (1, 3, 0.0, 0.123), 541 (2, 3, 0.0, 0.123)]) 542 543 def test_with_replacement_with_variable_n(self, sim=sim): 544 n = random.RandomDistribution('binomial', (5, 0.5), rng=MockRNG(start=1, delta=2)) 545 # should give (1, 3, 0, 2) 546 C = connectors.FixedNumberPostConnector(n=n, with_replacement=True, rng=MockRNG(delta=1)) 547 syn = sim.StaticSynapse() 548 prj = sim.Projection(self.p1, self.p2, C, syn) 549 # 0 - 0 550 # 1 - 1 2 3 551 # 2 - 552 # 3 - 4 0 553 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 554 [(1, 1, 0.0, 0.123), 555 (1, 3, 0.0, 0.123)]) 556 557 def test_with_replacement_no_self_connections(self, sim=sim): 558 C = connectors.FixedNumberPostConnector(n=3, with_replacement=True, 559 allow_self_connections=False, rng=MockRNG(start=2, delta=1)) 560 syn = sim.StaticSynapse() 561 prj = sim.Projection(self.p2, self.p2, C, syn) 562 # 0 - 2 3 4 563 # 1 - 0 2 3 564 # 2 - 4 0 1 565 # 3 - 2 4 0 566 # 4 - 1 2 3 567 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 568 [(2, 1, 0.0, 0.123), 569 (4, 1, 0.0, 0.123), 570 (0, 3, 0.0, 0.123), 571 (1, 3, 0.0, 0.123), 572 (4, 3, 0.0, 0.123)]) 573 574 575class TestFixedNumberPreConnector(unittest.TestCase): 576 577 def setUp(self, sim=sim): 578 sim.setup(num_processes=2, rank=1, min_delay=0.123) 579 self.p1 = sim.Population(4, sim.IF_cond_exp(), structure=space.Line()) 580 self.p2 = sim.Population(5, sim.HH_cond_exp(), structure=space.Line()) 581 assert_array_equal(self.p2._mask_local, np.array([0, 1, 0, 1, 0], dtype=bool)) 582 583 def test_with_n_smaller_than_population_size(self, sim=sim): 584 C = connectors.FixedNumberPreConnector(n=3, rng=MockRNG(delta=1)) 585 syn = sim.StaticSynapse(weight="0.1*d") 586 prj = sim.Projection(self.p1, self.p2, C, syn) 587 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 588 [(3, 1, 0.2, 0.123), 589 (2, 1, 0.1, 0.123), 590 (1, 1, 0.0, 0.123), 591 (3, 3, 0.0, 0.123), 592 (2, 3, 0.1, 0.123), 593 (1, 3, 0.2, 0.123), ]) 594 595 def test_with_n_larger_than_population_size(self, sim=sim): 596 C = connectors.FixedNumberPreConnector(n=7, rng=MockRNG(delta=1)) 597 syn = sim.StaticSynapse() 598 prj = sim.Projection(self.p1, self.p2, C, syn) 599 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 600 [(0, 1, 0.0, 0.123), 601 (1, 1, 0.0, 0.123), 602 (2, 1, 0.0, 0.123), 603 (3, 1, 0.0, 0.123), 604 (3, 1, 0.0, 0.123), 605 (2, 1, 0.0, 0.123), 606 (1, 1, 0.0, 0.123), 607 (0, 3, 0.0, 0.123), 608 (1, 3, 0.0, 0.123), 609 (2, 3, 0.0, 0.123), 610 (3, 3, 0.0, 0.123), 611 (3, 3, 0.0, 0.123), 612 (2, 3, 0.0, 0.123), 613 (1, 3, 0.0, 0.123), ]) 614 615 def test_with_n_larger_than_population_size_no_self_connections(self, sim=sim): 616 C = connectors.FixedNumberPreConnector( 617 n=7, allow_self_connections=False, rng=MockRNG(delta=1)) 618 syn = sim.StaticSynapse() 619 prj = sim.Projection(self.p2, self.p2, C, syn) 620 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 621 [(0, 1, 0.0, 0.123), 622 (2, 1, 0.0, 0.123), 623 (3, 1, 0.0, 0.123), 624 (4, 1, 0.0, 0.123), 625 (4, 1, 0.0, 0.123), 626 (3, 1, 0.0, 0.123), 627 (2, 1, 0.0, 0.123), 628 (0, 3, 0.0, 0.123), 629 (1, 3, 0.0, 0.123), 630 (2, 3, 0.0, 0.123), 631 (4, 3, 0.0, 0.123), 632 (4, 3, 0.0, 0.123), 633 (2, 3, 0.0, 0.123), 634 (1, 3, 0.0, 0.123), ]) 635 636 def test_with_replacement(self, sim=sim): 637 C = connectors.FixedNumberPreConnector(n=3, with_replacement=True, rng=MockRNG(delta=1)) 638 syn = sim.StaticSynapse() 639 prj = sim.Projection(self.p1, self.p2, C, syn) 640 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 641 [ # (0, 0, 0.0, 0.123), 642 #(1, 0, 0.0, 0.123), 643 #(2, 0, 0.0, 0.123), 644 (3, 1, 0.0, 0.123), 645 (0, 1, 0.0, 0.123), 646 (1, 1, 0.0, 0.123), 647 #(2, 2, 0.0, 0.123), 648 #(3, 2, 0.0, 0.123), 649 #(0, 2, 0.0, 0.123), 650 (1, 3, 0.0, 0.123), 651 (2, 3, 0.0, 0.123), 652 (3, 3, 0.0, 0.123), ]) 653 654 def test_with_replacement_with_variable_n(self, sim=sim): 655 n = random.RandomDistribution('binomial', (5, 0.5), rng=MockRNG(start=1, delta=2)) 656 # should give (1, 3, 0, 2, 4) 657 C = connectors.FixedNumberPreConnector(n=n, with_replacement=True, rng=MockRNG(delta=1)) 658 syn = sim.StaticSynapse() 659 prj = sim.Projection(self.p1, self.p2, C, syn) 660 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 661 [ # (0, 0, 0.0, 0.123), 662 (1, 1, 0.0, 0.123), 663 (2, 1, 0.0, 0.123), 664 (3, 1, 0.0, 0.123), 665 (0, 3, 0.0, 0.123), 666 (1, 3, 0.0, 0.123)]) 667 668 def test_with_replacement_no_self_connections(self, sim=sim): 669 C = connectors.FixedNumberPreConnector(n=3, with_replacement=True, 670 allow_self_connections=False, rng=MockRNG(start=2, delta=1)) 671 syn = sim.StaticSynapse() 672 prj = sim.Projection(self.p2, self.p2, C, syn) 673 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 674 [ # (2, 0, 0.0, 0.123), # [2, 3, 4] --> [2, 3, 4] 675 #(3, 0, 0.0, 0.123), 676 #(4, 0, 0.0, 0.123), 677 (0, 1, 0.0, 0.123), # [0, 1, 2] --> [0, 3, 2] 678 #(1, 1, 0.0, 0.123), 679 (3, 1, 0.0, 0.123), 680 (2, 1, 0.0, 0.123), 681 # (4, 2, 0.0, 0.123), # [4, 0, 1] --> [4, 0, 1] 682 #(0, 2, 0.0, 0.123), 683 #(1, 2, 0.0, 0.123), 684 (2, 3, 0.0, 0.123), # [2, 3, 4] --> [2, 0, 4] 685 #(3, 3, 0.0, 0.123), 686 (0, 3, 0.0, 0.123), 687 (4, 3, 0.0, 0.123), 688 ]) 689 690 def test_no_replacement_no_self_connections(self, sim=sim): 691 C = connectors.FixedNumberPreConnector(n=3, with_replacement=False, 692 allow_self_connections=False, rng=MockRNG(start=2, delta=1)) 693 syn = sim.StaticSynapse() 694 prj = sim.Projection(self.p2, self.p2, C, syn) 695 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 696 [(4, 1, 0.0, 0.123), 697 (3, 1, 0.0, 0.123), 698 (2, 1, 0.0, 0.123), 699 (4, 3, 0.0, 0.123), 700 #(3, 3, 0.0, 0.123), 701 (2, 3, 0.0, 0.123), 702 (1, 3, 0.0, 0.123), ]) 703 704 def test_with_replacement_parallel_unsafe(self, sim=sim): 705 C = connectors.FixedNumberPreConnector( 706 n=3, with_replacement=True, rng=MockRNG(delta=1, parallel_safe=False)) 707 syn = sim.StaticSynapse() 708 prj = sim.Projection(self.p1, self.p2, C, syn) 709 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 710 [(0, 1, 0.0, 0.123), 711 (1, 1, 0.0, 0.123), 712 (2, 1, 0.0, 0.123), 713 (3, 3, 0.0, 0.123), 714 (0, 3, 0.0, 0.123), 715 (1, 3, 0.0, 0.123), ]) 716 717 def test_no_replacement_parallel_unsafe(self, sim=sim): 718 C = connectors.FixedNumberPreConnector( 719 n=3, with_replacement=False, rng=MockRNG(delta=1, parallel_safe=False)) 720 syn = sim.StaticSynapse() 721 prj = sim.Projection(self.p1, self.p2, C, syn) 722 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 723 [(3, 1, 0.0, 0.123), 724 (2, 1, 0.0, 0.123), 725 (1, 1, 0.0, 0.123), 726 (3, 3, 0.0, 0.123), 727 (2, 3, 0.0, 0.123), 728 (1, 3, 0.0, 0.123), ]) 729 730 731class TestArrayConnector(unittest.TestCase): 732 733 def setUp(self, sim=sim): 734 sim.setup(num_processes=2, rank=1, min_delay=0.123) 735 self.p1 = sim.Population(3, sim.IF_cond_exp(), structure=space.Line()) 736 self.p2 = sim.Population(4, sim.HH_cond_exp(), structure=space.Line()) 737 assert_array_equal(self.p2._mask_local, np.array([1, 0, 1, 0], dtype=bool)) 738 739 def test_connect_with_scalar_weights_and_delays(self, sim=sim): 740 connections = np.array([ 741 [0, 1, 1, 0], 742 [1, 1, 0, 1], 743 [0, 0, 1, 0], 744 ], dtype=bool) 745 C = connectors.ArrayConnector(connections, safe=False) 746 syn = sim.StaticSynapse(weight=5.0, delay=0.5) 747 prj = sim.Projection(self.p1, self.p2, C, syn) 748 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 749 [(1, 0, 5.0, 0.5), 750 (0, 2, 5.0, 0.5), 751 (2, 2, 5.0, 0.5)]) 752 753 def test_connect_with_random_weights_parallel_safe(self, sim=sim): 754 rd_w = random.RandomDistribution( 755 'uniform', (0, 1), rng=MockRNG(delta=1.0, parallel_safe=True)) 756 rd_d = random.RandomDistribution('uniform', (0, 1), rng=MockRNG( 757 start=1.0, delta=0.1, parallel_safe=True)) 758 syn = sim.StaticSynapse(weight=rd_w, delay=rd_d) 759 connections = np.array([ 760 [0, 1, 1, 0], 761 [1, 1, 0, 1], 762 [0, 0, 1, 0], 763 ], dtype=bool) 764 C = connectors.ArrayConnector(connections, safe=False) 765 prj = sim.Projection(self.p1, self.p2, C, syn) 766 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 767 [(1, 0, 0.0, 1.0), 768 (0, 2, 3.0, 1.3), 769 (2, 2, 4.0, 1.4000000000000001)]) # better to do an "almost-equal" check 770 771 772class TestCloneConnector(unittest.TestCase): 773 774 def setUp(self, sim=sim): 775 sim.setup(num_processes=2, rank=1, min_delay=0.123) 776 self.p1 = sim.Population(4, sim.IF_cond_exp(), structure=space.Line()) 777 self.p2 = sim.Population(5, sim.HH_cond_exp(), structure=space.Line()) 778 assert_array_equal(self.p2._mask_local, np.array([0, 1, 0, 1, 0], dtype=bool)) 779 connection_list = [ 780 (0, 0, 0.0, 1.0), 781 (3, 0, 0.0, 1.0), 782 (2, 3, 0.0, 1.0), # local 783 (2, 2, 0.0, 1.0), 784 (0, 1, 0.0, 1.0), # local 785 ] 786 list_connector = connectors.FromListConnector(connection_list) 787 syn = sim.StaticSynapse() 788 self.ref_prj = sim.Projection(self.p1, self.p2, list_connector, syn) 789 self.orig_gather_dict = recording.gather_dict # create reference to original function 790 # The gather_dict function in recording needs to be temporarily replaced so it can work with 791 # a mock version of the function to avoid it throwing an mpi4py import error when setting 792 # the rank in pyNN.mock by hand to > 1 793 794 def mock_gather_dict(D, all=False): 795 return D 796 recording.gather_dict = mock_gather_dict 797 798 def tearDown(self, sim=sim): 799 # restore original gather_dict function 800 recording.gather_dict = self.orig_gather_dict 801 802 def test_connect(self, sim=sim): 803 syn = sim.StaticSynapse(weight=5.0, delay=0.5) 804 C = connectors.CloneConnector(self.ref_prj) 805 prj = sim.Projection(self.p1, self.p2, C, syn) 806 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 807 [(0, 1, 5.0, 0.5), 808 (2, 3, 5.0, 0.5)]) 809 810 def test_connect_with_pre_post_mismatch(self, sim=sim): 811 syn = sim.StaticSynapse() 812 C = connectors.CloneConnector(self.ref_prj) 813 p3 = sim.Population(5, sim.IF_cond_exp(), structure=space.Line()) 814 self.assertRaises(errors.ConnectionError, sim.Projection, self.p1, p3, C, syn) 815 816 817class TestIndexBasedProbabilityConnector(unittest.TestCase): 818 819 class IndexBasedProbability(connectors.IndexBasedExpression): 820 821 def __call__(self, i, j): 822 return np.array((i + j) % 3 == 0, dtype=float) 823 824 class IndexBasedWeights(connectors.IndexBasedExpression): 825 826 def __call__(self, i, j): 827 return np.array(i * j + 1, dtype=float) 828 829 class IndexBasedDelays(connectors.IndexBasedExpression): 830 831 def __call__(self, i, j): 832 return np.array(i + j + 1, dtype=float) 833 834 def setUp(self, sim=sim, **extra): 835 sim.setup(num_processes=2, rank=1, min_delay=0.123, **extra) 836 self.p1 = sim.Population(5, sim.IF_cond_exp(), structure=space.Line()) 837 self.p2 = sim.Population(5, sim.HH_cond_exp(), structure=space.Line()) 838 assert_array_equal(self.p2._mask_local, np.array([1, 0, 1, 0, 1], dtype=bool)) 839 840 def test_connect_with_scalar_weights_and_delays(self, sim=sim): 841 syn = sim.StaticSynapse(weight=1.0, delay=2) 842 C = connectors.IndexBasedProbabilityConnector(self.IndexBasedProbability()) 843 prj = sim.Projection(self.p1, self.p2, C, syn) 844 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 845 [(0, 0, 1, 2), 846 (3, 0, 1, 2), 847 (1, 2, 1, 2), 848 (4, 2, 1, 2), 849 (2, 4, 1, 2)]) 850 851 def test_connect_with_index_based_weights(self, sim=sim): 852 syn = sim.StaticSynapse(weight=self.IndexBasedWeights(), delay=2) 853 C = connectors.IndexBasedProbabilityConnector(self.IndexBasedProbability()) 854 prj = sim.Projection(self.p1, self.p2, C, syn) 855 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 856 [(0, 0, 1, 2), 857 (3, 0, 1, 2), 858 (1, 2, 3, 2), 859 (4, 2, 9, 2), 860 (2, 4, 9, 2)]) 861 862 def test_connect_with_index_based_delays(self, sim=sim): 863 syn = sim.StaticSynapse(weight=1.0, delay=self.IndexBasedDelays()) 864 C = connectors.IndexBasedProbabilityConnector(self.IndexBasedProbability()) 865 prj = sim.Projection(self.p1, self.p2, C, syn) 866 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 867 [(0, 0, 1, 1), 868 (3, 0, 1, 4), 869 (1, 2, 1, 4), 870 (4, 2, 1, 7), 871 (2, 4, 1, 7)]) 872 873 874class TestDisplacementDependentProbabilityConnector(unittest.TestCase): 875 876 def setUp(self, sim=sim, **extra): 877 sim.setup(num_processes=2, rank=1, min_delay=0.123, **extra) 878 self.p1 = sim.Population(9, sim.IF_cond_exp(), 879 structure=space.Grid2D(aspect_ratio=1.0, dx=1.0, dy=1.0)) 880 self.p2 = sim.Population(9, sim.HH_cond_exp(), 881 structure=space.Grid2D(aspect_ratio=1.0, dx=1.0, dy=1.0)) 882 assert_array_equal(self.p2._mask_local, np.array( 883 [1, 0, 1, 0, 1, 0, 1, 0, 1], dtype=bool)) 884 885 def test_connect(self, sim=sim): 886 syn = sim.StaticSynapse(weight=1.0, delay=2) 887 888 def displacement_expression(d): 889 return 0.5 * ((d[0] >= -1) * (d[0] <= 2)) + 0.25 * (d[1] >= 0) * (d[1] <= 1) 890 C = connectors.DisplacementDependentProbabilityConnector(displacement_expression, 891 rng=MockRNG(delta=0.01)) 892 prj = sim.Projection(self.p1, self.p2, C, syn) 893 self.assertEqual(prj.get(["weight", "delay"], format='list', gather=False), # use gather False because we are faking the MPI 894 [(0, 0, 1.0, 2.0), 895 (1, 0, 1.0, 2.0), 896 (2, 0, 1.0, 2.0), 897 (3, 0, 1.0, 2.0), 898 (4, 0, 1.0, 2.0), 899 (5, 0, 1.0, 2.0), 900 (6, 0, 1.0, 2.0), 901 (0, 2, 1.0, 2.0), 902 (1, 2, 1.0, 2.0), 903 (2, 2, 1.0, 2.0), 904 (3, 2, 1.0, 2.0), 905 (4, 2, 1.0, 2.0), 906 (5, 2, 1.0, 2.0), 907 (0, 4, 1.0, 2.0), 908 (1, 4, 1.0, 2.0), 909 (2, 4, 1.0, 2.0), 910 (3, 4, 1.0, 2.0), 911 (4, 4, 1.0, 2.0), 912 (5, 4, 1.0, 2.0), 913 (6, 4, 1.0, 2.0), 914 (7, 4, 1.0, 2.0), 915 (8, 4, 1.0, 2.0), 916 (0, 6, 1.0, 2.0), 917 (3, 6, 1.0, 2.0), 918 (6, 6, 1.0, 2.0), 919 (1, 8, 1.0, 2.0), 920 (2, 8, 1.0, 2.0)]) 921 922 923class TestFixedTotalNumberConnector(unittest.TestCase): 924 925 def setUp(self, sim=sim): 926 sim.setup(num_processes=2, rank=1, min_delay=0.123) 927 self.p1 = sim.Population(4, sim.IF_cond_exp(), structure=space.Line()) 928 self.p2 = sim.Population(5, sim.HH_cond_exp(), structure=space.Line()) 929 assert_array_equal(self.p2._mask_local, np.array([0, 1, 0, 1, 0], dtype=bool)) 930 931 def test_1(self): 932 C = connectors.FixedTotalNumberConnector(n=12, rng=random.NumpyRNG()) 933 syn = sim.StaticSynapse(weight="0.5*d") 934 prj = sim.Projection(self.p1, self.p2, C, syn) 935 connections = prj.get(["weight", "delay"], format='list', gather=False) 936 self.assertLess(len(connections), 12) # unlikely to be 12, since we have 2 MPI nodes 937 self.assertGreater(len(connections), 0) # unlikely to be 0 938