Changeset 94

Show
Ignore:
Timestamp:
06/06/07 21:26:30 (1 year ago)
Author:
apdavison
Message:

The improved ID class seems to be working for the nest module, although some unit tests are needed.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/improved-ID/common.py

    r92 r94  
     1# encoding: utf-8 
    12""" 
    23Defines the PyNN classes and functions, and hence the FACETS API. 
     
    78__version__ = "$Revision$" 
    89 
    9 import types, time, copy 
     10import types, time, copy, sys 
     11import numpy 
    1012 
    1113class InvalidParameterValueError(Exception): pass 
     
    2022#   Utility classes 
    2123# ============================================================================== 
     24 
     25# The following two functions taken from 
     26# http://www.nedbatchelder.com/text/pythonic-interfaces.html 
     27def _functionId(obj, nFramesUp): 
     28    """ Create a string naming the function n frames up on the stack. """ 
     29    fr = sys._getframe(nFramesUp+1) 
     30    co = fr.f_code 
     31    return "%s.%s" % (obj.__class__, co.co_name) 
     32 
     33def _abstractMethod(obj=None): 
     34    """ Use this instead of 'pass' for the body of abstract methods. """ 
     35    raise Exception("Unimplemented abstract method: %s" % _functionId(obj, 1)) 
    2236 
    2337class ID(int): 
     
    3246    def __init__(self,n): 
    3347        int.__init__(n) 
    34         self._position = None 
     48        self.parent = None 
    3549        self._cellclass = None 
    36         self._hocname   = None 
    37         # The cellclass can be a global attribute of the ID object, but 
    38         # it may be discussed:  
    39         # The problem is that a call to the low-level funcitons set() and get() will need 
    40         # the cellclass to work. So we have to choose if we want to store that information in the ID 
    41         # object (as an attribute for example) or if we want to type it each time we need a call to set() 
    42         # or get() : p[2,3].set(SpikeSourceArray, {'spike_train' : {}}). 
    43  
    44     def set(self,param,val=None): 
    45         raise Exception("Not yet implemented") 
    46      
    47     def get(self,param): 
    48         raise Exception("Not yet implemented") 
    49  
    50     def setCellClass(self, cellclass): 
    51         self._cellclass = cellclass     
    52      
    53     # Here is a proposal to manage the physical position of the cell, as an 
    54     # attribute of the ID class. Those positions can be used by functions such 
    55     # as _distantDependantProbability(), setTopographicDelay()... 
    56     def setPosition(self,pos): 
    57         self._position = pos 
    58          
    59     def getPosition(self): 
    60         return self._position 
    61  
     50        #self._hocname   = None 
     51 
     52    def __getattr__(self,name): 
     53        """Note that this currently does not translate units.""" 
     54        return _abstractMethod(self) 
     55     
     56    def __setattr__(self,name,value): 
     57        if name in ('parent','_cellclass','cellclass','_position','position'): 
     58            object.__setattr__(self,name,value) 
     59        else: 
     60            return _abstractMethod(self) 
     61 
     62    def _set_cellclass(self, cellclass): 
     63        if self.parent: 
     64            raise Exception("Cell class is determined by the Population and cannot be changed for individual neurons.") 
     65        else: 
     66            self._cellclass = cellclass # should check it is a standard cell class or a string 
     67 
     68    def _get_cellclass(self): 
     69        if self.parent: 
     70            return self.parent.celltype 
     71        else: 
     72            return self._cellclass 
     73         
     74    cellclass = property(_get_cellclass, _set_cellclass) 
     75     
     76    def _set_position(self,pos): 
     77        assert isinstance(pos, tuple) or isinstance(pos, numpy.ndarray) 
     78        assert len(pos) == 3 
     79        if self.parent: 
     80            index = numpy.where(self.parent.cell.flatten() == int(self))[0][0] 
     81            self.parent.positions[:,index] = pos 
     82        else: 
     83            self._position = pos 
     84         
     85    def _get_position(self): 
     86        if self.parent: 
     87            index = numpy.where(self.parent.cell.flatten() == int(self))[0][0] 
     88            return self.parent.positions[:,index]   
     89        else: 
     90            try: 
     91                return self._position 
     92            except (AttributeError, KeyError): 
     93                self._position = (int(self), 0, 0) 
     94                return self._position 
     95 
     96    position = property(_get_position, _set_position) 
    6297 
    6398 
     
    162197        'e_rev_I'    : -70.0,   # Reversal potential for inhibitory input in mV 
    163198        'v_thresh'   : -50.0,   # Spike threshold in mV. 
    164        'v_reset'    : -65.0,   # Reset potential after a spike in mV. 
    165        'i_offset'   : 0.0,     # Offset current in nA 
     199        'v_reset'    : -65.0,   # Reset potential after a spike in mV. 
     200        'i_offset'   : 0.0,     # Offset current in nA 
    166201        'v_init'     : -65.0,   # Membrane potential in mV at t = 0 
    167202    } 
     
    293328        pass 
    294329     
     330    def __iter__(self): 
     331        return _abstractMethod(self) 
     332         
     333    def addresses(self): 
     334        return _abstractMethod(self) 
     335     
     336    def ids(self): 
     337        return self.__iter__() 
     338     
     339    def locate(self): 
     340        return _abstractMethod(self) 
     341     
    295342    def __len__(self): 
    296343        """Returns the total number of cells in the population.""" 
    297344        return self.size 
     345     
     346    def _get_positions(self): 
     347        """ 
     348        Try to return self._positions. If it does not exist, create it and then return it 
     349        """ 
     350        try: 
     351            return self._positions 
     352        except AttributeError: 
     353            x,y,z = numpy.indices(list(self.dim) + [1]*(3-len(self.dim))).astype(float) 
     354            x = x.flatten(); y = y.flatten(); z = z.flatten() 
     355            self._positions = numpy.array((x,y,z)) 
     356            return self._positions 
     357 
     358    def _set_positions(self, pos_array): 
     359        assert isinstance(pos_array, numpy.ndarray) 
     360        assert pos_array.shape == (3,self.size) 
     361        self._positions = pos_array.copy() # take a copy in case pos_array is changed later 
     362 
     363    positions = property(_get_positions, _set_positions, 'A 3xN array (where N is the number of neurons in the Population) giving the x,y,z coordinates of all the neurons (soma, in the case of non-point models).') 
    298364     
    299365    def set(self,param,val=None): 
     
    306372             p.set({'tau_m':20,'v_rest':-65}) 
    307373        """ 
    308         pass 
     374        return _abstractMethod(self) 
    309375 
    310376    def tset(self,parametername,valueArray): 
     
    313379        valueArray, which must have the same dimensions as the Population. 
    314380        """ 
    315         pass 
     381        return _abstractMethod(self) 
    316382     
    317383    def rset(self,parametername,rand_distr): 
     
    320386        rand_distr, which should be a RandomDistribution object. 
    321387        """ 
    322         pass 
     388        return _abstractMethod(self) 
    323389     
    324390    def _call(self,methodname,arguments): 
     
    328394        set_background(). 
    329395        """ 
    330         pass 
     396        return _abstractMethod(self) 
    331397     
    332398    def _tcall(self,methodname,objarr): 
     
    338404        p.cell[i][j].memb_init(vInitArray[i][j]) for all i,j. 
    339405        """ 
    340         pass 
     406        return _abstractMethod(self) 
    341407 
    342408    def randomInit(self,rand_distr): 
     
    345411        random values. 
    346412        """ 
    347         pass 
     413        return _abstractMethod(self) 
    348414 
    349415    def record(self,record_from=None,rng=None): 
     
    354420        - or a list containing the ids of the cells to record. 
    355421        """ 
    356         pass 
     422        return _abstractMethod(self) 
    357423 
    358424    def record_v(self,record_from=None,rng=None): 
     
    364430        - or a list containing the ids of the cells to record. 
    365431        """ 
    366         pass 
     432        return _abstractMethod(self) 
    367433 
    368434    def printSpikes(self,filename,gather=True,compatible_output=True): 
     
    384450        otherwise, a file will be written on each node. 
    385451        """         
    386         pass 
     452        return _abstractMethod(self) 
    387453     
    388454    def print_v(self,filename,gather=True, compatible_output=True): 
     
    401467        voltage files. 
    402468        """ 
    403         pass 
     469        return _abstractMethod(self) 
    404470     
    405471    def meanSpikeCount(self,gather=True): 
     
    408474        """ 
    409475        # gather is not relevant, but is needed for API consistency 
    410         pass 
     476        return _abstractMethod(self) 
    411477 
    412478# ============================================================================== 
     
    479545        in row i of a 2D post population of size (n,m). 
    480546        """ 
    481         pass 
     547        return _abstractMethod(self) 
    482548     
    483549    def _fixedProbability(self,parameters,synapse_type=None): 
     
    560626        """ 
    561627        # Need to implement parameter parsing here... 
    562         pass 
     628        return _abstractMethod(self) 
    563629     
    564630    # --- Methods for setting connection parameters ---------------------------- 
     
    569635        value, or a list/1D array of length equal to the number of connections 
    570636        in the population. 
    571         Weights should be in nA for current-based and uS for conductance-based 
     637        Weights should be in nA for current-based and µS for conductance-based 
    572638        synapses. 
    573639        """ 
    574         pass 
     640        return _abstractMethod(self) 
    575641     
    576642    def randomizeWeights(self,rand_distr): 
     
    581647        # argument type. It could make for easier-to-read simulation code to 
    582648        # give it a separate name, though. Comments? 
    583         pass 
     649        return _abstractMethod(self) 
    584650     
    585651    def setDelays(self,d): 
     
    589655        in the population. 
    590656        """ 
    591         pass 
     657        return _abstractMethod(self) 
    592658     
    593659    def randomizeDelays(self,rand_distr): 
     
    595661        Set delays to random values taken from rand_distr. 
    596662        """ 
    597         pass 
     663        return _abstractMethod(self) 
    598664     
    599665    def setThreshold(self,threshold): 
     
    605671        # property of the cell model, whereas in NEURON it is a property of the 
    606672        # connection (NetCon). 
    607         pass 
     673        return _abstractMethod(self) 
    608674     
    609675     
     
    612678    def setupSTDP(self,stdp_model,parameterDict): 
    613679        """Set-up STDP.""" 
    614         pass 
     680        return _abstractMethod(self) 
    615681     
    616682    def toggleSTDP(self,onoff): 
    617683        """Turn plasticity on or off.""" 
    618         pass 
     684        return _abstractMethod(self) 
    619685     
    620686    def setMaxWeight(self,wmax): 
    621687        """Note that not all STDP models have maximum or minimum weights.""" 
    622         pass 
     688        return _abstractMethod(self) 
    623689     
    624690    def setMinWeight(self,wmin): 
    625691        """Note that not all STDP models have maximum or minimum weights.""" 
    626         pass 
     692        return _abstractMethod(self) 
    627693     
    628694    # --- Methods for writing/reading information to/from file. ---------------- 
     
    631697        """Save connections to file in a format suitable for reading in with the 
    632698        'fromFile' method.""" 
    633         pass 
     699        return _abstractMethod(self) 
    634700     
    635701    def printWeights(self,filename,format=None,gather=True): 
    636702        """Print synaptic weights to file.""" 
    637         pass 
     703        return _abstractMethod(self) 
    638704     
    639705    def weightHistogram(self,min=None,max=None,nbins=10): 
     
    645711        # it is arguable whether functions operating on the set of weights 
    646712        # should be put here or in an external module. 
    647         pass 
     713        return _abstractMethod(self) 
    648714 
    649715 
  • branches/improved-ID/nest.py

    r86 r94  
    3636    def __getattr__(self,name): 
    3737        """Note that this currently does not translate units.""" 
    38         translated_name = self._cellclass.translations[name][0] 
     38        translated_name = self.cellclass.translations[name][0] 
    3939        return pynest.getDict([int(self)])[0][translated_name] 
    4040     
     
    243243        raise "Invalid cell type" 
    244244    for id in cell_gids: 
    245         id.setCellClass(cellclass) 
     245    #    #id.setCellClass(cellclass) 
     246        id.cellclass = cellclass 
    246247    if n == 1: 
    247248        return cell_gids[0] 
     
    447448         
    448449        for id in self.cell: 
    449             id.setCellClass(cellclass) 
    450             id.setPosition(self.locate(id)) 
     450            id.parent = self 
     451            #id.setCellClass(cellclass) 
     452            #id.setPosition(self.locate(id)) 
    451453             
    452454        if self.cellparams: