Changeset 379

Show
Ignore:
Timestamp:
06/20/08 16:47:59 (5 months ago)
Author:
apdavison
Message:

Got some more Connectors working in neuron2.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/neuron2/__init__.py

    r378 r379  
    6565    """Return the current time in the simulation.""" 
    6666    return simulator.state.t 
    67 common.get_current_time = get_current_time 
     67#common.get_current_time = get_current_time 
    6868 
    6969def get_time_step(): 
    7070    return simulator.state.dt 
    71 common.get_time_step = get_time_step 
     71#common.get_time_step = get_time_step 
    7272 
    7373def get_min_delay(): 
    7474    return simulator.state.min_delay 
    75 common.get_min_delay = get_min_delay 
     75#common.get_min_delay = get_min_delay 
    7676 
    7777def num_processes(): 
     
    263263        self._all_ids = self._all_ids.reshape(self.dim) 
    264264        self._mask_local = self._mask_local.reshape(self.dim) 
     265        self.cell = self._all_ids # temporary, awaiting harmonisation 
    265266         
    266267        simulator.initializer.register(self) 
     
    288289     
    289290    def __iter__(self): 
    290         """Iterator over cell ids.""" 
     291        """Iterator over cell ids on the local node.""" 
    291292        return iter(self._local_ids) 
    292293 
     
    304305 
    305306    def ids(self): 
    306         """Iterator over cell ids.""" 
     307        """Iterator over cell ids on the local node.""" 
    307308        return self.__iter__() 
     309     
     310    def all(self): 
     311        """Iterator over cell ids on all nodes.""" 
     312        return self._all_ids.flat 
    308313     
    309314    def locate(self, id): 
     
    603608        ## Create connections 
    604609        if isinstance(method, str): 
    605             connection_method = getattr(self,'_%s' % method)    
    606             connection_method(method_parameters) 
     610            raise Exception('Connection methods as strings no longer supported. Please use a Connector.') 
    607611        elif isinstance(method, common.Connector): 
    608612            method.connect(self) 
     
    628632    # --- Connection methods --------------------------------------------------- 
    629633     
     634    # --- Methods for setting connection parameters ---------------------------- 
     635     
     636    def setWeights(self, w): 
     637        """ 
     638        w can be a single number, in which case all weights are set to this 
     639        value, or a list/1D array of length equal to the number of connections 
     640        in the population. 
     641        Weights should be in nA for current-based and µS for conductance-based 
     642        synapses. 
     643        """ 
     644        if isinstance(w, float) or isinstance(w, int): 
     645            logging.info("Projection %s: setWeights(%s)" % (self.label, w)) 
     646            for nc in self.connections: 
     647                nc.weight[0] = w # should first check weight value is ok, i.e. +ve for conductance-based, -ve for inhibitory current-based, not outside the weight limits for STDP...  
     648        elif isinstance(w, list) or isinstance(w, numpy.ndarray): 
     649            assert len(w) == len(self), "List of weights has length %d, Projection %s has length %d" % (len(w), self.label, len(self)) 
     650            logging.info("Projection %s: setWeights(iterable(min=%s, max=%s))" % (self.label, min(w), max(w))) 
     651            for nc, weight in zip(self.connections, w): 
     652                nc.weight[0] = w 
     653        else: 
     654            raise TypeError("Argument should be a numeric type (int, float...), a list, or a numpy array.") 
     655         
     656    def setDelays(self, d): 
     657        """ 
     658        d can be a single number, in which case all delays are set to this 
     659        value, or a list/1D array of length equal to the number of connections 
     660        in the population. 
     661        """ 
     662        if isinstance(d, float) or isinstance(d, int): 
     663            if d < get_min_delay(): 
     664                raise Exception("Delays must be greater than or equal to the minimum delay, currently %g ms" % get_min_delay()) 
     665            logging.info("Projection %s: setDelays(%s)" % (self.label, d)) 
     666            for nc in self.connections: 
     667                nc.delay = d 
     668            # if we have STDP, need to update pre2wa and post2wa delays as well 
     669            if self.synapse_dynamics and self.synapse_dynamics.slow: 
     670                ddf = self.synapse_dynamics.slow.dendritic_delay_fraction 
     671                for pre2wa, post2wa in self.stdp_connections: 
     672                    pre2wa.delay = float(d)*(1-ddf) 
     673                    post2wa.delay = float(d)*ddf 
     674        elif isinstance(d, list) or isinstance(d, numpy.ndarray): 
     675            d = numpy.array(d) 
     676            if not (d-get_min_delay()>=0).all(): 
     677                raise Exception("Delays must be greater than or equal to the minimum delay, currently %g ms" % get_min_delay()) 
     678            assert len(d) == len(self), "List of delays has length %d, Projection %s has length %d" % (len(d), self.label, len(self)) 
     679            logging.info("Projection %s: setDelays(iterable(min=%s, max=%s))" % (self.label, min(d), max(d))) 
     680            for nc, delay in zip(self.connections, d): 
     681                nc.delay = delay 
     682            # if we have STDP, need to update pre2wa and post2wa delays as well 
     683            if self.synapse_dynamics and self.synapse_dynamics.slow: 
     684                ddf = self.synapse_dynamics.slow.dendritic_delay_fraction 
     685                for (pre2wa, post2wa), delay in zip(self.stdp_connections, d): 
     686                    pre2wa.delay = float(delay)*(1-ddf) 
     687                    post2wa.delay = float(delay)*ddf 
     688        else: 
     689            raise TypeError("Argument should be a numeric type (int, float...), a list, or a numpy array.") 
     690         
  • trunk/src/neuron2/connectors.py

    r377 r379  
    88from pyNN.neuron2 import simulator 
    99import numpy 
    10 from math import * 
     10import logging 
     11from numpy import arccos, arcsin, arctan, arctan2, ceil, cos, cosh, e, exp, \ 
     12                  fabs, floor, fmod, hypot, ldexp, log, log10, modf, pi, power, \ 
     13                  sin, sinh, sqrt, tan, tanh 
    1114 
    1215# ============================================================================== 
     
    5962    delays = connector.delays_iterator() 
    6063    if isinstance(projection.rng, NativeRNG): 
    61         rng = neuron.h.Random(0 or projection.rng.seed), 
     64        rng = simulator.h.Random(0 or projection.rng.seed) 
    6265        rarr = [rng.uniform(0,1)] 
    6366        rarr.extend([rng.repick() for j in xrange(projection.pre.size*projection.post.size-1)]) 
     
    6871        # in case of uneven distribution of neurons between MPI nodes 
    6972        rarr = numpy.concatenate([projection.rng.next(projection.post.size, 'uniform', (0,1)) \ 
    70                                       for src in projection.pre._all_ids]) 
     73                                      for src in projection.pre.all()]) 
    7174    j = 0 
    72     required_rarr_length = projection.pre.size * len(projection.post._local_ids) 
    73     assert len(rarr) >= required_rarr_length, \ 
    74            "Random array is too short (%d elements, needs %d)" % (len(rarr), required_rarr_length) 
     75    required_length = projection.pre.size * len(projection.post._local_ids)  
     76    assert len(rarr) >= required_length, \ 
     77           "Random array is too short (%d elements, needs %d)" % (len(rarr), required_length) 
    7578         
    7679    create = rarr<p 
    77     for src in projection.pre._all_ids
     80    for src in projection.pre.all()
    7881        for tgt in projection.post:     
    7982            if connector.allow_self_connections or projection.pre != projection.post or tgt != src: 
     
    8386                                                     weights.next(), delays.next(), 
    8487                                                     projection.synapse_type)) 
    85  
     88            j += 1 
     89    assert j == required_length 
    8690 
    8791class AllToAllConnector(common.AllToAllConnector, HocConnector):     
     
    9498     
    9599    def connect(self, projection): 
    96         weights = connector.weights_iterator() 
    97         delays = connector.delays_iterator() 
     100        weights = self.weights_iterator() 
     101        delays = self.delays_iterator() 
    98102        if projection.pre.dim == projection.post.dim: 
    99103            for tgt in projection.post: 
     
    103107        else: 
    104108            raise Exception("OneToOneConnector does not support presynaptic and postsynaptic Populations of different sizes.") 
    105         return hoc_commands 
    106  
    107  
    108 #class FixedProbabilityConnector(common.FixedProbabilityConnector, HocConnector): 
    109 #     
    110 #    def connect(self, projection): 
    111 #        weight = self.getWeight(self.weights) 
    112 #        delay = self.getDelay(self.delays) 
    113 #        if isinstance(projection.rng, NativeRNG): 
    114 #            hoc_commands = ['rng = new Random(%d)' % 0 or distribution.rng.seed, 
    115 #                            'tmp = rng.uniform(0,1)'] 
    116 #            # Here we are forced to execute the commands on line to be able to 
    117 #            # catch the connections from NEURON 
    118 #            hoc_execute(hoc_commands) 
    119 #            #rarr = [HocToPy.get('rng.repick()','float') for j in xrange(projection.pre.size*projection.post.size)] 
    120 #            rarr = [h.rng.repick() for j in xrange(projection.pre.size*projection.post.size)] 
    121 #        else: 
    122 #            # We use concatenate, rather than just creating 
    123 #            # n=projection.pre.size*projection.post.size random numbers, 
    124 #            # in case of uneven distribution of neurons between MPI nodes 
    125 #            rarr = numpy.concatenate([projection.rng.next(projection.post.size, 'uniform', (0,1)) \ 
    126 #                                      for src in projection.pre.fullgidlist]) 
    127 #        hoc_commands = [] 
    128 #        j = 0 
    129 #        required_rarr_length = len(projection.pre.fullgidlist) * len(projection.post.gidlist) 
    130 #        assert len(rarr) >= required_rarr_length, \ 
    131 #               "Random array is too short (%d elements, needs %d)" % (len(rarr), required_rarr_length) 
    132 #        for src in projection.pre.fullgidlist: 
    133 #            for tgt in projection.post.gidlist: 
    134 #                if self.allow_self_connections or projection.pre != projection.post or tgt != src: 
    135 #                    if rarr[j] < self.p_connect:   
    136 #                        if hasattr(weight, 'next'): 
    137 #                            w = weight.next() 
    138 #                        else: 
    139 #                            w = weight 
    140 #                        if hasattr(delay, 'next'): 
    141 #                            d = delay.next() 
    142 #                        else: 
    143 #                            d = delay 
    144 #                        hoc_commands += self.singleConnect(projection, src, tgt, w, d)  
    145 #                j += 1 
    146 #        return hoc_commands 
    147 
    148  
    149 #class DistanceDependentProbabilityConnector(common.DistanceDependentProbabilityConnector, HocConnector): 
    150 #     
    151 #    def connect(self, projection): 
    152 #        weight = self.getWeight(self.weights) 
    153 #        delay = self.getDelay(self.delays) 
    154 #        periodic_boundaries = self.periodic_boundaries 
    155 #        if periodic_boundaries is not None: 
    156 #            dimensions = projection.post.dim 
    157 #            periodic_boundaries = numpy.concatenate((dimensions, numpy.zeros(3-len(dimensions)))) 
    158 #        if isinstance(projection.rng, NativeRNG): 
    159 #            hoc_commands = ['rng = new Random(%d)' % 0 or distribution.rng.seed, 
    160 #                            'tmp = rng.uniform(0,1)'] 
    161 #            # Here we are forced to execute the commands on line to be able to 
    162 #            # catch the connections from NEURON 
    163 #            hoc_execute(hoc_commands) 
    164 #            #rarr = [HocToPy.get('rng.repick()','float') for j in xrange(projection.pre.size*projection.post.size)] 
    165 #            rarr = [h.rng.repick() for j in xrange(projection.pre.size*projection.post.size)] 
    166 #        else: 
    167 #            rarr = projection.rng.uniform(0,1, projection.pre.size*projection.post.size) 
    168 #        # We need to use the gid stored as ID, so we should modify the loop to scan the global gidlist (containing ID) 
    169 #        hoc_commands = [] 
    170 #        j = 0 
    171 #        for tgt in projection.post.gidlist: 
    172 #            idx_pre  = 0 
    173 #            distances = common.distances(projection.pre, tgt, self.mask, self.scale_factor, self.offset, periodic_boundaries) 
    174 #            for src in projection.pre.fullgidlist: 
    175 #                if self.allow_self_connections or projection.pre != projection.post or tgt != src:  
    176 #                    # calculate the distance between the two cells : 
    177 #                    d = distances[idx_pre][0] 
    178 #                    p = eval(self.d_expression) 
    179 #                    if p >= 1 or (0 < p < 1 and rarr[j] < p): 
    180 #                        if hasattr(weight, 'next'): 
    181 #                            w = weight.next() 
    182 #                        else: 
    183 #                            w = weight 
    184 #                        if hasattr(delay, 'next'): 
    185 #                            d = delay.next() 
    186 #                        else: 
    187 #                            d = delay 
    188 #                        hoc_commands += self.singleConnect(projection, src, tgt, w, d) 
    189 #                j += 1 
    190 #                idx_pre += 1 
    191 #        return hoc_commands 
    192 
     109 
     110 
     111class FixedProbabilityConnector(common.FixedProbabilityConnector, HocConnector): 
     112 
     113    def connect(self, projection): 
     114        logging.info("Connecting %s to %s with probability %s" % (projection.pre.label, 
     115                                                                  projection.post.label, 
     116                                                                  self.p_connect)) 
     117        probabilistic_connect(self, projection, self.p_connect) 
     118 
     119class DistanceDependentProbabilityConnector(common.DistanceDependentProbabilityConnector, HocConnector): 
     120     
     121    def connect(self, projection): 
     122        periodic_boundaries = self.periodic_boundaries 
     123        if periodic_boundaries is not None: 
     124            dimensions = projection.post.dim 
     125            periodic_boundaries = numpy.concatenate((dimensions, numpy.zeros(3-len(dimensions)))) 
     126        j = 0 
     127        # this is not going to work for parallel sims 
     128        # either build up d gradually by iterating over local target cells, 
     129        # or use the local_mask somehow to pick out only part of the distance matrix 
     130        d = common.distances(projection.pre, projection.post, self.mask, 
     131                             self.scale_factor, self.offset, 
     132                             periodic_boundaries) 
     133        p_array = eval(self.d_expression) 
     134        probabilistic_connect(self, projection, p_array.flatten()) 
     135 
    193136#class _FixedNumberConnector(common.FixedNumberPreConnector, HocConnector): 
    194137#     
  • trunk/src/neuron2/simulator.py

    r377 r379  
    8888        if compatible_output: 
    8989            recording.write_compatible_output(filename, filename, Recorder.formats[self.variable], 
    90                                               self.population, common.get_time_step()
     90                                              self.population, state.dt
    9191         
    9292class _Initializer(object): 
  • trunk/test/neuron2tests.py

    r378 r379  
    77import pyNN.common as common 
    88import pyNN.random as random 
    9 from pyNN.neuron import * 
    109import unittest, sys, numpy 
    1110import numpy.random 
     
    4847        #self.assertAlmostEqual(HocToPy.get('cell%d.esyn.tau' % ifcell, 'float'), 3.141592654, places=5) 
    4948        try: 
    50             self.assertAlmostEqual(getattr(h, 'cell%d' % ifcell).esyn.tau, 3.141592654, places=5) 
     49            self.assertAlmostEqual(getattr(neuron.h, 'cell%d' % ifcell).esyn.tau, 3.141592654, places=5) 
    5150        except AttributeError: # if the cell is not on that node 
    5251            pass 
     
    475474        """Population.record_v() and Population.print_v(): not a full test, just checking  
    476475        # there are no Exceptions raised.""" 
    477         rng = NumpyRNG(123) 
     476        rng = random.NumpyRNG(123) 
    478477        v_reset  = -65.0 
    479478        v_thresh = -50.0 
    480         uniformDistr = RandomDistribution(rng=rng, distribution='uniform', parameters=[v_reset, v_thresh]) 
     479        uniformDistr = random.RandomDistribution(rng=rng, distribution='uniform', parameters=[v_reset, v_thresh]) 
    481480        self.pop2.randomInit(uniformDistr) 
    482481        self.pop2.record_v([self.pop2[0,0], self.pop2[1,1]]) 
     
    507506 
    508507# ============================================================================== 
    509 #class ProjectionInitTest(unittest.TestCase): 
    510 #    """Tests of the __init__() method of the Projection class.""" 
    511 #         
    512 #    def setUp(self): 
    513 #        neuron.Population.nPop = 0 
    514 #        neuron.Projection.nProj = 0 
    515 #        self.target33    = neuron.Population((3,3), neuron.IF_curr_alpha) 
    516 #        self.target6     = neuron.Population((6,), neuron.IF_curr_alpha) 
    517 #        self.source5     = neuron.Population((5,), neuron.SpikeSourcePoisson) 
    518 #        self.source22    = neuron.Population((2,2), neuron.SpikeSourcePoisson) 
    519 #        self.source33    = neuron.Population((3,3), neuron.SpikeSourcePoisson) 
    520 #        self.expoisson33 = neuron.Population((3,3), neuron.SpikeSourcePoisson,{'rate': 100}) 
    521 #         
    522 #    def testAllToAll(self): 
    523 #        """For all connections created with "allToAll" it should be possible to 
    524 #        obtain the weight using the top-level HocObject""" 
    525 #        for srcP in [self.source5, self.source22]: 
    526 #            for tgtP in [self.target6, self.target33]: 
    527 #                print "gid_counter = ", neuron.gid_counter 
    528 #                #prj1 = neuron.Projection(srcP, tgtP, 'allToAll') 
    529 #                prj2 = neuron.Projection(srcP, tgtP, neuron.AllToAllConnector()) 
    530 #                #prj1.setWeights(1.234) 
    531 #                #prj2.setWeights(1.234
    532 #                #for prj in prj1, prj2: 
    533 #                #    hoc_list = getattr(h, prj.label) 
    534 #                #    weights = [] 
    535 #                #    for connection_id in prj.connections: 
    536 #                #        weights.append(hoc_list.object(prj.connections.index(connection_id)).weight[0]
    537 #                #    assert weights == [1.234]*len(prj) 
     508class ProjectionInitTest(unittest.TestCase): 
     509    """Tests of the __init__() method of the Projection class.""" 
     510         
     511    def setUp(self): 
     512        neuron.Population.nPop = 0 
     513        neuron.Projection.nProj = 0 
     514        self.target33    = neuron.Population((3,3), neuron.IF_curr_alpha) 
     515        self.target6     = neuron.Population((6,), neuron.IF_curr_alpha) 
     516        self.source5     = neuron.Population((5,), neuron.SpikeSourcePoisson) 
     517        self.source22    = neuron.Population((2,2), neuron.SpikeSourcePoisson) 
     518        self.source33    = neuron.Population((3,3), neuron.SpikeSourcePoisson) 
     519        self.expoisson33 = neuron.Population((3,3), neuron.SpikeSourcePoisson,{'rate': 100}) 
     520         
     521    def testAllToAll(self): 
     522        """For all connections created with "allToAll" it should be possible to 
     523        obtain the weight using the top-level HocObject""" 
     524        for srcP in [self.source5, self.source22, self.target33]: 
     525            for tgtP in [self.target6, self.target33]: 
     526                #print "gid_counter = ", neuron.simulator.state.gid_counter 
     527                if srcP == tgtP: 
     528                    prj = neuron.Projection(srcP, tgtP, neuron.AllToAllConnector(allow_self_connections=False)) 
     529                else: 
     530                    prj = neuron.Projection(srcP, tgtP, neuron.AllToAllConnector()
     531                prj.setWeights(1.234) 
     532                weights = [] 
     533                for nc in prj.connections: 
     534                    weights.append(nc.weight[0]) 
     535                assert weights == [1.234]*len(prj
     536         
    538537             
    539 #    def testFixedProbability(self): 
    540 #        """For all connections created with "fixedProbability"...""" 
    541 #        for srcP in [self.source5, self.source22]: 
    542 #            for tgtP in [self.target6, self.target33]: 
    543 #                prj1 = neuron.Projection(srcP, tgtP, 'fixedProbability', 0.5, rng=NumpyRNG(12345)) 
    544 #                prj2 = neuron.Projection(srcP, tgtP, 'fixedProbability', 0.5, rng=NativeRNG(12345)) 
    545 #                prj3 = neuron.Projection(srcP, tgtP, FixedProbabilityConnector(0.5), rng=NumpyRNG(12345)) 
    546 #                assert (0 < len(prj1) < len(srcP)*len(tgtP)) \ 
    547 #                       and (0 < len(prj2) < len(srcP)*len(tgtP)) \ 
    548 #                       and (0 < len(prj3) < len(srcP)*len(tgtP)) 
    549 #                 
    550 #    def testOneToOne(self): 
    551 #        """For all connections created with "OneToOne" ...""" 
    552 #        prj1 = neuron.Projection(self.source33, self.target33, 'oneToOne') 
    553 #        prj2 = neuron.Projection(self.source33, self.target33, neuron.OneToOneConnector()) 
    554 #        assert len(prj1.connections) == len(self.target33.gidlist), prj1.connections 
    555 #        assert len(prj2.connections) == len(self.target33.gidlist), prj2.connections 
    556 #      
    557 #    def testDistanceDependentProbability(self): 
    558 #        """For all connections created with "distanceDependentProbability"...""" 
    559 #        # Test should be improved..." 
    560 #        for rngclass in (NumpyRNG, NativeRNG): 
    561 #            for expr in ('exp(-d)', 'd < 0.5'): 
    562 #                prj1 = neuron.Projection(self.source33, self.target33, 
    563 #                                         'distanceDependentProbability', 
    564 #                                         {'d_expression' : expr}, rng=rngclass(12345)) 
    565 #                prj2 = neuron.Projection(self.source33, self.target33, 
    566 #                                         neuron.DistanceDependentProbabilityConnector(d_expression=expr), 
    567 #                                         rng=rngclass(12345)) 
    568 #                assert (0 < len(prj1) < len(self.source33)*len(self.target33)) \ 
    569 #                   and (0 < len(prj2) < len(self.source33)*len(self.target33))  
    570 #                assert prj1.connections == prj2.connections, "%s %s" % (rngclass, expr) 
     538    def testFixedProbability(self): 
     539        """For all connections created with "fixedProbability"...""" 
     540        for srcP in [self.source5, self.source22]: 
     541            for tgtP in [self.target6, self.target33]: 
     542                prj1 = neuron.Projection(srcP, tgtP, neuron.FixedProbabilityConnector(0.5), rng=random.NumpyRNG(12345)) 
     543                prj2 = neuron.Projection(srcP, tgtP, neuron.FixedProbabilityConnector(0.5), rng=random.NativeRNG(12345)) 
     544                for prj in prj1, prj2: 
     545                    assert (0 < len(prj) < len(srcP)*len(tgtP)), 'len(prj) = %d, len(srcP)*len(tgtP) = %d' % (len(prj), len(srcP)*len(tgtP)) 
     546                 
     547    def testOneToOne(self): 
     548        """For all connections created with "OneToOne" ...""" 
     549        prj = neuron.Projection(self.source33, self.target33, neuron.OneToOneConnector()) 
     550        assert len(prj.connections) == len(self.target33._local_ids), prj.connections 
     551      
     552    def testDistanceDependentProbability(self): 
     553        """For all connections created with "distanceDependentProbability"...""" 
     554        # Test should be improved..." 
     555        for rngclass in (random.NumpyRNG, random.NativeRNG): 
     556            for expr in ('exp(-d)', 'd < 0.5'): 
     557        #rngclass = random.NumpyRNG 
     558        #expr = 'exp(-d)' 
     559                prj = neuron.Projection(self.source33, self.target33, 
     560                                        neuron.DistanceDependentProbabilityConnector(d_expression=expr), 
     561                                        rng=rngclass(12345)) 
     562                assert (0 < len(prj) < len(self.source33)*len(self.target33)) 
     563         
    571564# 
    572565#    def testFixedNumberPre(self):