- Timestamp:
- 10/12/11 10:20:32 (7 months ago)
- Location:
- trunk
- Files:
-
- 24 modified
-
examples/VAbenchmarks2-csa.py (modified) (1 diff)
-
examples/iaf_sfa_relref/iaf_sfa_network_INH_GAMMA.py (modified) (1 diff)
-
examples/iaf_sfa_relref/iaf_sfa_network_STATIC.py (modified) (1 diff)
-
src/brian/__init__.py (modified) (5 diffs)
-
src/brian/connectors.py (modified) (2 diffs)
-
src/brian/simulator.py (modified) (4 diffs)
-
src/common.py (modified) (14 diffs)
-
src/connectors.py (modified) (8 diffs)
-
src/connectors2.py (modified) (6 diffs)
-
src/core.py (modified) (2 diffs)
-
src/moose/__init__.py (modified) (2 diffs)
-
src/moose/simulator.py (modified) (1 diff)
-
src/nemo/__init__.py (modified) (2 diffs)
-
src/nemo/simulator.py (modified) (1 diff)
-
src/nest/__init__.py (modified) (4 diffs)
-
src/nest/connectors.py (modified) (1 diff)
-
src/nest/simulator.py (modified) (4 diffs)
-
src/neuron/__init__.py (modified) (4 diffs)
-
src/neuron/simulator.py (modified) (6 diffs)
-
src/pcsim/__init__.py (modified) (5 diffs)
-
src/pcsim/simulator.py (modified) (4 diffs)
-
test/system/scenarios.py (modified) (2 diffs)
-
test/unittests/test_connectors.py (modified) (15 diffs)
-
test/unittests/test_projection.py (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/examples/VAbenchmarks2-csa.py
r915 r998 131 131 132 132 print "%s Initialising membrane potential to random values..." % node_id 133 rng = NumpyRNG(seed=rngseed, parallel_safe=parallel_safe , rank=node_id, num_processes=np)133 rng = NumpyRNG(seed=rngseed, parallel_safe=parallel_safes) 134 134 uniformDistr = RandomDistribution('uniform', [v_reset,v_thresh], rng=rng) 135 135 all_cells.initialize('v', uniformDistr) -
trunk/examples/iaf_sfa_relref/iaf_sfa_network_INH_GAMMA.py
r910 r998 140 140 # Connect everything up 141 141 yTimer = time.time() 142 projection. connection_manager.convergent_connect(chosenPresIDs, currentPostID, weights, delaysClipped)142 projection._convergent_connect(chosenPresIDs, currentPostID, weights, delaysClipped) 143 143 timer4 += time.time() - myTimer 144 144 -
trunk/examples/iaf_sfa_relref/iaf_sfa_network_STATIC.py
r920 r998 142 142 # Connect everything up 143 143 yTimer = time.time() 144 projection. connection_manager.convergent_connect(chosenPresIDs, currentPostID, weights, delaysClipped)144 projection._convergent_connect(chosenPresIDs, currentPostID, weights, delaysClipped) 145 145 timer4 += time.time() - myTimer 146 146 -
trunk/src/brian/__init__.py
r962 r998 131 131 # threshold=v_thresh, 132 132 # reset=v_reset, 133 # clock=s tate.simclock,133 # clock=simulator.state.simclock, 134 134 # compile=True, 135 # max_delay=s tate.max_delay)135 # max_delay=simulator.state.max_delay) 136 136 # cell_parameters = cellparams or {} 137 137 # elif isinstance(cellclass, type) and issubclass(cellclass, standardmodels.StandardCellType): … … 238 238 else: 239 239 self._plasticity_model = "static_synapse" 240 241 self.connection_manager = simulator.ConnectionManager(self.synapse_type, self._plasticity_model, parent=self) 242 self.connections = self.connection_manager 240 241 self._n = {} 242 self._brian_connections = {} 243 self._indices = {} 244 self._populations = [{}, {}] 245 243 246 method.connect(self) 244 self.connection_manager._finalize() 247 self._finalize() 248 245 249 if self._plasticity_model != "static_synapse": 246 for key in self. connections.keys:247 synapses = self. connections.brian_connections[key]250 for key in self._brian_connections.keys: 251 synapses = self._brian_connections[key] 248 252 if self._plasticity_model is "stdp_synapse": 249 253 parameters = self.synapse_dynamics.slow.all_parameters … … 268 272 parameters['U']) 269 273 simulator.state.add(stp) 270 274 275 def __len__(self): 276 """Return the total number of connections in this Projection.""" 277 result = 0 278 for key in self._brian_connections.keys(): 279 result += self._n[key] 280 return result 281 282 def _get_indices(self): 283 sources = numpy.array([], int) 284 targets = numpy.array([], int) 285 for key in self._brian_connections.keys(): 286 paddings = self._populations[0][key[0]], self._populations[1][key[1]] 287 sources = numpy.concatenate((sources, self._indices[key][0] + paddings[0])) 288 targets = numpy.concatenate((targets, self._indices[key][1] + paddings[1])) 289 return sources.astype(int), targets.astype(int) 290 291 def __getitem__(self, i): 292 """Return the `i`th connection as a Connection object.""" 293 cumsum_idx = numpy.cumsum(self._n.values()) 294 if isinstance(i, slice): 295 idx = numpy.searchsorted(cumsum_idx, numpy.arange(*i.indices(i.stop)), 'left') 296 keys = [self._brian_connections.keys()[j] for j in idx] 297 else: 298 idx = numpy.searchsorted(cumsum_idx, i, 'left') 299 keys = self._brian_connections.keys()[idx] 300 global_indices = self._get_indices() 301 if isinstance(i, int): 302 if i < len(self): 303 pad = i - cumsum_idx[idx] 304 local_idx = self._indices[keys][0][pad], self._indices[keys][1][pad] 305 local_addr = global_indices[0][i], global_indices[1][i] 306 return Connection(self._brian_connections[keys], local_idx, local_addr) 307 else: 308 raise IndexError("%d > %d" % (i, len(self)-1)) 309 elif isinstance(i, slice): 310 if i.stop < len(self): 311 res = [] 312 for count, j in enumerate(xrange(*i.indices(i.stop))): 313 key = keys[count] 314 pad = j - cumsum_idx[idx[count]] 315 local_idx = self._indices[key][0][pad], self._indices[key][1][pad] 316 local_addr = global_indices[0][j], global_indices[1][j] 317 res.append(simulator.Connection(self._brian_connections[key], local_idx, local_addr)) 318 return res 319 else: 320 raise IndexError("%d > %d" % (i.stop, len(self)-1)) 321 322 def __connection_generator(self): 323 """Yield each connection in turn.""" 324 global_indices = self._get_indices() 325 count = 0 326 for key in self._brian_connections.keys(): 327 bc = self._brian_connections[key] 328 for i in xrange(bc.W.getnnz()): 329 local_idx = self._indices[key][0][i], self._indices[key][0][i] 330 local_addr = global_indices[0][count], global_indices[1][count] 331 yield simulator.Connection(bc, self._indices[key]) 332 count += 1 333 334 def __iter__(self): 335 """Return an iterator over all connections in this Projection.""" 336 return self.__connection_generator() 337 338 def _finalize(self): 339 for key in self._brian_connections.keys(): 340 self._indices[key] = self._brian_connections[key].W.nonzero() 341 self._brian_connections[key].compress() 342 343 def _get_brian_connection(self, source_group, target_group, synapse_obj, weight_units, homogeneous=False): 344 """ 345 Return the Brian Connection object that connects two NeuronGroups with a 346 given synapse model. 347 348 source_group -- presynaptic Brian NeuronGroup. 349 target_group -- postsynaptic Brian NeuronGroup 350 synapse_obj -- name of the variable that will be modified by synaptic 351 input. 352 weight_units -- Brian Units object: nA for current-based synapses, 353 uS for conductance-based synapses. 354 """ 355 key = (source_group, target_group, synapse_obj) 356 if not self._brian_connections.has_key(key): 357 assert isinstance(source_group, brian.NeuronGroup) 358 assert isinstance(target_group, brian.NeuronGroup), type(target_group) 359 assert isinstance(synapse_obj, basestring), "%s (%s)" % (synapse_obj, type(synapse_obj)) 360 try: 361 max_delay = simulator.state.max_delay*ms 362 except Exception: 363 raise Exception("Simulation timestep not yet set. Need to call setup()") 364 if not homogeneous: 365 self._brian_connections[key] = brian.DelayConnection(source_group, 366 target_group, 367 synapse_obj, 368 max_delay=max_delay) 369 else: 370 self._brian_connections[key] = brian.Connection(source_group, 371 target_group, 372 synapse_obj, 373 max_delay=simulator.state.max_delay*ms) 374 self._brian_connections[key].weight_units = weight_units 375 simulator.state.add(self._brian_connections[key]) 376 self._n[key] = 0 377 return self._brian_connections[key] 378 379 def _detect_parent_groups(self, cells): 380 groups = {} 381 for index, cell in enumerate(cells): 382 group = cell.parent_group 383 if not groups.has_key(group): 384 groups[group] = [index] 385 else: 386 groups[group] += [index] 387 return groups 388 389 def _divergent_connect(self, source, targets, weights, delays, homogeneous=False): 390 """ 391 Connect a neuron to one or more other neurons with a static connection. 392 393 `source` -- the ID of the pre-synaptic cell. 394 `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. 395 `weight` -- a list/1D array of connection weights, or a single weight. 396 Must have the same length as `targets`. 397 `delays` -- a list/1D array of connection delays, or a single delay. 398 Must have the same length as `targets`. 399 """ 400 #print "connecting", source, "to", targets, "with weights", weights, "and delays", delays 401 if not core.is_listlike(targets): 402 targets = [targets] 403 if isinstance(weights, float): 404 weights = [weights] 405 if isinstance(delays, float): 406 delays = [delays] 407 assert len(targets) > 0 408 if not isinstance(source, common.IDMixin): 409 raise errors.ConnectionError("source should be an ID object, actually %s" % type(source)) 410 for target in targets: 411 if not isinstance(target, common.IDMixin): 412 raise errors.ConnectionError("Invalid target ID: %s" % target) 413 assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets),len(weights),len(delays)) 414 if common.is_conductance(targets[0]): 415 units = uS 416 else: 417 units = nA 418 synapse_type = self.synapse_type or "excitatory" 419 try: 420 source_group = source.parent_group 421 except AttributeError, errmsg: 422 raise errors.ConnectionError("%s. Maybe trying to connect from non-existing cell (ID=%s)." % (errmsg, source)) 423 groups = self._detect_parent_groups(targets) # we assume here all the targets belong to the same NeuronGroup 424 425 weights = numpy.array(weights) * units 426 delays = numpy.array(delays) * ms 427 weights[weights == 0] = simulator.ZERO_WEIGHT 428 429 for target_group, indices in groups.items(): 430 synapse_obj = targets[indices[0]].parent.celltype.synapses[synapse_type] 431 bc = self._get_brian_connection(source_group, target_group, synapse_obj, units, homogeneous) 432 padding = (int(source.parent.first_id), int(targets[indices[0]].parent.first_id)) 433 src = int(source) - padding[0] 434 mytargets = numpy.array(targets, int)[indices] - padding[1] 435 bc.W.rows[src] = mytargets 436 bc.W.data[src] = weights[indices] 437 if not homogeneous: 438 bc.delayvec.rows[src] = mytargets 439 bc.delayvec.data[src] = delays[indices] 440 else: 441 bc.delay = int(delays[0] / bc.source.clock.dt) 442 key = (source_group, target_group, synapse_obj) 443 self._n[key] += len(mytargets) 444 445 pop_sources = self._populations[0] 446 if len(pop_sources) is 0: 447 pop_sources[source_group] = 0 448 elif not pop_sources.has_key(source_group): 449 pop_sources[source_group] = numpy.sum([len(item) for item in pop_sources.keys()]) 450 pop_targets = self._populations[1] 451 if len(pop_targets) is 0: 452 pop_targets[target_group] = 0 453 elif not pop_targets.has_key(target_group): 454 pop_targets[target_group] = numpy.sum([len(item) for item in pop_targets.keys()]) 455 271 456 def saveConnections(self, file, gather=True, compatible_output=True): 272 457 """ … … 275 460 """ 276 461 import operator 277 lines = numpy.empty((len(self .connection_manager), 4))462 lines = numpy.empty((len(self), 4)) 278 463 padding = 0 279 for key in self. connection_manager.keys:280 bc = self. connection_manager.brian_connections[key]464 for key in self._brian_connections.keys(): 465 bc = self._brian_connections[key] 281 466 size = bc.W.getnnz() 282 lines[padding:padding+size,0], lines[padding:padding+size,1] = self. connection_manager.indices[key]467 lines[padding:padding+size,0], lines[padding:padding+size,1] = self._indices[key] 283 468 lines[padding:padding+size,2] = bc.W.alldata / bc.weight_units 284 469 if isinstance(bc, brian.DelayConnection): … … 296 481 file.close() 297 482 483 def set(self, name, value): 484 """ 485 Set connection attributes for all connections in this Projection. 486 487 `name` -- attribute name 488 `value` -- the attribute numeric value, or a list/1D array of such 489 values of the same length as the number of local connections, 490 or a 2D array with the same dimensions as the connectivity 491 matrix (as returned by `get(format='array')`). 492 """ 493 for key in self._brian_connections.keys(): 494 bc = self._brian_connections[key] 495 padding = 0 496 if name == 'weight': 497 M = bc.W 498 units = bc.weight_units 499 elif name == 'delay': 500 M = bc.delay 501 units = ms 502 else: 503 raise Exception("Setting parameters other than weight and delay not yet supported.") 504 value = value*units 505 if numpy.isscalar(value): 506 if (name == 'weight') or (name == 'delay' and isinstance(bc, brian.DelayConnection)): 507 for row in xrange(M.shape[0]): 508 M.set_row(row, value) 509 elif (name == 'delay' and isinstance(bc, brian.Connection)): 510 bc.delay = int(value / bc.source.clock.dt) 511 else: 512 raise Exception("Setting a non appropriate parameter") 513 elif isinstance(value, numpy.ndarray) and len(value.shape) == 2: 514 if (name == 'delay') and not isinstance(bc, brian.DelayConnection): 515 raise Exception("FastConnector have been used, and only fixed homogeneous delays are allowed") 516 address_gen = ((i, j) for i,row in enumerate(bc.W.rows) for j in row) 517 for (i,j) in address_gen: 518 M[i,j] = value[i,j] 519 elif core.is_listlike(value): 520 N = M.getnnz() 521 assert len(value[padding:padding+N]) == N 522 if (name == 'delay') and not isinstance(bc, brian.DelayConnection): 523 raise Exception("FastConnector have been used: only fixed homogeneous delays are allowed") 524 M.alldata = value 525 else: 526 raise Exception("Values must be scalars or lists/arrays") 527 padding += M.getnnz() 528 529 def get(self, parameter_name, format, gather=True): 530 """ 531 Get the values of a given attribute (weight or delay) for all 532 connections in this Projection. 533 534 `parameter_name` -- name of the attribute whose values are wanted. 535 `format` -- "list" or "array". Array format implicitly assumes that all 536 connections belong to a single Projection. 537 538 Return a list or a 2D Numpy array. The array element X_ij contains the 539 attribute value for the connection from the ith neuron in the pre- 540 synaptic Population to the jth neuron in the post-synaptic Population, 541 if such a connection exists. If there are no such connections, X_ij will 542 be NaN. 543 """ 544 values = numpy.array([]) 545 for key in self._brian_connections.keys(): 546 bc = self._brian_connections[key] 547 if parameter_name == "weight": 548 values = numpy.concatenate((values, bc.W.alldata / bc.weight_units)) 549 elif parameter_name == 'delay': 550 if isinstance(bc, brian.DelayConnection): 551 values = numpy.concatenate((values, bc.delay.alldata / ms)) 552 else: 553 data = bc.delay * bc.source.clock.dt * numpy.ones(bc.W.getnnz()) /ms 554 values = numpy.concatenate((values, data)) 555 else: 556 raise Exception("Getting parameters other than weight and delay not yet supported.") 557 558 if format == 'list': 559 values = values.tolist() 560 elif format == 'array': 561 values_arr = numpy.nan * numpy.ones((self.parent.pre.size, self.parent.post.size)) 562 sources, targets = self._indices 563 values_arr[sources, targets] = values 564 values = values_arr 565 else: 566 raise Exception("format must be 'list' or 'array', actually '%s'" % format) 567 return values 568 298 569 Space = space.Space 299 570 -
trunk/src/brian/connectors.py
r962 r998 69 69 homogeneous = numpy.isscalar(self.delays_generator.source) 70 70 if len(targets) > 0: 71 self.projection. connection_manager.connect(src, targets.tolist(), weights, delays, homogeneous)71 self.projection._divergent_connect(src, targets.tolist(), weights, delays, homogeneous) 72 72 73 73 … … 136 136 for tgt, src, w, d in zip(projection.post.local_cells, sources, weights, delays): 137 137 # the float is in case the values are of type numpy.float64, which NEST chokes on 138 projection. connection_manager.connect(src, [tgt], float(w), float(d), homogeneous)138 projection._divergent_connect(src, [tgt], float(w), float(d), homogeneous) 139 139 self.progression(count) 140 140 count += 1 -
trunk/src/brian/simulator.py
r957 r998 4 4 implementation of the API. 5 5 6 Functions and classes us eable by the common implementation:6 Functions and classes usable by the common implementation: 7 7 8 8 Functions: 9 create_cells()10 9 reset() 11 10 run() … … 14 13 ID 15 14 Recorder 16 ConnectionManager17 15 Connection 18 16 … … 397 395 in the weight array. 398 396 `indices` -- the mapping of the x, y coordinates of the established 399 connections, stored by the connection_managerhandling those397 connections, stored by the Projection handling those 400 398 connections. 401 399 """ … … 425 423 weight = property(_get_weight, _set_weight) 426 424 delay = property(_get_delay, _set_delay) 427 428 429 class ConnectionManager(object): 430 """ 431 Manage synaptic connections, providing methods for creating, listing, 432 accessing individual connections. 433 """ 434 435 def __init__(self, synapse_type, synapse_model=None, parent=None): 436 """ 437 Create a new ConnectionManager. 438 439 `synapse_type` -- the 'physiological type' of the synapse, e.g. 440 'excitatory' or 'inhibitory',or any other key in the 441 `synapses` attibute of the celltype class. 442 `synapse_model` -- not used. Present for consistency with other simulators. 443 `parent` -- the parent `Projection`, if any. 444 """ 445 self.synapse_type = synapse_type 446 self.synapse_model = synapse_model 447 self.parent = parent 448 self.n = {} 449 self.brian_connections = {} 450 self.indices = {} 451 self._populations = [{}, {}] 452 453 def __getitem__(self, i): 454 """Return the `i`th connection as a Connection object.""" 455 cumsum_idx = numpy.cumsum(self.n.values()) 456 if isinstance(i, slice): 457 idx = numpy.searchsorted(cumsum_idx, numpy.arange(*i.indices(i.stop)), 'left') 458 keys = [self.keys[j] for j in idx] 459 else: 460 idx = numpy.searchsorted(cumsum_idx, i, 'left') 461 keys = self.keys[idx] 462 global_indices = self._indices 463 if isinstance(i, int): 464 if i < len(self): 465 pad = i - cumsum_idx[idx] 466 local_idx = self.indices[keys][0][pad], self.indices[keys][1][pad] 467 local_addr = global_indices[0][i], global_indices[1][i] 468 return Connection(self.brian_connections[keys], local_idx, local_addr) 469 else: 470 raise IndexError("%d > %d" % (i, len(self)-1)) 471 elif isinstance(i, slice): 472 if i.stop < len(self): 473 res = [] 474 for count, j in enumerate(xrange(*i.indices(i.stop))): 475 key = keys[count] 476 pad = j - cumsum_idx[idx[count]] 477 local_idx = self.indices[key][0][pad], self.indices[key][1][pad] 478 local_addr = global_indices[0][j], global_indices[1][j] 479 res.append(Connection(self.brian_connections[key], local_idx, local_addr)) 480 return res 481 else: 482 raise IndexError("%d > %d" % (i.stop, len(self)-1)) 483 484 def __len__(self): 485 """Return the total number of connections in this manager.""" 486 result = 0 487 for key in self.keys: 488 result += self.n[key] 489 return result 490 491 def __connection_generator(self): 492 """Yield each connection in turn.""" 493 global_indices = self._indices 494 count = 0 495 for key in self.keys: 496 bc = self.brian_connections[key] 497 for i in xrange(bc.W.getnnz()): 498 local_idx = self.indices[key][0][i], self.indices[key][0][i] 499 local_addr = global_indices[0][count], global_indices[1][count] 500 yield Connection(bc, self.indices[key]) 501 count += 1 502 503 @property 504 def keys(self): 505 return self.brian_connections.keys() 506 507 def __iter__(self): 508 """Return an iterator over all connections in this manager.""" 509 return self.__connection_generator() 510 511 def _finalize(self): 512 for key in self.keys: 513 self.indices[key] = self.brian_connections[key].W.nonzero() 514 self.brian_connections[key].compress() 515 516 @property 517 def _indices(self): 518 sources = numpy.array([], int) 519 targets = numpy.array([], int) 520 for key in self.keys: 521 paddings = self._populations[0][key[0]], self._populations[1][key[1]] 522 sources = numpy.concatenate((sources, self.indices[key][0] + paddings[0])) 523 targets = numpy.concatenate((targets, self.indices[key][1] + paddings[1])) 524 return sources.astype(int), targets.astype(int) 525 526 def _get_brian_connection(self, source_group, target_group, synapse_obj, weight_units, homogeneous=False): 527 """ 528 Return the Brian Connection object that connects two NeuronGroups with a 529 given synapse model. 530 531 source_group -- presynaptic Brian NeuronGroup. 532 target_group -- postsynaptic Brian NeuronGroup 533 synapse_obj -- name of the variable that will be modified by synaptic 534 input. 535 weight_units -- Brian Units object: nA for current-based synapses, 536 uS for conductance-based synapses. 537 """ 538 key = (source_group, target_group, synapse_obj) 539 if not self.brian_connections.has_key(key): 540 assert isinstance(source_group, brian.NeuronGroup) 541 assert isinstance(target_group, brian.NeuronGroup), type(target_group) 542 assert isinstance(synapse_obj, basestring), "%s (%s)" % (synapse_obj, type(synapse_obj)) 543 try: 544 max_delay = state.max_delay*ms 545 except Exception: 546 raise Exception("Simulation timestep not yet set. Need to call setup()") 547 if not homogeneous: 548 self.brian_connections[key] = brian.DelayConnection(source_group, 549 target_group, 550 synapse_obj, 551 max_delay=max_delay) 552 else: 553 self.brian_connections[key] = brian.Connection(source_group, 554 target_group, 555 synapse_obj, 556 max_delay=state.max_delay*ms) 557 self.brian_connections[key].weight_units = weight_units 558 state.add(self.brian_connections[key]) 559 self.n[key] = 0 560 return self.brian_connections[key] 561 562 def _detect_parent_groups(self, cells): 563 groups = {} 564 for index, cell in enumerate(cells): 565 group = cell.parent_group 566 if not groups.has_key(group): 567 groups[group] = [index] 568 else: 569 groups[group] += [index] 570 return groups 571 572 def connect(self, source, targets, weights, delays, homogeneous=False): 573 """ 574 Connect a neuron to one or more other neurons with a static connection. 575 576 `source` -- the ID of the pre-synaptic cell. 577 `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. 578 `weight` -- a list/1D array of connection weights, or a single weight. 579 Must have the same length as `targets`. 580 `delays` -- a list/1D array of connection delays, or a single delay. 581 Must have the same length as `targets`. 582 """ 583 #print "connecting", source, "to", targets, "with weights", weights, "and delays", delays 584 if not core.is_listlike(targets): 585 targets = [targets] 586 if isinstance(weights, float): 587 weights = [weights] 588 if isinstance(delays, float): 589 delays = [delays] 590 assert len(targets) > 0 591 if not isinstance(source, common.IDMixin): 592 raise errors.ConnectionError("source should be an ID object, actually %s" % type(source)) 593 for target in targets: 594 if not isinstance(target, common.IDMixin): 595 raise errors.ConnectionError("Invalid target ID: %s" % target) 596 assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets),len(weights),len(delays)) 597 if common.is_conductance(targets[0]): 598 units = uS 599 else: 600 units = nA 601 synapse_type = self.synapse_type or "excitatory" 602 try: 603 source_group = source.parent_group 604 except AttributeError, errmsg: 605 raise errors.ConnectionError("%s. Maybe trying to connect from non-existing cell (ID=%s)." % (errmsg, source)) 606 groups = self._detect_parent_groups(targets) # we assume here all the targets belong to the same NeuronGroup 607 608 weights = numpy.array(weights) * units 609 delays = numpy.array(delays) * ms 610 weights[weights == 0] = ZERO_WEIGHT 611 612 for target_group, indices in groups.items(): 613 synapse_obj = targets[indices[0]].parent.celltype.synapses[synapse_type] 614 bc = self._get_brian_connection(source_group, target_group, synapse_obj, units, homogeneous) 615 padding = (int(source.parent.first_id), int(targets[indices[0]].parent.first_id)) 616 src = int(source) - padding[0] 617 mytargets = numpy.array(targets, int)[indices] - padding[1] 618 bc.W.rows[src] = mytargets 619 bc.W.data[src] = weights[indices] 620 if not homogeneous: 621 bc.delayvec.rows[src] = mytargets 622 bc.delayvec.data[src] = delays[indices] 623 else: 624 bc.delay = int(delays[0] / bc.source.clock.dt) 625 key = (source_group, target_group, synapse_obj) 626 self.n[key] += len(mytargets) 627 628 pop_sources = self._populations[0] 629 if len(pop_sources) is 0: 630 pop_sources[source_group] = 0 631 elif not pop_sources.has_key(source_group): 632 pop_sources[source_group] = numpy.sum([len(item) for item in pop_sources.keys()]) 633 pop_targets = self._populations[1] 634 if len(pop_targets) is 0: 635 pop_targets[target_group] = 0 636 elif not pop_targets.has_key(target_group): 637 pop_targets[target_group] = numpy.sum([len(item) for item in pop_targets.keys()]) 638 639 640 def get(self, parameter_name, format): 641 """ 642 Get the values of a given attribute (weight or delay) for all 643 connections in this manager. 644 645 `parameter_name` -- name of the attribute whose values are wanted. 646 `format` -- "list" or "array". Array format implicitly assumes that all 647 connections belong to a single Projection. 648 649 Return a list or a 2D Numpy array. The array element X_ij contains the 650 attribute value for the connection from the ith neuron in the pre- 651 synaptic Population to the jth neuron in the post-synaptic Population, 652 if such a connection exists. If there are no such connections, X_ij will 653 be NaN. 654 """ 655 if self.parent is None: 656 raise Exception("Only implemented for connections created via a Projection object, not using connect()") 657 values = numpy.array([]) 658 for key in self.keys: 659 bc = self.brian_connections[key] 660 if parameter_name == "weight": 661 values = numpy.concatenate((values, bc.W.alldata / bc.weight_units)) 662 elif parameter_name == 'delay': 663 if isinstance(bc, brian.DelayConnection): 664 values = numpy.concatenate((values, bc.delay.alldata / ms)) 665 else: 666 data = bc.delay * bc.source.clock.dt * numpy.ones(bc.W.getnnz()) /ms 667 values = numpy.concatenate((values, data)) 668 else: 669 raise Exception("Getting parameters other than weight and delay not yet supported.") 670 671 if format == 'list': 672 values = values.tolist() 673 elif format == 'array': 674 values_arr = numpy.nan * numpy.ones((self.parent.pre.size, self.parent.post.size)) 675 sources, targets = self._indices 676 values_arr[sources, targets] = values 677 values = values_arr 678 else: 679 raise Exception("format must be 'list' or 'array', actually '%s'" % format) 680 return values 681 682 def set(self, name, value): 683 """ 684 Set connection attributes for all connections in this manager. 685 686 `name` -- attribute name 687 `value` -- the attribute numeric value, or a list/1D array of such 688 values of the same length as the number of local connections, 689 or a 2D array with the same dimensions as the connectivity 690 matrix (as returned by `get(format='array')`). 691 """ 692 if self.parent is None: 693 raise Exception("Only implemented for connections created via a Projection object, not using connect()") 694 for key in self.keys: 695 bc = self.brian_connections[key] 696 padding = 0 697 if name == 'weight': 698 M = bc.W 699 units = bc.weight_units 700 elif name == 'delay': 701 M = bc.delay 702 units = ms 703 else: 704 raise Exception("Setting parameters other than weight and delay not yet supported.") 705 value = value*units 706 if numpy.isscalar(value): 707 if (name == 'weight') or (name == 'delay' and isinstance(bc, brian.DelayConnection)): 708 for row in xrange(M.shape[0]): 709 M.set_row(row, value) 710 elif (name == 'delay' and isinstance(bc, brian.Connection)): 711 bc.delay = int(value / bc.source.clock.dt) 712 else: 713 raise Exception("Setting a non appropriate parameter") 714 elif isinstance(value, numpy.ndarray) and len(value.shape) == 2: 715 if (name == 'delay') and not isinstance(bc, brian.DelayConnection): 716 raise Exception("FastConnector have been used, and only fixed homogeneous delays are allowed") 717 address_gen = ((i, j) for i,row in enumerate(bc.W.rows) for j in row) 718 for (i,j) in address_gen: 719 M[i,j] = value[i,j] 720 elif core.is_listlike(value): 721 N = M.getnnz() 722 assert len(value[padding:padding+N]) == N 723 if (name == 'delay') and not isinstance(bc, brian.DelayConnection): 724 raise Exception("FastConnector have been used: only fixed homogeneous delays are allowed") 725 M.alldata = value 726 else: 727 raise Exception("Values must be scalars or lists/arrays") 728 padding += M.getnnz() 729 425 730 426 731 427 # --- Initialization, and module attributes ------------------------------------ -
trunk/src/common.py
r997 r998 64 64 DEFAULT_TIMESTEP = 0.1 65 65 DEFAULT_MIN_DELAY = DEFAULT_TIMESTEP 66 67 deprecated = core.deprecated 66 68 67 69 logger = logging.getLogger("PyNN") … … 1719 1721 def __len__(self): 1720 1722 """Return the total number of local connections.""" 1721 r eturn len(self.connection_manager)1723 raise NotImplementedError 1722 1724 1723 1725 def size(self, gather=True): … … 1738 1740 def __getitem__(self, i): 1739 1741 """Return the `i`th connection within the Projection.""" 1740 return self.connection_manager[i] 1742 raise NotImplementedError 1743 1744 def __iter__(self): 1745 """Return an iterator over all connections on the local MPI node.""" 1746 for i in range(len(self)): 1747 yield self[i] 1741 1748 1742 1749 # --- Methods for setting connection parameters --------------------------- 1743 1750 1751 def set(self, name, value): 1752 """ 1753 Set connection attributes for all connections on the local MPI node. 1754 1755 `name` -- attribute name 1756 1757 `value` -- the attribute numeric value, or a list/1D array of such 1758 values of the same length as the number of local connections, 1759 or a 2D array with the same dimensions as the connectivity 1760 matrix (as returned by `get(format='array')`). 1761 """ 1762 raise NotImplementedError 1763 1764 @deprecated("set('weight', w)") 1744 1765 def setWeights(self, w): 1745 1766 """ … … 1754 1775 # if post is an Assembly, some components might have cond-synapses, others curr, so need a more sophisticated check here 1755 1776 w = check_weight(w, self.synapse_type, is_conductance(self.post.local_cells[0])) 1756 self.connection_manager.set('weight', w) 1757 1777 self.set('weight', w) 1778 1779 @deprecated("set('weight', rand_distr)") 1758 1780 def randomizeWeights(self, rand_distr): 1759 1781 """ … … 1763 1785 # argument type. It could make for easier-to-read simulation code to 1764 1786 # give it a separate name, though. Comments? 1765 self.setWeights(rand_distr.next(len(self))) 1766 1787 self.set('weight', rand_distr.next(len(self))) 1788 1789 @deprecated("set('delay', d)") 1767 1790 def setDelays(self, d): 1768 1791 """ … … 1772 1795 connectivity matrix (as returned by `getDelays(format='array')`). 1773 1796 """ 1774 self.connection_manager.set('delay', d) 1775 1797 self.set('delay', d) 1798 1799 @deprecated("set('delay', rand_distr)") 1776 1800 def randomizeDelays(self, rand_distr): 1777 1801 """ 1778 1802 Set delays to random values taken from rand_distr. 1779 1803 """ 1780 self.setDelays(rand_distr.next(len(self))) 1781 1804 self.set('delay', rand_distr.next(len(self))) 1805 1806 @deprecated("set(param, value)") 1782 1807 def setSynapseDynamics(self, param, value): 1783 1808 """ … … 1785 1810 projection. 1786 1811 """ 1787 self.connection_manager.set(param, value) 1788 1812 self.set(param, value) 1813 1814 @deprecated("set(param, value)") 1789 1815 def randomizeSynapseDynamics(self, param, rand_distr): 1790 1816 """ 1791 1817 Set parameters of the synapse dynamics to values taken from rand_distr 1792 1818 """ 1793 self.set SynapseDynamics(param, rand_distr.next(len(self)))1819 self.set(param, rand_distr.next(len(self))) 1794 1820 1795 1821 # --- Methods for writing/reading information to/from file. --------------- 1796 1822 1823 def get(self, parameter_name, format, gather=True): 1824 """ 1825 Get the values of a given attribute (weight or delay) for all 1826 connections in this Projection. 1827 1828 `parameter_name` -- name of the attribute whose values are wanted. 1829 1830 `format` -- "list" or "array". Array format implicitly assumes that all 1831 connections belong to a single Projection. 1832 1833 Return a list or a 2D Numpy array. The array element X_ij contains the 1834 attribute value for the connection from the ith neuron in the pre- 1835 synaptic Population to the jth neuron in the post-synaptic Population, 1836 if a single such connection exists. If there are no such connections, 1837 X_ij will be NaN. If there are multiple such connections, the summed 1838 value will be given, which makes some sense for weights, but is 1839 pretty meaningless for delays. 1840 """ 1841 raise NotImplementedError 1842 1843 @deprecated("get('weight', format, gather)") 1797 1844 def getWeights(self, format='list', gather=True): 1798 1845 """ … … 1806 1853 if gather: 1807 1854 logger.error("getWeights() with gather=True not yet implemented") 1808 return self.connection_manager.get('weight', format) 1809 1855 return self.get('weight', format) 1856 1857 @deprecated("get('weight', format, gather)") 1810 1858 def getDelays(self, format='list', gather=True): 1811 1859 """ … … 1818 1866 if gather: 1819 1867 logger.error("getDelays() with gather=True not yet implemented") 1820 return self.connection_manager.get('delay', format) 1821 1868 return self.get('delay', format) 1869 1870 @deprecated("get(parameter_name, format, gather)") 1822 1871 def getSynapseDynamics(self, parameter_name, format='list', gather=True): 1823 1872 """ … … 1827 1876 if gather: 1828 1877 logger.error("getstandardmodels.SynapseDynamics() with gather=True not yet implemented") 1829 return self.connection_manager.get(parameter_name, format) 1830 1878 return self.get(parameter_name, format) 1879 1880 @deprecated("save('all', file, format, gather)") 1831 1881 def saveConnections(self, file, gather=True, compatible_output=True): 1832 1882 """ … … 1860 1910 file.close() 1861 1911 1912 @deprecated("save('weight', file, format, gather)") 1862 1913 def printWeights(self, file, format='list', gather=True): 1863 1914 """ … … 1865 1916 for non-existent connections. 1866 1917 """ 1867 weights = self.get Weights(format=format, gather=gather)1918 weights = self.get('weight', format=format, gather=gather) 1868 1919 1869 1920 if isinstance(file, basestring): … … 1875 1926 file.close() 1876 1927 1928 @deprecated("save('delay', file, format, gather)") 1877 1929 def printDelays(self, file, format='list', gather=True): 1878 1930 """ … … 1890 1942 file.close() 1891 1943 1944 @deprecated("numpy.histogram()") 1892 1945 def weightHistogram(self, min=None, max=None, nbins=10): 1893 1946 """ -
trunk/src/connectors.py
r957 r998 346 346 347 347 if len(targets) > 0: 348 self.projection. connection_manager.connect(src, targets.tolist(), weights, delays)348 self.projection._divergent_connect(src, targets.tolist(), weights, delays) 349 349 350 350 … … 526 526 ## to use a convergent_connect method, instead of a divergent_connect one 527 527 #idx = eval(tests) 528 #projection. connection_manager.connect(src, tgts[idx].tolist(), weights[idx], delays[idx])529 projection. connection_manager.connect(src, tgts.tolist(), weights, delays)528 #projection._divergent_connect(src, tgts[idx].tolist(), weights[idx], delays[idx]) 529 projection._divergent_connect(src, tgts.tolist(), weights, delays) 530 530 self.progression(count) 531 531 count += 1 … … 646 646 647 647 if len(targets) > 0: 648 projection. connection_manager.connect(src, targets.tolist(), weights, delays)648 projection._divergent_connect(src, targets.tolist(), weights, delays) 649 649 650 650 self.progression(count) … … 731 731 732 732 for src, w, d in zip(sources, weights, delays): 733 projection. connection_manager.connect(src, tgt, w, d)733 projection._divergent_connect(src, tgt, w, d) 734 734 735 735 self.progression(count) … … 776 776 for tgt, src, w, d in zip(projection.post.local_cells, sources, weights, delays): 777 777 # the float is in case the values are of type numpy.float64, which NEST chokes on 778 projection. connection_manager.connect(src, [tgt], [float(w)], [float(d)])778 projection._divergent_connect(src, [tgt], [float(w)], [float(d)]) 779 779 self.progression(count) 780 780 count += 1 … … 859 859 860 860 if len(targets) > 0: 861 self.projection. connection_manager.connect(src, targets.tolist(), weights, delays)861 self.projection._divergent_connect(src, targets.tolist(), weights, delays) 862 862 863 863 def connect(self, projection): … … 934 934 # Connection-set with arity 2 935 935 for (i, j, weight, delay) in c: 936 projection. connection_manager.connect (i, [j], weight, delay)936 projection._divergent_connect (i, [j], weight, delay) 937 937 elif CSAConnector.isConstant (self.weights) \ 938 938 and CSAConnector.isConstant (self.delays): 939 939 # Mask with constant weights and delays 940 940 for (i, j) in c: 941 projection. connection_manager.connect (i, [j], self.weights, self.delays)941 projection._divergent_connect (i, [j], self.weights, self.delays) 942 942 else: 943 943 # Mask with weights and/or delays iterable … … 949 949 delays = CSAConnector.constantIterator (delays) 950 950 for (i, j), weight, delay in zip (c, weights, delays): 951 projection. connection_manager.connect (i, [j], weight, delay)951 projection._divergent_connect (i, [j], weight, delay) -
trunk/src/connectors2.py
r741 r998 217 217 218 218 if len(sources) > 0: 219 self.projection. connection_manager.convergent_connect(sources.tolist(), tgt, weights, delays)219 self.projection._convergent_connect(sources.tolist(), tgt, weights, delays) 220 220 221 221 … … 364 364 src = projection.pre[tuple(src)] 365 365 tgt = projection.post[tuple(tgt)] 366 projection. connection_manager.connect(src, [tgt], weight, delay)366 projection._divergent_connect(src, [tgt], weight, delay) 367 367 self.progression(count) 368 368 … … 487 487 488 488 if len(targets) > 0: 489 projection. connection_manager.connect(src, targets.tolist(), weights, delays)489 projection._divergent_connect(src, targets.tolist(), weights, delays) 490 490 491 491 self.progression(count) … … 568 568 delays = delays_generator.get(n, distance_matrix, create) 569 569 if len(sources) > 0: 570 projection. connection_manager.convergent_connect(sources, tgt, weights, delays)570 projection._convergent_connect(sources, tgt, weights, delays) 571 571 self.progression(count) 572 572 … … 616 616 617 617 # the float is in case the values are of type numpy.float64, which NEST chokes on 618 projection. connection_manager.connect(src, [tgt], float(w), float(d))618 projection._divergent_connect(src, [tgt], float(w), float(d)) 619 619 self.progression(count) 620 620 count += 1 … … 682 682 683 683 if len(targets) > 0: 684 self.projection. connection_manager.connect(src, targets.tolist(), weights, delays)684 self.projection._divergent_connect(src, targets.tolist(), weights, delays) 685 685 686 686 def connect(self, projection): -
trunk/src/core.py
r957 r998 11 11 from copy import copy, deepcopy 12 12 import functools 13 import warnings 13 14 14 15 def is_listlike(obj): … … 275 276 """Support instance methods.""" 276 277 return functools.partial(self.__call__, obj) 278 279 class deprecated(object): 280 """ 281 Decorator to mark functions/methods as deprecated. Emits a warning when 282 function is called and suggests a replacement. 283 """ 284 285 def __init__(self, replacement=''): 286 self.replacement = replacement 287 288 def __call__(self, func): 289 def new_func(*args, **kwargs): 290 msg = "%s() is deprecated, and will be removed in a future release." % func.__name__ 291 if self.replacement: 292 msg += " Use %s instead." % self.replacement 293 warnings.warn(msg, category=DeprecationWarning) 294 return func(*args, **kwargs) 295 new_func.__name__ = func.__name__ 296 new_func.__doc__ = func.__doc__ 297 new_func.__dict__.update(func.__dict__) 298 return new_func -
trunk/src/moose/__init__.py
r957 r998 16 16 import os.path 17 17 from pyNN.moose import simulator 18 from pyNN import common, recording 18 from pyNN import common, recording, core 19 19 common.simulator = simulator 20 20 recording.simulator = simulator … … 149 149 assert synapse_dynamics is None, "don't yet handle synapse dynamics" 150 150 self.synapse_model = None 151 self.connection_manager = simulator.ConnectionManager(self.synapse_type, 152 self.synapse_model, 153 parent=self) 151 self.connections = [] 152 154 153 # Create connections 155 154 method.connect(self) 156 self.connections = self.connection_manager157 155 Projection.nProj += 1 158 156 159 157 def _divergent_connect(self, source, targets, weights, delays): 158 """ 159 Connect a neuron to one or more other neurons with a static connection. 160 161 `source` -- the ID of the pre-synaptic cell. 162 `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. 163 `weight` -- a list/1D array of connection weights, or a single weight. 164 Must have the same length as `targets`. 165 `delays` -- a list/1D array of connection delays, or a single delay. 166 Must have the same length as `targets`. 167 """ 168 if not isinstance(source, int) or source > simulator.state.gid_counter or source < 0: 169 errmsg = "Invalid source ID: %s (gid_counter=%d)" % (source, simulator.state.gid_counter) 170 raise errors.ConnectionError(errmsg) 171 if not core.is_listlike(targets): 172 targets = [targets] 173 174 weights = weights*1000.0 # scale units 175 if isinstance(weights, float): 176 weights = [weights] 177 if isinstance(delays, float): 178 delays = [delays] 179 assert len(targets) > 0 180 # need to scale weights for appropriate units 181 for target, weight, delay in zip(targets, weights, delays): 182 if target.local: 183 if not isinstance(target, common.IDMixin): 184 raise errors.ConnectionError("Invalid target ID: %s" % target) 185 if self.synapse_type == "excitatory": 186 synapse_object = target._cell.esyn 187 elif self.synapse_type == "inhibitory": 188 synapse_object = target._cell.isyn 189 else: 190 synapse_object = getattr(target._cell, self.synapse_type) 191 source._cell.source.connect('event', synapse_object, 'synapse') 192 synapse_object.n_incoming_connections += 1 193 index = synapse_object.n_incoming_connections - 1 194 synapse_object.setWeight(index, weight) 195 synapse_object.setDelay(index, delay) 196 self.connections.append((source, target, index)) 197 160 198 # ============================================================================== 161 199 # Low-level API for creating, connecting and recording from individual neurons -
trunk/src/moose/simulator.py
r957 r998 96 96 setattr(self._cell, name, val) 97 97 98 99 class ConnectionManager(object):100 """101 Manage synaptic connections, providing methods for creating, listing,102 accessing individual connections.103 """104 105 def __init__(self, synapse_type, synapse_model=None, parent=None):106 """107 Create a new ConnectionManager.108 109 `synapse_model` -- either None or 'Tsodyks-Markram'.110 `parent` -- the parent `Projection`111 """112 assert parent is not None113 self.connections = []114 self.parent = parent115 self.synapse_type = synapse_type116 self.synapse_model = synapse_model117 118 def connect(self, source, targets, weights, delays):119 """120 Connect a neuron to one or more other neurons with a static connection.121 122 `source` -- the ID of the pre-synaptic cell.123 `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID.124 `weight` -- a list/1D array of connection weights, or a single weight.125 Must have the same length as `targets`.126 `delays` -- a list/1D array of connection delays, or a single delay.127 Must have the same length as `targets`.128 """129 if not isinstance(source, int) or source > state.gid_counter or source < 0:130 errmsg = "Invalid source ID: %s (gid_counter=%d)" % (source, state.gid_counter)131 raise errors.ConnectionError(errmsg)132 if not core.is_listlike(targets):133 targets = [targets]134 135 weights = weights*1000.0 # scale units136 if isinstance(weights, float):137 weights = [weights]138 if isinstance(delays, float):139 delays = [delays]140 assert len(targets) > 0141 # need to scale weights for appropriate units142 for target, weight, delay in zip(targets, weights, delays):143 if target.local:144 if not isinstance(target, common.IDMixin):145 raise errors.ConnectionError("Invalid target ID: %s" % target)146 if self.synapse_type == "excitatory":147 synapse_object = target._cell.esyn148 elif self.synapse_type == "inhibitory":149 synapse_object = target._cell.isyn150 else:151 synapse_object = getattr(target._cell, self.synapse_type)152 source._cell.source.connect('event', synapse_object, 'synapse')153 synapse_object.n_incoming_connections += 1154 index = synapse_object.n_incoming_connections - 1155 synapse_object.setWeight(index, weight)156 synapse_object.setDelay(index, delay)157 self.connections.append((source, target, index))158 159 98 state = _State() # a Singleton, so only a single instance ever exists 160 99 del _State -
trunk/src/nemo/__init__.py
r957 r998 191 191 else: 192 192 self._plasticity_model = "static_synapse" 193 194 self.connection_manager = simulator.ConnectionManager(self.synapse_type, self._plasticity_model, parent=self) 195 self.connections = self.connection_manager 193 194 self.synapse_model = self._plasticity_model 195 self._sources = [] 196 self._is_plastic = False 197 if self.synapse_model is "stdp_synapse": 198 self._is_plastic = True 199 self._connections = None 200 196 201 method.connect(self) 202 203 def __getitem__(self, i): 204 if isinstance(i, int): 205 if i < len(self): 206 return simulator.Connection(self.connections[i]) 207 else: 208 raise IndexError("%d > %d" % (i, len(self)-1)) 209 elif isinstance(i, slice): 210 if i.stop < len(self): 211 return [simulator.Connection(self.connections[j]) for j in range(i.start, i.stop, i.step or 1)] 212 else: 213 raise IndexError("%d > %d" % (i.stop, len(self)-1)) 214 215 def __len__(self): 216 """Return the number of connections on the local MPI node.""" 217 return len(self.connections) 218 219 @property 220 def connections(self): 221 if self._connections is None: 222 self._connections = [] 223 for source in numpy.unique(self.sources): 224 self._connections += list(simulator.state.net.get_synapses_from(source)) 225 return self._connections 226 227 def _divergent_connect(self, source, targets, weights, delays): 228 """ 229 Connect a neuron to one or more other neurons with a static connection. 230 231 `source` -- the ID of the pre-synaptic cell. 232 `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. 233 `weight` -- a list/1D array of connection weights, or a single weight. 234 Must have the same length as `targets`. 235 `delays` -- a list/1D array of connection delays, or a single delay. 236 Must have the same length as `targets`. 237 """ 238 #print "connecting", source, "to", targets, "with weights", weights, "and delays", delays 239 if not core.is_listlike(targets): 240 targets = [targets] 241 if isinstance(weights, float): 242 weights = [weights] 243 if isinstance(delays, float): 244 delays = [delays] 245 assert len(targets) > 0 246 if not isinstance(source, common.IDMixin): 247 raise errors.ConnectionError("source should be an ID object, actually %s" % type(source)) 248 for target in targets: 249 if not isinstance(target, common.IDMixin): 250 raise errors.ConnectionError("Invalid target ID: %s" % target) 251 assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets),len(weights),len(delays)) 252 synapse_type = self.synapse_type or "excitatory" 253 delays = numpy.array(delays).astype(int).tolist() 254 if isinstance(weights, numpy.ndarray): 255 weights = weights.tolist() 256 source = int(source) 257 synapses = simulator.state.net.add_synapse(source, targets, delays, weights, self.is_plastic) 258 self._sources.append(source) 259 260 def get(self, parameter_name, format, gather=True): 261 """ 262 Get the values of a given attribute (weight or delay) for all 263 connections in this Projection. 264 265 `parameter_name` -- name of the attribute whose values are wanted. 266 `format` -- "list" or "array". Array format implicitly assumes that all 267 connections belong to a single Projection. 268 269 Return a list or a 2D Numpy array. The array element X_ij contains the 270 attribute value for the connection from the ith neuron in the pre- 271 synaptic Population to the jth neuron in the post-synaptic Population, 272 if such a connection exists. If there are no such connections, X_ij will 273 be NaN. 274 """ 275 if parameter_name not in ('weight', 'delay'): 276 raise Exception("Only weights and delays can be accessed by Nemo") 277 278 if format == 'list': 279 if parameter_name is "weight": 280 values = list(simulator.state.sim.get_synapse_weight(self.connections)) 281 if parameter_name is "delay": 282 values = list(simulator.state.sim.get_synapse_delay(self.connections)) 283 elif format == 'array': 284 value_arr = numpy.nan * numpy.ones((self.pre.size, self.post.size)) 285 sources = [i.source for i in self] 286 synapses = [i.synapse for i in self] 287 targets = list(simulator.state.sim.get_targets(synapses)) 288 addr = self.pre.id_to_index(sources), self.post.id_to_index(targets) 289 if parameter_name is "weight": 290 data = list(simulator.state.sim.get_weights(synapses)) 291 if parameter_name is "delay": 292 data = list(simulator.state.sim.get_delays(synapses)) 293 for idx in xrange(len(data)): 294 address = addr[0][idx], addr[1][idx] 295 if numpy.isnan(value_arr[address]): 296 value_arr[address] = data[idx] 297 else: 298 value_arr[address] += data[idx] 299 values = value_arr 300 else: 301 raise Exception("format must be 'list' or 'array', actually '%s'" % format) 302 return values 197 303 198 304 def saveConnections(self, file, gather=True, compatible_output=True): … … 205 311 file = files.StandardTextFile(file, mode='w') 206 312 207 lines = numpy.empty((len(self .connection_manager), 4))208 lines[:,0] = [i.source for i in self .connection_manager]209 lines[:,1] = [i.target for i in self .connection_manager]313 lines = numpy.empty((len(self), 4)) 314 lines[:,0] = [i.source for i in self] 315 lines[:,1] = [i.target for i in self] 210 316 if compatible_output: 211 317 lines[:,0] = self.pre.id_to_index(lines[:, 0]) 212 318 lines[:,1] = self.post.id_to_index(lines[:, 1]) 213 synapses = [i.synapse for i in self .connection_manager]319 synapses = [i.synapse for i in self] 214 320 lines[:,2] = list(simulator.state.sim.get_weights(synapses)) 215 321 lines[:,3] = list(simulator.state.sim.get_delays(synapses)) -
trunk/src/nemo/simulator.py
r977 r998 225 225 weight = property(_get_weight, _set_weight) 226 226 delay = property(_get_delay, _set_delay) 227 228 229 class ConnectionManager(object): 230 """ 231 Manage synaptic connections, providing methods for creating, listing, 232 accessing individual connections. 233 """ 234 235 def __init__(self, synapse_type, synapse_model=None, parent=None): 236 """ 237 Create a new ConnectionManager. 238 239 `synapse_type` -- the 'physiological type' of the synapse, e.g. 240 'excitatory' or 'inhibitory',or any other key in the 241 `synapses` attibute of the celltype class. 242 `synapse_model` -- not used. Present for consistency with other simulators. 243 `parent` -- the parent `Projection`, if any. 244 """ 245 self.synapse_type = synapse_type 246 self.synapse_model = synapse_model 247 self.parent = parent 248 self.sources = [] 249 self.is_plastic = False 250 if self.synapse_model is "stdp_synapse": 251 self.is_plastic = True 252 self._connections = None 253 254 def __getitem__(self, i): 255 if isinstance(i, int): 256 if i < len(self): 257 return Connection(self.connections[i]) 258 else: 259 raise IndexError("%d > %d" % (i, len(self)-1)) 260 elif isinstance(i, slice): 261 if i.stop < len(self): 262 return [Connection(self.connections[j]) for j in range(i.start, i.stop, i.step or 1)] 263 else: 264 raise IndexError("%d > %d" % (i.stop, len(self)-1)) 265 266 def __len__(self): 267 """Return the number of connections on the local MPI node.""" 268 return len(self.connections) 269 270 def __iter__(self): 271 """Return an iterator over all connections on the local MPI node.""" 272 for i in range(len(self)): 273 yield self[i] 274 275 @property 276 def connections(self): 277 if self._connections is None: 278 self._connections = [] 279 for source in numpy.unique(self.sources): 280 self._connections += list(state.net.get_synapses_from(source)) 281 return self._connections 282 283 def connect(self, source, targets, weights, delays): 284 """ 285 Connect a neuron to one or more other neurons with a static connection. 286 287 `source` -- the ID of the pre-synaptic cell. 288 `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. 289 `weight` -- a list/1D array of connection weights, or a single weight. 290 Must have the same length as `targets`. 291 `delays` -- a list/1D array of connection delays, or a single delay. 292 Must have the same length as `targets`. 293 """ 294 #print "connecting", source, "to", targets, "with weights", weights, "and delays", delays 295 if not core.is_listlike(targets): 296 targets = [targets] 297 if isinstance(weights, float): 298 weights = [weights] 299 if isinstance(delays, float): 300 delays = [delays] 301 assert len(targets) > 0 302 if not isinstance(source, common.IDMixin): 303 raise errors.ConnectionError("source should be an ID object, actually %s" % type(source)) 304 for target in targets: 305 if not isinstance(target, common.IDMixin): 306 raise errors.ConnectionError("Invalid target ID: %s" % target) 307 assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets),len(weights),len(delays)) 308 synapse_type = self.synapse_type or "excitatory" 309 delays = numpy.array(delays).astype(int).tolist() 310 if isinstance(weights, numpy.ndarray): 311 weights = weights.tolist() 312 source = int(source) 313 synapses = state.net.add_synapse(source, targets, delays, weights, self.is_plastic) 314 self.sources.append(source) 315 316 def get(self, parameter_name, format): 317 """ 318 Get the values of a given attribute (weight or delay) for all 319 connections in this manager. 320 321 `parameter_name` -- name of the attribute whose values are wanted. 322 `format` -- "list" or "array". Array format implicitly assumes that all 323 connections belong to a single Projection. 324 325 Return a list or a 2D Numpy array. The array element X_ij contains the 326 attribute value for the connection from the ith neuron in the pre- 327 synaptic Population to the jth neuron in the post-synaptic Population, 328 if such a connection exists. If there are no such connections, X_ij will 329 be NaN. 330 """ 331 if parameter_name not in ('weight', 'delay'): 332 raise Exception("Only weights and delays can be accessed by Nemo") 333 334 if format == 'list': 335 if parameter_name is "weight": 336 values = list(state.sim.get_synapse_weight(self.connections)) 337 if parameter_name is "delay": 338 values = list(state.sim.get_synapse_delay(self.connections)) 339 elif format == 'array': 340 value_arr = numpy.nan * numpy.ones((self.parent.pre.size, self.parent.post.size)) 341 sources = [i.source for i in self] 342 synapses = [i.synapse for i in self] 343 targets = list(state.sim.get_targets(synapses)) 344 addr = self.parent.pre.id_to_index(sources), self.parent.post.id_to_index(targets) 345 if parameter_name is "weight": 346 data = list(state.sim.get_weights(synapses)) 347 if parameter_name is "delay": 348 data = list(state.sim.get_delays(synapses)) 349 for idx in xrange(len(data)): 350 address = addr[0][idx], addr[1][idx] 351 if numpy.isnan(value_arr[address]): 352 value_arr[address] = data[idx] 353 else: 354 value_arr[address] += data[idx] 355 values = value_arr 356 else: 357 raise Exception("format must be 'list' or 'array', actually '%s'" % format) 358 return values 359 360 def set(self, name, value): 361 """ 362 Set connection attributes for all connections in this manager. 363 364 `name` -- attribute name 365 `value` -- the attribute numeric value, or a list/1D array of such 366 values of the same length as the number of local connections, 367 or a 2D array with the same dimensions as the connectivity 368 matrix (as returned by `get(format='array')`). 369 """ 370 if self.parent is None: 371 raise Exception("Only implemented for connections created via a Projection object, not using connect()") 372 pass 227 373 228 374 229 # --- Initialization, and module attributes ------------------------------------ -
trunk/src/nest/__init__.py
r991 r998 133 133 'min_delay': min_delay, 134 134 'max_delay': max_delay}) 135 simulator.connection_managers = []136 135 simulator.reset() 137 136 … … 325 324 else: 326 325 synapse_dynamics = NativeSynapseDynamics("static_synapse") 327 self.synapse_model = synapse_dynamics._get_nest_synapse_model("projection_%d" % Projection.nProj) 326 synapse_model = synapse_dynamics._get_nest_synapse_model("projection_%d" % Projection.nProj) 327 if synapse_model is None: 328 self.synapse_model = 'static_synapse_%s' % id(self) 329 nest.CopyModel('static_synapse', self.synapse_model) 330 else: 331 self.synapse_model = synapse_model 332 self._sources = [] 333 self._connections = None 328 334 Projection.nProj += 1 329 330 self.connection_manager = simulator.ConnectionManager(self.synapse_type, 331 self.synapse_model, 332 parent=self) 333 335 334 336 # Create connections 335 337 method.connect(self) 336 self.connection_manager._set_tsodyks_params() 337 self.connections = self.connection_manager 338 338 339 def __getitem__(self, i): 340 """Return the `i`th connection on the local MPI node.""" 341 if isinstance(i, int): 342 if i < len(self): 343 return simulator.Connection(self, i) 344 else: 345 raise IndexError("%d > %d" % (i, len(self)-1)) 346 elif isinstance(i, slice): 347 if i.stop < len(self): 348 return [simulator.Connection(self, j) for j in range(i.start, i.stop, i.step or 1)] 349 else: 350 raise IndexError("%d > %d" % (i.stop, len(self)-1)) 351 352 def __len__(self): 353 """Return the number of connections on the local MPI node.""" 354 return nest.GetDefaults(self.synapse_model)['num_connections'] 355 356 @property 357 def connections(self): 358 if self._connections is None: 359 self._sources = numpy.unique(self._sources) 360 self._connections = nest.FindConnections(self._sources, synapse_type=self.synapse_model) 361 return self._connections 362 363 def _set_tsodyks_params(self): 364 if 'tsodyks' in self.synapse_model: # there should be a better way to do this. In particular, if the synaptic time constant is changed 365 # after creating the Projection, tau_psc ought to be changed as well. 366 assert self.synapse_type in ('excitatory', 'inhibitory'), "only basic synapse types support Tsodyks-Markram connections" 367 logger.debug("setting tau_psc") 368 targets = nest.GetStatus(self.connections, 'target') 369 if self.synapse_type == 'inhibitory': 370 param_name = self.post.local_cells[0].celltype.translations['tau_syn_I']['translated_name'] 371 if self.synapse_type == 'excitatory': 372 param_name = self.post.local_cells[0].celltype.translations['tau_syn_E']['translated_name'] 373 tau_syn = nest.GetStatus(targets, (param_name)) 374 nest.SetStatus(self.connections, 'tau_psc', tau_syn) 375 376 def _divergent_connect(self, source, targets, weights, delays): 377 """ 378 Connect a neuron to one or more other neurons. 379 380 `source` -- the ID of the pre-synaptic cell. 381 `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. 382 `weight` -- a list/1D array of connection weights, or a single weight. 383 Must have the same length as `targets`. 384 `delays` -- a list/1D array of connection delays, or a single delay. 385 Must have the same length as `targets`. 386 """ 387 # are we sure the targets are all on the current node? 388 if core.is_listlike(source): 389 assert len(source) == 1 390 source = source[0] 391 if not core.is_listlike(targets): 392 targets = [targets] 393 assert len(targets) > 0 394 395 if self.synapse_type not in targets[0].celltype.synapse_types: 396 raise errors.ConnectionError("User gave synapse_type=%s, synapse_type must be one of: %s" % ( self.synapse_type, "'"+"', '".join(st for st in targets[0].celltype.synapse_types or ['*No connections supported*']))+"'" ) 397 weights = numpy.array(weights)*1000.0 # weights should be in nA or uS, but iaf_neuron uses pA and iaf_cond_neuron uses nS. 398 # Using convention in this way is not ideal. We should 399 # be able to look up the units used by each model somewhere. 400 if self.synapse_type == 'inhibitory' and common.is_conductance(targets[0]): 401 weights = -1*weights # NEST wants negative values for inhibitory weights, even if these are conductances 402 if isinstance(weights, numpy.ndarray): 403 weights = weights.tolist() 404 elif isinstance(weights, float): 405 weights = [weights] 406 if isinstance(delays, numpy.ndarray): 407 delays = delays.tolist() 408 elif isinstance(delays, float): 409 delays = [delays] 410 411 if targets[0].celltype.standard_receptor_type: 412 try: 413 nest.DivergentConnect([source], targets, weights, delays, self.synapse_model) 414 except nest.NESTError, e: 415 raise errors.ConnectionError("%s. source=%s, targets=%s, weights=%s, delays=%s, synapse model='%s'" % ( 416 e, source, targets, weights, delays, self.synapse_model)) 417 else: 418 for target, w, d in zip(targets, weights, delays): 419 nest.Connect([source], [target], {'weight': w, 'delay': d, 'receptor_type': target.celltype.get_receptor_type(self.synapse_type)}) 420 self._connections = None # reset the caching of the connection list, since this will have to be recalculated 421 self._sources.append(source) 422 423 def _convergent_connect(self, sources, target, weights, delays): 424 """ 425 Connect one or more neurons to a single post-synaptic neuron. 426 `sources` -- a list/1D array of pre-synaptic cell IDs, or a single ID. 427 `target` -- the ID of the post-synaptic cell. 428 `weight` -- a list/1D array of connection weights, or a single weight. 429 Must have the same length as `targets`. 430 `delays` -- a list/1D array of connection delays, or a single delay. 431 Must have the same length as `targets`. 432 """ 433 # are we sure the targets are all on the current node? 434 if core.is_listlike(target): 435 assert len(target) == 1 436 target = target[0] 437 if not core.is_listlike(sources): 438 sources = [sources] 439 assert len(sources) > 0, sources 440 if self.synapse_type not in ('excitatory', 'inhibitory', None): 441 raise errors.ConnectionError("synapse_type must be 'excitatory', 'inhibitory', or None (equivalent to 'excitatory')") 442 weights = numpy.array(weights)*1000.0# weights should be in nA or uS, but iaf_neuron uses pA and iaf_cond_neuron uses nS. 443 # Using convention in this way is not ideal. We should 444 # be able to look up the units used by each model somewhere. 445 if self.synapse_type == 'inhibitory' and common.is_conductance(target): 446 weights = -1*weights # NEST wants negative values for inhibitory weights, even if these are conductances 447 if isinstance(weights, numpy.ndarray): 448 weights = weights.tolist() 449 elif isinstance(weights, float): 450 weights = [weights] 451 if isinstance(delays, numpy.ndarray): 452 delays = delays.tolist() 453 elif isinstance(delays, float): 454 delays = [delays] 455 456 try: 457 nest.ConvergentConnect(sources, [target], weights, delays, self.synapse_model) 458 except nest.NESTError, e: 459 raise errors.ConnectionError("%s. sources=%s, target=%s, weights=%s, delays=%s, synapse model='%s'" % ( 460 e, sources, target, weights, delays, self.synapse_model)) 461 self._connections = None # reset the caching of the connection list, since this will have to be recalculated 462 self._sources.extend(sources) 463 464 def set(self, name, value): 465 """ 466 Set connection attributes for all connections on the local MPI node. 467 468 `name` -- attribute name 469 470 `value` -- the attribute numeric value, or a list/1D array of such 471 values of the same length as the number of local connections, 472 or a 2D array with the same dimensions as the connectivity 473 matrix (as returned by `get(format='array')`). 474 """ 475 if not (numpy.isscalar(value) or core.is_listlike(value)): 476 raise TypeError("Argument should be a numeric type (int, float...), a list, or a numpy array.") 477 478 if isinstance(value, numpy.ndarray) and len(value.shape) == 2: 479 value_list = [] 480 connection_parameters = nest.GetStatus(self.connections, ('source', 'target')) 481 for conn in connection_parameters: 482 addr = self.pre.id_to_index(conn['source']), self.post.id_to_index(conn['target']) 483 try: 484 val = value[addr] 485 except IndexError, e: 486 raise IndexError("%s. addr=%s" % (e, addr)) 487 if numpy.isnan(val): 488 raise Exception("Array contains no value for synapse from %d to %d" % (c.source, c.target)) 489 else: 490 value_list.append(val) 491 value = value_list 492 if core.is_listlike(value): 493 value = numpy.array(value) 494 else: 495 value = float(value) 496 497 if name == 'weight': 498 value *= 1000.0 499 if self.synapse_type == 'inhibitory' and common.is_conductance(self[0].target): 500 value *= -1 # NEST wants negative values for inhibitory weights, even if these are conductances 501 elif name == 'delay': 502 pass 503 else: 504 #translation = self.synapse_dynamics.reverse_translate({name: value}) 505 #name, value = translation.items()[0] 506 translated_name = None 507 if self.synapse_dynamics.fast: 508 if name in self.synapse_dynamics.fast.translations: 509 translated_name = self.synapse_dynamics.fast.translations[name]["translated_name"] # a hack 510 if translated_name is None: 511 if self.synapse_dynamics.slow: 512 for component_name in "timing_dependence", "weight_dependence", "voltage_dependence": 513 component = getattr(self.synapse_dynamics.slow, component_name) 514 if component and name in component.translations: 515 translated_name = component.translations[name]["translated_name"] 516 break 517 if translated_name: 518 name = translated_name 519 520 i = 0 521 try: 522 nest.SetStatus(self.connections, name, value) 523 except nest.NESTError, e: 524 n = 1 525 if hasattr(value, '__len__'): 526 n = len(value) 527 raise Exception("%s. Trying to set %d values." % (e, n)) 339 528 340 529 def saveConnections(self, file, gather=True, compatible_output=True): … … 348 537 file = files.StandardTextFile(file, mode='w') 349 538 350 lines = nest.GetStatus(self.connection _manager.connections, ('source', 'target', 'weight', 'delay'))539 lines = nest.GetStatus(self.connections, ('source', 'target', 'weight', 'delay')) 351 540 352 541 if gather == True and num_processes() > 1: … … 386 575 self.setDelays(rand_distr.next(len(self), mask_local=False)) 387 576 577 def get(self, parameter_name, format, gather=True): 578 """ 579 Get the values of a given attribute (weight or delay) for all 580 connections in this Projection. 581 582 `parameter_name` -- name of the attribute whose values are wanted. 583 584 `format` -- "list" or "array". Array format implicitly assumes that all 585 connections belong to a single Projection. 586 587 Return a list or a 2D Numpy array. The array element X_ij contains the 588 attribute value for the connection from the ith neuron in the pre- 589 synaptic Population to the jth neuron in the post-synaptic Population, 590 if a single such connection exists. If there are no such connections, 591 X_ij will be NaN. If there are multiple such connections, the summed 592 value will be given, which makes some sense for weights, but is 593 pretty meaningless for delays. 594 """ 595 596 if parameter_name not in ('weight', 'delay'): 597 translated_name = None 598 if self.synapse_dynamics.fast and parameter_name in self.synapse_dynamics.fast.translations: 599 translated_name = self.synapse_dynamics.fast.translations[parameter_name]["translated_name"] # this is a hack that works because there are no units conversions 600 elif self.synapse_dynamics.slow: 601 for component_name in "timing_dependence", "weight_dependence", "voltage_dependence": 602 component = getattr(self.synapse_dynamics.slow, component_name) 603 if component and parameter_name in component.translations: 604 translated_name = component.translations[parameter_name]["translated_name"] 605 break 606 if translated_name: 607 parameter_name = translated_name 608 else: 609 raise Exception("synapse type does not have an attribute '%s', or else this attribute is not accessible." % parameter_name) 610 if format == 'list': 611 values = nest.GetStatus(self.connections, parameter_name) 612 if parameter_name == "weight": 613 values = [0.001*val for val in values] 614 elif format == 'array': 615 value_arr = numpy.nan * numpy.ones((self.pre.size, self.post.size)) 616 connection_parameters = nest.GetStatus(self.connections, ('source', 'target', parameter_name)) 617 for conn in connection_parameters: 618 # (offset is always 0,0 for connections created with connect()) 619 src, tgt, value = conn 620 addr = self.pre.id_to_index(src), self.post.id_to_index(tgt) 621 if numpy.isnan(value_arr[addr]): 622 value_arr[addr] = value 623 else: 624 value_arr[addr] += value 625 if parameter_name == 'weight': 626 value_arr *= 0.001 627 if self.synapse_type == 'inhibitory' and common.is_conductance(self[0].target): 628 value_arr *= -1 # NEST uses negative values for inhibitory weights, even if these are conductances 629 values = value_arr 630 else: 631 raise Exception("format must be 'list' or 'array', actually '%s'" % format) 632 return values 633 388 634 Space = space.Space 389 635 -
trunk/src/nest/connectors.py
r970 r998 92 92 93 93 if len(sources) > 0: 94 self.projection. connection_manager.convergent_connect(sources.tolist(), tgt, weights, delays)94 self.projection._convergent_connect(sources.tolist(), tgt, weights, delays) 95 95 96 96 -
trunk/src/nest/simulator.py
r991 r998 4 4 implementation of the API. 5 5 6 Functions and classes us eable by the common implementation:6 Functions and classes usable by the common implementation: 7 7 8 8 Functions: 9 create_cells()10 9 run() 11 10 … … 13 12 ID 14 13 Recorder 15 ConnectionManager16 14 Connection 17 15 … … 39 37 recorder_list = [] 40 38 recording_devices = [] 41 connection_managers = []42 39 43 40 global net … … 211 208 212 209 213 class ConnectionManager:214 """215 Manage synaptic connections, providing methods for creating, listing,216 accessing individual connections.217 """218 219 def __init__(self, synapse_type, synapse_model=None, parent=None):220 """221 Create a new ConnectionManager.222 223 `synapse_type` -- the 'physiological type' of the synapse, e.g.224 'excitatory' or 'inhibitory'225 `synapse_model` -- the NEST synapse model to be used for all connections226 created with this manager.227 `parent` -- the parent `Projection`, if any.228 """229 global connection_managers230 self.sources = []231 if synapse_model is None:232 self.synapse_model = 'static_synapse_%s' % id(self)233 nest.CopyModel('static_synapse', self.synapse_model)234 else:235 self.synapse_model = synapse_model236 self.synapse_type = synapse_type237 self.parent = parent238 if parent is not None:239 assert parent.synapse_model == self.synapse_model240 self._connections = None241 connection_managers.append(self)242 243 def __getitem__(self, i):244 """Return the `i`th connection on the local MPI node."""245 if isinstance(i, int):246 if i < len(self):247 return Connection(self, i)248 else:249 raise IndexError("%d > %d" % (i, len(self)-1))250 elif isinstance(i, slice):251 if i.stop < len(self):252 return [Connection(self, j) for j in range(i.start, i.stop, i.step or 1)]253 else:254 raise IndexError("%d > %d" % (i.stop, len(self)-1))255 256 def __len__(self):257 """Return the number of connections on the local MPI node."""258 return nest.GetDefaults(self.synapse_model)['num_connections']259 260 def __iter__(self):261 """Return an iterator over all connections on the local MPI node."""262 for i in range(len(self)):263 yield self[i]264 265 @property266 def connections(self):267 if self._connections is None:268 self.sources = numpy.unique(self.sources)269 self._connections = nest.FindConnections(self.sources, synapse_type=self.synapse_model)270 return self._connections271 272 def _set_tsodyks_params(self):273 if 'tsodyks' in self.synapse_model: # there should be a better way to do this. In particular, if the synaptic time constant is changed274 # after creating the Projection, tau_psc ought to be changed as well.275 assert self.synapse_type in ('excitatory', 'inhibitory'), "only basic synapse types support Tsodyks-Markram connections"276 logger.debug("setting tau_psc")277 targets = nest.GetStatus(self.connections, 'target')278 if self.synapse_type == 'inhibitory':279 param_name = self.parent.post.local_cells[0].celltype.translations['tau_syn_I']['translated_name']280 if self.synapse_type == 'excitatory':281 param_name = self.parent.post.local_cells[0].celltype.translations['tau_syn_E']['translated_name']282 tau_syn = nest.GetStatus(targets, (param_name))283 nest.SetStatus(self.connections, 'tau_psc', tau_syn)284 285 def connect(self, source, targets, weights, delays):286 """287 Connect a neuron to one or more other neurons.288 289 `source` -- the ID of the pre-synaptic cell.290 `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID.291 `weight` -- a list/1D array of connection weights, or a single weight.292 Must have the same length as `targets`.293 `delays` -- a list/1D array of connection delays, or a single delay.294 Must have the same length as `targets`.295 """296 # are we sure the targets are all on the current node?297 if core.is_listlike(source):298 assert len(source) == 1299 source = source[0]300 if not core.is_listlike(targets):301 targets = [targets]302 assert len(targets) > 0303 304 if self.synapse_type not in targets[0].celltype.synapse_types:305 raise errors.ConnectionError("User gave synapse_type=%s, synapse_type must be one of: %s" % ( self.synapse_type, "'"+"', '".join(st for st in targets[0].celltype.synapse_types or ['*No connections supported*']))+"'" )306 weights = numpy.array(weights)*1000.0 # weights should be in nA or uS, but iaf_neuron uses pA and iaf_cond_neuron uses nS.307 # Using convention in this way is not ideal. We should308 # be able to look up the units used by each model somewhere.309 if self.synapse_type == 'inhibitory' and common.is_conductance(targets[0]):310 weights = -1*weights # NEST wants negative values for inhibitory weights, even if these are conductances311 if isinstance(weights, numpy.ndarray):312 weights = weights.tolist()313 elif isinstance(weights, float):314 weights = [weights]315 if isinstance(delays, numpy.ndarray):316 delays = delays.tolist()317 elif isinstance(delays, float):318 delays = [delays]319 320 if targets[0].celltype.standard_receptor_type:321 try:322 nest.DivergentConnect([source], targets, weights, delays, self.synapse_model)323 except nest.NESTError, e:324 raise errors.ConnectionError("%s. source=%s, targets=%s, weights=%s, delays=%s, synapse model='%s'" % (325 e, source, targets, weights, delays, self.synapse_model))326 else:327 for target, w, d in zip(targets, weights, delays):328 nest.Connect([source], [target], {'weight': w, 'delay': d, 'receptor_type': target.celltype.get_receptor_type(self.synapse_type)})329 self._connections = None # reset the caching of the connection list, since this will have to be recalculated330 self.sources.append(source)331 332 def convergent_connect(self, sources, target, weights, delays):333 """334 Connect one or more neurons to a single post-synaptic neuron.335 `sources` -- a list/1D array of pre-synaptic cell IDs, or a single ID.336 `target` -- the ID of the post-synaptic cell.337 `weight` -- a list/1D array of connection weights, or a single weight.338 Must have the same length as `targets`.339 `delays` -- a list/1D array of connection delays, or a single delay.340 Must have the same length as `targets`.341 """342 # are we sure the targets are all on the current node?343 if core.is_listlike(target):344 assert len(target) == 1345 target = target[0]346 if not core.is_listlike(sources):347 sources = [sources]348 assert len(sources) > 0, sources349 if self.synapse_type not in ('excitatory', 'inhibitory', None):350 raise errors.ConnectionError("synapse_type must be 'excitatory', 'inhibitory', or None (equivalent to 'excitatory')")351 weights = numpy.array(weights)*1000.0# weights should be in nA or uS, but iaf_neuron uses pA and iaf_cond_neuron uses nS.352 # Using convention in this way is not ideal. We should353 # be able to look up the units used by each model somewhere.354 if self.synapse_type == 'inhibitory' and common.is_conductance(target):355 weights = -1*weights # NEST wants negative values for inhibitory weights, even if these are conductances356 if isinstance(weights, numpy.ndarray):357 weights = weights.tolist()358 elif isinstance(weights, float):359 weights = [weights]360 if isinstance(delays, numpy.ndarray):361 delays = delays.tolist()362 elif isinstance(delays, float):363 delays = [delays]364 365 try:366 nest.ConvergentConnect(sources, [target], weights, delays, self.synapse_model)367 except nest.NESTError, e:368 raise errors.ConnectionError("%s. sources=%s, target=%s, weights=%s, delays=%s, synapse model='%s'" % (369 e, sources, target, weights, delays, self.synapse_model))370 self._connections = None # reset the caching of the connection list, since this will have to be recalculated371 self.sources.extend(sources)372 373 def get(self, parameter_name, format):374 """375 Get the values of a given attribute (weight or delay) for all376 connections in this manager.377 378 `parameter_name` -- name of the attribute whose values are wanted.379 380 `format` -- "list" or "array". Array format implicitly assumes that all381 connections belong to a single Projection.382 383 Return a list or a 2D Numpy array. The array element X_ij contains the384 attribute value for the connection from the ith neuron in the pre-385 synaptic Population to the jth neuron in the post-synaptic Population,386 if a single such connection exists. If there are no such connections,387 X_ij will be NaN. If there are multiple such connections, the summed388 value will be given, which makes some sense for weights, but is389 pretty meaningless for delays.390 """391 392 if parameter_name not in ('weight', 'delay'):393 translated_name = None394 if self.parent.synapse_dynamics.fast and parameter_name in self.parent.synapse_dynamics.fast.translations:395 translated_name = self.parent.synapse_dynamics.fast.translations[parameter_name]["translated_name"] # this is a hack that works because there are no units conversions396 elif self.parent.synapse_dynamics.slow:397 for component_name in "timing_dependence", "weight_dependence", "voltage_dependence":398 component = getattr(self.parent.synapse_dynamics.slow, component_name)399 if component and parameter_name in component.translations:400 translated_name = component.translations[parameter_name]["translated_name"]401 break402 if translated_name:403 parameter_name = translated_name404 else:405 raise Exception("synapse type does not have an attribute '%s', or else this attribute is not accessible." % parameter_name)406 if format == 'list':407 values = nest.GetStatus(self.connections, parameter_name)408 if parameter_name == "weight":409 values = [0.001*val for val in values]410 elif format == 'array':411 value_arr = numpy.nan * numpy.ones((self.parent.pre.size, self.parent.post.size))412 connection_parameters = nest.GetStatus(self.connections, ('source', 'target', parameter_name))413 for conn in connection_parameters:414 # don't need to pass offset as arg, now we store the parent projection415 # (offset is always 0,0 for connections created with connect())416 src, tgt, value = conn417 addr = self.parent.pre.id_to_index(src), self.parent.post.id_to_index(tgt)418 if numpy.isnan(value_arr[addr]):419 value_arr[addr] = value420 else:421 value_arr[addr] += value422 if parameter_name == 'weight':423 value_arr *= 0.001424 if self.synapse_type == 'inhibitory' and common.is_conductance(self[0].target):425 value_arr *= -1 # NEST uses negative values for inhibitory weights, even if these are conductances426 values = value_arr427 else:428 raise Exception("format must be 'list' or 'array', actually '%s'" % format)429 return values430 431 def set(self, name, value):432 """433 Set connection attributes for all connections on the local MPI node.434 435 `name` -- attribute name436 437 `value` -- the attribute numeric value, or a list/1D array of such438 values of the same length as the number of local connections,439 or a 2D array with the same dimensions as the connectivity440 matrix (as returned by `get(format='array')`).441 """442 if not (numpy.isscalar(value) or core.is_listlike(value)):443 raise TypeError("Argument should be a numeric type (int, float...), a list, or a numpy array.")444 445 if isinstance(value, numpy.ndarray) and len(value.shape) == 2:446 value_list = []447 connection_parameters = nest.GetStatus(self.connections, ('source', 'target'))448 for conn in connection_parameters:449 addr = self.parent.pre.id_to_index(conn['source']), self.parent.post.id_to_index(conn['target'])450 try:451 val = value[addr]452 except IndexError, e:453 raise IndexError("%s. addr=%s" % (e, addr))454 if numpy.isnan(val):455 raise Exception("Array contains no value for synapse from %d to %d" % (c.source, c.target))456 else:457 value_list.append(val)458 value = value_list459 if core.is_listlike(value):460 value = numpy.array(value)461 else:462 value = float(value)463 464 if name == 'weight':465 value *= 1000.0466 if self.synapse_type == 'inhibitory' and common.is_conductance(self[0].target):467 value *= -1 # NEST wants negative values for inhibitory weights, even if these are conductances468 elif name == 'delay':469 pass470 else:471 #translation = self.parent.synapse_dynamics.reverse_translate({name: value})472 #name, value = translation.items()[0]473 translated_name = None474 if self.parent.synapse_dynamics.fast:475 if name in self.parent.synapse_dynamics.fast.translations:476 translated_name = self.parent.synapse_dynamics.fast.translations[name]["translated_name"] # a hack477 if translated_name is None:478 if self.parent.synapse_dynamics.slow:479 for component_name in "timing_dependence", "weight_dependence", "voltage_dependence":480 component = getattr(self.parent.synapse_dynamics.slow, component_name)481 if component and name in component.translations:482 translated_name = component.translations[name]["translated_name"]483 break484 if translated_name:485 name = translated_name486 487 i = 0488 try:489 nest.SetStatus(self.connections, name, value)490 except nest.NESTError, e:491 n = 1492 if hasattr(value, '__len__'):493 n = len(value)494 raise Exception("%s. Trying to set %d values." % (e, n))495 496 210 # --- Initialization, and module attributes ------------------------------------ 497 211 -
trunk/src/neuron/__init__.py
r957 r998 12 12 from pyNN.random import * 13 13 from pyNN.neuron import simulator 14 from pyNN import common, recording as base_recording, space, __doc__14 from pyNN import common, core, recording as base_recording, space, __doc__ 15 15 common.simulator = simulator 16 16 base_recording.simulator = simulator … … 205 205 for cell in self.post: 206 206 cell._cell.set_Tsodyks_Markram_synapses(self.synapse_type, U, tau_rec, tau_facil, u0) 207 s ynapse_model = 'Tsodyks-Markram'207 self.synapse_model = 'Tsodyks-Markram' 208 208 else: 209 synapse_model = None 210 211 self.connection_manager = simulator.ConnectionManager(self.synapse_type, 212 synapse_model=synapse_model, 213 parent=self) 214 self.connections = self.connection_manager 209 self.synapse_model = None 210 self.connections = [] 211 215 212 ## Create connections 216 213 method.connect(self) … … 243 240 Projection.nProj += 1 244 241 242 def __getitem__(self, i): 243 """Return the `i`th connection on the local MPI node.""" 244 if isinstance(i, int): 245 if i < len(self): 246 return self.connections[i] 247 else: 248 raise IndexError("%d > %d" % (i, len(self)-1)) 249 elif isinstance(i, slice): 250 if i.stop < len(self): 251 return [self.connections[j] for j in range(*i.indices(i.stop))] 252 else: 253 raise IndexError("%d > %d" % (i.stop, len(self)-1)) 254 255 def __len__(self): 256 """Return the number of connections on the local MPI node.""" 257 return len(self.connections) 258 259 def _resolve_synapse_type(self): 260 if self.synapse_type is None: 261 self.synapse_type = weight>=0 and 'excitatory' or 'inhibitory' 262 if self.synapse_model == 'Tsodyks-Markram' and 'TM' not in self.synapse_type: 263 self.synapse_type += '_TM' 264 265 def _divergent_connect(self, source, targets, weights, delays): 266 """ 267 Connect a neuron to one or more other neurons with a static connection. 268 269 `source` -- the ID of the pre-synaptic cell. 270 `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. 271 `weight` -- a list/1D array of connection weights, or a single weight. 272 Must have the same length as `targets`. 273 `delays` -- a list/1D array of connection delays, or a single delay. 274 Must have the same length as `targets`. 275 """ 276 if not isinstance(source, int) or source > simulator.state.gid_counter or source < 0: 277 errmsg = "Invalid source ID: %s (gid_counter=%d)" % (source, simulator.state.gid_counter) 278 raise errors.ConnectionError(errmsg) 279 if not core.is_listlike(targets): 280 targets = [targets] 281 if isinstance(weights, float): 282 weights = [weights] 283 if isinstance(delays, float): 284 delays = [delays] 285 assert len(targets) > 0 286 for target in targets: 287 if not isinstance(target, common.IDMixin): 288 raise errors.ConnectionError("Invalid target ID: %s" % target) 289 290 assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets), len(weights), len(delays)) 291 self._resolve_synapse_type() 292 for target, weight, delay in zip(targets, weights, delays): 293 if target.local: 294 if "." in self.synapse_type: 295 section, synapse_type = self.synapse_type.split(".") 296 synapse_object = getattr(getattr(target._cell, section), synapse_type) 297 else: 298 synapse_object = getattr(target._cell, self.synapse_type) 299 nc = simulator.state.parallel_context.gid_connect(int(source), synapse_object) 300 nc.weight[0] = weight 301 302 # if we have a mechanism (e.g. from 9ML) that includes multiple 303 # synaptic channels, need to set nc.weight[1] here 304 if nc.wcnt() > 1 and hasattr(target._cell, "type"): 305 nc.weight[1] = target._cell.type.synapse_types.index(self.synapse_type) 306 nc.delay = delay 307 # nc.threshold is supposed to be set by ParallelContext.threshold, called in _build_cell(), above, but this hasn't been tested 308 self.connections.append(simulator.Connection(source, target, nc)) 309 310 def _convergent_connect(self, sources, target, weights, delays): 311 """ 312 Connect a neuron to one or more other neurons with a static connection. 313 314 `sources` -- a list/1D array of pre-synaptic cell IDs, or a single ID. 315 `target` -- the ID of the post-synaptic cell. 316 `weight` -- a list/1D array of connection weights, or a single weight. 317 Must have the same length as `targets`. 318 `delays` -- a list/1D array of connection delays, or a single delay. 319 Must have the same length as `targets`. 320 """ 321 if not isinstance(target, int) or target > simulator.state.gid_counter or target < 0: 322 errmsg = "Invalid target ID: %s (gid_counter=%d)" % (target, simulator.state.gid_counter) 323 raise errors.ConnectionError(errmsg) 324 if not core.is_listlike(sources): 325 sources = [sources] 326 if isinstance(weights, float): 327 weights = [weights] 328 if isinstance(delays, float): 329 delays = [delays] 330 assert len(sources) > 0 331 for source in sources: 332 if not isinstance(source, common.IDMixin): 333 raise errors.ConnectionError("Invalid source ID: %s" % source) 334 335 assert len(sources) == len(weights) == len(delays), "%s %s %s" % (len(sources),len(weights),len(delays)) 336 337 if target.local: 338 for source, weight, delay in zip(sources, weights, delays): 339 if self.synapse_type is None: 340 self.synapse_type = weight >= 0 and 'excitatory' or 'inhibitory' 341 if self.synapse_model == 'Tsodyks-Markram' and 'TM' not in self.synapse_type: 342 self.synapse_type += '_TM' 343 synapse_object = getattr(target._cell, self.synapse_type) 344 nc = simulator.state.parallel_context.gid_connect(int(source), synapse_object) 345 nc.weight[0] = weight 346 nc.delay = delay 347 # nc.threshold is supposed to be set by ParallelContext.threshold, called in _build_cell(), above, but this hasn't been tested 348 self.connections.append(Connection(source, target, nc)) 349 350 245 351 # --- Methods for setting connection parameters ---------------------------- 246 352 353 def set(self, name, value): 354 """ 355 Set connection attributes for all connections on the local MPI node. 356 357 `name` -- attribute name 358 `value` -- the attribute numeric value, or a list/1D array of such 359 values of the same length as the number of local connections, 360 or a 2D array with the same dimensions as the connectivity 361 matrix (as returned by `get(format='array')`). 362 """ 363 if numpy.isscalar(value): 364 for c in self: 365 setattr(c, name, value) 366 elif isinstance(value, numpy.ndarray) and len(value.shape) == 2: 367 for c in self.connections: 368 addr = (self.pre.id_to_index(c.source), self.post.id_to_index(c.target)) 369 try: 370 val = value[addr] 371 except IndexError, e: 372 raise IndexError("%s. addr=%s" % (e, addr)) 373 if numpy.isnan(val): 374 raise Exception("Array contains no value for synapse from %d to %d" % (c.source, c.target)) 375 else: 376 setattr(c, name, val) 377 elif core.is_listlike(value): 378 for c,val in zip(self.connections, value): 379 setattr(c, name, val) 380 else: 381 raise TypeError("Argument should be a numeric type (int, float...), a list, or a numpy array.") 382 247 383 def randomizeWeights(self, rand_distr): 248 384 """ … … 277 413 self.setDelays(rarr) 278 414 415 def get(self, parameter_name, format, gather=True): 416 """ 417 Get the values of a given attribute (weight, delay, etc) for all 418 connections on the local MPI node. 419 420 `parameter_name` -- name of the attribute whose values are wanted. 421 `format` -- "list" or "array". Array format implicitly assumes that all 422 connections belong to a single Projection. 423 424 Return a list or a 2D Numpy array. The array element X_ij contains the 425 attribute value for the connection from the ith neuron in the pre- 426 synaptic Population to the jth neuron in the post-synaptic Population, 427 if a single such connection exists. If there are no such connections, 428 X_ij will be NaN. If there are multiple such connections, the summed 429 value will be given, which makes some sense for weights, but is 430 pretty meaningless for delays. 431 """ 432 if format == 'list': 433 values = [getattr(c, parameter_name) for c in self.connections] 434 elif format == 'array': 435 values = numpy.nan * numpy.ones((self.pre.size, self.post.size)) 436 for c in self.connections: 437 value = getattr(c, parameter_name) 438 addr = (self.pre.id_to_index(c.source), self.post.id_to_index(c.target)) 439 if numpy.isnan(values[addr]): 440 values[addr] = value 441 else: 442 values[addr] += value 443 else: 444 raise Exception("format must be 'list' or 'array'") 445 return values 446 279 447 280 448 Space = space.Space -
trunk/src/neuron/simulator.py
r967 r998 7 7 8 8 Functions: 9 create_cells()10 9 reset() 11 10 run() … … 15 14 ID 16 15 Recorder 17 ConnectionManager18 16 Connection 19 17 … … 42 40 nrn_dll_loaded = [] 43 41 recorder_list = [] 44 connection_managers = []45 42 gid_sources = [] 46 43 logger = logging.getLogger("PyNN") … … 167 164 168 165 def clear(self): 169 global connection_managers,gid_sources166 global gid_sources 170 167 self.parallel_context.gid_clear() 171 168 gid_sources = [] … … 173 170 self.running = False 174 171 h.plastic_connections = [] 175 connection_managers = []176 172 177 173 def reset(): … … 366 362 367 363 368 369 class ConnectionManager(object):370 """371 Manage synaptic connections, providing methods for creating, listing,372 accessing individual connections.373 """374 375 def __init__(self, synapse_type, synapse_model=None, parent=None):376 """377 Create a new ConnectionManager.378 379 `synapse_model` -- either None or 'Tsodyks-Markram'.380 `parent` -- the parent `Projection`381 """382 global connection_managers383 assert parent is not None384 self.connections = []385 self.parent = parent386 self.synapse_type = synapse_type387 self.synapse_model = synapse_model388 connection_managers.append(self)389 390 def __getitem__(self, i):391 """Return the `i`th connection on the local MPI node."""392 if isinstance(i, int):393 if i < len(self):394 return self.connections[i]395 else:396 raise IndexError("%d > %d" % (i, len(self)-1))397 elif isinstance(i, slice):398 if i.stop < len(self):399 return [self.connections[j] for j in range(*i.indices(i.stop))]400 else:401 raise IndexError("%d > %d" % (i.stop, len(self)-1))402 403 def __len__(self):404 """Return the number of connections on the local MPI node."""405 return len(self.connections)406 407 def __iter__(self):408 """Return an iterator over all connections on the local MPI node."""409 return iter(self.connections)410 411 def _resolve_synapse_type(self):412 if self.synapse_type is None:413 self.synapse_type = weight>=0 and 'excitatory' or 'inhibitory'414 if self.synapse_model == 'Tsodyks-Markram' and 'TM' not in self.synapse_type:415 self.synapse_type += '_TM'416 417 def connect(self, source, targets, weights, delays):418 """419 Connect a neuron to one or more other neurons with a static connection.420 421 `source` -- the ID of the pre-synaptic cell.422 `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID.423 `weight` -- a list/1D array of connection weights, or a single weight.424 Must have the same length as `targets`.425 `delays` -- a list/1D array of connection delays, or a single delay.426 Must have the same length as `targets`.427 """428 if not isinstance(source, int) or source > state.gid_counter or source < 0:429 errmsg = "Invalid source ID: %s (gid_counter=%d)" % (source, state.gid_counter)430 raise errors.ConnectionError(errmsg)431 if not core.is_listlike(targets):432 targets = [targets]433 if isinstance(weights, float):434 weights = [weights]435 if isinstance(delays, float):436 delays = [delays]437 assert len(targets) > 0438 for target in targets:439 if not isinstance(target, common.IDMixin):440 raise errors.ConnectionError("Invalid target ID: %s" % target)441 442 assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets), len(weights), len(delays))443 self._resolve_synapse_type()444 for target, weight, delay in zip(targets, weights, delays):445 if target.local:446 if "." in self.synapse_type:447 section, synapse_type = self.synapse_type.split(".")448 synapse_object = getattr(getattr(target._cell, section), synapse_type)449 else:450 synapse_object = getattr(target._cell, self.synapse_type)451 nc = state.parallel_context.gid_connect(int(source), synapse_object)452 nc.weight[0] = weight453 454 # if we have a mechanism (e.g. from 9ML) that includes multiple455 # synaptic channels, need to set nc.weight[1] here456 if nc.wcnt() > 1 and hasattr(target._cell, "type"):457 nc.weight[1] = target._cell.type.synapse_types.index(self.synapse_type)458 nc.delay = delay459 # nc.threshold is supposed to be set by ParallelContext.threshold, called in _build_cell(), above, but this hasn't been tested460 self.connections.append(Connection(source, target, nc))461 462 def convergent_connect(self, sources, target, weights, delays):463 """464 Connect a neuron to one or more other neurons with a static connection.465 466 `sources` -- a list/1D array of pre-synaptic cell IDs, or a single ID.467 `target` -- the ID of the post-synaptic cell.468 `weight` -- a list/1D array of connection weights, or a single weight.469 Must have the same length as `targets`.470 `delays` -- a list/1D array of connection delays, or a single delay.471 Must have the same length as `targets`.472 """473 if not isinstance(target, int) or target > state.gid_counter or target < 0:474 errmsg = "Invalid target ID: %s (gid_counter=%d)" % (target, state.gid_counter)475 raise errors.ConnectionError(errmsg)476 if not core.is_listlike(sources):477 sources = [sources]478 if isinstance(weights, float):479 weights = [weights]480 if isinstance(delays, float):481 delays = [delays]482 assert len(sources) > 0483 for source in sources:484 if not isinstance(source, common.IDMixin):485 raise errors.ConnectionError("Invalid source ID: %s" % source)486 487 assert len(sources) == len(weights) == len(delays), "%s %s %s" % (len(sources),len(weights),len(delays))488 489 if target.local:490 for source, weight, delay in zip(sources, weights, delays):491 if self.synapse_type is None:492 self.synapse_type = weight >= 0 and 'excitatory' or 'inhibitory'493 if self.synapse_model == 'Tsodyks-Markram' and 'TM' not in self.synapse_type:494 self.synapse_type += '_TM'495 synapse_object = getattr(target._cell, self.synapse_type)496 nc = state.parallel_context.gid_connect(int(source), synapse_object)497 nc.weight[0] = weight498 nc.delay = delay499 # nc.threshold is supposed to be set by ParallelContext.threshold, called in _build_cell(), above, but this hasn't been tested500 self.connections.append(Connection(source, target, nc))501 502 def get(self, parameter_name, format):503 """504 Get the values of a given attribute (weight, delay, etc) for all505 connections on the local MPI node.506 507 `parameter_name` -- name of the attribute whose values are wanted.508 `format` -- "list" or "array". Array format implicitly assumes that all509 connections belong to a single Projection.510 511 Return a list or a 2D Numpy array. The array element X_ij contains the512 attribute value for the connection from the ith neuron in the pre-513 synaptic Population to the jth neuron in the post-synaptic Population,514 if a single such connection exists. If there are no such connections,515 X_ij will be NaN. If there are multiple such connections, the summed516 value will be given, which makes some sense for weights, but is517 pretty meaningless for delays.518 """519 if format == 'list':520 values = [getattr(c, parameter_name) for c in self.connections]521 elif format == 'array':522 values = numpy.nan * numpy.ones((self.parent.pre.size, self.parent.post.size))523 for c in self.connections:524 value = getattr(c, parameter_name)525 addr = (self.parent.pre.id_to_index(c.source), self.parent.post.id_to_index(c.target))526 if numpy.isnan(values[addr]):527 values[addr] = value528 else:529 values[addr] += value530 else:531 raise Exception("format must be 'list' or 'array'")532 return values533 534 def set(self, name, value):535 """536 Set connection attributes for all connections on the local MPI node.537 538 `name` -- attribute name539 `value` -- the attribute numeric value, or a list/1D array of such540 values of the same length as the number of local connections,541 or a 2D array with the same dimensions as the connectivity542 matrix (as returned by `get(format='array')`).543 """544 if numpy.isscalar(value):545 for c in self:546 setattr(c, name, value)547 elif isinstance(value, numpy.ndarray) and len(value.shape) == 2:548 for c in self.connections:549 addr = (self.parent.pre.id_to_index(c.source), self.parent.post.id_to_index(c.target))550 try:551 val = value[addr]552 except IndexError, e:553 raise IndexError("%s. addr=%s" % (e, addr))554 if numpy.isnan(val):555 raise Exception("Array contains no value for synapse from %d to %d" % (c.source, c.target))556 else:557 setattr(c, name, val)558 elif core.is_listlike(value):559 for c,val in zip(self.connections, value):560 setattr(c, name, val)561 else:562 raise TypeError("Argument should be a numeric type (int, float...), a list, or a numpy array.")563 564 565 364 # --- Initialization, and module attributes ------------------------------------ 566 365 -
trunk/src/pcsim/__init__.py
r957 r998 254 254 - the ID of the last cell created 255 255 """ 256 global net257 256 assert n > 0, 'n must be a positive integer' 258 257 … … 419 418 420 419 nProj = 0 420 synapse_target_ids = { 'excitatory': 1, 'inhibitory': 2 } 421 421 422 422 def __init__(self, presynaptic_population, postsynaptic_population, … … 614 614 ##self.synapse_type = self.syn_factory #target or 'excitatory' 615 615 self.synapse_type = target or 'excitatory' 616 self.connection_manager = simulator.ConnectionManager(self.syn_factory, parent=self) 617 self.connections = self.connection_manager 616 self.connections = [] 618 617 method.connect(self) 619 618 Projection.nProj += 1 … … 622 621 # useful when we start (re-)optimizing the implementation 623 622 624 ##def __len__(self): 625 ## """Return the total number of connections.""" 626 ## return self.pcsim_projection.size() 623 def __len__(self): 624 """Return the total number of connections.""" 625 ###return self.pcsim_projection.size() 626 return len(self.connections) 627 627 628 628 #def __getitem__(self, n): 629 629 # return self.pcsim_projection[n] 630 631 630 def __getitem__(self, i): 631 """Return the `i`th connection on the local MPI node.""" 632 #if self.parent: 633 # if self.parent.is_conductance: 634 # A = 1e6 # S --> uS 635 # else: 636 # A = 1e9 # A --> nA 637 # return Connection(self.parent.pcsim_projection.object(i), A) 638 #else: 639 return self.connections[i] 640 641 def _divergent_connect(self, source, targets, weights, delays): 642 """ 643 Connect a neuron to one or more other neurons with a static connection. 644 645 `source` -- the ID of the pre-synaptic cell. 646 `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. 647 `weight` -- a list/1D array of connection weights, or a single weight. 648 Must have the same length as `targets`. 649 `delays` -- a list/1D array of connection delays, or a single delay. 650 Must have the same length as `targets`. 651 """ 652 if not isinstance(source, (int, long)) or source < 0: 653 errmsg = "Invalid source ID: %s" % source 654 raise errors.ConnectionError(errmsg) 655 if not core.is_listlike(targets): 656 targets = [targets] 657 if isinstance(weights, float): 658 weights = [weights] 659 if isinstance(delays, float): 660 delays = [delays] 661 assert len(targets) > 0 662 for target in targets: 663 if not isinstance(target, common.IDMixin): 664 raise errors.ConnectionError("Invalid target ID: %s" % target) 665 assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets),len(weights),len(delays)) 666 if common.is_conductance(targets[0]): 667 weight_scale_factor = 1e-6 # Convert from µS to S 668 else: 669 weight_scale_factor = 1e-9 # Convert from nA to A 670 671 synapse_type = self.syn_factory or "excitatory" 672 if isinstance(synapse_type, basestring): 673 syn_target_id = Projection.synapse_target_ids[synapse_type] 674 syn_factory = pypcsim.SimpleScalingSpikingSynapse( 675 syn_target_id, weights[0], delays[0]) 676 elif isinstance(synapse_type, pypcsim.SimObject): 677 syn_factory = synapse_type 678 else: 679 raise errors.ConnectionError("synapse_type must be a string or a PCSIM synapse factory. Actual type is %s" % type(synapse_type)) 680 for target, weight, delay in zip(targets, weights, delays): 681 syn_factory.W = weight*weight_scale_factor 682 syn_factory.delay = delay*0.001 # ms --> s 683 try: 684 c = simulator.net.connect(source, target, syn_factory) 685 except RuntimeError, e: 686 raise errors.ConnectionError(e) 687 if target.local: 688 self.connections.append(simulator.Connection(source, target, simulator.net.object(c), 1.0/weight_scale_factor)) 689 690 def _convergent_connect(self, sources, target, weights, delays): 691 """ 692 Connect a neuron to one or more other neurons with a static connection. 693 694 `sources` -- a list/1D array of pre-synaptic cell IDs, or a single ID. 695 `target` -- the ID of the post-synaptic cell. 696 `weight` -- a list/1D array of connection weights, or a single weight. 697 Must have the same length as `targets`. 698 `delays` -- a list/1D array of connection delays, or a single delay. 699 Must have the same length as `targets`. 700 """ 701 if not isinstance(target, (int, long)) or target < 0: 702 errmsg = "Invalid target ID: %s" % target 703 raise errors.ConnectionError(errmsg) 704 if not core.is_listlike(sources): 705 sources = [sources] 706 if isinstance(weights, float): 707 weights = [weights] 708 if isinstance(delays, float): 709 delays = [delays] 710 assert len(sources) > 0 711 for source in sources: 712 if not isinstance(source, common.IDMixin): 713 raise errors.ConnectionError("Invalid source ID: %s" % source) 714 assert len(sources) == len(weights) == len(delays), "%s %s %s" % (len(sources),len(weights),len(delays)) 715 if common.is_conductance(target): 716 weight_scale_factor = 1e-6 # Convert from µS to S 717 else: 718 weight_scale_factor = 1e-9 # Convert from nA to A 719 720 synapse_type = self.syn_factory or "excitatory" 721 if isinstance(synapse_type, basestring): 722 syn_target_id = Projection.synapse_target_ids[synapse_type] 723 syn_factory = pypcsim.SimpleScalingSpikingSynapse( 724 syn_target_id, weights[0], delays[0]) 725 elif isinstance(synapse_type, pypcsim.SimObject): 726 syn_factory = synapse_type 727 else: 728 raise errors.ConnectionError("synapse_type must be a string or a PCSIM synapse factory. Actual type is %s" % type(synapse_type)) 729 for source, weight, delay in zip(sources, weights, delays): 730 syn_factory.W = weight*weight_scale_factor 731 syn_factory.delay = delay*0.001 # ms --> s 732 try: 733 c = simulator.net.connect(source, target, syn_factory) 734 except RuntimeError, e: 735 raise errors.ConnectionError(e) 736 if target.local: 737 self.connections.append(simulator.Connection(source, target, simulator.net.object(c), 1.0/weight_scale_factor)) 738 632 739 # --- Methods for setting connection parameters ---------------------------- 633 740 741 def set(self, name, value): 742 """ 743 Set connection attributes for all connections on the local MPI node. 744 745 `name` -- attribute name 746 `value` -- the attribute numeric value, or a list/1D array of such 747 values of the same length as the number of local connections, 748 or a 2D array with the same dimensions as the connectivity 749 matrix (as returned by `get(format='array')`) 750 """ 751 if numpy.isscalar(value): 752 for c in self: 753 setattr(c, name, value) 754 elif isinstance(value, numpy.ndarray) and len(value.shape) == 2: 755 for c in self.connections: 756 addr = (self.pre.id_to_index(c.source), self.post.id_to_index(c.target)) 757 try: 758 val = value[addr] 759 except IndexError, e: 760 raise IndexError("%s. addr=%s" % (e, addr)) 761 if numpy.isnan(val): 762 raise Exception("Array contains no value for synapse from %d to %d" % (c.source, c.target)) 763 else: 764 setattr(c, name, val) 765 elif core.is_listlike(value): 766 for c,val in zip(self.connections, value): 767 setattr(c, name, val) 768 else: 769 raise TypeError("Argument should be a numeric type (int, float...), a list, or a numpy array.") 770 634 771 ##def setWeights(self, w): 635 772 ## """ … … 684 821 ## for i in range(len(self)): 685 822 ## simulator.net.object(self.pcsim_projection[i]).delay = delays[i] 686 ## 823 824 def get(self, parameter_name, format, gather=True): 825 """ 826 Get the values of a given attribute (weight, delay, etc) for all 827 connections on the local MPI node. 828 829 `parameter_name` -- name of the attribute whose values are wanted. 830 `format` -- "list" or "array". Array format implicitly assumes that all 831 connections belong to a single Projection. 832 833 Return a list or a 2D Numpy array. The array element X_ij contains the 834 attribute value for the connection from the ith neuron in the pre- 835 synaptic Population to the jth neuron in the post-synaptic Population, 836 if such a connection exists. If there are no such connections, X_ij will 837 be NaN. 838 """ 839 if format == 'list': 840 values = [getattr(c, parameter_name) for c in self] 841 elif format == 'array': 842 values = numpy.nan * numpy.ones((self.pre.size, self.post.size)) 843 for c in self: 844 addr = (self.pre.id_to_index(c.source), self.post.id_to_index(c.target)) 845 values[addr] = getattr(c, parameter_name) 846 else: 847 raise Exception("format must be 'list' or 'array'") 848 return values 849 850 687 851 ##def getWeights(self, format='list', gather=True): 688 852 ## """ -
trunk/src/pcsim/simulator.py
r957 r998 7 7 8 8 Functions: 9 create_cells()10 9 reset() 11 10 … … 13 12 ID 14 13 Recorder 15 ConnectionManager16 14 Connection 17 15 … … 36 34 37 35 recorder_list = [] 38 connection_managers = []39 36 STATE_VARIABLE_MAP = {"v": ("Vinit", 1e-3)} 40 37 … … 197 194 198 195 199 class ConnectionManager(object):200 """201 Manage synaptic connections, providing methods for creating, listing,202 accessing individual connections.203 """204 205 synapse_target_ids = { 'excitatory': 1, 'inhibitory': 2 }206 207 def __init__(self, synapse_type, synapse_model=None, parent=None):208 """209 Create a new ConnectionManager.210 211 `synapse_type` -- the 'physiological type' of the synapse, e.g.212 'excitatory' or 'inhibitory', or a PCSIM synapse213 factory.214 `synapse_model` -- not used. Present for consistency with other simulators.215 `parent` -- the parent `Projection`, if any.216 """217 global connection_managers218 self.synapse_type = synapse_type219 self.connections = []220 self.parent = parent221 connection_managers.append(self)222 self.parent = parent223 #if parent is None:224 self.connections = []225 226 def __getitem__(self, i):227 """Return the `i`th connection on the local MPI node."""228 #if self.parent:229 # if self.parent.is_conductance:230 # A = 1e6 # S --> uS231 # else:232 # A = 1e9 # A --> nA233 # return Connection(self.parent.pcsim_projection.object(i), A)234 #else:235 return self.connections[i]236 237 def __len__(self):238 """Return the number of connections on the local MPI node."""239 #if self.parent:240 # return self.parent.pcsim_projection.size()241 #else:242 return len(self.connections)243 244 def __iter__(self):245 """Return an iterator over all connections on the local MPI node."""246 for i in range(len(self)):247 yield self[i]248 249 def connect(self, source, targets, weights, delays):250 """251 Connect a neuron to one or more other neurons with a static connection.252 253 `source` -- the ID of the pre-synaptic cell.254 `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID.255 `weight` -- a list/1D array of connection weights, or a single weight.256 Must have the same length as `targets`.257 `delays` -- a list/1D array of connection delays, or a single delay.258 Must have the same length as `targets`.259 """260 if not isinstance(source, (int, long)) or source < 0:261 errmsg = "Invalid source ID: %s" % source262 raise errors.ConnectionError(errmsg)263 if not core.is_listlike(targets):264 targets = [targets]265 if isinstance(weights, float):266 weights = [weights]267 if isinstance(delays, float):268 delays = [delays]269 assert len(targets) > 0270 for target in targets:271 if not isinstance(target, common.IDMixin):272 raise errors.ConnectionError("Invalid target ID: %s" % target)273 assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets),len(weights),len(delays))274 if common.is_conductance(targets[0]):275 weight_scale_factor = 1e-6 # Convert from µS to S276 else:277 weight_scale_factor = 1e-9 # Convert from nA to A278 279 synapse_type = self.synapse_type or "excitatory"280 if isinstance(synapse_type, basestring):281 syn_target_id = ConnectionManager.synapse_target_ids[synapse_type]282 syn_factory = pypcsim.SimpleScalingSpikingSynapse(283 syn_target_id, weights[0], delays[0])284 elif isinstance(synapse_type, pypcsim.SimObject):285 syn_factory = synapse_type286 else:287 raise errors.ConnectionError("synapse_type must be a string or a PCSIM synapse factory. Actual type is %s" % type(synapse_type))288 for target, weight, delay in zip(targets, weights, delays):289 syn_factory.W = weight*weight_scale_factor290 syn_factory.delay = delay*0.001 # ms --> s291 try:292 c = net.connect(source, target, syn_factory)293 except RuntimeError, e:294 raise errors.ConnectionError(e)295 if target.local:296 self.connections.append(Connection(source, target, net.object(c), 1.0/weight_scale_factor))297 298 def convergent_connect(self, sources, target, weights, delays):299 """300 Connect a neuron to one or more other neurons with a static connection.301 302 `sources` -- a list/1D array of pre-synaptic cell IDs, or a single ID.303 `target` -- the ID of the post-synaptic cell.304 `weight` -- a list/1D array of connection weights, or a single weight.305 Must have the same length as `targets`.306 `delays` -- a list/1D array of connection delays, or a single delay.307 Must have the same length as `targets`.308 """309 if not isinstance(target, (int, long)) or target < 0:310 errmsg = "Invalid target ID: %s" % target311 raise errors.ConnectionError(errmsg)312 if not core.is_listlike(sources):313 sources = [sources]314 if isinstance(weights, float):315 weights = [weights]316 if isinstance(delays, float):317 delays = [delays]318 assert len(sources) > 0319 for source in sources:320 if not isinstance(source, common.IDMixin):321 raise errors.ConnectionError("Invalid source ID: %s" % source)322 assert len(sources) == len(weights) == len(delays), "%s %s %s" % (len(sources),len(weights),len(delays))323 if common.is_conductance(target):324 weight_scale_factor = 1e-6 # Convert from µS to S325 else:326 weight_scale_factor = 1e-9 # Convert from nA to A327 328 synapse_type = self.synapse_type or "excitatory"329 if isinstance(synapse_type, basestring):330 syn_target_id = ConnectionManager.synapse_target_ids[synapse_type]331 syn_factory = pypcsim.SimpleScalingSpikingSynapse(332 syn_target_id, weights[0], delays[0])333 elif isinstance(synapse_type, pypcsim.SimObject):334 syn_factory = synapse_type335 else:336 raise errors.ConnectionError("synapse_type must be a string or a PCSIM synapse factory. Actual type is %s" % type(synapse_type))337 for source, weight, delay in zip(sources, weights, delays):338 syn_factory.W = weight*weight_scale_factor339 syn_factory.delay = delay*0.001 # ms --> s340 try:341 c = net.connect(source, target, syn_factory)342 except RuntimeError, e:343 raise errors.ConnectionError(e)344 if target.local:345 self.connections.append(Connection(source, target, net.object(c), 1.0/weight_scale_factor))346 347 def get(self, parameter_name, format):348 """349 Get the values of a given attribute (weight, delay, etc) for all350 connections on the local MPI node.351 352 `parameter_name` -- name of the attribute whose values are wanted.353 `format` -- "list" or "array". Array format implicitly assumes that all354 connections belong to a single Projection.355 356 Return a list or a 2D Numpy array. The array element X_ij contains the357 attribute value for the connection from the ith neuron in the pre-358 synaptic Population to the jth neuron in the post-synaptic Population,359 if such a connection exists. If there are no such connections, X_ij will360 be NaN.361 """362 if format == 'list':363 values = [getattr(c, parameter_name) for c in self]364 elif format == 'array':365 values = numpy.nan * numpy.ones((self.parent.pre.size, self.parent.post.size))366 for c in self:367 addr = (self.parent.pre.id_to_index(c.source), self.parent.post.id_to_index(c.target))368 values[addr] = getattr(c, parameter_name)369 else:370 raise Exception("format must be 'list' or 'array'")371 return values372 373 def set(self, name, value):374 """375 Set connection attributes for all connections on the local MPI node.376 377 `name` -- attribute name378 `value` -- the attribute numeric value, or a list/1D array of such379 values of the same length as the number of local connections,380 or a 2D array with the same dimensions as the connectivity381 matrix (as returned by `get(format='array')`)382 """383 if numpy.isscalar(value):384 for c in self:385 setattr(c, name, value)386 elif isinstance(value, numpy.ndarray) and len(value.shape) == 2:387 for c in self.connections:388 addr = (self.parent.pre.id_to_index(c.source), self.parent.post.id_to_index(c.target))389 try:390 val = value[addr]391 except IndexError, e:392 raise IndexError("%s. addr=%s" % (e, addr))393 if numpy.isnan(val):394 raise Exception("Array contains no value for synapse from %d to %d" % (c.source, c.target))395 else:396 setattr(c, name, val)397 elif core.is_listlike(value):398 for c,val in zip(self.connections, value):399 setattr(c, name, val)400 else:401 raise TypeError("Argument should be a numeric type (int, float...), a list, or a numpy array.")402 403 404 196 # --- Initialization, and module attributes ------------------------------------ 405 197 -
trunk/test/system/scenarios.py
r993 r998 408 408 assert_arrays_equal(rec, data[0]) 409 409 410 @register(exclude=['pcsim' ])410 @register(exclude=['pcsim', 'moose']) 411 411 def test_EIF_cond_alpha_isfa_ista(sim): 412 412 set_simulator(sim) … … 448 448 449 449 450 @register(exclude=['pcsim' ])450 @register(exclude=['pcsim', 'moose']) 451 451 def test_record_vm_and_gsyn_from_assembly(sim): 452 452 from pyNN.utility import init_logging -
trunk/test/unittests/test_connectors.py
r850 r998 53 53 54 54 55 class MockConnectionManager(object): 56 57 def __init__(self): 55 class MockRNG(random.WrappedRNG): 56 rng = None 57 58 def __init__(self, num_processes, delta=1): 59 random.num_processes = num_processes 60 random.WrappedRNG.__init__(self) 61 self.start = 0.0 62 self.delta = delta 63 64 def _next(self, distribution, n, parameters): 65 s = self.start 66 self.start += n*self.delta 67 return numpy.arange(s, s+n*self.delta, self.delta) 68 69 70 class MockProjection(object): 71 72 def __init__(self, pre, post): 73 self.pre = pre 74 self.post = post 58 75 self.connections = [] 59 60 def connect(self, src, targets, weights, delays): 76 self.rng = MockRNG(num_processes=2, delta=0.1) 77 self.synapse_type = 'inhibitory' 78 79 def _divergent_connect(self, src, targets, weights, delays): 61 80 #if src in self.connections: 62 81 # raise Exception("connect already called with source %s" % src) # no reason why this shouldn't happen, but it doesn't in the current implementation, so I'm being lazy … … 74 93 self.connections.append((src, tgt, w, d)) 75 94 76 def convergent_connect(self, sources, tgt, weights, delays):95 def _convergent_connect(self, sources, tgt, weights, delays): 77 96 if isinstance(weights, float): 78 97 weights = repeat(weights) … … 81 100 for src, w, d in zip(sources, weights, delays): 82 101 self.connections.append((src, tgt, w, d)) 83 84 85 class MockRNG(random.WrappedRNG):86 rng = None87 88 def __init__(self, num_processes, delta=1):89 random.num_processes = num_processes90 random.WrappedRNG.__init__(self)91 self.start = 0.092 self.delta = delta93 94 def _next(self, distribution, n, parameters):95 s = self.start96 self.start += n*self.delta97 return numpy.arange(s, s+n*self.delta, self.delta)98 99 100 class MockProjection(object):101 102 def __init__(self, pre, post):103 self.pre = pre104 self.post = post105 self.connection_manager = MockConnectionManager()106 self.rng = MockRNG(num_processes=2, delta=0.1)107 self.synapse_type = 'inhibitory'108 102 109 103 … … 119 113 C.progression = Mock() 120 114 C.connect(self.prj) 121 assert_equal(self.prj.connection _manager.connections,115 assert_equal(self.prj.connections, 122 116 [(18, 80, 5.0, 0.5), (20, 82, 5, 0.5)]) 123 117 … … 128 122 C.progression = Mock() 129 123 C.connect(self.prj) 130 assert_equal(self.prj.connection _manager.connections,124 assert_equal(self.prj.connections, 131 125 [(18, 80, 1.0, 0.5), (20, 82, 3.0, 0.5)]) 132 126 … … 143 137 C.progression = Mock() 144 138 C.connect(self.prj) 145 assert_equal(set(self.prj.connection _manager.connections),139 assert_equal(set(self.prj.connections), 146 140 set([(17, 80, 5.0, 0.5), 147 141 (17, 82, 5.0, 0.5), … … 159 153 C.progression = Mock() 160 154 C.connect(self.prj) 161 assert_equal(self.prj.connection _manager.connections,155 assert_equal(self.prj.connections, 162 156 [(17, 80, 1.0, 0.5), 163 157 (17, 82, 3.0, 0.5), … … 175 169 C.progression = Mock() 176 170 C.connect(self.prj) 177 assert_equal(self.prj.connection _manager.connections,171 assert_equal(self.prj.connections, 178 172 [(17, 80, 163.0, 0.5), # 100+|17-80| 179 173 (17, 82, 165.0, 0.5), # 100+|17-82| … … 220 214 # first 8 are created (17, 79), (17, 80), (17,81), (17,82), (17,83), (18,79), (18,80), (18,81) 221 215 # of these, (17,80), (17,82), (18,80) are created on this node 222 assert_equal(self.prj.connection _manager.connections,216 assert_equal(self.prj.connections, 223 217 [(17, 80, 0.0, MIN_DELAY), 224 218 (17, 82, 0.0, MIN_DELAY), … … 240 234 # 20 possible connections. Only those with a sufficiently small distance 241 235 # are created 242 assert_equal(self.prj.connection _manager.connections,236 assert_equal(self.prj.connections, 243 237 [(18, 80, 0.0, MIN_DELAY), 244 238 (19, 80, 0.0, MIN_DELAY), … … 266 260 C.connect(self.prj) 267 261 # note that ListConnector does not filter out non-local connections 268 assert_equal(self.prj.connection _manager.connections,262 assert_equal(self.prj.connections, 269 263 [(17, 79, 0.1, 0.1), 270 264 (17, 80, 0.5, 0.14), … … 307 301 C = connectors.FromFileConnector("test.connections", distributed=False) 308 302 C.connect(self.prj) 309 assert_equal(self.prj.connection _manager.connections,303 assert_equal(self.prj.connections, 310 304 [(17, 79, 0.1, 0.1), 311 305 (17, 80, 0.5, 0.14), … … 319 313 C = connectors.FromFileConnector("test.connections", distributed=True) 320 314 C.connect(self.prj) 321 assert_equal(self.prj.connection _manager.connections,315 assert_equal(self.prj.connections, 322 316 [(17, 80, 0.5, 0.14), 323 317 (19, 82, 0.3, 0.12)]) … … 340 334 C.connect(self.prj) 341 335 # FixedNumberPost does not currently filter out only local connections 342 assert_equal(self.prj.connection _manager.connections,336 assert_equal(self.prj.connections, 343 337 [(17, 79, 0.0, MIN_DELAY), 344 338 (17, 80, 0.0, MIN_DELAY), … … 371 365 self.prj.post.local_cells = [MockCell(n) for n in self.prj.post.local_cells] 372 366 C.connect(self.prj) 373 assert_equal(self.prj.connection _manager.connections,367 assert_equal(self.prj.connections, 374 368 [(17, 80, 0.0, MIN_DELAY), 375 369 (18, 80, 0.0, MIN_DELAY), -
trunk/test/unittests/test_projection.py
r880 r998 24 24 first_id = 555 25 25 26 class MockConnectionManager(object):27 26 def __len__(self): 28 27 return 999 … … 49 48 synapse_dynamics=standardmodels.SynapseDynamics()) 50 49 51 def test_len():52 p1 = MockPopulation()53 p2 = MockPopulation()54 prj = common.Projection(p1, p2, method=Mock())55 prj.connection_manager = MockConnectionManager()56 assert_equal(len(prj), len(prj.connection_manager))57 58 50 def test_size_no_gather(): 59 51 p1 = MockPopulation() 60 52 p2 = MockPopulation() 61 53 prj = common.Projection(p1, p2, method=Mock()) 62 prj.connection_manager = MockConnectionManager() 63 assert_equal(prj.size(gather=False), len(prj)) 54 orig_len = common.Projection.__len__ 55 common.Projection.__len__ = Mock(return_value=42) 56 n = prj.size(gather=False) 57 prj.__len__.assert_called() 58 common.Projection.__len__ = orig_len 64 59 65 60 def test_size_with_gather(): 66 61 orig_mpi_sum = common.recording.mpi_sum 62 orig_len = common.Projection.__len__ 67 63 common.recording.mpi_sum = Mock() 68 p1 = MockPopulation()69 p 2= MockPopulation()70 p rj = common.Projection(p1, p2, method=Mock())71 prj .connection_manager = MockConnectionManager()64 common.Projection.__len__ = Mock(return_value=42) 65 p1 = MockPopulation() 66 p2 = MockPopulation() 67 prj = common.Projection(p1, p2, method=Mock()) 72 68 prj.size(gather=True) 73 69 common.recording.mpi_sum.assert_called_with(len(prj)) 74 70 common.recording.mpi_sum = orig_mpi_sum 75 76 def test__getitem(): 77 p1 = MockPopulation() 78 p2 = MockPopulation() 79 prj = common.Projection(p1, p2, method=Mock()) 80 prj.connection_manager = MockConnectionManager() 81 assert_equal(prj[0], 888) 71 common.Projection.__len__ = orig_len 82 72 83 73 def test_set_weights(): … … 87 77 prj.synapse_type = "foo" 88 78 prj.post.local_cells = [0] 89 prj.connection_manager = MockConnectionManager() 90 prj.connection_manager.set = Mock() 79 prj.set = Mock() 91 80 prj.setWeights(0.5) 92 prj. connection_manager.set.assert_called_with('weight', 0.5)81 prj.set.assert_called_with('weight', 0.5) 93 82 94 83 def test_randomize_weights(): 95 p1 = MockPopulation() 96 p2 = MockPopulation() 97 prj = common.Projection(p1, p2, method=Mock()) 98 prj.connection_manager = MockConnectionManager() 99 prj.setWeights = Mock() 84 orig_len = common.Projection.__len__ 85 common.Projection.__len__ = Mock(return_value=42) 86 p1 = MockPopulation() 87 p2 = MockPopulation() 88 prj = common.Projection(p1, p2, method=Mock()) 89 prj.set = Mock() 100 90 rd = Mock() 101 91 rd.next = Mock(return_value=777) 102 92 prj.randomizeWeights(rd) 103 93 rd.next.assert_called_with(len(prj)) 104 prj.setWeights.assert_called_with(777) 94 prj.set.assert_called_with('weight', 777) 95 common.Projection.__len__ = orig_len 105 96 106 97 def test_set_delays(): … … 108 99 p2 = MockPopulation() 109 100 prj = common.Projection(p1, p2, method=Mock()) 110 prj.connection_manager = MockConnectionManager() 111 prj.connection_manager.set = Mock() 101 prj.set = Mock() 112 102 prj.setDelays(0.5) 113 prj. connection_manager.set.assert_called_with('delay', 0.5)103 prj.set.assert_called_with('delay', 0.5) 114 104 115 105 def test_randomize_delays(): 116 p1 = MockPopulation() 117 p2 = MockPopulation() 118 prj = common.Projection(p1, p2, method=Mock()) 119 prj.connection_manager = MockConnectionManager() 120 prj.setDelays = Mock() 106 orig_len = common.Projection.__len__ 107 common.Projection.__len__ = Mock(return_value=42) 108 p1 = MockPopulation() 109 p2 = MockPopulation() 110 prj = common.Projection(p1, p2, method=Mock()) 111 prj.set = Mock() 121 112 rd = Mock() 122 113 rd.next = Mock(return_value=777) 123 114 prj.randomizeDelays(rd) 124 115 rd.next.assert_called_with(len(prj)) 125 prj.setDelays.assert_called_with(777) 116 prj.set.assert_called_with('delay', 777) 117 common.Projection.__len__ = orig_len 126 118 127 119 def test_set_synapse_dynamics_param(): … … 129 121 p2 = MockPopulation() 130 122 prj = common.Projection(p1, p2, method=Mock()) 131 prj.connection_manager = MockConnectionManager() 132 prj.connection_manager.set = Mock() 123 prj.set = Mock() 133 124 prj.setSynapseDynamics('U', 0.5) 134 prj. connection_manager.set.assert_called_with('U', 0.5)125 prj.set.assert_called_with('U', 0.5) 135 126 136 127 def test_get_weights(): … … 138 129 p2 = MockPopulation() 139 130 prj = common.Projection(p1, p2, method=Mock()) 140 prj.connection_manager = MockConnectionManager() 141 prj.connection_manager.get = Mock() 131 prj.get = Mock() 142 132 prj.getWeights(format='list', gather=False) 143 prj. connection_manager.get.assert_called_with('weight', 'list')133 prj.get.assert_called_with('weight', 'list') 144 134 145 135 def test_get_delays(): … … 147 137 p2 = MockPopulation() 148 138 prj = common.Projection(p1, p2, method=Mock()) 149 prj.connection_manager = MockConnectionManager() 150 prj.connection_manager.get = Mock() 139 prj.get = Mock() 151 140 prj.getDelays(format='list', gather=False) 152 prj. connection_manager.get.assert_called_with('delay', 'list')141 prj.get.assert_called_with('delay', 'list') 153 142 154 143 def test_save_connections(): … … 159 148 p2 = MockPopulation() 160 149 prj = common.Projection(p1, p2, method=Mock()) 161 prj.connection_manager = MockConnectionManager()162 150 prj.connections = [MockConnection(), MockConnection(), MockConnection()] 163 151 prj.saveConnections(filename, gather=False, compatible_output=False) … … 172 160 p2 = MockPopulation() 173 161 prj = common.Projection(p1, p2, method=Mock()) 174 prj. connection_manager = MockConnectionManager()162 prj.get = Mock(return_value=range(5)) 175 163 prj.printWeights(filename, format='list', gather=False) 164 prj.get.assert_called_with('weight', format='list', gather=False) 176 165 assert os.path.exists(filename) 177 166 os.remove(filename) … … 184 173 p2 = MockPopulation() 185 174 prj = common.Projection(p1, p2, method=Mock()) 186 prj. connection_manager = MockConnectionManager()175 prj.get = Mock(return_value=numpy.arange(5.0)) 187 176 prj.printWeights(filename, format='array', gather=False) 177 prj.get.assert_called_with('weight', format='array', gather=False) 188 178 assert os.path.exists(filename) 189 179 os.remove(filename) … … 214 204 215 205 def test_describe(): 206 orig_len = common.Projection.__len__ 207 common.Projection.__len__ = Mock(return_value=42) 216 208 p1 = MockPopulation() 217 209 p2 = MockPopulation() 218 210 prj = common.Projection(p1, p2, method=Mock(), synapse_dynamics=standardmodels.SynapseDynamics()) 219 prj.connection_manager = MockConnectionManager()220 211 prj.pre.describe = Mock() 221 212 prj.post.describe = Mock() 222 213 assert isinstance(prj.describe(engine='string'), basestring) 223 214 assert isinstance(prj.describe(template=None), dict) 215 common.Projection.__len__ = orig_len
