Changeset 821

Show
Ignore:
Timestamp:
11/16/10 19:26:42 (3 years ago)
Author:
apdavison
Message:

Minor fixes and trivial whitespace changes, from playing with the pep8 utility.

Location:
trunk
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/common.py

    r820 r821  
    1212    check_weight() 
    1313    check_delay() 
    14      
     14 
    1515Accessing individual neurons: 
    1616    IDMixin 
    17      
     17 
    1818Common API implementation/base classes: 
    1919  1. Simulation set-up and control: 
     
    4949 
    5050if not 'simulator' in locals(): 
    51     simulator = None # should be set by simulator-specific modules 
     51    simulator = None  # should be set by simulator-specific modules 
    5252 
    5353DEFAULT_WEIGHT = 0.0 
     
    5959logger = logging.getLogger("PyNN") 
    6060 
    61 # ============================================================================== 
     61# ============================================================================= 
    6262#   Utility functions and classes 
    63 # ============================================================================== 
     63# ============================================================================= 
    6464 
    6565 
    6666def is_conductance(target_cell): 
    6767    """ 
    68     Returns True if the target cell uses conductance-based synapses, False if it 
    69     uses current-based synapses, and None if the synapse-basis cannot be determined. 
     68    Returns True if the target cell uses conductance-based synapses, False if 
     69    it uses current-based synapses, and None if the synapse-basis cannot be 
     70    determined. 
    7071    """ 
    7172    if hasattr(target_cell, 'local') and target_cell.local and hasattr(target_cell, 'cellclass'): 
    7273        if isinstance(target_cell.cellclass, type): 
    7374            is_conductance = target_cell.cellclass.conductance_based 
    74         else: # where cellclass is a string, i.e. for native cell types in NEST 
     75        else:  # where cellclass is a string, i.e. for native cell types in NEST 
    7576            is_conductance = "cond" in target_cell.cellclass 
    7677    else: 
     
    7879    return is_conductance 
    7980 
     81 
    8082def check_weight(weight, synapse_type, is_conductance): 
    81     #print "check_weight: node=%s, weight=%s, synapse_type=%s, is_conductance=%s" % (rank(), weight, synapse_type, is_conductance) 
    8283    if weight is None: 
    8384        weight = DEFAULT_WEIGHT 
    8485    if core.is_listlike(weight): 
    8586        weight = numpy.array(weight) 
    86         nan_filter = (1-numpy.isnan(weight)).astype(bool) # weight arrays may contain NaN, which should be ignored 
     87        nan_filter = (1 - numpy.isnan(weight)).astype(bool) # weight arrays may contain NaN, which should be ignored 
    8788        filtered_weight = weight[nan_filter] 
    88         all_negative = (filtered_weight<=0).all() 
    89         all_positive = (filtered_weight>=0).all() 
     89        all_negative = (filtered_weight <= 0).all() 
     90        all_positive = (filtered_weight >= 0).all() 
    9091        if not (all_negative or all_positive): 
    9192            raise errors.InvalidWeightError("Weights must be either all positive or all negative") 
     
    9899        if not all_positive: 
    99100            raise errors.InvalidWeightError("Weights must be positive for conductance-based and/or excitatory synapses") 
    100     elif is_conductance==False and synapse_type == 'inhibitory': 
     101    elif is_conductance == False and synapse_type == 'inhibitory': 
    101102        if not all_negative: 
    102103            raise errors.InvalidWeightError("Weights must be negative for current-based, inhibitory synapses") 
    103     else: # is_conductance is None. This happens if the cell does not exist on the current node. 
     104    else:  # is_conductance is None. This happens if the cell does not exist on the current node. 
    104105        logger.debug("Can't check weight, conductance status unknown.") 
    105106    return weight 
     107 
    106108 
    107109def check_delay(delay): 
     
    110112    # If the delay is too small , we have to throw an error 
    111113    if delay < get_min_delay() or delay > get_max_delay(): 
    112         raise errors.ConnectionError("delay (%s) is out of range [%s,%s]" % (delay, get_min_delay(), get_max_delay())) 
     114        raise errors.ConnectionError("delay (%s) is out of range [%s,%s]" % \ 
     115                                     (delay, get_min_delay(), get_max_delay())) 
    113116    return delay 
    114117 
    115118 
    116 # ============================================================================== 
     119# ============================================================================= 
    117120#   Accessing individual neurons 
    118 # ============================================================================== 
     121# ============================================================================= 
    119122 
    120123class IDMixin(object): 
     
    137140                val = self.get_parameters()[name] 
    138141            except KeyError: 
    139                 raise errors.NonExistentParameterError(name, self.cellclass.__name__, 
     142                raise errors.NonExistentParameterError(name, 
     143                                                       self.cellclass.__name__, 
    140144                                                       self.cellclass.get_parameter_names()) 
    141145        return val 
    142      
     146 
    143147    def __setattr__(self, name, value): 
    144148        if name == "parent": 
    145149            object.__setattr__(self, name, value) 
    146150        elif self.cellclass.has_parameter(name): 
    147             self.set_parameters(**{name:value}) 
     151            self.set_parameters(**{name: value}) 
    148152        else: 
    149153            object.__setattr__(self, name, value) 
    150154 
    151155    def set_parameters(self, **parameters): 
    152         """Set cell parameters, given as a sequence of parameter=value arguments.""" 
     156        """ 
     157        Set cell parameters, given as a sequence of parameter=value arguments. 
     158        """ 
    153159        # if some of the parameters are computed from the values of other 
    154160        # parameters, need to get and translate all parameters 
     
    156162            if self.is_standard_cell: 
    157163                computed_parameters = self.cellclass.computed_parameters() 
    158                 have_computed_parameters = numpy.any([p_name in computed_parameters for p_name in parameters]) 
    159                 if have_computed_parameters:      
     164                have_computed_parameters = numpy.any([p_name in computed_parameters 
     165                                                      for p_name in parameters]) 
     166                if have_computed_parameters: 
    160167                    all_parameters = self.get_parameters() 
    161168                    all_parameters.update(parameters) 
     
    165172        else: 
    166173            raise errors.NotLocalError("Cannot set parameters for a cell that does not exist on this node.") 
    167      
     174 
    168175    def get_parameters(self): 
    169176        """Return a dict of all cell parameters.""" 
     
    185192        else: 
    186193            return celltype 
    187       
     194 
    188195    @property 
    189196    def is_standard_cell(self): 
    190         return (type(self.cellclass) == type and issubclass(self.cellclass, standardmodels.StandardCellType)) 
    191          
     197        return (type(self.cellclass) == type and 
     198                issubclass(self.cellclass, standardmodels.StandardCellType)) 
     199 
    192200    def _set_position(self, pos): 
    193201        """ 
    194202        Set the cell position in 3D space. 
    195          
     203 
    196204        Cell positions are stored in an array in the parent Population. 
    197205        """ 
     
    199207        assert len(pos) == 3 
    200208        self.parent._set_cell_position(self, pos) 
    201          
     209 
    202210    def _get_position(self): 
    203211        """ 
    204212        Return the cell position in 3D space. 
    205          
     213 
    206214        Cell positions are stored in an array in the parent Population, if any, 
    207215        or within the ID object otherwise. Positions are generated the first 
     
    211219 
    212220    position = property(_get_position, _set_position) 
    213      
     221 
    214222    @property 
    215223    def local(self): 
    216224        return self.parent.is_local(self) 
    217      
     225 
    218226    def inject(self, current_source): 
    219227        """Inject current from a current source object into the cell.""" 
     
    223231        """Get the initial value of a state variable of the cell.""" 
    224232        return self.parent._get_cell_initial_value(self, variable) 
    225          
     233 
    226234    def set_initial_value(self, variable, value): 
    227235        """Set the initial value of a state variable of the cell.""" 
    228236        self.parent._set_cell_initial_value(self, variable, value) 
    229237 
    230 # ============================================================================== 
     238 
     239# ============================================================================= 
    231240#   Functions for simulation set-up and control 
    232 # ============================================================================== 
     241# ============================================================================= 
     242 
    233243 
    234244def setup(timestep=DEFAULT_TIMESTEP, min_delay=DEFAULT_MIN_DELAY, 
     
    247257    if min_delay < timestep: 
    248258        "min_delay (%g) must be greater than timestep (%g)" % (min_delay, timestep) 
    249      
     259 
    250260def end(compatible_output=True): 
    251261    """Do any necessary cleaning up before exiting.""" 
    252262    raise NotImplementedError 
    253      
     263 
    254264def run(simtime): 
    255265    """Run the simulation for simtime ms.""" 
     
    259269    """ 
    260270    Reset the time to zero, neuron membrane potentials and synaptic weights to 
    261     their initial values, and delete any recorded data. The network structure is 
    262     not changed, nor is the specification of which neurons to record from.""" 
     271    their initial values, and delete any recorded data. The network structure 
     272    is not changed, nor is the specification of which neurons to record from. 
     273    """ 
    263274    simulator.reset() 
    264275 
     
    291302    return simulator.state.mpi_rank 
    292303 
    293 # ============================================================================== 
    294  Low-level API for creating, connecting and recording from individual neurons 
    295 # ============================================================================== 
     304# ============================================================================= 
     305Low-level API for creating, connecting and recording from individual neurons 
     306# ============================================================================= 
    296307 
    297308def build_create(population_class): 
     
    299310        """ 
    300311        Create n cells all of the same type. 
    301          
     312 
    302313        If n > 1, return a list of cell ids/references. 
    303314        If n==1, return just the single id. 
    304315        """ 
    305         return population_class(n, cellclass, cellparams) # return the Population or Population.all_cells? 
     316        return population_class(n, cellclass, cellparams)  # return the Population or Population.all_cells? 
    306317    return create 
    307318 
    308319def build_connect(projection_class, connector_class): 
    309     def connect(source, target, weight=0.0, delay=None, synapse_type=None, p=1, rng=None): 
     320    def connect(source, target, weight=0.0, delay=None, synapse_type=None, 
     321                p=1, rng=None): 
    310322        """ 
    311323        Connect a source of spikes to a synaptic target. 
    312          
    313         source and target can both be individual cells or lists of cells, in which 
    314         case all possible connections are made with probability p, using either the 
    315         random number generator supplied, or the default rng otherwise. 
    316         Weights should be in nA or µS. 
     324 
     325        source and target can both be individual cells or lists of cells, in 
     326        which case all possible connections are made with probability p, using 
     327        either the random number generator supplied, or the default rng 
     328        otherwise. Weights should be in nA or µS. 
    317329        """ 
    318330        if isinstance(source, IDMixin): 
     
    327339    """ 
    328340    Set one or more parameters of an individual cell or list of cells. 
    329      
     341 
    330342    param can be a dict, in which case val should not be supplied, or a string 
    331343    giving the parameter name, in which case val is the parameter value. 
     
    344356        assert isinstance(source, (BasePopulation, Assembly)) 
    345357        source._record(variable, to_file=filename) 
    346         simulator.recorder_list.append(source.recorders[variable]) # this is a bit hackish - better to add to Population.__del__? 
     358        simulator.recorder_list.append(source.recorders[variable])  # this is a bit hackish - better to add to Population.__del__? 
    347359    if variable == 'v': 
    348360        record.__doc__ = """ 
     
    356368 
    357369 
    358 # ============================================================================== 
     370# ============================================================================= 
    359371#   High-level API for creating, connecting and recording from populations of 
    360372#   neurons. 
    361 # ============================================================================== 
     373# ============================================================================= 
    362374 
    363375class BasePopulation(object): 
    364376    record_filter = None 
    365      
     377 
    366378    def __getitem__(self, index): 
    367379        """ 
     
    383395        else: 
    384396            raise TypeError("indices must be integers, slices, lists, arrays or tuples, not %s" % type(index).__name__) 
    385      
     397 
    386398    def __len__(self): 
    387399        """Return the total number of cells in the population (all nodes).""" 
    388400        return self.size 
    389      
     401 
    390402    def __iter__(self): 
    391403        """Iterator over cell ids on the local node.""" 
    392404        return iter(self.local_cells) 
    393      
     405 
    394406    def is_local(self, id): 
    395407        assert id.parent is self 
    396408        index = self.id_to_index(id) 
    397409        return self._mask_local[index] 
    398      
     410 
    399411    def all(self): 
    400412        """Iterator over cell ids on all nodes.""" 
     
    408420        index = self.id_to_index(id) 
    409421        return self.positions[:, index] 
    410      
     422 
    411423    def _set_cell_position(self, id, pos): 
    412424        index = self.id_to_index(id) 
     
    425437    def nearest(self, position): 
    426438        """Return the neuron closest to the specified position.""" 
    427         # doesn't always work correctly if a position is equidistant between two 
    428         # neurons, i.e. 0.5 should be rounded up, but it isn't always. 
     439        # doesn't always work correctly if a position is equidistant between 
     440        # two neurons, i.e. 0.5 should be rounded up, but it isn't always. 
    429441        # also doesn't take account of periodic boundary conditions 
    430         pos = numpy.array([position]*self.positions.shape[1]).transpose() 
     442        pos = numpy.array([position] * self.positions.shape[1]).transpose() 
    431443        dist_arr = (self.positions - pos)**2 
    432444        distances = dist_arr.sum(axis=0) 
    433445        nearest = distances.argmin() 
    434446        return self[nearest] 
    435      
    436     def get(self, parameter_name): # would be nice to add a 'gather' argument 
     447 
     448    def get(self, parameter_name):  # would be nice to add a 'gather' argument 
    437449        """ 
    438450        Get the values of a parameter for every local cell in the population. 
     
    443455            return self._get_array(parameter_name) 
    444456        else: 
    445             return [getattr(cell, parameter_name) for cell in self] # list or array? 
     457            return [getattr(cell, parameter_name) for cell in self]  # list or array? 
    446458 
    447459    def set(self, param, val=None): 
     
    450462        can be a dict, in which case val should not be supplied, or a string 
    451463        giving the parameter name, in which case val is the parameter value. 
    452         val can be a numeric value, or list of such (e.g. for setting spike times). 
     464        val can be a numeric value, or list of such (e.g. for setting spike 
     465        times). 
    453466        e.g. p.set("tau_m",20.0). 
    454467             p.set({'tau_m':20,'v_rest':-65}) 
     
    457470        # -- Proposed change to arguments -- 
    458471        #Set one or more parameters for every cell in the population. 
    459         #  
     472        # 
    460473        #Each value may be a single number or a list/array of numbers of the same 
    461474        #size as the population. If the parameter itself takes lists/arrays as 
    462475        #values (e.g. spike times), then the value provided may be either a 
    463476        #single lists/1D array, a list of lists/1D arrays, or a 2D array. 
    464         #  
     477        # 
    465478        #e.g. p.set(tau_m=20.0). 
    466479        #     p.set(tau_m=20, v_rest=[-65.0, -65.3, ... , -67.2]) 
     
    476489                param_dict[name] = float(val) 
    477490            elif isinstance(val, (list, numpy.ndarray)): 
    478                 pass # ought to check list/array only contains numeric types 
     491                pass  # ought to check list/array only contains numeric types 
    479492            else: 
    480493                raise errors.InvalidParameterValueError 
     
    496509        #accepts arguments x,y,z and returns a single value. 
    497510        #""" 
    498         if (self.size,) == value_array.shape: # the values are numbers or non-array objects 
     511        if (self.size,) == value_array.shape:  # the values are numbers or non-array objects 
    499512            local_values = value_array[self._mask_local] 
    500513            assert local_values.size == self.local_cells.size, "%d != %d" % (local_values.size, self.local_cells.size) 
    501         elif len(value_array.shape) == 2: # the values are themselves 1D arrays 
     514        elif len(value_array.shape) == 2:  # the values are themselves 1D arrays 
    502515            if value_array.shape[0] != self.size: 
    503                 raise errors.InvalidDimensionsError, "Population: %d, value_array first dimension: %s" % (self.size, 
    504                                                                                                           value_array.shape[0]) 
    505             local_values = value_array[self._mask_local] # not sure this works 
    506         else: 
    507             raise errors.InvalidDimensionsError, "Population: %d, value_array: %s" % (self.size, 
    508                                                                                       str(value_array.shape)) 
     516                raise errors.InvalidDimensionsError("Population: %d, value_array first dimension: %s" % (self.size, 
     517                                                                                                         value_array.shape[0])) 
     518            local_values = value_array[self._mask_local]  # not sure this works 
     519        else: 
     520            raise errors.InvalidDimensionsError("Population: %d, value_array: %s" % (self.size, 
     521                                                                                     str(value_array.shape))) 
    509522        assert local_values.shape[0] == self.local_cells.size, "%d != %d" % (local_values.size, self.local_cells.size) 
    510          
     523 
    511524        try: 
    512525            logger.debug("%s.tset('%s', array(shape=%s, min=%s, max=%s))", 
    513526                         self.label, parametername, value_array.shape, 
    514527                         value_array.min(), value_array.max()) 
    515         except TypeError: # min() and max() won't work for non-numeric values 
     528        except TypeError:  # min() and max() won't work for non-numeric values 
    516529            logger.debug("%s.tset('%s', non_numeric_array(shape=%s))", 
    517530                         self.label, parametername, value_array.shape) 
    518          
     531 
    519532        # Set the values for each cell 
    520533        if hasattr(self, "_set_array"): 
     
    537550            self._native_rset(parametername, rand_distr) 
    538551        else: 
    539             rarr = rand_distr.next(n=self.all_cells.size, mask_local=False) #self._mask_local) 
    540             rarr = numpy.array(rarr) # isn't rarr already an array? 
     552            rarr = rand_distr.next(n=self.all_cells.size, mask_local=False) 
     553            rarr = numpy.array(rarr)  # isn't rarr already an array? 
    541554            assert rarr.size == self.size, "%s != %s" % (rarr.size, self.size) 
    542555            self.tset(parametername, rarr) 
     
    549562        """ 
    550563        raise NotImplementedError() 
    551      
     564 
    552565    def _tcall(self, methodname, objarr): 
    553566        """ 
    554         `Topographic' call. Call the method methodname() for every cell in the  
    555         population. The argument to the method depends on the coordinates of the 
    556         cell. objarr is an array with the same dimensions as the Population. 
     567        `Topographic' call. Call the method methodname() for every cell in the 
     568        population. The argument to the method depends on the coordinates of 
     569        the cell. objarr is an array with the same dimensions as the 
     570        Population. 
    557571        e.g. p.tcall("memb_init", vinitArray) calls 
    558572        p.cell[i][j].memb_init(vInitArray[i][j]) for all i,j. 
     
    571585        """ 
    572586        Set initial values of state variables, e.g. the membrane potential. 
    573          
     587 
    574588        `value` may either be a numeric value (all neurons set to the same 
    575589                value) or a `RandomDistribution` object (each neuron gets a 
     
    586600                self._set_initial_value_array(variable, value) 
    587601            else: 
    588                 for cell in self: # only on local node 
     602                for cell in self:  # only on local node 
    589603                    cell.set_initial_value(variable, value) 
    590          
     604 
    591605    def can_record(self, variable): 
    592606        """Determine whether `variable` can be recorded from this population.""" 
     
    594608            return (variable in self.celltype.recordable) 
    595609        else: 
    596             return True # for now, not able to check for native cells, although it should be possible in principle 
     610            return True  # for now, not able to check for native cells, although it should be possible in principle 
    597611 
    598612    def _record(self, variable, record_from=None, rng=None, to_file=True): 
     
    602616        if not self.can_record(variable): 
    603617            raise errors.RecordingError(variable, self.celltype) 
    604         if isinstance(record_from, list): #record from the fixed list specified by user 
     618        if isinstance(record_from, list):  # record from the fixed list specified by user 
    605619            pass 
    606         elif record_from is None: # record from all cells: 
     620        elif record_from is None:  # record from all cells: 
    607621            record_from = self.all_cells 
    608         elif isinstance(record_from, int): # record from a number of cells, selected at random   
     622        elif isinstance(record_from, int):  # record from a number of cells, selected at random 
    609623            nrec = record_from 
    610624            if not rng: 
     
    620634        if isinstance(to_file, basestring): 
    621635            self.recorders[variable].file = to_file 
    622              
    623636 
    624637    def record(self, record_from=None, rng=None, to_file=True): 
    625638        """ 
    626         If record_from is not given, record spikes from all cells in the Population. 
    627         record_from can be an integer - the number of cells to record from, chosen 
    628         at random (in this case a random number generator can also be supplied) 
    629         - or a list containing the ids of the cells to record. 
     639        If record_from is not given, record spikes from all cells in the 
     640        Population. record_from can be an integer - the number of cells to 
     641        record from, chosen at random (in this case a random number generator 
     642        can also be supplied) - or a list containing the ids of the cells to 
     643        record. 
    630644        """ 
    631645        self._record('spikes', record_from, rng, to_file) 
     
    633647    def record_v(self, record_from=None, rng=None, to_file=True): 
    634648        """ 
    635         If record_from is not given, record the membrane potential for all cells in 
    636         the Population. 
    637         record_from can be an integer - the number of cells to record from, chosen 
    638         at random (in this case a random number generator can also be supplied) 
    639         - or a list containing the ids of the cells to record. 
     649        If record_from is not given, record the membrane potential for all 
     650        cells in the Population. 
     651        record_from can be an integer - the number of cells to record from, 
     652        chosen at random (in this case a random number generator can also be 
     653        supplied) - or a list containing the ids of the cells to record. 
    640654        """ 
    641655        self._record('v', record_from, rng, to_file) 
     
    645659        If record_from is not given, record synaptic conductances 
    646660        for all cells in the Population. 
    647         record_from can be an integer - the number of cells to record from, chosen 
    648         at random (in this case a random number generator can also be supplied) 
    649         - or a list containing the ids of the cells to record. 
     661        record_from can be an integer - the number of cells to record from, 
     662        chosen at random (in this case a random number generator can also be 
     663        supplied) - or a list containing the ids of the cells to record. 
    650664        """ 
    651665        self._record('gsyn', record_from, rng, to_file) 
     
    654668        """ 
    655669        Write spike times to file. 
    656          
     670 
    657671        file should be either a filename or a PyNN File object. 
    658          
     672 
    659673        If compatible_output is True, the format is "spiketime cell_id", 
    660674        where cell_id is the index of the cell counting along rows and down 
     
    664678        The timestep, first id, last id, and number of data points per cell are 
    665679        written in a header, indicated by a '#' at the beginning of the line. 
    666          
     680 
    667681        If compatible_output is False, the raw format produced by the simulator 
    668682        is used. This may be faster, since it avoids any post-processing of the 
    669683        spike files. 
    670          
     684 
    671685        For parallel simulators, if gather is True, all data will be gathered 
    672686        to the master node and a single output file created there. Otherwise, a 
    673687        file will be written on each node, containing only the cells simulated 
    674688        on that node. 
    675         """         
     689        """ 
    676690        self.recorders['spikes'].write(file, gather, compatible_output, self.record_filter) 
    677      
     691 
    678692    def getSpikes(self, gather=True, compatible_output=True): 
    679693        """ 
     
    688702        """ 
    689703        Write membrane potential traces to file. 
    690          
     704 
    691705        file should be either a filename or a PyNN File object. 
    692          
     706 
    693707        If compatible_output is True, the format is "v cell_id", 
    694708        where cell_id is the index of the cell counting along rows and down 
     
    696710        The timestep, first id, last id, and number of data points per cell are 
    697711        written in a header, indicated by a '#' at the beginning of the line. 
    698          
     712 
    699713        If compatible_output is False, the raw format produced by the simulator 
    700714        is used. This may be faster, since it avoids any post-processing of the 
    701715        voltage files. 
    702          
     716 
    703717        For parallel simulators, if gather is True, all data will be gathered 
    704718        to the master node and a single output file created there. Otherwise, a 
     
    707721        """ 
    708722        self.recorders['v'].write(file, gather, compatible_output, self.record_filter) 
    709      
     723 
    710724    def get_v(self, gather=True, compatible_output=True): 
    711725        """ 
     
    714728        """ 
    715729        return self.recorders['v'].get(gather, compatible_output, self.record_filter) 
    716      
     730 
    717731    def print_gsyn(self, file, gather=True, compatible_output=True): 
    718732        """ 
    719733        Write synaptic conductance traces to file. 
    720          
     734 
    721735        file should be either a filename or a PyNN File object. 
    722          
     736 
    723737        If compatible_output is True, the format is "t g cell_id", 
    724738        where cell_id is the index of the cell counting along rows and down 
     
    732746        """ 
    733747        self.recorders['gsyn'].write(file, gather, compatible_output, self.record_filter) 
    734      
     748 
    735749    def get_gsyn(self, gather=True, compatible_output=True): 
    736750        """ 
     
    745759        """ 
    746760        return self.recorders['spikes'].count(gather) 
    747          
     761 
    748762    def meanSpikeCount(self, gather=True): 
    749763        """ 
     
    752766        spike_counts = self.recorders['spikes'].count(gather) 
    753767        total_spikes = sum(spike_counts.values()) 
    754         if rank() == 0 or not gather: # should maybe use allgather, and get the numbers on all nodes 
     768        if rank() == 0 or not gather:  # should maybe use allgather, and get the numbers on all nodes 
    755769            return float(total_spikes)/len(spike_counts) 
    756770 
     
    762776            raise TypeError("Can't inject current into a spike source.") 
    763777        current_source.inject_into(self) 
    764      
     778 
    765779    def save_positions(self, filename): 
    766780        """ 
     
    768782        """ 
    769783        # this should be rewritten to use self.positions and recording.files 
    770         fmt   = "%s\t%s\t%s\t%s\n" % ("%d", "%g", "%g", "%g") 
     784        fmt = "%s\t%s\t%s\t%s\n" % ("%d", "%g", "%g", "%g") 
    771785        lines = [] 
    772         for cell in self.all():   
    773             x,y,z = cell.position 
    774             line = fmt  % (cell, x, y, z) 
     786        for cell in self.all(): 
     787            x, y, z = cell.position 
     788            line = fmt % (cell, x, y, z) 
    775789            lines.append(line) 
    776790        if rank() == 0: 
     
    785799    """ 
    786800    nPop = 0 
    787      
     801 
    788802    def __init__(self, size, cellclass, cellparams=None, structure=None, 
    789803                 label=None): 
    790804        """ 
    791805        Create a population of neurons all of the same type. 
    792          
    793         size - number of cells in the Population. For backwards-compatibility, n 
    794                may also be a tuple giving the dimensions of a grid, e.g. n=(10,10) 
    795                is equivalent to n=100 with structure=Grid2D() 
     806 
     807        size - number of cells in the Population. For backwards-compatibility, 
     808               n may also be a tuple giving the dimensions of a grid, 
     809               e.g. n=(10,10) is equivalent to n=100 with structure=Grid2D() 
    796810        cellclass should either be a standardized cell class (a class inheriting 
    797         from common.standardmodels.StandardCellType) or a string giving the name of the 
    798         simulator-specific model that makes up the population. 
     811        from common.standardmodels.StandardCellType) or a string giving the 
     812        name of the simulator-specific model that makes up the population. 
    799813        cellparams should be a dict which is passed to the neuron model 
    800814          constructor 
     
    802816        label is an optional name for the population. 
    803817        """ 
    804         if not isinstance(size, int): # also allow a single integer, for a 1D population 
     818        if not isinstance(size, int):  # also allow a single integer, for a 1D population 
    805819            assert isinstance(size, tuple), "`size` must be an integer or a tuple of ints. You have supplied a %s" % type(size) 
    806820            # check the things inside are ints 
    807821            for e in size: 
    808822                assert isinstance(e, int), "`size` must be an integer or a tuple of ints. Element '%s' is not an int" % str(e) 
    809                  
     823 
    810824            assert structure is None, "If you specify `size` as a tuple you may not specify structure." 
    811825            if len(size) == 1: 
    812826                structure = space.Line() 
    813827            elif len(size) == 2: 
    814                 nx,ny = size  
     828                nx, ny = size 
    815829                structure = space.Grid2D(nx/float(ny)) 
    816830            elif len(size) == 3: 
    817                 nx,ny,nz = size 
     831                nx, ny, nz = size 
    818832                structure = space.Grid3D(nx/float(ny), nx/float(nz)) 
    819833            else: 
     
    821835            size = reduce(operator.mul, size) 
    822836        self.size = size 
    823         self.label = label or 'population%d' % Population.nPop          
     837        self.label = label or 'population%d' % Population.nPop 
    824838        if isinstance(cellclass, type) and issubclass(cellclass, standardmodels.StandardCellType): 
    825839            self.celltype = cellclass(cellparams) 
    826840        else: 
    827             self.celltype = cellclass         
     841            self.celltype = cellclass 
    828842        self._structure = structure or space.Line() 
    829843        self._positions = None 
     
    842856                          'gsyn'  : self.recorder_class('gsyn', population=self)} 
    843857        Population.nPop += 1 
    844      
     858 
    845859    @property 
    846860    def local_cells(self): 
    847861        return self.all_cells[self._mask_local] 
    848      
     862 
    849863    @property 
    850864    def cell(self): 
    851         warn("The `Population.cell` attribute is not an official part of the API, and its use is deprecated. \ 
    852               It will be removed in a future release. All uses of `cell` may be replaced by `all_cells`") 
     865        warn("The `Population.cell` attribute is not an official part of the \ 
     866              API, and its use is deprecated. It will be removed in a future \ 
     867              release. All uses of `cell` may be replaced by `all_cells`") 
    853868        return self.all_cells 
    854      
     869 
    855870    def id_to_index(self, id): 
    856871        """ 
    857         Given the ID(s) of cell(s) in the Population, return its (their) index (order in the 
    858         Population). 
     872        Given the ID(s) of cell(s) in the Population, return its (their) index 
     873        (order in the Population). 
    859874        >>> assert p.id_to_index(p[5]) == 5 
    860875        >>> assert p.id_to_index(p.index([1,2,3])) == [1,2,3] 
    861876        """ 
    862         if not self.first_id <= id <= self.last_id: # this test assumes id is a single ID, supposed to support id being a list/array of IDs 
     877        if not self.first_id <= id <= self.last_id:  # this test assumes id is a single ID, supposed to support id being a list/array of IDs 
    863878            raise IndexError("id should be in the range [%d,%d], actually %d" % (self.first_id, self.last_id, id)) 
    864         return id - self.first_id # this assumes ids are consecutive 
    865      
     879        return id - self.first_id  # this assumes ids are consecutive 
     880 
    866881    def id_to_local_index(self, id): 
    867882        if num_processes() > 1: 
    868             return self.local_cells.tolist().index(id) # probably very slow 
     883            return self.local_cells.tolist().index(id)  # probably very slow 
    869884        else: 
    870885            return self.id_to_index(id) 
    871      
     886 
    872887    def _get_structure(self): 
    873888        return self._structure 
    874      
     889 
    875890    def _set_structure(self, structure): 
    876891        assert isinstance(structure, space.BaseStructure) 
    877892        if structure != self._structure: 
    878             self._positions = None # setting a new structure invalidates previously calculated positions 
     893            self._positions = None  # setting a new structure invalidates previously calculated positions 
    879894            self._structure = structure 
    880895    structure = property(fget=_get_structure, fset=_set_structure) 
    881896    # arguably structure should be read-only, i.e. it is not possible to change it after Population creation 
    882      
     897 
    883898    def _get_positions(self): 
    884899        """ 
    885         Try to return self._positions. If it does not exist, create it and then return it 
     900        Try to return self._positions. If it does not exist, create it and then 
     901        return it. 
    886902        """ 
    887903        if self._positions is None: 
     
    892908        assert isinstance(pos_array, numpy.ndarray) 
    893909        assert pos_array.shape == (3, self.size), "%s != %s" % (pos_array.shape, (3, self.size)) 
    894         self._positions = pos_array.copy() # take a copy in case pos_array is changed later 
    895         self._structure = None # explicitly setting positions destroys any previous structure 
     910        self._positions = pos_array.copy()  # take a copy in case pos_array is changed later 
     911        self._structure = None  # explicitly setting positions destroys any previous structure 
    896912 
    897913    positions = property(_get_positions, _set_positions, 
     
    899915                         giving the x,y,z coordinates of all the neurons (soma, in the 
    900916                         case of non-point models).""") 
    901      
     917 
    902918    def describe(self, template='population_default.txt', engine='default'): 
    903919        """ 
    904920        Returns a human-readable description of the population. 
    905          
     921 
    906922        The output may be customized by specifying a different template 
    907923        togther with an associated template engine (see ``pyNN.descriptions``). 
    908          
     924 
    909925        If template is None, then a dictionary containing the template context 
    910926        will be returned. 
     
    931947 
    932948class PopulationView(BasePopulation): 
    933      
     949 
    934950    def __init__(self, parent, selector, label=None): 
    935951        self.parent = parent 
    936         self.mask = selector # later we can have fancier selectors, for now we just have numpy masks 
     952        self.mask = selector  # later we can have fancier selectors, for now we just have numpy masks 
    937953        self.label = label or "view of %s with mask %s" % (parent.label, self.mask) 
    938954        # maybe just redefine __getattr__ instead of the following... 
    939955        self.celltype = self.parent.celltype 
    940956        self.cellparams = self.parent.cellparams 
    941         self.all_cells = self.parent.all_cells[self.mask] # do we need to ensure this is ordered? 
     957        self.all_cells = self.parent.all_cells[self.mask]  # do we need to ensure this is ordered? 
    942958        self.size = len(self.all_cells) 
    943959        self._mask_local = self.parent._mask_local[self.mask] 
    944960        self.local_cells = self.all_cells[self._mask_local] 
    945         self.first_id = self.all_cells[0] # only works if we assume all_cells is sorted, otherwise could use min() 
     961        self.first_id = self.all_cells[0]  # only works if we assume all_cells is sorted, otherwise could use min() 
    946962        self.last_id = self.all_cells[-1] 
    947963        self.recorders = self.parent.recorders 
    948964        self.record_filter = self.all_cells 
    949      
     965 
    950966    @property 
    951967    def initial_values(self): 
     
    973989        >>> assert id_to_index(p.index([1,2,3])) == [1,2,3] 
    974990        """ 
    975         index, = numpy.where(self.all_cells==id) 
     991        index, = numpy.where(self.all_cells == id) 
    976992        if index.size == 1: 
    977993            return index.item() 
     
    9841000        """ 
    9851001        Returns a human-readable description of the population view. 
    986          
     1002 
    9871003        The output may be customized by specifying a different template 
    9881004        togther with an associated template engine (see ``pyNN.descriptions``). 
    989          
     1005 
    9901006        If template is None, then a dictionary containing the template context 
    9911007        will be returned. 
     
    9981014 
    9991015 
    1000 # ============================================================================== 
     1016# ============================================================================= 
    10011017 
    10021018class Assembly(object): 
     
    10131029            if not isinstance(p, BasePopulation): 
    10141030                raise TypeError("argument is a %s, not a Population." % type(p).__name__) 
    1015         self.populations = list(populations) # should this be a set? 
     1031        self.populations = list(populations)  # should this be a set? 
    10161032        self.label = kwargs.get('label', 'assembly%d' % Assembly.count) 
    10171033        assert isinstance(self.label, basestring), "label must be a string or unicode" 
     
    10201036    @property 
    10211037    def local_cells(self): 
    1022         return numpy.append(self.populations[0].local_cells, [p.local_cells for p in self.populations[1:]]) 
     1038        return numpy.append(self.populations[0].local_cells, 
     1039                            [p.local_cells for p in self.populations[1:]]) 
    10231040 
    10241041    @property 
    10251042    def all_cells(self): 
    1026         return numpy.append(self.populations[0].all_cells, [p.all_cells for p in self.populations[1:]]) 
     1043        return numpy.append(self.populations[0].all_cells, 
     1044                            [p.all_cells for p in self.populations[1:]]) 
    10271045 
    10281046    @property 
    10291047    def size(self): 
    10301048        return sum(p.size for p in self.populations) 
    1031      
     1049 
    10321050    def __iter__(self): 
    10331051        return chain(iter(p) for p in self.populations) 
    1034      
     1052 
    10351053    def __len__(self): 
    10361054        """Return the total number of cells in the population (all nodes).""" 
    10371055        return self.size 
    1038      
     1056 
    10391057    def __add__(self, other): 
    10401058        if isinstance(other, BasePopulation): 
     
    10441062        else: 
    10451063            raise TypeError("can only add a Population or another Assembly to an Assembly") 
    1046      
     1064 
    10471065    def __iadd__(self, other): 
    10481066        if isinstance(other, BasePopulation): 
     
    10531071            raise TypeError("can only add a Population or another Assembly to an Assembly") 
    10541072        return self 
    1055      
     1073 
    10561074    def initialize(self, variable, value): 
    10571075        for p in self.populations: 
     
    10751093        """ 
    10761094        Returns a human-readable description of the assembly. 
    1077          
     1095 
    10781096        The output may be customized by specifying a different template 
    10791097        togther with an associated template engine (see ``pyNN.descriptions``). 
    1080          
     1098 
    10811099        If template is None, then a dictionary containing the template context 
    10821100        will be returned. 
     
    10861104        return descriptions.render(engine, template, context) 
    10871105 
    1088 # ============================================================================== 
     1106# ============================================================================= 
     1107 
    10891108 
    10901109class Projection(object): 
    10911110    """ 
    10921111    A container for all the connections of a given type (same synapse type and 
    1093     plasticity mechanisms) between two populations, together with methods to set 
    1094     parameters of those connections, including of plasticity mechanisms. 
    1095     """ 
    1096      
     1112    plasticity mechanisms) between two populations, together with methods to 
     1113    set parameters of those connections, including of plasticity mechanisms. 
     1114    """ 
     1115 
    10971116    def __init__(self, presynaptic_neurons, postsynaptic_neurons, method, 
    10981117                 source=None, target=None, synapse_dynamics=None, 
     
    11011120        presynaptic_neurons and postsynaptic_neurons - Population, PopulationView 
    11021121                                                       or Assembly objects. 
    1103          
     1122 
    11041123        source - string specifying which attribute of the presynaptic cell 
    11051124                 signals action potentials. This is only needed for 
    1106                  multicompartmental cells with branching axons or dendrodendritic 
    1107                  synapses. All standard cells have a single source, and this 
    1108                  is the default. 
    1109                   
     1125                 multicompartmental cells with branching axons or 
     1126                 dendrodendriticsynapses. All standard cells have a single 
     1127                 source, and this is the default. 
     1128 
    11101129        target - string specifying which synapse on the postsynaptic cell to 
    11111130                 connect to. For standard cells, this can be 'excitatory' or 
    11121131                 'inhibitory'. For non-standard cells, it could be 'NMDA', etc. 
    1113                  If target is not given, the default values of 'excitatory' is used. 
    1114          
     1132                 If target is not given, the default values of 'excitatory' is 
     1133                 used. 
     1134 
    11151135        method - a Connector object, encapsulating the algorithm to use for 
    11161136                 connecting the neurons. 
    1117          
    1118         synapse_dynamics - a `standardmodels.SynapseDynamics` object specifying which 
    1119                  synaptic plasticity mechanisms to use. 
    1120          
     1137 
     1138        synapse_dynamics - a `standardmodels.SynapseDynamics` object specifying 
     1139                 which synaptic plasticity mechanisms to use. 
     1140 
    11211141        rng - specify an RNG object to be used by the Connector. 
    11221142        """ 
    1123         for prefix, pop in zip(("pre", "post"), (presynaptic_neurons, postsynaptic_neurons)): 
     1143        for prefix, pop in zip(("pre", "post"), 
     1144                               (presynaptic_neurons, postsynaptic_neurons)): 
    11241145            if not isinstance(pop, (BasePopulation, Assembly)): 
    11251146                raise errors.ConnectionError("%ssynaptic_neurons must be a Population, PopulationView or Assembly, not a %s" % (prefix, type(pop))) 
    1126         self.pre    = presynaptic_neurons  # } these really         
    1127         self.source = source               # } should be 
    1128         self.post   = postsynaptic_neurons # } read-only 
    1129         self.target = target               # } 
     1147        self.pre    = presynaptic_neurons  #  } these really 
     1148        self.source = source               #  } should be 
     1149        self.post   = postsynaptic_neurons #  } read-only 
     1150        self.target = target               #  } 
    11301151        self.label  = label 
    11311152        if isinstance(rng, random.AbstractRNG): 
     
    11491170        """Return the total number of local connections.""" 
    11501171        return len(self.connection_manager) 
    1151      
     1172 
    11521173    def size(self, gather=True): 
    11531174        """ 
     
    11611182        else: 
    11621183            return len(self) 
    1163      
     1184 
    11641185    def __repr__(self): 
    11651186        return 'Projection("%s")' % self.label 
    1166      
    1167      
     1187 
    11681188    def __getitem__(self, i): 
    11691189        return self.connection_manager[i] 
    1170      
    1171     # --- Methods for setting connection parameters ---------------------------- 
    1172      
     1190 
     1191    # --- Methods for setting connection parameters --------------------------- 
     1192 
    11731193    def setWeights(self, w): 
    11741194        """ 
     
    11841204        w = check_weight(w, self.synapse_type, is_conductance(self.post.local_cells[0])) 
    11851205        self.connection_manager.set('weight', w) 
    1186      
     1206 
    11871207    def randomizeWeights(self, rand_distr): 
    11881208        """ 
     
    11931213        # give it a separate name, though. Comments? 
    11941214        self.setWeights(rand_distr.next(len(self))) 
    1195      
     1215 
    11961216    def setDelays(self, d): 
    11971217        """ 
     
    12021222        """ 
    12031223        self.connection_manager.set('delay', d) 
    1204      
     1224 
    12051225    def randomizeDelays(self, rand_distr): 
    12061226        """ 
     
    12211241        """ 
    12221242        self.setSynapseDynamics(param, rand_distr.next(len(self))) 
    1223      
    1224     # --- Methods for writing/reading information to/from file. ---------------- 
    1225      
     1243 
     1244    # --- Methods for writing/reading information to/from file. --------------- 
     1245 
    12261246    def getWeights(self, format='list', gather=True): 
    12271247        """ 
    12281248        Get synaptic weights for all connections in this Projection. 
    1229          
     1249 
    12301250        Possible formats are: a list of length equal to the number of connections 
    12311251        in the projection, a 2D weight array (with NaN for non-existent 
     
    12361256            logger.error("getWeights() with gather=True not yet implemented") 
    12371257        return self.connection_manager.get('weight', format, offset=(self.pre.first_id, self.post.first_id)) 
    1238              
     1258 
    12391259    def getDelays(self, format='list', gather=True): 
    12401260        """ 
    12411261        Get synaptic delays for all connections in this Projection. 
    1242          
     1262 
    12431263        Possible formats are: a list of length equal to the number of connections 
    12441264        in the projection, a 2D delay array (with NaN for non-existent 
     
    12571277            logger.error("getstandardmodels.SynapseDynamics() with gather=True not yet implemented") 
    12581278        return self.connection_manager.get(parameter_name, format, offset=(self.pre.first_id, self.post.first_id)) 
    1259      
     1279 
    12601280    def saveConnections(self, filename, gather=True, compatible_output=True): 
    12611281        """ 
    12621282        Save connections to file in a format suitable for reading in with a 
    12631283        FromFileConnector. 
    1264         """     
     1284        """ 
    12651285        fmt = "%d\t%d\t%g\t%g\n" 
    12661286        lines = [] 
    12671287        if not compatible_output: 
    1268             for c in self.connections:    
    1269                 line = fmt  % (c.source,  
     1288            for c in self.connections: 
     1289                line = fmt  % (c.source, 
    12701290                               c.target, 
    12711291                               c.weight, 
     
    12731293                lines.append(line) 
    12741294        else: 
    1275             for c in self.connections:    
     1295            for c in self.connections:  
    12761296                line = fmt  % (self.pre.id_to_index(c.source), 
    12771297                               self.post.id_to_index(c.target), 
     
    12921312            f.writelines(lines) 
    12931313            f.close() 
    1294      
     1314 
    12951315    def printWeights(self, filename, format='list', gather=True): 
    1296         """Print synaptic weights to file. In the array format, zeros are printed 
    1297         for non-existent connections.""" 
     1316        """ 
     1317        Print synaptic weights to file. In the array format, zeros are printed 
     1318        for non-existent connections. 
     1319        """ 
    12981320        weights = self.getWeights(format=format, gather=gather) 
    12991321        f = open(filename, 'w', DEFAULT_BUFFER_SIZE) 
     
    13071329            #    f.write(fmt % tuple(row)) 
    13081330        f.close() 
    1309      
     1331 
    13101332    def weightHistogram(self, min=None, max=None, nbins=10): 
    13111333        """ 
     
    13171339        # should be put here or in an external module. 
    13181340        bins = numpy.arange(min, max, float(max-min)/nbins) 
    1319         return numpy.histogram(self.getWeights(format='list', gather=True), bins) # returns n, bins 
    1320      
     1341        return numpy.histogram(self.getWeights(format='list', gather=True), bins)  # returns n, bins 
     1342 
    13211343    def describe(self, template='projection_default.txt', engine='default'): 
    13221344        """ 
    13231345        Returns a human-readable description of the projection. 
    1324          
     1346 
    13251347        The output may be customized by specifying a different template 
    13261348        togther with an associated template engine (see ``pyNN.descriptions``). 
    1327          
     1349 
    13281350        If template is None, then a dictionary containing the template context 
    13291351        will be returned. 
     
    13451367 
    13461368 
    1347 # ============================================================================== 
     1369# ============================================================================= 
  • trunk/src/nest/__init__.py

    r820 r821  
    284284            assert len(rarr) == len(self.local_cells), "%d != %d" % (len(rarr), len(self.local_cells)) 
    285285        nest.SetStatus(self.local_cells.tolist(), STATE_VARIABLE_MAP[variable], value) 
    286         self.initial_values[variable] = core.LazyArray(value, self.size) 
     286        self.initial_values[variable] = core.LazyArray(value, (self.size,)) 
    287287 
    288288    def _record(self, variable, record_from=None, rng=None, to_file=True): 
  • trunk/test/unittests/test_space.py

    r812 r821  
    232232        rs = space.RandomStructure(boundary=s, origin=(1.0, 1.0, 1.0)) 
    233233        positions = rs.generate_positions(n) 
    234         assert_equal(positions.shape, (n,3)) 
     234        assert_equal(positions.shape, (3,n)) 
    235235        for axis in range(2): 
    236236            assert 3 < max(positions[:,axis]) < 3.5